Version 2.2.1-dev.2.0
Merge commit '9d3988eb67b3c388fb8eb4425da3ba07182e08a2' into dev
diff --git a/.packages b/.packages
index a686ef2..87f497f 100644
--- a/.packages
+++ b/.packages
@@ -16,7 +16,6 @@
args:third_party/pkg/args/lib
async:third_party/pkg/async/lib
async_helper:pkg/async_helper/lib
-barback:third_party/pkg/barback/lib
bazel_worker:third_party/pkg/bazel_worker/lib
boolean_selector:third_party/pkg/boolean_selector/lib
build_integration:pkg/build_integration/lib
@@ -48,7 +47,6 @@
http_retry:third_party/pkg/http_retry/lib
http_throttle:third_party/pkg/http_throttle/lib
intl:third_party/pkg/intl/lib
-isolate:third_party/pkg/isolate/lib
js:pkg/js/lib
js_ast:pkg/js_ast/lib
js_runtime:sdk/lib/_internal/js_runtime/lib
@@ -67,9 +65,8 @@
package_config:third_party/pkg_tested/package_config/lib
package_resolver:third_party/pkg_tested/package_resolver/lib
path:third_party/pkg/path/lib
-plugin:third_party/pkg/plugin/lib
pool:third_party/pkg/pool/lib
-protobuf:third_party/pkg/protobuf/lib
+protobuf:third_party/pkg/protobuf/protobuf/lib
pub:third_party/pkg/pub/lib
pub_semver:third_party/pkg/pub_semver/lib
quiver:third_party/pkg/quiver/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 37704bb..110eaf0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,5 @@
+## 2.2.1-dev.2.0
+
## 2.2.1-dev.1.1
* Cherry-pick 567d552de8ff93d704111467e7f3bf3b896ab684 to dev
@@ -5,6 +7,8 @@
## 2.2.1-dev.1.0
+* RegExp patterns can now use lookbehind assertions.
+
### Tool Changes
#### Pub client
diff --git a/DEPS b/DEPS
index f1860721..c6f2c79 100644
--- a/DEPS
+++ b/DEPS
@@ -36,7 +36,7 @@
"chromium_git": "https://chromium.googlesource.com",
"fuchsia_git": "https://fuchsia.googlesource.com",
- "co19_2_rev": "b54821029f62b5b5873925cfef6c01f1100d1982",
+ "co19_2_rev": "2d157d6b9135f891ffd1d35b7a2d5dfa57611f63",
# As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
# should be kept up to date with the revisions pulled by the Flutter engine.
@@ -54,7 +54,7 @@
# Revisions of /third_party/* dependencies.
"args_tag": "1.4.4",
"async_tag": "2.0.8",
- "bazel_worker_tag": "0.1.14",
+ "bazel_worker_tag": "bazel_worker-v0.1.20",
"boolean_selector_tag" : "1.0.4",
"boringssl_gen_rev": "bbf52f18f425e29b1185f2f6753bec02ed8c5880",
"boringssl_rev" : "702e2b6d3831486535e958f262a05c75a5cb312e",
@@ -108,10 +108,9 @@
"package_config_tag": "1.0.5",
"package_resolver_tag": "1.0.10",
"path_tag": "1.6.2",
- "plugin_tag": "f5b4b0e32d1406d62daccea030ba6457d14b1c47",
"ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_tag": "1.3.6",
- "protobuf_tag": "0.9.0",
+ "protobuf_rev": "0c77167b16d00b561a6055bfe26690af7f26ae88",
"pub_rev": "3c060aae47985e9a248b850f1d0450304a5c97e3",
"pub_semver_tag": "1.4.2",
"quiver_tag": "2.0.0+1",
@@ -157,7 +156,7 @@
Var("dart_root") + "/tools/sdks": {
"packages": [{
"package": "dart/dart-sdk/${{platform}}",
- "version": "version:2.2.1-dev.0.0",
+ "version": "version:2.2.1-dev.1.1",
}],
"dep_type": "cipd",
},
@@ -303,12 +302,10 @@
+ "@" + Var("package_resolver_tag"),
Var("dart_root") + "/third_party/pkg/path":
Var("dart_git") + "path.git" + "@" + Var("path_tag"),
- Var("dart_root") + "/third_party/pkg/plugin":
- Var("dart_git") + "plugin.git" + "@" + Var("plugin_tag"),
Var("dart_root") + "/third_party/pkg/pool":
Var("dart_git") + "pool.git" + "@" + Var("pool_tag"),
Var("dart_root") + "/third_party/pkg/protobuf":
- Var("dart_git") + "protobuf.git" + "@" + Var("protobuf_tag"),
+ Var("dart_git") + "protobuf.git" + "@" + Var("protobuf_rev"),
Var("dart_root") + "/third_party/pkg/pub_semver":
Var("dart_git") + "pub_semver.git" + "@" + Var("pub_semver_tag"),
Var("dart_root") + "/third_party/pkg/pub":
diff --git a/docs/process/breaking-changes.md b/docs/process/breaking-changes.md
index adf71a2..5ed9bcb 100644
--- a/docs/process/breaking-changes.md
+++ b/docs/process/breaking-changes.md
@@ -66,7 +66,7 @@
[TODO: Link to an issue template for this]
-* Email `announce@dartlang.org, flutter-announce@googlegroups.com`,:
+* Email Dart Announce (`announce@dartlang.org`):
* Subject: 'Breaking change [bug ID]: [short summary]'
@@ -77,6 +77,9 @@
* A request that developers may leave comments in the linked issue, if this
breaking change poses a severe problem.
+* Once you have sent the announce email, please let `aadilmaan@google.com` know
+as he will help drive the request through approval review process.
+
### Step 2: Approval
If there is a general agreement that the benefit of the change outweighs the
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index d4f29d6..a08c3bc 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -196,7 +196,11 @@
try {
var analysisDriver = server.getAnalysisDriver(file);
var session = analysisDriver.currentSession;
- var resolvedLibrary = await session.getResolvedLibrary(file);
+
+ var fileElement = await session.getUnitElement(file);
+ var libraryPath = fileElement.element.librarySource.fullName;
+
+ var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
var requestedLibraryElement = await session.getLibraryByUri(
library.uriStr,
);
@@ -214,10 +218,10 @@
var completion = params.label;
var builder = DartChangeBuilder(session);
- await builder.addFileEdit(file, (builder) {
+ await builder.addFileEdit(libraryPath, (builder) {
var result = builder.importLibraryElement(
targetLibrary: resolvedLibrary,
- targetPath: file,
+ targetPath: libraryPath,
targetOffset: params.offset,
requestedLibrary: requestedLibraryElement,
requestedElement: requestedElement,
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 c5ee92f..26a8028 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
@@ -43,6 +43,12 @@
Expression get dotTarget;
/**
+ * Return a list containing the names of the experiments that have been
+ * enabled.
+ */
+ List<String> get enabledExperiments;
+
+ /**
* Return `true` if free standing identifiers should be suggested
*/
bool get includeIdentifiers;
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 1d493ed..70f98dc 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -30,7 +30,6 @@
import 'package:analyzer/src/plugin/resolver_provider.dart';
import 'package:args/args.dart';
import 'package:linter/src/rules.dart' as linter;
-import 'package:plugin/manager.dart';
import 'package:telemetry/crash_reporting.dart';
import 'package:telemetry/telemetry.dart' as telemetry;
@@ -440,10 +439,8 @@
final serve_http = diagnosticServerPort != null;
//
- // Process all of the plugins so that extensions are registered.
+ // Register lint rules.
//
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(AnalysisEngine.instance.requiredPlugins);
linter.registerLintRules();
_DiagnosticServerImpl diagnosticServer = new _DiagnosticServerImpl();
@@ -701,6 +698,15 @@
return sdk;
}
+ /**
+ * Constructs a uuid combining the current date and a random integer.
+ */
+ String _generateUuidString() {
+ int millisecondsSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
+ int random = new Random().nextInt(0x3fffffff);
+ return '$millisecondsSinceEpoch$random';
+ }
+
String _getSdkPath(ArgResults args) {
if (args[SDK_OPTION] != null) {
return args[SDK_OPTION];
@@ -768,15 +774,6 @@
}
/**
- * Constructs a uuid combining the current date and a random integer.
- */
- String _generateUuidString() {
- int millisecondsSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
- int random = new Random().nextInt(0x3fffffff);
- return '$millisecondsSinceEpoch$random';
- }
-
- /**
* Perform log files rolling.
*
* Rename existing files with names `[path].(x)` to `[path].(x+1)`.
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 a53579e..710ca2d 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
@@ -326,6 +326,10 @@
}
@override
+ List<String> get enabledExperiments =>
+ result.session.analysisContext.analysisOptions.enabledExperiments;
+
+ @override
bool get includeIdentifiers {
return opType.includeIdentifiers;
}
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 ecc25d3..fb9885d 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,6 +9,7 @@
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/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
@@ -327,6 +328,13 @@
}
@override
+ visitForElement(ForElement node) {
+ _addCollectionElementKeywords();
+ _addExpressionKeywords(node);
+ return super.visitForElement(node);
+ }
+
+ @override
visitFormalParameterList(FormalParameterList node) {
AstNode constructorDeclaration =
node.thisOrAncestorOfType<ConstructorDeclaration>();
@@ -387,6 +395,13 @@
}
@override
+ visitIfElement(IfElement node) {
+ _addCollectionElementKeywords();
+ _addExpressionKeywords(node);
+ return super.visitIfElement(node);
+ }
+
+ @override
visitIfStatement(IfStatement node) {
if (_isPreviousTokenSynthetic(entity, TokenType.CLOSE_PAREN)) {
// analyzer parser
@@ -449,6 +464,12 @@
}
@override
+ visitListLiteral(ListLiteral node) {
+ _addCollectionElementKeywords();
+ super.visitListLiteral(node);
+ }
+
+ @override
visitMethodDeclaration(MethodDeclaration node) {
if (entity == node.body) {
if (isEmptyBody(node.body)) {
@@ -549,6 +570,18 @@
}
@override
+ visitSetOrMapLiteral(SetOrMapLiteral node) {
+ _addCollectionElementKeywords();
+ super.visitSetOrMapLiteral(node);
+ }
+
+ @override
+ visitSpreadElement(SpreadElement node) {
+ _addExpressionKeywords(node);
+ return super.visitSpreadElement(node);
+ }
+
+ @override
visitStringLiteral(StringLiteral node) {
// ignored
}
@@ -627,6 +660,17 @@
}
}
+ void _addCollectionElementKeywords() {
+ List<String> enabledExperiments = request.enabledExperiments;
+ if (enabledExperiments.contains(EnableString.control_flow_collections) ||
+ enabledExperiments.contains(EnableString.spread_collections)) {
+ _addSuggestions([
+ Keyword.FOR,
+ Keyword.IF,
+ ]);
+ }
+ }
+
void _addCompilationUnitKeywords() {
_addSuggestions([
Keyword.ABSTRACT,
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 63faf71..50e4b46 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
@@ -76,9 +76,11 @@
}
String containingMethodName;
List<InterfaceType> mixins;
+ List<InterfaceType> superclassConstraints;
if (expression is SuperExpression && type is InterfaceType) {
// Suggest members from superclass if target is "super"
mixins = (type as InterfaceType).mixins;
+ superclassConstraints = (type as InterfaceType).superclassConstraints;
type = (type as InterfaceType).superclass;
// Determine the name of the containing method because
// the most likely completion is a super expression with same name
@@ -99,7 +101,8 @@
// Build the suggestions
if (type is InterfaceType) {
_SuggestionBuilder builder = new _SuggestionBuilder(containingLibrary);
- builder.buildSuggestions(type, containingMethodName, mixins: mixins);
+ builder.buildSuggestions(type, containingMethodName,
+ mixins: mixins, superclassConstraints: superclassConstraints);
return builder.suggestions.toList();
}
return const <CompletionSuggestion>[];
@@ -290,7 +293,7 @@
* is the name of the method in which the completion is requested.
*/
void buildSuggestions(InterfaceType type, String containingMethodName,
- {List<InterfaceType> mixins}) {
+ {List<InterfaceType> mixins, List<InterfaceType> superclassConstraints}) {
// Visit all of the types in the class hierarchy, collecting possible
// completions. If multiple elements are found that complete to the same
// identifier, addSuggestion will discard all but the first (with a few
@@ -299,6 +302,9 @@
if (mixins != null) {
types.addAll(mixins);
}
+ if (superclassConstraints != null) {
+ types.addAll(superclassConstraints);
+ }
for (InterfaceType targetType in types) {
for (MethodElement method in targetType.methods) {
// Exclude static methods when completion on an instance
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 2b18345..4c4e5a8 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -60,6 +60,11 @@
static const CONVERT_INTO_FINAL_FIELD = const AssistKind(
'dart.assist.convert.getterToFinalField', 30, "Convert to final field",
associatedErrorCodes: <String>['prefer_final_fields']);
+ static const CONVERT_INTO_ABSOLUTE_IMPORT = const AssistKind(
+ 'dart.assist.convert.relativeToAbsoluteImport',
+ 30,
+ "Convert to absolute import",
+ associatedErrorCodes: <String>['avoid_relative_lib_imports']);
static const CONVERT_INTO_FOR_INDEX = const AssistKind(
'dart.assist.convert.forEachToForIndex', 30, "Convert to for-index loop");
static const CONVERT_INTO_GENERIC_FUNCTION_SYNTAX = const AssistKind(
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 f092854..ee38d9c 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -104,6 +104,7 @@
await _addProposal_convertMapConstructorToMapLiteral();
await _addProposal_convertPartOfToUri();
await _addProposal_convertSetConstructorToSetLiteral();
+ await _addProposal_convertToAbsoluteImport();
await _addProposal_convertToAsyncFunctionBody();
await _addProposal_convertToBlockFunctionBody();
await _addProposal_convertToDoubleQuotedString();
@@ -1725,6 +1726,29 @@
changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY);
}
+ Future<void> _addProposal_convertToAbsoluteImport() async {
+ var node = this.node;
+ if (node is StringLiteral) {
+ node = node.parent;
+ }
+ if (node is ImportDirective) {
+ var importDirective = node;
+ var importUri = node.uriSource?.uri;
+ if (importUri?.scheme != 'package') {
+ return;
+ }
+ var changeBuilder = _newDartChangeBuilder();
+ await changeBuilder.addFileEdit(file, (builder) {
+ builder.addSimpleReplacement(
+ range.node(importDirective.uri), "'$importUri'");
+ });
+ _addAssistFromBuilder(
+ changeBuilder,
+ DartAssistKind.CONVERT_INTO_ABSOLUTE_IMPORT,
+ );
+ }
+ }
+
Future<void> _addProposal_convertToMultilineString() async {
var node = this.node;
if (node is InterpolationElement) {
@@ -2516,7 +2540,10 @@
await changeBuilder.addFileEdit(file, (builder) {
builder.addReplacement(range.node(widgetExpr), (builder) {
builder.writeType(streamBuilderElement.type);
- builder.writeln('<Object>(');
+
+ builder.write('<');
+ builder.addSimpleLinkedEdit('type', 'Object');
+ builder.writeln('>(');
String indentOld = utils.getLinePrefix(widgetExpr.offset);
String indentNew1 = indentOld + utils.getIndent(1);
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index ec60587..3bb80d7 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -73,15 +73,36 @@
errorCode == StaticTypeWarningCode.UNDEFINED_SETTER ||
errorCode == CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER ||
(errorCode is LintCode &&
- (errorCode.name == LintNames.annotate_overrides ||
+ (errorCode.name == LintNames.always_require_non_null_named_parameters ||
+ errorCode.name == LintNames.annotate_overrides ||
+ errorCode.name == LintNames.avoid_annotating_with_dynamic ||
+ errorCode.name == LintNames.avoid_empty_else ||
errorCode.name == LintNames.avoid_init_to_null ||
+ errorCode.name == LintNames.avoid_return_types_on_setters ||
+ errorCode.name == LintNames.avoid_types_on_closure_parameters ||
+ errorCode.name == LintNames.await_only_futures ||
+ errorCode.name == LintNames.empty_catches ||
+ errorCode.name == LintNames.empty_constructor_bodies ||
+ errorCode.name == LintNames.empty_statements ||
+ errorCode.name == LintNames.no_duplicate_case_values ||
+ errorCode.name == LintNames.non_constant_identifier_names ||
+ errorCode.name == LintNames.null_closures ||
errorCode.name == LintNames.prefer_collection_literals ||
errorCode.name == LintNames.prefer_conditional_assignment ||
errorCode.name == LintNames.prefer_const_declarations ||
+ errorCode.name == LintNames.prefer_equal_for_default_values ||
+ errorCode.name == LintNames.prefer_final_fields ||
+ errorCode.name == LintNames.prefer_final_locals ||
+ errorCode.name == LintNames.prefer_is_not_empty ||
+ errorCode.name == LintNames.type_init_formals ||
+ errorCode.name == LintNames.unawaited_futures ||
errorCode.name == LintNames.unnecessary_brace_in_string_interps ||
errorCode.name == LintNames.unnecessary_const ||
errorCode.name == LintNames.unnecessary_lambdas ||
- errorCode.name == LintNames.unnecessary_this));
+ errorCode.name == LintNames.unnecessary_new ||
+ errorCode.name == LintNames.unnecessary_overrides ||
+ errorCode.name == LintNames.unnecessary_this ||
+ errorCode.name == LintNames.use_rethrow_when_possible));
/**
* The implementation of [DartFixContext].
@@ -105,6 +126,8 @@
class DartFixKind {
static const ADD_ASYNC =
const FixKind('ADD_ASYNC', 50, "Add 'async' modifier");
+ static const ADD_AWAIT =
+ const FixKind('ADD_AWAIT', 50, "Add 'await' keyword");
static const ADD_EXPLICIT_CAST = const FixKind(
'ADD_EXPLICIT_CAST', 50, "Add cast",
appliedTogetherMessage: "Add all casts in file");
@@ -262,8 +285,12 @@
static const REPLACE_BOOLEAN_WITH_BOOL = const FixKind(
'REPLACE_BOOLEAN_WITH_BOOL', 50, "Replace 'boolean' with 'bool'",
appliedTogetherMessage: "Replace all 'boolean' with 'bool' in file");
+ static const REPLACE_COLON_WITH_EQUALS =
+ const FixKind('REPLACE_COLON_WITH_EQUALS', 50, "Replace ':' with '='");
static const REPLACE_FINAL_WITH_CONST = const FixKind(
'REPLACE_FINAL_WITH_CONST', 50, "Replace 'final' with 'const'");
+ static const REPLACE_NULL_WITH_CLOSURE = const FixKind(
+ 'REPLACE_NULL_WITH_CLOSURE', 50, "Replace 'null' with a closure");
static const REPLACE_RETURN_TYPE_FUTURE = const FixKind(
'REPLACE_RETURN_TYPE_FUTURE',
50,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 322e99a..adeb0f9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -592,12 +592,18 @@
if (name == LintNames.non_constant_identifier_names) {
await _addFix_renameToCamelCase();
}
+ if (name == LintNames.null_closures) {
+ await _addFix_replaceNullWithClosure();
+ }
if (name == LintNames.prefer_conditional_assignment) {
await _addFix_replaceWithConditionalAssignment();
}
if (errorCode.name == LintNames.prefer_const_declarations) {
await _addFix_replaceFinalWithConst();
}
+ if (errorCode.name == LintNames.prefer_equal_for_default_values) {
+ await _addFix_replaceColonWithEquals();
+ }
if (name == LintNames.prefer_final_fields) {
await _addFix_makeVariableFinal();
}
@@ -610,6 +616,9 @@
if (name == LintNames.type_init_formals) {
await _addFix_removeTypeAnnotation();
}
+ if (name == LintNames.unawaited_futures) {
+ await _addFix_addAwait();
+ }
if (name == LintNames.unnecessary_brace_in_string_interps) {
await _addFix_removeInterpolationBraces();
}
@@ -656,6 +665,14 @@
}
}
+ Future<void> _addFix_addAwait() async {
+ var changeBuilder = _newDartChangeBuilder();
+ await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+ builder.addSimpleInsertion(node.offset, 'await ');
+ });
+ _addFixFromBuilder(changeBuilder, DartFixKind.ADD_AWAIT);
+ }
+
Future<void> _addFix_addExplicitCast() async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
@@ -3162,6 +3179,17 @@
args: [newName]);
}
+ Future<void> _addFix_replaceColonWithEquals() async {
+ if (node is DefaultFormalParameter) {
+ var changeBuilder = _newDartChangeBuilder();
+ await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+ builder.addSimpleReplacement(
+ range.token((node as DefaultFormalParameter).separator), '=');
+ });
+ _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_COLON_WITH_EQUALS);
+ }
+ }
+
Future<void> _addFix_replaceFinalWithConst() async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
@@ -3185,6 +3213,39 @@
_addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_VAR_WITH_DYNAMIC);
}
+ Future<void> _addFix_replaceNullWithClosure() async {
+ var nodeToFix;
+ var parameters = const <ParameterElement>[];
+ if (coveredNode is NamedExpression) {
+ NamedExpression namedExpression = coveredNode;
+ var expression = namedExpression.expression;
+ if (expression is NullLiteral) {
+ var element = namedExpression.element;
+ if (element is ParameterElement) {
+ var type = element.type;
+ if (type is FunctionType) {
+ parameters = type.parameters;
+ }
+ }
+ nodeToFix = expression;
+ }
+ } else if (coveredNode is NullLiteral) {
+ nodeToFix = coveredNode;
+ }
+
+ if (nodeToFix != null) {
+ var changeBuilder = _newDartChangeBuilder();
+ await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+ builder.addReplacement(range.node(nodeToFix),
+ (DartEditBuilder builder) {
+ builder.writeParameters(parameters);
+ builder.write(' => null');
+ });
+ });
+ _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_NULL_WITH_CLOSURE);
+ }
+ }
+
Future<void> _addFix_replaceWithConditionalAssignment() async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
@@ -4341,14 +4402,18 @@
static const String no_duplicate_case_values = 'no_duplicate_case_values';
static const String non_constant_identifier_names =
'non_constant_identifier_names';
+ static const String null_closures = 'null_closures';
static const String prefer_collection_literals = 'prefer_collection_literals';
static const String prefer_conditional_assignment =
'prefer_conditional_assignment';
static const String prefer_const_declarations = 'prefer_const_declarations';
+ static const String prefer_equal_for_default_values =
+ 'prefer_equal_for_default_values';
static const String prefer_final_fields = 'prefer_final_fields';
static const String prefer_final_locals = 'prefer_final_locals';
static const String prefer_is_not_empty = 'prefer_is_not_empty';
static const String type_init_formals = 'type_init_formals';
+ static const String unawaited_futures = 'unawaited_futures';
static const String unnecessary_brace_in_string_interps =
'unnecessary_brace_in_string_interps';
static const String unnecessary_const = 'unnecessary_const';
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index 6135864..f4593b4 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -23,7 +23,6 @@
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
-import 'package:plugin/manager.dart';
import 'package:test/test.dart';
import 'package:watcher/watcher.dart';
@@ -108,11 +107,6 @@
AnalysisServer createAnalysisServer() {
//
- // Process plugins
- //
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(AnalysisEngine.instance.requiredPlugins);
- //
// Create an SDK in the mock file system.
//
new MockSdk(
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 4a7e95d..88938f1 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -17,6 +17,7 @@
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
import 'package:analyzer/src/generated/sdk.dart';
@@ -30,7 +31,6 @@
import 'package:linter/src/rules.dart';
import 'package:linter/src/rules/avoid_as.dart';
import 'package:path/path.dart' as path;
-import 'package:plugin/manager.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:watcher/watcher.dart';
@@ -1722,9 +1722,6 @@
.firstWhere((ErrorProcessor p) => p.appliesTo(error), orElse: () => null);
void processRequiredPlugins() {
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(AnalysisEngine.instance.requiredPlugins);
-
registerLintRules();
}
@@ -1981,7 +1978,9 @@
String sdkExtPath = '$projPath/sdk_ext';
newFile('$projPath/test', content: 'test.dart');
newFile('$sdkExtPath/entry.dart');
- List<int> bytes = new SummaryBuilder([], null).build();
+ List<int> bytes = new SummaryBuilder(
+ [], RestrictedAnalysisContext(analysisOptions, null, null))
+ .build();
newFileWithBytes('$projPath/sdk.ds', bytes);
// Setup _embedder.yaml.
newFile('$libPath/_embedder.yaml', content: r'''
@@ -2045,8 +2044,10 @@
expect(
lintNames,
- unorderedEquals(
- ['avoid_as' /* embedder */, 'camel_case_types' /* options */]));
+ unorderedEquals([
+ 'avoid_as' /* embedder */,
+ 'camel_case_types' /* options */
+ ]));
// Sanity check embedder libs.
var source = sourceFactory.forUri('dart:foobar');
@@ -2498,20 +2499,12 @@
ContextBuilder builder =
createContextBuilder(folder, options, useSummaries: true);
- AnalysisContext context = builder.buildContext(folder.path);
- SourceFactory sourceFactory = context.sourceFactory;
- AnalysisOptions analysisOptions = context.analysisOptions;
- context.dispose();
+ builder.analysisDriverScheduler = scheduler;
+ builder.byteStore = MemoryByteStore();
+ builder.performanceLog = logger;
+ builder.fileContentOverlay = FileContentOverlay();
+ currentDriver = builder.buildDriver(contextRoot);
- currentDriver = new AnalysisDriver(
- scheduler,
- logger,
- resourceProvider,
- new MemoryByteStore(),
- new FileContentOverlay(),
- contextRoot,
- sourceFactory,
- analysisOptions);
driverMap[path] = currentDriver;
currentDriver.exceptions.listen((ExceptionResult result) {
AnalysisEngine.instance.logger
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
index c9be4cd..1ea7f7c 100644
--- a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
@@ -44,6 +44,7 @@
class int {}
class num {}
class Object {}
+class Iterable<E> {}
class Map<K, V> {}
class Null {}
class String {}
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 73f5b37..2955d79 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
@@ -5,6 +5,7 @@
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/dart/ast/token.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -14,6 +15,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(KeywordContributorTest);
+ defineReflectiveTests(KeywordContributorWithUiAsCodeTest);
});
}
@@ -1882,3 +1884,153 @@
return true;
}
}
+
+@reflectiveTest
+class KeywordContributorWithUiAsCodeTest extends KeywordContributorTest {
+ static const List<Keyword> COLLECTION_ELEMENT_START = const [
+ Keyword.CONST,
+ Keyword.FALSE,
+ Keyword.FOR,
+ Keyword.IF,
+ Keyword.NEW,
+ Keyword.NULL,
+ Keyword.TRUE,
+ ];
+
+ @override
+ void setupResourceProvider() {
+ super.setupResourceProvider();
+ createAnalysisOptionsFile(experiments: [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections
+ ]);
+ }
+
+ test_ifOrForElement_forElement() async {
+ addTestSource('''
+f() => [for (var e in c) ^];
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_ifElement_else() async {
+ addTestSource('''
+f() => [if (true) 1 else ^];
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_ifElement_then() async {
+ addTestSource('''
+f() => [if (true) ^];
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_list_empty() async {
+ addTestSource('''
+f() => [^];
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_list_first() async {
+ addTestSource('''
+f() => [^1, 2];
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_list_last() async {
+ addTestSource('''
+f() => [1, 2, ^];
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_list_middle() async {
+ addTestSource('''
+f() => [1, ^, 2];
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_map_empty() async {
+ addTestSource('''
+f() => <String, int>{^};
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_map_first() async {
+ addTestSource('''
+f() => <String, int>{^'a' : 1};
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_map_last() async {
+ addTestSource('''
+f() => <String, int>{'a' : 1, 'b' : 2, ^};
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_map_middle() async {
+ addTestSource('''
+f() => <String, int>{'a' : 1, ^, 'b' : 2];
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_set_empty() async {
+ addTestSource('''
+f() => <int>{^};
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_set_first() async {
+ addTestSource('''
+f() => <int>{^1, 2};
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_set_last() async {
+ addTestSource('''
+f() => <int>{1, 2, ^};
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_ifOrForElement_set_middle() async {
+ addTestSource('''
+f() => <int>{1, ^, 2};
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(COLLECTION_ELEMENT_START);
+ }
+
+ test_spreadElement() async {
+ addTestSource('''
+f() => [...^];
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(KeywordContributorTest.EXPRESSION_START_NO_INSTANCE);
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
index c3712b1..11eb5eb 100644
--- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -3659,6 +3659,19 @@
assertNotSuggested('ms3');
}
+ test_super_fromSuperclassConstraint() async {
+ addTestSource('''
+class C {
+ void c(x, int y) {}
+}
+mixin M on C {
+ m() {super.^}
+}
+''');
+ await computeSuggestions();
+ assertSuggestMethod('c', 'C', 'void');
+ }
+
test_super_withMixin() async {
addTestSource('''
mixin M {
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
index 4dbfd3c..e99991e 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
@@ -134,6 +134,35 @@
''');
}
+ test_newImport_part() async {
+ var partCode = r'''
+part of 'test.dart';
+
+main() {} // ref
+''';
+ var partPath = newFile('/home/test/lib/a.dart', content: partCode).path;
+ addTestFile(r'''
+part 'a.dart';
+''');
+
+ var mathSet = await waitForSetWithUri('dart:math');
+ var result = await _getSuggestionDetails(
+ _buildRequest(
+ file: partPath,
+ id: mathSet.id,
+ label: 'sin',
+ offset: partCode.indexOf('} // ref'),
+ ),
+ );
+
+ expect(result.completion, 'sin');
+ _assertTestFileChange(result.change, r'''
+import 'dart:math';
+
+part 'a.dart';
+''');
+ }
+
void _assertEmptyChange(SourceChange change) {
expect(change.edits, isEmpty);
}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart
new file mode 100644
index 0000000..36e3fab
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConvertIntoAbsoluteImportTest);
+ });
+}
+
+@reflectiveTest
+class ConvertIntoAbsoluteImportTest extends AssistProcessorTest {
+ @override
+ AssistKind get kind => DartAssistKind.CONVERT_INTO_ABSOLUTE_IMPORT;
+
+ test_fileName_onUri() async {
+ addSource('/home/test/lib/foo.dart', '');
+
+ await resolveTestUnit('''
+import 'foo.dart';
+''');
+ await assertHasAssistAt('foo.dart', '''
+import 'package:test/foo.dart';
+''');
+ }
+
+ test_fileName_onImport() async {
+ addSource('/home/test/lib/foo.dart', '');
+
+ await resolveTestUnit('''
+import 'foo.dart';
+''');
+ // Validate assist is on import keyword too.
+ await assertHasAssistAt('import', '''
+import 'package:test/foo.dart';
+''');
+ }
+
+ test_nonPackage_Uri() async {
+ addSource('/home/test/lib/foo.dart', '');
+
+ await resolveTestUnit('''
+import 'dart:core';
+''');
+
+ await assertNoAssistAt('dart:core');
+ await assertNoAssistAt('import');
+ }
+
+ test_path() async {
+ addSource('/home/test/lib/foo/bar.dart', '');
+
+ testFile = convertPath('/home/test/lib/src/test.dart');
+
+ await resolveTestUnit('''
+import '../foo/bar.dart';
+''');
+ await assertHasAssistAt('bar.dart', '''
+import 'package:test/foo/bar.dart';
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index 1d75bb9..9bba973 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -11,6 +11,7 @@
as convert_documentation_into_block;
import 'convert_documentation_into_line_test.dart'
as convert_documentation_into_line;
+import 'convert_into_absolute_import_test.dart' as convert_into_absolute_import;
import 'convert_into_async_body_test.dart' as convert_into_async_body;
import 'convert_into_block_body_test.dart' as convert_into_block_body;
import 'convert_into_expression_body_test.dart' as convert_into_expression_body;
@@ -82,6 +83,7 @@
convert_class_to_mixin.main();
convert_documentation_into_block.main();
convert_documentation_into_line.main();
+ convert_into_absolute_import.main();
convert_into_async_body.main();
convert_into_block_body.main();
convert_into_expression_body.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_await_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_await_test.dart
new file mode 100644
index 0000000..1391007
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_await_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(AddAwaitTest);
+ });
+}
+
+@reflectiveTest
+class AddAwaitTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.ADD_AWAIT;
+
+ @override
+ String get lintCode => LintNames.unawaited_futures;
+
+ test_intLiteral() async {
+ await resolveTestUnit('''
+Future doSomething() => new Future();
+
+void main() async {
+ doSomething()/*LINT*/;
+}
+''');
+ await assertHasFix('''
+Future doSomething() => new Future();
+
+void main() async {
+ await doSomething()/*LINT*/;
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
new file mode 100644
index 0000000..375a662
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ReplaceColonWithEqualsTest);
+ });
+}
+
+@reflectiveTest
+class ReplaceColonWithEqualsTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REPLACE_COLON_WITH_EQUALS;
+
+ @override
+ String get lintCode => LintNames.prefer_equal_for_default_values;
+
+ test_method() async {
+ await resolveTestUnit('''
+void f1({int a}) { }
+
+f1({a/*LINT*/: 1}) => null;
+''');
+ await assertHasFix('''
+void f1({int a}) { }
+
+f1({a/*LINT*/= 1}) => null;
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart
new file mode 100644
index 0000000..4ada2dd
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ReplaceNullWithClosureTest);
+ });
+}
+
+@reflectiveTest
+class ReplaceNullWithClosureTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REPLACE_NULL_WITH_CLOSURE;
+
+ @override
+ String get lintCode => LintNames.null_closures;
+
+ test_null_closure_named_expression() async {
+ await resolveTestUnit('''
+main() {
+ [1, 3, 5].firstWhere((e) => e.isOdd, orElse: /*LINT*/null);
+}
+''');
+ await assertHasFix('''
+main() {
+ [1, 3, 5].firstWhere((e) => e.isOdd, orElse: /*LINT*/() => null);
+}
+''');
+ }
+
+ test_null_closure_named_expression_with_args() async {
+ await resolveTestUnit('''
+void f({int closure(x, y)}) { }
+main() {
+ f(closure: /*LINT*/null);
+}
+''');
+ await assertHasFix('''
+void f({int closure(x, y)}) { }
+main() {
+ f(closure: /*LINT*/(x, y) => null);
+}
+''');
+ }
+
+ test_null_closure_named_expression_with_args_2() async {
+ await resolveTestUnit('''
+void f({int closure(x, y, {z})}) { }
+main() {
+ f(closure: /*LINT*/null);
+}
+''');
+ await assertHasFix('''
+void f({int closure(x, y, {z})}) { }
+main() {
+ f(closure: /*LINT*/(x, y, {z}) => null);
+}
+''');
+ }
+
+ /// Currently failing since the LINT annotation is tagging the ArgumentList
+ /// where the fix (and lint) expect a NullLiteral.
+ /// todo (pq): re-write FixProcessorLintTest to run the actual lints.
+ @failingTest
+ test_null_closure_literal() async {
+ await resolveTestUnit('''
+void f(dynamic x) { }
+main() {
+ f(null/*LINT*/);
+}
+''');
+ await assertHasFix('''
+void f(dynamic x) { }
+main() {
+ f(/*LINT*/() => null);
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 07369fb..9e4fffb 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -5,6 +5,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'add_async_test.dart' as add_async;
+import 'add_await_test.dart' as add_await;
import 'add_explicit_cast_test.dart' as add_explicit_cast;
import 'add_field_formal_parameters_test.dart' as add_field_formal_parameters;
import 'add_missing_parameter_named_test.dart' as add_missing_parameter_named;
@@ -57,6 +58,7 @@
import 'remove_annotation_test.dart' as remove_annotation;
import 'remove_await_test.dart' as remove_await;
import 'remove_dead_code_test.dart' as remove_dead_code;
+import 'remove_duplicate_case_test.dart' as remove_duplicate_case;
import 'remove_empty_catch_test.dart' as remove_empty_catch;
import 'remove_empty_constructor_body_test.dart'
as remove_empty_constructor_body;
@@ -81,7 +83,9 @@
import 'remove_unused_import_test.dart' as remove_unused_import;
import 'rename_to_camel_case_test.dart' as rename_to_camel_case;
import 'replace_boolean_with_bool_test.dart' as replace_boolean_with_bool;
+import 'replace_colon_with_equals_test.dart' as replace_colon_with_equals;
import 'replace_final_with_const_test.dart' as replace_final_with_const;
+import 'replace_null_with_closure_test.dart' as replace_null_with_closure;
import 'replace_return_type_future_test.dart' as replace_return_type_future;
import 'replace_var_with_dynamic_test.dart' as replace_var_with_dynamic;
import 'replace_with_brackets_test.dart' as replace_with_brackets;
@@ -97,10 +101,12 @@
import 'use_eq_eq_null_test.dart' as use_eq_eq_null;
import 'use_is_not_empty_test.dart' as use_is_not_empty;
import 'use_not_eq_null_test.dart' as use_not_eq_null;
+import 'use_rethrow_test.dart' as use_rethrow;
main() {
defineReflectiveSuite(() {
add_async.main();
+ add_await.main();
add_explicit_cast.main();
add_field_formal_parameters.main();
add_missing_parameter_named.main();
@@ -147,6 +153,7 @@
remove_annotation.main();
remove_await.main();
remove_dead_code.main();
+ remove_duplicate_case.main();
remove_empty_catch.main();
remove_empty_constructor_body.main();
remove_empty_else.main();
@@ -168,7 +175,9 @@
remove_unused_import.main();
rename_to_camel_case.main();
replace_boolean_with_bool.main();
+ replace_colon_with_equals.main();
replace_final_with_const.main();
+ replace_null_with_closure.main();
replace_return_type_future.main();
replace_var_with_dynamic.main();
replace_with_brackets.main();
@@ -182,5 +191,6 @@
use_eq_eq_null.main();
use_is_not_empty.main();
use_not_eq_null.main();
+ use_rethrow.main();
}, name: 'fix');
}
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 88eea40..e376b96 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,4 +1,4 @@
-##
+## 0.35.4
* Deprecated AST structures that will no longer be used after the
control_flow_collections and spread_collections experiments are enabled. The
following AST node types are deprecated:
@@ -13,6 +13,13 @@
* `visitForStatement` (override `visitForStatement2` instead)
* `visitMapLiteral` (override `visitSetOrMapLiteral` instead)
* `visitSetLiteral` (override `visitSetOrMapLiteral` instead)
+* Deprecated ASTFactory methods that will no longer be available after the
+ control_flow_collections and spread_collections experiments are enabled. The
+ following factory methods are deprecated:
+ * `mapLiteral` and `mapLiteral2` (use `setOrMapLiteral` instead)
+ * `setLiteral` and `setLiteral2` (use `setOrMapLiteral` instead)
+* Bug fixes: #33119, #33241, #35747, #35900, #36048, #36129
+* The analyzer no longer uses `package:html` (see #35802)
## 0.35.3
* Further updates to the AST structure for the control_flow_collections and
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 271b921..b2ce8fa 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -4731,8 +4731,17 @@
/// This getter will always return `false` if [isSet] returns `true`.
///
/// However, this getter is _not_ the inverse of [isSet]. It is possible for
- /// both getters to return `false` if the literal was either invalid or
- /// ambiguous.
+ /// both getters to return `false` if
+ ///
+ /// - the AST has not been resolved (because determining the kind of the
+ /// literal is done during resolution),
+ /// - the literal is ambiguous (contains one or more spread elements and none
+ /// of those elements can be used to determine the kind of the literal), or
+ /// - the literal is invalid because it contains both expressions (for sets)
+ /// and map entries (for maps).
+ ///
+ /// In both of the latter two cases there will be compilation errors
+ /// associated with the literal.
bool get isMap;
/// Return `true` if this literal represents a set literal.
@@ -4740,8 +4749,17 @@
/// This getter will always return `false` if [isMap] returns `true`.
///
/// However, this getter is _not_ the inverse of [isMap]. It is possible for
- /// both getters to return `false` if the literal was either invalid or
- /// ambiguous.
+ /// both getters to return `false` if
+ ///
+ /// - the AST has not been resolved (because determining the kind of the
+ /// literal is done during resolution),
+ /// - the literal is ambiguous (contains one or more spread elements and none
+ /// of those elements can be used to determine the kind of the literal), or
+ /// - the literal is invalid because it contains both expressions (for sets)
+ /// and map entries (for maps).
+ ///
+ /// In both of the latter two cases there will be compilation errors
+ /// associated with the literal.
bool get isSet;
/// Return the left curly bracket.
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index f4ce6d91..156688d 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// 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.
@@ -39,13 +39,13 @@
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/java_engine.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/task/api/model.dart' show AnalysisTarget;
-import 'package:analyzer/src/task/dart.dart';
/// An element that represents a class or a mixin. The class can be defined by
/// either a class declaration (with a class body), a mixin application (without
@@ -727,10 +727,6 @@
/// subclasses as being immutable.
bool get isImmutable;
- /// Return `true` if this annotation marks the associated constructor as
- /// being literal.
- bool get isLiteral;
-
/// Return `true` if this annotation marks the associated member as running
/// a single test.
bool get isIsTest;
@@ -743,6 +739,10 @@
/// `JS` annotation.
bool get isJS;
+ /// Return `true` if this annotation marks the associated constructor as
+ /// being literal.
+ bool get isLiteral;
+
/// Return `true` if this annotation marks the associated member as requiring
/// overriding methods to call super.
bool get isMustCallSuper;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 92894f9..a4ba3c5 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -67,6 +67,8 @@
CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD,
CompileTimeErrorCode.AMBIGUOUS_EXPORT,
+ CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
+ CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER,
CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
CompileTimeErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS,
CompileTimeErrorCode.ARGUMENT_DEFINITION_TEST_NON_PARAMETER,
@@ -110,6 +112,8 @@
CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
CompileTimeErrorCode.CONST_NOT_INITIALIZED,
CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+ CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+ CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP,
CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS,
CompileTimeErrorCode.CONST_WITH_NON_CONST,
CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT,
@@ -127,6 +131,7 @@
CompileTimeErrorCode.DUPLICATE_PART,
CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY,
CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
+ CompileTimeErrorCode.EXPRESSION_IN_MAP,
CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS,
CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
CompileTimeErrorCode.EXTENDS_NON_CLASS,
@@ -181,6 +186,7 @@
CompileTimeErrorCode.INVALID_USE_OF_COVARIANT,
CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
CompileTimeErrorCode.LABEL_UNDEFINED,
+ CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP,
CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME,
CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL,
CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL,
@@ -226,6 +232,8 @@
CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
CompileTimeErrorCode.NON_SYNC_FACTORY,
CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS,
+ CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
+ CompileTimeErrorCode.NOT_MAP_SPREAD,
CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS,
CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT,
CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT,
@@ -390,6 +398,7 @@
ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
ParserErrorCode.EXPECTED_CASE_OR_DEFAULT,
ParserErrorCode.EXPECTED_CLASS_MEMBER,
+ ParserErrorCode.EXPECTED_ELSE_OR_COMMA,
ParserErrorCode.EXPECTED_EXECUTABLE,
ParserErrorCode.EXPECTED_INSTEAD,
ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index b6fd429..95a75e7 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -3,57 +3,27 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
-import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/cancelable_future.dart';
import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
import 'package:analyzer/src/context/cache.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/resolver.dart';
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_collection.dart';
import 'package:analyzer/src/plugin/resolver_provider.dart';
-import 'package:analyzer/src/plugin/task.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/dart_work_manager.dart';
import 'package:analyzer/src/task/driver.dart';
-import 'package:analyzer/src/task/manager.dart';
-
-/**
- * Type of callback functions used by PendingFuture. Functions of this type
- * should perform a computation based on the data in [entry] and return it. If
- * the computation can't be performed yet because more analysis is needed,
- * `null` should be returned.
- *
- * The function may also throw an exception, in which case the corresponding
- * future will be completed with failure.
- *
- * Because this function is called while the state of analysis is being updated,
- * it should be free of side effects so that it doesn't cause reentrant changes
- * to the analysis state.
- */
-typedef T PendingFutureComputer<T>(CacheEntry entry);
/**
* An [AnalysisContext] in which analysis can be performed.
*/
class AnalysisContextImpl implements InternalAnalysisContext {
/**
- * The flag that is `true` if the context is being analyzed.
- */
- bool _isActive = false;
-
- /**
* A client-provided name used to identify this context, or `null` if the
* client has not provided a name.
*/
@@ -66,22 +36,6 @@
AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
/**
- * The embedder yaml locator for this context.
- */
- @deprecated
- EmbedderYamlLocator _embedderYamlLocator = new EmbedderYamlLocator(null);
-
- /**
- * A flag indicating whether this context is disposed.
- */
- bool _disposed = false;
-
- /**
- * A cache of content used to override the default content of a source.
- */
- ContentCache _contentCache = new ContentCache();
-
- /**
* The source factory used to create the sources that can be analyzed in this
* context.
*/
@@ -92,18 +46,6 @@
*/
DeclaredVariables _declaredVariables = new DeclaredVariables();
- /**
- * The partition that contains analysis results that are not shared with other
- * contexts.
- */
- CachePartition _privatePartition;
-
- /**
- * The cache in which information about the results associated with targets
- * are stored.
- */
- AnalysisCache _cache;
-
@override
final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
new ReentrantSynchronousStream<InvalidatedResult>();
@@ -111,55 +53,17 @@
ReentrantSynchronousStreamSubscription onResultInvalidatedSubscription = null;
/**
- * Configuration data associated with this context.
- */
- final HashMap<ResultDescriptor, Object> _configurationData =
- new HashMap<ResultDescriptor, Object>();
-
- /**
- * The task manager used to manage the tasks used to analyze code.
- */
- TaskManager _taskManager;
-
- /**
* A list of all [WorkManager]s used by this context.
*/
@override
final List<WorkManager> workManagers = <WorkManager>[];
/**
- * The [DartWorkManager] instance that performs Dart specific scheduling.
- */
- DartWorkManager dartWorkManager;
-
- /**
* The analysis driver used to perform analysis.
*/
AnalysisDriver driver;
/**
- * A list containing sources for which data should not be flushed.
- */
- List<Source> _priorityOrder = <Source>[];
-
- CacheConsistencyValidatorImpl _cacheConsistencyValidator;
-
- /**
- * A map from all sources for which there are futures pending to a list of
- * the corresponding PendingFuture objects. These sources will be analyzed
- * in the same way as priority sources, except with higher priority.
- */
- Map<AnalysisTarget, List<PendingFuture>> _pendingFutureTargets =
- new HashMap<AnalysisTarget, List<PendingFuture>>();
-
- /**
- * A table mapping sources to the change notices that are waiting to be
- * returned related to that source.
- */
- Map<Source, ChangeNoticeImpl> _pendingNotices =
- new HashMap<Source, ChangeNoticeImpl>();
-
- /**
* The [TypeProvider] for this context, `null` if not yet created.
*/
TypeProvider _typeProvider;
@@ -170,23 +74,6 @@
TypeSystem _typeSystem;
/**
- * The controller for sending [SourcesChangedEvent]s.
- */
- StreamController<SourcesChangedEvent> _onSourcesChangedController;
-
- /**
- * A subscription for a stream of events indicating when files are (and are
- * not) being implicitly analyzed.
- */
- StreamController<ImplicitAnalysisEvent> _implicitAnalysisEventsController;
-
- /**
- * The listeners that are to be notified when various analysis results are
- * produced in this context.
- */
- List<AnalysisListener> _listeners = new List<AnalysisListener>();
-
- /**
* Determines whether this context should attempt to make use of the global
* SDK cache partition. Note that if this context is responsible for
* resynthesizing the SDK element model, this flag should be set to `false`,
@@ -199,13 +86,6 @@
ResultProvider resultProvider;
/**
- * The map of [ResultChangedEvent] controllers.
- */
- final Map<ResultDescriptor, StreamController<ResultChangedEvent>>
- _resultChangedControllers =
- <ResultDescriptor, StreamController<ResultChangedEvent>>{};
-
- /**
* The most recently incrementally resolved source, or `null` when it was
* already validated, or the most recent change was not incrementally resolved.
*/
@@ -230,30 +110,12 @@
/**
* Initialize a newly created analysis context.
*/
- AnalysisContextImpl() {
- AnalysisEngine.instance.processRequiredPlugins();
- _privatePartition = new UniversalCachePartition(this);
- _cache = createCacheFromSourceFactory(null);
- _taskManager = AnalysisEngine.instance.taskManager;
- for (WorkManagerFactory factory
- in AnalysisEngine.instance.enginePlugin.workManagerFactories) {
- WorkManager workManager = factory(this);
- if (workManager != null) {
- workManagers.add(workManager);
- if (workManager is DartWorkManager) {
- dartWorkManager = workManager;
- }
- }
- }
- driver = new AnalysisDriver(_taskManager, workManagers, this);
- _onSourcesChangedController =
- new StreamController<SourcesChangedEvent>.broadcast();
- _implicitAnalysisEventsController =
- new StreamController<ImplicitAnalysisEvent>.broadcast();
- }
+ AnalysisContextImpl();
@override
- AnalysisCache get analysisCache => _cache;
+ AnalysisCache get analysisCache {
+ throw UnimplementedError();
+ }
@override
AnalysisOptions get analysisOptions => _options;
@@ -261,37 +123,20 @@
@override
void set analysisOptions(AnalysisOptions options) {
this._options = options;
- for (WorkManager workManager in workManagers) {
- workManager.onAnalysisOptionsChanged();
- }
}
@override
void set analysisPriorityOrder(List<Source> sources) {
- if (sources == null || sources.isEmpty) {
- _priorityOrder = const <Source>[];
- } else {
- while (sources.remove(null)) {
- // Nothing else to do.
- }
- if (sources.isEmpty) {
- _priorityOrder = const <Source>[];
- } else {
- _priorityOrder = sources;
- }
- }
- for (WorkManager workManager in workManagers) {
- workManager.applyPriorityTargets(_priorityOrder);
- }
- driver.reset();
+ throw UnimplementedError();
}
- CacheConsistencyValidator get cacheConsistencyValidator =>
- _cacheConsistencyValidator ??= new CacheConsistencyValidatorImpl(this);
+ CacheConsistencyValidator get cacheConsistencyValidator {
+ throw UnimplementedError();
+ }
@override
set contentCache(ContentCache value) {
- _contentCache = value;
+ throw UnimplementedError();
}
@override
@@ -306,117 +151,86 @@
@deprecated
@override
- EmbedderYamlLocator get embedderYamlLocator => _embedderYamlLocator;
+ EmbedderYamlLocator get embedderYamlLocator {
+ throw UnimplementedError();
+ }
@override
List<AnalysisTarget> get explicitTargets {
- List<AnalysisTarget> targets = <AnalysisTarget>[];
- MapIterator<AnalysisTarget, CacheEntry> iterator = _cache.iterator();
- while (iterator.moveNext()) {
- if (iterator.value.explicitlyAdded) {
- targets.add(iterator.key);
- }
- }
- return targets;
+ throw UnimplementedError();
}
@override
- List<Source> get htmlSources => _getSources(SourceKind.HTML);
+ List<Source> get htmlSources {
+ throw UnimplementedError();
+ }
@override
- Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents =>
- _implicitAnalysisEventsController.stream;
+ Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents {
+ throw UnimplementedError();
+ }
@override
- bool get isActive => _isActive;
+ bool get isActive {
+ throw UnimplementedError();
+ }
@override
set isActive(bool active) {
- if (active != _isActive) {
- _isActive = active;
- _privatePartition.isActive = active;
- }
+ throw UnimplementedError();
}
@override
- bool get isDisposed => _disposed;
+ bool get isDisposed {
+ throw UnimplementedError();
+ }
@override
List<Source> get launchableClientLibrarySources {
- List<Source> sources = <Source>[];
- for (Source source in _cache.sources) {
- CacheEntry entry = _cache.get(source);
- if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
- !source.isInSystemLibrary &&
- isClientLibrary(source)) {
- sources.add(source);
- }
- }
- return sources;
+ throw UnimplementedError();
}
@override
List<Source> get launchableServerLibrarySources {
- List<Source> sources = <Source>[];
- for (Source source in _cache.sources) {
- CacheEntry entry = _cache.get(source);
- if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
- !source.isInSystemLibrary &&
- isServerLibrary(source)) {
- sources.add(source);
- }
- }
- return sources;
+ throw UnimplementedError();
}
@override
- List<Source> get librarySources => _getSources(SourceKind.LIBRARY);
+ List<Source> get librarySources {
+ throw UnimplementedError();
+ }
@override
- Stream<SourcesChangedEvent> get onSourcesChanged =>
- _onSourcesChangedController.stream;
-
- /**
- * Make _pendingFutureSources available to unit tests.
- */
- Map<AnalysisTarget, List<PendingFuture>>
- get pendingFutureSources_forTesting => _pendingFutureTargets;
+ Stream<SourcesChangedEvent> get onSourcesChanged {
+ throw UnimplementedError();
+ }
@override
- List<Source> get prioritySources => _priorityOrder;
+ List<Source> get prioritySources {
+ throw UnimplementedError();
+ }
@override
- List<AnalysisTarget> get priorityTargets => prioritySources;
+ List<AnalysisTarget> get priorityTargets {
+ throw UnimplementedError();
+ }
@override
- CachePartition get privateAnalysisCachePartition => _privatePartition;
+ CachePartition get privateAnalysisCachePartition {
+ throw UnimplementedError();
+ }
@override
SourceFactory get sourceFactory => _sourceFactory;
@override
void set sourceFactory(SourceFactory factory) {
- if (identical(_sourceFactory, factory)) {
- return;
- } else if (factory.context != null) {
- throw new StateError(
- "Source factories cannot be shared between contexts");
- }
- if (_sourceFactory != null) {
- _sourceFactory.context = null;
- }
- factory.context = this;
_sourceFactory = factory;
- _cache?.dispose();
- _cache = createCacheFromSourceFactory(factory);
- for (WorkManager workManager in workManagers) {
- workManager.onSourceFactoryChanged();
- }
}
@override
List<Source> get sources {
- return _cache.sources.toList();
+ throw UnimplementedError();
}
/**
@@ -426,57 +240,15 @@
* testing purposes only.
*/
List<Source> get sourcesNeedingProcessing {
- HashSet<Source> sources = new HashSet<Source>();
- bool hintsEnabled = _options.hint;
- bool lintsEnabled = _options.lint;
-
- MapIterator<AnalysisTarget, CacheEntry> iterator =
- _privatePartition.iterator();
- while (iterator.moveNext()) {
- AnalysisTarget target = iterator.key;
- if (target is Source) {
- _getSourcesNeedingProcessing(
- target, iterator.value, false, hintsEnabled, lintsEnabled, sources);
- }
- }
- return new List<Source>.from(sources);
+ throw UnimplementedError();
}
- List<Source> get test_priorityOrder => _priorityOrder;
+ List<Source> get test_priorityOrder {
+ throw UnimplementedError();
+ }
@override
TypeProvider get typeProvider {
- // The `AnalysisContextTarget.request` results go into the SDK partition,
- // and the TYPE_PROVIDER result is computed and put into the SDK partition
- // only by the first non-SDK analysis context. So, in order to reuse it
- // in other analysis contexts, we need to ask for it from the cache.
- _typeProvider ??= getResult(AnalysisContextTarget.request, TYPE_PROVIDER);
- if (_typeProvider != null) {
- return _typeProvider;
- }
-
- // Make sure a task didn't accidentally try to call back into the context
- // to retrieve the type provider.
- assert(!driver.isTaskRunning);
-
- Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
- if (coreSource == null) {
- throw new AnalysisException("Could not create a source for dart:core");
- }
- LibraryElement coreElement = computeLibraryElement(coreSource);
- if (coreElement == null) {
- throw new AnalysisException("Could not create an element for dart:core");
- }
-
- Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
- if (asyncSource == null) {
- throw new AnalysisException("Could not create a source for dart:async");
- }
- LibraryElement asyncElement = computeLibraryElement(asyncSource);
- if (asyncElement == null) {
- throw new AnalysisException("Could not create an element for dart:async");
- }
- _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
return _typeProvider;
}
@@ -490,411 +262,175 @@
@override
TypeSystem get typeSystem {
- if (_typeSystem == null) {
- _typeSystem = TypeSystem.create(this);
- }
- return _typeSystem;
+ return _typeSystem ??= Dart2TypeSystem(typeProvider);
}
@override
bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
- return PerformanceStatistics.summary.makeCurrentWhile(() {
- // Use this helper if it is set.
- if (resultProvider != null && resultProvider.compute(entry, result)) {
- return true;
- }
- // Ask the SDK.
- DartSdk dartSdk = sourceFactory.dartSdk;
- if (dartSdk != null) {
- AnalysisContext sdkContext = dartSdk.context;
- if (!identical(sdkContext, this) &&
- sdkContext is InternalAnalysisContext) {
- return sdkContext.aboutToComputeResult(entry, result);
- }
- }
- // Cannot provide the result.
- return false;
- });
+ throw UnimplementedError();
}
@override
void addListener(AnalysisListener listener) {
- if (!_listeners.contains(listener)) {
- _listeners.add(listener);
- }
+ throw UnimplementedError();
}
@override
void applyAnalysisDelta(AnalysisDelta delta) {
- ChangeSet changeSet = new ChangeSet();
- delta.analysisLevels.forEach((Source source, AnalysisLevel level) {
- if (level == AnalysisLevel.NONE) {
- changeSet.removedSource(source);
- } else {
- changeSet.addedSource(source);
- }
- });
- applyChanges(changeSet);
+ throw UnimplementedError();
}
@override
void applyChanges(ChangeSet changeSet) {
- if (changeSet.isEmpty) {
- return;
- }
- //
- // First, compute the list of sources that have been removed.
- //
- List<Source> removedSources = changeSet.removedSources.toList();
- for (SourceContainer container in changeSet.removedContainers) {
- _addSourcesInContainer(removedSources, container);
- }
- //
- // Then determine which cached results are no longer valid.
- //
- for (Source source in changeSet.addedSources) {
- _sourceAvailable(source);
- }
- // Exclude sources that are overridden in the content cache, so the change
- // will have no effect. Just ignore it to avoid wasting time doing
- // re-analysis.
- List<Source> changedSources = changeSet.changedSources
- .where((s) => _contentCache.getContents(s) == null)
- .toList();
- for (Source source in changedSources) {
- _sourceChanged(source);
- }
- changeSet.changedContents.forEach((Source key, String value) {
- _contentsChanged(key, value, false);
- });
- changeSet.changedRanges
- .forEach((Source source, ChangeSet_ContentChange change) {
- _contentRangeChanged(source, change.contents, change.offset,
- change.oldLength, change.newLength);
- });
- for (Source source in removedSources) {
- _sourceRemoved(source);
- }
- for (WorkManager workManager in workManagers) {
- workManager.applyChange(
- changeSet.addedSources, changedSources, removedSources);
- }
- _onSourcesChangedController.add(new SourcesChangedEvent(changeSet));
+ throw UnimplementedError();
}
@override
- String computeDocumentationComment(Element element) =>
- element?.documentationComment;
+ String computeDocumentationComment(Element element) {
+ throw UnimplementedError();
+ }
@override
List<AnalysisError> computeErrors(Source source) {
- return computeResult(source, DART_ERRORS);
+ throw UnimplementedError();
}
@override
- List<Source> computeExportedLibraries(Source source) =>
- computeResult(source, EXPORTED_LIBRARIES);
+ List<Source> computeExportedLibraries(Source source) {
+ throw UnimplementedError();
+ }
@override
- List<Source> computeImportedLibraries(Source source) =>
- computeResult(source, EXPLICITLY_IMPORTED_LIBRARIES);
+ List<Source> computeImportedLibraries(Source source) {
+ throw UnimplementedError();
+ }
@override
SourceKind computeKindOf(Source source) {
- String name = source.shortName;
- if (AnalysisEngine.isDartFileName(name)) {
- return computeResult(source, SOURCE_KIND);
- }
- return SourceKind.UNKNOWN;
+ throw UnimplementedError();
}
@override
LibraryElement computeLibraryElement(Source source) {
- //_computeResult(source, HtmlEntry.ELEMENT);
- return computeResult(source, LIBRARY_ELEMENT);
+ throw UnimplementedError();
}
@override
- LineInfo computeLineInfo(Source source) => computeResult(source, LINE_INFO);
+ LineInfo computeLineInfo(Source source) {
+ throw UnimplementedError();
+ }
@override
CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync(
Source unitSource, Source librarySource) {
- if (!AnalysisEngine.isDartFileName(unitSource.shortName) ||
- !AnalysisEngine.isDartFileName(librarySource.shortName)) {
- return new CancelableFuture.error(new AnalysisNotScheduledError());
- }
- return new AnalysisFutureHelper<CompilationUnit>(this,
- new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT)
- .computeAsync();
+ throw UnimplementedError();
}
@override
V computeResult<V>(AnalysisTarget target, ResultDescriptor<V> descriptor) {
- // Make sure we are not trying to invoke the task model in a reentrant
- // fashion.
- assert(!driver.isTaskRunning);
- CacheEntry entry = getCacheEntry(target);
- CacheState state = entry.getState(descriptor);
- if (state == CacheState.FLUSHED || state == CacheState.INVALID) {
- // Check the result provider.
- bool success = aboutToComputeResult(entry, descriptor);
- if (success) {
- return entry.getValue(descriptor);
- }
- // Compute the result.
- driver.computeResult(target, descriptor);
- entry = getCacheEntry(target);
- }
- state = entry.getState(descriptor);
- if (state == CacheState.ERROR) {
- throw new AnalysisException(
- 'Cannot compute $descriptor for $target', entry.exception);
- }
- return entry.getValue(descriptor);
+ throw UnimplementedError();
}
/**
* Create an analysis cache based on the given source [factory].
*/
AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
- AnalysisCache createCache() {
- if (factory == null) {
- return new AnalysisCache(<CachePartition>[_privatePartition]);
- }
- if (!useSdkCachePartition) {
- return new AnalysisCache(<CachePartition>[_privatePartition]);
- }
- DartSdk sdk = factory.dartSdk;
- if (sdk == null) {
- return new AnalysisCache(<CachePartition>[_privatePartition]);
- }
- return new AnalysisCache(<CachePartition>[
- AnalysisEngine.instance.partitionManager.forSdk(sdk),
- _privatePartition
- ]);
- }
-
- AnalysisCache cache = createCache();
- onResultInvalidatedSubscription?.cancel();
- onResultInvalidatedSubscription =
- cache.onResultInvalidated.listen((InvalidatedResult event) {
- onResultInvalidated.add(event);
- StreamController<ResultChangedEvent> controller =
- _resultChangedControllers[event.descriptor];
- if (controller != null) {
- controller.add(new ResultChangedEvent(
- this, event.entry.target, event.descriptor, event.value, false));
- }
- });
- return cache;
+ throw UnimplementedError();
}
@override
- void dispose() {
- _disposed = true;
- for (List<PendingFuture> pendingFutures in _pendingFutureTargets.values) {
- for (PendingFuture pendingFuture in pendingFutures) {
- pendingFuture.forciblyComplete();
- }
- }
- _pendingFutureTargets.clear();
- _privatePartition.dispose();
- _cache.dispose();
- }
+ void dispose() {}
@override
List<CompilationUnit> ensureResolvedDartUnits(Source unitSource) {
- // Check every library.
- List<CompilationUnit> units = <CompilationUnit>[];
- List<Source> containingLibraries = getLibrariesContaining(unitSource);
- for (Source librarySource in containingLibraries) {
- LibrarySpecificUnit target =
- new LibrarySpecificUnit(librarySource, unitSource);
- CompilationUnit unit = getResult(target, RESOLVED_UNIT);
- if (unit == null) {
- units = null;
- break;
- }
- units.add(unit);
- }
- // If we have results, then we're done.
- if (units != null) {
- return units;
- }
- // Schedule computing of RESOLVED_UNIT results.
- for (Source librarySource in containingLibraries) {
- LibrarySpecificUnit target =
- new LibrarySpecificUnit(librarySource, unitSource);
- dartWorkManager.addPriorityResult(target, RESOLVED_UNIT);
- }
- return null;
+ throw UnimplementedError();
}
@override
bool exists(Source source) {
- if (source == null) {
- return false;
- }
- bool overriddenExists = _contentCache.getExists(source);
- if (overriddenExists != null) {
- return overriddenExists;
- }
- return source.exists();
+ throw UnimplementedError();
}
@override
CacheEntry getCacheEntry(AnalysisTarget target) {
- CacheEntry entry = _cache.get(target);
- if (entry == null) {
- entry = new CacheEntry(target);
- ImplicitAnalysisEvent event = null;
- if (target is Source) {
- entry.modificationTime = getModificationStamp(target);
- event = new ImplicitAnalysisEvent(target, true);
- }
- _cache.put(entry);
- if (event != null) {
- _implicitAnalysisEventsController.add(event);
- }
- }
- return entry;
+ throw UnimplementedError();
}
@override
CompilationUnitElement getCompilationUnitElement(
Source unitSource, Source librarySource) {
- AnalysisTarget target = new LibrarySpecificUnit(librarySource, unitSource);
- return getResult(target, COMPILATION_UNIT_ELEMENT);
+ throw UnimplementedError();
}
@deprecated
@override
- V getConfigurationData<V>(ResultDescriptor<V> key) =>
- (_configurationData[key] ?? key?.defaultValue) as V;
-
- @override
- TimestampedData<String> getContents(Source source) {
- String contents = _contentCache.getContents(source);
- if (contents != null) {
- return new TimestampedData<String>(
- _contentCache.getModificationStamp(source), contents);
- }
- return source.contents;
+ V getConfigurationData<V>(ResultDescriptor<V> key) {
+ throw UnimplementedError();
}
@override
- InternalAnalysisContext getContextFor(Source source) =>
- _cache.getContextFor(source) ?? this;
+ TimestampedData<String> getContents(Source source) {
+ throw UnimplementedError();
+ }
+
+ @override
+ InternalAnalysisContext getContextFor(Source source) {
+ throw UnimplementedError();
+ }
@override
Element getElement(ElementLocation location) {
- // TODO(brianwilkerson) This should not be a "get" method.
- try {
- List<String> components = location.components;
- Source source = _computeSourceFromEncoding(components[0]);
- String sourceName = source.shortName;
- if (AnalysisEngine.isDartFileName(sourceName)) {
- ElementImpl element = computeLibraryElement(source) as ElementImpl;
- for (int i = 1; i < components.length; i++) {
- if (element == null) {
- return null;
- }
- element = element.getChild(components[i]);
- }
- return element;
- }
- } catch (exception) {
- // If the location cannot be decoded for some reason then the underlying
- // cause should have been logged already and we can fall though to return
- // null.
- }
- return null;
+ throw UnimplementedError();
}
@override
AnalysisErrorInfo getErrors(Source source) {
- List<AnalysisError> allErrors = <AnalysisError>[];
- for (WorkManager workManager in workManagers) {
- List<AnalysisError> errors = workManager.getErrors(source);
- allErrors.addAll(errors);
- }
- LineInfo lineInfo = getLineInfo(source);
- return new AnalysisErrorInfoImpl(allErrors, lineInfo);
+ throw UnimplementedError();
}
@override
List<Source> getHtmlFilesReferencing(Source source) {
- return const <Source>[];
+ throw UnimplementedError();
}
@override
SourceKind getKindOf(Source source) {
- String name = source.shortName;
- if (AnalysisEngine.isDartFileName(name)) {
- return getResult(source, SOURCE_KIND);
- }
- return SourceKind.UNKNOWN;
+ throw UnimplementedError();
}
@override
List<Source> getLibrariesContaining(Source source) {
- SourceKind kind = getKindOf(source);
- if (kind == SourceKind.LIBRARY) {
- return <Source>[source];
- }
- return dartWorkManager.getLibrariesContainingPart(source);
+ throw UnimplementedError();
}
@override
List<Source> getLibrariesDependingOn(Source librarySource) {
- List<Source> dependentLibraries = <Source>[];
- for (Source source in _cache.sources) {
- CacheEntry entry = _cache.get(source);
- if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY) {
- if (_contains(entry.getValue(EXPORTED_LIBRARIES), librarySource)) {
- dependentLibraries.add(source);
- }
- if (_contains(entry.getValue(IMPORTED_LIBRARIES), librarySource)) {
- dependentLibraries.add(source);
- }
- }
- }
- if (dependentLibraries.isEmpty) {
- return const <Source>[];
- }
- return dependentLibraries;
+ throw UnimplementedError();
}
@override
List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
- return const <Source>[];
+ throw UnimplementedError();
}
@override
- LibraryElement getLibraryElement(Source source) =>
- getResult(source, LIBRARY_ELEMENT);
+ LibraryElement getLibraryElement(Source source) {
+ throw UnimplementedError();
+ }
@override
- LineInfo getLineInfo(Source source) => getResult(source, LINE_INFO);
+ LineInfo getLineInfo(Source source) {
+ throw UnimplementedError();
+ }
@override
int getModificationStamp(Source source) {
- int stamp = _contentCache.getModificationStamp(source);
- if (stamp != null) {
- return stamp;
- }
- return source.modificationStamp;
+ throw UnimplementedError();
}
@override
ChangeNoticeImpl getNotice(Source source) {
- ChangeNoticeImpl notice = _pendingNotices[source];
- if (notice == null) {
- notice = new ChangeNoticeImpl(source);
- _pendingNotices[source] = notice;
- }
- return notice;
+ throw UnimplementedError();
}
@override
@@ -913,87 +449,29 @@
@override
CompilationUnit getResolvedCompilationUnit(
Source unitSource, LibraryElement library) {
- if (library == null ||
- !AnalysisEngine.isDartFileName(unitSource.shortName)) {
- return null;
- }
- return getResolvedCompilationUnit2(unitSource, library.source);
+ throw UnimplementedError();
}
@override
CompilationUnit getResolvedCompilationUnit2(
Source unitSource, Source librarySource) {
- if (!AnalysisEngine.isDartFileName(unitSource.shortName) ||
- !AnalysisEngine.isDartFileName(librarySource.shortName)) {
- return null;
- }
- return getResult(
- new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT);
+ throw UnimplementedError();
}
@override
V getResult<V>(AnalysisTarget target, ResultDescriptor<V> result) {
- return _cache.getValue(target, result);
+ throw UnimplementedError();
}
@override
List<Source> getSourcesWithFullName(String path) {
- return analysisCache.getSourcesWithFullName(path);
+ throw UnimplementedError();
}
@override
bool handleContentsChanged(
Source source, String originalContents, String newContents, bool notify) {
- CacheEntry entry = _cache.get(source);
- if (entry == null) {
- return false;
- }
- // If there were no "originalContents" in the content cache,
- // use the contents of the file instead.
- if (originalContents == null) {
- try {
- TimestampedData<String> fileContents = source.contents;
- if (fileContents.modificationTime == entry.modificationTime) {
- originalContents = fileContents.data;
- }
- } catch (e) {}
- }
- bool changed = newContents != originalContents;
- if (newContents != null) {
- if (changed) {
- entry.modificationTime = _contentCache.getModificationStamp(source);
- // Don't compare with old contents because the cache has already been
- // updated, and we know at this point that it changed.
- _sourceChanged(source, compareWithOld: false);
- entry.setValue(CONTENT, newContents, const <TargetedResult>[]);
- } else {
- entry.modificationTime = _contentCache.getModificationStamp(source);
- }
- } else if (originalContents != null) {
- // We are removing the overlay for the file, check if the file's
- // contents is the same as it was in the overlay.
- try {
- TimestampedData<String> fileContents = getContents(source);
- newContents = fileContents.data;
- entry.modificationTime = fileContents.modificationTime;
- if (newContents == originalContents) {
- entry.setValue(CONTENT, newContents, const <TargetedResult>[]);
- changed = false;
- }
- } catch (e) {}
- // If not the same content (e.g. the file is being closed without save),
- // then force analysis.
- if (changed) {
- if (newContents == null) {
- _sourceChanged(source);
- }
- }
- }
- if (notify && changed) {
- _onSourcesChangedController
- .add(new SourcesChangedEvent.changedContent(source, newContents));
- }
- return changed;
+ throw UnimplementedError();
}
/**
@@ -1001,797 +479,97 @@
* to do.
*/
void invalidateCachedResults() {
- _cache?.dispose();
- _cache = createCacheFromSourceFactory(_sourceFactory);
- for (WorkManager workManager in workManagers) {
- workManager.onAnalysisOptionsChanged();
- }
+ throw UnimplementedError();
}
@override
void invalidateLibraryHints(Source librarySource) {
- List<Source> sources = getResult(librarySource, UNITS);
- if (sources != null) {
- for (Source source in sources) {
- getCacheEntry(source).setState(HINTS, CacheState.INVALID);
- }
- }
+ throw UnimplementedError();
}
@override
bool isClientLibrary(Source librarySource) {
- CacheEntry entry = _cache.get(librarySource);
- return entry != null &&
- _referencesDartHtml(librarySource) &&
- entry.getValue(IS_LAUNCHABLE);
+ throw UnimplementedError();
}
@override
bool isServerLibrary(Source librarySource) {
- CacheEntry entry = _cache.get(librarySource);
- return entry != null &&
- !_referencesDartHtml(librarySource) &&
- entry.getValue(IS_LAUNCHABLE);
+ throw UnimplementedError();
}
@override
Stream<ResultChangedEvent> onResultChanged(ResultDescriptor descriptor) {
- driver.onResultComputed(descriptor).listen((ResultChangedEvent event) {
- _resultChangedControllers[descriptor]?.add(event);
- });
- return _resultChangedControllers.putIfAbsent(descriptor, () {
- return new StreamController<ResultChangedEvent>.broadcast(sync: true);
- }).stream;
+ throw UnimplementedError();
}
@override
@deprecated
Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) {
- return onResultChanged(descriptor)
- .where((event) => event.wasComputed)
- .map((event) {
- return new ComputedResult(
- event.context, event.descriptor, event.target, event.value);
- });
+ throw UnimplementedError();
}
@override
CompilationUnit parseCompilationUnit(Source source) {
- if (!AnalysisEngine.isDartFileName(source.shortName)) {
- return null;
- }
- try {
- getContents(source);
- } catch (exception, stackTrace) {
- throw new AnalysisException('Could not get contents of $source',
- new CaughtException(exception, stackTrace));
- }
- return computeResult(source, PARSED_UNIT);
+ throw UnimplementedError();
}
@override
AnalysisResult performAnalysisTask() {
- return PerformanceStatistics.analysis.makeCurrentWhile(() {
- _evaluatePendingFutures();
- bool done = !driver.performAnalysisTask();
- List<ChangeNotice> notices = _getChangeNotices(done);
- if (notices != null) {
- int noticeCount = notices.length;
- for (int i = 0; i < noticeCount; i++) {
- ChangeNotice notice = notices[i];
- _notifyErrors(notice.source, notice.errors, notice.lineInfo);
- }
- }
- return new AnalysisResult(notices, -1, '', -1);
- });
+ throw UnimplementedError();
}
@override
void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
- elementMap.forEach((Source librarySource, LibraryElement library) {
- //
- // Cache the element in the library's info.
- //
- CacheEntry entry = getCacheEntry(librarySource);
- setValue(ResultDescriptor result, value) {
- entry.setValue(result, value, const <TargetedResult>[]);
- }
-
- setValue(BUILD_DIRECTIVES_ERRORS, AnalysisError.NO_ERRORS);
- setValue(BUILD_LIBRARY_ERRORS, AnalysisError.NO_ERRORS);
- // CLASS_ELEMENTS
- setValue(COMPILATION_UNIT_ELEMENT, library.definingCompilationUnit);
- // CONSTRUCTORS
- // CONSTRUCTORS_ERRORS
- entry.setState(CONTENT, CacheState.FLUSHED);
- setValue(EXPORTED_LIBRARIES, const <Source>[]);
- // EXPORT_SOURCE_CLOSURE
- setValue(IMPORTED_LIBRARIES, const <Source>[]);
- // IMPORT_SOURCE_CLOSURE
- setValue(INCLUDED_PARTS, const <Source>[]);
- setValue(IS_LAUNCHABLE, false);
- setValue(LIBRARY_ELEMENT, library);
- setValue(LIBRARY_ELEMENT1, library);
- setValue(LIBRARY_ELEMENT2, library);
- setValue(LIBRARY_ELEMENT3, library);
- setValue(LIBRARY_ELEMENT4, library);
- setValue(LIBRARY_ELEMENT5, library);
- setValue(LIBRARY_ELEMENT6, library);
- setValue(LIBRARY_ELEMENT7, library);
- setValue(LIBRARY_ELEMENT8, library);
- setValue(LIBRARY_ELEMENT9, library);
- setValue(LINE_INFO, new LineInfo(<int>[0]));
- setValue(PARSE_ERRORS, AnalysisError.NO_ERRORS);
- entry.setState(PARSED_UNIT, CacheState.FLUSHED);
- entry.setState(RESOLVE_TYPE_NAMES_ERRORS, CacheState.FLUSHED);
- entry.setState(RESOLVE_TYPE_BOUNDS_ERRORS, CacheState.FLUSHED);
- setValue(SCAN_ERRORS, AnalysisError.NO_ERRORS);
- setValue(SOURCE_KIND, SourceKind.LIBRARY);
- entry.setState(TOKEN_STREAM, CacheState.FLUSHED);
- setValue(UNITS, <Source>[librarySource]);
-
- LibrarySpecificUnit unit =
- new LibrarySpecificUnit(librarySource, librarySource);
- entry = getCacheEntry(unit);
- setValue(HINTS, AnalysisError.NO_ERRORS);
- setValue(LINTS, AnalysisError.NO_ERRORS);
- setValue(LIBRARY_UNIT_ERRORS, AnalysisError.NO_ERRORS);
- setValue(RESOLVE_DIRECTIVES_ERRORS, AnalysisError.NO_ERRORS);
- setValue(RESOLVE_TYPE_NAMES_ERRORS, AnalysisError.NO_ERRORS);
- setValue(RESOLVE_UNIT_ERRORS, AnalysisError.NO_ERRORS);
- entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT6, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT7, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT8, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT9, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT10, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT11, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT12, CacheState.FLUSHED);
- // USED_IMPORTED_ELEMENTS
- // USED_LOCAL_ELEMENTS
- setValue(STRONG_MODE_ERRORS, AnalysisError.NO_ERRORS);
- setValue(VARIABLE_REFERENCE_ERRORS, AnalysisError.NO_ERRORS);
- setValue(VERIFY_ERRORS, AnalysisError.NO_ERRORS);
- });
-
- CacheEntry entry = getCacheEntry(AnalysisContextTarget.request);
- entry.setValue(TYPE_PROVIDER, typeProvider, const <TargetedResult>[]);
+ throw UnimplementedError();
}
@override
void removeListener(AnalysisListener listener) {
- _listeners.remove(listener);
+ throw UnimplementedError();
}
@override
CompilationUnit resolveCompilationUnit(
Source unitSource, LibraryElement library) {
- if (library == null) {
- return null;
- }
- return resolveCompilationUnit2(unitSource, library.source);
+ throw UnimplementedError();
}
@override
CompilationUnit resolveCompilationUnit2(
Source unitSource, Source librarySource) {
- return computeResult(
- new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT);
+ throw UnimplementedError();
}
@override
void setChangedContents(Source source, String contents, int offset,
int oldLength, int newLength) {
- if (_contentRangeChanged(source, contents, offset, oldLength, newLength)) {
- _onSourcesChangedController.add(new SourcesChangedEvent.changedRange(
- source, contents, offset, oldLength, newLength));
- }
+ throw UnimplementedError();
}
@deprecated
@override
void setConfigurationData(ResultDescriptor key, Object data) {
- _configurationData[key] = data;
+ throw UnimplementedError();
}
@override
void setContents(Source source, String contents) {
- _contentsChanged(source, contents, true);
+ throw UnimplementedError();
}
@override
bool shouldErrorsBeAnalyzed(Source source) {
- CacheEntry entry = analysisCache.get(source);
- if (source.isInSystemLibrary) {
- return _options.generateSdkErrors;
- } else if (!entry.explicitlyAdded) {
- return _options.generateImplicitErrors;
- } else {
- return true;
- }
+ throw UnimplementedError();
}
@override
void test_flushAstStructures(Source source) {
- CacheEntry entry = getCacheEntry(source);
- entry.setState(PARSED_UNIT, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT6, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT7, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT8, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT9, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT10, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT11, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT12, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
+ throw UnimplementedError();
}
@override
void visitContentCache(ContentCacheVisitor visitor) {
- _contentCache.accept(visitor);
- }
-
- /**
- * Add all of the sources contained in the given source [container] to the
- * given list of [sources].
- */
- void _addSourcesInContainer(List<Source> sources, SourceContainer container) {
- for (Source source in _cache.sources) {
- if (container.contains(source)) {
- sources.add(source);
- }
- }
- }
-
- /**
- * Remove the given [pendingFuture] from [_pendingFutureTargets], since the
- * client has indicated its computation is not needed anymore.
- */
- void _cancelFuture(PendingFuture pendingFuture) {
- List<PendingFuture> pendingFutures =
- _pendingFutureTargets[pendingFuture.target];
- if (pendingFutures != null) {
- pendingFutures.remove(pendingFuture);
- if (pendingFutures.isEmpty) {
- _pendingFutureTargets.remove(pendingFuture.target);
- }
- }
- }
-
- /**
- * Given the encoded form of a source ([encoding]), use the source factory to
- * reconstitute the original source.
- */
- Source _computeSourceFromEncoding(String encoding) =>
- _sourceFactory.fromEncoding(encoding);
-
- /**
- * Return `true` if the given list of [sources] contains the given
- * [targetSource].
- */
- bool _contains(List<Source> sources, Source targetSource) {
- for (Source source in sources) {
- if (source == targetSource) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Set the contents of the given [source] to the given [contents] and mark the
- * source as having changed. The additional [offset], [oldLength] and
- * [newLength] information is used by the context to determine what reanalysis
- * is necessary. The method [setChangedContents] triggers a source changed
- * event where as this method does not.
- */
- bool _contentRangeChanged(Source source, String contents, int offset,
- int oldLength, int newLength) {
- bool changed = false;
- String originalContents = _contentCache.setContents(source, contents);
- if (contents != null) {
- if (contents != originalContents) {
- _sourceChanged(source);
- changed = true;
- CacheEntry entry = _cache.get(source);
- if (entry != null) {
- entry.modificationTime = _contentCache.getModificationStamp(source);
- entry.setValue(CONTENT, contents, const <TargetedResult>[]);
- }
- }
- } else if (originalContents != null) {
- _sourceChanged(source);
- changed = true;
- }
- return changed;
- }
-
- /**
- * Set the contents of the given [source] to the given [contents] and mark the
- * source as having changed. This has the effect of overriding the default
- * contents of the source. If the contents are `null` the override is removed
- * so that the default contents will be returned. If [notify] is true, a
- * source changed event is triggered.
- */
- void _contentsChanged(Source source, String contents, bool notify) {
- String originalContents = _contentCache.setContents(source, contents);
- handleContentsChanged(source, originalContents, contents, notify);
- }
-
- /**
- * Create a cache entry for the given [source]. The source was explicitly
- * added to this context if [explicitlyAdded] is `true`. Return the cache
- * entry that was created.
- */
- CacheEntry _createCacheEntry(Source source, bool explicitlyAdded) {
- CacheEntry entry = new CacheEntry(source);
- entry.modificationTime = getModificationStamp(source);
- entry.explicitlyAdded = explicitlyAdded;
- _cache.put(entry);
- if (!explicitlyAdded) {
- _implicitAnalysisEventsController
- .add(new ImplicitAnalysisEvent(source, true));
- }
- return entry;
- }
-
- /**
- * Return a list containing all of the cache entries for targets associated
- * with the given [source].
- */
- List<CacheEntry> _entriesFor(Source source) {
- List<CacheEntry> entries = <CacheEntry>[];
- MapIterator<AnalysisTarget, CacheEntry> iterator = _cache.iterator();
- while (iterator.moveNext()) {
- if (iterator.key.source == source) {
- entries.add(iterator.value);
- }
- }
- return entries;
- }
-
- void _evaluatePendingFutures() {
- for (AnalysisTarget target in _pendingFutureTargets.keys) {
- CacheEntry cacheEntry = _cache.get(target);
- List<PendingFuture> pendingFutures = _pendingFutureTargets[target];
- for (int i = 0; i < pendingFutures.length;) {
- if (cacheEntry == null) {
- pendingFutures[i].forciblyComplete();
- pendingFutures.removeAt(i);
- } else if (pendingFutures[i].evaluate(cacheEntry)) {
- pendingFutures.removeAt(i);
- } else {
- i++;
- }
- }
- }
- }
-
- /**
- * Return a list containing all of the change notices that are waiting to be
- * returned. If there are no notices, then return either `null` or an empty
- * list, depending on the value of [nullIfEmpty].
- */
- List<ChangeNotice> _getChangeNotices(bool nullIfEmpty) {
- if (_pendingNotices.isEmpty) {
- if (nullIfEmpty) {
- return null;
- }
- return const <ChangeNoticeImpl>[];
- }
- List<ChangeNotice> notices = new List.from(_pendingNotices.values);
- _pendingNotices.clear();
- return notices;
- }
-
- /**
- * Return a list containing all of the sources known to this context that have
- * the given [kind].
- */
- List<Source> _getSources(SourceKind kind) {
- List<Source> sources = <Source>[];
- if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) {
- for (Source source in _cache.sources) {
- CacheEntry entry = _cache.get(source);
- if (entry.getValue(SOURCE_KIND) == kind) {
- sources.add(source);
- }
- }
- }
- if (sources.isEmpty) {
- return const <Source>[];
- }
- return sources;
- }
-
- /**
- * Look at the given [source] to see whether a task needs to be performed
- * related to it. If so, add the source to the set of sources that need to be
- * processed. This method is intended to be used for testing purposes only.
- */
- void _getSourcesNeedingProcessing(
- Source source,
- CacheEntry entry,
- bool isPriority,
- bool hintsEnabled,
- bool lintsEnabled,
- HashSet<Source> sources) {
- CacheState state = entry.getState(CONTENT);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- state = entry.getState(SOURCE_KIND);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- SourceKind kind = entry.getValue(SOURCE_KIND);
- if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) {
- state = entry.getState(SCAN_ERRORS);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- state = entry.getState(PARSE_ERRORS);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
-// if (isPriority) {
-// if (!entry.hasResolvableCompilationUnit) {
-// sources.add(source);
-// return;
-// }
-// }
- for (Source librarySource in getLibrariesContaining(source)) {
- CacheEntry libraryEntry = _cache.get(librarySource);
- state = libraryEntry.getState(LIBRARY_ELEMENT);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- CacheEntry unitEntry =
- _cache.get(new LibrarySpecificUnit(librarySource, source));
- state = unitEntry.getState(RESOLVED_UNIT);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- if (shouldErrorsBeAnalyzed(source)) {
- state = unitEntry.getState(VERIFY_ERRORS);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- if (hintsEnabled) {
- state = unitEntry.getState(HINTS);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- }
- if (lintsEnabled) {
- state = unitEntry.getState(LINTS);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- }
- }
- }
-// } else if (kind == SourceKind.HTML) {
-// CacheState parsedUnitState = entry.getState(HtmlEntry.PARSED_UNIT);
-// if (parsedUnitState == CacheState.INVALID ||
-// (isPriority && parsedUnitState == CacheState.FLUSHED)) {
-// sources.add(source);
-// return;
-// }
-// CacheState resolvedUnitState =
-// entry.getState(HtmlEntry.RESOLVED_UNIT);
-// if (resolvedUnitState == CacheState.INVALID ||
-// (isPriority && resolvedUnitState == CacheState.FLUSHED)) {
-// sources.add(source);
-// return;
-// }
- }
- }
-
- /**
- * Log the given debugging [message].
- */
- void _logInformation(String message) {
- AnalysisEngine.instance.logger.logInformation(message);
- }
-
- /**
- * Notify all of the analysis listeners that the errors associated with the
- * given [source] has been updated to the given [errors].
- */
- void _notifyErrors(
- Source source, List<AnalysisError> errors, LineInfo lineInfo) {
- int count = _listeners.length;
- for (int i = 0; i < count; i++) {
- _listeners[i].computedErrors(this, source, errors, lineInfo);
- }
- }
-
- bool _referencesDartHtml(Source librarySource) {
- Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
- Set<Source> checkedSources = new Set<Source>();
- bool _refHtml(Source source) {
- if (!checkedSources.add(source)) {
- return false;
- }
- if (source == htmlSource) {
- return true;
- }
- LibraryElement library = _cache.getValue(source, LIBRARY_ELEMENT);
- if (library != null) {
- return library.importedLibraries.any((x) => _refHtml(x.source)) ||
- library.exportedLibraries.any((x) => _refHtml(x.source));
- }
- return false;
- }
-
- return _refHtml(librarySource);
- }
-
- void _removeFromCache(Source source) {
- CacheEntry entry = _cache.remove(source);
- if (entry != null && !entry.explicitlyAdded) {
- _implicitAnalysisEventsController
- .add(new ImplicitAnalysisEvent(source, false));
- }
- }
-
- /**
- * Remove the given [source] from the priority order if it is in the list.
- */
- void _removeFromPriorityOrder(Source source) {
- int count = _priorityOrder.length;
- List<Source> newOrder = <Source>[];
- for (int i = 0; i < count; i++) {
- if (_priorityOrder[i] != source) {
- newOrder.add(_priorityOrder[i]);
- }
- }
- if (newOrder.length < count) {
- analysisPriorityOrder = newOrder;
- }
- }
-
- /**
- * Create an entry for the newly added [source] and invalidate any sources
- * that referenced the source before it existed.
- */
- void _sourceAvailable(Source source) {
- driver.reset();
- // TODO(brianwilkerson) This method needs to check whether the source was
- // previously being implicitly analyzed. If so, the cache entry needs to be
- // update to reflect the new status and an event needs to be generated to
- // inform clients that it is no longer being implicitly analyzed.
- CacheEntry entry = _cache.get(source);
- if (entry == null) {
- _createCacheEntry(source, true);
- } else {
- entry.explicitlyAdded = true;
- entry.modificationTime = getModificationStamp(source);
- entry.setState(CONTENT, CacheState.INVALID);
- entry.setState(MODIFICATION_TIME, CacheState.INVALID);
- }
- }
-
- /**
- * Invalidate the [source] that was changed and any sources that referenced
- * the source before it existed.
- *
- * Note: source may be considered "changed" if it was previously missing,
- * but pointed to by an import or export directive.
- */
- void _sourceChanged(Source source, {bool compareWithOld: true}) {
- CacheEntry entry = _cache.get(source);
- // If the source has no cache entry, there is nothing to invalidate.
- if (entry == null) {
- return;
- }
-
- String oldContents = compareWithOld ? entry.getValue(CONTENT) : null;
-
- // Flush so that from now on we will get new contents.
- // (For example, in getLibrariesContaining.)
- entry.setState(CONTENT, CacheState.FLUSHED);
-
- // Prepare the new contents.
- TimestampedData<String> fileContents;
- try {
- fileContents = getContents(source);
- } catch (e) {}
-
- // Update 'modificationTime' - we are going to update the entry.
- {
- int time = fileContents?.modificationTime ?? -1;
- for (CacheEntry entry in _entriesFor(source)) {
- entry.modificationTime = time;
- }
- }
-
- // Fast path if the contents is the same as it was last time.
- if (oldContents != null && fileContents?.data == oldContents) {
- return;
- }
-
- // We're going to update the cache, so reset the driver.
- driver.reset();
-
- // We need to invalidate the cache.
- {
- entry.setState(CONTENT, CacheState.INVALID);
- entry.setState(MODIFICATION_TIME, CacheState.INVALID);
- entry.setState(SOURCE_KIND, CacheState.INVALID);
- }
- for (WorkManager workManager in workManagers) {
- workManager
- .applyChange(const <Source>[], <Source>[source], const <Source>[]);
- }
- }
-
- /**
- * Record that the given [source] has been removed.
- */
- void _sourceRemoved(Source source) {
- driver.reset();
- _removeFromCache(source);
- _removeFromPriorityOrder(source);
- }
-}
-
-/**
- * A helper class used to create futures for [AnalysisContextImpl].
- * Using a helper class allows us to preserve the generic parameter T.
- */
-class AnalysisFutureHelper<T> {
- final AnalysisContextImpl _context;
- final AnalysisTarget _target;
- final ResultDescriptor<T> _descriptor;
-
- AnalysisFutureHelper(this._context, this._target, this._descriptor);
-
- /**
- * Return a future that will be completed with the result specified
- * in the constructor. If the result is cached, the future will be
- * completed immediately with the resulting value. If not, then
- * analysis is scheduled that will produce the required result.
- * If the result cannot be generated, then the future will be completed with
- * the error AnalysisNotScheduledError.
- */
- CancelableFuture<T> computeAsync() {
- if (_context.isDisposed) {
- // No further analysis is expected, so return a future that completes
- // immediately with AnalysisNotScheduledError.
- return new CancelableFuture.error(new AnalysisNotScheduledError());
- }
- CacheEntry entry = _context.getCacheEntry(_target);
- PendingFuture<T> pendingFuture =
- new PendingFuture<T>(_context, _target, (CacheEntry entry) {
- CacheState state = entry.getState(_descriptor);
- if (state == CacheState.ERROR) {
- throw entry.exception;
- } else if (state == CacheState.INVALID) {
- return null;
- }
- return entry.getValue(_descriptor);
- });
- if (!pendingFuture.evaluate(entry)) {
- _context._pendingFutureTargets
- .putIfAbsent(_target, () => <PendingFuture>[])
- .add(pendingFuture);
- _context.dartWorkManager.addPriorityResult(_target, _descriptor);
- }
- return pendingFuture.future;
- }
-}
-
-class CacheConsistencyValidatorImpl implements CacheConsistencyValidator {
- final AnalysisContextImpl context;
-
- CacheConsistencyValidatorImpl(this.context);
-
- @override
- List<Source> getSourcesToComputeModificationTimes() {
- return context._privatePartition.sources.toList();
- }
-
- @override
- bool sourceModificationTimesComputed(List<Source> sources, List<int> times) {
- Stopwatch timer = new Stopwatch()..start();
- HashSet<Source> changedSources = new HashSet<Source>();
- HashSet<Source> removedSources = new HashSet<Source>();
- for (int i = 0; i < sources.length; i++) {
- Source source = sources[i];
- // When a source is in the content cache,
- // its modification time in the file system does not matter.
- if (context._contentCache.getModificationStamp(source) != null) {
- continue;
- }
- // When we were not able to compute the modification time in the
- // file system, there is nothing to compare with, so skip the source.
- int sourceTime = times[i];
- if (sourceTime == null) {
- continue;
- }
- // Compare with the modification time in the cache entry.
- CacheEntry entry = context._privatePartition.get(source);
- if (entry != null) {
- if (entry.modificationTime != sourceTime) {
- if (sourceTime == -1) {
- removedSources.add(source);
- PerformanceStatistics
- .cacheConsistencyValidationStatistics.numOfRemoved++;
- } else {
- changedSources.add(source);
- PerformanceStatistics
- .cacheConsistencyValidationStatistics.numOfChanged++;
- }
- }
- }
- }
- for (Source source in changedSources) {
- context._sourceChanged(source);
- }
- for (Source source in removedSources) {
- context._sourceRemoved(source);
- }
- if (changedSources.length > 0 || removedSources.length > 0) {
- StringBuffer buffer = new StringBuffer();
- buffer.write("Consistency check took ");
- buffer.write(timer.elapsedMilliseconds);
- buffer.writeln(" ms and found");
- buffer.write(" ");
- buffer.write(changedSources.length);
- buffer.writeln(" changed sources");
- buffer.write(" ");
- buffer.write(removedSources.length);
- buffer.write(" removed sources.");
- context._logInformation(buffer.toString());
- }
- return changedSources.isNotEmpty || removedSources.isNotEmpty;
+ throw UnimplementedError();
}
}
@@ -1801,117 +579,16 @@
*/
class PartitionManager {
/**
- * A table mapping SDK's to the partitions used for those SDK's.
- */
- Map<DartSdk, SdkCachePartition> _sdkPartitions =
- new HashMap<DartSdk, SdkCachePartition>();
-
- /**
* Clear any cached data being maintained by this manager.
*/
- void clearCache() {
- _sdkPartitions.clear();
- }
+ void clearCache() {}
/**
* Return the partition being used for the given [sdk], creating the partition
* if necessary.
*/
SdkCachePartition forSdk(DartSdk sdk) {
- // Call sdk.context now, because when it creates a new
- // InternalAnalysisContext instance, it calls forSdk() again, so creates an
- // SdkCachePartition instance.
- // So, if we initialize context after "partition == null", we end up
- // with two SdkCachePartition instances.
- InternalAnalysisContext sdkContext = sdk.context;
- // Check cache for an existing partition.
- SdkCachePartition partition = _sdkPartitions[sdk];
- if (partition == null) {
- partition = new SdkCachePartition(sdkContext);
- _sdkPartitions[sdk] = partition;
- }
- return partition;
- }
-}
-
-/**
- * Representation of a pending computation which is based on the results of
- * analysis that may or may not have been completed.
- */
-class PendingFuture<T> {
- /**
- * The context in which this computation runs.
- */
- final AnalysisContextImpl _context;
-
- /**
- * The target used by this computation to compute its value.
- */
- final AnalysisTarget target;
-
- /**
- * The function which implements the computation.
- */
- final PendingFutureComputer<T> _computeValue;
-
- /**
- * The completer that should be completed once the computation has succeeded.
- */
- CancelableCompleter<T> _completer;
-
- PendingFuture(this._context, this.target, this._computeValue) {
- _completer = new CancelableCompleter<T>(_onCancel);
- }
-
- /**
- * Retrieve the future which will be completed when this object is
- * successfully evaluated.
- */
- CancelableFuture<T> get future => _completer.future;
-
- /**
- * Execute [_computeValue], passing it the given [entry], and complete
- * the pending future if it's appropriate to do so. If the pending future is
- * completed by this call, true is returned; otherwise false is returned.
- *
- * Once this function has returned true, it should not be called again.
- *
- * Other than completing the future, this method is free of side effects.
- * Note that any code the client has attached to the future will be executed
- * in a microtask, so there is no danger of side effects occurring due to
- * client callbacks.
- */
- bool evaluate(CacheEntry entry) {
- assert(!_completer.isCompleted);
- try {
- T result = _computeValue(entry);
- if (result == null) {
- return false;
- } else {
- _completer.complete(result);
- return true;
- }
- } catch (exception, stackTrace) {
- _completer.completeError(exception, stackTrace);
- return true;
- }
- }
-
- /**
- * No further analysis updates are expected which affect this future, so
- * complete it with an AnalysisNotScheduledError in order to avoid
- * deadlocking the client.
- */
- void forciblyComplete() {
- try {
- throw new AnalysisNotScheduledError();
- } catch (exception, stackTrace) {
- _completer.completeError(exception, stackTrace);
- }
- }
-
- void _onCancel() {
- _context._cancelFuture(this);
+ throw UnimplementedError();
}
}
@@ -1955,15 +632,6 @@
@override
AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
- if (factory == null) {
- return super.createCacheFromSourceFactory(factory);
- }
- DartSdk sdk = factory.dartSdk;
- if (sdk == null) {
- throw new ArgumentError(
- "The source factory for an SDK analysis context must have a DartUriResolver");
- }
- return new AnalysisCache(
- <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]);
+ throw UnimplementedError();
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 418b2ff..7a4b3d0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
@@ -14,6 +14,7 @@
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/compute.dart';
import 'package:analyzer/src/dart/constant/constant_verifier.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/handle.dart';
@@ -27,10 +28,10 @@
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/hint/sdk_constraint_verifier.dart';
+import 'package:analyzer/src/ignore_comments/ignore_info.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/linter_visitor.dart';
import 'package:analyzer/src/services/lint.dart';
-import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/src/task/strong/checker.dart';
import 'package:pub_semver/pub_semver.dart';
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 44f61a4..2b3f303 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/element/element.dart'
show CompilationUnitElement, LibraryElement;
-import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -43,7 +42,7 @@
/// We use it as an approximation for the heap size of elements.
int _linkedDataInBytes = 0;
- AnalysisContextImpl analysisContext;
+ RestrictedAnalysisContext analysisContext;
SummaryResynthesizer resynthesizer;
InheritanceManager2 inheritanceManager;
@@ -63,18 +62,19 @@
store.addStore(externalSummaries);
}
- // Fill the store with summaries required for the initial library.
- load(targetLibrary);
-
analysisContext = new RestrictedAnalysisContext(
analysisOptions,
declaredVariables,
sourceFactory,
);
- var provider = new InputPackagesResultProvider(analysisContext, store,
- session: session);
- resynthesizer = provider.resynthesizer;
+ // Fill the store with summaries required for the initial library.
+ load(targetLibrary);
+
+ resynthesizer = new StoreBasedSummaryResynthesizer(
+ analysisContext, session, sourceFactory, true, store);
+ analysisContext.typeProvider = resynthesizer.typeProvider;
+ resynthesizer.finishCoreAsyncLibraries();
inheritanceManager = new InheritanceManager2(analysisContext.typeSystem);
}
@@ -173,7 +173,7 @@
}, (String uri) {
UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri];
return unlinkedUnit;
- }, (_) => null);
+ }, DeclaredVariables(), analysisContext.analysisOptions);
logger.writeln('Linked ${linkedLibraries.length} libraries.');
});
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 5144eeb..8dfa18b 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3042,6 +3042,9 @@
}
@override
+ ParameterElement get declaredElement => _parameter.declaredElement;
+
+ @override
Token get beginToken => _parameter.beginToken;
@override
@@ -8990,6 +8993,19 @@
/// whether the kind has not or cannot be determined.
_SetOrMapKind _resolvedKind;
+ /// The context type computed by
+ /// [ResolverVisitor._computeSetOrMapContextType].
+ ///
+ /// Note that this is not the same as the context pushed down by type
+ /// inference (which can be obtained via [InferenceContext.getContext]). For
+ /// example, in the following code:
+ ///
+ /// var m = {};
+ ///
+ /// The context pushed down by type inference is null, whereas the
+ /// `contextType` is `Map<dynamic, dynamic>`.
+ InterfaceType contextType;
+
/// Initialize a newly created set or map literal. The [constKeyword] can be
/// `null` if the literal is not a constant. The [typeArguments] can be `null`
/// if no type arguments were declared. The [elements] can be `null` if the
diff --git a/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
index b6b9169..a919a7f 100644
--- a/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
+++ b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
@@ -344,29 +344,26 @@
@override
Object visitSetOrMapLiteral(SetOrMapLiteral node) {
- if (node.isMap) {
- Map<String, Object> map = new HashMap<String, Object>();
- for (CollectionElement element in node.elements2) {
- if (element is MapLiteralEntry) {
- Object key = element.key.accept(this);
- Object value = element.value.accept(this);
- if (key is String && !identical(value, NOT_A_CONSTANT)) {
- map[key] = value;
- } else {
- return NOT_A_CONSTANT;
- }
+ // There are a lot of constants that this class does not support, so we
+ // didn't add support for set literals. As a result, this assumes that we're
+ // looking at a map literal until we prove otherwise.
+ Map<String, Object> map = new HashMap<String, Object>();
+ for (CollectionElement element in node.elements2) {
+ if (element is MapLiteralEntry) {
+ Object key = element.key.accept(this);
+ Object value = element.value.accept(this);
+ if (key is String && !identical(value, NOT_A_CONSTANT)) {
+ map[key] = value;
} else {
- // There are a lot of constants that this class does not support, so
- // we didn't add support for the extended collection support.
return NOT_A_CONSTANT;
}
+ } else {
+ // There are a lot of constants that this class does not support, so
+ // we didn't add support for the extended collection support.
+ return NOT_A_CONSTANT;
}
- return map;
- } else if (node.isSet) {
- // There are a lot of constants that this class does not support, so
- // we didn't add support for set literals.
}
- return NOT_A_CONSTANT;
+ return map;
}
@override
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 9588569..cb913fe 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -903,13 +903,20 @@
}
@override
- SetOrMapLiteral visitSetOrMapLiteral(SetOrMapLiteral node) =>
- astFactory.setOrMapLiteral(
- constKeyword: cloneToken(node.constKeyword),
- typeArguments: cloneNode(node.typeArguments),
- leftBracket: cloneToken(node.leftBracket),
- elements: cloneNodeList(node.elements2),
- rightBracket: cloneToken(node.rightBracket));
+ SetOrMapLiteral visitSetOrMapLiteral(SetOrMapLiteral node) {
+ var result = astFactory.setOrMapLiteral(
+ constKeyword: cloneToken(node.constKeyword),
+ typeArguments: cloneNode(node.typeArguments),
+ leftBracket: cloneToken(node.leftBracket),
+ elements: cloneNodeList(node.elements2),
+ rightBracket: cloneToken(node.rightBracket));
+ if (node.isMap) {
+ (result as SetOrMapLiteralImpl).becomeMap();
+ } else if (node.isSet) {
+ (result as SetOrMapLiteralImpl).becomeSet();
+ }
+ return result;
+ }
@override
ShowCombinator visitShowCombinator(ShowCombinator node) => astFactory
diff --git a/pkg/analyzer/lib/src/dart/constant/compute.dart b/pkg/analyzer/lib/src/dart/constant/compute.dart
index 4031e2f..712d4b6 100644
--- a/pkg/analyzer/lib/src/dart/constant/compute.dart
+++ b/pkg/analyzer/lib/src/dart/constant/compute.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2018, 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.
@@ -10,7 +10,6 @@
show TypeProvider, TypeSystem;
import 'package:analyzer/src/summary/link.dart' as graph
show DependencyWalker, Node;
-import 'package:analyzer/src/task/dart.dart';
/// Compute values of the given [constants] with correct ordering.
void computeConstants(
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 3373f64..a8459c1 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -2,10 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'dart:collection';
-
import 'package:analyzer/dart/analysis/declared_variables.dart';
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/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -14,6 +13,7 @@
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
+import 'package:analyzer/src/dart/constant/potentially_constant.dart';
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/error/codes.dart';
@@ -143,20 +143,17 @@
void visitListLiteral(ListLiteral node) {
super.visitListLiteral(node);
if (node.isConst) {
- // Dummy sets of keys to accommodate the fact that
- // `_validateCollectionElement` handles map literals.
- HashSet<DartObject> keys = new HashSet<DartObject>();
- List<Expression> invalidKeys = new List<Expression>();
+ InterfaceType nodeType = node.staticType;
+ DartType elementType = nodeType.typeArguments[0];
+ var verifier = _ConstLiteralVerifier(
+ this,
+ isConst: true,
+ errorCode: CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT,
+ forList: true,
+ listElementType: elementType,
+ );
for (CollectionElement element in node.elements2) {
- bool isValid = _validateCollectionElement(element, true, keys,
- invalidKeys, CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT);
- if (isValid && element is Expression) {
- // TODO(brianwilkerson) Handle the other kinds of elements.
- _reportErrorIfFromDeferredLibrary(
- element,
- CompileTimeErrorCode
- .NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY);
- }
+ verifier.verify(element);
}
}
}
@@ -171,69 +168,55 @@
void visitSetOrMapLiteral(SetOrMapLiteral node) {
super.visitSetOrMapLiteral(node);
bool isConst = node.isConst;
- HashSet<DartObject> keys = new HashSet<DartObject>();
- List<Expression> invalidKeys = new List<Expression>();
if (node.isSet) {
- HashSet<DartObject> elements = new HashSet<DartObject>();
- List<Expression> invalidElements = new List<Expression>();
if (isConst) {
+ InterfaceType nodeType = node.staticType;
+ var elementType = nodeType.typeArguments[0];
+ var duplicateElements = <Expression>[];
+ var verifier = _ConstLiteralVerifier(
+ this,
+ isConst: isConst,
+ errorCode: CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT,
+ forSet: true,
+ setElementType: elementType,
+ setUniqueValues: Set<DartObject>(),
+ setDuplicateElements: duplicateElements,
+ );
for (CollectionElement element in node.elements2) {
- if (element is Expression) {
- // TODO(mfairhurst): unify this with _validateCollectionElemet
- DartObject result = _validate(
- element, CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT);
- if (result != null) {
- _reportErrorIfFromDeferredLibrary(
- element,
- CompileTimeErrorCode
- .NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY);
- if (!elements.add(result)) {
- invalidElements.add(element);
- }
- DartType type = result.type;
- if (_implementsEqualsWhenNotAllowed(type)) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode
- .CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
- element,
- [type.displayName]);
- }
- }
- } else {
- bool isValid = _validateCollectionElement(element, isConst, keys,
- invalidKeys, CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT);
- if (isValid) {
- // TODO(mfairhurst) report deferred library error
- }
- }
+ verifier.verify(element);
}
- for (var invalidElement in invalidElements) {
+ for (var duplicateElement in duplicateElements) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.EQUAL_VALUES_IN_CONST_SET, invalidElement);
+ StaticWarningCode.EQUAL_VALUES_IN_CONST_SET,
+ duplicateElement,
+ );
}
}
} else if (node.isMap) {
+ InterfaceType nodeType = node.staticType;
+ var keyType = nodeType.typeArguments[0];
+ var valueType = nodeType.typeArguments[1];
bool reportEqualKeys = true;
+ var duplicateKeyElements = <Expression>[];
+ var verifier = _ConstLiteralVerifier(
+ this,
+ isConst: isConst,
+ errorCode: CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT,
+ forMap: true,
+ mapKeyType: keyType,
+ mapValueType: valueType,
+ mapUniqueKeys: Set<DartObject>(),
+ mapDuplicateKeyElements: duplicateKeyElements,
+ );
for (CollectionElement entry in node.elements2) {
- if (entry is MapLiteralEntry) {
- // TODO(mfairhurst): Change non-const error to a hint, and report
- // duplicates in constant evaluator instead.
- // TODO(mfairhurst): unify this with _validateCollectionElemet
- if (!_validateMapLiteralEntry(entry, isConst, keys, invalidKeys)) {
- reportEqualKeys = false;
- }
- } else {
- bool isValid = _validateCollectionElement(entry, isConst, keys,
- invalidKeys, CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT);
- if (isValid) {
- // TODO(mfarihurst): handle deferred library checks
- }
- }
+ verifier.verify(entry);
}
if (reportEqualKeys) {
- for (int i = 0; i < invalidKeys.length; i++) {
+ for (var duplicateKeyElement in duplicateKeyElements) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.EQUAL_KEYS_IN_MAP, invalidKeys[i]);
+ StaticWarningCode.EQUAL_KEYS_IN_MAP,
+ duplicateKeyElement,
+ );
}
}
}
@@ -452,38 +435,6 @@
return result;
}
- bool _validateCollectionElement(
- CollectionElement element,
- bool isConst,
- HashSet<DartObject> keys,
- List<Expression> invalidKeys,
- ErrorCode errorCode) {
- if (element is Expression) {
- return !isConst || _validate(element, errorCode) != null;
- } else if (element is ForElement) {
- if (isConst) {
- _errorReporter.reportErrorForNode(errorCode, element);
- return false;
- }
- return true;
- } else if (element is IfElement) {
- bool validCondition =
- !isConst || _validate(element.condition, errorCode) != null;
- return validCondition &&
- _validateCollectionElement(
- element.thenElement, isConst, keys, invalidKeys, errorCode) !=
- null &&
- _validateCollectionElement(
- element.elseElement, isConst, keys, invalidKeys, errorCode) !=
- null;
- } else if (element is MapLiteralEntry) {
- return _validateMapLiteralEntry(element, isConst, keys, invalidKeys);
- } else if (element is SpreadElement) {
- return !isConst || _validate(element.expression, errorCode) != null;
- }
- return null;
- }
-
/// Validate that if the passed arguments are constant expressions.
///
/// @param argumentList the argument list to evaluate
@@ -632,52 +583,6 @@
_validateInitializerExpression(parameterElements, argument);
}
}
-
- bool _validateMapLiteralEntry(MapLiteralEntry entry, bool isConst,
- HashSet<DartObject> keys, List<Expression> invalidKeys) {
- Expression key = entry.key;
- if (isConst) {
- DartObjectImpl keyResult =
- _validate(key, CompileTimeErrorCode.NON_CONSTANT_MAP_KEY);
- Expression valueExpression = entry.value;
- DartObjectImpl valueResult = _validate(
- valueExpression, CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE);
- if (valueResult != null) {
- _reportErrorIfFromDeferredLibrary(valueExpression,
- CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY);
- }
- if (keyResult != null) {
- _reportErrorIfFromDeferredLibrary(key,
- CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY);
- if (!keys.add(keyResult)) {
- invalidKeys.add(key);
- }
- DartType type = keyResult.type;
- if (_implementsEqualsWhenNotAllowed(type)) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode
- .CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
- key,
- [type.displayName]);
- }
- }
- } else {
- // Note: we throw the errors away because this isn't actually a const.
- AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
- ErrorReporter subErrorReporter =
- new ErrorReporter(errorListener, _errorReporter.source);
- DartObjectImpl result =
- key.accept(new ConstantVisitor(_evaluationEngine, subErrorReporter));
- if (result != null) {
- if (!keys.add(result)) {
- invalidKeys.add(key);
- }
- } else {
- return false;
- }
- }
- return true;
- }
}
class _ConstantVerifier_validateInitializerExpression extends ConstantVisitor {
@@ -739,3 +644,327 @@
return super.visitSimpleIdentifier(node);
}
}
+
+class _ConstLiteralVerifier {
+ final ConstantVerifier verifier;
+ final bool isConst;
+ final Set<DartObject> mapUniqueKeys;
+ final List<Expression> mapDuplicateKeyElements;
+ final ErrorCode errorCode;
+ final DartType listElementType;
+ final DartType mapKeyType;
+ final DartType mapValueType;
+ final DartType setElementType;
+ final Set<DartObject> setUniqueValues;
+ final List<CollectionElement> setDuplicateElements;
+ final bool forList;
+ final bool forMap;
+ final bool forSet;
+
+ _ConstLiteralVerifier(
+ this.verifier, {
+ this.isConst,
+ this.mapUniqueKeys,
+ this.mapDuplicateKeyElements,
+ this.errorCode,
+ this.listElementType,
+ this.mapKeyType,
+ this.mapValueType,
+ this.setElementType,
+ this.setUniqueValues,
+ this.setDuplicateElements,
+ this.forList = false,
+ this.forMap = false,
+ this.forSet = false,
+ });
+
+ bool verify(CollectionElement element) {
+ if (element is Expression) {
+ if (!isConst) return true;
+
+ var value = verifier._validate(element, errorCode);
+ if (value == null) return false;
+
+ if (forList) {
+ return _validateListExpression(element, value);
+ }
+
+ if (forSet) {
+ return _validateSetExpression(element, value);
+ }
+
+ return true;
+ } else if (element is ForElement) {
+ if (!isConst) return true;
+
+ verifier._errorReporter.reportErrorForNode(errorCode, element);
+ return false;
+ } else if (element is IfElement) {
+ if (!isConst) return true;
+
+ var conditionValue = verifier._validate(element.condition, errorCode);
+ var conditionBool = conditionValue?.toBoolValue();
+
+ // The errors have already been reported.
+ if (conditionBool == null) return false;
+
+ var thenValid = true;
+ var elseValid = true;
+ if (conditionBool) {
+ thenValid = verify(element.thenElement);
+ if (element.elseElement != null) {
+ elseValid = _reportNotPotentialConstants(element.elseElement);
+ }
+ } else {
+ thenValid = _reportNotPotentialConstants(element.thenElement);
+ if (element.elseElement != null) {
+ elseValid = verify(element.elseElement);
+ }
+ }
+
+ return thenValid && elseValid;
+ } else if (element is MapLiteralEntry) {
+ return _validateMapLiteralEntry(element);
+ } else if (element is SpreadElement) {
+ if (!isConst) return true;
+
+ var value = verifier._validate(element.expression, errorCode);
+ if (value == null) return false;
+
+ if (forList || forSet) {
+ return _validateListOrSetSpread(element, value);
+ }
+
+ if (forMap) {
+ return _validateMapSpread(element, value);
+ }
+
+ return true;
+ }
+ throw new UnsupportedError(
+ 'Unhandled type of collection element: ${element.runtimeType}',
+ );
+ }
+
+ /// Return `true` if the [node] is a potential constant.
+ bool _reportNotPotentialConstants(AstNode node) {
+ var notPotentiallyConstants = getNotPotentiallyConstants(node);
+ if (notPotentiallyConstants.isEmpty) return true;
+
+ for (var notConst in notPotentiallyConstants) {
+ CompileTimeErrorCode errorCode;
+ if (forList) {
+ errorCode = CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT;
+ } else if (forMap) {
+ errorCode = CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT;
+ for (var parent = notConst; parent != null; parent = parent.parent) {
+ if (parent is MapLiteralEntry) {
+ if (parent.key == notConst) {
+ errorCode = CompileTimeErrorCode.NON_CONSTANT_MAP_KEY;
+ } else {
+ errorCode = CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE;
+ }
+ break;
+ }
+ }
+ } else if (forSet) {
+ errorCode = CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT;
+ }
+ verifier._errorReporter.reportErrorForNode(errorCode, notConst);
+ }
+
+ return false;
+ }
+
+ bool _validateListExpression(Expression expression, DartObjectImpl value) {
+ if (!verifier._evaluationEngine.runtimeTypeMatch(value, listElementType)) {
+ verifier._errorReporter.reportErrorForNode(
+ StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
+ expression,
+ [value.type, listElementType],
+ );
+ return false;
+ }
+
+ verifier._reportErrorIfFromDeferredLibrary(
+ expression,
+ CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
+ );
+
+ return true;
+ }
+
+ bool _validateListOrSetSpread(SpreadElement element, DartObjectImpl value) {
+ var listValue = value.toListValue();
+ var setValue = value.toSetValue();
+
+ if (listValue == null && setValue == null) {
+ if (value.isNull && _isNullableSpread(element)) {
+ return true;
+ }
+ verifier._errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+ element.expression,
+ );
+ return false;
+ }
+
+ if (listValue != null) {
+ var elementType = value.type.typeArguments[0];
+ if (verifier._implementsEqualsWhenNotAllowed(elementType)) {
+ verifier._errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+ element,
+ [elementType],
+ );
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool _validateMapLiteralEntry(MapLiteralEntry entry) {
+ if (!forMap) return false;
+
+ var keyExpression = entry.key;
+ var valueExpression = entry.value;
+
+ if (isConst) {
+ var keyValue = verifier._validate(
+ keyExpression,
+ CompileTimeErrorCode.NON_CONSTANT_MAP_KEY,
+ );
+ var valueValue = verifier._validate(
+ valueExpression,
+ CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE,
+ );
+
+ if (keyValue != null) {
+ var keyType = keyValue.type;
+
+ if (!verifier._evaluationEngine
+ .runtimeTypeMatch(keyValue, mapKeyType)) {
+ verifier._errorReporter.reportErrorForNode(
+ StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+ keyExpression,
+ [keyType, mapKeyType],
+ );
+ }
+
+ if (verifier._implementsEqualsWhenNotAllowed(keyType)) {
+ verifier._errorReporter.reportErrorForNode(
+ CompileTimeErrorCode
+ .CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+ keyExpression,
+ [keyType],
+ );
+ }
+
+ verifier._reportErrorIfFromDeferredLibrary(
+ keyExpression,
+ CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY,
+ );
+
+ if (!mapUniqueKeys.add(keyValue)) {
+ mapDuplicateKeyElements.add(keyExpression);
+ }
+ }
+
+ if (valueValue != null) {
+ if (!verifier._evaluationEngine
+ .runtimeTypeMatch(valueValue, mapValueType)) {
+ verifier._errorReporter.reportErrorForNode(
+ StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
+ valueExpression,
+ [valueValue.type, mapValueType],
+ );
+ }
+
+ verifier._reportErrorIfFromDeferredLibrary(
+ valueExpression,
+ CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
+ );
+ }
+ } else {
+ // Note: we throw the errors away because this isn't actually a const.
+ var nullErrorReporter = new ErrorReporter(
+ AnalysisErrorListener.NULL_LISTENER,
+ verifier._errorReporter.source,
+ );
+ var keyValue = keyExpression.accept(
+ new ConstantVisitor(verifier._evaluationEngine, nullErrorReporter),
+ );
+
+ if (keyValue != null) {
+ if (!mapUniqueKeys.add(keyValue)) {
+ mapDuplicateKeyElements.add(keyExpression);
+ }
+ }
+ }
+ return true;
+ }
+
+ bool _validateMapSpread(SpreadElement element, DartObjectImpl value) {
+ if (value.isNull && _isNullableSpread(element)) {
+ return true;
+ }
+ Map<DartObject, DartObject> map = value.toMapValue();
+ if (map != null) {
+ // TODO(brianwilkerson) Figure out how to improve the error messages. They
+ // currently point to the whole spread expression, but the key and/or
+ // value being referenced might not be located there (if it's referenced
+ // through a const variable).
+ for (var entry in map.entries) {
+ DartObjectImpl keyValue = entry.key;
+ if (keyValue != null) {
+ if (!mapUniqueKeys.add(keyValue)) {
+ mapDuplicateKeyElements.add(element.expression);
+ }
+ }
+ }
+ return true;
+ }
+ verifier._errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP,
+ element.expression,
+ );
+ return false;
+ }
+
+ bool _validateSetExpression(Expression expression, DartObjectImpl value) {
+ if (!verifier._evaluationEngine.runtimeTypeMatch(value, setElementType)) {
+ verifier._errorReporter.reportErrorForNode(
+ StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
+ expression,
+ [value.type, setElementType],
+ );
+ return false;
+ }
+
+ if (verifier._implementsEqualsWhenNotAllowed(value.type)) {
+ verifier._errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+ expression,
+ [value.type],
+ );
+ return false;
+ }
+
+ verifier._reportErrorIfFromDeferredLibrary(
+ expression,
+ CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY,
+ );
+
+ if (!setUniqueValues.add(value)) {
+ setDuplicateElements.add(expression);
+ }
+
+ return true;
+ }
+
+ static bool _isNullableSpread(SpreadElement element) {
+ return element.spreadOperator.type ==
+ TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 390eea8..c4416ee 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -26,7 +26,7 @@
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/type_system.dart'
show Dart2TypeSystem, TypeSystem;
-import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/src/task/api/model.dart';
/**
* Helper class encapsulating the methods for evaluating constants and
@@ -930,6 +930,23 @@
}
/**
+ * Interface for [AnalysisTarget]s for which constant evaluation can be
+ * performed.
+ */
+abstract class ConstantEvaluationTarget extends AnalysisTarget {
+ /**
+ * Return the [AnalysisContext] which should be used to evaluate this
+ * constant.
+ */
+ AnalysisContext get context;
+
+ /**
+ * Return whether this constant is evaluated.
+ */
+ bool get isConstantEvaluated;
+}
+
+/**
* Interface used by unit tests to verify correct dependency analysis during
* constant evaluation.
*/
@@ -993,58 +1010,7 @@
/**
* A visitor used to evaluate constant expressions to produce their compile-time
- * value. According to the Dart Language Specification: <blockquote> A constant
- * expression is one of the following:
- *
- * * A literal number.
- * * A literal boolean.
- * * A literal string where any interpolated expression is a compile-time
- * constant that evaluates to a numeric, string or boolean value or to
- * <b>null</b>.
- * * A literal symbol.
- * * <b>null</b>.
- * * A qualified reference to a static constant variable.
- * * An identifier expression that denotes a constant variable, class or type
- * alias.
- * * A constant constructor invocation.
- * * A constant list literal.
- * * A constant map literal.
- * * A simple or qualified identifier denoting a top-level function or a static
- * method.
- * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant
- * expression.
- * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
- * where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- * expressions and <i>identical()</i> is statically bound to the predefined
- * dart function <i>identical()</i> discussed above.
- * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or
- * <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
- * <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric,
- * string or boolean value.
- * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &&
- * e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>,
- * <i>e1</sub></i> and <i>e2</sub></i> are constant expressions that evaluate
- * to a boolean value.
- * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
- * e<sub>2</sub></i>, <i>e<sub>1</sub> & e<sub>2</sub></i>,
- * <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> >>
- * e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, where
- * <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- * expressions that evaluate to an integer value or to <b>null</b>.
- * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
- * e<sub>2</sub></i>, <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> *
- * e<sub>2</sub></i>, <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub>
- * ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> > e<sub>2</sub></i>,
- * <i>e<sub>1</sub> < e<sub>2</sub></i>, <i>e<sub>1</sub> >=
- * e<sub>2</sub></i>, <i>e<sub>1</sub> <= e<sub>2</sub></i> or
- * <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i>
- * and <i>e<sub>2</sub></i> are constant expressions that evaluate to a
- * numeric value or to <b>null</b>.
- * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
- * e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
- * <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
- * evaluates to a boolean value.
- * </blockquote>
+ * value.
*/
class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
/**
@@ -1467,7 +1433,14 @@
@override
DartObjectImpl visitSetOrMapLiteral(SetOrMapLiteral node) {
- if (node.isMap) {
+ // Note: due to dartbug.com/33441, it's possible that a set/map literal
+ // resynthesized from a summary will have neither its `isSet` or `isMap`
+ // boolean set to `true`. We work around the problem by assuming such
+ // literals are maps.
+ // TODO(paulberry): when dartbug.com/33441 is fixed, add an assertion here
+ // to verify that `node.isSet == !node.isMap`.
+ bool isMap = !node.isSet;
+ if (isMap) {
if (!node.isConst) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL, node);
@@ -1494,7 +1467,7 @@
InterfaceType mapType =
_typeProvider.mapType.instantiate([keyType, valueType]);
return new DartObjectImpl(mapType, new MapState(map));
- } else if (node.isSet) {
+ } else {
if (!node.isConst) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL, node);
@@ -1516,7 +1489,6 @@
InterfaceType setType = _typeProvider.setType.instantiate([elementType]);
return new DartObjectImpl(setType, new SetState(set));
}
- return null;
}
@override
@@ -1580,8 +1552,7 @@
*/
bool _addElementsToList(List<DartObject> list, CollectionElement element) {
if (element is IfElement) {
- DartObjectImpl conditionResult = element.condition.accept(this);
- bool conditionValue = conditionResult?.toBoolValue();
+ bool conditionValue = _evaluateCondition(element.condition);
if (conditionValue == null) {
return true;
} else if (conditionValue) {
@@ -1618,8 +1589,7 @@
bool _addElementsToMap(
Map<DartObjectImpl, DartObjectImpl> map, CollectionElement element) {
if (element is IfElement) {
- DartObjectImpl conditionResult = element.condition.accept(this);
- bool conditionValue = conditionResult?.toBoolValue();
+ bool conditionValue = _evaluateCondition(element.condition);
if (conditionValue == null) {
return true;
} else if (conditionValue) {
@@ -1656,8 +1626,7 @@
*/
bool _addElementsToSet(Set<DartObject> set, CollectionElement element) {
if (element is IfElement) {
- DartObjectImpl conditionResult = element.condition.accept(this);
- bool conditionValue = conditionResult?.toBoolValue();
+ bool conditionValue = _evaluateCondition(element.condition);
if (conditionValue == null) {
return true;
} else if (conditionValue) {
@@ -1707,6 +1676,27 @@
}
/**
+ * Evaluate the given [condition] with the assumption that it must be a
+ * `bool`.
+ */
+ bool _evaluateCondition(Expression condition) {
+ DartObjectImpl conditionResult = condition.accept(this);
+ bool conditionValue = conditionResult?.toBoolValue();
+ if (conditionValue == null) {
+ // TODO(brianwilkerson) Figure out why the static type is sometimes null.
+ DartType staticType = condition.staticType;
+ if (staticType == null ||
+ typeSystem.isAssignableTo(staticType, _typeProvider.boolType)) {
+ // If the static type is not assignable, then we will have already
+ // reported this error.
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, condition);
+ }
+ }
+ return conditionValue;
+ }
+
+ /**
* Return the constant value of the static constant represented by the given
* [element]. The [node] is the node to be used if an error needs to be
* reported.
diff --git a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
new file mode 100644
index 0000000..5a48513
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
@@ -0,0 +1,330 @@
+// Copyright (c) 2019, 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/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+
+/// Check if the [node] and all its sub-nodes are potentially constant.
+///
+/// Return the list of nodes that are not potentially constant.
+List<AstNode> getNotPotentiallyConstants(AstNode node) {
+ var collector = _Collector();
+ collector.collect(node);
+ return collector.nodes;
+}
+
+/// Return `true` if the [node] is a constant type expression.
+bool isConstantTypeExpression(TypeAnnotation node) {
+ if (node is TypeName) {
+ if (_isConstantTypeName(node.name)) {
+ var arguments = node.typeArguments?.arguments;
+ if (arguments != null) {
+ for (var argument in arguments) {
+ if (!isConstantTypeExpression(argument)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ if (node.type is DynamicTypeImpl) {
+ return true;
+ }
+ if (node.type is VoidType) {
+ return true;
+ }
+ return false;
+ }
+
+ if (node is GenericFunctionType) {
+ var returnType = node.returnType;
+ if (returnType != null) {
+ if (!isConstantTypeExpression(returnType)) {
+ return false;
+ }
+ }
+
+ var typeParameters = node.typeParameters?.typeParameters;
+ if (typeParameters != null) {
+ for (var parameter in typeParameters) {
+ var bound = parameter.bound;
+ if (bound != null && !isConstantTypeExpression(bound)) {
+ return false;
+ }
+ }
+ }
+
+ var formalParameters = node.parameters?.parameters;
+ if (formalParameters != null) {
+ for (var parameter in formalParameters) {
+ if (parameter is SimpleFormalParameter) {
+ if (!isConstantTypeExpression(parameter.type)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool _isConstantTypeName(Identifier name) {
+ var element = name.staticElement;
+ if (element is ClassElement || element is GenericTypeAliasElement) {
+ if (name is PrefixedIdentifier) {
+ if (name.isDeferred) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+class _Collector {
+ final List<AstNode> nodes = [];
+
+ void collect(AstNode node) {
+ if (node is BooleanLiteral ||
+ node is DoubleLiteral ||
+ node is IntegerLiteral ||
+ node is NullLiteral ||
+ node is SimpleStringLiteral ||
+ node is SymbolLiteral) {
+ return;
+ }
+
+ if (node is StringInterpolation) {
+ for (var component in node.elements) {
+ if (component is InterpolationExpression) {
+ collect(component.expression);
+ }
+ }
+ return;
+ }
+
+ if (node is Identifier) {
+ return _identifier(node);
+ }
+
+ if (node is InstanceCreationExpression) {
+ if (!node.isConst) {
+ nodes.add(node);
+ }
+ return;
+ }
+
+ if (node is TypedLiteral) {
+ return _typeLiteral(node);
+ }
+
+ if (node is ParenthesizedExpression) {
+ collect(node.expression);
+ return;
+ }
+
+ if (node is MethodInvocation) {
+ return _methodInvocation(node);
+ }
+
+ if (node is BinaryExpression) {
+ collect(node.leftOperand);
+ collect(node.rightOperand);
+ return;
+ }
+
+ if (node is PrefixExpression) {
+ var operator = node.operator.type;
+ if (operator == TokenType.BANG ||
+ operator == TokenType.MINUS ||
+ operator == TokenType.TILDE) {
+ collect(node.operand);
+ return;
+ }
+ nodes.add(node);
+ return;
+ }
+
+ if (node is ConditionalExpression) {
+ collect(node.condition);
+ collect(node.thenExpression);
+ collect(node.elseExpression);
+ return;
+ }
+
+ if (node is PropertyAccess) {
+ return _propertyAccess(node);
+ }
+
+ if (node is AsExpression) {
+ if (!isConstantTypeExpression(node.type)) {
+ nodes.add(node.type);
+ }
+ collect(node.expression);
+ return;
+ }
+
+ if (node is IsExpression) {
+ if (!isConstantTypeExpression(node.type)) {
+ nodes.add(node.type);
+ }
+ collect(node.expression);
+ return;
+ }
+
+ if (node is MapLiteralEntry) {
+ collect(node.key);
+ collect(node.value);
+ return;
+ }
+
+ if (node is SpreadElement) {
+ collect(node.expression);
+ return;
+ }
+
+ if (node is IfElement) {
+ collect(node.condition);
+ collect(node.thenElement);
+ if (node.elseElement != null) {
+ collect(node.elseElement);
+ }
+ return;
+ }
+
+ nodes.add(node);
+ }
+
+ void _identifier(Identifier node) {
+ var element = node.staticElement;
+
+ if (node is PrefixedIdentifier) {
+ if (node.isDeferred) {
+ nodes.add(node);
+ return;
+ }
+ if (node.identifier.name == 'length') {
+ collect(node.prefix);
+ return;
+ }
+ if (element is MethodElement && element.isStatic) {
+ if (_isConstantTypeName(node.prefix)) {
+ return;
+ }
+ }
+ }
+
+ if (element is VariableElement) {
+ if (!element.isConst) {
+ nodes.add(node);
+ }
+ return;
+ }
+ if (element is PropertyAccessorElement && element.isGetter) {
+ var variable = element.variable;
+ if (!variable.isConst) {
+ nodes.add(node);
+ }
+ return;
+ }
+ if (_isConstantTypeName(node)) {
+ return;
+ }
+ if (element is FunctionElement) {
+ return;
+ }
+ nodes.add(node);
+ }
+
+ void _methodInvocation(MethodInvocation node) {
+ var arguments = node.argumentList?.arguments;
+ if (arguments?.length == 2 && node.methodName.name == 'identical') {
+ var library = node.methodName?.staticElement?.library;
+ if (library?.isDartCore == true) {
+ collect(arguments[0]);
+ collect(arguments[1]);
+ return;
+ }
+ }
+ nodes.add(node);
+ }
+
+ void _propertyAccess(PropertyAccess node) {
+ if (node.propertyName.name == 'length') {
+ collect(node.target);
+ return;
+ }
+
+ var target = node.target;
+ if (target is PrefixedIdentifier) {
+ if (target.isDeferred) {
+ nodes.add(node);
+ return;
+ }
+
+ var element = node.propertyName.staticElement;
+ if (element is PropertyAccessorElement && element.isGetter) {
+ var variable = element.variable;
+ if (!variable.isConst) {
+ nodes.add(node.propertyName);
+ }
+ return;
+ }
+ }
+
+ nodes.add(node);
+ }
+
+ void _typeLiteral(TypedLiteral node) {
+ if (!node.isConst) {
+ nodes.add(node);
+ return;
+ }
+
+ if (node is ListLiteral) {
+ var typeArguments = node.typeArguments?.arguments;
+ if (typeArguments?.length == 1) {
+ var elementType = typeArguments[0];
+ if (!isConstantTypeExpression(elementType)) {
+ nodes.add(elementType);
+ }
+ }
+
+ for (var element in node.elements2) {
+ collect(element);
+ }
+ return;
+ }
+
+ if (node is SetOrMapLiteral) {
+ var typeArguments = node.typeArguments?.arguments;
+ if (typeArguments?.length == 1) {
+ var elementType = typeArguments[0];
+ if (!isConstantTypeExpression(elementType)) {
+ nodes.add(elementType);
+ }
+ }
+
+ if (typeArguments?.length == 2) {
+ var keyType = typeArguments[0];
+ var valueType = typeArguments[1];
+ if (!isConstantTypeExpression(keyType)) {
+ nodes.add(keyType);
+ }
+ if (!isConstantTypeExpression(valueType)) {
+ nodes.add(valueType);
+ }
+ }
+
+ for (var element in node.elements2) {
+ collect(element);
+ }
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 3a9b8a7..6e5f535 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -12,11 +12,11 @@
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/constant/evaluation.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/handle.dart'
show ConstructorElementHandle;
import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/task/dart.dart';
ConstructorElementImpl getConstructorImpl(ConstructorElement constructor) {
while (constructor is ConstructorMember) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 1f9c4c1..5cf726d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -14,6 +14,7 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/compute.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/type.dart';
@@ -31,7 +32,6 @@
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary2/linked_unit_context.dart';
import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/task/dart.dart';
/// Assert that the given [object] is null, which in the places where this
/// function is called means that the element is not resynthesized.
@@ -60,6 +60,10 @@
/// given [offset] in the file that contains the declaration of this element.
AbstractClassElementImpl(String name, int offset) : super(name, offset);
+ AbstractClassElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created class element to have the given [name].
AbstractClassElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -414,9 +418,6 @@
/// The unlinked representation of the class in the summary.
final UnlinkedClass _unlinkedClass;
- final Reference reference;
- final LinkedNode _linkedNode;
-
/// If this class is resynthesized, whether it has a constant constructor.
bool _hasConstConstructorCached;
@@ -455,31 +456,25 @@
/// Initialize a newly created class element to have the given [name] at the
/// given [offset] in the file that contains the declaration of this element.
ClassElementImpl(String name, int offset)
- : reference = null,
- _linkedNode = null,
- _unlinkedClass = null,
+ : _unlinkedClass = null,
super(name, offset);
- ClassElementImpl.forLinkedNode(this.reference, this._linkedNode,
- CompilationUnitElementImpl enclosingUnit)
+ ClassElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
+ Reference reference, LinkedNode linkedNode)
: _unlinkedClass = null,
- super.forSerialized(enclosingUnit) {
- reference.element = this;
+ super.forLinkedNode(enclosing, reference, linkedNode) {
+ enclosing.linkedContext.loadClassMemberReferences(reference);
}
/// Initialize a newly created class element to have the given [name].
ClassElementImpl.forNode(Identifier name)
- : reference = null,
- _linkedNode = null,
- _unlinkedClass = null,
+ : _unlinkedClass = null,
super.forNode(name);
/// Initialize using the given serialized information.
ClassElementImpl.forSerialized(
this._unlinkedClass, CompilationUnitElementImpl enclosingUnit)
- : reference = null,
- _linkedNode = null,
- super.forSerialized(enclosingUnit);
+ : super.forSerialized(enclosingUnit);
/// Set whether this class is abstract.
void set abstract(bool isAbstract) {
@@ -489,6 +484,18 @@
@override
List<PropertyAccessorElement> get accessors {
+ if (linkedNode != null) {
+ if (_accessors != null) return _accessors;
+
+ if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+ linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+ _createPropertiesAndAccessors();
+ assert(_accessors != null);
+ return _accessors;
+ } else {
+ return _accessors = const [];
+ }
+ }
if (_accessors == null) {
if (_unlinkedClass != null) {
_resynthesizeFieldsAndPropertyAccessors();
@@ -536,16 +543,18 @@
return _constructors = _computeMixinAppConstructors();
}
- if (_linkedNode != null) {
- var context = enclosingUnit._linkedContext;
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
var containerRef = reference.getChild('@constructor');
- _constructors = _linkedNode.classOrMixinDeclaration_members
- .where((node) => node.kind == LinkedNodeKind.constructorDeclaration)
- .map((node) {
- var name = context.getConstructorDeclarationName(node);
- var reference = containerRef.getChild(name);
- return ConstructorElementImpl.forLinkedNode(reference, node, this);
- }).toList();
+ if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+ _constructors = linkedNode.classOrMixinDeclaration_members
+ .where((node) => node.kind == LinkedNodeKind.constructorDeclaration)
+ .map((node) {
+ var name = context.getConstructorDeclarationName(node);
+ var reference = containerRef.getChild(name);
+ return ConstructorElementImpl.forLinkedNode(reference, node, this);
+ }).toList();
+ }
}
if (_unlinkedClass != null) {
@@ -601,6 +610,11 @@
@override
String get documentationComment {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getCommentText(
+ linkedNode.annotatedNode_comment,
+ );
+ }
if (_unlinkedClass != null) {
return _unlinkedClass.documentationComment?.text;
}
@@ -612,6 +626,18 @@
@override
List<FieldElement> get fields {
+ if (linkedNode != null) {
+ if (_fields != null) return _fields;
+
+ if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+ linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+ _createPropertiesAndAccessors();
+ assert(_fields != null);
+ return _fields;
+ } else {
+ _fields = const [];
+ }
+ }
if (_fields == null) {
if (_unlinkedClass != null) {
_resynthesizeFieldsAndPropertyAccessors();
@@ -710,13 +736,13 @@
return _interfaces;
}
- if (_linkedNode != null) {
- var context = enclosingUnit._linkedContext;
- var implementsClause =
- _linkedNode.classOrMixinDeclaration_implementsClause;
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ var implementsClause = context.getImplementsClause(linkedNode);
if (implementsClause != null) {
return _interfaces = implementsClause.implementsClause_interfaces
.map((node) => context.getInterfaceType(node.typeName_type))
+ .where((type) => type != null)
.toList();
}
} else if (_unlinkedClass != null) {
@@ -757,8 +783,12 @@
@override
bool get isAbstract {
- if (_linkedNode != null) {
- return _linkedNode.classDeclaration_abstractKeyword != 0;
+ if (linkedNode != null) {
+ if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+ return linkedNode.classDeclaration_abstractKeyword != 0;
+ } else {
+ return linkedNode.classTypeAlias_abstractKeyword != 0;
+ }
}
if (_unlinkedClass != null) {
return _unlinkedClass.isAbstract;
@@ -768,6 +798,9 @@
@override
bool get isMixinApplication {
+ if (linkedNode != null) {
+ return linkedNode.kind == LinkedNodeKind.classTypeAlias;
+ }
if (_unlinkedClass != null) {
return _unlinkedClass.isMixinApplication;
}
@@ -819,6 +852,24 @@
return _methods;
}
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ var containerRef = reference.getChild('@method');
+ if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+ linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+ return _methods = linkedNode.classOrMixinDeclaration_members
+ .where((node) => node.kind == LinkedNodeKind.methodDeclaration)
+ .where((node) => node.methodDeclaration_propertyKeyword == 0)
+ .map((node) {
+ var name = context.getSimpleName(node.methodDeclaration_name);
+ var reference = containerRef.getChild(name);
+ return MethodElementImpl.forLinkedNode(reference, node, this);
+ }).toList();
+ } else {
+ return _methods = const <MethodElement>[];
+ }
+ }
+
if (_unlinkedClass != null) {
var unlinkedExecutables = _unlinkedClass.executables;
@@ -872,12 +923,18 @@
return _mixins;
}
- if (_linkedNode != null) {
- var context = enclosingUnit._linkedContext;
- var withClause = _linkedNode.classDeclaration_withClause;
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ LinkedNode withClause;
+ if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+ withClause = linkedNode.classDeclaration_withClause;
+ } else {
+ withClause = linkedNode.classTypeAlias_withClause;
+ }
if (withClause != null) {
return _mixins = withClause.withClause_mixinTypes
.map((node) => context.getInterfaceType(node.typeName_type))
+ .where((type) => type != null)
.toList();
}
} else if (_unlinkedClass != null) {
@@ -923,7 +980,7 @@
@override
String get name {
- if (_linkedNode != null) {
+ if (linkedNode != null) {
return reference.name;
}
if (_unlinkedClass != null) {
@@ -949,13 +1006,19 @@
@override
InterfaceType get supertype {
if (_supertype == null) {
- if (_linkedNode != null) {
- var context = enclosingUnit._linkedContext;
- var extendsClause = _linkedNode.classDeclaration_extendsClause;
- if (extendsClause != null) {
- _supertype = context.getInterfaceType(
- extendsClause.extendsClause_superclass.typeName_type,
- );
+ if (linkedNode != null) {
+ LinkedNode superclass;
+ if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+ superclass = linkedNode
+ .classDeclaration_extendsClause?.extendsClause_superclass;
+ } else {
+ superclass = linkedNode.classTypeAlias_superclass;
+ }
+ if (superclass != null) {
+ var context = enclosingUnit.linkedContext;
+ _supertype = context.getInterfaceType(superclass.typeName_type);
+ } else if (!linkedNode.classDeclaration_isDartObject) {
+ _supertype = context.typeProvider.objectType;
}
} else if (_unlinkedClass != null) {
if (_unlinkedClass.supertype != null) {
@@ -991,6 +1054,27 @@
return _type;
}
+ @override
+ List<TypeParameterElement> get typeParameters {
+ if (_typeParameterElements != null) return _typeParameterElements;
+
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ var containerRef = reference.getChild('@typeParameter');
+ var typeParameters = context.getTypeParameters(linkedNode);
+ if (typeParameters == null) {
+ return _typeParameterElements = const [];
+ }
+ return _typeParameterElements = typeParameters.map((node) {
+ var name = context.getSimpleName(node.typeParameter_name);
+ var reference = containerRef.getChild(name);
+ reference.node = node;
+ return TypeParameterElementImpl.forLinkedNode(this, reference, node);
+ }).toList();
+ }
+ return super.typeParameters;
+ }
+
/// Set the type parameters defined for this class to the given
/// [typeParameters].
void set typeParameters(List<TypeParameterElement> typeParameters) {
@@ -1208,6 +1292,75 @@
}).toList(growable: false);
}
+ void _createPropertiesAndAccessors() {
+ assert(_accessors == null);
+ assert(_fields == null);
+
+ var context = enclosingUnit.linkedContext;
+ var accessorList = <PropertyAccessorElementImpl>[];
+ var fieldList = <FieldElementImpl>[];
+
+ var fields = context.classFields(linkedNode);
+ for (var field in fields) {
+ var name = context.getVariableName(field);
+ var fieldElement = FieldElementImpl.forLinkedNodeFactory(
+ this,
+ reference.getChild('@field').getChild(name),
+ field,
+ );
+ fieldList.add(fieldElement);
+
+ accessorList.add(fieldElement.getter);
+ if (fieldElement.setter != null) {
+ accessorList.add(fieldElement.setter);
+ }
+ }
+
+ for (var node in linkedNode.classOrMixinDeclaration_members) {
+ if (node.kind == LinkedNodeKind.methodDeclaration) {
+ var isGetter = context.isGetterMethod(node);
+ var isSetter = context.isSetterMethod(node);
+ if (!isGetter && !isSetter) continue;
+
+ var name = context.getMethodName(node);
+ var containerRef = isGetter
+ ? reference.getChild('@getter')
+ : reference.getChild('@setter');
+
+ var accessorElement = PropertyAccessorElementImpl.forLinkedNode(
+ this,
+ containerRef.getChild(name),
+ node,
+ );
+ accessorList.add(accessorElement);
+
+ var fieldRef = reference.getChild('@field').getChild(name);
+ FieldElementImpl field = fieldRef.element;
+ if (field == null) {
+ field = new FieldElementImpl(name, -1);
+ fieldRef.element = field;
+ field.enclosingElement = this;
+ field.isSynthetic = true;
+ field.isFinal = isGetter;
+ field.isStatic = accessorElement.isStatic;
+ fieldList.add(field);
+ } else {
+ field.isFinal = false;
+ }
+
+ accessorElement.variable = field;
+ if (isGetter) {
+ field.getter = accessorElement;
+ } else {
+ field.setter = accessorElement;
+ }
+ }
+ }
+
+ _accessors = accessorList;
+ _fields = fieldList;
+ }
+
/// Return `true` if the given [type] is an [InterfaceType] that can be used
/// as a class.
bool _isInterfaceTypeClass(DartType type) {
@@ -1412,9 +1565,7 @@
/// The unlinked representation of the part in the summary.
final UnlinkedPart _unlinkedPart;
- final LinkedUnitContext _linkedContext;
- final Reference reference;
- final LinkedNode _linkedNode;
+ final LinkedUnitContext linkedContext;
/// The source that corresponds to this compilation unit.
@override
@@ -1477,27 +1628,20 @@
: resynthesizerContext = null,
_unlinkedUnit = null,
_unlinkedPart = null,
- _linkedContext = null,
- reference = null,
- _linkedNode = null,
+ linkedContext = null,
super(null, -1);
CompilationUnitElementImpl.forLinkedNode(LibraryElementImpl enclosingLibrary,
- this._linkedContext, this.reference, this._linkedNode)
+ this.linkedContext, Reference reference, LinkedNode linkedNode)
: resynthesizerContext = null,
_unlinkedUnit = null,
_unlinkedPart = null,
- super.forSerialized(null) {
- _enclosingElement = enclosingLibrary;
- _nameOffset = -1;
- }
+ super.forLinkedNode(enclosingLibrary, reference, linkedNode);
/// Initialize using the given serialized information.
CompilationUnitElementImpl.forSerialized(LibraryElementImpl enclosingLibrary,
this.resynthesizerContext, this._unlinkedUnit, this._unlinkedPart)
- : _linkedContext = null,
- reference = null,
- _linkedNode = null,
+ : linkedContext = null,
super.forSerialized(null) {
_enclosingElement = enclosingLibrary;
_nameOffset = -1;
@@ -1505,6 +1649,12 @@
@override
List<PropertyAccessorElement> get accessors {
+ if (linkedNode != null) {
+ if (_accessors != null) return _accessors;
+ _createPropertiesAndAccessors(this);
+ assert(_accessors != null);
+ return _accessors;
+ }
if (_accessors == null) {
if (_unlinkedUnit != null) {
_explicitTopLevelAccessors ??=
@@ -1557,6 +1707,19 @@
@override
List<ClassElement> get enums {
+ if (linkedNode != null) {
+ if (_enums != null) return _enums;
+ var context = enclosingUnit.linkedContext;
+ var containerRef = reference.getChild('@enum');
+ _enums = linkedNode.compilationUnit_declarations
+ .where((node) => node.kind == LinkedNodeKind.enumDeclaration)
+ .map((node) {
+ var name = context.getUnitMemberName(node);
+ var reference = containerRef.getChild(name);
+ reference.node = node;
+ return EnumElementImpl.forLinkedNode(this, reference, node);
+ }).toList();
+ }
if (_unlinkedUnit != null) {
_enums ??= _unlinkedUnit.enums
.map((e) => new EnumElementImpl.forSerialized(e, this))
@@ -1576,8 +1739,23 @@
@override
List<FunctionElement> get functions {
- if (_unlinkedUnit != null) {
- _functions ??= _unlinkedUnit.executables
+ if (_functions != null) return _functions;
+
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ var containerRef = reference.getChild('@function');
+ _functions = linkedNode.compilationUnit_declarations
+ .where((node) =>
+ node.kind == LinkedNodeKind.functionDeclaration &&
+ !context.isGetterFunction(node) &&
+ !context.isSetterFunction(node))
+ .map((node) {
+ var name = context.getUnitMemberName(node);
+ var reference = containerRef.getChild(name);
+ return FunctionElementImpl.forLinkedNode(this, reference, node);
+ }).toList();
+ } else if (_unlinkedUnit != null) {
+ _functions = _unlinkedUnit.executables
.where((e) => e.kind == UnlinkedExecutableKind.functionOrMethod)
.map((e) => new FunctionElementImpl.forSerialized(e, this))
.toList(growable: false);
@@ -1596,8 +1774,22 @@
@override
List<FunctionTypeAliasElement> get functionTypeAliases {
+ if (_typeAliases != null) return _typeAliases;
+
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ var containerRef = reference.getChild('@typeAlias');
+ _typeAliases = linkedNode.compilationUnit_declarations
+ .where((node) => node.kind == LinkedNodeKind.functionTypeAlias)
+ .map((node) {
+ var name = context.getUnitMemberName(node);
+ var reference = containerRef.getChild(name);
+ return GenericTypeAliasElementImpl.forLinkedNode(this, reference, node);
+ }).toList();
+ }
+
if (_unlinkedUnit != null) {
- _typeAliases ??= _unlinkedUnit.typedefs.map((t) {
+ _typeAliases = _unlinkedUnit.typedefs.map((t) {
return new GenericTypeAliasElementImpl.forSerialized(t, this);
}).toList(growable: false);
}
@@ -1657,6 +1849,12 @@
@override
List<TopLevelVariableElement> get topLevelVariables {
+ if (linkedNode != null) {
+ if (_variables != null) return _variables;
+ _createPropertiesAndAccessors(this);
+ assert(_variables != null);
+ return _variables;
+ }
if (_variables == null) {
if (_unlinkedUnit != null) {
_explicitTopLevelAccessors ??=
@@ -1711,15 +1909,18 @@
@override
List<ClassElement> get types {
- if (_linkedNode != null) {
- var context = enclosingUnit._linkedContext;
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
var containerRef = reference.getChild('@class');
- _types = _linkedNode.compilationUnit_declarations
- .where((node) => node.kind == LinkedNodeKind.classDeclaration)
+ _types = linkedNode.compilationUnit_declarations
+ .where((node) =>
+ node.kind == LinkedNodeKind.classDeclaration ||
+ node.kind == LinkedNodeKind.classTypeAlias)
.map((node) {
var name = context.getUnitMemberName(node);
var reference = containerRef.getChild(name);
- return ClassElementImpl.forLinkedNode(reference, node, this);
+ reference.node = node;
+ return ClassElementImpl.forLinkedNode(this, reference, node);
}).toList();
} else if (_unlinkedUnit != null) {
_types ??= _unlinkedUnit.classes
@@ -1880,6 +2081,89 @@
}
return null;
}
+
+ static void _createPropertiesAndAccessors(CompilationUnitElementImpl unit) {
+ if (unit._variables != null) return;
+ assert(unit._accessors == null);
+
+ var accessorMap =
+ <CompilationUnitElementImpl, List<PropertyAccessorElementImpl>>{};
+ var variableMap =
+ <CompilationUnitElementImpl, List<TopLevelVariableElementImpl>>{};
+
+ var units = unit.library.units;
+ for (CompilationUnitElementImpl unit in units) {
+ var context = unit.linkedContext;
+
+ var accessorList = <PropertyAccessorElementImpl>[];
+ accessorMap[unit] = accessorList;
+
+ var variableList = <TopLevelVariableElementImpl>[];
+ variableMap[unit] = variableList;
+
+ var variables = context.topLevelVariables(unit.linkedNode);
+ for (var variable in variables) {
+ var name = context.getVariableName(variable);
+ var reference = unit.reference.getChild('@variable').getChild(name);
+ var variableElement = TopLevelVariableElementImpl.forLinkedNodeFactory(
+ unit,
+ reference,
+ variable,
+ );
+ variableList.add(variableElement);
+
+ accessorList.add(variableElement.getter);
+ if (variableElement.setter != null) {
+ accessorList.add(variableElement.setter);
+ }
+ }
+
+ for (var node in unit.linkedNode.compilationUnit_declarations) {
+ if (node.kind == LinkedNodeKind.functionDeclaration) {
+ var isGetter = context.isGetterFunction(node);
+ var isSetter = context.isSetterFunction(node);
+ if (!isGetter && !isSetter) continue;
+
+ var name = context.getUnitMemberName(node);
+ var containerRef = isGetter
+ ? unit.reference.getChild('@getter')
+ : unit.reference.getChild('@setter');
+
+ var accessorElement = PropertyAccessorElementImpl.forLinkedNode(
+ unit,
+ containerRef.getChild(name),
+ node,
+ );
+ accessorList.add(accessorElement);
+
+ var fieldRef = unit.reference.getChild('@field').getChild(name);
+ TopLevelVariableElementImpl field = fieldRef.element;
+ if (field == null) {
+ field = new TopLevelVariableElementImpl(name, -1);
+ fieldRef.element = field;
+ field.enclosingElement = unit;
+ field.isSynthetic = true;
+ field.isFinal = isGetter;
+ variableList.add(field);
+ } else {
+ field.isFinal = false;
+ }
+
+ accessorElement.variable = field;
+ if (isGetter) {
+ field.getter = accessorElement;
+ } else {
+ field.setter = accessorElement;
+ }
+ }
+ }
+ }
+
+ for (CompilationUnitElementImpl unit in units) {
+ unit._accessors = accessorMap[unit];
+ unit._variables = variableMap[unit];
+ }
+ }
}
/// A [FieldElement] for a 'const' or 'final' field that has an initializer.
@@ -1895,6 +2179,10 @@
/// [name] and [offset].
ConstFieldElementImpl(String name, int offset) : super(name, offset);
+ ConstFieldElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created field element to have the given [name].
ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -1913,8 +2201,21 @@
EnumElementImpl enumElement, this._unlinkedEnumValue, this._index)
: super(enumElement);
+ ConstFieldElementImpl_EnumValue.forLinkedNode(EnumElementImpl enumElement,
+ Reference reference, LinkedNode linkedNode, this._index)
+ : _unlinkedEnumValue = null,
+ super.forLinkedNode(enumElement, reference, linkedNode);
+
+ @override
+ Expression get constantInitializer => null;
+
@override
String get documentationComment {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getCommentText(
+ linkedNode.annotatedNode_comment,
+ );
+ }
if (_unlinkedEnumValue != null) {
return _unlinkedEnumValue.documentationComment?.text;
}
@@ -1946,6 +2247,9 @@
@override
String get name {
+ if (linkedNode != null) {
+ return reference.name;
+ }
if (_unlinkedEnumValue != null) {
return _unlinkedEnumValue.name;
}
@@ -1954,9 +2258,16 @@
@override
int get nameOffset {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getSimpleOffset(
+ linkedNode.enumConstantDeclaration_name,
+ );
+ }
int offset = super.nameOffset;
- if (offset == -1 && _unlinkedEnumValue != null) {
- return _unlinkedEnumValue.nameOffset;
+ if (offset == -1) {
+ if (_unlinkedEnumValue != null) {
+ return _unlinkedEnumValue.nameOffset;
+ }
}
return offset;
}
@@ -2008,6 +2319,10 @@
enclosingElement = _enum;
}
+ ConstFieldElementImpl_ofEnum.forLinkedNode(
+ this._enum, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(_enum, reference, linkedNode);
+
@override
void set evaluationResult(_) {
assert(false);
@@ -2080,34 +2395,21 @@
@override
bool isConstantEvaluated = false;
- final Reference reference;
- final LinkedNode _linkedNode;
+ /// Initialize a newly created constructor element to have the given [name]
+ /// and [offset].
+ ConstructorElementImpl(String name, int offset) : super(name, offset);
- /// Initialize a newly created constructor element to have the given [name
- /// ] and[offset].
- ConstructorElementImpl(String name, int offset)
- : reference = null,
- _linkedNode = null,
- super(name, offset);
-
- ConstructorElementImpl.forLinkedNode(
- this.reference, this._linkedNode, ClassElementImpl enclosingClass)
- : super.forLinkedNode(enclosingClass) {
- reference.element = this;
- }
+ ConstructorElementImpl.forLinkedNode(Reference reference,
+ LinkedNode linkedNode, ClassElementImpl enclosingClass)
+ : super.forLinkedNode(enclosingClass, reference, linkedNode);
/// Initialize a newly created constructor element to have the given [name].
- ConstructorElementImpl.forNode(Identifier name)
- : reference = null,
- _linkedNode = null,
- super.forNode(name);
+ ConstructorElementImpl.forNode(Identifier name) : super.forNode(name);
/// Initialize using the given serialized information.
ConstructorElementImpl.forSerialized(
UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass)
- : reference = null,
- _linkedNode = null,
- super.forSerialized(serializedExecutable, enclosingClass);
+ : super.forSerialized(serializedExecutable, enclosingClass);
/// Return the constant initializers for this element, which will be empty if
/// there are no initializers, or `null` if there was an error in the source.
@@ -2130,7 +2432,7 @@
@override
String get displayName {
- if (_linkedNode != null) {
+ if (linkedNode != null) {
return reference.name;
}
return super.displayName;
@@ -2152,8 +2454,8 @@
@override
bool get isConst {
- if (_linkedNode != null) {
- return _linkedNode.constructorDeclaration_constKeyword != 0;
+ if (linkedNode != null) {
+ return linkedNode.constructorDeclaration_constKeyword != 0;
}
if (serializedExecutable != null) {
return serializedExecutable.isConst;
@@ -2200,17 +2502,9 @@
}
@override
- bool get isExternal {
- if (_linkedNode != null) {
- return _linkedNode.constructorDeclaration_externalKeyword != 0;
- }
- return super.isExternal;
- }
-
- @override
bool get isFactory {
- if (_linkedNode != null) {
- return _linkedNode.constructorDeclaration_factoryKeyword != 0;
+ if (linkedNode != null) {
+ return linkedNode.constructorDeclaration_factoryKeyword != 0;
}
if (serializedExecutable != null) {
return serializedExecutable.isFactory;
@@ -2222,19 +2516,11 @@
bool get isStatic => false;
@override
- bool get isSynthetic {
- if (_linkedNode != null) {
- return _linkedNode.isSynthetic;
- }
- return super.isSynthetic;
- }
-
- @override
ElementKind get kind => ElementKind.CONSTRUCTOR;
@override
String get name {
- if (_linkedNode != null) {
+ if (linkedNode != null) {
return reference.name;
}
return super.name;
@@ -2415,6 +2701,10 @@
ConstTopLevelVariableElementImpl(String name, int offset)
: super(name, offset);
+ ConstTopLevelVariableElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created top-level variable element to have the given
/// [name].
ConstTopLevelVariableElementImpl.forNode(Identifier name)
@@ -2448,11 +2738,16 @@
EvaluationResultImpl _evaluationResult;
Expression get constantInitializer {
- if (_constantInitializer == null) {
- if (_unlinkedConst != null) {
- _constantInitializer = enclosingUnit.resynthesizerContext
- .buildExpression(this, _unlinkedConst);
- }
+ if (_constantInitializer != null) return _constantInitializer;
+
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ return _constantInitializer = context.readInitializer(linkedNode);
+ }
+
+ if (_unlinkedConst != null) {
+ _constantInitializer = enclosingUnit.resynthesizerContext
+ .buildExpression(this, _unlinkedConst);
}
return _constantInitializer;
}
@@ -2515,6 +2810,10 @@
DefaultParameterElementImpl(String name, int nameOffset)
: super(name, nameOffset);
+ DefaultParameterElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created parameter element to have the given [name].
DefaultParameterElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -2807,6 +3106,9 @@
/// root of the element structure.
ElementImpl _enclosingElement;
+ Reference reference;
+ final LinkedNode linkedNode;
+
/// The name of this element.
String _name;
@@ -2838,19 +3140,26 @@
/// Initialize a newly created element to have the given [name] at the given
/// [_nameOffset].
- ElementImpl(String name, this._nameOffset) {
+ ElementImpl(String name, this._nameOffset, {this.reference})
+ : linkedNode = null {
this._name = StringUtilities.intern(name);
+ this.reference?.element = this;
}
/// Initialize from linked node.
- ElementImpl.forLinkedNode(this._enclosingElement);
+ ElementImpl.forLinkedNode(
+ this._enclosingElement, this.reference, this.linkedNode) {
+ reference?.element = this;
+ }
/// Initialize a newly created element to have the given [name].
ElementImpl.forNode(Identifier name)
: this(name == null ? "" : name.name, name == null ? -1 : name.offset);
/// Initialize from serialized information.
- ElementImpl.forSerialized(this._enclosingElement);
+ ElementImpl.forSerialized(this._enclosingElement)
+ : reference = null,
+ linkedNode = null;
/// The length of the element's code, or `null` if the element is synthetic.
int get codeLength => _codeLength;
@@ -3100,7 +3409,12 @@
bool get isResynthesized => enclosingUnit?.resynthesizerContext != null;
@override
- bool get isSynthetic => hasModifier(Modifier.SYNTHETIC);
+ bool get isSynthetic {
+ if (linkedNode != null) {
+ return linkedNode.isSynthetic;
+ }
+ return hasModifier(Modifier.SYNTHETIC);
+ }
/// Set whether this element is synthetic.
void set isSynthetic(bool isSynthetic) {
@@ -3129,6 +3443,11 @@
}
List<ElementAnnotation> get metadata {
+ if (linkedNode != null) {
+ if (_metadata != null) return _metadata;
+ var metadata = enclosingUnit.linkedContext.getMetadataOrEmpty(linkedNode);
+ return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+ }
return _metadata ?? const <ElementAnnotation>[];
}
@@ -3157,8 +3476,6 @@
_nameOffset = offset;
}
- Reference get reference => null;
-
@override
AnalysisSession get session {
return _enclosingElement?.session;
@@ -3340,6 +3657,23 @@
}
}
+ /// Return annotations for the given [nodeList] in the [unit].
+ List<ElementAnnotation> _buildAnnotations2(
+ CompilationUnitElementImpl unit, List<LinkedNode> nodeList) {
+ var length = nodeList.length;
+ if (length == 0) {
+ return const <ElementAnnotation>[];
+ }
+
+ var annotations = new List<ElementAnnotation>(length);
+ for (int i = 0; i < length; i++) {
+ var ast = unit.linkedContext.readNode(nodeList[i]);
+ annotations[i] = ElementAnnotationImpl(enclosingUnit)
+ ..annotationAst = ast;
+ }
+ return annotations;
+ }
+
/// If the element associated with the given [type] is a generic function type
/// element, then make it a child of this element. Return the [type] as a
/// convenience.
@@ -3526,6 +3860,11 @@
: _unlinkedEnum = null,
super(name, offset);
+ EnumElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
+ Reference reference, LinkedNode linkedNode)
+ : _unlinkedEnum = null,
+ super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created class element to have the given [name].
EnumElementImpl.forNode(Identifier name)
: _unlinkedEnum = null,
@@ -3544,6 +3883,9 @@
@override
List<PropertyAccessorElement> get accessors {
if (_accessors == null) {
+ if (linkedNode != null) {
+ _resynthesizeMembers2();
+ }
if (_unlinkedEnum != null) {
_resynthesizeMembers();
}
@@ -3587,6 +3929,11 @@
@override
String get documentationComment {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getCommentText(
+ linkedNode.annotatedNode_comment,
+ );
+ }
if (_unlinkedEnum != null) {
return _unlinkedEnum.documentationComment?.text;
}
@@ -3596,6 +3943,9 @@
@override
List<FieldElement> get fields {
if (_fields == null) {
+ if (linkedNode != null) {
+ _resynthesizeMembers2();
+ }
if (_unlinkedEnum != null) {
_resynthesizeMembers();
}
@@ -3654,6 +4004,9 @@
@override
List<MethodElement> get methods {
if (_methods == null) {
+ if (linkedNode != null) {
+ _resynthesizeMembers2();
+ }
if (_unlinkedEnum != null) {
_resynthesizeMembers();
}
@@ -3666,6 +4019,9 @@
@override
String get name {
+ if (linkedNode != null) {
+ return reference.name;
+ }
if (_unlinkedEnum != null) {
return _unlinkedEnum.name;
}
@@ -3716,11 +4072,14 @@
void createToStringMethodElement() {
var method = new MethodElementImpl('toString', -1);
method.isSynthetic = true;
- if (_unlinkedEnum != null) {
+ if (linkedNode != null || _unlinkedEnum != null) {
method.returnType = context.typeProvider.stringType;
method.type = new FunctionTypeImpl(method);
}
method.enclosingElement = this;
+ if (linkedNode != null) {
+ method.reference = reference.getChild('@method').getChild('toString');
+ }
_methods = <MethodElement>[method];
}
@@ -3755,6 +4114,51 @@
.toList(growable: false);
createToStringMethodElement();
}
+
+ void _resynthesizeMembers2() {
+ var fields = <FieldElementImpl>[];
+ var getters = <PropertyAccessorElementImpl>[];
+
+ // Build the 'index' field.
+ {
+ var field = FieldElementImpl('index', -1)
+ ..enclosingElement = this
+ ..isSynthetic = true
+ ..isFinal = true
+ ..type = context.typeProvider.intType;
+ fields.add(field);
+ getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
+ reference: reference.getChild('@getter').getChild('index'))
+ ..enclosingElement = this);
+ }
+
+ // Build the 'values' field.
+ {
+ var field = ConstFieldElementImpl_EnumValues(this);
+ fields.add(field);
+ getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
+ reference: reference.getChild('@getter').getChild('values'))
+ ..enclosingElement = this);
+ }
+
+ // Build fields for all enum constants.
+ var constants = linkedNode.enumDeclaration_constants;
+ for (var i = 0; i < constants.length; ++i) {
+ var constant = constants[i];
+ var name = enclosingUnit.linkedContext.getSimpleName(
+ constant.enumConstantDeclaration_name,
+ );
+ var reference = this.reference.getChild('@constant').getChild(name);
+ var field = new ConstFieldElementImpl_EnumValue.forLinkedNode(
+ this, reference, constant, i);
+ fields.add(field);
+ getters.add(field.getter);
+ }
+
+ _fields = fields;
+ _accessors = getters;
+ createToStringMethodElement();
+ }
}
/// A base class for concrete implementations of an [ExecutableElement].
@@ -3779,14 +4183,17 @@
/// Initialize a newly created executable element to have the given [name] and
/// [offset].
- ExecutableElementImpl(String name, int offset)
+ ExecutableElementImpl(String name, int offset, {Reference reference})
: serializedExecutable = null,
- super(name, offset);
+ super(name, offset, reference: reference);
/// Initialize using the given linked node.
- ExecutableElementImpl.forLinkedNode(ElementImpl enclosingElement)
+ ExecutableElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
: serializedExecutable = null,
- super.forLinkedNode(enclosingElement);
+ super.forLinkedNode(enclosing, reference, linkedNode) {
+ reference.element = this;
+ }
/// Initialize a newly created executable element to have the given [name].
ExecutableElementImpl.forNode(Identifier name)
@@ -3827,6 +4234,9 @@
@override
String get displayName {
+ if (linkedNode != null) {
+ return reference.name;
+ }
if (serializedExecutable != null) {
return serializedExecutable.name;
}
@@ -3835,6 +4245,11 @@
@override
String get documentationComment {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getCommentText(
+ linkedNode.annotatedNode_comment,
+ );
+ }
if (serializedExecutable != null) {
return serializedExecutable.documentationComment?.text;
}
@@ -3878,6 +4293,9 @@
@override
bool get isAsynchronous {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isAsynchronous(linkedNode);
+ }
if (serializedExecutable != null) {
return serializedExecutable.isAsynchronous;
}
@@ -3886,6 +4304,9 @@
@override
bool get isExternal {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isExternal(linkedNode);
+ }
if (serializedExecutable != null) {
return serializedExecutable.isExternal;
}
@@ -3894,6 +4315,9 @@
@override
bool get isGenerator {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isGenerator(linkedNode);
+ }
if (serializedExecutable != null) {
return serializedExecutable.isGenerator;
}
@@ -3917,6 +4341,9 @@
@override
String get name {
+ if (linkedNode != null) {
+ return reference.name;
+ }
if (serializedExecutable != null) {
return serializedExecutable.name;
}
@@ -3925,6 +4352,12 @@
@override
int get nameOffset {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getSimpleOffset(
+ linkedNode.namedCompilationUnitMember_name,
+ );
+ }
+
int offset = super.nameOffset;
if (offset == 0 && serializedExecutable != null) {
return serializedExecutable.nameOffset;
@@ -3935,6 +4368,37 @@
@override
List<ParameterElement> get parameters {
if (_parameters == null) {
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ var containerRef = reference.getChild('@parameter');
+ var formalParameters = context.getFormalParameters(linkedNode);
+ if (formalParameters != null) {
+ _parameters = formalParameters.map((node) {
+ if (node.kind == LinkedNodeKind.defaultFormalParameter) {
+ var parameterNode = node.defaultFormalParameter_parameter;
+ var name = context.getFormalParameterName(parameterNode);
+ var reference = containerRef.getChild(name);
+ reference.node = node;
+ return DefaultParameterElementImpl.forLinkedNode(
+ this,
+ reference,
+ node,
+ );
+ } else {
+ var name = context.getFormalParameterName(node);
+ var reference = containerRef.getChild(name);
+ reference.node = node;
+ return ParameterElementImpl.forLinkedNodeFactory(
+ this,
+ reference,
+ node,
+ );
+ }
+ }).toList();
+ } else {
+ _parameters = const [];
+ }
+ }
if (serializedExecutable != null) {
_parameters = ParameterElementImpl.resynthesizeList(
serializedExecutable.parameters, this);
@@ -3955,6 +4419,10 @@
@override
DartType get returnType {
+ if (linkedNode != null) {
+ return _returnType ??=
+ enclosingUnit.linkedContext.getReturnType(linkedNode);
+ }
if (serializedExecutable != null &&
_declaredReturnType == null &&
_returnType == null) {
@@ -3976,8 +4444,11 @@
@override
FunctionType get type {
+ if (linkedNode != null) {
+ return _type ??= new FunctionTypeImpl(this);
+ }
if (serializedExecutable != null) {
- _type ??= new FunctionTypeImpl(this);
+ return _type ??= new FunctionTypeImpl(this);
}
return _type;
}
@@ -4228,6 +4699,38 @@
/// [name] at the given [offset].
FieldElementImpl(String name, int offset) : super(name, offset);
+ FieldElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode) {
+ if (!linkedNode.isSynthetic) {
+ var enclosingRef = enclosing.reference;
+
+ this.getter = PropertyAccessorElementImpl_ImplicitGetter(
+ this,
+ reference: enclosingRef.getChild('@getter').getChild(name),
+ );
+
+ if (!isConst && !isFinal) {
+ this.setter = PropertyAccessorElementImpl_ImplicitSetter(
+ this,
+ reference: enclosingRef.getChild('@setter').getChild(name),
+ );
+ }
+ }
+ }
+
+ factory FieldElementImpl.forLinkedNodeFactory(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+ if (enclosing.enclosingUnit.linkedContext.isConst(linkedNode)) {
+ return ConstFieldElementImpl.forLinkedNode(
+ enclosing,
+ reference,
+ linkedNode,
+ );
+ }
+ return FieldElementImpl.forLinkedNode(enclosing, reference, linkedNode);
+ }
+
/// Initialize a newly created field element to have the given [name].
FieldElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -4275,6 +4778,9 @@
@override
bool get isStatic {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isStatic(linkedNode);
+ }
if (_unlinkedVariable != null) {
return _unlinkedVariable.isStatic;
}
@@ -4320,6 +4826,10 @@
FieldFormalParameterElementImpl(String name, int nameOffset)
: super(name, nameOffset);
+ FieldFormalParameterElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created parameter element to have the given [name].
FieldFormalParameterElementImpl.forNode(Identifier name)
: super.forNode(name);
@@ -4362,6 +4872,11 @@
@override
DartType get type {
+ if (linkedNode != null) {
+ return _type ??= enclosingUnit.linkedContext.getType(
+ linkedNode.fieldFormalParameter_type2,
+ );
+ }
if (unlinkedParam != null &&
unlinkedParam.type == null &&
!unlinkedParam.isFunctionTyped &&
@@ -4396,6 +4911,10 @@
/// [offset].
FunctionElementImpl(String name, int offset) : super(name, offset);
+ FunctionElementImpl.forLinkedNode(CompilationUnitElementImpl enclosingUnit,
+ Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosingUnit, reference, linkedNode);
+
/// Initialize a newly created function element to have the given [name].
FunctionElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -4447,6 +4966,16 @@
ElementKind get kind => ElementKind.FUNCTION;
@override
+ DartType get returnType {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getType(
+ linkedNode.functionDeclaration_returnType2,
+ );
+ }
+ return super.returnType;
+ }
+
+ @override
SourceRange get visibleRange {
if (serializedExecutable != null) {
if (serializedExecutable.visibleLength == 0) {
@@ -4768,6 +5297,13 @@
: _unlinkedTypedef = null,
super(name, offset);
+ GenericTypeAliasElementImpl.forLinkedNode(
+ CompilationUnitElementImpl enclosingUnit,
+ Reference reference,
+ LinkedNode linkedNode)
+ : _unlinkedTypedef = null,
+ super.forLinkedNode(enclosingUnit, reference, linkedNode);
+
/// Initialize a newly created type alias element to have the given [name].
GenericTypeAliasElementImpl.forNode(Identifier name)
: _unlinkedTypedef = null,
@@ -4799,6 +5335,11 @@
@override
String get documentationComment {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getCommentText(
+ linkedNode.annotatedNode_comment,
+ );
+ }
if (_unlinkedTypedef != null) {
return _unlinkedTypedef.documentationComment?.text;
}
@@ -4818,31 +5359,53 @@
@override
GenericFunctionTypeElementImpl get function {
- if (_function == null) {
- if (_unlinkedTypedef != null) {
- if (_unlinkedTypedef.style == TypedefStyle.genericFunctionType) {
- DartType type = enclosingUnit.resynthesizerContext.resolveTypeRef(
- this, _unlinkedTypedef.returnType,
- declaredType: true);
- if (type is FunctionType) {
- Element element = type.element;
- if (element is GenericFunctionTypeElement) {
- (element as GenericFunctionTypeElementImpl).enclosingElement =
- this;
- _function = element;
- }
+ if (_function != null) return _function;
+
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ _function = new GenericFunctionTypeElementImpl.forOffset(-1);
+ _function.enclosingElement = this;
+ _function.returnType = context.getType(
+ linkedNode.functionTypeAlias_returnType2,
+ );
+ var containerRef = reference.getChild('@parameter');
+ var formalParameters = context.getFormalParameters(linkedNode);
+ _function.parameters = formalParameters.map((node) {
+ var name = context.getFormalParameterName(node);
+ var reference = containerRef.getChild(name);
+ reference.node = node;
+ return ParameterElementImpl.forLinkedNodeFactory(
+ this,
+ reference,
+ node,
+ );
+ }).toList();
+ return _function;
+ }
+
+ if (_unlinkedTypedef != null) {
+ if (_unlinkedTypedef.style == TypedefStyle.genericFunctionType) {
+ DartType type = enclosingUnit.resynthesizerContext.resolveTypeRef(
+ this, _unlinkedTypedef.returnType,
+ declaredType: true);
+ if (type is FunctionType) {
+ Element element = type.element;
+ if (element is GenericFunctionTypeElement) {
+ (element as GenericFunctionTypeElementImpl).enclosingElement = this;
+ _function = element;
}
- } else {
- _function = new GenericFunctionTypeElementImpl.forOffset(-1);
- _function.enclosingElement = this;
- _function.returnType = enclosingUnit.resynthesizerContext
- .resolveTypeRef(_function, _unlinkedTypedef.returnType,
- declaredType: true);
- _function.parameters = ParameterElementImpl.resynthesizeList(
- _unlinkedTypedef.parameters, _function);
}
+ } else {
+ _function = new GenericFunctionTypeElementImpl.forOffset(-1);
+ _function.enclosingElement = this;
+ _function.returnType = enclosingUnit.resynthesizerContext
+ .resolveTypeRef(_function, _unlinkedTypedef.returnType,
+ declaredType: true);
+ _function.parameters = ParameterElementImpl.resynthesizeList(
+ _unlinkedTypedef.parameters, _function);
}
}
+
return _function;
}
@@ -4870,6 +5433,9 @@
@override
String get name {
+ if (linkedNode != null) {
+ return reference.name;
+ }
if (_unlinkedTypedef != null) {
return _unlinkedTypedef.name;
}
@@ -5087,6 +5653,12 @@
_linkedDependency = null,
super(null, offset);
+ ImportElementImpl.forLinkedNode(
+ LibraryElementImpl enclosing, LinkedNode linkedNode)
+ : _unlinkedImport = null,
+ _linkedDependency = null,
+ super.forLinkedNode(enclosing, null, linkedNode);
+
/// Initialize using the given serialized information.
ImportElementImpl.forSerialized(this._unlinkedImport, this._linkedDependency,
LibraryElementImpl enclosingLibrary)
@@ -5114,10 +5686,28 @@
}
@override
+ CompilationUnitElementImpl get enclosingUnit {
+ LibraryElementImpl enclosingLibrary = enclosingElement;
+ return enclosingLibrary._definingCompilationUnit;
+ }
+
+ @override
String get identifier => "${importedLibrary.identifier}@$nameOffset";
@override
LibraryElement get importedLibrary {
+ if (_importedLibrary != null) return _importedLibrary;
+
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ var relativeUriStr = context.getStringContent(
+ linkedNode.uriBasedDirective_uri,
+ );
+ var relativeUri = Uri.parse(relativeUriStr);
+ var uri = resolveRelativeUri(librarySource.uri, relativeUri);
+ var elementFactory = context.bundleContext.elementFactory;
+ return _importedLibrary = elementFactory.libraryOfUri('$uri');
+ }
if (_linkedDependency != null) {
if (_importedLibrary == null) {
LibraryElementImpl library = enclosingElement as LibraryElementImpl;
@@ -5158,6 +5748,11 @@
@override
List<ElementAnnotation> get metadata {
+ if (linkedNode != null) {
+ if (_metadata != null) return _metadata;
+ var metadata = enclosingUnit.linkedContext.getMetadataOrEmpty(linkedNode);
+ return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+ }
if (_metadata == null) {
if (_unlinkedImport != null) {
return _metadata = _buildAnnotations(
@@ -5365,6 +5960,9 @@
final UnlinkedUnit unlinkedDefiningUnit;
+ /// The context of the defining unit.
+ final LinkedUnitContext linkedContext;
+
/// The compilation unit that defines this library.
CompilationUnitElement _definingCompilationUnit;
@@ -5419,14 +6017,32 @@
this.context, this.session, String name, int offset, this.nameLength)
: resynthesizerContext = null,
unlinkedDefiningUnit = null,
+ linkedContext = null,
super(name, offset);
+ LibraryElementImpl.forLinkedNode(
+ this.context,
+ this.session,
+ String name,
+ int offset,
+ this.nameLength,
+ this.linkedContext,
+ Reference reference,
+ LinkedNode linkedNode)
+ : resynthesizerContext = null,
+ unlinkedDefiningUnit = null,
+ super.forLinkedNode(null, reference, linkedNode) {
+ _name = name;
+ _nameOffset = offset;
+ }
+
/// Initialize a newly created library element in the given [context] to have
/// the given [name].
LibraryElementImpl.forNode(this.context, this.session, LibraryIdentifier name)
: nameLength = name != null ? name.length : 0,
resynthesizerContext = null,
unlinkedDefiningUnit = null,
+ linkedContext = null,
super.forNode(name);
/// Initialize using the given serialized information.
@@ -5438,7 +6054,8 @@
this.nameLength,
this.resynthesizerContext,
this.unlinkedDefiningUnit)
- : super.forSerialized(null) {
+ : linkedContext = null,
+ super.forSerialized(null) {
_name = name;
_nameOffset = offset;
setResolutionCapability(
@@ -5612,6 +6229,13 @@
@override
List<ImportElement> get imports {
if (_imports == null) {
+ if (linkedNode != null) {
+ return _imports = linkedNode.compilationUnit_directives
+ .where((node) => node.kind == LinkedNodeKind.importDirective)
+ .map((node) {
+ return ImportElementImpl.forLinkedNode(this, node);
+ }).toList();
+ }
if (unlinkedDefiningUnit != null) {
_imports = buildImportsFromSummary(this, unlinkedDefiningUnit.imports,
resynthesizerContext.linkedLibrary.importDependencies);
@@ -5779,6 +6403,13 @@
@override
List<ElementAnnotation> get metadata {
+ if (linkedNode != null) {
+ if (_metadata != null) return _metadata;
+ CompilationUnitElementImpl enclosingUnit = _definingCompilationUnit;
+ var context = enclosingUnit.linkedContext;
+ var metadata = context.getMetadataOrEmpty(linkedNode);
+ return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+ }
if (_metadata == null) {
if (unlinkedDefiningUnit != null) {
_metadata = _buildAnnotations(
@@ -6163,6 +6794,10 @@
/// given [offset].
MethodElementImpl(String name, int offset) : super(name, offset);
+ MethodElementImpl.forLinkedNode(Reference reference, LinkedNode linkedNode,
+ ClassElementImpl enclosingClass)
+ : super.forLinkedNode(enclosingClass, reference, linkedNode);
+
/// Initialize a newly created method element to have the given [name].
MethodElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -6194,6 +6829,14 @@
super.enclosingElement as ClassElementImpl;
@override
+ bool get isAbstract {
+ if (linkedNode != null) {
+ return !isExternal && enclosingUnit.linkedContext.isAbstract(linkedNode);
+ }
+ return super.isAbstract;
+ }
+
+ @override
bool get isOperator {
String name = displayName;
if (name.isEmpty) {
@@ -6208,6 +6851,9 @@
@override
bool get isStatic {
+ if (linkedNode != null) {
+ return linkedNode.methodDeclaration_modifierKeyword != 0;
+ }
if (serializedExecutable != null) {
return serializedExecutable.isStatic;
}
@@ -6233,6 +6879,16 @@
}
@override
+ DartType get returnType {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getType(
+ linkedNode.methodDeclaration_returnType2,
+ );
+ }
+ return super.returnType;
+ }
+
+ @override
T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
@override
@@ -6772,6 +7428,11 @@
: _unlinkedVariable = null,
super(name, offset);
+ NonParameterVariableElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : _unlinkedVariable = null,
+ super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created variable element to have the given [name].
NonParameterVariableElementImpl.forNode(Identifier name)
: _unlinkedVariable = null,
@@ -6800,6 +7461,11 @@
@override
String get documentationComment {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getCommentText(
+ linkedNode.variableDeclaration_declaration.comment,
+ );
+ }
if (_unlinkedVariable != null) {
return _unlinkedVariable.documentationComment?.text;
}
@@ -6883,6 +7549,11 @@
@override
String get name {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getSimpleName(
+ linkedNode.variableDeclaration_name,
+ );
+ }
if (_unlinkedVariable != null) {
return _unlinkedVariable.name;
}
@@ -6891,6 +7562,11 @@
@override
int get nameOffset {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getSimpleOffset(
+ linkedNode.variableDeclaration_name,
+ );
+ }
int offset = super.nameOffset;
if (offset == 0) {
if (_unlinkedVariable != null) {
@@ -6959,6 +7635,31 @@
: unlinkedParam = null,
super(name, nameOffset);
+ ParameterElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : unlinkedParam = null,
+ super.forLinkedNode(enclosing, reference, linkedNode);
+
+ factory ParameterElementImpl.forLinkedNodeFactory(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+ var kind = linkedNode.kind;
+ if (kind == LinkedNodeKind.fieldFormalParameter) {
+ return FieldFormalParameterElementImpl.forLinkedNode(
+ enclosing,
+ reference,
+ linkedNode,
+ );
+ } else if (kind == LinkedNodeKind.simpleFormalParameter) {
+ return ParameterElementImpl.forLinkedNode(
+ enclosing,
+ reference,
+ linkedNode,
+ );
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ }
+
/// Initialize a newly created parameter element to have the given [name].
ParameterElementImpl.forNode(Identifier name)
: unlinkedParam = null,
@@ -7110,6 +7811,13 @@
@override
bool get isCovariant {
+ if (linkedNode != null) {
+ if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+ var parameter = linkedNode.defaultFormalParameter_parameter;
+ return parameter.normalFormalParameter_isCovariant;
+ }
+ return linkedNode.normalFormalParameter_isCovariant;
+ }
if (isExplicitlyCovariant || inheritsCovariant) {
return true;
}
@@ -7133,6 +7841,16 @@
@override
bool get isFinal {
+ if (linkedNode != null) {
+ if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+ var parameter = linkedNode.defaultFormalParameter_parameter;
+ return parameter.simpleFormalParameter_keyword != 0;
+ }
+ if (linkedNode.kind == LinkedNodeKind.fieldFormalParameter) {
+ return false;
+ }
+ return linkedNode.simpleFormalParameter_keyword != 0;
+ }
if (unlinkedParam != null) {
return unlinkedParam.isFinal;
}
@@ -7168,6 +7886,9 @@
@override
String get name {
+ if (linkedNode != null) {
+ return reference.name;
+ }
if (unlinkedParam != null) {
return unlinkedParam.name;
}
@@ -7176,6 +7897,12 @@
@override
int get nameOffset {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.getSimpleOffset(
+ linkedNode.normalFormalParameter_identifier,
+ );
+ }
+
int offset = super.nameOffset;
if (offset == 0) {
if (unlinkedParam != null) {
@@ -7193,7 +7920,19 @@
@override
ParameterKind get parameterKind {
- if (unlinkedParam != null && _parameterKind == null) {
+ if (_parameterKind != null) return _parameterKind;
+
+ if (linkedNode != null) {
+ if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+ if (linkedNode.defaultFormalParameter_isNamed) {
+ return _parameterKind = ParameterKind.NAMED;
+ } else {
+ return _parameterKind = ParameterKind.POSITIONAL;
+ }
+ }
+ return _parameterKind = ParameterKind.REQUIRED;
+ }
+ if (unlinkedParam != null) {
switch (unlinkedParam.kind) {
case UnlinkedParamKind.named:
_parameterKind = ParameterKind.NAMED;
@@ -7221,6 +7960,18 @@
@override
DartType get type {
+ if (linkedNode != null) {
+ if (_type != null) return _type;
+ if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+ var parameter = linkedNode.defaultFormalParameter_parameter;
+ return _type = enclosingUnit.linkedContext.getType(
+ parameter.simpleFormalParameter_type2,
+ );
+ }
+ return _type = enclosingUnit.linkedContext.getType(
+ linkedNode.simpleFormalParameter_type2,
+ );
+ }
_resynthesizeTypeAndParameters();
return super.type;
}
@@ -7518,6 +8269,10 @@
/// [name] and [offset].
PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
+ PropertyAccessorElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created property accessor element to have the given
/// [name].
PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -7529,8 +8284,9 @@
/// Initialize a newly created synthetic property accessor element to be
/// associated with the given [variable].
- PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable)
- : super(variable.name, variable.nameOffset) {
+ PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable,
+ {Reference reference})
+ : super(variable.name, variable.nameOffset, reference: reference) {
this.variable = variable;
isStatic = variable.isStatic;
isSynthetic = true;
@@ -7587,7 +8343,18 @@
}
@override
+ bool get isAbstract {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isAbstract(linkedNode);
+ }
+ return super.isAbstract;
+ }
+
+ @override
bool get isGetter {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isGetter(linkedNode);
+ }
if (serializedExecutable != null) {
return serializedExecutable.kind == UnlinkedExecutableKind.getter;
}
@@ -7596,6 +8363,9 @@
@override
bool get isSetter {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isSetter(linkedNode);
+ }
if (serializedExecutable != null) {
return serializedExecutable.kind == UnlinkedExecutableKind.setter;
}
@@ -7604,6 +8374,9 @@
@override
bool get isStatic {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isStatic(linkedNode);
+ }
if (serializedExecutable != null) {
return serializedExecutable.isStatic ||
variable is TopLevelVariableElement;
@@ -7627,6 +8400,9 @@
@override
String get name {
+ if (linkedNode != null) {
+ return reference.name;
+ }
if (serializedExecutable != null) {
return serializedExecutable.name;
}
@@ -7673,8 +8449,9 @@
extends PropertyAccessorElementImpl {
/// Create the implicit getter and bind it to the [property].
PropertyAccessorElementImpl_ImplicitGetter(
- PropertyInducingElementImpl property)
- : super.forVariable(property) {
+ PropertyInducingElementImpl property,
+ {Reference reference})
+ : super.forVariable(property, reference: reference) {
property.getter = this;
enclosingElement = property.enclosingElement;
}
@@ -7709,8 +8486,9 @@
extends PropertyAccessorElementImpl {
/// Create the implicit setter and bind it to the [property].
PropertyAccessorElementImpl_ImplicitSetter(
- PropertyInducingElementImpl property)
- : super.forVariable(property) {
+ PropertyInducingElementImpl property,
+ {Reference reference})
+ : super.forVariable(property, reference: reference) {
property.setter = this;
enclosingElement = property.enclosingElement;
}
@@ -7759,6 +8537,10 @@
/// [offset].
PropertyInducingElementImpl(String name, int offset) : super(name, offset);
+ PropertyInducingElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created element to have the given [name].
PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -7779,6 +8561,12 @@
@override
DartType get type {
+ if (linkedNode != null) {
+ if (_type != null) return _type;
+ return _type = enclosingUnit.linkedContext.getType(
+ linkedNode.variableDeclaration_type2,
+ );
+ }
if (isSynthetic && _type == null) {
if (getter != null) {
_type = getter.returnType;
@@ -7950,6 +8738,42 @@
/// the given [name] and [offset].
TopLevelVariableElementImpl(String name, int offset) : super(name, offset);
+ TopLevelVariableElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode) {
+ if (!linkedNode.isSynthetic) {
+ var enclosingRef = enclosing.reference;
+
+ this.getter = PropertyAccessorElementImpl_ImplicitGetter(
+ this,
+ reference: enclosingRef.getChild('@getter').getChild(name),
+ );
+
+ if (!isConst && !isFinal) {
+ this.setter = PropertyAccessorElementImpl_ImplicitSetter(
+ this,
+ reference: enclosingRef.getChild('@setter').getChild(name),
+ );
+ }
+ }
+ }
+
+ factory TopLevelVariableElementImpl.forLinkedNodeFactory(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+ if (enclosing.enclosingUnit.linkedContext.isConst(linkedNode)) {
+ return ConstTopLevelVariableElementImpl.forLinkedNode(
+ enclosing,
+ reference,
+ linkedNode,
+ );
+ }
+ return TopLevelVariableElementImpl.forLinkedNode(
+ enclosing,
+ reference,
+ linkedNode,
+ );
+ }
+
/// Initialize a newly created top-level variable element to have the given
/// [name].
TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -7996,6 +8820,13 @@
: _unlinkedTypeParam = null,
super(name, offset);
+ TypeParameterElementImpl.forLinkedNode(
+ TypeParameterizedElementMixin enclosing,
+ Reference reference,
+ LinkedNode linkedNode)
+ : _unlinkedTypeParam = null,
+ super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created type parameter element to have the given
/// [name].
TypeParameterElementImpl.forNode(Identifier name)
@@ -8016,16 +8847,27 @@
}
DartType get bound {
- if (_bound == null) {
- if (_unlinkedTypeParam != null) {
- if (_unlinkedTypeParam.bound == null) {
- return null;
- }
- _bound = enclosingUnit.resynthesizerContext.resolveTypeRef(
- this, _unlinkedTypeParam.bound,
- instantiateToBoundsAllowed: false, declaredType: true);
+ if (_bound != null) return _bound;
+
+ if (linkedNode != null) {
+ var bound = linkedNode.typeParameter_bound;
+ if (bound != null) {
+ var context = enclosingUnit.linkedContext;
+ return _bound = context.getTypeAnnotationType(bound);
+ } else {
+ return null;
}
}
+
+ if (_unlinkedTypeParam != null) {
+ if (_unlinkedTypeParam.bound == null) {
+ return null;
+ }
+ return _bound = enclosingUnit.resynthesizerContext.resolveTypeRef(
+ this, _unlinkedTypeParam.bound,
+ instantiateToBoundsAllowed: false, declaredType: true);
+ }
+
return _bound;
}
@@ -8067,6 +8909,9 @@
@override
String get name {
+ if (linkedNode != null) {
+ return reference.name;
+ }
if (_unlinkedTypeParam != null) {
return _unlinkedTypeParam.name;
}
@@ -8083,6 +8928,9 @@
}
TypeParameterType get type {
+ if (linkedNode != null) {
+ _type ??= new TypeParameterTypeImpl(this);
+ }
if (_unlinkedTypeParam != null) {
_type ??= new TypeParameterTypeImpl(this);
}
@@ -8133,19 +8981,34 @@
@override
List<TypeParameterElement> get typeParameters {
- if (_typeParameterElements == null) {
- List<UnlinkedTypeParam> unlinkedParams = unlinkedTypeParams;
- if (unlinkedParams != null) {
- int numTypeParameters = unlinkedParams.length;
- _typeParameterElements =
- new List<TypeParameterElement>(numTypeParameters);
- for (int i = 0; i < numTypeParameters; i++) {
- _typeParameterElements[i] =
- new TypeParameterElementImpl.forSerialized(
- unlinkedParams[i], this);
- }
+ if (_typeParameterElements != null) return _typeParameterElements;
+
+ if (linkedNode != null) {
+ var context = enclosingUnit.linkedContext;
+ var containerRef = reference.getChild('@typeParameter');
+ var typeParameters = context.getTypeParameters(linkedNode);
+ if (typeParameters == null) {
+ return _typeParameterElements = const [];
+ }
+ return _typeParameterElements = typeParameters.map((node) {
+ var name = context.getSimpleName(node.typeParameter_name);
+ var reference = containerRef.getChild(name);
+ reference.node = node;
+ return TypeParameterElementImpl.forLinkedNode(this, reference, node);
+ }).toList();
+ }
+
+ List<UnlinkedTypeParam> unlinkedParams = unlinkedTypeParams;
+ if (unlinkedParams != null) {
+ int numTypeParameters = unlinkedParams.length;
+ _typeParameterElements =
+ new List<TypeParameterElement>(numTypeParameters);
+ for (int i = 0; i < numTypeParameters; i++) {
+ _typeParameterElements[i] =
+ new TypeParameterElementImpl.forSerialized(unlinkedParams[i], this);
}
}
+
return _typeParameterElements ?? const <TypeParameterElement>[];
}
@@ -8243,6 +9106,10 @@
/// [offset]. The offset may be `-1` if the element is synthetic.
UriReferencedElementImpl(String name, int offset) : super(name, offset);
+ UriReferencedElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize using the given serialized information.
UriReferencedElementImpl.forSerialized(ElementImpl enclosingElement)
: super.forSerialized(enclosingElement);
@@ -8303,6 +9170,10 @@
/// [offset].
VariableElementImpl(String name, int offset) : super(name, offset);
+ VariableElementImpl.forLinkedNode(
+ ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+ : super.forLinkedNode(enclosing, reference, linkedNode);
+
/// Initialize a newly created variable element to have the given [name].
VariableElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -8366,6 +9237,9 @@
@override
bool get isConst {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isConst(linkedNode);
+ }
return hasModifier(Modifier.CONST);
}
@@ -8379,6 +9253,9 @@
@override
bool get isFinal {
+ if (linkedNode != null) {
+ return enclosingUnit.linkedContext.isFinal(linkedNode);
+ }
return hasModifier(Modifier.FINAL);
}
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 1d45edd..62e8d17 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -163,6 +163,8 @@
'EXPECTED_CLASS_MEMBER', "Expected a class member.",
correction: "Try placing this code inside a class member.");
+ static const ParserErrorCode EXPECTED_ELSE_OR_COMMA = _EXPECTED_ELSE_OR_COMMA;
+
static const ParserErrorCode EXPECTED_EXECUTABLE = const ParserErrorCode(
'EXPECTED_EXECUTABLE',
"Expected a method, getter, setter or operator declaration.",
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index c4a7f45..fd3008b 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -101,6 +101,7 @@
_STACK_OVERFLOW,
_MISSING_CATCH_OR_FINALLY,
_EXPERIMENT_NOT_ENABLED,
+ _EXPECTED_ELSE_OR_COMMA,
];
const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -239,6 +240,9 @@
r"An equality expression can't be an operand of another equality expression.",
correction: "Try re-writing the expression.");
+const ParserErrorCode _EXPECTED_ELSE_OR_COMMA = const ParserErrorCode(
+ 'EXPECTED_ELSE_OR_COMMA', r"Expected 'else' or comma.");
+
const ParserErrorCode _EXPECTED_INSTEAD = const ParserErrorCode(
'EXPECTED_INSTEAD', r"Expected '#string' instead of this.");
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index adb3a99..b1161d4 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -213,6 +213,26 @@
correction: "Try removing the export of one of the libraries, or "
"explicitly hiding the name in one of the export directives.");
+ static const CompileTimeErrorCode AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH =
+ const CompileTimeErrorCode(
+ 'AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH',
+ "This literal must be both a map and a set, because some elements "
+ "spread a 'Map' and others spread an 'Iterable', but that isn't "
+ "allowed.",
+ correction:
+ "Try removing or changing some of the elements so that all of "
+ "the elements are consistent.");
+
+ static const CompileTimeErrorCode AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER =
+ const CompileTimeErrorCode(
+ 'AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER',
+ "This literal must be either a map or a set, but none of the "
+ "elements have enough type information to know which, and that isn't "
+ "allowed.",
+ correction:
+ "Try adding type arguments to the literal (one for sets, two "
+ "for maps).");
+
/**
* 15 Metadata: The constant expression given in an annotation is type checked
* and evaluated in the scope surrounding the declaration being annotated.
@@ -634,6 +654,14 @@
correction:
"Try declaring the field as final, or adding the keyword 'static'.");
+ static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_LIST_OR_SET =
+ const CompileTimeErrorCode('CONST_SPREAD_EXPECTED_LIST_OR_SET',
+ "A list or a set is expected in this spread.");
+
+ static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_MAP =
+ const CompileTimeErrorCode(
+ 'CONST_SPREAD_EXPECTED_MAP', "A map is expected in this spread.");
+
/**
* 12.8 Maps: It is a compile-time error if the key of an entry in a constant
* map literal is an instance of a class that implements the operator
@@ -973,6 +1001,12 @@
"The exported library '{0}' can't have a part-of directive.",
correction: "Try exporting the library that the part is a part of.");
+ static const CompileTimeErrorCode EXPRESSION_IN_MAP =
+ const CompileTimeErrorCode(
+ 'EXPRESSION_IN_MAP', "Expressions cannot be used in a map literal.",
+ correction:
+ "Try removing the expression or converting it to be a map entry.");
+
/**
* 7.9 Superclasses: It is a compile-time error if the extends clause of a
* class <i>C</i> includes a type expression that does not denote a class
@@ -1691,6 +1725,12 @@
correction: "Try defining the label, or "
"correcting the name to match an existing label.");
+ static const CompileTimeErrorCode MAP_ENTRY_NOT_IN_MAP =
+ const CompileTimeErrorCode('MAP_ENTRY_NOT_IN_MAP',
+ "Map entries can only be used in a map literal.",
+ correction:
+ "Try converting the collection to a map or removing the map entry.");
+
/**
* 7 Classes: It is a compile time error if a class <i>C</i> declares a member
* with the same name as <i>C</i>.
@@ -2239,6 +2279,14 @@
"{0} required argument(s) expected, but {1} found.",
correction: "Try adding the missing arguments.");
+ static const CompileTimeErrorCode NOT_ITERABLE_SPREAD =
+ const CompileTimeErrorCode('NOT_ITERABLE_SPREAD',
+ "Spread elements in list or set literals must implement 'Iterable'.");
+
+ static const CompileTimeErrorCode NOT_MAP_SPREAD = const CompileTimeErrorCode(
+ 'NOT_MAP_SPREAD',
+ "Spread elements in map literals must implement 'Map'.");
+
/**
* 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the
* superinitializer appears and let <i>S</i> be the superclass of <i>C</i>.
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
new file mode 100644
index 0000000..29b65b9
--- /dev/null
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -0,0 +1,203 @@
+// Copyright (c) 2019, 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/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// Verifier for [CollectionElement]s in list, set, or map literals.
+class LiteralElementVerifier {
+ final TypeProvider typeProvider;
+ final TypeSystem typeSystem;
+ final ErrorReporter errorReporter;
+ final bool Function(Expression) checkForUseOfVoidResult;
+
+ final bool forList;
+ final bool forSet;
+ final DartType elementType;
+
+ final bool forMap;
+ final DartType mapKeyType;
+ final DartType mapValueType;
+
+ LiteralElementVerifier(
+ this.typeProvider,
+ this.typeSystem,
+ this.errorReporter,
+ this.checkForUseOfVoidResult, {
+ this.forList = false,
+ this.forSet = false,
+ this.elementType,
+ this.forMap = false,
+ this.mapKeyType,
+ this.mapValueType,
+ });
+
+ void verify(CollectionElement element) {
+ _verifyElement(element);
+ }
+
+ /// Check that the given [type] is assignable to the [elementType], otherwise
+ /// report the list or set error on the [errorNode].
+ void _checkAssignableToElementType(DartType type, AstNode errorNode) {
+ if (!typeSystem.isAssignableTo(type, elementType)) {
+ var errorCode = forList
+ ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+ : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
+ errorReporter.reportTypeErrorForNode(
+ errorCode,
+ errorNode,
+ [type, elementType],
+ );
+ }
+ }
+
+ /// Verify that the given [element] can be assigned to the [elementType] of
+ /// the enclosing list, set, of map literal.
+ void _verifyElement(CollectionElement element) {
+ if (element is Expression) {
+ if (forList || forSet) {
+ if (!elementType.isVoid && checkForUseOfVoidResult(element)) {
+ return;
+ }
+ _checkAssignableToElementType(element.staticType, element);
+ } else {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.EXPRESSION_IN_MAP, element);
+ }
+ } else if (element is ForElement) {
+ _verifyElement(element.body);
+ } else if (element is IfElement) {
+ _verifyElement(element.thenElement);
+ _verifyElement(element.elseElement);
+ } else if (element is MapLiteralEntry) {
+ if (forMap) {
+ _verifyMapLiteralEntry(element);
+ } else {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, element);
+ }
+ } else if (element is SpreadElement) {
+ Expression expression = element.expression;
+ if (forList || forSet) {
+ _verifySpreadForListOrSet(expression);
+ } else if (forMap) {
+ _verifySpreadForMap(expression);
+ }
+ }
+ }
+
+ /// Verify that the [entry]'s key and value are assignable to [mapKeyType]
+ /// and [mapValueType].
+ void _verifyMapLiteralEntry(MapLiteralEntry entry) {
+ if (!mapKeyType.isVoid && checkForUseOfVoidResult(entry.key)) {
+ return;
+ }
+
+ if (!mapValueType.isVoid && checkForUseOfVoidResult(entry.value)) {
+ return;
+ }
+
+ var keyType = entry.key.staticType;
+ if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+ errorReporter.reportTypeErrorForNode(
+ StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+ entry.key,
+ [keyType, mapKeyType],
+ );
+ }
+
+ var valueType = entry.value.staticType;
+ if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+ errorReporter.reportTypeErrorForNode(
+ StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
+ entry.value,
+ [valueType, mapValueType],
+ );
+ }
+ }
+
+ /// Verify that the type of the elements of the given [expression] can be
+ /// assigned to the [elementType] of the enclosing collection.
+ void _verifySpreadForListOrSet(Expression expression) {
+ var expressionType = expression.staticType;
+ if (expressionType.isDynamic) return;
+
+ // TODO(scheglov) Check for non-null-aware spread?
+ if (expressionType.isDartCoreNull) return;
+
+ InterfaceType iterableType;
+ var iterableObjectType = typeProvider.iterableObjectType;
+ if (expressionType is InterfaceTypeImpl &&
+ typeSystem.isSubtypeOf(expressionType, iterableObjectType)) {
+ iterableType = expressionType.asInstanceOf(
+ iterableObjectType.element,
+ );
+ }
+
+ if (iterableType == null) {
+ return errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
+ expression,
+ );
+ }
+
+ var iterableElementType = iterableType.typeArguments[0];
+ if (!typeSystem.isAssignableTo(iterableElementType, elementType)) {
+ var errorCode = forList
+ ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+ : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
+ errorReporter.reportTypeErrorForNode(
+ errorCode,
+ expression,
+ [iterableElementType, elementType],
+ );
+ }
+ }
+
+ /// Verify that the [expression] is a subtype of `Map<Object, Object>`, and
+ /// its key and values are assignable to [mapKeyType] and [mapValueType].
+ void _verifySpreadForMap(Expression expression) {
+ var expressionType = expression.staticType;
+ if (expressionType.isDynamic) return;
+
+ // TODO(scheglov) Check for non-null-aware spread?
+ if (expressionType.isDartCoreNull) return;
+
+ InterfaceType mapType;
+ var mapObjectObjectType = typeProvider.mapObjectObjectType;
+ if (expressionType is InterfaceTypeImpl &&
+ typeSystem.isSubtypeOf(expressionType, mapObjectObjectType)) {
+ mapType = expressionType.asInstanceOf(mapObjectObjectType.element);
+ }
+
+ if (mapType == null) {
+ return errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.NOT_MAP_SPREAD,
+ expression,
+ );
+ }
+
+ var keyType = mapType.typeArguments[0];
+ if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+ errorReporter.reportTypeErrorForNode(
+ StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+ expression,
+ [keyType, mapKeyType],
+ );
+ }
+
+ var valueType = mapType.typeArguments[1];
+ if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+ errorReporter.reportTypeErrorForNode(
+ StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
+ expression,
+ [valueType, mapValueType],
+ );
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 808478c..55671cc 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -25,7 +25,6 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/timestamped_data.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:analyzer/src/plugin/engine_plugin.dart';
import 'package:analyzer/src/plugin/resolver_provider.dart';
import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer/src/summary/api_signature.dart';
@@ -34,8 +33,6 @@
import 'package:analyzer/src/task/manager.dart';
import 'package:front_end/src/fasta/scanner/token.dart';
import 'package:path/path.dart' as pathos;
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
import 'package:pub_semver/pub_semver.dart';
export 'package:analyzer/error/listener.dart' show RecordingErrorListener;
@@ -747,12 +744,6 @@
Logger _logger = Logger.NULL;
/**
- * The plugin that defines the extension points and extensions that are
- * inherently defined by the analysis engine.
- */
- final EnginePlugin enginePlugin = new EnginePlugin();
-
- /**
* The instrumentation service that is to be used by this analysis engine.
*/
InstrumentationService _instrumentationService =
@@ -803,13 +794,6 @@
}
/**
- * Return the list of plugins that clients are required to process, either by
- * creating an [ExtensionManager] or by using the method
- * [processRequiredPlugins].
- */
- List<Plugin> get requiredPlugins => <Plugin>[enginePlugin];
-
- /**
* Return the task manager used to manage the tasks used to analyze code.
*/
TaskManager get taskManager {
@@ -841,12 +825,8 @@
* plugins. This method can only be used by clients that do not need to
* process any other plugins.
*/
- void processRequiredPlugins() {
- if (enginePlugin.workManagerFactoryExtensionPoint == null) {
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(requiredPlugins);
- }
- }
+ @deprecated
+ void processRequiredPlugins() {}
/**
* Return `true` if the given [fileName] is an analysis options file.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 48f58c6..50697a0 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -15,11 +15,13 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/error/literal_element_verifier.dart';
import 'package:analyzer/src/error/pending_error.dart';
import 'package:analyzer/src/generated/element_resolver.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -28,7 +30,6 @@
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/dart.dart';
/**
* A visitor used to traverse an AST structure looking for additional errors and
@@ -740,13 +741,6 @@
}
@override
- @deprecated
- void visitForEachStatement(ForEachStatement node) {
- _checkForInIterable(node);
- super.visitForEachStatement(node);
- }
-
- @override
void visitFormalParameterList(FormalParameterList node) {
_checkDuplicateDefinitionInParameterList(node);
_checkUseOfCovariantInParameters(node);
@@ -773,18 +767,6 @@
}
@override
- @deprecated
- void visitForStatement(ForStatement node) {
- if (node.condition != null) {
- _checkForNonBoolCondition(node.condition);
- }
- if (node.variables != null) {
- _checkDuplicateVariables(node.variables);
- }
- super.visitForStatement(node);
- }
-
- @override
void visitFunctionDeclaration(FunctionDeclaration node) {
ExecutableElement functionElement = node.declaredElement;
if (functionElement != null &&
@@ -913,6 +895,12 @@
}
@override
+ void visitIfElement(IfElement node) {
+ _checkForNonBoolCondition(node.condition);
+ super.visitIfElement(node);
+ }
+
+ @override
void visitIfStatement(IfStatement node) {
_checkForNonBoolCondition(node.condition);
super.visitIfStatement(node);
@@ -1014,28 +1002,6 @@
}
@override
- @deprecated
- void visitMapLiteral(MapLiteral node) {
- TypeArgumentList typeArguments = node.typeArguments;
- if (typeArguments != null) {
- NodeList<TypeAnnotation> arguments = typeArguments.arguments;
- if (arguments.isNotEmpty) {
- if (node.isConst) {
- _checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
- CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP);
- }
- }
- _checkTypeArgumentCount(typeArguments, 2,
- StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS);
- }
- _checkForRawTypedLiteral(node);
- _checkForImplicitDynamicTypedLiteral(node);
- _checkForMapTypeNotAssignable(node);
- _checkForNonConstMapAsExpressionStatement(node);
- super.visitMapLiteral(node);
- }
-
- @override
void visitMethodDeclaration(MethodDeclaration node) {
ExecutableElement previousFunction = _enclosingFunction;
try {
@@ -1221,28 +1187,6 @@
}
@override
- @deprecated
- void visitSetLiteral(SetLiteral node) {
- TypeArgumentList typeArguments = node.typeArguments;
- if (typeArguments != null) {
- if (node.isConst) {
- NodeList<TypeAnnotation> arguments = typeArguments.arguments;
- if (arguments.isNotEmpty) {
- _checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
- CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET);
- }
- }
- _checkTypeArgumentCount(typeArguments, 1,
- StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS);
- }
- _checkForRawTypedLiteral(node);
- _checkForImplicitDynamicTypedLiteral(node);
- _checkForSetElementTypeNotAssignable(node);
-
- super.visitSetLiteral(node);
- }
-
- @override
void visitSetOrMapLiteral(SetOrMapLiteral node) {
TypeArgumentList typeArguments = node.typeArguments;
if (node.isMap) {
@@ -1259,7 +1203,7 @@
}
_checkForRawTypedLiteral(node);
_checkForImplicitDynamicTypedLiteral(node);
- _checkForMapTypeNotAssignable3(node);
+ _checkForMapTypeNotAssignable(node);
_checkForNonConstMapAsExpressionStatement3(node);
} else if (node.isSet) {
if (typeArguments != null) {
@@ -2284,63 +2228,6 @@
}
/**
- * Verify that the type of the elements of the given [spreadExpression] (the
- * [spreadExpressionType]) can be assigned to the element type of the
- * enclosing collection (the [elementType]). If not, report an error with the
- * given [errorCode].
- */
- void _checkForArgumentTypeNotAssignableInSpread(
- Expression spreadExpression,
- DartType spreadExpressionType,
- DartType elementType,
- ErrorCode errorCode) {
- if (spreadExpressionType != null && elementType != null) {
- if (!elementType.isVoid && _checkForUseOfVoidResult(spreadExpression)) {
- return;
- }
- if (spreadExpressionType is InterfaceType) {
- if (_typeSystem.isSubtypeOf(
- spreadExpressionType, _typeProvider.iterableObjectType)) {
- InterfaceType iterableType =
- (spreadExpressionType as InterfaceTypeImpl)
- .asInstanceOf(_typeProvider.iterableType.element);
- if (iterableType != null) {
- // The `iterableType` will be `null` when `spreadExpressionType` is
- // `Null`. Fall through in that case to perform the default type
- // check.
- List<DartType> typeArguments = iterableType.typeArguments;
- if (typeArguments.length == 1) {
- _checkForAssignableExpressionAtType(
- spreadExpression, typeArguments[0], elementType, errorCode);
- return;
- }
- }
- } else if (_typeSystem.isSubtypeOf(
- spreadExpressionType, _typeProvider.mapObjectObjectType)) {
- // TODO(brianwilkerson) Handle spreads involving maps? This method
- // isn't currently called for maps, but might be if it's reworked as
- // expected.
-// InterfaceType mapType =
-// (spreadExpressionType as InterfaceTypeImpl)
-// .asInstanceOf(_typeProvider.mapType.element);
-// if (mapType != null) {
-// List<DartType> typeArguments = mapType.typeArguments;
-// if (typeArguments.length == 2) {
-// _checkForAssignableExpressionAtType(
-// spreadExpression, typeArguments[0], keyType, errorCode);
-// _checkForAssignableExpressionAtType(
-// spreadExpression, typeArguments[1], valueType, errorCode);
-// return;
-// }
-// }
- }
- }
- _checkForAssignableExpressionAtType(
- spreadExpression, spreadExpressionType, elementType, errorCode);
- }
- }
-
- /**
* Verify that the given [expression] can be assigned to its corresponding
* parameters. The [expectedStaticType] is the expected static type.
*
@@ -2599,34 +2486,6 @@
}
/**
- * Verify that the given [element] can be assigned to the [elementType] of the
- * enclosing list or set literal. Report an error with the given [errorCode]
- * if not.
- *
- * This method corresponds to
- * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes].
- */
- void _checkForCollectionElementTypeNotAssignableWithElementType(
- CollectionElement element, DartType elementType, ErrorCode errorCode) {
- if (element is ForElement) {
- _checkForCollectionElementTypeNotAssignableWithElementType(
- element.body, elementType, errorCode);
- } else if (element is IfElement) {
- _checkForCollectionElementTypeNotAssignableWithElementType(
- element.thenElement, elementType, errorCode);
- _checkForCollectionElementTypeNotAssignableWithElementType(
- element.elseElement, elementType, errorCode);
- } else if (element is Expression) {
- _checkForArgumentTypeNotAssignable(
- element, elementType, getStaticType(element), errorCode);
- } else if (element is SpreadElement) {
- Expression expression = element.expression;
- _checkForArgumentTypeNotAssignableInSpread(
- expression, getStaticType(expression), elementType, errorCode);
- }
- }
-
- /**
* Verify that the [_enclosingClass] does not have a method and getter pair
* with the same name on, via inheritance.
*
@@ -3808,84 +3667,6 @@
}
/**
- * Check for a type mis-match between the iterable expression and the
- * assigned variable in a for-in statement.
- */
- @deprecated
- void _checkForInIterable(ForEachStatement node) {
- DeclaredIdentifier loopVariable = node.loopVariable;
-
- // Ignore malformed for statements.
- if (node.identifier == null && loopVariable == null) {
- return;
- }
-
- if (_checkForNullableDereference(node.iterable)) {
- return;
- }
-
- if (_checkForUseOfVoidResult(node.iterable)) {
- return;
- }
-
- DartType iterableType = getStaticType(node.iterable);
- if (iterableType.isDynamic) {
- return;
- }
-
- // The type of the loop variable.
- SimpleIdentifier variable = node.identifier ?? loopVariable.identifier;
- DartType variableType = getStaticType(variable);
-
- DartType loopType = node.awaitKeyword != null
- ? _typeProvider.streamType
- : _typeProvider.iterableType;
-
- // Use an explicit string instead of [loopType] to remove the "<E>".
- String loopTypeName = node.awaitKeyword != null ? "Stream" : "Iterable";
-
- // The object being iterated has to implement Iterable<T> for some T that
- // is assignable to the variable's type.
- // TODO(rnystrom): Move this into mostSpecificTypeArgument()?
- iterableType = iterableType.resolveToBound(_typeProvider.objectType);
- DartType bestIterableType =
- _typeSystem.mostSpecificTypeArgument(iterableType, loopType);
-
- // Allow it to be a supertype of Iterable<T> (basically just Object) and do
- // an implicit downcast to Iterable<dynamic>.
- if (bestIterableType == null) {
- if (_typeSystem.isSubtypeOf(loopType, iterableType)) {
- bestIterableType = DynamicTypeImpl.instance;
- }
- }
-
- if (loopVariable != null) {
- if (loopVariable.isConst) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, loopVariable);
- }
- } else if (node.identifier != null) {
- Element variableElement = node.identifier.staticElement;
- if (variableElement is VariableElement && variableElement.isConst) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, node.identifier);
- }
- }
-
- if (bestIterableType == null) {
- _errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
- node.iterable,
- [iterableType, loopTypeName]);
- } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) {
- _errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
- node.iterable,
- [iterableType, loopTypeName, variableType]);
- }
- }
-
- /**
* Check that the given [typeReference] is not a type reference and that then
* the [name] is reference to an instance member.
*
@@ -4082,131 +3863,20 @@
DartType listElementType = typeArguments[0];
// Check every list element.
- bool isConst = literal.isConst;
+ var verifier = LiteralElementVerifier(
+ _typeProvider,
+ _typeSystem,
+ _errorReporter,
+ _checkForUseOfVoidResult,
+ forList: true,
+ elementType: listElementType,
+ );
for (CollectionElement element in literal.elements2) {
- if (isConst) {
- // TODO(paulberry): this error should be based on the actual type of the
- // list element, not the static type. See dartbug.com/21119.
- _checkForCollectionElementTypeNotAssignableWithElementType(
- element,
- listElementType,
- CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
- } else {
- _checkForCollectionElementTypeNotAssignableWithElementType(
- element,
- listElementType,
- StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
- }
+ verifier.verify(element);
}
}
- /**
- * Verify that the given [element] can be assigned to the [elementType] of the
- * enclosing list or set literal. Report an error with the given [errorCode]
- * if not.
- *
- * This method corresponds to
- * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes].
- */
- void _checkForMapElementTypeNotAssignableWithKeyOrValueType(
- CollectionElement element,
- DartType keyType,
- DartType valueType,
- ErrorCode keyErrorCode,
- ErrorCode valueErrorCode) {
- if (element is ForElement) {
- _checkForMapElementTypeNotAssignableWithKeyOrValueType(
- element.body, keyType, valueType, keyErrorCode, valueErrorCode);
- } else if (element is IfElement) {
- _checkForMapElementTypeNotAssignableWithKeyOrValueType(
- element.thenElement,
- keyType,
- valueType,
- keyErrorCode,
- valueErrorCode);
- _checkForMapElementTypeNotAssignableWithKeyOrValueType(
- element.elseElement,
- keyType,
- valueType,
- keyErrorCode,
- valueErrorCode);
- } else if (element is MapLiteralEntry) {
- _checkForArgumentTypeNotAssignableWithExpectedTypes(
- element.key, keyType, keyErrorCode);
- _checkForArgumentTypeNotAssignableWithExpectedTypes(
- element.value, valueType, valueErrorCode);
- } else if (element is SpreadElement) {
- Expression expression = element.expression;
- DartType expressionType = getStaticType(expression);
- if (expressionType is ParameterizedType) {
- List<DartType> typeArguments = expressionType.typeArguments;
- if (typeArguments.length == 2) {
- _checkForArgumentTypeNotAssignable(
- expression, keyType, typeArguments[0], keyErrorCode);
- _checkForArgumentTypeNotAssignable(
- expression, valueType, typeArguments[1], valueErrorCode);
- }
- }
- }
- }
-
- /**
- * Verify that the key/value of entries of the given map [literal] are
- * subtypes of the map's static type.
- *
- * See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE],
- * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE],
- * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
- * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
- */
- @deprecated
- void _checkForMapTypeNotAssignable(MapLiteral literal) {
- // Determine the map's key and value types. We base this on the static type
- // and not the literal's type arguments because in strong mode, the type
- // arguments may be inferred.
- DartType mapType = literal.staticType;
- if (mapType == null) {
- // This is known to happen when the literal is the default value in an
- // optional parameter in a generic function type alias.
- return;
- }
- assert(mapType is InterfaceTypeImpl);
-
- List<DartType> typeArguments = (mapType as InterfaceTypeImpl).typeArguments;
- assert(typeArguments.length == 2);
- DartType keyType = typeArguments[0];
- DartType valueType = typeArguments[1];
-
- bool isConst = literal.isConst;
- NodeList<MapLiteralEntry> entries = literal.entries;
- for (MapLiteralEntry entry in entries) {
- Expression key = entry.key;
- Expression value = entry.value;
- if (isConst) {
- // TODO(paulberry): this error should be based on the actual type of the
- // list element, not the static type. See dartbug.com/21119.
- _checkForArgumentTypeNotAssignableWithExpectedTypes(key, keyType,
- CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE);
- _checkForArgumentTypeNotAssignableWithExpectedTypes(value, valueType,
- CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
- }
- _checkForArgumentTypeNotAssignableWithExpectedTypes(
- key, keyType, StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE);
- _checkForArgumentTypeNotAssignableWithExpectedTypes(
- value, valueType, StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
- }
- }
-
- /**
- * Verify that the key/value of entries of the given map [literal] are
- * subtypes of the map's static type.
- *
- * See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE],
- * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE],
- * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
- * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
- */
- void _checkForMapTypeNotAssignable3(SetOrMapLiteral literal) {
+ void _checkForMapTypeNotAssignable(SetOrMapLiteral literal) {
// Determine the map's key and value types. We base this on the static type
// and not the literal's type arguments because in strong mode, the type
// arguments may be inferred.
@@ -4227,26 +3897,17 @@
DartType keyType = typeArguments[0];
DartType valueType = typeArguments[1];
- bool isConst = literal.isConst;
- NodeList<CollectionElement> entries = literal.elements2;
- for (CollectionElement entry in entries) {
- if (isConst) {
- // TODO(paulberry): this error should be based on the actual type of
- // the map entries, not the static type. See dartbug.com/21119.
- _checkForMapElementTypeNotAssignableWithKeyOrValueType(
- entry,
- keyType,
- valueType,
- CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
- CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
- } else {
- _checkForMapElementTypeNotAssignableWithKeyOrValueType(
- entry,
- keyType,
- valueType,
- StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
- StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
- }
+ var verifier = LiteralElementVerifier(
+ _typeProvider,
+ _typeSystem,
+ _errorReporter,
+ _checkForUseOfVoidResult,
+ forMap: true,
+ mapKeyType: keyType,
+ mapValueType: valueType,
+ );
+ for (CollectionElement element in literal.elements2) {
+ verifier.verify(element);
}
}
}
@@ -4815,38 +4476,6 @@
*
* See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT].
*/
- @deprecated
- void _checkForNonConstMapAsExpressionStatement(MapLiteral literal) {
- // "const"
- if (literal.constKeyword != null) {
- return;
- }
- // has type arguments
- if (literal.typeArguments != null) {
- return;
- }
- // prepare statement
- Statement statement = literal.thisOrAncestorOfType<ExpressionStatement>();
- if (statement == null) {
- return;
- }
- // OK, statement does not start with map
- if (!identical(statement.beginToken, literal.beginToken)) {
- return;
- }
-
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT, literal);
- }
-
- /**
- * Verify the given map [literal] either:
- * * has `const modifier`
- * * has explicit type arguments
- * * is not start of the statement
- *
- * See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT].
- */
void _checkForNonConstMapAsExpressionStatement3(SetOrMapLiteral literal) {
// "const"
if (literal.constKeyword != null) {
@@ -5475,42 +5104,6 @@
* See [CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE], and
* [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE].
*/
- @deprecated
- void _checkForSetElementTypeNotAssignable(SetLiteral literal) {
- // Determine the list's element type. We base this on the static type and
- // not the literal's type arguments because in strong mode, the type
- // arguments may be inferred.
- DartType setType = literal.staticType;
- assert(setType is InterfaceTypeImpl);
-
- List<DartType> typeArguments = (setType as InterfaceTypeImpl).typeArguments;
- assert(typeArguments.length == 1);
-
- DartType setElementType = typeArguments[0];
-
- // Check every set element.
- bool isConst = literal.isConst;
- for (Expression element in literal.elements) {
- if (isConst) {
- // TODO(paulberry): this error should be based on the actual type of the
- // element, not the static type. See dartbug.com/21119.
- _checkForArgumentTypeNotAssignableWithExpectedTypes(
- element,
- setElementType,
- CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
- }
- _checkForArgumentTypeNotAssignableWithExpectedTypes(element,
- setElementType, StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
- }
- }
-
- /**
- * Verify that the elements in the given set [literal] are subtypes of the
- * set's static type.
- *
- * See [CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE], and
- * [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE].
- */
void _checkForSetElementTypeNotAssignable3(SetOrMapLiteral literal) {
// Determine the set's element type. We base this on the static type and
// not the literal's type arguments because in strong mode, the type
@@ -5527,21 +5120,16 @@
DartType setElementType = typeArguments[0];
// Check every set element.
- bool isConst = literal.isConst;
+ var verifier = LiteralElementVerifier(
+ _typeProvider,
+ _typeSystem,
+ _errorReporter,
+ _checkForUseOfVoidResult,
+ forSet: true,
+ elementType: setElementType,
+ );
for (CollectionElement element in literal.elements2) {
- if (isConst) {
- // TODO(paulberry): this error should be based on the actual type of
- // the element, not the static type. See dartbug.com/21119.
- _checkForCollectionElementTypeNotAssignableWithElementType(
- element,
- setElementType,
- CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
- } else {
- _checkForCollectionElementTypeNotAssignableWithElementType(
- element,
- setElementType,
- StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
- }
+ verifier.verify(element);
}
}
}
@@ -6918,6 +6506,7 @@
*/
class _UninstantiatedBoundChecker extends RecursiveAstVisitor {
final ErrorReporter _errorReporter;
+
_UninstantiatedBoundChecker(this._errorReporter);
@override
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 5ecd8d4..cd39326 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -3675,8 +3675,8 @@
///
/// mapLiteral ::=
/// 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
- MapLiteral // ignore: deprecated_member_use_from_same_package
- parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
+ SetOrMapLiteral parseMapLiteral(
+ Token modifier, TypeArgumentList typeArguments) {
Token leftBracket = getAndAdvance();
if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
// ignore: deprecated_member_use_from_same_package
@@ -4032,8 +4032,7 @@
_tokenMatchesKeyword(_peek(), Keyword.FOR)) {
Token awaitToken = _currentToken;
Statement statement = parseForStatement();
- // ignore: deprecated_member_use_from_same_package
- if (statement is! ForStatement) {
+ if (!(statement is ForStatement2 && statement.forLoopParts is ForParts)) {
_reportErrorForToken(
CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT, awaitToken);
}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 7891289..88fce5b 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1135,8 +1135,6 @@
if (parent is IfStatement && parent.condition == childOfParent ||
parent is ForPartsWithDeclarations &&
parent.condition == childOfParent ||
- // ignore: deprecated_member_use_from_same_package
- parent is ForStatement && parent.condition == childOfParent ||
parent is DoStatement && parent.condition == childOfParent ||
parent is WhileStatement && parent.condition == childOfParent ||
parent is ConditionalExpression && parent.condition == childOfParent ||
@@ -3540,11 +3538,6 @@
}
@override
- void visitNode(AstNode node) {
- super.visitNode(node);
- }
-
- @override
void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
_addStaticVariables(node.variables.variables);
super.visitTopLevelVariableDeclaration(node);
@@ -3670,6 +3663,8 @@
*/
final InheritanceManager2 inheritance;
+ final AnalysisOptionsImpl _analysisOptions;
+
/// The object used to resolve the element associated with the current node.
ElementResolver elementResolver;
@@ -3736,13 +3731,14 @@
{Scope nameScope,
bool propagateTypes: true,
reportConstEvaluationErrors: true})
- : super(definingLibrary, source, typeProvider, errorListener,
+ : _analysisOptions = definingLibrary.context.analysisOptions,
+ super(definingLibrary, source, typeProvider, errorListener,
nameScope: nameScope) {
- AnalysisOptions options = definingLibrary.context.analysisOptions;
this.elementResolver = new ElementResolver(this,
reportConstEvaluationErrors: reportConstEvaluationErrors);
this.typeSystem = definingLibrary.context.typeSystem;
bool strongModeHints = false;
+ AnalysisOptions options = _analysisOptions;
if (options is AnalysisOptionsImpl) {
strongModeHints = options.strongModeHints;
}
@@ -4250,6 +4246,7 @@
resolutionMap.elementDeclaredByFormalParameter(node.parameter)?.type);
super.visitDefaultFormalParameter(node);
ParameterElement element = node.declaredElement;
+
if (element.initializer != null && node.defaultValue != null) {
(element.initializer as FunctionElementImpl).returnType =
node.defaultValue.staticType;
@@ -4328,52 +4325,7 @@
}
@override
- @deprecated
- void visitForEachStatementInScope(ForEachStatement node) {
- Expression iterable = node.iterable;
- DeclaredIdentifier loopVariable = node.loopVariable;
- SimpleIdentifier identifier = node.identifier;
-
- identifier?.accept(this);
-
- DartType valueType;
- if (loopVariable != null) {
- TypeAnnotation typeAnnotation = loopVariable.type;
- valueType = typeAnnotation?.type ?? UnknownInferredType.instance;
- }
- if (identifier != null) {
- Element element = identifier.staticElement;
- if (element is VariableElement) {
- valueType = element.type;
- } else if (element is PropertyAccessorElement) {
- if (element.parameters.isNotEmpty) {
- valueType = element.parameters[0].type;
- }
- }
- }
- if (valueType != null) {
- InterfaceType targetType = (node.awaitKeyword == null)
- ? typeProvider.iterableType
- : typeProvider.streamType;
- InferenceContext.setType(iterable, targetType.instantiate([valueType]));
- }
-
- //
- // We visit the iterator before the loop variable because the loop variable
- // cannot be in scope while visiting the iterator.
- //
- iterable?.accept(this);
- loopVariable?.accept(this);
- Statement body = node.body;
- if (body != null) {
- visitStatementInScope(body);
- }
- node.accept(elementResolver);
- node.accept(typeAnalyzer);
- }
-
- @override
- void visitForElement(ForElement node) {
+ void visitForElementInScope(ForElement node) {
ForLoopParts forLoopParts = node.forLoopParts;
if (forLoopParts is ForParts) {
if (forLoopParts is ForPartsWithDeclarations) {
@@ -4485,17 +4437,6 @@
}
@override
- @deprecated
- void visitForStatementInScope(ForStatement node) {
- node.variables?.accept(this);
- node.initialization?.accept(this);
- InferenceContext.setType(node.condition, typeProvider.boolType);
- node.condition?.accept(this);
- visitStatementInScope(node.body);
- node.updaters.accept(this);
- }
-
- @override
void visitFunctionDeclaration(FunctionDeclaration node) {
ExecutableElement outerFunction = _enclosingFunction;
FunctionBody outerFunctionBody = _currentFunctionBody;
@@ -4573,9 +4514,6 @@
}
@override
- void visitGenericFunctionType(GenericFunctionType node) {}
-
- @override
void visitGenericTypeAliasInFunctionScope(GenericTypeAlias node) {
super.visitGenericTypeAliasInFunctionScope(node);
safelyVisitComment(node.documentationComment);
@@ -4695,40 +4633,6 @@
}
@override
- @deprecated
- void visitMapLiteral(MapLiteral node) {
- InterfaceType mapT;
- if (node.typeArguments != null) {
- var targs = node.typeArguments.arguments.map((t) => t.type).toList();
- if (targs.length == 2 && targs.any((t) => !t.isDynamic)) {
- mapT = typeProvider.mapType.instantiate([targs[0], targs[1]]);
- }
- } else {
- mapT = typeAnalyzer.inferMapType(node, downwards: true);
- if (mapT != null &&
- node.typeArguments == null &&
- node.entries.isEmpty &&
- typeSystem.isAssignableTo(typeProvider.iterableObjectType, mapT) &&
- !typeSystem.isAssignableTo(typeProvider.mapObjectObjectType, mapT)) {
- // The node is really an empty set literal with no type arguments, so
- // don't try to visit the replaced map literal.
- return;
- }
- }
- if (mapT != null) {
- DartType kType = mapT.typeArguments[0];
- DartType vType = mapT.typeArguments[1];
- for (MapLiteralEntry entry in node.entries) {
- InferenceContext.setType(entry.key, kType);
- InferenceContext.setType(entry.value, vType);
- }
- InferenceContext.setType(node, mapT);
- } else {
- InferenceContext.clearType(node);
- }
- visitNode(node);
- }
-
@override
void visitMethodDeclaration(MethodDeclaration node) {
ExecutableElement outerFunction = _enclosingFunction;
@@ -4863,38 +4767,31 @@
}
@override
- @deprecated
- void visitSetLiteral(SetLiteral node) {
- InterfaceType setT;
-
- TypeArgumentList typeArguments = node.typeArguments;
- if (typeArguments != null) {
- if (typeArguments.length == 1) {
- DartType elementType = typeArguments.arguments[0].type;
- if (!elementType.isDynamic) {
- setT = typeProvider.setType.instantiate([elementType]);
- }
- }
- } else {
- setT = typeAnalyzer.inferSetType(node, downwards: true);
- }
- if (setT != null) {
- DartType eType = setT.typeArguments[0];
- for (Expression child in node.elements) {
- InferenceContext.setType(child, eType);
- }
- InferenceContext.setType(node, setT);
- } else {
- InferenceContext.clearType(node);
- }
- visitNode(node);
- }
-
- @override
void visitSetOrMapLiteral(SetOrMapLiteral node) {
- DartType literalType = _computeContextType(node);
- // TODO(brianwilkerson) Determine whether we need special handling for type
- // parameter types. (E-mail sent.)
+ var typeArguments = node.typeArguments?.arguments;
+ InterfaceType literalType;
+ var literalResolution = _computeSetOrMapResolution(node);
+ if (literalResolution.kind == _LiteralResolutionKind.set) {
+ if (typeArguments != null && typeArguments.length == 1) {
+ var elementType = typeArguments[0].type;
+ literalType = typeProvider.setType.instantiate([elementType]);
+ } else {
+ literalType = typeAnalyzer.inferSetTypeDownwards(
+ node, literalResolution.contextType);
+ }
+ } else if (literalResolution.kind == _LiteralResolutionKind.map) {
+ if (typeArguments != null && typeArguments.length == 2) {
+ var keyType = typeArguments[0].type;
+ var valueType = typeArguments[1].type;
+ literalType = typeProvider.mapType.instantiate([keyType, valueType]);
+ } else {
+ literalType = typeAnalyzer.inferMapTypeDownwards(
+ node, literalResolution.contextType);
+ }
+ } else {
+ assert(literalResolution.kind == _LiteralResolutionKind.ambiguous);
+ literalType = null;
+ }
if (literalType is InterfaceType) {
List<DartType> typeArguments = literalType.typeArguments;
if (typeArguments.length == 1) {
@@ -4903,15 +4800,34 @@
typeProvider.iterableType.instantiate([elementType]);
_pushCollectionTypesDownToAll(node.elements2,
elementType: elementType, iterableType: iterableType);
+ if (!_analysisOptions.experimentStatus.spread_collections &&
+ !_analysisOptions.experimentStatus.control_flow_collections &&
+ node.elements2.isEmpty &&
+ node.typeArguments == null &&
+ node.isMap) {
+ // The node is really an empty set literal with no type arguments.
+ // Rewrite the AST.
+ // ignore: deprecated_member_use_from_same_package
+ SetOrMapLiteral setLiteral = new AstFactoryImpl().setLiteral(
+ node.constKeyword,
+ null,
+ node.leftBracket,
+ null,
+ node.rightBracket);
+ InferenceContext.setType(
+ setLiteral, InferenceContext.getContext(node));
+ NodeReplacer.replace(node, setLiteral);
+ node = setLiteral;
+ }
} else if (typeArguments.length == 2) {
DartType keyType = typeArguments[0];
DartType valueType = typeArguments[1];
_pushCollectionTypesDownToAll(node.elements2,
iterableType: literalType, keyType: keyType, valueType: valueType);
}
- InferenceContext.setType(node, literalType);
+ (node as SetOrMapLiteralImpl).contextType = literalType;
} else {
- InferenceContext.clearType(node);
+ (node as SetOrMapLiteralImpl).contextType = null;
}
super.visitSetOrMapLiteral(node);
}
@@ -5076,59 +4992,6 @@
}
}
- /// Compute the context type for the given set or map [literal].
- DartType _computeContextType(SetOrMapLiteral literal) {
- _LiteralResolution typeArgumentsResolution =
- _fromTypeArguments(literal.typeArguments);
- DartType contextType = InferenceContext.getContext(literal);
- _LiteralResolution contextResolution = _fromContextType(contextType);
- _LeafElements elementCounts = new _LeafElements(literal.elements2);
- _LiteralResolution elementResolution = elementCounts.resolution;
-
- List<_LiteralResolution> unambiguousResolutions = [];
- Set<_LiteralResolutionKind> kinds = new Set<_LiteralResolutionKind>();
- if (typeArgumentsResolution.kind != _LiteralResolutionKind.ambiguous) {
- unambiguousResolutions.add(typeArgumentsResolution);
- kinds.add(typeArgumentsResolution.kind);
- }
- if (contextResolution.kind != _LiteralResolutionKind.ambiguous) {
- unambiguousResolutions.add(contextResolution);
- kinds.add(contextResolution.kind);
- }
- if (elementResolution.kind != _LiteralResolutionKind.ambiguous) {
- unambiguousResolutions.add(elementResolution);
- kinds.add(elementResolution.kind);
- }
-
- if (kinds.length == 2) {
- // It looks like it needs to be both a map and a set. Attempt to recover.
- if (elementResolution.kind == _LiteralResolutionKind.ambiguous &&
- elementResolution.contextType != null) {
- return elementResolution.contextType;
- } else if (typeArgumentsResolution.kind !=
- _LiteralResolutionKind.ambiguous &&
- typeArgumentsResolution.contextType != null) {
- return typeArgumentsResolution.contextType;
- } else if (contextResolution.kind != _LiteralResolutionKind.ambiguous &&
- contextResolution.contextType != null) {
- return contextResolution.contextType;
- }
- } else if (unambiguousResolutions.length >= 2) {
- // If there are three resolutions, the last resolution is guaranteed to be
- // from the elements, which always has a context type of `null` (when it
- // is not ambiguous). So, whether there are 2 or 3 resolutions only the
- // first two are potentially interesting.
- return unambiguousResolutions[0].contextType ??
- unambiguousResolutions[1].contextType;
- } else if (unambiguousResolutions.length == 1) {
- return unambiguousResolutions[0].contextType;
- } else if (literal.elements2.isEmpty) {
- return typeProvider.mapType
- .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]);
- }
- return null;
- }
-
/// Given the declared return type of a function, compute the type of the
/// values which should be returned or yielded as appropriate. If a type
/// cannot be computed from the declared return type, return null.
@@ -5160,6 +5023,62 @@
return declaredType;
}
+ /// Compute the context type for the given set or map [literal].
+ _LiteralResolution _computeSetOrMapResolution(SetOrMapLiteral literal) {
+ _LiteralResolution typeArgumentsResolution =
+ _fromTypeArguments(literal.typeArguments);
+ DartType contextType = InferenceContext.getContext(literal);
+ _LiteralResolution contextResolution = _fromContextType(contextType);
+ _LeafElements elementCounts = new _LeafElements(literal.elements2);
+ _LiteralResolution elementResolution = elementCounts.resolution;
+
+ List<_LiteralResolution> unambiguousResolutions = [];
+ Set<_LiteralResolutionKind> kinds = new Set<_LiteralResolutionKind>();
+ if (typeArgumentsResolution.kind != _LiteralResolutionKind.ambiguous) {
+ unambiguousResolutions.add(typeArgumentsResolution);
+ kinds.add(typeArgumentsResolution.kind);
+ }
+ if (contextResolution.kind != _LiteralResolutionKind.ambiguous) {
+ unambiguousResolutions.add(contextResolution);
+ kinds.add(contextResolution.kind);
+ }
+ if (elementResolution.kind != _LiteralResolutionKind.ambiguous) {
+ unambiguousResolutions.add(elementResolution);
+ kinds.add(elementResolution.kind);
+ }
+
+ if (kinds.length == 2) {
+ // It looks like it needs to be both a map and a set. Attempt to recover.
+ if (elementResolution.kind == _LiteralResolutionKind.ambiguous &&
+ elementResolution.contextType != null) {
+ return elementResolution;
+ } else if (typeArgumentsResolution.kind !=
+ _LiteralResolutionKind.ambiguous &&
+ typeArgumentsResolution.contextType != null) {
+ return typeArgumentsResolution;
+ } else if (contextResolution.kind != _LiteralResolutionKind.ambiguous &&
+ contextResolution.contextType != null) {
+ return contextResolution;
+ }
+ } else if (unambiguousResolutions.length >= 2) {
+ // If there are three resolutions, the last resolution is guaranteed to be
+ // from the elements, which always has a context type of `null` (when it
+ // is not ambiguous). So, whether there are 2 or 3 resolutions only the
+ // first two are potentially interesting.
+ return unambiguousResolutions[0].contextType == null
+ ? unambiguousResolutions[1]
+ : unambiguousResolutions[0];
+ } else if (unambiguousResolutions.length == 1) {
+ return unambiguousResolutions[0];
+ } else if (literal.elements2.isEmpty) {
+ return _LiteralResolution(
+ _LiteralResolutionKind.map,
+ typeProvider.mapType.instantiate(
+ [typeProvider.dynamicType, typeProvider.dynamicType]));
+ }
+ return _LiteralResolution(_LiteralResolutionKind.ambiguous, null);
+ }
+
/// Return a newly created cloner that can be used to clone constant
/// expressions.
ConstantAstCloner _createCloner() {
@@ -5196,16 +5115,14 @@
DartType unwrappedContextType = unwrap(contextType);
// TODO(brianwilkerson) Find out what the "greatest closure" is and use that
// where [unwrappedContextType] is used below.
- if (typeSystem.isAssignableTo(
- typeProvider.iterableObjectType, unwrappedContextType) &&
- !typeSystem.isAssignableTo(
- typeProvider.mapObjectObjectType, unwrappedContextType)) {
+ bool isIterable = typeSystem.isSubtypeOf(
+ unwrappedContextType, typeProvider.iterableObjectType);
+ bool isMap = typeSystem.isSubtypeOf(
+ unwrappedContextType, typeProvider.mapObjectObjectType);
+ if (isIterable && !isMap) {
return _LiteralResolution(
_LiteralResolutionKind.set, unwrappedContextType);
- } else if (typeSystem.isAssignableTo(
- typeProvider.mapObjectObjectType, unwrappedContextType) &&
- !typeSystem.isAssignableTo(
- typeProvider.iterableObjectType, unwrappedContextType)) {
+ } else if (isMap && !isIterable) {
return _LiteralResolution(
_LiteralResolutionKind.map, unwrappedContextType);
}
@@ -5871,35 +5788,34 @@
}
@override
- @deprecated
- void visitForEachStatement(ForEachStatement node) {
- Scope outerNameScope = nameScope;
- ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
- try {
- nameScope = new EnclosedScope(nameScope);
- _implicitLabelScope = _implicitLabelScope.nest(node);
- visitForEachStatementInScope(node);
- } finally {
- nameScope = outerNameScope;
- _implicitLabelScope = outerImplicitScope;
- }
- }
-
- /// Visit the given statement after it's scope has been created. This replaces
- /// the normal call to the inherited visit method so that ResolverVisitor can
- /// intervene when type propagation is enabled.
- ///
- /// @param node the statement to be visited
- @deprecated
- void visitForEachStatementInScope(ForEachStatement node) {
+ void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
//
// We visit the iterator before the loop variable because the loop variable
// cannot be in scope while visiting the iterator.
//
- node.identifier?.accept(this);
node.iterable?.accept(this);
node.loopVariable?.accept(this);
- visitStatementInScope(node.body);
+ }
+
+ @override
+ void visitForElement(ForElement node) {
+ Scope outerNameScope = nameScope;
+ try {
+ nameScope = new EnclosedScope(nameScope);
+ visitForElementInScope(node);
+ } finally {
+ nameScope = outerNameScope;
+ }
+ }
+
+ /// Visit the given [node] after it's scope has been created. This replaces
+ /// the normal call to the inherited visit method so that ResolverVisitor can
+ /// intervene when type propagation is enabled.
+ void visitForElementInScope(ForElement node) {
+ // TODO(brianwilkerson) Investigate the possibility of removing the
+ // visit...InScope methods now that type propagation is no longer done.
+ node.forLoopParts?.accept(this);
+ node.body?.accept(this);
}
@override
@@ -5919,21 +5835,6 @@
}
@override
- @deprecated
- void visitForStatement(ForStatement node) {
- Scope outerNameScope = nameScope;
- ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
- try {
- nameScope = new EnclosedScope(nameScope);
- _implicitLabelScope = _implicitLabelScope.nest(node);
- visitForStatementInScope(node);
- } finally {
- nameScope = outerNameScope;
- _implicitLabelScope = outerImplicitScope;
- }
- }
-
- @override
void visitForStatement2(ForStatement2 node) {
Scope outerNameScope = nameScope;
ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
@@ -5957,20 +5858,6 @@
visitStatementInScope(node.body);
}
- /// Visit the given statement after it's scope has been created. This replaces
- /// the normal call to the inherited visit method so that ResolverVisitor can
- /// intervene when type propagation is enabled.
- ///
- /// @param node the statement to be visited
- @deprecated
- void visitForStatementInScope(ForStatement node) {
- node.variables?.accept(this);
- node.initialization?.accept(this);
- node.condition?.accept(this);
- node.updaters.accept(this);
- visitStatementInScope(node.body);
- }
-
@override
void visitFunctionDeclaration(FunctionDeclaration node) {
ExecutableElement functionElement = node.declaredElement;
@@ -9063,15 +8950,20 @@
/// Return `true` if the given collection [element] does not contain any
/// synthetic tokens.
bool _isComplete(CollectionElement element) {
- Token token = element.beginToken;
- int endOffset = element.endToken.offset;
- while (token != null && token.offset <= endOffset) {
- if (token.isSynthetic) {
- return false;
- }
- token = token.next;
- }
+ // TODO(paulberry,brianwilkerson): the code below doesn't work because it
+ // assumes access to token offsets, which aren't available when working with
+ // expressions resynthesized from summaries. For now we just assume the
+ // collection element is complete.
return true;
+// Token token = element.beginToken;
+// int endOffset = element.endToken.offset;
+// while (token != null && token.offset <= endOffset) {
+// if (token.isSynthetic) {
+// return false;
+// }
+// token = token.next;
+// }
+// return true;
}
}
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 66fe369..377affe 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -10,10 +10,7 @@
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/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/ast_factory.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' show ConstructorMember;
import 'package:analyzer/src/dart/element/type.dart';
@@ -55,11 +52,6 @@
DartType _dynamicType;
/**
- * The status of the active experiments of the current context.
- */
- ExperimentStatus _experimentStatus;
-
- /**
* True if inference failures should be reported, otherwise false.
*/
bool _strictInference;
@@ -87,7 +79,6 @@
_promoteManager = _resolver.promoteManager;
AnalysisOptionsImpl analysisOptions =
_resolver.definingLibrary.context.analysisOptions;
- _experimentStatus = analysisOptions.experimentStatus;
_strictInference = analysisOptions.strictInference;
}
@@ -189,101 +180,30 @@
return inferred;
}
- @deprecated
- ParameterizedType inferMapType(MapLiteral node, {bool downwards: false}) {
- DartType contextType = InferenceContext.getContext(node);
- if (contextType != null && _experimentStatus.set_literals) {
- DartType unwrap(DartType type) {
- if (type is InterfaceType &&
- type.isDartAsyncFutureOr &&
- type.typeArguments.length == 1) {
- return unwrap(type.typeArguments[0]);
- }
- return type;
- }
-
- DartType unwrappedContextType = unwrap(contextType);
- if (node.typeArguments == null &&
- node.entries.isEmpty &&
- _typeSystem.isAssignableTo(
- _typeProvider.iterableObjectType, unwrappedContextType) &&
- !_typeSystem.isAssignableTo(
- _typeProvider.mapObjectObjectType, unwrappedContextType)) {
- // The node is really an empty set literal with no type arguments.
- // Rewrite the AST and infer the type of the set as appropriate.
- SetLiteral setLiteral = new AstFactoryImpl().setLiteral(
- node.constKeyword, null, node.leftBracket, null, node.rightBracket);
- InferenceContext.setType(setLiteral, contextType);
- NodeReplacer.replace(node, setLiteral);
- DartType type = inferSetType(setLiteral, downwards: downwards);
- setLiteral.staticType = type;
- return type;
- }
- }
- List<DartType> elementTypes;
- List<ParameterElement> parameters;
- if (downwards) {
- if (contextType == null) {
- return null;
- }
- elementTypes = [];
- parameters = [];
- } else {
- var keyTypes =
- node.entries.map((e) => e.key.staticType).where((t) => t != null);
- var valueTypes =
- node.entries.map((e) => e.value.staticType).where((t) => t != null);
- var keyTypeParam = _typeProvider.mapType.typeParameters[0].type;
- var valueTypeParam = _typeProvider.mapType.typeParameters[1].type;
- var syntheticKeyParameter = new ParameterElementImpl.synthetic(
- 'key', keyTypeParam, ParameterKind.POSITIONAL);
- var syntheticValueParameter = new ParameterElementImpl.synthetic(
- 'value', valueTypeParam, ParameterKind.POSITIONAL);
- parameters = new List.filled(keyTypes.length, syntheticKeyParameter,
- growable: true)
- ..addAll(new List.filled(valueTypes.length, syntheticValueParameter));
- elementTypes = new List<DartType>.from(keyTypes)..addAll(valueTypes);
+ ParameterizedType inferMapTypeDownwards(
+ SetOrMapLiteral node, DartType contextType) {
+ if (contextType == null) {
+ return null;
}
- // Use both downwards and upwards information to infer the type.
var ts = _typeSystem as Dart2TypeSystem;
ParameterizedType inferred = ts.inferGenericFunctionOrType(
- _typeProvider.mapType, parameters, elementTypes, contextType,
- downwards: downwards,
+ _typeProvider.mapType, [], [], contextType,
+ downwards: true,
errorReporter: _resolver.errorReporter,
errorNode: node);
return inferred;
}
- @deprecated
- DartType inferSetType(SetLiteral node, {bool downwards: false}) {
- DartType contextType = InferenceContext.getContext(node);
+ DartType inferSetTypeDownwards(SetOrMapLiteral node, DartType contextType) {
+ if (contextType == null) {
+ return null;
+ }
var ts = _typeSystem as Dart2TypeSystem;
- List<DartType> elementTypes;
- List<ParameterElement> parameters;
-
- if (downwards) {
- if (contextType == null) {
- return null;
- }
-
- elementTypes = [];
- parameters = [];
- } else {
- // Also use upwards information to infer the type.
- elementTypes = node.elements
- .map((e) => e.staticType)
- .where((t) => t != null)
- .toList();
- var setTypeParam = _typeProvider.setType.typeParameters[0].type;
- var syntheticParamElement = new ParameterElementImpl.synthetic(
- 'element', setTypeParam, ParameterKind.POSITIONAL);
- parameters = new List.filled(elementTypes.length, syntheticParamElement);
- }
DartType inferred = ts.inferGenericFunctionOrType<InterfaceType>(
- _typeProvider.setType, parameters, elementTypes, contextType,
- downwards: downwards,
+ _typeProvider.setType, [], [], contextType,
+ downwards: true,
errorReporter: _resolver.errorReporter,
errorNode: node);
return inferred;
@@ -704,65 +624,6 @@
}
/**
- * The Dart Language Specification, 12.7: <blockquote>The static type of a map literal of the form
- * <i><b>const</b> <K, V> {k<sub>1</sub>:e<sub>1</sub>, …,
- * k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i><K, V> {k<sub>1</sub>:e<sub>1</sub>,
- * …, k<sub>n</sub>:e<sub>n</sub>}</i> is `Map<K, V>`. The static type a map
- * literal of the form <i><b>const</b> {k<sub>1</sub>:e<sub>1</sub>, …,
- * k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i>{k<sub>1</sub>:e<sub>1</sub>, …,
- * k<sub>n</sub>:e<sub>n</sub>}</i> is `Map<dynamic, dynamic>`.
- *
- * It is a compile-time error if the first type argument to a map literal is not
- * <i>String</i>.</blockquote>
- */
- @override
- @deprecated
- void visitMapLiteral(MapLiteral node) {
- TypeArgumentList typeArguments = node.typeArguments;
-
- // If we have type arguments, use them
- if (typeArguments != null) {
- DartType staticKeyType = _dynamicType;
- DartType staticValueType = _dynamicType;
- NodeList<TypeAnnotation> arguments = typeArguments.arguments;
- if (arguments != null && arguments.length == 2) {
- DartType entryKeyType = _getType(arguments[0]);
- if (entryKeyType != null) {
- staticKeyType = entryKeyType;
- }
- DartType entryValueType = _getType(arguments[1]);
- if (entryValueType != null) {
- staticValueType = entryValueType;
- }
- }
- _recordStaticType(
- node,
- _typeProvider.mapType
- .instantiate(<DartType>[staticKeyType, staticValueType]));
- return;
- }
-
- DartType mapDynamicType = _typeProvider.mapType
- .instantiate(<DartType>[_dynamicType, _dynamicType]);
-
- // If we have no explicit type arguments, try to infer type arguments.
- ParameterizedType inferred = inferMapType(node);
-
- if (inferred != mapDynamicType) {
- // TODO(jmesserly): this results in an "inferred" message even when we
- // in fact had an error above, because it will still attempt to return
- // a type. Perhaps we should record inference from TypeSystem if
- // everything was successful?
- _resolver.inferenceContext.recordInference(node, inferred);
- _recordStaticType(node, inferred);
- return;
- }
-
- // If no type arguments and no inference, use dynamic
- _recordStaticType(node, mapDynamicType);
- }
-
- /**
* The Dart Language Specification, 12.15.1: <blockquote>An ordinary method invocation <i>i</i>
* has the form <i>o.m(a<sub>1</sub>, …, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>,
* …, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
@@ -1010,66 +871,42 @@
}
@override
- @deprecated
- void visitSetLiteral(SetLiteral node) {
- TypeArgumentList typeArguments = node.typeArguments;
-
- // If we have type arguments, use them
- if (typeArguments != null) {
- DartType elementType = _dynamicType;
- NodeList<TypeAnnotation> arguments = typeArguments.arguments;
- if (arguments != null && arguments.length == 1) {
- DartType type = _getType(arguments[0]);
- if (type != null) {
- elementType = type;
- }
- }
- _recordStaticType(
- node, _typeProvider.setType.instantiate(<DartType>[elementType]));
- return;
- }
-
- DartType setDynamicType =
- _typeProvider.setType.instantiate(<DartType>[_dynamicType]);
-
- // If we have no explicit type arguments, try to infer type arguments.
- ParameterizedType inferred = inferSetType(node);
-
- if (inferred != setDynamicType) {
- // TODO(jmesserly): this results in an "inferred" message even when we
- // in fact had an error above, because it will still attempt to return
- // a type. Perhaps we should record inference from TypeSystem if
- // everything was successful?
- _resolver.inferenceContext.recordInference(node, inferred);
- _recordStaticType(node, inferred);
- return;
- }
-
- // If no type arguments and no inference, use dynamic
- _recordStaticType(node, setDynamicType);
- }
-
- @override
void visitSetOrMapLiteral(SetOrMapLiteral node) {
- DartType staticType = node.staticType;
- if (staticType == null) {
- DartType literalType = _inferSetOrMapLiteralType(node);
- if (literalType.element == _typeProvider.mapType.element) {
- (node as SetOrMapLiteralImpl).becomeMap();
- } else {
- assert(literalType.element == _typeProvider.setType.element);
- (node as SetOrMapLiteralImpl).becomeSet();
- }
- _resolver.inferenceContext.recordInference(node, literalType);
- _recordStaticType(node, literalType);
- } else if (staticType is InterfaceType) {
- List<DartType> typeArguments = staticType.typeArguments;
+ var typeArguments = node.typeArguments?.arguments;
+
+ // If we have type arguments, use them.
+ // TODO(paulberry): this logic seems redundant with
+ // ResolverVisitor._fromTypeArguments
+ if (typeArguments != null) {
if (typeArguments.length == 1) {
(node as SetOrMapLiteralImpl).becomeSet();
+ var elementType = _getType(typeArguments[0]) ?? _dynamicType;
+ _recordStaticType(
+ node, _typeProvider.setType.instantiate(<DartType>[elementType]));
+ return;
} else if (typeArguments.length == 2) {
(node as SetOrMapLiteralImpl).becomeMap();
+ var keyType = _getType(typeArguments[0]) ?? _dynamicType;
+ var valueType = _getType(typeArguments[1]) ?? _dynamicType;
+ _recordStaticType(node,
+ _typeProvider.mapType.instantiate(<DartType>[keyType, valueType]));
+ return;
}
+ // If we get here, then a nonsense number of type arguments were provided,
+ // so treat it as though no type arguments were provided.
}
+ DartType literalType = _inferSetOrMapLiteralType(node);
+ if (literalType.isDynamic) {
+ // The literal is ambiguous, and further analysis won't resolve the
+ // ambiguity. Leave it as neither a set nor a map.
+ } else if (literalType.element == _typeProvider.mapType.element) {
+ (node as SetOrMapLiteralImpl).becomeMap();
+ } else {
+ assert(literalType.element == _typeProvider.setType.element);
+ (node as SetOrMapLiteralImpl).becomeSet();
+ }
+ _resolver.inferenceContext.recordInference(node, literalType);
+ _recordStaticType(node, literalType);
}
/**
@@ -1283,16 +1120,30 @@
return _typeSystem.leastUpperBound(thenType, elseType);
} else if (element is Expression) {
return element.staticType;
+ } else if (element is MapLiteralEntry) {
+ // This error will be reported elsewhere.
+ return _typeProvider.dynamicType;
} else if (element is SpreadElement) {
- DartType collectionType = element.expression.staticType;
- if (collectionType is ParameterizedType) {
- List<DartType> typeArguments = collectionType.typeArguments;
- if (typeArguments.length == 1) {
- return typeArguments[0];
+ DartType expressionType = element.expression.staticType;
+ bool isNull = expressionType.isDartCoreNull;
+ if (!isNull && expressionType is InterfaceType) {
+ if (_typeSystem.isSubtypeOf(
+ expressionType, _typeProvider.iterableObjectType)) {
+ InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
+ .asInstanceOf(_typeProvider.iterableType.element);
+ return iterableType.typeArguments[0];
}
+ } else if (expressionType.isDynamic) {
+ return expressionType;
+ } else if (isNull &&
+ element.spreadOperator.type ==
+ TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
+ return expressionType;
}
+ // TODO(brianwilkerson) Report this as an error.
+ return _typeProvider.dynamicType;
}
- return null;
+ throw StateError('Unhandled element type ${element.runtimeType}');
}
/**
@@ -1551,7 +1402,7 @@
}
_InferredCollectionElementTypeInformation elseType =
_inferCollectionElementType(element.elseElement);
- return _InferredCollectionElementTypeInformation.leastUpperBound(
+ return _InferredCollectionElementTypeInformation.forIfElement(
_typeSystem, thenType, elseType);
} else if (element is Expression) {
return _InferredCollectionElementTypeInformation(
@@ -1569,41 +1420,19 @@
expressionType, _typeProvider.iterableObjectType)) {
InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
.asInstanceOf(_typeProvider.iterableType.element);
- if (iterableType != null) {
- // The `iterableType` will be `null` when `expressionType` is
- // `Null`. Fall through in that case to perform the default type
- // check.
- List<DartType> typeArguments = iterableType.typeArguments;
- if (typeArguments.length == 1) {
- return _InferredCollectionElementTypeInformation(
- elementType: typeArguments[0],
- keyType: null,
- valueType: null);
- }
- }
return _InferredCollectionElementTypeInformation(
- elementType: _typeProvider.dynamicType,
+ elementType: iterableType.typeArguments[0],
keyType: null,
valueType: null);
} else if (_typeSystem.isSubtypeOf(
expressionType, _typeProvider.mapObjectObjectType)) {
InterfaceType mapType = (expressionType as InterfaceTypeImpl)
.asInstanceOf(_typeProvider.mapType.element);
- if (mapType != null) {
- // The `iterableType` will be `null` when `expressionType` is
- // `Null`. Fall through in that case to perform the default type
- // check.
- List<DartType> typeArguments = mapType.typeArguments;
- if (typeArguments.length == 2) {
- return _InferredCollectionElementTypeInformation(
- elementType: null,
- keyType: typeArguments[0],
- valueType: typeArguments[1]);
- }
- }
- DartType dynamicType = _typeProvider.dynamicType;
+ List<DartType> typeArguments = mapType.typeArguments;
return _InferredCollectionElementTypeInformation(
- elementType: null, keyType: dynamicType, valueType: dynamicType);
+ elementType: null,
+ keyType: typeArguments[0],
+ valueType: typeArguments[1]);
}
} else if (expressionType.isDynamic) {
return _InferredCollectionElementTypeInformation(
@@ -1636,11 +1465,7 @@
AstNode parent = loopVariable.parent;
Token awaitKeyword;
Expression iterable;
- // ignore: deprecated_member_use_from_same_package
- if (parent is ForEachStatement) {
- awaitKeyword = parent.awaitKeyword;
- iterable = parent.iterable;
- } else if (parent is ForEachPartsWithDeclaration) {
+ if (parent is ForEachPartsWithDeclaration) {
AstNode parentParent = parent.parent;
if (parentParent is ForStatement2Impl) {
awaitKeyword = parentParent.awaitKeyword;
@@ -1952,11 +1777,10 @@
}
DartType _inferSetOrMapLiteralType(SetOrMapLiteral literal) {
- DartType contextType = InferenceContext.getContext(literal);
+ var literalImpl = literal as SetOrMapLiteralImpl;
+ DartType contextType = literalImpl.contextType;
+ literalImpl.contextType = null; // Not needed anymore.
NodeList<CollectionElement> elements = literal.elements2;
- if (elements.length < 2 && contextType != null) {
- return contextType;
- }
List<_InferredCollectionElementTypeInformation> inferredTypes = [];
bool canBeAMap = true;
bool mustBeAMap = false;
@@ -1976,11 +1800,36 @@
} else if (canBeAMap && mustBeAMap) {
return _toMapType(literal, contextType, inferredTypes);
}
- if (contextType == null) {
- DartType dynamicType = _typeProvider.dynamicType;
- return _typeProvider.mapType.instantiate([dynamicType, dynamicType]);
+ // Note: according to the spec, the following computations should be based
+ // on the greatest closure of the context type (unless the context type is
+ // `?`). In practice, we can just use the context type directly, because
+ // the only way the greatest closure of the context type could possibly have
+ // a different subtype relationship to `Iterable<Object>` and
+ // `Map<Object, Object>` is if the context type is `?`.
+ bool contextProvidesAmbiguityResolutionClues =
+ contextType != null && contextType is! UnknownInferredType;
+ bool contextIsIterable = contextProvidesAmbiguityResolutionClues &&
+ _typeSystem.isSubtypeOf(contextType, _typeProvider.iterableObjectType);
+ bool contextIsMap = contextProvidesAmbiguityResolutionClues &&
+ _typeSystem.isSubtypeOf(contextType, _typeProvider.mapObjectObjectType);
+ if (contextIsIterable && !contextIsMap) {
+ return _toSetType(literal, contextType, inferredTypes);
+ } else if ((contextIsMap && !contextIsIterable) || elements.isEmpty) {
+ return _toMapType(literal, contextType, inferredTypes);
+ } else {
+ // Ambiguous. We're not going to get any more information to resolve the
+ // ambiguity. We don't want to make an arbitrary decision at this point
+ // because it will interfere with future type inference (see
+ // dartbug.com/36210), so we return a type of `dynamic`.
+ if (mustBeAMap && mustBeASet) {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH, literal);
+ } else {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER, literal);
+ }
+ return _typeProvider.dynamicType;
}
- return contextType;
}
/**
@@ -2106,22 +1955,44 @@
_InferredCollectionElementTypeInformation(
{this.elementType, this.keyType, this.valueType});
- factory _InferredCollectionElementTypeInformation.leastUpperBound(
- TypeSystem typeSystem,
- _InferredCollectionElementTypeInformation first,
- _InferredCollectionElementTypeInformation second) =>
- _InferredCollectionElementTypeInformation(
- elementType: _leastUpperBoundOfTypes(
- typeSystem, first.elementType, second.elementType),
- keyType: _leastUpperBoundOfTypes(
- typeSystem, first.keyType, second.keyType),
- valueType: _leastUpperBoundOfTypes(
- typeSystem, first.valueType, second.valueType));
+ factory _InferredCollectionElementTypeInformation.forIfElement(
+ TypeSystem typeSystem,
+ _InferredCollectionElementTypeInformation thenInfo,
+ _InferredCollectionElementTypeInformation elseInfo) {
+ if (thenInfo.isDynamic) {
+ DartType dynamic = thenInfo.elementType;
+ return _InferredCollectionElementTypeInformation(
+ elementType: _dynamicOrNull(elseInfo.elementType, dynamic),
+ keyType: _dynamicOrNull(elseInfo.keyType, dynamic),
+ valueType: _dynamicOrNull(elseInfo.valueType, dynamic));
+ } else if (elseInfo.isDynamic) {
+ DartType dynamic = elseInfo.elementType;
+ return _InferredCollectionElementTypeInformation(
+ elementType: _dynamicOrNull(thenInfo.elementType, dynamic),
+ keyType: _dynamicOrNull(thenInfo.keyType, dynamic),
+ valueType: _dynamicOrNull(thenInfo.valueType, dynamic));
+ }
+ return _InferredCollectionElementTypeInformation(
+ elementType: _leastUpperBoundOfTypes(
+ typeSystem, thenInfo.elementType, elseInfo.elementType),
+ keyType: _leastUpperBoundOfTypes(
+ typeSystem, thenInfo.keyType, elseInfo.keyType),
+ valueType: _leastUpperBoundOfTypes(
+ typeSystem, thenInfo.valueType, elseInfo.valueType));
+ }
bool get canBeAMap => keyType != null || valueType != null;
bool get canBeASet => elementType != null;
+ bool get isDynamic =>
+ elementType != null &&
+ elementType.isDynamic &&
+ keyType != null &&
+ keyType.isDynamic &&
+ valueType != null &&
+ valueType.isDynamic;
+
bool get mustBeAMap => canBeAMap && elementType == null;
bool get mustBeASet => canBeASet && keyType == null && valueType == null;
@@ -2131,6 +2002,13 @@
return '($elementType, $keyType, $valueType)';
}
+ static DartType _dynamicOrNull(DartType type, DartType dynamic) {
+ if (type == null) {
+ return null;
+ }
+ return dynamic;
+ }
+
static DartType _leastUpperBoundOfTypes(
TypeSystem typeSystem, DartType first, DartType second) {
if (first == null) {
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index 296457a..a2e6994 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -495,7 +495,7 @@
fieldFormalParameter(null, null, identifier);
@Deprecated('Use forStatement2')
- static ForEachStatement forEachStatement(DeclaredIdentifier loopVariable,
+ static ForStatement2 forEachStatement(DeclaredIdentifier loopVariable,
Expression iterator, Statement body) =>
astFactory.forStatement2(
forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
@@ -508,7 +508,7 @@
body: body);
@Deprecated('Use forStatement2')
- static ForEachStatement forEachStatement2(
+ static ForStatement2 forEachStatement2(
SimpleIdentifier identifier, Expression iterator, Statement body) =>
astFactory.forStatement2(
forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
@@ -530,7 +530,7 @@
TokenFactory.tokenFromType(TokenType.CLOSE_PAREN));
@Deprecated('Use forStatement2')
- static ForStatement forStatement(Expression initialization,
+ static ForStatement2 forStatement(Expression initialization,
Expression condition, List<Expression> updaters, Statement body) =>
astFactory.forStatement2(
forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
@@ -544,27 +544,19 @@
rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
body: body);
- static
- // ignore: deprecated_member_use_from_same_package
- ForStatement forStatement2(
- VariableDeclarationList variableList,
- Expression condition,
- List<Expression> updaters,
- Statement body) =>
- astFactory.forStatement2(
- forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
- leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
- forLoopParts: astFactory.forPartsWithDeclarations(
- variables: variableList,
- leftSeparator:
- TokenFactory.tokenFromType(TokenType.SEMICOLON),
- condition: condition,
- rightSeparator:
- TokenFactory.tokenFromType(TokenType.SEMICOLON),
- updaters: updaters),
- rightParenthesis:
- TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
- body: body);
+ static ForStatement2 forStatement2(VariableDeclarationList variableList,
+ Expression condition, List<Expression> updaters, Statement body) =>
+ astFactory.forStatement2(
+ forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
+ leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
+ forLoopParts: astFactory.forPartsWithDeclarations(
+ variables: variableList,
+ leftSeparator: TokenFactory.tokenFromType(TokenType.SEMICOLON),
+ condition: condition,
+ rightSeparator: TokenFactory.tokenFromType(TokenType.SEMICOLON),
+ updaters: updaters),
+ rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
+ body: body);
static FunctionDeclaration functionDeclaration(
TypeAnnotation type,
@@ -678,6 +670,20 @@
.toList();
}
+ static IfElement ifElement(
+ Expression condition, CollectionElement thenElement,
+ [CollectionElement elseElement]) =>
+ astFactory.ifElement(
+ ifKeyword: TokenFactory.tokenFromKeyword(Keyword.IF),
+ leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
+ condition: condition,
+ rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
+ thenElement: thenElement,
+ elseKeyword: elseElement == null
+ ? null
+ : TokenFactory.tokenFromKeyword(Keyword.ELSE),
+ elseElement: elseElement);
+
static IfStatement ifStatement(
Expression condition, Statement thenStatement) =>
ifStatement2(condition, thenStatement, null);
@@ -825,7 +831,7 @@
static ListLiteral listLiteral2(
Keyword keyword, TypeArgumentList typeArguments,
- [List<Expression> elements]) =>
+ [List<CollectionElement> elements]) =>
astFactory.listLiteral(
keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
typeArguments,
@@ -834,7 +840,8 @@
TokenFactory.tokenFromType(TokenType.CLOSE_SQUARE_BRACKET));
@Deprecated('Use setOrMapLiteral')
- static MapLiteral mapLiteral(Keyword keyword, TypeArgumentList typeArguments,
+ static SetOrMapLiteral mapLiteral(
+ Keyword keyword, TypeArgumentList typeArguments,
[List<MapLiteralEntry> entries]) =>
astFactory.mapLiteral(
keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
@@ -844,7 +851,7 @@
TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
@Deprecated('Use setOrMapLiteral')
- static MapLiteral mapLiteral2([List<MapLiteralEntry> entries]) =>
+ static SetOrMapLiteral mapLiteral2([List<MapLiteralEntry> entries]) =>
mapLiteral(null, null, entries);
static MapLiteralEntry mapLiteralEntry(String key, Expression value) =>
@@ -1087,8 +1094,8 @@
astFactory.scriptTag(TokenFactory.tokenFromString(scriptTag));
@Deprecated('Use setOrMapLiteral')
- static SetLiteral setLiteral(Keyword keyword, TypeArgumentList typeArguments,
- List<Expression> elements) =>
+ static SetOrMapLiteral setLiteral(Keyword keyword,
+ TypeArgumentList typeArguments, List<Expression> elements) =>
astFactory.setLiteral(
keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
typeArguments,
@@ -1133,6 +1140,12 @@
TypeAnnotation type, String parameterName) =>
simpleFormalParameter2(null, type, parameterName);
+ static SpreadElement spreadElement(
+ TokenType operator, Expression expression) =>
+ astFactory.spreadElement(
+ spreadOperator: TokenFactory.tokenFromType(operator),
+ expression: expression);
+
static StringInterpolation string([List<InterpolationElement> elements]) =>
astFactory.stringInterpolation(elements);
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 30b2925..6e978a6 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -577,6 +577,9 @@
///
/// In practice this will always replace `?` with either bottom or top
/// (dynamic), depending on the position of `?`.
+ ///
+ /// This implements the operation the spec calls "least closure", or
+ /// sometimes "least closure with respect to `?`".
DartType lowerBoundForType(DartType type) {
return _substituteForUnknownType(type, lowerBound: true);
}
@@ -641,6 +644,9 @@
///
/// In practice this will always replace `?` with either bottom or top
/// (dynamic), depending on the position of `?`.
+ ///
+ /// This implements the operation the spec calls "greatest closure", or
+ /// sometimes "greatest closure with respect to `?`".
DartType upperBoundForType(DartType type) {
return _substituteForUnknownType(type);
}
diff --git a/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
new file mode 100644
index 0000000..2596ac9
--- /dev/null
+++ b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/// Information about analysis `//ignore:` and `//ignore_for_file` comments
+/// within a source file.
+class IgnoreInfo {
+ /// Instance shared by all cases without matches.
+ static final IgnoreInfo _EMPTY_INFO = new IgnoreInfo();
+
+ /// A regular expression for matching 'ignore' comments. Produces matches
+ /// containing 2 groups. For example:
+ ///
+ /// * ['//ignore: error_code', 'error_code']
+ ///
+ /// Resulting codes may be in a list ('error_code_1,error_code2').
+ static final RegExp _IGNORE_MATCHER =
+ new RegExp(r'//+[ ]*ignore:(.*)$', multiLine: true);
+
+ /// A regular expression for matching 'ignore_for_file' comments. Produces
+ /// matches containing 2 groups. For example:
+ ///
+ /// * ['//ignore_for_file: error_code', 'error_code']
+ ///
+ /// Resulting codes may be in a list ('error_code_1,error_code2').
+ static final RegExp _IGNORE_FOR_FILE_MATCHER =
+ new RegExp(r'//[ ]*ignore_for_file:(.*)$', multiLine: true);
+
+ final Map<int, List<String>> _ignoreMap = new HashMap<int, List<String>>();
+
+ final Set<String> _ignoreForFileSet = new HashSet<String>();
+
+ /// Whether this info object defines any ignores.
+ bool get hasIgnores => ignores.isNotEmpty || _ignoreForFileSet.isNotEmpty;
+
+ /// Iterable of error codes ignored for the whole file.
+ Iterable<String> get ignoreForFiles => _ignoreForFileSet;
+
+ /// Map of line numbers to associated ignored error codes.
+ Map<int, Iterable<String>> get ignores => _ignoreMap;
+
+ /// Ignore this [errorCode] at [line].
+ void add(int line, String errorCode) {
+ _ignoreMap.putIfAbsent(line, () => new List<String>()).add(errorCode);
+ }
+
+ /// Ignore these [errorCodes] at [line].
+ void addAll(int line, Iterable<String> errorCodes) {
+ _ignoreMap.putIfAbsent(line, () => new List<String>()).addAll(errorCodes);
+ }
+
+ /// Ignore these [errorCodes] in the whole file.
+ void addAllForFile(Iterable<String> errorCodes) {
+ _ignoreForFileSet.addAll(errorCodes);
+ }
+
+ /// Test whether this [errorCode] is ignored at the given [line].
+ bool ignoredAt(String errorCode, int line) =>
+ _ignoreForFileSet.contains(errorCode) ||
+ _ignoreMap[line]?.contains(errorCode) == true;
+
+ /// Calculate ignores for the given [content] with line [info].
+ static IgnoreInfo calculateIgnores(String content, LineInfo info) {
+ Iterable<Match> matches = _IGNORE_MATCHER.allMatches(content);
+ Iterable<Match> fileMatches = _IGNORE_FOR_FILE_MATCHER.allMatches(content);
+ if (matches.isEmpty && fileMatches.isEmpty) {
+ return _EMPTY_INFO;
+ }
+
+ IgnoreInfo ignoreInfo = new IgnoreInfo();
+ for (Match match in matches) {
+ // See _IGNORE_MATCHER for format --- note the possibility of error lists.
+ Iterable<String> codes = match
+ .group(1)
+ .split(',')
+ .map((String code) => code.trim().toLowerCase());
+ CharacterLocation location = info.getLocation(match.start);
+ int lineNumber = location.lineNumber;
+ String beforeMatch = content.substring(
+ info.getOffsetOfLine(lineNumber - 1),
+ info.getOffsetOfLine(lineNumber - 1) + location.columnNumber - 1);
+
+ if (beforeMatch.trim().isEmpty) {
+ // The comment is on its own line, so it refers to the next line.
+ ignoreInfo.addAll(lineNumber + 1, codes);
+ } else {
+ // The comment sits next to code, so it refers to its own line.
+ ignoreInfo.addAll(lineNumber, codes);
+ }
+ }
+ for (Match match in fileMatches) {
+ Iterable<String> codes = match
+ .group(1)
+ .split(',')
+ .map((String code) => code.trim().toLowerCase());
+ ignoreInfo.addAllForFile(codes);
+ }
+ return ignoreInfo;
+ }
+}
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index c9abd60..d62aaa0 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -34,8 +34,6 @@
import 'package:package_config/packages_file.dart' as pkgfile show parse;
import 'package:package_config/src/packages_impl.dart' show MapPackages;
import 'package:path/path.dart' as p;
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
import 'package:yaml/yaml.dart';
AnalysisOptionsProvider _optionsProvider = new AnalysisOptionsProvider();
@@ -125,9 +123,7 @@
final LinterOptions options;
- LintDriver(this.options) {
- _processPlugins();
- }
+ LintDriver(this.options);
/// Return the number of sources that have been analyzed so far.
int get numSourcesAnalyzed => _sourcesAnalyzed.length;
@@ -252,13 +248,6 @@
}
return null;
}
-
- void _processPlugins() {
- List<Plugin> plugins = <Plugin>[];
- plugins.addAll(AnalysisEngine.instance.requiredPlugins);
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(plugins);
- }
}
/// Prints logging information comments to the [outSink] and error messages to
diff --git a/pkg/analyzer/lib/src/plugin/engine_plugin.dart b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
deleted file mode 100644
index 6f97315..0000000
--- a/pkg/analyzer/lib/src/plugin/engine_plugin.dart
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/error/error.dart' show AnalysisError;
-import 'package:analyzer/src/generated/engine.dart'
- show InternalAnalysisContext;
-import 'package:analyzer/src/plugin/task.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/dart_work_manager.dart';
-import 'package:analyzer/src/task/options_work_manager.dart';
-import 'package:plugin/plugin.dart';
-
-/**
- * A plugin that defines the extension points and extensions that are inherently
- * defined by the analysis engine.
- */
-class EnginePlugin implements Plugin {
- /**
- * The simple identifier of the extension point that allows plugins to
- * register new analysis error results to compute for a Dart source.
- */
- static const String DART_ERRORS_FOR_SOURCE_EXTENSION_POINT =
- 'dartErrorsForSource';
-
- /**
- * The simple identifier of the extension point that allows plugins to
- * register new analysis error results to compute for a Dart library
- * specific unit.
- */
- static const String DART_ERRORS_FOR_UNIT_EXTENSION_POINT =
- 'dartErrorsForUnit';
-
- /**
- * The simple identifier of the extension point that allows plugins to
- * register new analysis error results to compute for an HTML source.
- */
- static const String HTML_ERRORS_EXTENSION_POINT = 'htmlErrors';
-
- /**
- * The simple identifier of the extension point that allows plugins to
- * register new work manager factories with the analysis engine.
- */
- static const String WORK_MANAGER_FACTORY_EXTENSION_POINT =
- 'workManagerFactory';
-
- /**
- * The unique identifier of this plugin.
- */
- static const String UNIQUE_IDENTIFIER = 'analysis_engine.core';
-
- /**
- * The extension point that allows plugins to register new analysis error
- * results for a Dart source.
- */
- ExtensionPoint<ListResultDescriptor<AnalysisError>>
- dartErrorsForSourceExtensionPoint;
-
- /**
- * The extension point that allows plugins to register new analysis error
- * results for a Dart library specific unit.
- */
- ExtensionPoint<ListResultDescriptor<AnalysisError>>
- dartErrorsForUnitExtensionPoint;
-
- /**
- * The extension point that allows plugins to register new analysis error
- * results for an HTML source.
- */
- ExtensionPoint<ListResultDescriptor<AnalysisError>> htmlErrorsExtensionPoint;
-
- /**
- * The extension point that allows plugins to register new work manager
- * factories with the analysis engine.
- */
- ExtensionPoint<WorkManagerFactory> workManagerFactoryExtensionPoint;
-
- /**
- * Initialize a newly created plugin.
- */
- EnginePlugin();
-
- /**
- * Return a list containing all of the contributed analysis error result
- * descriptors for Dart sources.
- */
- @ExtensionPointId('DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID')
- List<ListResultDescriptor<AnalysisError>> get dartErrorsForSource =>
- dartErrorsForSourceExtensionPoint.extensions;
-
- /**
- * Return a list containing all of the contributed analysis error result
- * descriptors for Dart library specific units.
- */
- @ExtensionPointId('DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID')
- List<ListResultDescriptor<AnalysisError>> get dartErrorsForUnit =>
- dartErrorsForUnitExtensionPoint.extensions;
-
- /**
- * Return a list containing all of the contributed analysis error result
- * descriptors for HTML sources.
- */
- @ExtensionPointId('HTML_ERRORS_EXTENSION_POINT_ID')
- List<ListResultDescriptor<AnalysisError>> get htmlErrors =>
- htmlErrorsExtensionPoint.extensions;
-
- @override
- String get uniqueIdentifier => UNIQUE_IDENTIFIER;
-
- /**
- * Return a list containing all of the work manager factories that were
- * contributed.
- */
- List<WorkManagerFactory> get workManagerFactories =>
- workManagerFactoryExtensionPoint.extensions;
-
- @override
- void registerExtensionPoints(RegisterExtensionPoint registerExtensionPoint) {
- dartErrorsForSourceExtensionPoint =
- new ExtensionPoint<ListResultDescriptor<AnalysisError>>(
- this, DART_ERRORS_FOR_SOURCE_EXTENSION_POINT, null);
- registerExtensionPoint(dartErrorsForSourceExtensionPoint);
- dartErrorsForUnitExtensionPoint =
- new ExtensionPoint<ListResultDescriptor<AnalysisError>>(
- this, DART_ERRORS_FOR_UNIT_EXTENSION_POINT, null);
- registerExtensionPoint(dartErrorsForUnitExtensionPoint);
- htmlErrorsExtensionPoint =
- new ExtensionPoint<ListResultDescriptor<AnalysisError>>(
- this, HTML_ERRORS_EXTENSION_POINT, null);
- registerExtensionPoint(htmlErrorsExtensionPoint);
- workManagerFactoryExtensionPoint = new ExtensionPoint<WorkManagerFactory>(
- this, WORK_MANAGER_FACTORY_EXTENSION_POINT, null);
- registerExtensionPoint(workManagerFactoryExtensionPoint);
- }
-
- @override
- void registerExtensions(RegisterExtension registerExtension) {
- _registerWorkManagerFactoryExtensions(registerExtension);
- _registerDartErrorsForSource(registerExtension);
- _registerDartErrorsForUnit(registerExtension);
- }
-
- void _registerDartErrorsForSource(RegisterExtension registerExtension) {
- registerExtension(DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID, PARSE_ERRORS);
- registerExtension(DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID, SCAN_ERRORS);
- }
-
- void _registerDartErrorsForUnit(RegisterExtension registerExtension) {
- registerExtension(
- DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID, LIBRARY_UNIT_ERRORS);
- }
-
- void _registerWorkManagerFactoryExtensions(
- RegisterExtension registerExtension) {
- String taskId = WORK_MANAGER_EXTENSION_POINT_ID;
- registerExtension(taskId,
- (InternalAnalysisContext context) => new DartWorkManager(context));
- registerExtension(taskId,
- (InternalAnalysisContext context) => new OptionsWorkManager(context));
- }
-}
-
-/**
- * Annotation describing the relationship between a getter in [EnginePlugin]
- * and the associated identifier (in 'task.dart') which can be passed to the
- * extension manager to populate it.
- *
- * This annotation is not used at runtime; it is used to aid in static analysis
- * of the task model during development.
- */
-class ExtensionPointId {
- final String extensionPointId;
-
- const ExtensionPointId(this.extensionPointId);
-}
diff --git a/pkg/analyzer/lib/src/plugin/task.dart b/pkg/analyzer/lib/src/plugin/task.dart
index 8292485..fec6844 100644
--- a/pkg/analyzer/lib/src/plugin/task.dart
+++ b/pkg/analyzer/lib/src/plugin/task.dart
@@ -7,44 +7,7 @@
* analysis tasks.
*/
import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/plugin/engine_plugin.dart';
import 'package:analyzer/src/task/api/model.dart';
-import 'package:plugin/plugin.dart';
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * analysis error results to compute for a Dart source. The object used as an
- * extension must be a [ResultDescriptor].
- */
-final String DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID = Plugin.join(
- EnginePlugin.UNIQUE_IDENTIFIER,
- EnginePlugin.DART_ERRORS_FOR_SOURCE_EXTENSION_POINT);
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * analysis error results to compute for a Dart library specific unit. The
- * object used as an extension must be a [ResultDescriptor].
- */
-final String DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID = Plugin.join(
- EnginePlugin.UNIQUE_IDENTIFIER,
- EnginePlugin.DART_ERRORS_FOR_UNIT_EXTENSION_POINT);
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * analysis error results to compute for an HTML source. The object used as an
- * extension must be a [ResultDescriptor].
- */
-final String HTML_ERRORS_EXTENSION_POINT_ID = Plugin.join(
- EnginePlugin.UNIQUE_IDENTIFIER, EnginePlugin.HTML_ERRORS_EXTENSION_POINT);
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * work managers with the analysis engine. The object used as an extension must
- * be a [WorkManagerFactory].
- */
-final String WORK_MANAGER_EXTENSION_POINT_ID = Plugin.join(
- EnginePlugin.UNIQUE_IDENTIFIER,
- EnginePlugin.WORK_MANAGER_FACTORY_EXTENSION_POINT);
/**
* A function that will create a new [WorkManager] for the given [context].
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 4ec0123..aaed6fe 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -624,6 +624,7 @@
var isLibrary = file.isLibrary;
var library = isLibrary ? file : file.library;
+ if (library == null) return;
if (isLibrary) {
file.refresh(containingContext);
diff --git a/pkg/analyzer/lib/src/summary/expr_builder.dart b/pkg/analyzer/lib/src/summary/expr_builder.dart
index 3301d95..960e342 100644
--- a/pkg/analyzer/lib/src/summary/expr_builder.dart
+++ b/pkg/analyzer/lib/src/summary/expr_builder.dart
@@ -17,7 +17,7 @@
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/resynthesize.dart';
-bool _isSetOrMapEnabled(ExperimentStatus experimentStatus) =>
+bool _isSpreadOrControlFlowEnabled(ExperimentStatus experimentStatus) =>
experimentStatus.spread_collections ||
experimentStatus.control_flow_collections;
@@ -31,7 +31,8 @@
final ElementImpl context;
final UnlinkedExpr _uc;
final bool requireValidConst;
- final bool useSetOrMap;
+ final bool isSpreadOrControlFlowEnabled;
+ final bool becomeSetOrMap;
int intPtr = 0;
int doublePtr = 0;
@@ -47,15 +48,20 @@
final Map<String, ParameterElement> parametersInScope;
- ExprBuilder(this.resynthesizer, this.context, this._uc,
- {this.requireValidConst: true,
- this.localFunctions,
- Map<String, ParameterElement> parametersInScope})
- : this.parametersInScope =
+ ExprBuilder(
+ this.resynthesizer,
+ this.context,
+ this._uc, {
+ this.requireValidConst: true,
+ this.localFunctions,
+ Map<String, ParameterElement> parametersInScope,
+ this.becomeSetOrMap: true,
+ }) : this.parametersInScope =
parametersInScope ?? _parametersInScope(context),
- this.useSetOrMap = _isSetOrMapEnabled((resynthesizer
- .library.context.analysisOptions as AnalysisOptionsImpl)
- .experimentStatus);
+ this.isSpreadOrControlFlowEnabled = _isSpreadOrControlFlowEnabled(
+ (resynthesizer.library.context.analysisOptions
+ as AnalysisOptionsImpl)
+ .experimentStatus);
bool get hasNonEmptyExpr => _uc != null && _uc.operations.isNotEmpty;
@@ -234,7 +240,7 @@
break;
case UnlinkedExprOperation.makeTypedSet:
TypeAnnotation itemType = _newTypeName();
- if (useSetOrMap) {
+ if (isSpreadOrControlFlowEnabled) {
_pushSetOrMap(
AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType]));
} else {
@@ -311,6 +317,18 @@
case UnlinkedExprOperation.pushThis:
_push(AstTestFactory.thisExpression());
break;
+ case UnlinkedExprOperation.spreadElement:
+ _pushSpread(TokenType.PERIOD_PERIOD_PERIOD);
+ break;
+ case UnlinkedExprOperation.nullAwareSpreadElement:
+ _pushSpread(TokenType.PERIOD_PERIOD_PERIOD_QUESTION);
+ break;
+ case UnlinkedExprOperation.ifElement:
+ _pushIfElement(false);
+ break;
+ case UnlinkedExprOperation.ifElseElement:
+ _pushIfElement(true);
+ break;
case UnlinkedExprOperation.cascadeSectionBegin:
case UnlinkedExprOperation.cascadeSectionEnd:
case UnlinkedExprOperation.pushLocalFunctionReference:
@@ -613,7 +631,7 @@
CollectionElement _popCollectionElement() => stack.removeLast();
- void _push(Expression expr) {
+ void _push(CollectionElement expr) {
stack.add(expr);
}
@@ -638,6 +656,13 @@
_push(AstTestFactory.propertyAccess(target, propertyNode));
}
+ void _pushIfElement(bool hasElse) {
+ CollectionElement elseElement = hasElse ? _popCollectionElement() : null;
+ CollectionElement thenElement = _popCollectionElement();
+ Expression condition = _pop();
+ _push(AstTestFactory.ifElement(condition, thenElement, elseElement));
+ }
+
void _pushInstanceCreation() {
EntityRef ref = _uc.references[refPtr++];
ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
@@ -750,9 +775,10 @@
void _pushList(TypeArgumentList typeArguments) {
int count = _uc.ints[intPtr++];
- List<Expression> elements = <Expression>[];
+ List<CollectionElement> elements =
+ isSpreadOrControlFlowEnabled ? <CollectionElement>[] : <Expression>[];
for (int i = 0; i < count; i++) {
- elements.insert(0, _pop());
+ elements.insert(0, _popCollectionElement());
}
var typeArg = typeArguments == null
? resynthesizer.typeProvider.dynamicType
@@ -825,7 +851,7 @@
: typeArguments.arguments[1].type;
var staticType =
resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
- if (useSetOrMap) {
+ if (isSpreadOrControlFlowEnabled) {
_push(
AstTestFactory.setOrMapLiteral(Keyword.CONST, typeArguments, entries)
..staticType = staticType);
@@ -865,27 +891,54 @@
int count = _uc.ints[intPtr++];
List<CollectionElement> elements = <CollectionElement>[];
for (int i = 0; i < count; i++) {
- elements.add(_popCollectionElement());
+ elements.insert(0, _popCollectionElement());
}
+
+ bool isMap = true; // assume Map unless can prove otherwise
DartType staticType;
- if (typeArguments != null && typeArguments.arguments.length == 2) {
- var keyType = typeArguments.arguments[0].type;
- var valueType = typeArguments.arguments[1].type;
- staticType =
- resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
- } else if (typeArguments != null && typeArguments.arguments.length == 1) {
- var valueType = typeArguments == null
- ? resynthesizer.typeProvider.dynamicType
- : typeArguments.arguments[0].type;
- staticType = resynthesizer.typeProvider.setType.instantiate([valueType]);
+ if (typeArguments != null) {
+ if (typeArguments.arguments.length == 2) {
+ var keyType = typeArguments.arguments[0].type;
+ var valueType = typeArguments.arguments[1].type;
+ staticType = resynthesizer.typeProvider.mapType
+ .instantiate([keyType, valueType]);
+ } else if (typeArguments.arguments.length == 1) {
+ isMap = false;
+ var valueType = typeArguments == null
+ ? resynthesizer.typeProvider.dynamicType
+ : typeArguments.arguments[0].type;
+ staticType =
+ resynthesizer.typeProvider.setType.instantiate([valueType]);
+ }
+ } else {
+ for (var i = 0; i < elements.length; ++i) {
+ var element = elements[i];
+ if (element is Expression) {
+ isMap = false;
+ }
+ }
}
- _push(astFactory.setOrMapLiteral(
- constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
- typeArguments: typeArguments,
- leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
- elements: elements,
- rightBracket: TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET))
- ..staticType = staticType);
+
+ SetOrMapLiteral setOrMapLiteral = astFactory.setOrMapLiteral(
+ constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
+ typeArguments: typeArguments,
+ leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
+ elements: elements,
+ rightBracket: TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET),
+ );
+ if (becomeSetOrMap) {
+ if (isMap) {
+ (setOrMapLiteral as SetOrMapLiteralImpl).becomeMap();
+ } else {
+ (setOrMapLiteral as SetOrMapLiteralImpl).becomeSet();
+ }
+ }
+ _push(setOrMapLiteral..staticType = staticType);
+ }
+
+ void _pushSpread(TokenType operator) {
+ Expression operand = _pop();
+ _push(AstTestFactory.spreadElement(operator, operand));
}
List<Expression> _removeTopExpressions(int count) {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index f77a8b6..ca27841f 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -4571,6 +4571,7 @@
bool _variantField_31;
String _variantField_20;
String _variantField_22;
+ LinkedNodeVariablesDeclarationBuilder _variantField_32;
@override
List<LinkedNodeBuilder> get adjacentStrings_strings {
@@ -8781,6 +8782,12 @@
}
@override
+ int get methodDeclaration_actualProperty {
+ assert(kind == idl.LinkedNodeKind.methodDeclaration);
+ return _variantField_19 ??= 0;
+ }
+
+ @override
int get normalFormalParameter_covariantKeyword {
assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -8862,6 +8869,12 @@
_variantField_19 = value;
}
+ void set methodDeclaration_actualProperty(int value) {
+ assert(kind == idl.LinkedNodeKind.methodDeclaration);
+ assert(value == null || value >= 0);
+ _variantField_19 = value;
+ }
+
void set normalFormalParameter_covariantKeyword(int value) {
assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -8906,6 +8919,30 @@
}
@override
+ LinkedNodeTypeBuilder get fieldFormalParameter_type2 {
+ assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+ return _variantField_24;
+ }
+
+ @override
+ LinkedNodeTypeBuilder get functionDeclaration_returnType2 {
+ assert(kind == idl.LinkedNodeKind.functionDeclaration);
+ return _variantField_24;
+ }
+
+ @override
+ LinkedNodeTypeBuilder get functionTypeAlias_returnType2 {
+ assert(kind == idl.LinkedNodeKind.functionTypeAlias);
+ return _variantField_24;
+ }
+
+ @override
+ LinkedNodeTypeBuilder get genericFunctionType_returnType2 {
+ assert(kind == idl.LinkedNodeKind.genericFunctionType);
+ return _variantField_24;
+ }
+
+ @override
LinkedNodeTypeBuilder get invocationExpression_invokeType {
assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
kind == idl.LinkedNodeKind.methodInvocation);
@@ -8913,27 +8950,80 @@
}
@override
+ LinkedNodeTypeBuilder get methodDeclaration_returnType2 {
+ assert(kind == idl.LinkedNodeKind.methodDeclaration);
+ return _variantField_24;
+ }
+
+ @override
+ LinkedNodeTypeBuilder get simpleFormalParameter_type2 {
+ assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+ return _variantField_24;
+ }
+
+ @override
LinkedNodeTypeBuilder get typeName_type {
assert(kind == idl.LinkedNodeKind.typeName);
return _variantField_24;
}
+ @override
+ LinkedNodeTypeBuilder get variableDeclaration_type2 {
+ assert(kind == idl.LinkedNodeKind.variableDeclaration);
+ return _variantField_24;
+ }
+
void set binaryExpression_invokeType(LinkedNodeTypeBuilder value) {
assert(kind == idl.LinkedNodeKind.binaryExpression);
_variantField_24 = value;
}
+ void set fieldFormalParameter_type2(LinkedNodeTypeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+ _variantField_24 = value;
+ }
+
+ void set functionDeclaration_returnType2(LinkedNodeTypeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.functionDeclaration);
+ _variantField_24 = value;
+ }
+
+ void set functionTypeAlias_returnType2(LinkedNodeTypeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.functionTypeAlias);
+ _variantField_24 = value;
+ }
+
+ void set genericFunctionType_returnType2(LinkedNodeTypeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.genericFunctionType);
+ _variantField_24 = value;
+ }
+
void set invocationExpression_invokeType(LinkedNodeTypeBuilder value) {
assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
kind == idl.LinkedNodeKind.methodInvocation);
_variantField_24 = value;
}
+ void set methodDeclaration_returnType2(LinkedNodeTypeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.methodDeclaration);
+ _variantField_24 = value;
+ }
+
+ void set simpleFormalParameter_type2(LinkedNodeTypeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+ _variantField_24 = value;
+ }
+
void set typeName_type(LinkedNodeTypeBuilder value) {
assert(kind == idl.LinkedNodeKind.typeName);
_variantField_24 = value;
}
+ void set variableDeclaration_type2(LinkedNodeTypeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.variableDeclaration);
+ _variantField_24 = value;
+ }
+
@override
bool get booleanLiteral_value {
assert(kind == idl.LinkedNodeKind.booleanLiteral);
@@ -8941,12 +9031,26 @@
}
@override
+ bool get classDeclaration_isDartObject {
+ assert(kind == idl.LinkedNodeKind.classDeclaration);
+ return _variantField_27 ??= false;
+ }
+
+ @override
bool get defaultFormalParameter_isNamed {
assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
return _variantField_27 ??= false;
}
@override
+ bool get normalFormalParameter_isCovariant {
+ assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+ kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+ kind == idl.LinkedNodeKind.simpleFormalParameter);
+ return _variantField_27 ??= false;
+ }
+
+ @override
bool get setOrMapLiteral_isMap {
assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
return _variantField_27 ??= false;
@@ -8957,11 +9061,23 @@
_variantField_27 = value;
}
+ void set classDeclaration_isDartObject(bool value) {
+ assert(kind == idl.LinkedNodeKind.classDeclaration);
+ _variantField_27 = value;
+ }
+
void set defaultFormalParameter_isNamed(bool value) {
assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
_variantField_27 = value;
}
+ void set normalFormalParameter_isCovariant(bool value) {
+ assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+ kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+ kind == idl.LinkedNodeKind.simpleFormalParameter);
+ _variantField_27 = value;
+ }
+
void set setOrMapLiteral_isMap(bool value) {
assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
_variantField_27 = value;
@@ -9454,6 +9570,18 @@
_variantField_22 = value;
}
+ @override
+ LinkedNodeVariablesDeclarationBuilder get variableDeclaration_declaration {
+ assert(kind == idl.LinkedNodeKind.variableDeclaration);
+ return _variantField_32;
+ }
+
+ void set variableDeclaration_declaration(
+ LinkedNodeVariablesDeclarationBuilder value) {
+ assert(kind == idl.LinkedNodeKind.variableDeclaration);
+ _variantField_32 = value;
+ }
+
LinkedNodeBuilder.adjacentStrings({
List<LinkedNodeBuilder> adjacentStrings_strings,
LinkedNodeTypeBuilder expression_type,
@@ -9775,6 +9903,7 @@
int classDeclaration_classKeyword,
int classOrMixinDeclaration_rightBracket,
int classOrMixinDeclaration_leftBracket,
+ bool classDeclaration_isDartObject,
LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
List<LinkedNodeBuilder> classOrMixinDeclaration_members,
LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
@@ -9788,6 +9917,7 @@
_variantField_16 = classDeclaration_classKeyword,
_variantField_18 = classOrMixinDeclaration_rightBracket,
_variantField_19 = classOrMixinDeclaration_leftBracket,
+ _variantField_27 = classDeclaration_isDartObject,
_variantField_12 = classOrMixinDeclaration_implementsClause,
_variantField_5 = classOrMixinDeclaration_members,
_variantField_13 = classOrMixinDeclaration_typeParameters,
@@ -9862,6 +9992,7 @@
int functionDeclaration_externalKeyword,
LinkedNodeBuilder functionDeclaration_returnType,
int functionDeclaration_propertyKeyword,
+ LinkedNodeTypeBuilder functionDeclaration_returnType2,
LinkedNodeBuilder namedCompilationUnitMember_name,
}) : _kind = idl.LinkedNodeKind.functionDeclaration,
_variantField_11 = annotatedNode_comment,
@@ -9870,6 +10001,7 @@
_variantField_15 = functionDeclaration_externalKeyword,
_variantField_7 = functionDeclaration_returnType,
_variantField_16 = functionDeclaration_propertyKeyword,
+ _variantField_24 = functionDeclaration_returnType2,
_variantField_14 = namedCompilationUnitMember_name;
LinkedNodeBuilder.functionTypeAlias({
@@ -9880,6 +10012,7 @@
LinkedNodeBuilder functionTypeAlias_typeParameters,
int typeAlias_typedefKeyword,
int typeAlias_semicolon,
+ LinkedNodeTypeBuilder functionTypeAlias_returnType2,
LinkedNodeBuilder namedCompilationUnitMember_name,
}) : _kind = idl.LinkedNodeKind.functionTypeAlias,
_variantField_11 = annotatedNode_comment,
@@ -9889,6 +10022,7 @@
_variantField_8 = functionTypeAlias_typeParameters,
_variantField_18 = typeAlias_typedefKeyword,
_variantField_19 = typeAlias_semicolon,
+ _variantField_24 = functionTypeAlias_returnType2,
_variantField_14 = namedCompilationUnitMember_name;
LinkedNodeBuilder.genericTypeAlias({
@@ -9933,6 +10067,8 @@
int methodDeclaration_modifierKeyword,
int methodDeclaration_operatorKeyword,
int methodDeclaration_propertyKeyword,
+ int methodDeclaration_actualProperty,
+ LinkedNodeTypeBuilder methodDeclaration_returnType2,
LinkedNodeBuilder methodDeclaration_typeParameters,
LinkedNodeBuilder methodDeclaration_name,
}) : _kind = idl.LinkedNodeKind.methodDeclaration,
@@ -9945,6 +10081,8 @@
_variantField_16 = methodDeclaration_modifierKeyword,
_variantField_17 = methodDeclaration_operatorKeyword,
_variantField_18 = methodDeclaration_propertyKeyword,
+ _variantField_19 = methodDeclaration_actualProperty,
+ _variantField_24 = methodDeclaration_returnType2,
_variantField_9 = methodDeclaration_typeParameters,
_variantField_10 = methodDeclaration_name;
@@ -10039,12 +10177,16 @@
LinkedNodeBuilder variableDeclaration_initializer,
int variableDeclaration_equals,
LinkedNodeBuilder variableDeclaration_name,
+ LinkedNodeTypeBuilder variableDeclaration_type2,
+ LinkedNodeVariablesDeclarationBuilder variableDeclaration_declaration,
}) : _kind = idl.LinkedNodeKind.variableDeclaration,
_variantField_11 = annotatedNode_comment,
_variantField_4 = annotatedNode_metadata,
_variantField_6 = variableDeclaration_initializer,
_variantField_15 = variableDeclaration_equals,
- _variantField_7 = variableDeclaration_name;
+ _variantField_7 = variableDeclaration_name,
+ _variantField_24 = variableDeclaration_type2,
+ _variantField_32 = variableDeclaration_declaration;
LinkedNodeBuilder.fieldFormalParameter({
List<LinkedNodeBuilder> normalFormalParameter_metadata,
@@ -10055,6 +10197,8 @@
int fieldFormalParameter_period,
int fieldFormalParameter_thisKeyword,
int normalFormalParameter_covariantKeyword,
+ LinkedNodeTypeBuilder fieldFormalParameter_type2,
+ bool normalFormalParameter_isCovariant,
LinkedNodeBuilder normalFormalParameter_identifier,
idl.LinkedNodeFormalParameterKind formalParameter_kind,
LinkedNodeBuilder normalFormalParameter_comment,
@@ -10067,6 +10211,8 @@
_variantField_16 = fieldFormalParameter_period,
_variantField_17 = fieldFormalParameter_thisKeyword,
_variantField_19 = normalFormalParameter_covariantKeyword,
+ _variantField_24 = fieldFormalParameter_type2,
+ _variantField_27 = normalFormalParameter_isCovariant,
_variantField_12 = normalFormalParameter_identifier,
_variantField_26 = formalParameter_kind,
_variantField_14 = normalFormalParameter_comment;
@@ -10077,6 +10223,7 @@
LinkedNodeBuilder functionTypedFormalParameter_returnType,
LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
int normalFormalParameter_covariantKeyword,
+ bool normalFormalParameter_isCovariant,
LinkedNodeBuilder normalFormalParameter_identifier,
idl.LinkedNodeFormalParameterKind formalParameter_kind,
LinkedNodeBuilder normalFormalParameter_comment,
@@ -10086,6 +10233,7 @@
_variantField_7 = functionTypedFormalParameter_returnType,
_variantField_8 = functionTypedFormalParameter_typeParameters,
_variantField_19 = normalFormalParameter_covariantKeyword,
+ _variantField_27 = normalFormalParameter_isCovariant,
_variantField_12 = normalFormalParameter_identifier,
_variantField_26 = formalParameter_kind,
_variantField_14 = normalFormalParameter_comment;
@@ -10095,6 +10243,8 @@
LinkedNodeBuilder simpleFormalParameter_type,
int simpleFormalParameter_keyword,
int normalFormalParameter_covariantKeyword,
+ LinkedNodeTypeBuilder simpleFormalParameter_type2,
+ bool normalFormalParameter_isCovariant,
LinkedNodeBuilder normalFormalParameter_identifier,
idl.LinkedNodeFormalParameterKind formalParameter_kind,
LinkedNodeBuilder normalFormalParameter_comment,
@@ -10103,6 +10253,8 @@
_variantField_6 = simpleFormalParameter_type,
_variantField_15 = simpleFormalParameter_keyword,
_variantField_19 = normalFormalParameter_covariantKeyword,
+ _variantField_24 = simpleFormalParameter_type2,
+ _variantField_27 = normalFormalParameter_isCovariant,
_variantField_12 = normalFormalParameter_identifier,
_variantField_26 = formalParameter_kind,
_variantField_14 = normalFormalParameter_comment;
@@ -10488,12 +10640,14 @@
LinkedNodeBuilder genericFunctionType_returnType,
LinkedNodeBuilder genericFunctionType_formalParameters,
int genericFunctionType_question,
+ LinkedNodeTypeBuilder genericFunctionType_returnType2,
}) : _kind = idl.LinkedNodeKind.genericFunctionType,
_variantField_6 = genericFunctionType_typeParameters,
_variantField_15 = genericFunctionType_functionKeyword,
_variantField_7 = genericFunctionType_returnType,
_variantField_8 = genericFunctionType_formalParameters,
- _variantField_16 = genericFunctionType_question;
+ _variantField_16 = genericFunctionType_question,
+ _variantField_24 = genericFunctionType_returnType2;
LinkedNodeBuilder.ifElement({
LinkedNodeBuilder ifMixin_condition,
@@ -10899,6 +11053,7 @@
_variantField_10?.flushInformative();
_variantField_25?.flushInformative();
_variantField_14?.flushInformative();
+ _variantField_32?.flushInformative();
}
/**
@@ -10985,6 +11140,8 @@
this._variantField_29 == null ? 0 : this._variantField_29.index);
signature.addString(this._variantField_30 ?? '');
signature.addBool(this._variantField_31 == true);
+ signature.addBool(this._variantField_32 != null);
+ this._variantField_32?.collectApiSignature(signature);
}
fb.Offset finish(fb.Builder fbBuilder) {
@@ -11008,6 +11165,7 @@
fb.Offset offset_variantField_23;
fb.Offset offset_variantField_20;
fb.Offset offset_variantField_22;
+ fb.Offset offset_variantField_32;
if (!(_variantField_2 == null || _variantField_2.isEmpty)) {
offset_variantField_2 = fbBuilder
.writeList(_variantField_2.map((b) => b.finish(fbBuilder)).toList());
@@ -11072,6 +11230,9 @@
if (_variantField_22 != null) {
offset_variantField_22 = fbBuilder.writeString(_variantField_22);
}
+ if (_variantField_32 != null) {
+ offset_variantField_32 = _variantField_32.finish(fbBuilder);
+ }
fbBuilder.startTable();
if (offset_variantField_2 != null) {
fbBuilder.addOffset(2, offset_variantField_2);
@@ -11171,6 +11332,9 @@
if (offset_variantField_22 != null) {
fbBuilder.addOffset(22, offset_variantField_22);
}
+ if (offset_variantField_32 != null) {
+ fbBuilder.addOffset(32, offset_variantField_32);
+ }
return fbBuilder.endTable();
}
}
@@ -11223,6 +11387,7 @@
bool _variantField_31;
String _variantField_20;
String _variantField_22;
+ idl.LinkedNodeVariablesDeclaration _variantField_32;
@override
List<idl.LinkedNode> get adjacentStrings_strings {
@@ -14174,6 +14339,14 @@
}
@override
+ int get methodDeclaration_actualProperty {
+ assert(kind == idl.LinkedNodeKind.methodDeclaration);
+ _variantField_19 ??=
+ const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
+ return _variantField_19;
+ }
+
+ @override
int get normalFormalParameter_covariantKeyword {
assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -14229,6 +14402,38 @@
}
@override
+ idl.LinkedNodeType get fieldFormalParameter_type2 {
+ assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+ _variantField_24 ??=
+ const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+ return _variantField_24;
+ }
+
+ @override
+ idl.LinkedNodeType get functionDeclaration_returnType2 {
+ assert(kind == idl.LinkedNodeKind.functionDeclaration);
+ _variantField_24 ??=
+ const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+ return _variantField_24;
+ }
+
+ @override
+ idl.LinkedNodeType get functionTypeAlias_returnType2 {
+ assert(kind == idl.LinkedNodeKind.functionTypeAlias);
+ _variantField_24 ??=
+ const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+ return _variantField_24;
+ }
+
+ @override
+ idl.LinkedNodeType get genericFunctionType_returnType2 {
+ assert(kind == idl.LinkedNodeKind.genericFunctionType);
+ _variantField_24 ??=
+ const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+ return _variantField_24;
+ }
+
+ @override
idl.LinkedNodeType get invocationExpression_invokeType {
assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
kind == idl.LinkedNodeKind.methodInvocation);
@@ -14238,6 +14443,22 @@
}
@override
+ idl.LinkedNodeType get methodDeclaration_returnType2 {
+ assert(kind == idl.LinkedNodeKind.methodDeclaration);
+ _variantField_24 ??=
+ const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+ return _variantField_24;
+ }
+
+ @override
+ idl.LinkedNodeType get simpleFormalParameter_type2 {
+ assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+ _variantField_24 ??=
+ const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+ return _variantField_24;
+ }
+
+ @override
idl.LinkedNodeType get typeName_type {
assert(kind == idl.LinkedNodeKind.typeName);
_variantField_24 ??=
@@ -14246,6 +14467,14 @@
}
@override
+ idl.LinkedNodeType get variableDeclaration_type2 {
+ assert(kind == idl.LinkedNodeKind.variableDeclaration);
+ _variantField_24 ??=
+ const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+ return _variantField_24;
+ }
+
+ @override
bool get booleanLiteral_value {
assert(kind == idl.LinkedNodeKind.booleanLiteral);
_variantField_27 ??=
@@ -14254,6 +14483,14 @@
}
@override
+ bool get classDeclaration_isDartObject {
+ assert(kind == idl.LinkedNodeKind.classDeclaration);
+ _variantField_27 ??=
+ const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
+ return _variantField_27;
+ }
+
+ @override
bool get defaultFormalParameter_isNamed {
assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
_variantField_27 ??=
@@ -14262,6 +14499,16 @@
}
@override
+ bool get normalFormalParameter_isCovariant {
+ assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+ kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+ kind == idl.LinkedNodeKind.simpleFormalParameter);
+ _variantField_27 ??=
+ const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
+ return _variantField_27;
+ }
+
+ @override
bool get setOrMapLiteral_isMap {
assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
_variantField_27 ??=
@@ -14601,6 +14848,14 @@
const fb.StringReader().vTableGet(_bc, _bcOffset, 22, '');
return _variantField_22;
}
+
+ @override
+ idl.LinkedNodeVariablesDeclaration get variableDeclaration_declaration {
+ assert(kind == idl.LinkedNodeKind.variableDeclaration);
+ _variantField_32 ??= const _LinkedNodeVariablesDeclarationReader()
+ .vTableGet(_bc, _bcOffset, 32, null);
+ return _variantField_32;
+ }
}
abstract class _LinkedNodeMixin implements idl.LinkedNode {
@@ -15014,6 +15269,9 @@
if (classOrMixinDeclaration_leftBracket != 0)
_result["classOrMixinDeclaration_leftBracket"] =
classOrMixinDeclaration_leftBracket;
+ if (classDeclaration_isDartObject != false)
+ _result["classDeclaration_isDartObject"] =
+ classDeclaration_isDartObject;
if (classOrMixinDeclaration_implementsClause != null)
_result["classOrMixinDeclaration_implementsClause"] =
classOrMixinDeclaration_implementsClause.toJson();
@@ -15119,6 +15377,9 @@
if (functionDeclaration_propertyKeyword != 0)
_result["functionDeclaration_propertyKeyword"] =
functionDeclaration_propertyKeyword;
+ if (functionDeclaration_returnType2 != null)
+ _result["functionDeclaration_returnType2"] =
+ functionDeclaration_returnType2.toJson();
if (namedCompilationUnitMember_name != null)
_result["namedCompilationUnitMember_name"] =
namedCompilationUnitMember_name.toJson();
@@ -15142,6 +15403,9 @@
_result["typeAlias_typedefKeyword"] = typeAlias_typedefKeyword;
if (typeAlias_semicolon != 0)
_result["typeAlias_semicolon"] = typeAlias_semicolon;
+ if (functionTypeAlias_returnType2 != null)
+ _result["functionTypeAlias_returnType2"] =
+ functionTypeAlias_returnType2.toJson();
if (namedCompilationUnitMember_name != null)
_result["namedCompilationUnitMember_name"] =
namedCompilationUnitMember_name.toJson();
@@ -15207,6 +15471,12 @@
if (methodDeclaration_propertyKeyword != 0)
_result["methodDeclaration_propertyKeyword"] =
methodDeclaration_propertyKeyword;
+ if (methodDeclaration_actualProperty != 0)
+ _result["methodDeclaration_actualProperty"] =
+ methodDeclaration_actualProperty;
+ if (methodDeclaration_returnType2 != null)
+ _result["methodDeclaration_returnType2"] =
+ methodDeclaration_returnType2.toJson();
if (methodDeclaration_typeParameters != null)
_result["methodDeclaration_typeParameters"] =
methodDeclaration_typeParameters.toJson();
@@ -15326,6 +15596,12 @@
_result["variableDeclaration_equals"] = variableDeclaration_equals;
if (variableDeclaration_name != null)
_result["variableDeclaration_name"] = variableDeclaration_name.toJson();
+ if (variableDeclaration_type2 != null)
+ _result["variableDeclaration_type2"] =
+ variableDeclaration_type2.toJson();
+ if (variableDeclaration_declaration != null)
+ _result["variableDeclaration_declaration"] =
+ variableDeclaration_declaration.toJson();
}
if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
if (normalFormalParameter_metadata.isNotEmpty)
@@ -15352,6 +15628,12 @@
if (normalFormalParameter_covariantKeyword != 0)
_result["normalFormalParameter_covariantKeyword"] =
normalFormalParameter_covariantKeyword;
+ if (fieldFormalParameter_type2 != null)
+ _result["fieldFormalParameter_type2"] =
+ fieldFormalParameter_type2.toJson();
+ if (normalFormalParameter_isCovariant != false)
+ _result["normalFormalParameter_isCovariant"] =
+ normalFormalParameter_isCovariant;
if (normalFormalParameter_identifier != null)
_result["normalFormalParameter_identifier"] =
normalFormalParameter_identifier.toJson();
@@ -15380,6 +15662,9 @@
if (normalFormalParameter_covariantKeyword != 0)
_result["normalFormalParameter_covariantKeyword"] =
normalFormalParameter_covariantKeyword;
+ if (normalFormalParameter_isCovariant != false)
+ _result["normalFormalParameter_isCovariant"] =
+ normalFormalParameter_isCovariant;
if (normalFormalParameter_identifier != null)
_result["normalFormalParameter_identifier"] =
normalFormalParameter_identifier.toJson();
@@ -15405,6 +15690,12 @@
if (normalFormalParameter_covariantKeyword != 0)
_result["normalFormalParameter_covariantKeyword"] =
normalFormalParameter_covariantKeyword;
+ if (simpleFormalParameter_type2 != null)
+ _result["simpleFormalParameter_type2"] =
+ simpleFormalParameter_type2.toJson();
+ if (normalFormalParameter_isCovariant != false)
+ _result["normalFormalParameter_isCovariant"] =
+ normalFormalParameter_isCovariant;
if (normalFormalParameter_identifier != null)
_result["normalFormalParameter_identifier"] =
normalFormalParameter_identifier.toJson();
@@ -15832,6 +16123,9 @@
genericFunctionType_formalParameters.toJson();
if (genericFunctionType_question != 0)
_result["genericFunctionType_question"] = genericFunctionType_question;
+ if (genericFunctionType_returnType2 != null)
+ _result["genericFunctionType_returnType2"] =
+ genericFunctionType_returnType2.toJson();
}
if (kind == idl.LinkedNodeKind.ifElement) {
if (ifMixin_condition != null)
@@ -16519,6 +16813,7 @@
classOrMixinDeclaration_rightBracket,
"classOrMixinDeclaration_leftBracket":
classOrMixinDeclaration_leftBracket,
+ "classDeclaration_isDartObject": classDeclaration_isDartObject,
"classOrMixinDeclaration_implementsClause":
classOrMixinDeclaration_implementsClause,
"classOrMixinDeclaration_members": classOrMixinDeclaration_members,
@@ -16589,6 +16884,7 @@
"functionDeclaration_returnType": functionDeclaration_returnType,
"functionDeclaration_propertyKeyword":
functionDeclaration_propertyKeyword,
+ "functionDeclaration_returnType2": functionDeclaration_returnType2,
"namedCompilationUnitMember_name": namedCompilationUnitMember_name,
"isSynthetic": isSynthetic,
"kind": kind,
@@ -16604,6 +16900,7 @@
"functionTypeAlias_typeParameters": functionTypeAlias_typeParameters,
"typeAlias_typedefKeyword": typeAlias_typedefKeyword,
"typeAlias_semicolon": typeAlias_semicolon,
+ "functionTypeAlias_returnType2": functionTypeAlias_returnType2,
"namedCompilationUnitMember_name": namedCompilationUnitMember_name,
"isSynthetic": isSynthetic,
"kind": kind,
@@ -16646,6 +16943,8 @@
"methodDeclaration_modifierKeyword": methodDeclaration_modifierKeyword,
"methodDeclaration_operatorKeyword": methodDeclaration_operatorKeyword,
"methodDeclaration_propertyKeyword": methodDeclaration_propertyKeyword,
+ "methodDeclaration_actualProperty": methodDeclaration_actualProperty,
+ "methodDeclaration_returnType2": methodDeclaration_returnType2,
"methodDeclaration_typeParameters": methodDeclaration_typeParameters,
"methodDeclaration_name": methodDeclaration_name,
"isSynthetic": isSynthetic,
@@ -16732,8 +17031,10 @@
"variableDeclaration_initializer": variableDeclaration_initializer,
"variableDeclaration_equals": variableDeclaration_equals,
"variableDeclaration_name": variableDeclaration_name,
+ "variableDeclaration_type2": variableDeclaration_type2,
"isSynthetic": isSynthetic,
"kind": kind,
+ "variableDeclaration_declaration": variableDeclaration_declaration,
};
}
if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
@@ -16749,6 +17050,8 @@
"fieldFormalParameter_thisKeyword": fieldFormalParameter_thisKeyword,
"normalFormalParameter_covariantKeyword":
normalFormalParameter_covariantKeyword,
+ "fieldFormalParameter_type2": fieldFormalParameter_type2,
+ "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
"normalFormalParameter_identifier": normalFormalParameter_identifier,
"formalParameter_kind": formalParameter_kind,
"normalFormalParameter_comment": normalFormalParameter_comment,
@@ -16767,6 +17070,7 @@
functionTypedFormalParameter_typeParameters,
"normalFormalParameter_covariantKeyword":
normalFormalParameter_covariantKeyword,
+ "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
"normalFormalParameter_identifier": normalFormalParameter_identifier,
"formalParameter_kind": formalParameter_kind,
"normalFormalParameter_comment": normalFormalParameter_comment,
@@ -16781,6 +17085,8 @@
"simpleFormalParameter_keyword": simpleFormalParameter_keyword,
"normalFormalParameter_covariantKeyword":
normalFormalParameter_covariantKeyword,
+ "simpleFormalParameter_type2": simpleFormalParameter_type2,
+ "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
"normalFormalParameter_identifier": normalFormalParameter_identifier,
"formalParameter_kind": formalParameter_kind,
"normalFormalParameter_comment": normalFormalParameter_comment,
@@ -17143,6 +17449,7 @@
"genericFunctionType_formalParameters":
genericFunctionType_formalParameters,
"genericFunctionType_question": genericFunctionType_question,
+ "genericFunctionType_returnType2": genericFunctionType_returnType2,
"isSynthetic": isSynthetic,
"kind": kind,
};
@@ -17547,58 +17854,53 @@
class LinkedNodeBundleBuilder extends Object
with _LinkedNodeBundleMixin
implements idl.LinkedNodeBundle {
- LinkedNodeBuilder _node;
- LinkedNodeReferenceBuilder _references;
- UnlinkedTokensBuilder _tokens;
+ List<LinkedNodeLibraryBuilder> _libraries;
+ LinkedNodeReferencesBuilder _references;
@override
- LinkedNodeBuilder get node => _node;
+ List<LinkedNodeLibraryBuilder> get libraries =>
+ _libraries ??= <LinkedNodeLibraryBuilder>[];
- void set node(LinkedNodeBuilder value) {
- this._node = value;
+ void set libraries(List<LinkedNodeLibraryBuilder> value) {
+ this._libraries = value;
}
@override
- LinkedNodeReferenceBuilder get references => _references;
+ LinkedNodeReferencesBuilder get references => _references;
- void set references(LinkedNodeReferenceBuilder value) {
+ /// The shared list of references used in the [libraries].
+ void set references(LinkedNodeReferencesBuilder value) {
this._references = value;
}
- @override
- UnlinkedTokensBuilder get tokens => _tokens;
-
- void set tokens(UnlinkedTokensBuilder value) {
- this._tokens = value;
- }
-
LinkedNodeBundleBuilder(
- {LinkedNodeBuilder node,
- LinkedNodeReferenceBuilder references,
- UnlinkedTokensBuilder tokens})
- : _node = node,
- _references = references,
- _tokens = tokens;
+ {List<LinkedNodeLibraryBuilder> libraries,
+ LinkedNodeReferencesBuilder references})
+ : _libraries = libraries,
+ _references = references;
/**
* Flush [informative] data recursively.
*/
void flushInformative() {
- _node?.flushInformative();
+ _libraries?.forEach((b) => b.flushInformative());
_references?.flushInformative();
- _tokens?.flushInformative();
}
/**
* Accumulate non-[informative] data into [signature].
*/
void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addBool(this._tokens != null);
- this._tokens?.collectApiSignature(signature);
signature.addBool(this._references != null);
this._references?.collectApiSignature(signature);
- signature.addBool(this._node != null);
- this._node?.collectApiSignature(signature);
+ if (this._libraries == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._libraries.length);
+ for (var x in this._libraries) {
+ x?.collectApiSignature(signature);
+ }
+ }
}
List<int> toBuffer() {
@@ -17607,27 +17909,21 @@
}
fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_node;
+ fb.Offset offset_libraries;
fb.Offset offset_references;
- fb.Offset offset_tokens;
- if (_node != null) {
- offset_node = _node.finish(fbBuilder);
+ if (!(_libraries == null || _libraries.isEmpty)) {
+ offset_libraries = fbBuilder
+ .writeList(_libraries.map((b) => b.finish(fbBuilder)).toList());
}
if (_references != null) {
offset_references = _references.finish(fbBuilder);
}
- if (_tokens != null) {
- offset_tokens = _tokens.finish(fbBuilder);
- }
fbBuilder.startTable();
- if (offset_node != null) {
- fbBuilder.addOffset(2, offset_node);
+ if (offset_libraries != null) {
+ fbBuilder.addOffset(1, offset_libraries);
}
if (offset_references != null) {
- fbBuilder.addOffset(1, offset_references);
- }
- if (offset_tokens != null) {
- fbBuilder.addOffset(0, offset_tokens);
+ fbBuilder.addOffset(0, offset_references);
}
return fbBuilder.endTable();
}
@@ -17654,55 +17950,283 @@
_LinkedNodeBundleImpl(this._bc, this._bcOffset);
- idl.LinkedNode _node;
- idl.LinkedNodeReference _references;
- idl.UnlinkedTokens _tokens;
+ List<idl.LinkedNodeLibrary> _libraries;
+ idl.LinkedNodeReferences _references;
@override
- idl.LinkedNode get node {
- _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
- return _node;
+ List<idl.LinkedNodeLibrary> get libraries {
+ _libraries ??= const fb.ListReader<idl.LinkedNodeLibrary>(
+ const _LinkedNodeLibraryReader())
+ .vTableGet(_bc, _bcOffset, 1, const <idl.LinkedNodeLibrary>[]);
+ return _libraries;
}
@override
- idl.LinkedNodeReference get references {
+ idl.LinkedNodeReferences get references {
_references ??=
- const _LinkedNodeReferenceReader().vTableGet(_bc, _bcOffset, 1, null);
+ const _LinkedNodeReferencesReader().vTableGet(_bc, _bcOffset, 0, null);
return _references;
}
-
- @override
- idl.UnlinkedTokens get tokens {
- _tokens ??=
- const _UnlinkedTokensReader().vTableGet(_bc, _bcOffset, 0, null);
- return _tokens;
- }
}
abstract class _LinkedNodeBundleMixin implements idl.LinkedNodeBundle {
@override
Map<String, Object> toJson() {
Map<String, Object> _result = <String, Object>{};
- if (node != null) _result["node"] = node.toJson();
+ if (libraries.isNotEmpty)
+ _result["libraries"] =
+ libraries.map((_value) => _value.toJson()).toList();
if (references != null) _result["references"] = references.toJson();
- if (tokens != null) _result["tokens"] = tokens.toJson();
return _result;
}
@override
Map<String, Object> toMap() => {
- "node": node,
+ "libraries": libraries,
"references": references,
- "tokens": tokens,
};
@override
String toString() => convert.json.encode(toJson());
}
-class LinkedNodeReferenceBuilder extends Object
- with _LinkedNodeReferenceMixin
- implements idl.LinkedNodeReference {
+class LinkedNodeLibraryBuilder extends Object
+ with _LinkedNodeLibraryMixin
+ implements idl.LinkedNodeLibrary {
+ List<int> _exports;
+ String _name;
+ int _nameLength;
+ int _nameOffset;
+ List<LinkedNodeUnitBuilder> _units;
+ String _uriStr;
+
+ @override
+ List<int> get exports => _exports ??= <int>[];
+
+ void set exports(List<int> value) {
+ assert(value == null || value.every((e) => e >= 0));
+ this._exports = value;
+ }
+
+ @override
+ String get name => _name ??= '';
+
+ void set name(String value) {
+ this._name = value;
+ }
+
+ @override
+ int get nameLength => _nameLength ??= 0;
+
+ void set nameLength(int value) {
+ assert(value == null || value >= 0);
+ this._nameLength = value;
+ }
+
+ @override
+ int get nameOffset => _nameOffset ??= 0;
+
+ void set nameOffset(int value) {
+ assert(value == null || value >= 0);
+ this._nameOffset = value;
+ }
+
+ @override
+ List<LinkedNodeUnitBuilder> get units => _units ??= <LinkedNodeUnitBuilder>[];
+
+ void set units(List<LinkedNodeUnitBuilder> value) {
+ this._units = value;
+ }
+
+ @override
+ String get uriStr => _uriStr ??= '';
+
+ void set uriStr(String value) {
+ this._uriStr = value;
+ }
+
+ LinkedNodeLibraryBuilder(
+ {List<int> exports,
+ String name,
+ int nameLength,
+ int nameOffset,
+ List<LinkedNodeUnitBuilder> units,
+ String uriStr})
+ : _exports = exports,
+ _name = name,
+ _nameLength = nameLength,
+ _nameOffset = nameOffset,
+ _units = units,
+ _uriStr = uriStr;
+
+ /**
+ * Flush [informative] data recursively.
+ */
+ void flushInformative() {
+ _units?.forEach((b) => b.flushInformative());
+ }
+
+ /**
+ * Accumulate non-[informative] data into [signature].
+ */
+ void collectApiSignature(api_sig.ApiSignature signature) {
+ signature.addString(this._uriStr ?? '');
+ if (this._units == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._units.length);
+ for (var x in this._units) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this._exports == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._exports.length);
+ for (var x in this._exports) {
+ signature.addInt(x);
+ }
+ }
+ signature.addString(this._name ?? '');
+ signature.addInt(this._nameOffset ?? 0);
+ signature.addInt(this._nameLength ?? 0);
+ }
+
+ fb.Offset finish(fb.Builder fbBuilder) {
+ fb.Offset offset_exports;
+ fb.Offset offset_name;
+ fb.Offset offset_units;
+ fb.Offset offset_uriStr;
+ if (!(_exports == null || _exports.isEmpty)) {
+ offset_exports = fbBuilder.writeListUint32(_exports);
+ }
+ if (_name != null) {
+ offset_name = fbBuilder.writeString(_name);
+ }
+ if (!(_units == null || _units.isEmpty)) {
+ offset_units =
+ fbBuilder.writeList(_units.map((b) => b.finish(fbBuilder)).toList());
+ }
+ if (_uriStr != null) {
+ offset_uriStr = fbBuilder.writeString(_uriStr);
+ }
+ fbBuilder.startTable();
+ if (offset_exports != null) {
+ fbBuilder.addOffset(2, offset_exports);
+ }
+ if (offset_name != null) {
+ fbBuilder.addOffset(3, offset_name);
+ }
+ if (_nameLength != null && _nameLength != 0) {
+ fbBuilder.addUint32(5, _nameLength);
+ }
+ if (_nameOffset != null && _nameOffset != 0) {
+ fbBuilder.addUint32(4, _nameOffset);
+ }
+ if (offset_units != null) {
+ fbBuilder.addOffset(1, offset_units);
+ }
+ if (offset_uriStr != null) {
+ fbBuilder.addOffset(0, offset_uriStr);
+ }
+ return fbBuilder.endTable();
+ }
+}
+
+class _LinkedNodeLibraryReader extends fb.TableReader<_LinkedNodeLibraryImpl> {
+ const _LinkedNodeLibraryReader();
+
+ @override
+ _LinkedNodeLibraryImpl createObject(fb.BufferContext bc, int offset) =>
+ new _LinkedNodeLibraryImpl(bc, offset);
+}
+
+class _LinkedNodeLibraryImpl extends Object
+ with _LinkedNodeLibraryMixin
+ implements idl.LinkedNodeLibrary {
+ final fb.BufferContext _bc;
+ final int _bcOffset;
+
+ _LinkedNodeLibraryImpl(this._bc, this._bcOffset);
+
+ List<int> _exports;
+ String _name;
+ int _nameLength;
+ int _nameOffset;
+ List<idl.LinkedNodeUnit> _units;
+ String _uriStr;
+
+ @override
+ List<int> get exports {
+ _exports ??=
+ const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 2, const <int>[]);
+ return _exports;
+ }
+
+ @override
+ String get name {
+ _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 3, '');
+ return _name;
+ }
+
+ @override
+ int get nameLength {
+ _nameLength ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 5, 0);
+ return _nameLength;
+ }
+
+ @override
+ int get nameOffset {
+ _nameOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 4, 0);
+ return _nameOffset;
+ }
+
+ @override
+ List<idl.LinkedNodeUnit> get units {
+ _units ??=
+ const fb.ListReader<idl.LinkedNodeUnit>(const _LinkedNodeUnitReader())
+ .vTableGet(_bc, _bcOffset, 1, const <idl.LinkedNodeUnit>[]);
+ return _units;
+ }
+
+ @override
+ String get uriStr {
+ _uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+ return _uriStr;
+ }
+}
+
+abstract class _LinkedNodeLibraryMixin implements idl.LinkedNodeLibrary {
+ @override
+ Map<String, Object> toJson() {
+ Map<String, Object> _result = <String, Object>{};
+ if (exports.isNotEmpty) _result["exports"] = exports;
+ if (name != '') _result["name"] = name;
+ if (nameLength != 0) _result["nameLength"] = nameLength;
+ if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+ if (units.isNotEmpty)
+ _result["units"] = units.map((_value) => _value.toJson()).toList();
+ if (uriStr != '') _result["uriStr"] = uriStr;
+ return _result;
+ }
+
+ @override
+ Map<String, Object> toMap() => {
+ "exports": exports,
+ "name": name,
+ "nameLength": nameLength,
+ "nameOffset": nameOffset,
+ "units": units,
+ "uriStr": uriStr,
+ };
+
+ @override
+ String toString() => convert.json.encode(toJson());
+}
+
+class LinkedNodeReferencesBuilder extends Object
+ with _LinkedNodeReferencesMixin
+ implements idl.LinkedNodeReferences {
List<String> _name;
List<int> _parent;
@@ -17721,7 +18245,7 @@
this._parent = value;
}
- LinkedNodeReferenceBuilder({List<String> name, List<int> parent})
+ LinkedNodeReferencesBuilder({List<String> name, List<int> parent})
: _name = name,
_parent = parent;
@@ -17773,22 +18297,22 @@
}
}
-class _LinkedNodeReferenceReader
- extends fb.TableReader<_LinkedNodeReferenceImpl> {
- const _LinkedNodeReferenceReader();
+class _LinkedNodeReferencesReader
+ extends fb.TableReader<_LinkedNodeReferencesImpl> {
+ const _LinkedNodeReferencesReader();
@override
- _LinkedNodeReferenceImpl createObject(fb.BufferContext bc, int offset) =>
- new _LinkedNodeReferenceImpl(bc, offset);
+ _LinkedNodeReferencesImpl createObject(fb.BufferContext bc, int offset) =>
+ new _LinkedNodeReferencesImpl(bc, offset);
}
-class _LinkedNodeReferenceImpl extends Object
- with _LinkedNodeReferenceMixin
- implements idl.LinkedNodeReference {
+class _LinkedNodeReferencesImpl extends Object
+ with _LinkedNodeReferencesMixin
+ implements idl.LinkedNodeReferences {
final fb.BufferContext _bc;
final int _bcOffset;
- _LinkedNodeReferenceImpl(this._bc, this._bcOffset);
+ _LinkedNodeReferencesImpl(this._bc, this._bcOffset);
List<String> _name;
List<int> _parent;
@@ -17808,7 +18332,7 @@
}
}
-abstract class _LinkedNodeReferenceMixin implements idl.LinkedNodeReference {
+abstract class _LinkedNodeReferencesMixin implements idl.LinkedNodeReferences {
@override
Map<String, Object> toJson() {
Map<String, Object> _result = <String, Object>{};
@@ -17842,7 +18366,7 @@
List<int> get functionFormalParameters =>
_functionFormalParameters ??= <int>[];
- /// References to [LinkedNodeReference].
+ /// References to [LinkedNodeReferences].
void set functionFormalParameters(List<int> value) {
assert(value == null || value.every((e) => e >= 0));
this._functionFormalParameters = value;
@@ -17858,7 +18382,7 @@
@override
List<int> get functionTypeParameters => _functionTypeParameters ??= <int>[];
- /// References to [LinkedNodeReference].
+ /// References to [LinkedNodeReferences].
void set functionTypeParameters(List<int> value) {
assert(value == null || value.every((e) => e >= 0));
this._functionTypeParameters = value;
@@ -17867,7 +18391,7 @@
@override
int get interfaceClass => _interfaceClass ??= 0;
- /// Reference to a [LinkedNodeReference].
+ /// Reference to a [LinkedNodeReferences].
void set interfaceClass(int value) {
assert(value == null || value >= 0);
this._interfaceClass = value;
@@ -17891,7 +18415,7 @@
@override
int get typeParameterParameter => _typeParameterParameter ??= 0;
- /// Reference to a [LinkedNodeReference].
+ /// Reference to a [LinkedNodeReferences].
void set typeParameterParameter(int value) {
assert(value == null || value >= 0);
this._typeParameterParameter = value;
@@ -18113,6 +18637,302 @@
String toString() => convert.json.encode(toJson());
}
+class LinkedNodeUnitBuilder extends Object
+ with _LinkedNodeUnitMixin
+ implements idl.LinkedNodeUnit {
+ LinkedNodeBuilder _node;
+ UnlinkedTokensBuilder _tokens;
+ String _uriStr;
+
+ @override
+ LinkedNodeBuilder get node => _node;
+
+ void set node(LinkedNodeBuilder value) {
+ this._node = value;
+ }
+
+ @override
+ UnlinkedTokensBuilder get tokens => _tokens;
+
+ void set tokens(UnlinkedTokensBuilder value) {
+ this._tokens = value;
+ }
+
+ @override
+ String get uriStr => _uriStr ??= '';
+
+ void set uriStr(String value) {
+ this._uriStr = value;
+ }
+
+ LinkedNodeUnitBuilder(
+ {LinkedNodeBuilder node, UnlinkedTokensBuilder tokens, String uriStr})
+ : _node = node,
+ _tokens = tokens,
+ _uriStr = uriStr;
+
+ /**
+ * Flush [informative] data recursively.
+ */
+ void flushInformative() {
+ _node?.flushInformative();
+ _tokens?.flushInformative();
+ }
+
+ /**
+ * Accumulate non-[informative] data into [signature].
+ */
+ void collectApiSignature(api_sig.ApiSignature signature) {
+ signature.addString(this._uriStr ?? '');
+ signature.addBool(this._tokens != null);
+ this._tokens?.collectApiSignature(signature);
+ signature.addBool(this._node != null);
+ this._node?.collectApiSignature(signature);
+ }
+
+ fb.Offset finish(fb.Builder fbBuilder) {
+ fb.Offset offset_node;
+ fb.Offset offset_tokens;
+ fb.Offset offset_uriStr;
+ if (_node != null) {
+ offset_node = _node.finish(fbBuilder);
+ }
+ if (_tokens != null) {
+ offset_tokens = _tokens.finish(fbBuilder);
+ }
+ if (_uriStr != null) {
+ offset_uriStr = fbBuilder.writeString(_uriStr);
+ }
+ fbBuilder.startTable();
+ if (offset_node != null) {
+ fbBuilder.addOffset(2, offset_node);
+ }
+ if (offset_tokens != null) {
+ fbBuilder.addOffset(1, offset_tokens);
+ }
+ if (offset_uriStr != null) {
+ fbBuilder.addOffset(0, offset_uriStr);
+ }
+ return fbBuilder.endTable();
+ }
+}
+
+class _LinkedNodeUnitReader extends fb.TableReader<_LinkedNodeUnitImpl> {
+ const _LinkedNodeUnitReader();
+
+ @override
+ _LinkedNodeUnitImpl createObject(fb.BufferContext bc, int offset) =>
+ new _LinkedNodeUnitImpl(bc, offset);
+}
+
+class _LinkedNodeUnitImpl extends Object
+ with _LinkedNodeUnitMixin
+ implements idl.LinkedNodeUnit {
+ final fb.BufferContext _bc;
+ final int _bcOffset;
+
+ _LinkedNodeUnitImpl(this._bc, this._bcOffset);
+
+ idl.LinkedNode _node;
+ idl.UnlinkedTokens _tokens;
+ String _uriStr;
+
+ @override
+ idl.LinkedNode get node {
+ _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
+ return _node;
+ }
+
+ @override
+ idl.UnlinkedTokens get tokens {
+ _tokens ??=
+ const _UnlinkedTokensReader().vTableGet(_bc, _bcOffset, 1, null);
+ return _tokens;
+ }
+
+ @override
+ String get uriStr {
+ _uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+ return _uriStr;
+ }
+}
+
+abstract class _LinkedNodeUnitMixin implements idl.LinkedNodeUnit {
+ @override
+ Map<String, Object> toJson() {
+ Map<String, Object> _result = <String, Object>{};
+ if (node != null) _result["node"] = node.toJson();
+ if (tokens != null) _result["tokens"] = tokens.toJson();
+ if (uriStr != '') _result["uriStr"] = uriStr;
+ return _result;
+ }
+
+ @override
+ Map<String, Object> toMap() => {
+ "node": node,
+ "tokens": tokens,
+ "uriStr": uriStr,
+ };
+
+ @override
+ String toString() => convert.json.encode(toJson());
+}
+
+class LinkedNodeVariablesDeclarationBuilder extends Object
+ with _LinkedNodeVariablesDeclarationMixin
+ implements idl.LinkedNodeVariablesDeclaration {
+ LinkedNodeBuilder _comment;
+ bool _isConst;
+ bool _isFinal;
+ bool _isStatic;
+
+ @override
+ LinkedNodeBuilder get comment => _comment;
+
+ void set comment(LinkedNodeBuilder value) {
+ this._comment = value;
+ }
+
+ @override
+ bool get isConst => _isConst ??= false;
+
+ void set isConst(bool value) {
+ this._isConst = value;
+ }
+
+ @override
+ bool get isFinal => _isFinal ??= false;
+
+ void set isFinal(bool value) {
+ this._isFinal = value;
+ }
+
+ @override
+ bool get isStatic => _isStatic ??= false;
+
+ void set isStatic(bool value) {
+ this._isStatic = value;
+ }
+
+ LinkedNodeVariablesDeclarationBuilder(
+ {LinkedNodeBuilder comment, bool isConst, bool isFinal, bool isStatic})
+ : _comment = comment,
+ _isConst = isConst,
+ _isFinal = isFinal,
+ _isStatic = isStatic;
+
+ /**
+ * Flush [informative] data recursively.
+ */
+ void flushInformative() {
+ _comment?.flushInformative();
+ }
+
+ /**
+ * Accumulate non-[informative] data into [signature].
+ */
+ void collectApiSignature(api_sig.ApiSignature signature) {
+ signature.addBool(this._isConst == true);
+ signature.addBool(this._isFinal == true);
+ signature.addBool(this._isStatic == true);
+ signature.addBool(this._comment != null);
+ this._comment?.collectApiSignature(signature);
+ }
+
+ fb.Offset finish(fb.Builder fbBuilder) {
+ fb.Offset offset_comment;
+ if (_comment != null) {
+ offset_comment = _comment.finish(fbBuilder);
+ }
+ fbBuilder.startTable();
+ if (offset_comment != null) {
+ fbBuilder.addOffset(3, offset_comment);
+ }
+ if (_isConst == true) {
+ fbBuilder.addBool(0, true);
+ }
+ if (_isFinal == true) {
+ fbBuilder.addBool(1, true);
+ }
+ if (_isStatic == true) {
+ fbBuilder.addBool(2, true);
+ }
+ return fbBuilder.endTable();
+ }
+}
+
+class _LinkedNodeVariablesDeclarationReader
+ extends fb.TableReader<_LinkedNodeVariablesDeclarationImpl> {
+ const _LinkedNodeVariablesDeclarationReader();
+
+ @override
+ _LinkedNodeVariablesDeclarationImpl createObject(
+ fb.BufferContext bc, int offset) =>
+ new _LinkedNodeVariablesDeclarationImpl(bc, offset);
+}
+
+class _LinkedNodeVariablesDeclarationImpl extends Object
+ with _LinkedNodeVariablesDeclarationMixin
+ implements idl.LinkedNodeVariablesDeclaration {
+ final fb.BufferContext _bc;
+ final int _bcOffset;
+
+ _LinkedNodeVariablesDeclarationImpl(this._bc, this._bcOffset);
+
+ idl.LinkedNode _comment;
+ bool _isConst;
+ bool _isFinal;
+ bool _isStatic;
+
+ @override
+ idl.LinkedNode get comment {
+ _comment ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 3, null);
+ return _comment;
+ }
+
+ @override
+ bool get isConst {
+ _isConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 0, false);
+ return _isConst;
+ }
+
+ @override
+ bool get isFinal {
+ _isFinal ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 1, false);
+ return _isFinal;
+ }
+
+ @override
+ bool get isStatic {
+ _isStatic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
+ return _isStatic;
+ }
+}
+
+abstract class _LinkedNodeVariablesDeclarationMixin
+ implements idl.LinkedNodeVariablesDeclaration {
+ @override
+ Map<String, Object> toJson() {
+ Map<String, Object> _result = <String, Object>{};
+ if (comment != null) _result["comment"] = comment.toJson();
+ if (isConst != false) _result["isConst"] = isConst;
+ if (isFinal != false) _result["isFinal"] = isFinal;
+ if (isStatic != false) _result["isStatic"] = isStatic;
+ return _result;
+ }
+
+ @override
+ Map<String, Object> toMap() => {
+ "comment": comment,
+ "isConst": isConst,
+ "isFinal": isFinal,
+ "isStatic": isStatic,
+ };
+
+ @override
+ String toString() => convert.json.encode(toJson());
+}
+
class LinkedReferenceBuilder extends Object
with _LinkedReferenceMixin
implements idl.LinkedReference {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index bb8bc6b..6cd172f 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -398,6 +398,8 @@
function,
+ genericTypeAlias,
+
interface,
typeParameter,
@@ -970,7 +972,26 @@
/// Pop the top 2 values from the stack, place them in a [MapLiteralEntry],
/// and push the result back onto the stack.
- makeMapLiteralEntry
+ makeMapLiteralEntry,
+
+ /// Pop the top value from the stack, convert it to a spread element of type
+ /// `...`, and push the result back onto the stack.
+ spreadElement,
+
+ /// Pop the top value from the stack, convert it to a spread element of type
+ /// `...?`, and push the result back onto the stack.
+ nullAwareSpreadElement,
+
+ /// Pop the top two values from the stack. The first is a condition
+ /// and the second is a collection element. Push an "if" element having the
+ /// given condition, with the collection element as its "then" clause.
+ ifElement,
+
+ /// Pop the top three values from the stack. The first is a condition and the
+ /// other two are collection elements. Push an "if" element having the given
+ /// condition, with the two collection elements as its "then" and "else"
+ /// clauses, respectively.
+ ifElseElement
}
/// Enum used to indicate the kind of a parameter.
@@ -1791,19 +1812,36 @@
variantField_20:string (id: 20);
variantField_22:string (id: 22);
+
+ variantField_32:LinkedNodeVariablesDeclaration (id: 32);
}
-/// TODO(scheglov) extend to support multiple libraries or remove
+/// Information about a group of libraries linked together, for example because
+/// they form a single cycle, or because they represent a single build artifact.
table LinkedNodeBundle {
- node:LinkedNode (id: 2);
+ libraries:[LinkedNodeLibrary] (id: 1);
- references:LinkedNodeReference (id: 1);
+ /// The shared list of references used in the [libraries].
+ references:LinkedNodeReferences (id: 0);
+}
- tokens:UnlinkedTokens (id: 0);
+/// Information about a single library in a [LinkedNodeBundle].
+table LinkedNodeLibrary {
+ exports:[uint] (id: 2);
+
+ name:string (id: 3);
+
+ nameLength:uint (id: 5);
+
+ nameOffset:uint (id: 4);
+
+ units:[LinkedNodeUnit] (id: 1);
+
+ uriStr:string (id: 0);
}
/// Flattened tree of declarations referenced from [LinkedNode]s.
-table LinkedNodeReference {
+table LinkedNodeReferences {
name:[string] (id: 1);
parent:[uint] (id: 0);
@@ -1811,25 +1849,46 @@
/// Information about a Dart type.
table LinkedNodeType {
- /// References to [LinkedNodeReference].
+ /// References to [LinkedNodeReferences].
functionFormalParameters:[uint] (id: 0);
functionReturnType:LinkedNodeType (id: 1);
- /// References to [LinkedNodeReference].
+ /// References to [LinkedNodeReferences].
functionTypeParameters:[uint] (id: 2);
- /// Reference to a [LinkedNodeReference].
+ /// Reference to a [LinkedNodeReferences].
interfaceClass:uint (id: 3);
interfaceTypeArguments:[LinkedNodeType] (id: 4);
kind:LinkedNodeTypeKind (id: 5);
- /// Reference to a [LinkedNodeReference].
+ /// Reference to a [LinkedNodeReferences].
typeParameterParameter:uint (id: 6);
}
+/// Information about a single library in a [LinkedNodeLibrary].
+table LinkedNodeUnit {
+ node:LinkedNode (id: 2);
+
+ tokens:UnlinkedTokens (id: 1);
+
+ uriStr:string (id: 0);
+}
+
+/// Information about a top-level declaration, or a field declaration that
+/// contributes information to [LinkedNodeKind.variableDeclaration].
+table LinkedNodeVariablesDeclaration {
+ comment:LinkedNode (id: 3);
+
+ isConst:bool (id: 0);
+
+ isFinal:bool (id: 1);
+
+ isStatic:bool (id: 2);
+}
+
/// Information about the resolution of an [UnlinkedReference].
table LinkedReference {
/// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index b25b830..c9e84f8 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -987,6 +987,9 @@
@VariantId(6, variant: LinkedNodeKind.classDeclaration)
LinkedNode get classDeclaration_extendsClause;
+ @VariantId(27, variant: LinkedNodeKind.classDeclaration)
+ bool get classDeclaration_isDartObject;
+
@VariantId(7, variant: LinkedNodeKind.classDeclaration)
LinkedNode get classDeclaration_withClause;
@@ -1338,6 +1341,9 @@
@VariantId(6, variant: LinkedNodeKind.fieldFormalParameter)
LinkedNode get fieldFormalParameter_type;
+ @VariantId(24, variant: LinkedNodeKind.fieldFormalParameter)
+ LinkedNodeType get fieldFormalParameter_type2;
+
@VariantId(7, variant: LinkedNodeKind.fieldFormalParameter)
LinkedNode get fieldFormalParameter_typeParameters;
@@ -1459,6 +1465,9 @@
@VariantId(7, variant: LinkedNodeKind.functionDeclaration)
LinkedNode get functionDeclaration_returnType;
+ @VariantId(24, variant: LinkedNodeKind.functionDeclaration)
+ LinkedNodeType get functionDeclaration_returnType2;
+
@VariantId(6, variant: LinkedNodeKind.functionDeclarationStatement)
LinkedNode get functionDeclarationStatement_functionDeclaration;
@@ -1480,6 +1489,9 @@
@VariantId(7, variant: LinkedNodeKind.functionTypeAlias)
LinkedNode get functionTypeAlias_returnType;
+ @VariantId(24, variant: LinkedNodeKind.functionTypeAlias)
+ LinkedNodeType get functionTypeAlias_returnType2;
+
@VariantId(8, variant: LinkedNodeKind.functionTypeAlias)
LinkedNode get functionTypeAlias_typeParameters;
@@ -1504,6 +1516,9 @@
@VariantId(7, variant: LinkedNodeKind.genericFunctionType)
LinkedNode get genericFunctionType_returnType;
+ @VariantId(24, variant: LinkedNodeKind.genericFunctionType)
+ LinkedNodeType get genericFunctionType_returnType2;
+
@VariantId(6, variant: LinkedNodeKind.genericFunctionType)
LinkedNode get genericFunctionType_typeParameters;
@@ -1696,6 +1711,9 @@
@VariantId(7, variant: LinkedNodeKind.mapLiteralEntry)
LinkedNode get mapLiteralEntry_value;
+ @VariantId(19, variant: LinkedNodeKind.methodDeclaration)
+ int get methodDeclaration_actualProperty;
+
@VariantId(6, variant: LinkedNodeKind.methodDeclaration)
LinkedNode get methodDeclaration_body;
@@ -1720,6 +1738,9 @@
@VariantId(8, variant: LinkedNodeKind.methodDeclaration)
LinkedNode get methodDeclaration_returnType;
+ @VariantId(24, variant: LinkedNodeKind.methodDeclaration)
+ LinkedNodeType get methodDeclaration_returnType2;
+
@VariantId(9, variant: LinkedNodeKind.methodDeclaration)
LinkedNode get methodDeclaration_typeParameters;
@@ -1804,6 +1825,13 @@
])
LinkedNode get normalFormalParameter_identifier;
+ @VariantId(27, variantList: [
+ LinkedNodeKind.fieldFormalParameter,
+ LinkedNodeKind.functionTypedFormalParameter,
+ LinkedNodeKind.simpleFormalParameter,
+ ])
+ bool get normalFormalParameter_isCovariant;
+
@VariantId(4, variantList: [
LinkedNodeKind.fieldFormalParameter,
LinkedNodeKind.functionTypedFormalParameter,
@@ -1931,6 +1959,9 @@
@VariantId(6, variant: LinkedNodeKind.simpleFormalParameter)
LinkedNode get simpleFormalParameter_type;
+ @VariantId(24, variant: LinkedNodeKind.simpleFormalParameter)
+ LinkedNodeType get simpleFormalParameter_type2;
+
@VariantId(15, variant: LinkedNodeKind.simpleIdentifier)
int get simpleIdentifier_element;
@@ -2140,6 +2171,9 @@
])
int get uriBasedDirective_uriElement;
+ @VariantId(32, variant: LinkedNodeKind.variableDeclaration)
+ LinkedNodeVariablesDeclaration get variableDeclaration_declaration;
+
@VariantId(15, variant: LinkedNodeKind.variableDeclaration)
int get variableDeclaration_equals;
@@ -2149,6 +2183,9 @@
@VariantId(7, variant: LinkedNodeKind.variableDeclaration)
LinkedNode get variableDeclaration_name;
+ @VariantId(24, variant: LinkedNodeKind.variableDeclaration)
+ LinkedNodeType get variableDeclaration_type2;
+
@VariantId(15, variant: LinkedNodeKind.variableDeclarationList)
int get variableDeclarationList_keyword;
@@ -2198,20 +2235,19 @@
int get yieldStatement_yieldKeyword;
}
-/// TODO(scheglov) extend to support multiple libraries or remove
+/// Information about a group of libraries linked together, for example because
+/// they form a single cycle, or because they represent a single build artifact.
@TopLevel('LNBn')
abstract class LinkedNodeBundle extends base.SummaryClass {
factory LinkedNodeBundle.fromBuffer(List<int> buffer) =>
generated.readLinkedNodeBundle(buffer);
- @Id(2)
- LinkedNode get node;
-
@Id(1)
- LinkedNodeReference get references;
+ List<LinkedNodeLibrary> get libraries;
+ /// The shared list of references used in the [libraries].
@Id(0)
- UnlinkedTokens get tokens;
+ LinkedNodeReferences get references;
}
/// Types of comments.
@@ -2344,8 +2380,29 @@
yieldStatement,
}
+/// Information about a single library in a [LinkedNodeBundle].
+abstract class LinkedNodeLibrary extends base.SummaryClass {
+ @Id(2)
+ List<int> get exports;
+
+ @Id(3)
+ String get name;
+
+ @Id(5)
+ int get nameLength;
+
+ @Id(4)
+ int get nameOffset;
+
+ @Id(1)
+ List<LinkedNodeUnit> get units;
+
+ @Id(0)
+ String get uriStr;
+}
+
/// Flattened tree of declarations referenced from [LinkedNode]s.
-abstract class LinkedNodeReference extends base.SummaryClass {
+abstract class LinkedNodeReferences extends base.SummaryClass {
@Id(1)
List<String> get name;
@@ -2355,18 +2412,18 @@
/// Information about a Dart type.
abstract class LinkedNodeType extends base.SummaryClass {
- /// References to [LinkedNodeReference].
+ /// References to [LinkedNodeReferences].
@Id(0)
List<int> get functionFormalParameters;
@Id(1)
LinkedNodeType get functionReturnType;
- /// References to [LinkedNodeReference].
+ /// References to [LinkedNodeReferences].
@Id(2)
List<int> get functionTypeParameters;
- /// Reference to a [LinkedNodeReference].
+ /// Reference to a [LinkedNodeReferences].
@Id(3)
int get interfaceClass;
@@ -2376,7 +2433,7 @@
@Id(5)
LinkedNodeTypeKind get kind;
- /// Reference to a [LinkedNodeReference].
+ /// Reference to a [LinkedNodeReferences].
@Id(6)
int get typeParameterParameter;
}
@@ -2386,11 +2443,40 @@
bottom,
dynamic_,
function,
+ genericTypeAlias,
interface,
typeParameter,
void_
}
+/// Information about a single library in a [LinkedNodeLibrary].
+abstract class LinkedNodeUnit extends base.SummaryClass {
+ @Id(2)
+ LinkedNode get node;
+
+ @Id(1)
+ UnlinkedTokens get tokens;
+
+ @Id(0)
+ String get uriStr;
+}
+
+/// Information about a top-level declaration, or a field declaration that
+/// contributes information to [LinkedNodeKind.variableDeclaration].
+abstract class LinkedNodeVariablesDeclaration extends base.SummaryClass {
+ @Id(3)
+ LinkedNode get comment;
+
+ @Id(0)
+ bool get isConst;
+
+ @Id(1)
+ bool get isFinal;
+
+ @Id(2)
+ bool get isStatic;
+}
+
/// Information about the resolution of an [UnlinkedReference].
abstract class LinkedReference extends base.SummaryClass {
/// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
@@ -3782,6 +3868,25 @@
/// Pop the top 2 values from the stack, place them in a [MapLiteralEntry],
/// and push the result back onto the stack.
makeMapLiteralEntry,
+
+ /// Pop the top value from the stack, convert it to a spread element of type
+ /// `...`, and push the result back onto the stack.
+ spreadElement,
+
+ /// Pop the top value from the stack, convert it to a spread element of type
+ /// `...?`, and push the result back onto the stack.
+ nullAwareSpreadElement,
+
+ /// Pop the top two values from the stack. The first is a condition
+ /// and the second is a collection element. Push an "if" element having the
+ /// given condition, with the collection element as its "then" clause.
+ ifElement,
+
+ /// Pop the top three values from the stack. The first is a condition and the
+ /// other two are collection elements. Push an "if" element having the given
+ /// condition, with the two collection elements as its "then" and "else"
+ /// clauses, respectively.
+ ifElseElement,
}
/// Unlinked summary information about an import declaration.
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 541cfe7..d38b602 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -2,8 +2,6 @@
// 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/dart/analysis/session.dart';
-
/// This library is capable of producing linked summaries from unlinked
/// ones (or prelinked ones). It functions by building a miniature
/// element model to represent the contents of the summaries, and then
@@ -57,12 +55,13 @@
///
/// - Where possible, we favor method dispatch instead of "is" and "as"
/// checks. E.g. see [ReferenceableElementForLink.asConstructor].
+import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/builder.dart';
@@ -116,11 +115,12 @@
Set<String> libraryUris,
GetDependencyCallback getDependency,
GetUnitCallback getUnit,
- GetDeclaredVariable getDeclaredVariable,
+ DeclaredVariables declaredVariables,
+ AnalysisOptions analysisOptions,
[GetAstCallback getAst]) {
Map<String, LinkedLibraryBuilder> linkedLibraries =
- setupForLink(libraryUris, getUnit, getDeclaredVariable);
- _relink(linkedLibraries, getDependency, getUnit, getAst);
+ setupForLink(libraryUris, getUnit, declaredVariables);
+ _relink(linkedLibraries, getDependency, getUnit, getAst, analysisOptions);
return linkedLibraries;
}
@@ -132,7 +132,7 @@
/// of the libraries in this build unit, and whose values are the corresponding
/// [LinkedLibraryBuilder]s.
Map<String, LinkedLibraryBuilder> setupForLink(Set<String> libraryUris,
- GetUnitCallback getUnit, GetDeclaredVariable getDeclaredVariable) {
+ GetUnitCallback getUnit, DeclaredVariables declaredVariables) {
Map<String, LinkedLibraryBuilder> linkedLibraries =
<String, LinkedLibraryBuilder>{};
for (String absoluteUri in libraryUris) {
@@ -141,7 +141,7 @@
getUnit(absoluteUri),
getUnit,
(String absoluteUri) => getUnit(absoluteUri)?.publicNamespace,
- getDeclaredVariable);
+ declaredVariables);
}
return linkedLibraries;
}
@@ -301,8 +301,9 @@
Map<String, LinkedLibraryBuilder> libraries,
GetDependencyCallback getDependency,
GetUnitCallback getUnit,
- GetAstCallback getAst) {
- new Linker(libraries, getDependency, getUnit, getAst).link();
+ GetAstCallback getAst,
+ AnalysisOptions analysisOptions) {
+ new Linker(libraries, getDependency, getUnit, getAst, analysisOptions).link();
}
/// Create an [UnlinkedParam] representing the given [parameter], which should
@@ -412,37 +413,7 @@
/// [UnlinkedUnit] objects.
typedef UnlinkedUnit GetUnitCallback(String absoluteUri);
-/// Stub implementation of [AnalysisOptions] used during linking.
-class AnalysisOptionsForLink implements AnalysisOptionsImpl {
- final Linker _linker;
-
- AnalysisOptionsForLink(this._linker);
-
- @override
- bool get hint => false;
-
- @override
- bool get implicitCasts => true;
-
- @override
- bool get strictInference => false;
-
- @override
- bool get strictRawTypes => false;
-
- @deprecated
- @override
- bool get previewDart2 => true;
-
- @override
- bool get strongMode => true;
-
- @override
- bool get strongModeHints => false;
-
- @override
- ExperimentStatus get experimentStatus => new ExperimentStatus();
-
+class AnalysisSessionForLink implements AnalysisSession {
@override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
@@ -498,6 +469,9 @@
Source get librarySource => library.source;
@override
+ get linkedNode => null;
+
+ @override
List<MethodElementForLink> get methods;
@override
@@ -1931,6 +1905,7 @@
case UnlinkedExprOperation.makeUntypedList:
case UnlinkedExprOperation.makeUntypedMap:
case UnlinkedExprOperation.makeUntypedSet:
+ case UnlinkedExprOperation.makeUntypedSetOrMap:
intPtr++;
break;
case UnlinkedExprOperation.assignToRef:
@@ -1958,6 +1933,7 @@
intPtr++;
break;
case UnlinkedExprOperation.makeTypedMap:
+ case UnlinkedExprOperation.makeTypedMap2:
refPtr += 2;
intPtr++;
break;
@@ -2105,7 +2081,7 @@
ContextForLink(this._linker);
@override
- AnalysisOptionsForLink get analysisOptions => _linker.analysisOptions;
+ AnalysisOptions get analysisOptions => _linker.analysisOptions;
@override
TypeProvider get typeProvider => _linker.typeProvider;
@@ -2344,6 +2320,9 @@
LibraryElement get library => enclosingElement.library;
@override
+ get linkedNode => null;
+
+ @override
String get name {
if (_name == null) {
_name = serializedExecutable.name;
@@ -2512,7 +2491,9 @@
List<UnlinkedExecutable> localFunctions)
: _builder = new ExprBuilder(
unitResynthesizer, _functionElement, unlinkedConst,
- requireValidConst: false, localFunctions: localFunctions);
+ requireValidConst: false,
+ localFunctions: localFunctions,
+ becomeSetOrMap: false);
TopLevelInferenceErrorKind get errorKind {
// TODO(paulberry): should we return TopLevelInferenceErrorKind.assignment
@@ -2854,6 +2835,9 @@
bool get isAsynchronous => serializedExecutable.isAsynchronous;
@override
+ get linkedNode => null;
+
+ @override
DartType get returnType {
// If this is a variable whose type needs inferring, infer it.
if (_variable.hasImplicitType) {
@@ -3169,6 +3153,9 @@
LibraryElementForLink get library => enclosingElement.library;
@override
+ get linkedNode => null;
+
+ @override
String get name => _unlinkedTypedef.name;
@override
@@ -3287,6 +3274,9 @@
LibraryElementForLink get library => enclosingElement.library;
@override
+ get linkedNode => null;
+
+ @override
String get name => '-';
@override
@@ -3370,6 +3360,9 @@
LibraryElementForLink get library => enclosingElement.library;
@override
+ get linkedNode => null;
+
+ @override
String get name => _unlinkedTypedef.name;
@override
@@ -3651,6 +3644,9 @@
LibraryResynthesizerContext get resynthesizerContext => this;
@override
+ AnalysisSession get session => _linker.session;
+
+ @override
Source get source => definingCompilationUnit.source;
@override
@@ -3948,10 +3944,13 @@
SpecialTypeElementForLink _bottomElement;
InheritanceManager2 _inheritanceManager;
ContextForLink _context;
- AnalysisOptionsForLink _analysisOptions;
+ AnalysisSessionForLink _session;
+
+ /// Gets an instance of [AnalysisOptions] for use during linking.
+ final AnalysisOptions analysisOptions;
Linker(Map<String, LinkedLibraryBuilder> linkedLibraries, this.getDependency,
- this.getUnit, this.getAst) {
+ this.getUnit, this.getAst, this.analysisOptions) {
// Create elements for the libraries to be linked. The rest of
// the element model will be created on demand.
linkedLibraries
@@ -3962,10 +3961,6 @@
});
}
- /// Get an instance of [AnalysisOptions] for use during linking.
- AnalysisOptionsForLink get analysisOptions =>
- _analysisOptions ??= new AnalysisOptionsForLink(this);
-
/// Get the library element for `dart:async`.
LibraryElementForLink get asyncLibrary =>
_asyncLibrary ??= getLibrary(Uri.parse('dart:async'));
@@ -3990,6 +3985,10 @@
InheritanceManager2 get inheritanceManager =>
_inheritanceManager ??= new InheritanceManager2(typeSystem);
+ /// Get a stub implementation of [AnalysisContext] which can be used during
+ /// linking.
+ get session => _session ??= new AnalysisSessionForLink();
+
/// Indicates whether type inference should use strong mode rules.
@deprecated
bool get strongMode => true;
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index dc9e818..91a51d2 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -1,23 +1,21 @@
+// 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:io' as io;
import 'dart:math' show min;
import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.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/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/resynthesize.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
/**
* A [ConflictingSummaryException] indicates that two different summaries
@@ -187,130 +185,7 @@
@override
bool compute(CacheEntry entry, ResultDescriptor result) {
- AnalysisTarget target = entry.target;
-
- if (result == TYPE_PROVIDER) {
- entry.setValue(result as ResultDescriptor<TypeProvider>,
- _resynthesizer.typeProvider, const <TargetedResult>[]);
- return true;
- }
-
- // LINE_INFO can be provided using just the UnlinkedUnit.
- if (target is Source && result == LINE_INFO) {
- String uriString = target.uri.toString();
- UnlinkedUnit unlinkedUnit = _dataStore.unlinkedMap[uriString];
- if (unlinkedUnit != null) {
- List<int> lineStarts = unlinkedUnit.lineStarts;
- if (lineStarts.isNotEmpty) {
- LineInfo lineInfo = new LineInfo(lineStarts);
- entry.setValue(result as ResultDescriptor<LineInfo>, lineInfo,
- const <TargetedResult>[]);
- return true;
- }
- }
- return false;
- }
-
- // Check whether there are results for the source.
- if (!hasResultsForSource(target.librarySource ?? target.source)) {
- return false;
- }
- // Constant expressions are always resolved in summaries.
- if (result == CONSTANT_EXPRESSION_RESOLVED &&
- target is ConstantEvaluationTarget) {
- entry.setValue(
- result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
- return true;
- }
- // Provide results for Source.
- if (target is Source) {
- String uriString = target.uri.toString();
- // Provide known results.
- if (result == LIBRARY_ELEMENT1 ||
- result == LIBRARY_ELEMENT2 ||
- result == LIBRARY_ELEMENT3 ||
- result == LIBRARY_ELEMENT4 ||
- result == LIBRARY_ELEMENT5 ||
- result == LIBRARY_ELEMENT6 ||
- result == LIBRARY_ELEMENT7 ||
- result == LIBRARY_ELEMENT8 ||
- result == LIBRARY_ELEMENT9 ||
- result == LIBRARY_ELEMENT) {
- LibraryElement libraryElement =
- resynthesizer.getLibraryElement(uriString);
- entry.setValue(result as ResultDescriptor<LibraryElement>,
- libraryElement, const <TargetedResult>[]);
- return true;
- } else if (result == READY_LIBRARY_ELEMENT2 ||
- result == READY_LIBRARY_ELEMENT6 ||
- result == READY_LIBRARY_ELEMENT7) {
- entry.setValue(
- result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
- return true;
- } else if (result == MODIFICATION_TIME) {
- entry.setValue(
- result as ResultDescriptor<int>, 0, const <TargetedResult>[]);
- return true;
- } else if (result == SOURCE_KIND) {
- UnlinkedUnit unlinked = _dataStore.unlinkedMap[uriString];
- if (unlinked != null) {
- entry.setValue(
- result as ResultDescriptor<SourceKind>,
- unlinked.isPartOf ? SourceKind.PART : SourceKind.LIBRARY,
- const <TargetedResult>[]);
- return true;
- }
- return false;
- } else if (result == CONTAINING_LIBRARIES) {
- List<String> libraryUriStrings =
- _dataStore.getContainingLibraryUris(uriString);
- if (libraryUriStrings != null) {
- List<Source> librarySources = libraryUriStrings
- .map((libraryUriString) =>
- context.sourceFactory.resolveUri(target, libraryUriString))
- .toList(growable: false);
- entry.setValue(result as ResultDescriptor<List<Source>>,
- librarySources, const <TargetedResult>[]);
- return true;
- }
- return false;
- }
- } else if (target is LibrarySpecificUnit) {
- if (result == CREATED_RESOLVED_UNIT1 ||
- result == CREATED_RESOLVED_UNIT2 ||
- result == CREATED_RESOLVED_UNIT3 ||
- result == CREATED_RESOLVED_UNIT4 ||
- result == CREATED_RESOLVED_UNIT5 ||
- result == CREATED_RESOLVED_UNIT6 ||
- result == CREATED_RESOLVED_UNIT7 ||
- result == CREATED_RESOLVED_UNIT8 ||
- result == CREATED_RESOLVED_UNIT9 ||
- result == CREATED_RESOLVED_UNIT10 ||
- result == CREATED_RESOLVED_UNIT11) {
- entry.setValue(
- result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
- return true;
- }
- if (result == COMPILATION_UNIT_ELEMENT) {
- String libraryUri = target.library.uri.toString();
- String unitUri = target.unit.uri.toString();
- CompilationUnitElement unit = resynthesizer.getElement(
- new ElementLocationImpl.con3(<String>[libraryUri, unitUri]));
- if (unit != null) {
- entry.setValue(result as ResultDescriptor<CompilationUnitElement>,
- unit, const <TargetedResult>[]);
- return true;
- }
- }
- } else if (target is VariableElement) {
- if (result == INFERRED_STATIC_VARIABLE) {
- entry.setValue(result as ResultDescriptor<VariableElement>, target,
- const <TargetedResult>[]);
- return true;
- }
- }
- // Unknown target.
- return false;
+ throw UnimplementedError();
}
/**
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
index 6bda8fd..1785442 100644
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ b/pkg/analyzer/lib/src/summary/prelink.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
@@ -21,19 +22,13 @@
UnlinkedUnit definingUnit,
GetPartCallback getPart,
GetImportCallback getImport,
- GetDeclaredVariable getDeclaredVariable) {
- return new _Prelinker(definingUnitUri, definingUnit, getPart, getImport,
- getDeclaredVariable)
+ DeclaredVariables declaredVariables) {
+ return new _Prelinker(
+ definingUnitUri, definingUnit, getPart, getImport, declaredVariables)
.prelink();
}
/**
- * Return the raw string value of the variable with the given [name],
- * or `null` of the variable is not defined.
- */
-typedef String GetDeclaredVariable(String name);
-
-/**
* Type of the callback used by the prelinker to obtain public namespace
* information about libraries with the given [absoluteUri] imported by the
* library to be prelinked (and the transitive closure of parts and exports
@@ -219,7 +214,7 @@
final UnlinkedUnit definingUnit;
final GetPartCallback getPart;
final GetImportCallback getImport;
- final GetDeclaredVariable getDeclaredVariable;
+ final DeclaredVariables declaredVariables;
/**
* Cache of values returned by [getImport].
@@ -263,7 +258,7 @@
final Map<String, _ExportNamespace> exportNamespaces = {};
_Prelinker(this.definingUnitUri, this.definingUnit, this.getPart,
- this.getImport, this.getDeclaredVariable) {
+ this.getImport, this.declaredVariables) {
partCache[definingUnitUri] = definingUnit;
importCache[definingUnitUri] = definingUnit.publicNamespace;
}
@@ -719,7 +714,7 @@
String _selectUri(
String defaultUri, List<UnlinkedConfiguration> configurations) {
for (UnlinkedConfiguration configuration in configurations) {
- if (getDeclaredVariable(configuration.name) == configuration.value) {
+ if (declaredVariables.get(configuration.name) == configuration.value) {
return configuration.uri;
}
}
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index 5e93786..f367937 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -344,14 +344,6 @@
typeName.typeArguments != null);
} else if (expr is ListLiteral) {
_serializeListLiteral(expr);
- // ignore: deprecated_member_use_from_same_package
- } else if (expr is MapLiteral) {
- // ignore: deprecated_member_use_from_same_package
- _serializeMapLiteral(expr);
- // ignore: deprecated_member_use_from_same_package
- } else if (expr is SetLiteral) {
- // ignore: deprecated_member_use_from_same_package
- _serializeSetLiteral(expr);
} else if (expr is SetOrMapLiteral) {
_serializeSetOrMapLiteral(expr);
} else if (expr is MethodInvocation) {
@@ -549,6 +541,23 @@
_serialize(element.key);
_serialize(element.value);
operations.add(UnlinkedExprOperation.makeMapLiteralEntry);
+ } else if (element is SpreadElement) {
+ _serialize(element.expression);
+ bool isNullAware = element.spreadOperator.type ==
+ TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+ operations.add(isNullAware
+ ? UnlinkedExprOperation.nullAwareSpreadElement
+ : UnlinkedExprOperation.spreadElement);
+ } else if (element is IfElement) {
+ _serialize(element.condition);
+ _serializeCollectionElement(element.thenElement);
+ var elseElement = element.elseElement;
+ if (elseElement == null) {
+ operations.add(UnlinkedExprOperation.ifElement);
+ } else {
+ _serializeCollectionElement(elseElement);
+ operations.add(UnlinkedExprOperation.ifElseElement);
+ }
} else {
// TODO(paulberry): Implement serialization for spread and control flow
// elements.
@@ -573,27 +582,6 @@
}
}
- @deprecated
- void _serializeMapLiteral(MapLiteral expr) {
- if (forConst || expr.typeArguments == null) {
- for (MapLiteralEntry entry in expr.entries) {
- _serialize(entry.key);
- _serialize(entry.value);
- }
- ints.add(expr.entries.length);
- } else {
- ints.add(0);
- }
- if (expr.typeArguments != null &&
- expr.typeArguments.arguments.length == 2) {
- references.add(serializeType(expr.typeArguments.arguments[0]));
- references.add(serializeType(expr.typeArguments.arguments[1]));
- operations.add(UnlinkedExprOperation.makeTypedMap);
- } else {
- operations.add(UnlinkedExprOperation.makeUntypedMap);
- }
- }
-
void _serializeMethodInvocation(MethodInvocation invocation) {
Expression target = invocation.target;
SimpleIdentifier methodName = invocation.methodName;
@@ -673,24 +661,6 @@
}
}
- @deprecated
- void _serializeSetLiteral(SetLiteral expr) {
- if (forConst || expr.typeArguments == null) {
- List<Expression> elements = expr.elements;
- elements.forEach(_serialize);
- ints.add(elements.length);
- } else {
- ints.add(0);
- }
- if (expr.typeArguments != null &&
- expr.typeArguments.arguments.length == 1) {
- references.add(serializeType(expr.typeArguments.arguments[0]));
- operations.add(UnlinkedExprOperation.makeTypedSet);
- } else {
- operations.add(UnlinkedExprOperation.makeUntypedSet);
- }
- }
-
void _serializeSetOrMapLiteral(SetOrMapLiteral expr) {
if (forConst || expr.typeArguments == null) {
for (CollectionElement element in expr.elements2) {
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index 9d7b6ad..f774d2a 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -4,6 +4,7 @@
import 'dart:collection';
+import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
@@ -25,11 +26,9 @@
class SummaryBuilder {
final Iterable<Source> librarySources;
final AnalysisContext context;
+
/**
* Create a summary builder for these [librarySources] and [context].
- *
- * TODO(paulberry): remove optional "strong" parameter once all callers have
- * stopped passing it in.
*/
SummaryBuilder(this.librarySources, this.context);
@@ -92,9 +91,7 @@
throw new StateError('Unable to find unresolved unit $uri.');
}
return unlinked;
- }, (String name) {
- throw new StateError('Unexpected call to GetDeclaredVariable($name).');
- });
+ }, DeclaredVariables(), context.analysisOptions);
map.forEach(bundleAssembler.addLinkedLibrary);
return bundleAssembler.assemble().toBuffer();
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index f8490e1..33f51e3 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -8,25 +8,17 @@
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/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
/// Deserializer of fully resolved ASTs from flat buffers.
class AstBinaryReader {
- final Reference _nameRoot;
- final LinkedNodeReference _linkedReferences;
- final List<Reference> _references;
+ final LinkedUnitContext _unitContext;
- final UnlinkedTokens _tokensBinary;
- final List<Token> _tokens;
-
- AstBinaryReader(this._nameRoot, this._linkedReferences, this._tokensBinary)
- : _references = List<Reference>(_linkedReferences.name.length),
- _tokens = List<Token>(_tokensBinary.type.length);
+ AstBinaryReader(this._unitContext);
AstNode readNode(LinkedNode data) {
if (data == null) return null;
@@ -269,89 +261,18 @@
}
}
- CommentToken _getCommentToken(int index) {
- var result = _getToken(index);
- var token = result;
- while (true) {
- index = _tokensBinary.next[index];
- if (index == 0) return result;
-
- var nextToken = _getToken(index);
- token.next = nextToken;
- token = nextToken;
- }
- }
-
T _getElement<T extends Element>(int index) {
- return _getReferenceByIndex(index)?.element;
+ var bundleContext = _unitContext.bundleContext;
+ return bundleContext.elementOfIndex(index);
}
List<T> _getElements<T extends Element>(List<int> indexList) {
- var result = List<T>(indexList.length);
- for (var i = 0; i < indexList.length; ++i) {
- var index = indexList[i];
- result[i] = _getElement(index);
- }
- return result;
- }
-
- Reference _getReferenceByIndex(int index) {
- var reference = _references[index];
- if (reference != null) return reference;
-
- if (index == 0) {
- _references[index] = _nameRoot;
- return _nameRoot;
- }
-
- var parentIndex = _linkedReferences.parent[index];
- var parent = _getReferenceByIndex(parentIndex);
- if (parent == null) return null;
-
- var name = _linkedReferences.name[index];
- reference = parent[name];
- _references[index] = reference;
-
- return reference;
+ var bundleContext = _unitContext.bundleContext;
+ return bundleContext.elementsOfIndexes(indexList);
}
Token _getToken(int index) {
- var token = _tokens[index];
- if (token == null) {
- var kind = _tokensBinary.kind[index];
- switch (kind) {
- case UnlinkedTokenKind.nothing:
- return null;
- case UnlinkedTokenKind.comment:
- return CommentToken(
- _binaryToAstTokenType(_tokensBinary.type[index]),
- _tokensBinary.lexeme[index],
- _tokensBinary.offset[index],
- );
- case UnlinkedTokenKind.keyword:
- return KeywordToken(
- _binaryToAstTokenType(_tokensBinary.type[index]),
- _tokensBinary.offset[index],
- _getCommentToken(_tokensBinary.precedingComment[index]),
- );
- case UnlinkedTokenKind.simple:
- return SimpleToken(
- _binaryToAstTokenType(_tokensBinary.type[index]),
- _tokensBinary.offset[index],
- _getCommentToken(_tokensBinary.precedingComment[index]),
- );
- case UnlinkedTokenKind.string:
- return StringToken(
- _binaryToAstTokenType(_tokensBinary.type[index]),
- _tokensBinary.lexeme[index],
- _tokensBinary.offset[index],
- _getCommentToken(_tokensBinary.precedingComment[index]),
- );
- default:
- throw UnimplementedError('Token kind: $kind');
- }
- }
- return token;
+ return _unitContext.tokensContext.tokenOfIndex(index);
}
List<Token> _getTokens(List<int> indexList) {
@@ -1236,7 +1157,7 @@
leftBracket: _getToken(data.setOrMapLiteral_leftBracket),
typeArguments: readNode(data.typedLiteral_typeArguments),
rightBracket: _getToken(data.setOrMapLiteral_leftBracket),
- );
+ )..staticType = _readType(data.expression_type);
if (data.setOrMapLiteral_isMap) {
node.becomeMap();
} else if (data.setOrMapLiteral_isSet) {
@@ -1523,279 +1444,4 @@
}
return result;
}
-
- static TokenType _binaryToAstTokenType(UnlinkedTokenType type) {
- switch (type) {
- case UnlinkedTokenType.ABSTRACT:
- return Keyword.ABSTRACT;
- case UnlinkedTokenType.AMPERSAND:
- return TokenType.AMPERSAND;
- case UnlinkedTokenType.AMPERSAND_AMPERSAND:
- return TokenType.AMPERSAND_AMPERSAND;
- case UnlinkedTokenType.AMPERSAND_EQ:
- return TokenType.AMPERSAND_EQ;
- case UnlinkedTokenType.AS:
- return TokenType.AS;
- case UnlinkedTokenType.ASSERT:
- return Keyword.ASSERT;
- case UnlinkedTokenType.ASYNC:
- return Keyword.ASYNC;
- case UnlinkedTokenType.AT:
- return TokenType.AT;
- case UnlinkedTokenType.AWAIT:
- return Keyword.AWAIT;
- case UnlinkedTokenType.BACKPING:
- return TokenType.BACKPING;
- case UnlinkedTokenType.BACKSLASH:
- return TokenType.BACKSLASH;
- case UnlinkedTokenType.BANG:
- return TokenType.BANG;
- case UnlinkedTokenType.BANG_EQ:
- return TokenType.BANG_EQ;
- case UnlinkedTokenType.BAR:
- return TokenType.BAR;
- case UnlinkedTokenType.BAR_BAR:
- return TokenType.BAR_BAR;
- case UnlinkedTokenType.BAR_EQ:
- return TokenType.BAR_EQ;
- case UnlinkedTokenType.BREAK:
- return Keyword.BREAK;
- case UnlinkedTokenType.CARET:
- return TokenType.CARET;
- case UnlinkedTokenType.CARET_EQ:
- return TokenType.CARET_EQ;
- case UnlinkedTokenType.CASE:
- return Keyword.CASE;
- case UnlinkedTokenType.CATCH:
- return Keyword.CATCH;
- case UnlinkedTokenType.CLASS:
- return Keyword.CLASS;
- case UnlinkedTokenType.CLOSE_CURLY_BRACKET:
- return TokenType.CLOSE_CURLY_BRACKET;
- case UnlinkedTokenType.CLOSE_PAREN:
- return TokenType.CLOSE_PAREN;
- case UnlinkedTokenType.CLOSE_SQUARE_BRACKET:
- return TokenType.CLOSE_SQUARE_BRACKET;
- case UnlinkedTokenType.COLON:
- return TokenType.COLON;
- case UnlinkedTokenType.COMMA:
- return TokenType.COMMA;
- case UnlinkedTokenType.CONST:
- return Keyword.CONST;
- case UnlinkedTokenType.CONTINUE:
- return Keyword.CONTINUE;
- case UnlinkedTokenType.COVARIANT:
- return Keyword.COVARIANT;
- case UnlinkedTokenType.DEFAULT:
- return Keyword.DEFAULT;
- case UnlinkedTokenType.DEFERRED:
- return Keyword.DEFERRED;
- case UnlinkedTokenType.DO:
- return Keyword.DO;
- case UnlinkedTokenType.DOUBLE:
- return TokenType.DOUBLE;
- case UnlinkedTokenType.DYNAMIC:
- return Keyword.DYNAMIC;
- case UnlinkedTokenType.ELSE:
- return Keyword.ELSE;
- case UnlinkedTokenType.ENUM:
- return Keyword.ENUM;
- case UnlinkedTokenType.EOF:
- return TokenType.EOF;
- case UnlinkedTokenType.EQ:
- return TokenType.EQ;
- case UnlinkedTokenType.EQ_EQ:
- return TokenType.EQ_EQ;
- case UnlinkedTokenType.EXPORT:
- return Keyword.EXPORT;
- case UnlinkedTokenType.EXTENDS:
- return Keyword.EXTENDS;
- case UnlinkedTokenType.EXTERNAL:
- return Keyword.EXTERNAL;
- case UnlinkedTokenType.FACTORY:
- return Keyword.FACTORY;
- case UnlinkedTokenType.FALSE:
- return Keyword.FALSE;
- case UnlinkedTokenType.FINAL:
- return Keyword.FINAL;
- case UnlinkedTokenType.FINALLY:
- return Keyword.FINALLY;
- case UnlinkedTokenType.FOR:
- return Keyword.FOR;
- case UnlinkedTokenType.FUNCTION:
- return TokenType.FUNCTION;
- case UnlinkedTokenType.FUNCTION_KEYWORD:
- return Keyword.FUNCTION;
- case UnlinkedTokenType.GET:
- return Keyword.GET;
- case UnlinkedTokenType.GT:
- return TokenType.GT;
- case UnlinkedTokenType.GT_EQ:
- return TokenType.GT_EQ;
- case UnlinkedTokenType.GT_GT:
- return TokenType.GT_GT;
- case UnlinkedTokenType.GT_GT_EQ:
- return TokenType.GT_GT_EQ;
- case UnlinkedTokenType.HASH:
- return TokenType.HASH;
- case UnlinkedTokenType.HEXADECIMAL:
- return TokenType.HEXADECIMAL;
- case UnlinkedTokenType.HIDE:
- return Keyword.HIDE;
- case UnlinkedTokenType.IDENTIFIER:
- return TokenType.IDENTIFIER;
- case UnlinkedTokenType.IF:
- return Keyword.IF;
- case UnlinkedTokenType.IMPLEMENTS:
- return Keyword.IMPLEMENTS;
- case UnlinkedTokenType.IMPORT:
- return Keyword.IMPORT;
- case UnlinkedTokenType.IN:
- return Keyword.IN;
- case UnlinkedTokenType.INDEX:
- return TokenType.INDEX;
- case UnlinkedTokenType.INDEX_EQ:
- return TokenType.INDEX_EQ;
- case UnlinkedTokenType.INT:
- return TokenType.INT;
- case UnlinkedTokenType.INTERFACE:
- return Keyword.INTERFACE;
- case UnlinkedTokenType.IS:
- return TokenType.IS;
- case UnlinkedTokenType.LIBRARY:
- return Keyword.LIBRARY;
- case UnlinkedTokenType.LT:
- return TokenType.LT;
- case UnlinkedTokenType.LT_EQ:
- return TokenType.LT_EQ;
- case UnlinkedTokenType.LT_LT:
- return TokenType.LT_LT;
- case UnlinkedTokenType.LT_LT_EQ:
- return TokenType.LT_LT_EQ;
- case UnlinkedTokenType.MINUS:
- return TokenType.MINUS;
- case UnlinkedTokenType.MINUS_EQ:
- return TokenType.MINUS_EQ;
- case UnlinkedTokenType.MINUS_MINUS:
- return TokenType.MINUS_MINUS;
- case UnlinkedTokenType.MIXIN:
- return Keyword.MIXIN;
- case UnlinkedTokenType.MULTI_LINE_COMMENT:
- return TokenType.MULTI_LINE_COMMENT;
- case UnlinkedTokenType.NATIVE:
- return Keyword.NATIVE;
- case UnlinkedTokenType.NEW:
- return Keyword.NEW;
- case UnlinkedTokenType.NULL:
- return Keyword.NULL;
- case UnlinkedTokenType.OF:
- return Keyword.OF;
- case UnlinkedTokenType.ON:
- return Keyword.ON;
- case UnlinkedTokenType.OPEN_CURLY_BRACKET:
- return TokenType.OPEN_CURLY_BRACKET;
- case UnlinkedTokenType.OPEN_PAREN:
- return TokenType.OPEN_PAREN;
- case UnlinkedTokenType.OPEN_SQUARE_BRACKET:
- return TokenType.OPEN_SQUARE_BRACKET;
- case UnlinkedTokenType.OPERATOR:
- return Keyword.OPERATOR;
- case UnlinkedTokenType.PART:
- return Keyword.PART;
- case UnlinkedTokenType.PATCH:
- return Keyword.PATCH;
- case UnlinkedTokenType.PERCENT:
- return TokenType.PERCENT;
- case UnlinkedTokenType.PERCENT_EQ:
- return TokenType.PERCENT_EQ;
- case UnlinkedTokenType.PERIOD:
- return TokenType.PERIOD;
- case UnlinkedTokenType.PERIOD_PERIOD:
- return TokenType.PERIOD_PERIOD;
- case UnlinkedTokenType.PERIOD_PERIOD_PERIOD:
- return TokenType.PERIOD_PERIOD_PERIOD;
- case UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION:
- return TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
- case UnlinkedTokenType.PLUS:
- return TokenType.PLUS;
- case UnlinkedTokenType.PLUS_EQ:
- return TokenType.PLUS_EQ;
- case UnlinkedTokenType.PLUS_PLUS:
- return TokenType.PLUS_PLUS;
- case UnlinkedTokenType.QUESTION:
- return TokenType.QUESTION;
- case UnlinkedTokenType.QUESTION_PERIOD:
- return TokenType.QUESTION_PERIOD;
- case UnlinkedTokenType.QUESTION_QUESTION:
- return TokenType.QUESTION_QUESTION;
- case UnlinkedTokenType.QUESTION_QUESTION_EQ:
- return TokenType.QUESTION_QUESTION_EQ;
- case UnlinkedTokenType.RETHROW:
- return Keyword.RETHROW;
- case UnlinkedTokenType.RETURN:
- return Keyword.RETURN;
- case UnlinkedTokenType.SCRIPT_TAG:
- return TokenType.SCRIPT_TAG;
- case UnlinkedTokenType.SEMICOLON:
- return TokenType.SEMICOLON;
- case UnlinkedTokenType.SET:
- return Keyword.SET;
- case UnlinkedTokenType.SHOW:
- return Keyword.SHOW;
- case UnlinkedTokenType.SINGLE_LINE_COMMENT:
- return TokenType.SINGLE_LINE_COMMENT;
- case UnlinkedTokenType.SLASH:
- return TokenType.SLASH;
- case UnlinkedTokenType.SLASH_EQ:
- return TokenType.SLASH_EQ;
- case UnlinkedTokenType.SOURCE:
- return Keyword.SOURCE;
- case UnlinkedTokenType.STAR:
- return TokenType.STAR;
- case UnlinkedTokenType.STAR_EQ:
- return TokenType.STAR_EQ;
- case UnlinkedTokenType.STATIC:
- return Keyword.STATIC;
- case UnlinkedTokenType.STRING:
- return TokenType.STRING;
- case UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION:
- return TokenType.STRING_INTERPOLATION_EXPRESSION;
- case UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER:
- return TokenType.STRING_INTERPOLATION_IDENTIFIER;
- case UnlinkedTokenType.SUPER:
- return Keyword.SUPER;
- case UnlinkedTokenType.SWITCH:
- return Keyword.SWITCH;
- case UnlinkedTokenType.SYNC:
- return Keyword.SYNC;
- case UnlinkedTokenType.THIS:
- return Keyword.THIS;
- case UnlinkedTokenType.THROW:
- return Keyword.THROW;
- case UnlinkedTokenType.TILDE:
- return TokenType.TILDE;
- case UnlinkedTokenType.TILDE_SLASH:
- return TokenType.TILDE_SLASH;
- case UnlinkedTokenType.TILDE_SLASH_EQ:
- return TokenType.TILDE_SLASH_EQ;
- case UnlinkedTokenType.TRUE:
- return Keyword.TRUE;
- case UnlinkedTokenType.TRY:
- return Keyword.TRY;
- case UnlinkedTokenType.TYPEDEF:
- return Keyword.TYPEDEF;
- case UnlinkedTokenType.VAR:
- return Keyword.VAR;
- case UnlinkedTokenType.VOID:
- return Keyword.VOID;
- case UnlinkedTokenType.WHILE:
- return Keyword.WHILE;
- case UnlinkedTokenType.WITH:
- return Keyword.WITH;
- case UnlinkedTokenType.YIELD:
- return Keyword.YIELD;
- default:
- throw StateError('Unexpected type: $type');
- }
- }
}
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 185370e..187dc7b 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -8,36 +8,24 @@
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/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:meta/meta.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
/// Serializer of fully resolved ASTs into flat buffers.
class AstBinaryWriter extends ThrowingAstVisitor<LinkedNodeBuilder> {
- final referenceRoot = Reference.root();
- final referenceBuilder = LinkedNodeReferenceBuilder();
- final _references = <Reference>[];
+ final LinkingBundleContext _linkingBundleContext;
+ final TokensContext _tokensContext;
- final UnlinkedTokensBuilder tokens = UnlinkedTokensBuilder();
- final Map<Token, int> _tokenMap = Map.identity();
- int _tokenIndex = 0;
+ /// This field is set temporary while visiting [FieldDeclaration] or
+ /// [TopLevelVariableDeclaration] to store data shared among all variables
+ /// in these declarations.
+ LinkedNodeVariablesDeclarationBuilder _variablesDeclaration;
- AstBinaryWriter() {
- _references.add(referenceRoot);
- _addToken(
- isSynthetic: true,
- kind: UnlinkedTokenKind.nothing,
- length: 0,
- lexeme: '',
- offset: 0,
- precedingComment: 0,
- type: UnlinkedTokenType.NOTHING,
- );
- }
+ AstBinaryWriter(this._linkingBundleContext, this._tokensContext);
@override
LinkedNodeBuilder visitAdjacentStrings(AdjacentStrings node) {
@@ -105,7 +93,7 @@
@override
LinkedNodeBuilder visitAssignmentExpression(AssignmentExpression node) {
return LinkedNodeBuilder.assignmentExpression(
- assignmentExpression_element: _getReference(node.staticElement).index,
+ assignmentExpression_element: _getReferenceIndex(node.staticElement),
assignmentExpression_leftHandSide: node.leftHandSide.accept(this),
assignmentExpression_operator: _getToken(node.operator),
assignmentExpression_rightHandSide: node.rightHandSide.accept(this),
@@ -125,7 +113,7 @@
@override
LinkedNodeBuilder visitBinaryExpression(BinaryExpression node) {
return LinkedNodeBuilder.binaryExpression(
- binaryExpression_element: _getReference(node.staticElement).index,
+ binaryExpression_element: _getReferenceIndex(node.staticElement),
binaryExpression_leftOperand: node.leftOperand.accept(this),
binaryExpression_operator: _getToken(node.operator),
binaryExpression_rightOperand: node.rightOperand.accept(this),
@@ -312,7 +300,7 @@
@override
LinkedNodeBuilder visitConstructorName(ConstructorName node) {
return LinkedNodeBuilder.constructorName(
- constructorName_element: _getReference(node.staticElement).index,
+ constructorName_element: _getReferenceIndex(node.staticElement),
constructorName_name: node.name?.accept(this),
constructorName_period: _getToken(node.period),
constructorName_type: node.type.accept(this),
@@ -452,6 +440,10 @@
@override
LinkedNodeBuilder visitFieldDeclaration(FieldDeclaration node) {
+ _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder(
+ isStatic: node.isStatic,
+ );
+
var builder = LinkedNodeBuilder.fieldDeclaration(
fieldDeclaration_covariantKeyword: _getToken(node.covariantKeyword),
fieldDeclaration_fields: node.fields.accept(this),
@@ -459,6 +451,10 @@
fieldDeclaration_staticKeyword: _getToken(node.staticKeyword),
);
_storeClassMember(builder, node);
+
+ _variablesDeclaration.comment = builder.annotatedNode_comment;
+ _variablesDeclaration = null;
+
return builder;
}
@@ -688,7 +684,7 @@
@override
LinkedNodeBuilder visitIndexExpression(IndexExpression node) {
return LinkedNodeBuilder.indexExpression(
- indexExpression_element: _getReference(node.staticElement).index,
+ indexExpression_element: _getReferenceIndex(node.staticElement),
indexExpression_index: node.index.accept(this),
indexExpression_leftBracket: _getToken(node.leftBracket),
indexExpression_rightBracket: _getToken(node.rightBracket),
@@ -812,6 +808,7 @@
methodDeclaration_operatorKeyword: _getToken(node.operatorKeyword),
methodDeclaration_propertyKeyword: _getToken(node.propertyKeyword),
methodDeclaration_returnType: node.returnType?.accept(this),
+ methodDeclaration_typeParameters: node.typeParameters?.accept(this),
);
_storeClassMember(builder, node);
return builder;
@@ -899,7 +896,7 @@
LinkedNodeBuilder visitPostfixExpression(PostfixExpression node) {
return LinkedNodeBuilder.postfixExpression(
expression_type: _writeType(node.staticType),
- postfixExpression_element: _getReference(node.staticElement).index,
+ postfixExpression_element: _getReferenceIndex(node.staticElement),
postfixExpression_operand: node.operand.accept(this),
postfixExpression_operator: _getToken(node.operator),
);
@@ -919,7 +916,7 @@
LinkedNodeBuilder visitPrefixExpression(PrefixExpression node) {
return LinkedNodeBuilder.prefixExpression(
expression_type: _writeType(node.staticType),
- prefixExpression_element: _getReference(node.staticElement).index,
+ prefixExpression_element: _getReferenceIndex(node.staticElement),
prefixExpression_operand: node.operand.accept(this),
prefixExpression_operator: _getToken(node.operator),
);
@@ -945,7 +942,7 @@
redirectingConstructorInvocation_constructorName:
node.constructorName?.accept(this),
redirectingConstructorInvocation_element:
- _getReference(node.staticElement).index,
+ _getReferenceIndex(node.staticElement),
redirectingConstructorInvocation_period: _getToken(node.period),
redirectingConstructorInvocation_thisKeyword: _getToken(node.thisKeyword),
);
@@ -1012,11 +1009,16 @@
@override
LinkedNodeBuilder visitSimpleIdentifier(SimpleIdentifier node) {
- var isDeclared = node.inDeclarationContext();
+ Element element;
+ if (!node.inDeclarationContext()) {
+ element = node.staticElement;
+ if (element is MultiplyDefinedElement) {
+ element = null;
+ }
+ }
return LinkedNodeBuilder.simpleIdentifier(
- simpleIdentifier_element:
- isDeclared ? null : _getReference(node.staticElement).index,
+ simpleIdentifier_element: _getReferenceIndex(element),
simpleIdentifier_token: _getToken(node.token),
expression_type: _writeType(node.staticType),
);
@@ -1056,7 +1058,7 @@
superConstructorInvocation_constructorName:
node.constructorName?.accept(this),
superConstructorInvocation_element:
- _getReference(node.staticElement).index,
+ _getReferenceIndex(node.staticElement),
superConstructorInvocation_period: _getToken(node.period),
superConstructorInvocation_superKeyword: _getToken(node.superKeyword),
);
@@ -1133,11 +1135,17 @@
@override
LinkedNodeBuilder visitTopLevelVariableDeclaration(
TopLevelVariableDeclaration node) {
+ _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder();
+
var builder = LinkedNodeBuilder.topLevelVariableDeclaration(
topLevelVariableDeclaration_semicolon: _getToken(node.semicolon),
topLevelVariableDeclaration_variableList: node.variables?.accept(this),
);
_storeCompilationUnitMember(builder, node);
+
+ _variablesDeclaration.comment = builder.annotatedNode_comment;
+ _variablesDeclaration = null;
+
return builder;
}
@@ -1196,11 +1204,17 @@
variableDeclaration_equals: _getToken(node.equals),
variableDeclaration_initializer: node.initializer?.accept(this),
variableDeclaration_name: node.name.accept(this),
+ variableDeclaration_declaration: _variablesDeclaration,
);
}
@override
LinkedNodeBuilder visitVariableDeclarationList(VariableDeclarationList node) {
+ if (_variablesDeclaration != null) {
+ _variablesDeclaration.isConst = node.isConst;
+ _variablesDeclaration.isFinal = node.isFinal;
+ }
+
var builder = LinkedNodeBuilder.variableDeclarationList(
variableDeclarationList_keyword: _getToken(node.keyword),
variableDeclarationList_type: node.type?.accept(this),
@@ -1251,184 +1265,26 @@
}
LinkedNodeBuilder writeNode(AstNode node) {
- _writeTokens(node.beginToken, node.endToken);
return node.accept(this);
}
- /// Write [referenceRoot] and all its children into [referenceBuilder].
- void writeReferences() {
- for (var reference in _references) {
- referenceBuilder.parent.add(reference.parent?.index ?? 0);
- referenceBuilder.name.add(reference.name);
+ int _getReferenceIndex(Element element) {
+ if (element == null) return 0;
+
+ if (element is Member) {
+ element = (element as Member).baseElement;
}
- }
- void _addToken({
- @required bool isSynthetic,
- @required UnlinkedTokenKind kind,
- @required int length,
- @required String lexeme,
- @required int offset,
- @required int precedingComment,
- @required UnlinkedTokenType type,
- }) {
- tokens.endGroup.add(0);
- tokens.isSynthetic.add(isSynthetic);
- tokens.kind.add(kind);
- tokens.length.add(length);
- tokens.lexeme.add(lexeme);
- tokens.next.add(0);
- tokens.offset.add(offset);
- tokens.precedingComment.add(precedingComment);
- tokens.type.add(type);
- _tokenIndex++;
- }
-
- void _ensureReferenceIndex(Reference reference) {
- if (reference.index == null) {
- reference.index = _references.length;
- _references.add(reference);
+ var reference = (element as ElementImpl).reference;
+ if (identical(element, DynamicElementImpl.instance)) {
+ reference = _linkingBundleContext.dynamicReference;
}
- }
- Reference _getReference(Element element) {
- if (element == null) return referenceRoot;
-
- // TODO(scheglov) handle Member elements
-
- Reference result;
- if (element is ClassElement) {
- var containerRef = _getReference(element.library).getChild('@class');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else if (element is CompilationUnitElement) {
- return _getReference(element.enclosingElement);
- } else if (element is ConstructorElement) {
- var enclosingRef = _getReference(element.enclosingElement);
- var containerRef = enclosingRef.getChild('@constructor');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else if (element is DynamicElementImpl) {
- result = _getReference(element.library).getChild('@dynamic');
- } else if (element is FieldElement) {
- var enclosingRef = _getReference(element.enclosingElement);
- var containerRef = enclosingRef.getChild('@field');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else if (element is FunctionElement) {
- var containerRef = _getReference(element.library).getChild('@function');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name ?? '');
- } else if (element is FunctionTypeAliasElement) {
- var libraryRef = _getReference(element.library);
- var containerRef = libraryRef.getChild('@functionTypeAlias');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else if (element is GenericFunctionTypeElement) {
- if (element.enclosingElement is GenericTypeAliasElement) {
- return _getReference(element.enclosingElement);
- } else {
- var libraryRef = _getReference(element.library);
- var containerRef = libraryRef.getChild('@functionType');
- _ensureReferenceIndex(containerRef);
-
- // TODO(scheglov) do we need to store these elements at all?
- result = containerRef.getChild('<unnamed>');
- }
- } else if (element is GenericTypeAliasElement) {
- var containerRef = _getReference(element.library).getChild('@typeAlias');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else if (element is GenericFunctionTypeElement &&
- element.enclosingElement is ParameterElement) {
- return _getReference(element.enclosingElement);
- } else if (element is LibraryElement) {
- var uriStr = element.source.uri.toString();
- result = referenceRoot.getChild(uriStr);
- } else if (element is LabelElement) {
- var enclosingRef = _getReference(element.enclosingElement);
- var containerRef = enclosingRef.getChild('@label');
- _ensureReferenceIndex(containerRef);
-
- // TODO(scheglov) use index instead of offset
- result = containerRef.getChild('${element.nameOffset}');
- } else if (element is LocalVariableElement) {
- var enclosingRef = _getReference(element.enclosingElement);
- var containerRef = enclosingRef.getChild('@localVariable');
- _ensureReferenceIndex(containerRef);
-
- // TODO(scheglov) use index instead of offset
- result = containerRef.getChild('${element.nameOffset}');
- } else if (element is MethodElement) {
- var enclosingRef = _getReference(element.enclosingElement);
- var containerRef = enclosingRef.getChild('@method');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else if (element is MultiplyDefinedElement) {
- return referenceRoot;
- } else if (element is ParameterElement) {
- var enclosing = element.enclosingElement;
- var enclosingRef = _getReference(enclosing);
- var containerRef = enclosingRef.getChild('@parameter');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else if (element is PrefixElement) {
- var containerRef = _getReference(element.library).getChild('@prefix');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else if (element is PropertyAccessorElement) {
- var enclosingRef = _getReference(element.library);
- var containerRef = enclosingRef.getChild(
- element.isGetter ? '@getter' : '@setter',
- );
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.displayName);
- } else if (element is TopLevelVariableElement) {
- var enclosingRef = _getReference(element.library);
- var containerRef = enclosingRef.getChild('@variable');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else if (element is TypeParameterElement) {
- var enclosingRef = _getReference(element.enclosingElement);
- var containerRef = enclosingRef.getChild('@typeParameter');
- _ensureReferenceIndex(containerRef);
-
- result = containerRef.getChild(element.name);
- } else {
- throw UnimplementedError('(${element.runtimeType}) $element');
- }
- _ensureReferenceIndex(result);
- return result;
- }
-
- List<int> _getReferences(List<Element> elements) {
- var result = List<int>(elements.length);
- for (var i = 0; i < elements.length; ++i) {
- var element = elements[i];
- result[i] = _getReference(element).index;
- }
- return result;
+ return _linkingBundleContext.indexOfReference(reference);
}
int _getToken(Token token) {
- if (token == null) return 0;
-
- var index = _tokenMap[token];
- if (index == null) {
- throw StateError('Token must be written first: $token');
- }
- return index;
+ return _tokensContext.indexOfToken(token);
}
List<int> _getTokens(List<Token> tokenList) {
@@ -1602,36 +1458,7 @@
builder
..uriBasedDirective_uri = node.uri.accept(this)
..uriBasedDirective_uriContent = node.uriContent
- ..uriBasedDirective_uriElement = _getReference(node.uriElement).index;
- }
-
- int _writeCommentToken(CommentToken token) {
- if (token == null) return 0;
- var firstIndex = _tokenIndex;
-
- var previousIndex = 0;
- while (token != null) {
- var index = _tokenIndex;
- _tokenMap[token] = index;
- _addToken(
- isSynthetic: false,
- kind: UnlinkedTokenKind.comment,
- length: token.length,
- lexeme: token.lexeme,
- offset: token.offset,
- precedingComment: 0,
- type: _astToBinaryTokenType(token.type),
- );
-
- if (previousIndex != 0) {
- tokens.next[previousIndex] = index;
- }
- previousIndex = index;
-
- token = token.next;
- }
-
- return firstIndex;
+ ..uriBasedDirective_uriElement = _getReferenceIndex(node.uriElement);
}
List<LinkedNodeBuilder> _writeNodeList(List<AstNode> nodeList) {
@@ -1646,389 +1473,7 @@
return result;
}
- int _writeToken(Token token) {
- assert(_tokenMap[token] == null);
-
- var commentIndex = _writeCommentToken(token.precedingComments);
-
- var index = _tokenIndex;
- _tokenMap[token] = index;
-
- if (token is KeywordToken) {
- _addToken(
- isSynthetic: token.isSynthetic,
- kind: UnlinkedTokenKind.keyword,
- lexeme: '',
- offset: token.offset,
- length: token.length,
- precedingComment: commentIndex,
- type: _astToBinaryTokenType(token.type),
- );
- } else if (token is StringToken) {
- _addToken(
- isSynthetic: token.isSynthetic,
- kind: UnlinkedTokenKind.string,
- lexeme: token.lexeme,
- offset: token.offset,
- length: token.length,
- precedingComment: commentIndex,
- type: _astToBinaryTokenType(token.type),
- );
- } else if (token is SimpleToken) {
- _addToken(
- isSynthetic: token.isSynthetic,
- kind: UnlinkedTokenKind.simple,
- lexeme: token.lexeme,
- offset: token.offset,
- length: token.length,
- precedingComment: commentIndex,
- type: _astToBinaryTokenType(token.type),
- );
- } else {
- throw UnimplementedError('(${token.runtimeType}) $token');
- }
-
- return index;
- }
-
- /// Write all the tokens from the [first] to the [last] inclusively.
- void _writeTokens(Token first, Token last) {
- if (first is CommentToken) {
- first = (first as CommentToken).parent;
- }
-
- var endGroupToBeginIndexMap = <Token, int>{};
- var previousIndex = 0;
- for (var token = first;; token = token.next) {
- var index = _writeToken(token);
-
- if (previousIndex != 0) {
- tokens.next[previousIndex] = index;
- }
- previousIndex = index;
-
- if (token.endGroup != null) {
- endGroupToBeginIndexMap[token.endGroup] = index;
- }
-
- var beginIndex = endGroupToBeginIndexMap[token];
- if (beginIndex != null) {
- tokens.endGroup[beginIndex] = index;
- }
-
- if (token == last) break;
- }
- }
-
LinkedNodeTypeBuilder _writeType(DartType type) {
- if (type == null) return null;
-
- if (type.isBottom) {
- return LinkedNodeTypeBuilder(
- kind: LinkedNodeTypeKind.bottom,
- );
- } else if (type.isDynamic) {
- return LinkedNodeTypeBuilder(
- kind: LinkedNodeTypeKind.dynamic_,
- );
- } else if (type is FunctionType) {
- return LinkedNodeTypeBuilder(
- kind: LinkedNodeTypeKind.function,
- functionFormalParameters: _getReferences(type.parameters),
- functionReturnType: _writeType(type.returnType),
- functionTypeParameters: _getReferences(type.parameters),
- );
- } else if (type is InterfaceType) {
- return LinkedNodeTypeBuilder(
- kind: LinkedNodeTypeKind.interface,
- interfaceClass: _getReference(type.element).index,
- interfaceTypeArguments: type.typeArguments.map(_writeType).toList(),
- );
- } else if (type is TypeParameterType) {
- return LinkedNodeTypeBuilder(
- kind: LinkedNodeTypeKind.typeParameter,
- typeParameterParameter: _getReference(type.element).index,
- );
- } else if (type is VoidType) {
- return LinkedNodeTypeBuilder(
- kind: LinkedNodeTypeKind.void_,
- );
- } else {
- throw UnimplementedError('(${type.runtimeType}) $type');
- }
- }
-
- static UnlinkedTokenType _astToBinaryTokenType(TokenType type) {
- if (type == Keyword.ABSTRACT) {
- return UnlinkedTokenType.ABSTRACT;
- } else if (type == TokenType.AMPERSAND) {
- return UnlinkedTokenType.AMPERSAND;
- } else if (type == TokenType.AMPERSAND_AMPERSAND) {
- return UnlinkedTokenType.AMPERSAND_AMPERSAND;
- } else if (type == TokenType.AMPERSAND_EQ) {
- return UnlinkedTokenType.AMPERSAND_EQ;
- } else if (type == TokenType.AS) {
- return UnlinkedTokenType.AS;
- } else if (type == Keyword.ASSERT) {
- return UnlinkedTokenType.ASSERT;
- } else if (type == Keyword.ASYNC) {
- return UnlinkedTokenType.ASYNC;
- } else if (type == TokenType.AT) {
- return UnlinkedTokenType.AT;
- } else if (type == Keyword.AWAIT) {
- return UnlinkedTokenType.AWAIT;
- } else if (type == TokenType.BACKPING) {
- return UnlinkedTokenType.BACKPING;
- } else if (type == TokenType.BACKSLASH) {
- return UnlinkedTokenType.BACKSLASH;
- } else if (type == TokenType.BANG) {
- return UnlinkedTokenType.BANG;
- } else if (type == TokenType.BANG_EQ) {
- return UnlinkedTokenType.BANG_EQ;
- } else if (type == TokenType.BAR) {
- return UnlinkedTokenType.BAR;
- } else if (type == TokenType.BAR_BAR) {
- return UnlinkedTokenType.BAR_BAR;
- } else if (type == TokenType.BAR_EQ) {
- return UnlinkedTokenType.BAR_EQ;
- } else if (type == Keyword.BREAK) {
- return UnlinkedTokenType.BREAK;
- } else if (type == TokenType.CARET) {
- return UnlinkedTokenType.CARET;
- } else if (type == TokenType.CARET_EQ) {
- return UnlinkedTokenType.CARET_EQ;
- } else if (type == Keyword.CASE) {
- return UnlinkedTokenType.CASE;
- } else if (type == Keyword.CATCH) {
- return UnlinkedTokenType.CATCH;
- } else if (type == Keyword.CLASS) {
- return UnlinkedTokenType.CLASS;
- } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
- return UnlinkedTokenType.CLOSE_CURLY_BRACKET;
- } else if (type == TokenType.CLOSE_PAREN) {
- return UnlinkedTokenType.CLOSE_PAREN;
- } else if (type == TokenType.CLOSE_SQUARE_BRACKET) {
- return UnlinkedTokenType.CLOSE_SQUARE_BRACKET;
- } else if (type == TokenType.COLON) {
- return UnlinkedTokenType.COLON;
- } else if (type == TokenType.COMMA) {
- return UnlinkedTokenType.COMMA;
- } else if (type == Keyword.CONST) {
- return UnlinkedTokenType.CONST;
- } else if (type == Keyword.CONTINUE) {
- return UnlinkedTokenType.CONTINUE;
- } else if (type == Keyword.COVARIANT) {
- return UnlinkedTokenType.COVARIANT;
- } else if (type == Keyword.DEFAULT) {
- return UnlinkedTokenType.DEFAULT;
- } else if (type == Keyword.DEFERRED) {
- return UnlinkedTokenType.DEFERRED;
- } else if (type == Keyword.DO) {
- return UnlinkedTokenType.DO;
- } else if (type == TokenType.DOUBLE) {
- return UnlinkedTokenType.DOUBLE;
- } else if (type == Keyword.DYNAMIC) {
- return UnlinkedTokenType.DYNAMIC;
- } else if (type == Keyword.ELSE) {
- return UnlinkedTokenType.ELSE;
- } else if (type == Keyword.ENUM) {
- return UnlinkedTokenType.ENUM;
- } else if (type == TokenType.EOF) {
- return UnlinkedTokenType.EOF;
- } else if (type == TokenType.EQ) {
- return UnlinkedTokenType.EQ;
- } else if (type == TokenType.EQ_EQ) {
- return UnlinkedTokenType.EQ_EQ;
- } else if (type == Keyword.EXPORT) {
- return UnlinkedTokenType.EXPORT;
- } else if (type == Keyword.EXTENDS) {
- return UnlinkedTokenType.EXTENDS;
- } else if (type == Keyword.EXTERNAL) {
- return UnlinkedTokenType.EXTERNAL;
- } else if (type == Keyword.FACTORY) {
- return UnlinkedTokenType.FACTORY;
- } else if (type == Keyword.FALSE) {
- return UnlinkedTokenType.FALSE;
- } else if (type == Keyword.FINAL) {
- return UnlinkedTokenType.FINAL;
- } else if (type == Keyword.FINALLY) {
- return UnlinkedTokenType.FINALLY;
- } else if (type == Keyword.FOR) {
- return UnlinkedTokenType.FOR;
- } else if (type == Keyword.FUNCTION) {
- return UnlinkedTokenType.FUNCTION_KEYWORD;
- } else if (type == TokenType.FUNCTION) {
- return UnlinkedTokenType.FUNCTION;
- } else if (type == Keyword.GET) {
- return UnlinkedTokenType.GET;
- } else if (type == TokenType.GT) {
- return UnlinkedTokenType.GT;
- } else if (type == TokenType.GT_EQ) {
- return UnlinkedTokenType.GT_EQ;
- } else if (type == TokenType.GT_GT) {
- return UnlinkedTokenType.GT_GT;
- } else if (type == TokenType.GT_GT_EQ) {
- return UnlinkedTokenType.GT_GT_EQ;
- } else if (type == TokenType.HASH) {
- return UnlinkedTokenType.HASH;
- } else if (type == TokenType.HEXADECIMAL) {
- return UnlinkedTokenType.HEXADECIMAL;
- } else if (type == Keyword.HIDE) {
- return UnlinkedTokenType.HIDE;
- } else if (type == TokenType.IDENTIFIER) {
- return UnlinkedTokenType.IDENTIFIER;
- } else if (type == Keyword.IF) {
- return UnlinkedTokenType.IF;
- } else if (type == Keyword.IMPLEMENTS) {
- return UnlinkedTokenType.IMPLEMENTS;
- } else if (type == Keyword.IMPORT) {
- return UnlinkedTokenType.IMPORT;
- } else if (type == Keyword.IN) {
- return UnlinkedTokenType.IN;
- } else if (type == TokenType.INDEX) {
- return UnlinkedTokenType.INDEX;
- } else if (type == TokenType.INDEX_EQ) {
- return UnlinkedTokenType.INDEX_EQ;
- } else if (type == TokenType.INT) {
- return UnlinkedTokenType.INT;
- } else if (type == Keyword.INTERFACE) {
- return UnlinkedTokenType.INTERFACE;
- } else if (type == TokenType.IS) {
- return UnlinkedTokenType.IS;
- } else if (type == Keyword.LIBRARY) {
- return UnlinkedTokenType.LIBRARY;
- } else if (type == TokenType.LT) {
- return UnlinkedTokenType.LT;
- } else if (type == TokenType.LT_EQ) {
- return UnlinkedTokenType.LT_EQ;
- } else if (type == TokenType.LT_LT) {
- return UnlinkedTokenType.LT_LT;
- } else if (type == TokenType.LT_LT_EQ) {
- return UnlinkedTokenType.LT_LT_EQ;
- } else if (type == TokenType.MINUS) {
- return UnlinkedTokenType.MINUS;
- } else if (type == TokenType.MINUS_EQ) {
- return UnlinkedTokenType.MINUS_EQ;
- } else if (type == TokenType.MINUS_MINUS) {
- return UnlinkedTokenType.MINUS_MINUS;
- } else if (type == Keyword.MIXIN) {
- return UnlinkedTokenType.MIXIN;
- } else if (type == TokenType.MULTI_LINE_COMMENT) {
- return UnlinkedTokenType.MULTI_LINE_COMMENT;
- } else if (type == Keyword.NATIVE) {
- return UnlinkedTokenType.NATIVE;
- } else if (type == Keyword.NEW) {
- return UnlinkedTokenType.NEW;
- } else if (type == Keyword.NULL) {
- return UnlinkedTokenType.NULL;
- } else if (type == Keyword.OF) {
- return UnlinkedTokenType.OF;
- } else if (type == Keyword.ON) {
- return UnlinkedTokenType.ON;
- } else if (type == TokenType.OPEN_CURLY_BRACKET) {
- return UnlinkedTokenType.OPEN_CURLY_BRACKET;
- } else if (type == TokenType.OPEN_PAREN) {
- return UnlinkedTokenType.OPEN_PAREN;
- } else if (type == TokenType.OPEN_SQUARE_BRACKET) {
- return UnlinkedTokenType.OPEN_SQUARE_BRACKET;
- } else if (type == Keyword.OPERATOR) {
- return UnlinkedTokenType.OPERATOR;
- } else if (type == Keyword.PART) {
- return UnlinkedTokenType.PART;
- } else if (type == Keyword.PATCH) {
- return UnlinkedTokenType.PATCH;
- } else if (type == TokenType.PERCENT) {
- return UnlinkedTokenType.PERCENT;
- } else if (type == TokenType.PERCENT_EQ) {
- return UnlinkedTokenType.PERCENT_EQ;
- } else if (type == TokenType.PERIOD) {
- return UnlinkedTokenType.PERIOD;
- } else if (type == TokenType.PERIOD_PERIOD) {
- return UnlinkedTokenType.PERIOD_PERIOD;
- } else if (type == TokenType.PERIOD_PERIOD_PERIOD) {
- return UnlinkedTokenType.PERIOD_PERIOD_PERIOD;
- } else if (type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
- return UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION;
- } else if (type == TokenType.PLUS) {
- return UnlinkedTokenType.PLUS;
- } else if (type == TokenType.PLUS_EQ) {
- return UnlinkedTokenType.PLUS_EQ;
- } else if (type == TokenType.PLUS_PLUS) {
- return UnlinkedTokenType.PLUS_PLUS;
- } else if (type == TokenType.QUESTION) {
- return UnlinkedTokenType.QUESTION;
- } else if (type == TokenType.QUESTION_PERIOD) {
- return UnlinkedTokenType.QUESTION_PERIOD;
- } else if (type == TokenType.QUESTION_QUESTION) {
- return UnlinkedTokenType.QUESTION_QUESTION;
- } else if (type == TokenType.QUESTION_QUESTION_EQ) {
- return UnlinkedTokenType.QUESTION_QUESTION_EQ;
- } else if (type == Keyword.RETHROW) {
- return UnlinkedTokenType.RETHROW;
- } else if (type == Keyword.RETURN) {
- return UnlinkedTokenType.RETURN;
- } else if (type == TokenType.SCRIPT_TAG) {
- return UnlinkedTokenType.SCRIPT_TAG;
- } else if (type == TokenType.SEMICOLON) {
- return UnlinkedTokenType.SEMICOLON;
- } else if (type == Keyword.SET) {
- return UnlinkedTokenType.SET;
- } else if (type == Keyword.SHOW) {
- return UnlinkedTokenType.SHOW;
- } else if (type == TokenType.SINGLE_LINE_COMMENT) {
- return UnlinkedTokenType.SINGLE_LINE_COMMENT;
- } else if (type == TokenType.SLASH) {
- return UnlinkedTokenType.SLASH;
- } else if (type == TokenType.SLASH_EQ) {
- return UnlinkedTokenType.SLASH_EQ;
- } else if (type == Keyword.SOURCE) {
- return UnlinkedTokenType.SOURCE;
- } else if (type == TokenType.STAR) {
- return UnlinkedTokenType.STAR;
- } else if (type == TokenType.STAR_EQ) {
- return UnlinkedTokenType.STAR_EQ;
- } else if (type == Keyword.STATIC) {
- return UnlinkedTokenType.STATIC;
- } else if (type == TokenType.STRING) {
- return UnlinkedTokenType.STRING;
- } else if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
- return UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION;
- } else if (type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
- return UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER;
- } else if (type == Keyword.SUPER) {
- return UnlinkedTokenType.SUPER;
- } else if (type == Keyword.SWITCH) {
- return UnlinkedTokenType.SWITCH;
- } else if (type == Keyword.SYNC) {
- return UnlinkedTokenType.SYNC;
- } else if (type == Keyword.THIS) {
- return UnlinkedTokenType.THIS;
- } else if (type == Keyword.THROW) {
- return UnlinkedTokenType.THROW;
- } else if (type == TokenType.TILDE) {
- return UnlinkedTokenType.TILDE;
- } else if (type == TokenType.TILDE_SLASH) {
- return UnlinkedTokenType.TILDE_SLASH;
- } else if (type == TokenType.TILDE_SLASH_EQ) {
- return UnlinkedTokenType.TILDE_SLASH_EQ;
- } else if (type == Keyword.TRUE) {
- return UnlinkedTokenType.TRUE;
- } else if (type == Keyword.TRY) {
- return UnlinkedTokenType.TRY;
- } else if (type == Keyword.TYPEDEF) {
- return UnlinkedTokenType.TYPEDEF;
- } else if (type == Keyword.VAR) {
- return UnlinkedTokenType.VAR;
- } else if (type == Keyword.VOID) {
- return UnlinkedTokenType.VOID;
- } else if (type == Keyword.WHILE) {
- return UnlinkedTokenType.WHILE;
- } else if (type == Keyword.WITH) {
- return UnlinkedTokenType.WITH;
- } else if (type == Keyword.YIELD) {
- return UnlinkedTokenType.YIELD;
- } else {
- throw StateError('Unexpected type: $type');
- }
+ return _linkingBundleContext.writeType(type);
}
}
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
new file mode 100644
index 0000000..c3dcf81
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, 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/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+/// Used to resolve some AST nodes - variable initializers, and annotations.
+class AstResolver {
+ final Linker _linker;
+
+ LibraryElement _library;
+ Scope _nameScope;
+
+ AstResolver(this._linker, Reference libraryRef) {
+ _library = _linker.elementFactory.elementOfReference(libraryRef);
+ _nameScope = LibraryScope(_library);
+ }
+
+ LinkedNode resolve(UnitBuilder unit, AstNode node) {
+ var source = _FakeSource();
+ var errorListener = AnalysisErrorListener.NULL_LISTENER;
+
+ var typeResolverVisitor = new TypeResolverVisitor(
+ _library, source, _linker.typeProvider, errorListener,
+ nameScope: _nameScope);
+ node.accept(typeResolverVisitor);
+
+// expression.accept(_astRewriteVisitor);
+// expression.accept(_variableResolverVisitor);
+// if (_linker.getAst != null) {
+// expression.accept(_partialResolverVisitor);
+// }
+
+ var resolverVisitor = new ResolverVisitor(_linker.inheritance, _library,
+ source, _linker.typeProvider, errorListener,
+ nameScope: _nameScope,
+ propagateTypes: false,
+ reportConstEvaluationErrors: false);
+ node.accept(resolverVisitor);
+
+ var writer = AstBinaryWriter(
+ _linker.linkingBundleContext,
+ unit.context.tokensContext,
+ );
+ return writer.writeNode(node);
+ }
+}
+
+class _FakeSource implements Source {
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analyzer/lib/src/summary2/builder/library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/library_builder.dart
deleted file mode 100644
index a816247..0000000
--- a/pkg/analyzer/lib/src/summary2/builder/library_builder.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2019, 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/summary/idl.dart';
-import 'package:analyzer/src/summary2/builder/prefix_builder.dart';
-import 'package:analyzer/src/summary2/declaration.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/summary2/scope.dart';
-
-class LibraryBuilder {
- final Uri uri;
- final Reference reference;
- final List<UnitBuilder> units = [];
-
- /// The import scope of the library.
- final Scope importScope;
-
- /// Local declarations, enclosed by [importScope].
- final Scope scope;
-
- /// The export scope of the library.
- final Scope exportScope = Scope.top();
-
- LibraryBuilder(Uri uri, Reference reference)
- : this._(uri, reference, Scope.top());
-
- LibraryBuilder._(this.uri, this.reference, this.importScope)
- : scope = Scope(importScope, <String, Declaration>{});
-
- /// Add top-level declaration of the library units to the local scope.
- void addLocalDeclarations() {
- for (var unit in units) {
- for (var node in unit.node.compilationUnit_declarations) {
- if (node.kind == LinkedNodeKind.classDeclaration) {
- var name = unit.context.getUnitMemberName(node);
- var reference = this.reference.getChild('@class').getChild(name);
- reference.node = node;
- var declaration = Declaration(name, reference);
- scope.declare(name, declaration);
- } else {
- // TODO(scheglov) implement
- throw UnimplementedError();
- }
- }
- }
- }
-
- /// Return `true` if the export scope was modified.
- bool addToExportScope(String name, Declaration declaration) {
- if (name.startsWith('_')) return false;
- if (declaration is PrefixBuilder) return false;
-
- var existing = exportScope.map[name];
- if (existing == declaration) return false;
-
- // Ambiguous declaration detected.
- if (existing != null) return false;
-
- exportScope.map[name] = declaration;
- return true;
- }
-
- void addUnit(LinkedUnitContext context, LinkedNode node) {
- units.add(UnitBuilder(context, node));
- }
-
- void buildInitialExportScope() {
- // TODO(scheglov) Maybe store export scopes in summaries?
- scope.forEach((name, declaration) {
- addToExportScope(name, declaration);
- });
- }
-}
-
-class UnitBuilder {
- final LinkedUnitContext context;
- final LinkedNode node;
-
- UnitBuilder(this.context, this.node);
-}
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index c676b9b..f029ec9 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -2,27 +2,170 @@
// 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/dart/ast/ast.dart' as ast;
+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';
-import 'package:analyzer/src/summary2/builder/library_builder.dart';
+import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/builder/prefix_builder.dart';
+import 'package:analyzer/src/summary2/declaration.dart';
import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_bundle_context.dart';
import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/metadata_resolver.dart';
import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/reference_resolver.dart';
+import 'package:analyzer/src/summary2/scope.dart';
+import 'package:analyzer/src/summary2/tokens_writer.dart';
+import 'package:analyzer/src/summary2/top_level_inference.dart';
-class SourceLibraryBuilder extends LibraryBuilder {
+class SourceLibraryBuilder {
final Linker linker;
- final LinkedBundleContext bundleContext;
+ final Uri uri;
final Reference reference;
+ final LinkedNodeLibraryBuilder node;
+ final List<UnitBuilder> units = [];
- SourceLibraryBuilder(this.linker, this.bundleContext, Uri uri, this.reference)
- : super(uri, reference);
+ /// The import scope of the library.
+ final Scope importScope;
+
+ /// Local declarations, enclosed by [importScope].
+ final Scope scope;
+
+ /// The export scope of the library.
+ final Scope exportScope = Scope.top();
+
+ SourceLibraryBuilder(Linker linker, Uri uri, Reference reference,
+ LinkedNodeLibraryBuilder node)
+ : this._(linker, uri, reference, node, Scope.top());
+
+ SourceLibraryBuilder._(
+ this.linker, this.uri, this.reference, this.node, this.importScope)
+ : scope = Scope(importScope, <String, Declaration>{});
+
+ void addImportsToScope() {
+ // TODO
+ var hasDartCore = false;
+ var unitContext = units[0].context;
+ for (var directive in units[0].node.compilationUnit_directives) {
+ if (directive.kind == LinkedNodeKind.importDirective) {
+ var relativeUriStr = unitContext.getStringContent(
+ directive.uriBasedDirective_uri,
+ );
+ var relativeUri = Uri.parse(relativeUriStr);
+ var uri = resolveRelativeUri(this.uri, relativeUri);
+ var builder = linker.builders[uri];
+ if (builder != null) {
+ builder.exportScope.forEach((name, declaration) {
+ importScope.declare(name, declaration);
+ });
+ } else {
+ var references = linker.elementFactory.exportsOfLibrary('$uri');
+ _importExportedReferences(references);
+ }
+ // TODO(scheglov) prefix
+ // TODO(scheglov) combinators
+ }
+ }
+ if (!hasDartCore) {
+ var importDartCore = LinkedNodeBuilder.importDirective(
+ uriBasedDirective_uri: LinkedNodeBuilder.simpleStringLiteral(
+ simpleStringLiteral_value: 'dart:core',
+ ),
+ )..isSynthetic = true;
+ units[0].node.compilationUnit_directives.add(importDartCore);
+
+ // TODO(scheglov) This works only when dart:core is linked
+ var references = linker.elementFactory.exportsOfLibrary('dart:core');
+ _importExportedReferences(references);
+ }
+ }
+
+ /// Add top-level declaration of the library units to the local scope.
+ void addLocalDeclarations() {
+ for (var unit in units) {
+ var unitRef = reference.getChild('@unit').getChild('${unit.uri}');
+ var classRef = unitRef.getChild('@class');
+ var enumRef = unitRef.getChild('@enum');
+ var functionRef = unitRef.getChild('@function');
+ var typeAliasRef = unitRef.getChild('@typeAlias');
+ var getterRef = unitRef.getChild('@getter');
+ var setterRef = unitRef.getChild('@setter');
+ var variableRef = unitRef.getChild('@variable');
+ for (var node in unit.node.compilationUnit_declarations) {
+ if (node.kind == LinkedNodeKind.classDeclaration ||
+ node.kind == LinkedNodeKind.classTypeAlias) {
+ var name = unit.context.getUnitMemberName(node);
+ var reference = classRef.getChild(name);
+ reference.node = node;
+ var declaration = Declaration(name, reference);
+ scope.declare(name, declaration);
+ } else if (node.kind == LinkedNodeKind.enumDeclaration) {
+ var name = unit.context.getUnitMemberName(node);
+ var reference = enumRef.getChild(name);
+ reference.node = node;
+ var declaration = Declaration(name, reference);
+ scope.declare(name, declaration);
+ } else if (node.kind == LinkedNodeKind.functionDeclaration) {
+ var name = unit.context.getUnitMemberName(node);
+
+ Reference containerRef;
+ if (unit.context.isGetterFunction(node)) {
+ containerRef = getterRef;
+ } else if (unit.context.isSetterFunction(node)) {
+ containerRef = setterRef;
+ } else {
+ containerRef = functionRef;
+ }
+
+ var reference = containerRef.getChild(name);
+ reference.node = node;
+
+ var declaration = Declaration(name, reference);
+ scope.declare(name, declaration);
+ } else if (node.kind == LinkedNodeKind.functionTypeAlias) {
+ var name = unit.context.getUnitMemberName(node);
+ var reference = typeAliasRef.getChild(name);
+ reference.node = node;
+
+ var declaration = Declaration(name, reference);
+ scope.declare(name, declaration);
+ } else if (node.kind == LinkedNodeKind.genericTypeAlias) {
+ var name = unit.context.getUnitMemberName(node);
+ var reference = typeAliasRef.getChild(name);
+ reference.node = node;
+
+ var declaration = Declaration(name, reference);
+ scope.declare(name, declaration);
+ } else if (node.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+ var variableList = node.topLevelVariableDeclaration_variableList;
+ for (var variable in variableList.variableDeclarationList_variables) {
+ var name = unit.context.getVariableName(variable);
+
+ var reference = variableRef.getChild(name);
+ reference.node = node;
+
+ var getter = getterRef.getChild(name);
+ scope.declare(name, Declaration(name, getter));
+
+ if (!unit.context.isFinal(variable)) {
+ var setter = setterRef.getChild(name);
+ scope.declare('$name=', Declaration(name, setter));
+ }
+ }
+ } else {
+ // TODO(scheglov) implement
+ throw UnimplementedError('${node.kind}');
+ }
+ }
+ }
+ }
void addSyntheticConstructors() {
for (var declaration in scope.map.values) {
var reference = declaration.reference;
var node = reference.node;
-
+ if (node == null) continue;
if (node.kind != LinkedNodeKind.classDeclaration) continue;
// Skip the class if it already has a constructor.
@@ -35,75 +178,154 @@
LinkedNodeBuilder.constructorDeclaration(
constructorDeclaration_parameters:
LinkedNodeBuilder.formalParameterList(),
+ constructorDeclaration_body: LinkedNodeBuilder.emptyFunctionBody(),
)..isSynthetic = true,
);
}
}
+ /// Return `true` if the export scope was modified.
+ bool addToExportScope(String name, Declaration declaration) {
+ if (name.startsWith('_')) return false;
+ if (declaration is PrefixBuilder) return false;
+
+ var existing = exportScope.map[name];
+ if (existing == declaration) return false;
+
+ // Ambiguous declaration detected.
+ if (existing != null) return false;
+
+ exportScope.map[name] = declaration;
+ return true;
+ }
+
+ void buildInitialExportScope() {
+ scope.forEach((name, declaration) {
+ addToExportScope(name, declaration);
+ });
+ }
+
+ void performTopLevelInference() {
+ for (var unit in units) {
+ TopLevelInference(linker, reference, unit).infer();
+ }
+ }
+
+ void resolveMetadata() {
+ var metadataResolver = MetadataResolver(linker, reference);
+ for (var unit in units) {
+ metadataResolver.resolve(unit);
+ }
+ }
+
void resolveTypes() {
for (var unit in units) {
- for (var node in unit.node.compilationUnit_declarations) {
- if (node.kind == LinkedNodeKind.classDeclaration) {
- var extendsClause = node.classDeclaration_extendsClause;
- if (extendsClause != null) {
- _resolveTypeName(
- unit.context,
- extendsClause.extendsClause_superclass,
- );
- }
+ var unitReference = reference.getChild('@unit').getChild('${unit.uri}');
+ ReferenceResolver(
+ linker.linkingBundleContext,
+ unit,
+ scope,
+ unitReference,
+ ).resolve();
+ }
+ }
- var withClause = node.classDeclaration_withClause;
- if (withClause != null) {
- for (var typeName in withClause.withClause_mixinTypes) {
- _resolveTypeName(unit.context, typeName);
+ void storeExportScope() {
+ var linkingBundleContext = linker.linkingBundleContext;
+ for (var declaration in exportScope.map.values) {
+ var reference = declaration.reference;
+ var index = linkingBundleContext.indexOfReference(reference);
+ node.exports.add(index);
+ }
+ }
+
+ void _importExportedReferences(List<Reference> exportedReferences) {
+ for (var reference in exportedReferences) {
+ var name = reference.name;
+ importScope.declare(name, Declaration(name, reference));
+ }
+ }
+
+ static void build(Linker linker, Source librarySource,
+ Map<Source, ast.CompilationUnit> libraryUnits) {
+ var libraryUriStr = librarySource.uri.toString();
+ var libraryReference = linker.rootReference.getChild(libraryUriStr);
+
+ var unitNodeList = <LinkedNodeUnitBuilder>[];
+ var libraryNode = LinkedNodeLibraryBuilder(
+ units: unitNodeList,
+ uriStr: libraryUriStr,
+ );
+
+ var builder = SourceLibraryBuilder(
+ linker,
+ librarySource.uri,
+ libraryReference,
+ libraryNode,
+ );
+
+ ast.CompilationUnit definingUnit;
+ for (var unitSource in libraryUnits.keys) {
+ var unit = libraryUnits[unitSource];
+ definingUnit ??= unit;
+
+ var tokensResult = TokensWriter().writeTokens(
+ unit.beginToken,
+ unit.endToken,
+ );
+ var tokensContext = tokensResult.toContext();
+
+ var unitContext = LinkedUnitContext(
+ linker.bundleContext,
+ tokensContext,
+ );
+
+ var writer = AstBinaryWriter(linker.linkingBundleContext, tokensContext);
+ var unitNode = writer.writeNode(unit);
+
+ builder.units.add(
+ UnitBuilder(unitSource.uri, unitContext, unitNode),
+ );
+
+ libraryNode.units.add(
+ LinkedNodeUnitBuilder(
+ uriStr: '${unitSource.uri}',
+ tokens: tokensResult.tokens,
+ node: unitNode,
+ ),
+ );
+
+ if (libraryUriStr == 'dart:core') {
+ for (var declaration in unitNode.compilationUnit_declarations) {
+ if (declaration.kind == LinkedNodeKind.classDeclaration) {
+ var nameNode = declaration.namedCompilationUnitMember_name;
+ if (unitContext.getSimpleName(nameNode) == 'Object') {
+ declaration.classDeclaration_isDartObject = true;
}
}
-
- var implementsClause = node.classOrMixinDeclaration_implementsClause;
- if (implementsClause != null) {
- for (var typeName in implementsClause.implementsClause_interfaces) {
- _resolveTypeName(unit.context, typeName);
- }
- }
-
- // TODO(scheglov) type parameters
- assert(node.classOrMixinDeclaration_typeParameters == null);
- } else {
- // TODO(scheglov) implement
- throw UnimplementedError();
}
}
}
- }
- int _referenceIndex(Reference reference) {
- if (reference.index == null) {
- reference.index = linker.references.length;
- linker.references.add(reference);
- }
- return reference.index;
- }
-
- void _resolveTypeName(LinkedUnitContext context, LinkedNodeBuilder typeName) {
- var identifier = typeName.typeName_name;
- if (identifier.kind == LinkedNodeKind.simpleIdentifier) {
- var name = context.getSimpleName(identifier);
- var reference = exportScope.lookup(name).reference;
- var referenceIndex = _referenceIndex(reference);
- identifier.simpleIdentifier_element = referenceIndex;
- if (reference.isClass) {
- typeName.typeName_type = LinkedNodeTypeBuilder(
- kind: LinkedNodeTypeKind.interface,
- interfaceClass: referenceIndex,
- );
- // TODO(scheglov) type arguments
- } else {
- // TODO(scheglov) set Object? keep unresolved?
- throw UnimplementedError();
+ for (var directive in definingUnit.directives) {
+ if (directive is ast.LibraryDirective) {
+ var name = directive.name;
+ libraryNode.name = name.components.map((id) => id.name).join('.');
+ libraryNode.nameOffset = name.offset;
+ libraryNode.nameLength = name.length;
+ break;
}
- } else {
- // TODO(scheglov) implement
- throw UnimplementedError();
}
+
+ linker.linkingLibraries.add(libraryNode);
+ linker.builders[builder.uri] = builder;
}
}
+
+class UnitBuilder {
+ final Uri uri;
+ final LinkedUnitContext context;
+ final LinkedNode node;
+
+ UnitBuilder(this.uri, this.context, this.node);
+}
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index e24fc84..aec825a 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -2,140 +2,193 @@
// 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/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/ast_binary_writer.dart';
-import 'package:analyzer/src/summary2/builder/library_builder.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
import 'package:analyzer/src/summary2/linked_bundle_context.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
import 'package:analyzer/src/summary2/reference.dart';
LinkResult link(
- Reference rootReference,
+ AnalysisOptions analysisOptions,
+ SourceFactory sourceFactory,
+ List<LinkedNodeBundle> inputs,
Map<Source, Map<Source, CompilationUnit>> unitMap,
) {
- var linker = Linker(rootReference);
- linker.link(unitMap);
- return LinkResult(linker.references, linker.libraryResults);
-}
-
-class LibraryLinkResult {
- final Source source;
- final Map<Source, UnitLinkResult> units;
-
- LibraryLinkResult(this.source, this.units);
+ var linker = Linker(analysisOptions, sourceFactory);
+ linker.link(inputs, unitMap);
+ return LinkResult(linker.linkingBundle);
}
class Linker {
- final Reference rootReference;
+ final Reference rootReference = Reference.root();
+ LinkedElementFactory elementFactory;
- /// References used in all libraries being linked.
- /// Element references in [LinkedNode]s are indexes in this list.
- final List<Reference> references = [null];
+ LinkingBundleContext linkingBundleContext;
+ List<LinkedNodeLibraryBuilder> linkingLibraries = [];
+ LinkedNodeBundleBuilder linkingBundle;
+ LinkedBundleContext bundleContext;
- /// The output results.
- var libraryResults = <Source, LibraryLinkResult>{};
+ /// Libraries that are being linked.
+ final Map<Uri, SourceLibraryBuilder> builders = {};
- /// Libraries that are being linked, or are already linked.
- final Map<Uri, LibraryBuilder> builders = {};
+ _AnalysisContextForLinking analysisContext;
+ TypeProvider typeProvider;
+ Dart2TypeSystem typeSystem;
+ InheritanceManager2 inheritance;
- Linker(this.rootReference);
+ Linker(AnalysisOptions analysisOptions, SourceFactory sourceFactory) {
+ var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
+ dynamicRef.element = DynamicElementImpl.instance;
- void addBuilder(LibraryBuilder builder) {
- builders[builder.uri] = builder;
+ linkingBundleContext = LinkingBundleContext(dynamicRef);
+
+ analysisContext = _AnalysisContextForLinking(
+ analysisOptions,
+ sourceFactory,
+ );
+
+ elementFactory = LinkedElementFactory(
+ analysisContext,
+ _AnalysisSessionForLinking(),
+ rootReference,
+ );
+
+ linkingBundle = LinkedNodeBundleBuilder(
+ references: linkingBundleContext.referencesBuilder,
+ libraries: linkingLibraries,
+ );
+
+ bundleContext = LinkedBundleContext(
+ elementFactory,
+ linkingBundle.references,
+ );
}
- void addSyntheticConstructors() {
+ void link(List<LinkedNodeBundle> inputs,
+ Map<Source, Map<Source, CompilationUnit>> unitMap) {
+ for (var input in inputs) {
+ elementFactory.addBundle(input);
+ }
+
+ for (var librarySource in unitMap.keys) {
+ SourceLibraryBuilder.build(this, librarySource, unitMap[librarySource]);
+ }
+
+ // Add libraries being linked, so we can ask for their elements as well.
+ elementFactory.addBundle(linkingBundle, context: bundleContext);
+
+ _buildOutlines();
+ }
+
+ void _addSyntheticConstructors() {
for (var library in builders.values) {
- if (library is SourceLibraryBuilder) {
- library.addSyntheticConstructors();
- }
+ library.addSyntheticConstructors();
}
}
- void buildOutlines() {
- computeLibraryScopes();
- resolveTypes();
- addSyntheticConstructors();
+ void _buildOutlines() {
+ _computeLibraryScopes();
+ _addSyntheticConstructors();
+ _createTypeSystem();
+ _resolveTypes();
+ _performTopLevelInference();
+ _resolveMetadata();
}
- void computeLibraryScopes() {
- for (var uri in builders.keys) {
- var library = builders[uri];
+ void _computeLibraryScopes() {
+ for (var library in builders.values) {
+ library.addLocalDeclarations();
+ }
+
+ for (var library in builders.values) {
library.buildInitialExportScope();
}
+ for (var library in builders.values) {
+ library.addImportsToScope();
+ }
+
+ for (var library in builders.values) {
+ library.storeExportScope();
+ }
+
// TODO(scheglov) process imports and exports
}
- void link(Map<Source, Map<Source, CompilationUnit>> unitMap) {
- var linkedBundleContext = LinkedBundleContext(references);
- for (var librarySource in unitMap.keys) {
- var libraryUriStr = librarySource.uri.toString();
- var libraryReference = rootReference.getChild(libraryUriStr);
+ void _createTypeSystem() {
+ var coreRef = rootReference.getChild('dart:core');
+ var coreLib = elementFactory.elementOfReference(coreRef);
+ typeProvider = SummaryTypeProvider()..initializeCore(coreLib);
+ analysisContext.typeProvider = typeProvider;
- var unitResults = <Source, UnitLinkResult>{};
- libraryResults[librarySource] = LibraryLinkResult(
- librarySource,
- unitResults,
- );
+ typeSystem = Dart2TypeSystem(typeProvider);
+ analysisContext.typeSystem = typeSystem;
- var libraryBuilder = SourceLibraryBuilder(
- this,
- linkedBundleContext,
- librarySource.uri,
- libraryReference,
- );
- addBuilder(libraryBuilder);
-
- var libraryUnits = unitMap[librarySource];
- for (var unitSource in libraryUnits.keys) {
- var unit = libraryUnits[unitSource];
-
- var writer = AstBinaryWriter();
- var unitData = writer.writeNode(unit);
-
- var unitLinkResult = UnitLinkResult(writer.tokens, unitData);
- unitResults[unitSource] = unitLinkResult;
-
- var linkedUnitContext = LinkedUnitContext(
- linkedBundleContext,
- writer.tokens,
- );
- libraryBuilder.addUnit(linkedUnitContext, unitData);
- }
-
- libraryBuilder.addLocalDeclarations();
- }
-
- buildOutlines();
+ inheritance = InheritanceManager2(typeSystem);
}
- void resolveTypes() {
- for (var uri in builders.keys) {
- var library = builders[uri];
- if (library is SourceLibraryBuilder) {
- library.resolveTypes();
- }
+ void _performTopLevelInference() {
+ for (var library in builders.values) {
+ library.performTopLevelInference();
+ }
+ }
+
+ void _resolveMetadata() {
+ for (var library in builders.values) {
+ library.resolveMetadata();
+ }
+ }
+
+ void _resolveTypes() {
+ for (var library in builders.values) {
+ library.resolveTypes();
}
}
}
class LinkResult {
- /// Element references in [LinkedNode]s are indexes in this list.
- final List<Reference> references;
+ final LinkedNodeBundleBuilder bundle;
- final Map<Source, LibraryLinkResult> libraries;
-
- LinkResult(this.references, this.libraries);
+ LinkResult(this.bundle);
}
-class UnitLinkResult {
- final UnlinkedTokensBuilder tokens;
- final LinkedNodeBuilder node;
+class _AnalysisContextForLinking implements InternalAnalysisContext {
+ @override
+ final AnalysisOptions analysisOptions;
- UnitLinkResult(this.tokens, this.node);
+ @override
+ final SourceFactory sourceFactory;
+
+ @override
+ TypeProvider typeProvider;
+
+ @override
+ TypeSystem typeSystem;
+
+ _AnalysisContextForLinking(this.analysisOptions, this.sourceFactory);
+
+ @override
+ Namespace getPublicNamespace(LibraryElement library) {
+ // TODO(scheglov) Not sure if this method of AnalysisContext is useful.
+ var builder = new NamespaceBuilder();
+ return builder.createPublicNamespaceForLibrary(library);
+ }
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class _AnalysisSessionForLinking implements AnalysisSession {
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
index 2b1d0ed..fbaf454 100644
--- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
@@ -2,24 +2,107 @@
// 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/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/type.dart';
import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/reference.dart';
/// The context of a linked bundle, with shared references.
class LinkedBundleContext {
- final List<Reference> references;
+ final LinkedElementFactory elementFactory;
+ final LinkedNodeReferences referencesData;
+ final List<Reference> _references;
- LinkedBundleContext(this.references);
+ LinkedBundleContext(this.elementFactory, this.referencesData)
+ : _references = List<Reference>.filled(referencesData.name.length, null,
+ growable: true);
+
+ T elementOfIndex<T extends Element>(int index) {
+ var reference = referenceOfIndex(index);
+ return elementFactory.elementOfReference(reference);
+ }
+
+ List<T> elementsOfIndexes<T extends Element>(List<int> indexList) {
+ var result = List<T>(indexList.length);
+ for (var i = 0; i < indexList.length; ++i) {
+ var index = indexList[i];
+ result[i] = elementOfIndex(index);
+ }
+ return result;
+ }
InterfaceType getInterfaceType(LinkedNodeType linkedType) {
- if (linkedType.kind == LinkedNodeTypeKind.interface) {
- var element = references[linkedType.interfaceClass].element;
- // TODO(scheglov) type arguments
- assert(linkedType.interfaceTypeArguments.isEmpty);
- return InterfaceTypeImpl.explicit(element, []);
+ var type = getType(linkedType);
+ if (type is InterfaceType && !type.element.isEnum) {
+ return type;
}
return null;
}
+
+ DartType getType(LinkedNodeType linkedType) {
+ var kind = linkedType.kind;
+ if (kind == LinkedNodeTypeKind.dynamic_) {
+ return DynamicTypeImpl.instance;
+ } else if (kind == LinkedNodeTypeKind.function) {
+ var returnType = getType(linkedType.functionReturnType);
+ var typeParameters = linkedType.functionTypeParameters
+ .map(referenceOfIndex)
+ .map(elementFactory.elementOfReference)
+ .cast<TypeParameterElement>()
+ .toList();
+ var formalParameters = linkedType.functionFormalParameters
+ .map(referenceOfIndex)
+ .map(elementFactory.elementOfReference)
+ .cast<ParameterElement>()
+ .toList();
+ // TODO(scheglov) Rework this to purely synthetic types.
+ return FunctionElementImpl.synthetic(formalParameters, returnType).type;
+ } else if (kind == LinkedNodeTypeKind.interface) {
+ var reference = referenceOfIndex(linkedType.interfaceClass);
+ Element element = elementFactory.elementOfReference(reference);
+ return InterfaceTypeImpl.explicit(
+ element,
+ linkedType.interfaceTypeArguments.map(getType).toList(),
+ );
+ } else if (kind == LinkedNodeTypeKind.typeParameter) {
+ var reference = referenceOfIndex(linkedType.typeParameterParameter);
+ Element element = elementFactory.elementOfReference(reference);
+ return TypeParameterTypeImpl(element);
+ } else if (kind == LinkedNodeTypeKind.void_) {
+ return VoidTypeImpl.instance;
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ }
+
+ Reference referenceOfIndex(int index) {
+ // When we are linking a bundle, we add new references.
+ // So, grow the list of references when we have data for them.
+ if (index >= _references.length) {
+ if (referencesData.name.length > _references.length) {
+ _references.length = referencesData.name.length;
+ }
+ }
+
+ var reference = _references[index];
+ if (reference != null) return reference;
+
+ if (index == 0) {
+ reference = elementFactory.rootReference;
+ _references[index] = reference;
+ return reference;
+ }
+
+ var parentIndex = referencesData.parent[index];
+ var parent = referenceOfIndex(parentIndex);
+
+ var name = referencesData.name[index];
+ reference = parent.getChild(name);
+ _references[index] = reference;
+
+ return reference;
+ }
}
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
new file mode 100644
index 0000000..7653ed6
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -0,0 +1,299 @@
+// Copyright (c) 2019, 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/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
+
+class LinkedElementFactory {
+ final AnalysisContext analysisContext;
+ final AnalysisSession analysisSession;
+ final Reference rootReference;
+ final Map<String, _Library> libraryMap = {};
+
+ LinkedElementFactory(
+ this.analysisContext, this.analysisSession, this.rootReference);
+
+ void addBundle(LinkedNodeBundle bundle, {LinkedBundleContext context}) {
+ context ??= LinkedBundleContext(this, bundle.references);
+ for (var library in bundle.libraries) {
+ libraryMap[library.uriStr] = _Library(context, library);
+ }
+ }
+
+ Element elementOfReference(Reference reference) {
+ if (reference.element != null) {
+ return reference.element;
+ }
+ if (reference.parent == null) {
+ return null;
+ }
+
+ return _ElementRequest(this, reference).elementOfReference(reference);
+ }
+
+ List<Reference> exportsOfLibrary(String uriStr) {
+ var library = libraryMap[uriStr];
+ var exportIndexList = library.node.exports;
+ var exportReferences = List<Reference>(exportIndexList.length);
+ for (var i = 0; i < exportIndexList.length; ++i) {
+ var index = exportIndexList[i];
+ var reference = library.context.referenceOfIndex(index);
+ exportReferences[i] = reference;
+ }
+ return exportReferences;
+ }
+
+ LibraryElementImpl libraryOfUri(String uriStr) {
+ var reference = rootReference.getChild(uriStr);
+ return elementOfReference(reference);
+ }
+}
+
+class _ElementRequest {
+ final LinkedElementFactory elementFactory;
+ final Reference input;
+
+ _ElementRequest(this.elementFactory, this.input);
+
+ ElementImpl elementOfReference(Reference reference) {
+ if (reference.element != null) {
+ return reference.element;
+ }
+
+ var parent2 = reference.parent.parent;
+ if (parent2 == null) {
+ return _createLibraryElement(reference);
+ }
+
+ var parentName = reference.parent.name;
+
+ if (parentName == '@class') {
+ var unit = elementOfReference(parent2);
+ return _class(unit, reference);
+ }
+
+ if (parentName == '@constructor') {
+ var class_ = elementOfReference(parent2);
+ return _constructor(class_, reference);
+ }
+
+ if (parentName == '@function') {
+ CompilationUnitElementImpl enclosing = elementOfReference(parent2);
+ return _function(enclosing, reference);
+ }
+
+ if (parentName == '@getter') {
+ var enclosing = elementOfReference(parent2);
+ return _getter(enclosing, reference);
+ }
+
+ if (parentName == '@method') {
+ var enclosing = elementOfReference(parent2);
+ return _method(enclosing, reference);
+ }
+
+ if (parentName == '@parameter') {
+ ExecutableElementImpl enclosing = elementOfReference(parent2);
+ return _parameter(enclosing, reference);
+ }
+
+ if (parentName == '@typeAlias') {
+ var unit = elementOfReference(parent2);
+ return _typeAlias(unit, reference);
+ }
+
+ if (parentName == '@typeParameter') {
+ var enclosing = elementOfReference(parent2) as TypeParameterizedElement;
+ return _typeParameter(enclosing, reference);
+ }
+
+ if (parentName == '@unit') {
+ elementOfReference(parent2);
+ // Creating a library fills all its units.
+ assert(reference.element != null);
+ return reference.element;
+ }
+
+ // TODO(scheglov) support other elements
+ throw StateError('Not found: $input');
+ }
+
+ ClassElementImpl _class(
+ CompilationUnitElementImpl unit, Reference reference) {
+ if (reference.node == null) {
+ _indexUnitDeclarations(unit);
+ assert(reference.node != 0, '$reference');
+ }
+ return reference.element = ClassElementImpl.forLinkedNode(
+ unit,
+ reference,
+ reference.node,
+ );
+ }
+
+ ConstructorElementImpl _constructor(
+ ClassElementImpl class_, Reference reference) {
+ return reference.element = ConstructorElementImpl.forLinkedNode(
+ reference,
+ reference.node,
+ class_,
+ );
+ }
+
+ LibraryElementImpl _createLibraryElement(Reference reference) {
+ var uriStr = reference.name;
+
+ var sourceFactory = elementFactory.analysisContext.sourceFactory;
+ var librarySource = sourceFactory.forUri(uriStr);
+
+ var libraryData = elementFactory.libraryMap[uriStr];
+ var node = libraryData.node;
+ var hasName = node.name.isNotEmpty;
+
+ var definingUnitData = node.units[0];
+ var definingUnitContext = LinkedUnitContext(
+ libraryData.context,
+ TokensContext(definingUnitData.tokens),
+ );
+
+ var libraryElement = LibraryElementImpl.forLinkedNode(
+ elementFactory.analysisContext,
+ elementFactory.analysisSession,
+ node.name,
+ hasName ? node.nameOffset : -1,
+ node.name.length,
+ definingUnitContext,
+ reference,
+ definingUnitData.node,
+ );
+
+ var units = <CompilationUnitElementImpl>[];
+ var unitContainerRef = reference.getChild('@unit');
+ for (var unitData in node.units) {
+ var unitSource = sourceFactory.forUri(unitData.uriStr);
+ var tokensContext = TokensContext(unitData.tokens);
+ var unitElement = CompilationUnitElementImpl.forLinkedNode(
+ libraryElement,
+ LinkedUnitContext(libraryData.context, tokensContext),
+ unitContainerRef.getChild(unitData.uriStr),
+ unitData.node,
+ );
+ unitElement.source = unitSource;
+ unitElement.librarySource = librarySource;
+ units.add(unitElement);
+ unitContainerRef.getChild(unitData.uriStr).element = unitElement;
+ }
+
+ libraryElement.definingCompilationUnit = units[0];
+ libraryElement.parts = units.skip(1).toList();
+ return reference.element = libraryElement;
+ }
+
+ Element _function(CompilationUnitElementImpl enclosing, Reference reference) {
+ enclosing.functions;
+ assert(reference.element != null);
+ return reference.element;
+ }
+
+ PropertyAccessorElementImpl _getter(
+ ElementImpl enclosing, Reference reference) {
+ if (enclosing is ClassElementImpl) {
+ enclosing.accessors;
+ // Requesting accessors sets elements for accessors and fields.
+ assert(reference.element != null);
+ return reference.element;
+ }
+ if (enclosing is CompilationUnitElementImpl) {
+ enclosing.accessors;
+ // Requesting accessors sets elements for accessors and variables.
+ assert(reference.element != null);
+ return reference.element;
+ }
+ // Only classes and units have accessors.
+ throw StateError('${enclosing.runtimeType}');
+ }
+
+ void _indexUnitDeclarations(CompilationUnitElementImpl unit) {
+ var context = unit.linkedContext;
+ var unitRef = unit.reference;
+ var classRef = unitRef.getChild('@class');
+ var enumRef = unitRef.getChild('@class');
+ var functionRef = unitRef.getChild('@function');
+ var typeAliasRef = unitRef.getChild('@typeAlias');
+ var variableRef = unitRef.getChild('@variable');
+ for (var declaration in unit.linkedNode.compilationUnit_declarations) {
+ var kind = declaration.kind;
+ if (kind == LinkedNodeKind.classDeclaration ||
+ kind == LinkedNodeKind.classTypeAlias) {
+ var name = context.getUnitMemberName(declaration);
+ classRef.getChild(name).node = declaration;
+ } else if (kind == LinkedNodeKind.enumDeclaration) {
+ var name = context.getUnitMemberName(declaration);
+ enumRef.getChild(name).node = declaration;
+ } else if (kind == LinkedNodeKind.functionDeclaration) {
+ var name = context.getUnitMemberName(declaration);
+ functionRef.getChild(name).node = declaration;
+ } else if (kind == LinkedNodeKind.functionTypeAlias) {
+ var name = context.getUnitMemberName(declaration);
+ typeAliasRef.getChild(name).node = declaration;
+ } else if (kind == LinkedNodeKind.topLevelVariableDeclaration) {
+ var variables = declaration.topLevelVariableDeclaration_variableList;
+ for (var variable in variables.variableDeclarationList_variables) {
+ var name = context.getSimpleName(variable.variableDeclaration_name);
+ variableRef.getChild(name).node = variable;
+ }
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ }
+ }
+
+ MethodElementImpl _method(ClassElementImpl enclosing, Reference reference) {
+ enclosing.methods;
+ // Requesting methods sets elements for all of them.
+ assert(reference.element != null);
+ return reference.element;
+ }
+
+ Element _parameter(ExecutableElementImpl enclosing, Reference reference) {
+ enclosing.parameters;
+ assert(reference.element != null);
+ return reference.element;
+ }
+
+ GenericTypeAliasElementImpl _typeAlias(
+ CompilationUnitElementImpl unit, Reference reference) {
+ if (reference.node == null) {
+ _indexUnitDeclarations(unit);
+ assert(reference.node != 0, '$reference');
+ }
+ return reference.element = GenericTypeAliasElementImpl.forLinkedNode(
+ unit,
+ reference,
+ reference.node,
+ );
+ }
+
+ Element _typeParameter(
+ TypeParameterizedElement enclosing, Reference reference) {
+ enclosing.typeParameters;
+ // Requesting type parameters sets elements for all their references.
+ assert(reference.element != null);
+ return reference.element;
+ }
+}
+
+class _Library {
+ final LinkedBundleContext context;
+ final LinkedNodeLibrary node;
+
+ _Library(this.context, this.node);
+}
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index f7869e1..b1bb1f4 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -2,16 +2,37 @@
// 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/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_reader.dart';
import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
/// The context of a unit - the context of the bundle, and the unit tokens.
class LinkedUnitContext {
final LinkedBundleContext bundleContext;
- final UnlinkedTokens tokens;
+ final TokensContext tokensContext;
- LinkedUnitContext(this.bundleContext, this.tokens);
+ LinkedUnitContext(this.bundleContext, this.tokensContext);
+
+ Iterable<LinkedNode> classFields(LinkedNode class_) sync* {
+ for (var declaration in class_.classOrMixinDeclaration_members) {
+ if (declaration.kind == LinkedNodeKind.fieldDeclaration) {
+ var variableList = declaration.fieldDeclaration_fields;
+ for (var field in variableList.variableDeclarationList_variables) {
+ yield field;
+ }
+ }
+ }
+ }
+
+ String getCommentText(LinkedNode comment) {
+ if (comment == null) return null;
+
+ return comment.comment_tokens.map(getTokenLexeme).join('\n');
+ }
String getConstructorDeclarationName(LinkedNode node) {
var name = node.constructorDeclaration_name;
@@ -21,15 +42,343 @@
return '';
}
+ String getFormalParameterName(LinkedNode node) {
+ return getSimpleName(node.normalFormalParameter_identifier);
+ }
+
+ List<LinkedNode> getFormalParameters(LinkedNode node) {
+ LinkedNode parameterList;
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.constructorDeclaration) {
+ parameterList = node.constructorDeclaration_parameters;
+ } else if (kind == LinkedNodeKind.functionDeclaration) {
+ parameterList = node.functionDeclaration_functionExpression
+ .functionExpression_formalParameters;
+ } else if (kind == LinkedNodeKind.functionTypeAlias) {
+ parameterList = node.functionTypeAlias_formalParameters;
+ } else if (kind == LinkedNodeKind.methodDeclaration) {
+ parameterList = node.methodDeclaration_formalParameters;
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ return parameterList?.formalParameterList_parameters;
+ }
+
+ LinkedNode getImplementsClause(LinkedNode node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.classDeclaration) {
+ return node.classOrMixinDeclaration_implementsClause;
+ } else if (kind == LinkedNodeKind.classTypeAlias) {
+ return node.classTypeAlias_implementsClause;
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ }
+
InterfaceType getInterfaceType(LinkedNodeType linkedType) {
return bundleContext.getInterfaceType(linkedType);
}
+ List<LinkedNode> getMetadataOrEmpty(LinkedNode node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.classDeclaration ||
+ kind == LinkedNodeKind.classTypeAlias ||
+ kind == LinkedNodeKind.constructorDeclaration ||
+ kind == LinkedNodeKind.enumConstantDeclaration ||
+ kind == LinkedNodeKind.enumDeclaration ||
+ kind == LinkedNodeKind.functionDeclaration ||
+ kind == LinkedNodeKind.functionTypeAlias ||
+ kind == LinkedNodeKind.methodDeclaration ||
+ kind == LinkedNodeKind.mixinDeclaration ||
+ kind == LinkedNodeKind.variableDeclaration) {
+ return node.annotatedNode_metadata;
+ }
+ if (kind == LinkedNodeKind.fieldFormalParameter ||
+ kind == LinkedNodeKind.functionTypedFormalParameter ||
+ kind == LinkedNodeKind.simpleFormalParameter) {
+ return node.normalFormalParameter_metadata;
+ }
+ return const <LinkedNode>[];
+ }
+
+ String getMethodName(LinkedNode node) {
+ return getSimpleName(node.methodDeclaration_name);
+ }
+
+ DartType getReturnType(LinkedNode node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.functionDeclaration) {
+ return getType(node.functionDeclaration_returnType2);
+ } else if (kind == LinkedNodeKind.methodDeclaration) {
+ return getType(node.methodDeclaration_returnType2);
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ }
+
String getSimpleName(LinkedNode node) {
- return tokens.lexeme[node.simpleIdentifier_token];
+ return getTokenLexeme(node.simpleIdentifier_token);
+ }
+
+ int getSimpleOffset(LinkedNode node) {
+ return tokensContext.offset(node.simpleIdentifier_token);
+ }
+
+ String getStringContent(LinkedNode node) {
+ return node.simpleStringLiteral_value;
+ }
+
+ String getTokenLexeme(int token) {
+ return tokensContext.lexeme(token);
+ }
+
+ DartType getType(LinkedNodeType linkedType) {
+ return bundleContext.getType(linkedType);
+ }
+
+ DartType getTypeAnnotationType(LinkedNode node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.typeName) {
+ return getType(node.typeName_type);
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ }
+
+ List<LinkedNode> getTypeParameters(LinkedNode node) {
+ LinkedNode typeParameterList;
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.classTypeAlias) {
+ typeParameterList = node.classTypeAlias_typeParameters;
+ } else if (kind == LinkedNodeKind.classDeclaration ||
+ kind == LinkedNodeKind.mixinDeclaration) {
+ typeParameterList = node.classOrMixinDeclaration_typeParameters;
+ } else if (kind == LinkedNodeKind.constructorDeclaration) {
+ return const [];
+ } else if (kind == LinkedNodeKind.functionDeclaration) {
+ return getTypeParameters(node.functionDeclaration_functionExpression);
+ } else if (kind == LinkedNodeKind.functionExpression) {
+ typeParameterList = node.functionExpression_typeParameters;
+ } else if (kind == LinkedNodeKind.functionTypeAlias) {
+ typeParameterList = node.functionTypeAlias_typeParameters;
+ } else if (kind == LinkedNodeKind.methodDeclaration) {
+ typeParameterList = node.methodDeclaration_typeParameters;
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ return typeParameterList?.typeParameterList_typeParameters;
}
String getUnitMemberName(LinkedNode node) {
return getSimpleName(node.namedCompilationUnitMember_name);
}
+
+ String getVariableName(LinkedNode node) {
+ return getSimpleName(node.variableDeclaration_name);
+ }
+
+ bool isAbstract(LinkedNode node) {
+ return node.kind == LinkedNodeKind.methodDeclaration &&
+ node.methodDeclaration_body.kind == LinkedNodeKind.emptyFunctionBody;
+ }
+
+ bool isAsynchronous(LinkedNode node) {
+ LinkedNode body = _getFunctionBody(node);
+ if (body.kind == LinkedNodeKind.blockFunctionBody) {
+ return body.blockFunctionBody_keyword != 0;
+ } else if (body.kind == LinkedNodeKind.emptyFunctionBody) {
+ return false;
+ } else {
+ return body.expressionFunctionBody_keyword != 0;
+ }
+ }
+
+ bool isConst(LinkedNode node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.variableDeclaration) {
+ return node.variableDeclaration_declaration.isConst;
+ }
+ throw UnimplementedError('$kind');
+ }
+
+ bool isConstKeyword(int token) {
+ return tokensContext.type(token) == UnlinkedTokenType.CONST;
+ }
+
+ bool isConstVariableList(LinkedNode node) {
+ return isConstKeyword(node.variableDeclarationList_keyword);
+ }
+
+ bool isExternal(LinkedNode node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.constructorDeclaration) {
+ return node.constructorDeclaration_externalKeyword != 0;
+ } else if (kind == LinkedNodeKind.functionDeclaration) {
+ return node.functionDeclaration_externalKeyword != 0;
+ } else if (kind == LinkedNodeKind.methodDeclaration) {
+ return node.methodDeclaration_externalKeyword != 0;
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ }
+
+ bool isFinal(LinkedNode node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.enumConstantDeclaration) {
+ return false;
+ }
+ if (kind == LinkedNodeKind.variableDeclaration) {
+ return node.variableDeclaration_declaration.isFinal;
+ }
+ throw UnimplementedError('$kind');
+ }
+
+ bool isFinalKeyword(int token) {
+ return tokensContext.type(token) == UnlinkedTokenType.FINAL;
+ }
+
+ bool isFinalVariableList(LinkedNode node) {
+ return isFinalKeyword(node.variableDeclarationList_keyword);
+ }
+
+ bool isFunction(LinkedNode node) {
+ return node.kind == LinkedNodeKind.functionDeclaration;
+ }
+
+ bool isGenerator(LinkedNode node) {
+ LinkedNode body = _getFunctionBody(node);
+ if (body.kind == LinkedNodeKind.blockFunctionBody) {
+ return body.blockFunctionBody_star != 0;
+ }
+ return false;
+ }
+
+ bool isGetter(LinkedNode node) {
+ return isGetterMethod(node) || isGetterFunction(node);
+ }
+
+ bool isGetterFunction(LinkedNode node) {
+ return isFunction(node) &&
+ _isGetToken(node.functionDeclaration_propertyKeyword);
+ }
+
+ bool isGetterMethod(LinkedNode node) {
+ return isMethod(node) &&
+ _isGetToken(node.methodDeclaration_propertyKeyword);
+ }
+
+ bool isLibraryKeyword(int token) {
+ return tokensContext.type(token) == UnlinkedTokenType.LIBRARY;
+ }
+
+ bool isMethod(LinkedNode node) {
+ return node.kind == LinkedNodeKind.methodDeclaration;
+ }
+
+ bool isSetter(LinkedNode node) {
+ return isSetterMethod(node) || isSetterFunction(node);
+ }
+
+ bool isSetterFunction(LinkedNode node) {
+ return isFunction(node) &&
+ _isSetToken(node.functionDeclaration_propertyKeyword);
+ }
+
+ bool isSetterMethod(LinkedNode node) {
+ return isMethod(node) &&
+ _isSetToken(node.methodDeclaration_propertyKeyword);
+ }
+
+ bool isStatic(LinkedNode node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.functionDeclaration) {
+ return true;
+ } else if (kind == LinkedNodeKind.methodDeclaration) {
+ return node.methodDeclaration_modifierKeyword != 0;
+ } else if (kind == LinkedNodeKind.variableDeclaration) {
+ return node.variableDeclaration_declaration.isStatic;
+ }
+ throw UnimplementedError('$kind');
+ }
+
+ void loadClassMemberReferences(Reference reference) {
+ var node = reference.node;
+ if (node.kind != LinkedNodeKind.classDeclaration &&
+ node.kind != LinkedNodeKind.mixinDeclaration) {
+ return;
+ }
+
+ var constructorContainerRef = reference.getChild('@constructor');
+ var fieldContainerRef = reference.getChild('@field');
+ var methodContainerRef = reference.getChild('@method');
+ var getterContainerRef = reference.getChild('@getter');
+ var setterContainerRef = reference.getChild('@setter');
+ for (var member in node.classOrMixinDeclaration_members) {
+ if (member.kind == LinkedNodeKind.constructorDeclaration) {
+ var name = getConstructorDeclarationName(member);
+ constructorContainerRef.getChild(name).node = member;
+ } else if (member.kind == LinkedNodeKind.fieldDeclaration) {
+ var variableList = member.fieldDeclaration_fields;
+ for (var field in variableList.variableDeclarationList_variables) {
+ var name = getSimpleName(field.variableDeclaration_name);
+ fieldContainerRef.getChild(name).node = field;
+ }
+ } else if (member.kind == LinkedNodeKind.methodDeclaration) {
+ var name = getSimpleName(member.methodDeclaration_name);
+ var propertyKeyword = member.methodDeclaration_propertyKeyword;
+ if (_isGetToken(propertyKeyword)) {
+ getterContainerRef.getChild(name).node = member;
+ } else if (_isSetToken(propertyKeyword)) {
+ setterContainerRef.getChild(name).node = member;
+ } else {
+ methodContainerRef.getChild(name).node = member;
+ }
+ }
+ }
+ }
+
+ Expression readInitializer(LinkedNode linkedNode) {
+ if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+ return readNode(linkedNode.defaultFormalParameter_defaultValue);
+ }
+ return readNode(linkedNode.variableDeclaration_initializer);
+ }
+
+ AstNode readNode(LinkedNode linkedNode) {
+ var reader = AstBinaryReader(this);
+ return reader.readNode(linkedNode);
+ }
+
+ Iterable<LinkedNode> topLevelVariables(LinkedNode unit) sync* {
+ for (var declaration in unit.compilationUnit_declarations) {
+ if (declaration.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+ var variableList = declaration.topLevelVariableDeclaration_variableList;
+ for (var variable in variableList.variableDeclarationList_variables) {
+ yield variable;
+ }
+ }
+ }
+ }
+
+ LinkedNode _getFunctionBody(LinkedNode node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.constructorDeclaration) {
+ return node.constructorDeclaration_body;
+ } else if (kind == LinkedNodeKind.functionDeclaration) {
+ return node
+ .functionDeclaration_functionExpression.functionExpression_body;
+ } else if (kind == LinkedNodeKind.methodDeclaration) {
+ return node.methodDeclaration_body;
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ }
+
+ bool _isGetToken(int token) {
+ return tokensContext.type(token) == UnlinkedTokenType.GET;
+ }
+
+ bool _isSetToken(int token) {
+ return tokensContext.type(token) == UnlinkedTokenType.SET;
+ }
}
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
new file mode 100644
index 0000000..50b9b92
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2019, 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/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/type.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+class LinkingBundleContext {
+ /// The `dynamic` class is declared in `dart:core`, but is not a class.
+ /// Also, it is static, so we cannot set `reference` for it.
+ /// So, we have to push it in a separate way.
+ final Reference dynamicReference;
+
+ /// References used in all libraries being linked.
+ /// Element references in nodes are indexes in this list.
+ final List<Reference> references = [null];
+
+ /// Data about [references].
+ final LinkedNodeReferencesBuilder referencesBuilder =
+ LinkedNodeReferencesBuilder(
+ parent: [0],
+ name: [''],
+ );
+
+ LinkingBundleContext(this.dynamicReference);
+
+ int indexOfReference(Reference reference) {
+ if (reference.parent == null) return 0;
+ if (reference.index != null) return reference.index;
+
+ var parentIndex = indexOfReference(reference.parent);
+ referencesBuilder.parent.add(parentIndex);
+ referencesBuilder.name.add(reference.name);
+
+ reference.index = references.length;
+ references.add(reference);
+ return reference.index;
+ }
+
+ LinkedNodeTypeBuilder writeType(DartType type) {
+ if (type == null) return null;
+
+ if (type.isBottom) {
+ return LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.bottom,
+ );
+ } else if (type.isDynamic) {
+ return LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.dynamic_,
+ );
+ } else if (type is FunctionType) {
+ return LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.function,
+ functionFormalParameters: _getReferences(type.parameters),
+ functionReturnType: writeType(type.returnType),
+ functionTypeParameters: _getReferences(type.typeParameters),
+ );
+ } else if (type is InterfaceType) {
+ return LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.interface,
+ interfaceClass: _getReferenceIndex(type.element),
+ interfaceTypeArguments: type.typeArguments.map(writeType).toList(),
+ );
+ } else if (type is TypeParameterType) {
+ return LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.typeParameter,
+ typeParameterParameter: _getReferenceIndex(type.element),
+ );
+ } else if (type is VoidType) {
+ return LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.void_,
+ );
+ } else {
+ throw UnimplementedError('(${type.runtimeType}) $type');
+ }
+ }
+
+ int _getReferenceIndex(Element element) {
+ if (element == null) return 0;
+
+ var reference = (element as ElementImpl).reference;
+ return indexOfReference(reference);
+ }
+
+ List<int> _getReferences(List<Element> elements) {
+ var result = List<int>(elements.length);
+ for (var i = 0; i < elements.length; ++i) {
+ var element = elements[i];
+ result[i] = _getReferenceIndex(element);
+ }
+ return result;
+ }
+}
diff --git a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
new file mode 100644
index 0000000..2030086
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2019, 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/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_reader.dart';
+import 'package:analyzer/src/summary2/ast_resolver.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+class MetadataResolver {
+ AstResolver _astResolver;
+
+ MetadataResolver(Linker linker, Reference libraryRef) {
+ _astResolver = AstResolver(linker, libraryRef);
+ }
+
+ void resolve(UnitBuilder unit) {
+ var unitDeclarations = unit.node.compilationUnit_declarations;
+ for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
+ var kind = unitDeclaration.kind;
+ if (_isAnnotatedNode(kind)) {
+ _annotatedNode(
+ unit,
+ unitDeclaration,
+ );
+ }
+ if (kind == LinkedNodeKind.classDeclaration) {
+ _class(unit, unitDeclaration);
+ } else if (kind == LinkedNodeKind.enumDeclaration) {
+ _enumDeclaration(unit, unitDeclaration);
+ } else if (kind == LinkedNodeKind.functionDeclaration) {
+ var function = unitDeclaration.functionDeclaration_functionExpression;
+ _formalParameterList(
+ unit,
+ function.functionExpression_formalParameters,
+ );
+ } else if (kind == LinkedNodeKind.topLevelVariableDeclaration) {
+ _variables(
+ unit,
+ unitDeclaration,
+ unitDeclaration.topLevelVariableDeclaration_variableList,
+ );
+ }
+ }
+ }
+
+ void _annotatedNode(UnitBuilder unit, LinkedNodeBuilder node) {
+ var unresolved = node.annotatedNode_metadata;
+ var resolved = _list(unit, unresolved);
+ node.annotatedNode_metadata = resolved;
+ }
+
+ void _class(UnitBuilder unit, LinkedNodeBuilder unitDeclaration) {
+ var members = unitDeclaration.classOrMixinDeclaration_members;
+ for (var classMember in members) {
+ var kind = classMember.kind;
+ if (_isAnnotatedNode(kind)) {
+ _annotatedNode(unit, classMember);
+ }
+ if (kind == LinkedNodeKind.fieldDeclaration) {
+ _variables(
+ unit,
+ classMember,
+ classMember.fieldDeclaration_fields,
+ );
+ } else if (kind == LinkedNodeKind.methodDeclaration) {
+ _formalParameterList(
+ unit,
+ classMember.methodDeclaration_formalParameters,
+ );
+ }
+ }
+ }
+
+ void _enumDeclaration(UnitBuilder unit, LinkedNodeBuilder node) {
+ for (var constant in node.enumDeclaration_constants) {
+ var kind = constant.kind;
+ if (kind == LinkedNodeKind.enumConstantDeclaration) {
+ _annotatedNode(unit, constant);
+ }
+ }
+ }
+
+ void _formalParameterList(UnitBuilder unit, LinkedNodeBuilder node) {
+ if (node == null) return;
+
+ for (var parameter in node.formalParameterList_parameters) {
+ if (parameter.kind == LinkedNodeKind.defaultFormalParameter) {
+ var actual = parameter.defaultFormalParameter_parameter;
+ var unresolved = actual.normalFormalParameter_metadata;
+ var resolved = _list(unit, unresolved);
+ actual.normalFormalParameter_metadata = resolved;
+ } else {
+ var unresolved = parameter.normalFormalParameter_metadata;
+ var resolved = _list(unit, unresolved);
+ parameter.normalFormalParameter_metadata = resolved;
+ }
+ }
+ }
+
+ List<LinkedNodeBuilder> _list(UnitBuilder unit, List<LinkedNode> unresolved) {
+ var resolved = List<LinkedNodeBuilder>(unresolved.length);
+ for (var i = 0; i < unresolved.length; ++i) {
+ var unresolvedNode = unresolved[i];
+
+ var reader = AstBinaryReader(unit.context);
+ var ast = reader.readNode(unresolvedNode) as Annotation;
+ ast.elementAnnotation = ElementAnnotationImpl(null);
+
+ // Set some parent, so that resolver does not bail out.
+ astFactory.libraryDirective(null, [ast], null, null, null);
+
+ var resolvedNode = _astResolver.resolve(unit, ast);
+ resolved[i] = resolvedNode;
+ }
+ return resolved;
+ }
+
+ /// Resolve annotations of the [declaration] (field or top-level variable),
+ /// and set them as metadata for each variable in the [variableList].
+ void _variables(UnitBuilder unit, LinkedNodeBuilder declaration,
+ LinkedNodeBuilder variableList) {
+ for (var variable in variableList.variableDeclarationList_variables) {
+ var unresolved = declaration.annotatedNode_metadata;
+ var resolved = _list(unit, unresolved);
+ variable.annotatedNode_metadata = resolved;
+ }
+ }
+
+ static bool _isAnnotatedNode(LinkedNodeKind kind) {
+ return kind == LinkedNodeKind.classDeclaration ||
+ kind == LinkedNodeKind.classTypeAlias ||
+ kind == LinkedNodeKind.constructorDeclaration ||
+ kind == LinkedNodeKind.enumDeclaration ||
+ kind == LinkedNodeKind.functionDeclaration ||
+ kind == LinkedNodeKind.functionTypeAlias ||
+ kind == LinkedNodeKind.methodDeclaration;
+ }
+}
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index 6045db9..c89239d 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -48,6 +48,14 @@
bool get isClass => parent != null && parent.name == '@class';
+ bool get isEnum => parent != null && parent.name == '@enum';
+
+ bool get isGenericTypeAlias => parent != null && parent.name == '@typeAlias';
+
+ bool get isTypeParameter => parent != null && parent.name == '@typeParameter';
+
+ int get numOfChildren => _children != null ? _children.length : 0;
+
/// Return the child with the given name, or `null` if does not exist.
Reference operator [](String name) {
return _children != null ? _children[name] : null;
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
new file mode 100644
index 0000000..f044c1b
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -0,0 +1,463 @@
+// Copyright (c) 2019, 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/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/declaration.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/scope.dart';
+
+/// Recursive visitor of [LinkedNode]s that resolves explicit type annotations
+/// in outlines. This includes resolving element references in identifiers
+/// in type annotation, and setting [LinkedNodeType]s for corresponding type
+/// annotation nodes.
+///
+/// Declarations that have type annotations, e.g. return types of methods, get
+/// the corresponding type set (so, if there is an explicit type annotation,
+/// the type is set, otherwise we keep it empty, so we will attempt to infer
+/// it later).
+class ReferenceResolver {
+ final LinkingBundleContext linkingBundleContext;
+ final UnitBuilder unit;
+
+ /// TODO(scheglov) Update scope with local scopes (formal / type parameters).
+ Scope scope;
+
+ Reference reference;
+
+ ReferenceResolver(
+ this.linkingBundleContext,
+ this.unit,
+ this.scope,
+ this.reference,
+ );
+
+ LinkedNodeTypeBuilder get _dynamicType {
+ return LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.dynamic_,
+ );
+ }
+
+ void resolve() {
+ _node(unit.node);
+ }
+
+ void _classDeclaration(LinkedNodeBuilder node) {
+ var name = unit.context.getUnitMemberName(node);
+ reference = reference.getChild('@class').getChild(name);
+
+ var typeParameters = node.classOrMixinDeclaration_typeParameters;
+ _withTypeParameters(typeParameters, () {
+ var extendsClause = node.classDeclaration_extendsClause;
+ if (extendsClause != null) {
+ _typeName(extendsClause.extendsClause_superclass);
+ }
+
+ _nodeList(
+ node.classDeclaration_withClause?.withClause_mixinTypes,
+ );
+
+ _nodeList(
+ node.classOrMixinDeclaration_implementsClause
+ ?.implementsClause_interfaces,
+ );
+
+ for (var field in node.classOrMixinDeclaration_members) {
+ if (field.kind != LinkedNodeKind.constructorDeclaration) {
+ _node(field);
+ }
+ }
+ for (var field in node.classOrMixinDeclaration_members) {
+ if (field.kind == LinkedNodeKind.constructorDeclaration) {
+ _node(field);
+ }
+ }
+ });
+
+ reference = reference.parent.parent;
+ }
+
+ void _classTypeAlias(LinkedNodeBuilder node) {
+ var name = unit.context.getUnitMemberName(node);
+ reference = reference.getChild('@class').getChild(name);
+
+ var typeParameters = node.classTypeAlias_typeParameters;
+ _withTypeParameters(typeParameters, () {
+ var superclass = node.classTypeAlias_superclass;
+ if (superclass != null) {
+ _typeName(superclass);
+ }
+
+ _nodeList(
+ node.classTypeAlias_withClause?.withClause_mixinTypes,
+ );
+
+ _nodeList(
+ node.classTypeAlias_implementsClause?.implementsClause_interfaces,
+ );
+ });
+
+ reference = reference.parent.parent;
+ }
+
+ void _compilationUnit(LinkedNodeBuilder node) {
+ _nodeList(node.compilationUnit_directives);
+ _nodeList(node.compilationUnit_declarations);
+ }
+
+ void _constructorDeclaration(LinkedNodeBuilder node) {
+ _node(node.constructorDeclaration_parameters);
+ }
+
+ void _enumConstantDeclaration(LinkedNodeBuilder node) {}
+
+ void _enumDeclaration(LinkedNodeBuilder node) {
+ _nodeList(node.enumDeclaration_constants);
+ }
+
+ void _fieldDeclaration(LinkedNodeBuilder node) {
+ _node(node.fieldDeclaration_fields);
+ }
+
+ void _fieldFormalParameter(LinkedNodeBuilder node) {
+ var typeNode = node.fieldFormalParameter_type;
+ if (typeNode != null) {
+ _node(typeNode);
+ node.fieldFormalParameter_type2 = _getTypeAnnotationType(typeNode);
+ }
+
+ var formalParameters = node.fieldFormalParameter_formalParameters;
+ if (formalParameters != null) {
+ _node(formalParameters);
+ throw 'incomplete';
+ }
+ }
+
+ void _formalParameters(LinkedNodeBuilder node) {
+ for (var parameter in node.formalParameterList_parameters) {
+ _node(parameter);
+ }
+ }
+
+ void _functionDeclaration(LinkedNodeBuilder node) {
+ var name = unit.context.getUnitMemberName(node);
+ reference = reference.getChild('@function').getChild(name);
+
+ var function = node.functionDeclaration_functionExpression;
+ var typeParameters = function.functionExpression_typeParameters;
+ _withTypeParameters(typeParameters, () {
+ var returnType = node.functionDeclaration_returnType;
+ if (returnType != null) {
+ _node(returnType);
+ node.functionDeclaration_returnType2 =
+ _getTypeAnnotationType(returnType);
+ } else {
+ node.functionDeclaration_returnType2 = _dynamicType;
+ }
+
+ _node(function.functionExpression_formalParameters);
+ });
+
+ reference = reference.parent.parent;
+ }
+
+ void _functionExpression(LinkedNodeBuilder node) {
+ var typeParameters = node.functionExpression_typeParameters;
+ _withTypeParameters(typeParameters, () {
+ _node(node.functionExpression_formalParameters);
+ });
+ }
+
+ void _functionTypeAlias(LinkedNodeBuilder node) {
+ var name = unit.context.getUnitMemberName(node);
+ reference = reference.getChild('@typeAlias').getChild(name);
+
+ var typeParameters = node.functionTypeAlias_typeParameters;
+ _withTypeParameters(typeParameters, () {
+ var returnType = node.functionTypeAlias_returnType;
+ if (returnType != null) {
+ _node(returnType);
+ node.functionTypeAlias_returnType2 = _getTypeAnnotationType(returnType);
+ } else {
+ node.functionTypeAlias_returnType2 = _dynamicType;
+ }
+
+ _node(node.functionTypeAlias_formalParameters);
+ });
+
+ reference = reference.parent.parent;
+ }
+
+ void _genericFunctionType(LinkedNodeBuilder node) {
+ reference = reference.getChild('@function');
+
+ var name = '${reference.numOfChildren}';
+ reference = reference.getChild(name);
+
+ var typeParameters = node.genericFunctionType_typeParameters;
+ _withTypeParameters(typeParameters, () {
+ var returnType = node.genericFunctionType_returnType;
+ if (returnType != null) {
+ _node(returnType);
+ node.genericFunctionType_returnType2 =
+ _getTypeAnnotationType(returnType);
+ } else {
+ node.genericFunctionType_returnType2 = _dynamicType;
+ }
+
+ _node(node.genericFunctionType_formalParameters);
+ });
+
+ reference = reference.parent.parent;
+ }
+
+ void _genericTypeAlias(LinkedNodeBuilder node) {
+ var name = unit.context.getSimpleName(
+ node.namedCompilationUnitMember_name,
+ );
+ reference = reference.getChild('@typeAlias').getChild(name);
+
+ var typeParameters = node.genericTypeAlias_typeParameters;
+ _withTypeParameters(typeParameters, () {
+ _node(node.genericTypeAlias_functionType);
+ });
+
+ reference = reference.parent.parent;
+ }
+
+ LinkedNodeTypeBuilder _getTypeAnnotationType(LinkedNodeBuilder node) {
+ var kind = node.kind;
+ if (kind == LinkedNodeKind.typeName) {
+ return node.typeName_type;
+ } else {
+ throw UnimplementedError('$kind');
+ }
+ }
+
+ void _importDirective(LinkedNodeBuilder node) {}
+
+ void _libraryDirective(LinkedNodeBuilder node) {}
+
+ void _methodDeclaration(LinkedNodeBuilder node) {
+ var name = unit.context.getMethodName(node);
+ reference = reference.getChild('@method').getChild(name);
+
+ var typeParameters = node.methodDeclaration_typeParameters;
+ _withTypeParameters(typeParameters, () {
+ var returnType = node.methodDeclaration_returnType;
+ if (returnType != null) {
+ _node(returnType);
+ node.methodDeclaration_returnType2 = _getTypeAnnotationType(returnType);
+ }
+
+ _node(node.methodDeclaration_formalParameters);
+ });
+
+ reference = reference.parent.parent;
+ }
+
+ void _node(LinkedNodeBuilder node) {
+ if (node == null) return;
+
+ if (node.kind == LinkedNodeKind.classDeclaration) {
+ _classDeclaration(node);
+ } else if (node.kind == LinkedNodeKind.classTypeAlias) {
+ _classTypeAlias(node);
+ } else if (node.kind == LinkedNodeKind.compilationUnit) {
+ _compilationUnit(node);
+ } else if (node.kind == LinkedNodeKind.constructorDeclaration) {
+ _constructorDeclaration(node);
+ } else if (node.kind == LinkedNodeKind.defaultFormalParameter) {
+ _node(node.defaultFormalParameter_parameter);
+ } else if (node.kind == LinkedNodeKind.enumDeclaration) {
+ _enumDeclaration(node);
+ } else if (node.kind == LinkedNodeKind.enumConstantDeclaration) {
+ _enumConstantDeclaration(node);
+ } else if (node.kind == LinkedNodeKind.fieldDeclaration) {
+ _fieldDeclaration(node);
+ } else if (node.kind == LinkedNodeKind.fieldFormalParameter) {
+ _fieldFormalParameter(node);
+ } else if (node.kind == LinkedNodeKind.formalParameterList) {
+ _formalParameters(node);
+ } else if (node.kind == LinkedNodeKind.functionDeclaration) {
+ _functionDeclaration(node);
+ } else if (node.kind == LinkedNodeKind.functionExpression) {
+ _functionExpression(node);
+ } else if (node.kind == LinkedNodeKind.functionTypeAlias) {
+ _functionTypeAlias(node);
+ } else if (node.kind == LinkedNodeKind.genericFunctionType) {
+ _genericFunctionType(node);
+ } else if (node.kind == LinkedNodeKind.genericTypeAlias) {
+ _genericTypeAlias(node);
+ } else if (node.kind == LinkedNodeKind.importDirective) {
+ _importDirective(node);
+ } else if (node.kind == LinkedNodeKind.libraryDirective) {
+ _libraryDirective(node);
+ } else if (node.kind == LinkedNodeKind.methodDeclaration) {
+ _methodDeclaration(node);
+ } else if (node.kind == LinkedNodeKind.simpleFormalParameter) {
+ _simpleFormalParameter(node);
+ } else if (node.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+ _topLevelVariableDeclaration(node);
+ } else if (node.kind == LinkedNodeKind.typeArgumentList) {
+ _typeArgumentList(node);
+ } else if (node.kind == LinkedNodeKind.typeName) {
+ _typeName(node);
+ } else if (node.kind == LinkedNodeKind.typeParameter) {
+ _typeParameter(node);
+ } else if (node.kind == LinkedNodeKind.typeParameterList) {
+ _typeParameterList(node);
+ } else if (node.kind == LinkedNodeKind.variableDeclarationList) {
+ _variableDeclarationList(node);
+ } else {
+ // TODO(scheglov) implement
+ throw UnimplementedError('${node.kind}');
+ }
+ }
+
+ void _nodeList(List<LinkedNode> nodeList) {
+ if (nodeList == null) return;
+
+ for (var i = 0; i < nodeList.length; ++i) {
+ var node = nodeList[i];
+ _node(node);
+ }
+ }
+
+ void _simpleFormalParameter(LinkedNodeBuilder node) {
+ var typeNode = node.simpleFormalParameter_type;
+ if (typeNode != null) {
+ _node(typeNode);
+ node.simpleFormalParameter_type2 = _getTypeAnnotationType(typeNode);
+ } else {
+ // TODO(scheglov) might be inferred
+ node.simpleFormalParameter_type2 = _dynamicType;
+ }
+
+ if (node.normalFormalParameter_covariantKeyword != 0) {
+ node.normalFormalParameter_isCovariant = true;
+ } else {
+ // TODO(scheglov) might be inferred
+ }
+ }
+
+ void _topLevelVariableDeclaration(LinkedNodeBuilder node) {
+ _node(node.topLevelVariableDeclaration_variableList);
+ }
+
+ void _typeArgumentList(LinkedNodeBuilder node) {
+ for (var typeArgument in node.typeArgumentList_arguments) {
+ _typeName(typeArgument);
+ }
+ }
+
+ void _typeName(LinkedNodeBuilder node) {
+ if (node == null) return;
+
+ var identifier = node.typeName_name;
+ if (identifier.kind == LinkedNodeKind.simpleIdentifier) {
+ var name = unit.context.getSimpleName(identifier);
+
+ if (name == 'void') {
+ node.typeName_type = LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.void_,
+ );
+ return;
+ }
+
+ var declaration = scope.lookup(name);
+ if (declaration == null) {
+ identifier.simpleIdentifier_element = 0;
+ node.typeName_type = _dynamicType;
+ return;
+ }
+
+ var reference = declaration.reference;
+ var referenceIndex = linkingBundleContext.indexOfReference(reference);
+ identifier.simpleIdentifier_element = referenceIndex;
+
+ var typeArguments = const <LinkedNodeTypeBuilder>[];
+ var typeArgumentList = node.typeName_typeArguments;
+ if (typeArgumentList != null) {
+ _node(typeArgumentList);
+ typeArguments = typeArgumentList.typeArgumentList_arguments
+ .map((node) => _getTypeAnnotationType(node))
+ .toList();
+ }
+
+ if (reference.isClass) {
+ node.typeName_type = LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.interface,
+ interfaceClass: referenceIndex,
+ interfaceTypeArguments: typeArguments,
+ );
+ } else if (reference.isEnum) {
+ node.typeName_type = LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.interface,
+ interfaceClass: referenceIndex,
+ );
+ } else if (reference.isTypeParameter) {
+ node.typeName_type = LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.typeParameter,
+ typeParameterParameter: referenceIndex,
+ );
+ } else {
+ // TODO(scheglov) set Object? keep unresolved?
+ throw UnimplementedError();
+ }
+ } else {
+ // TODO(scheglov) implement
+ throw UnimplementedError();
+ }
+ }
+
+ void _typeParameter(LinkedNodeBuilder node) {
+ _node(node.typeParameter_bound);
+ // TODO(scheglov) set Object bound if no explicit?
+ }
+
+ void _typeParameterList(LinkedNodeBuilder node) {
+ for (var typeParameter in node.typeParameterList_typeParameters) {
+ _node(typeParameter);
+ }
+ }
+
+ void _variableDeclarationList(LinkedNodeBuilder node) {
+ var typeNode = node.variableDeclarationList_type;
+ if (typeNode != null) {
+ _node(typeNode);
+ for (var field in node.variableDeclarationList_variables) {
+ field.variableDeclaration_type2 = _getTypeAnnotationType(typeNode);
+ }
+ }
+ }
+
+ /// Enter the type parameters scope, visit them, and run [f].
+ void _withTypeParameters(LinkedNode typeParameterList, void f()) {
+ if (typeParameterList == null) {
+ f();
+ return;
+ }
+
+ scope = Scope(this.scope, {});
+
+ var containerRef = this.reference.getChild('@typeParameter');
+ var typeParameters = typeParameterList.typeParameterList_typeParameters;
+ for (var typeParameter in typeParameters) {
+ var name = unit.context.getSimpleName(typeParameter.typeParameter_name);
+ var reference = containerRef.getChild(name);
+ reference.node = typeParameter;
+ scope.declare(name, Declaration(name, reference));
+ }
+
+ _node(typeParameterList);
+ f();
+
+ if (typeParameterList != null) {
+ scope = scope.parent;
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/summary2/scope.dart b/pkg/analyzer/lib/src/summary2/scope.dart
index 6917dea..30f7419 100644
--- a/pkg/analyzer/lib/src/summary2/scope.dart
+++ b/pkg/analyzer/lib/src/summary2/scope.dart
@@ -21,6 +21,10 @@
}
Declaration lookup(String name) {
- return map[name];
+ var declaration = map[name];
+ if (declaration != null) return declaration;
+
+ if (parent == null) return null;
+ return parent.lookup(name);
}
}
diff --git a/pkg/analyzer/lib/src/summary2/tokens_context.dart b/pkg/analyzer/lib/src/summary2/tokens_context.dart
new file mode 100644
index 0000000..36b9d5a
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/tokens_context.dart
@@ -0,0 +1,395 @@
+// Copyright (c) 2019, 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/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/tokens_writer.dart';
+
+/// The context for reading or writing tokens.
+///
+/// Tokens cannot be compared, so tokens for [indexOfToken] must be previously
+/// received from [tokenOfIndex], or the context must be created from a
+/// [TokensResult] (the result of writing previously parsed tokens).
+class TokensContext {
+ final UnlinkedTokens _tokens;
+ final List<Token> _indexToToken;
+ final Map<Token, int> _tokenToIndex;
+
+ TokensContext(this._tokens)
+ : _indexToToken = List<Token>(_tokens.type.length),
+ _tokenToIndex = Map.identity();
+
+ TokensContext.fromResult(
+ this._tokens, this._indexToToken, this._tokenToIndex);
+
+ /// TODO(scheglov) Not used yet, maybe remove.
+ int addSyntheticToken(
+ UnlinkedTokenKind kind, UnlinkedTokenType type, String lexeme) {
+ var index = _tokens.kind.length;
+ UnlinkedTokensBuilder tokens = _tokens;
+ tokens.kind.add(kind);
+ tokens.lexeme.add(lexeme);
+ tokens.offset.add(0);
+ tokens.length.add(0);
+ tokens.type.add(type);
+ tokens.next.add(0);
+ tokens.endGroup.add(0);
+ tokens.precedingComment.add(0);
+ tokens.isSynthetic.add(true);
+ return index;
+ }
+
+ int indexOfToken(Token token) {
+ if (token == null) return 0;
+
+ var index = _tokenToIndex[token];
+ if (index == null) {
+ throw StateError('Unexpected token: $token');
+ }
+ return index;
+ }
+
+ String lexeme(int index) {
+ return _tokens.lexeme[index];
+ }
+
+ int offset(int index) {
+ return _tokens.offset[index];
+ }
+
+ Token tokenOfIndex(int index) {
+ if (index == 0) return null;
+
+ var token = _indexToToken[index];
+ if (token == null) {
+ var kind = _tokens.kind[index];
+ switch (kind) {
+ case UnlinkedTokenKind.nothing:
+ return null;
+ case UnlinkedTokenKind.comment:
+ return CommentToken(
+ _binaryToAstTokenType(_tokens.type[index]),
+ _tokens.lexeme[index],
+ _tokens.offset[index],
+ );
+ case UnlinkedTokenKind.keyword:
+ return KeywordToken(
+ _binaryToAstTokenType(_tokens.type[index]),
+ _tokens.offset[index],
+ _getCommentToken(_tokens.precedingComment[index]),
+ );
+ case UnlinkedTokenKind.simple:
+ return SimpleToken(
+ _binaryToAstTokenType(_tokens.type[index]),
+ _tokens.offset[index],
+ _getCommentToken(_tokens.precedingComment[index]),
+ );
+ case UnlinkedTokenKind.string:
+ return StringToken(
+ _binaryToAstTokenType(_tokens.type[index]),
+ _tokens.lexeme[index],
+ _tokens.offset[index],
+ _getCommentToken(_tokens.precedingComment[index]),
+ );
+ default:
+ throw UnimplementedError('Token kind: $kind');
+ }
+ }
+ return token;
+ }
+
+ UnlinkedTokenType type(int index) {
+ return _tokens.type[index];
+ }
+
+ CommentToken _getCommentToken(int index) {
+ var result = tokenOfIndex(index);
+ var token = result;
+ while (true) {
+ index = _tokens.next[index];
+ if (index == 0) return result;
+
+ var nextToken = tokenOfIndex(index);
+ token.next = nextToken;
+ token = nextToken;
+ }
+ }
+
+ static TokenType _binaryToAstTokenType(UnlinkedTokenType type) {
+ switch (type) {
+ case UnlinkedTokenType.ABSTRACT:
+ return Keyword.ABSTRACT;
+ case UnlinkedTokenType.AMPERSAND:
+ return TokenType.AMPERSAND;
+ case UnlinkedTokenType.AMPERSAND_AMPERSAND:
+ return TokenType.AMPERSAND_AMPERSAND;
+ case UnlinkedTokenType.AMPERSAND_EQ:
+ return TokenType.AMPERSAND_EQ;
+ case UnlinkedTokenType.AS:
+ return TokenType.AS;
+ case UnlinkedTokenType.ASSERT:
+ return Keyword.ASSERT;
+ case UnlinkedTokenType.ASYNC:
+ return Keyword.ASYNC;
+ case UnlinkedTokenType.AT:
+ return TokenType.AT;
+ case UnlinkedTokenType.AWAIT:
+ return Keyword.AWAIT;
+ case UnlinkedTokenType.BACKPING:
+ return TokenType.BACKPING;
+ case UnlinkedTokenType.BACKSLASH:
+ return TokenType.BACKSLASH;
+ case UnlinkedTokenType.BANG:
+ return TokenType.BANG;
+ case UnlinkedTokenType.BANG_EQ:
+ return TokenType.BANG_EQ;
+ case UnlinkedTokenType.BAR:
+ return TokenType.BAR;
+ case UnlinkedTokenType.BAR_BAR:
+ return TokenType.BAR_BAR;
+ case UnlinkedTokenType.BAR_EQ:
+ return TokenType.BAR_EQ;
+ case UnlinkedTokenType.BREAK:
+ return Keyword.BREAK;
+ case UnlinkedTokenType.CARET:
+ return TokenType.CARET;
+ case UnlinkedTokenType.CARET_EQ:
+ return TokenType.CARET_EQ;
+ case UnlinkedTokenType.CASE:
+ return Keyword.CASE;
+ case UnlinkedTokenType.CATCH:
+ return Keyword.CATCH;
+ case UnlinkedTokenType.CLASS:
+ return Keyword.CLASS;
+ case UnlinkedTokenType.CLOSE_CURLY_BRACKET:
+ return TokenType.CLOSE_CURLY_BRACKET;
+ case UnlinkedTokenType.CLOSE_PAREN:
+ return TokenType.CLOSE_PAREN;
+ case UnlinkedTokenType.CLOSE_SQUARE_BRACKET:
+ return TokenType.CLOSE_SQUARE_BRACKET;
+ case UnlinkedTokenType.COLON:
+ return TokenType.COLON;
+ case UnlinkedTokenType.COMMA:
+ return TokenType.COMMA;
+ case UnlinkedTokenType.CONST:
+ return Keyword.CONST;
+ case UnlinkedTokenType.CONTINUE:
+ return Keyword.CONTINUE;
+ case UnlinkedTokenType.COVARIANT:
+ return Keyword.COVARIANT;
+ case UnlinkedTokenType.DEFAULT:
+ return Keyword.DEFAULT;
+ case UnlinkedTokenType.DEFERRED:
+ return Keyword.DEFERRED;
+ case UnlinkedTokenType.DO:
+ return Keyword.DO;
+ case UnlinkedTokenType.DOUBLE:
+ return TokenType.DOUBLE;
+ case UnlinkedTokenType.DYNAMIC:
+ return Keyword.DYNAMIC;
+ case UnlinkedTokenType.ELSE:
+ return Keyword.ELSE;
+ case UnlinkedTokenType.ENUM:
+ return Keyword.ENUM;
+ case UnlinkedTokenType.EOF:
+ return TokenType.EOF;
+ case UnlinkedTokenType.EQ:
+ return TokenType.EQ;
+ case UnlinkedTokenType.EQ_EQ:
+ return TokenType.EQ_EQ;
+ case UnlinkedTokenType.EXPORT:
+ return Keyword.EXPORT;
+ case UnlinkedTokenType.EXTENDS:
+ return Keyword.EXTENDS;
+ case UnlinkedTokenType.EXTERNAL:
+ return Keyword.EXTERNAL;
+ case UnlinkedTokenType.FACTORY:
+ return Keyword.FACTORY;
+ case UnlinkedTokenType.FALSE:
+ return Keyword.FALSE;
+ case UnlinkedTokenType.FINAL:
+ return Keyword.FINAL;
+ case UnlinkedTokenType.FINALLY:
+ return Keyword.FINALLY;
+ case UnlinkedTokenType.FOR:
+ return Keyword.FOR;
+ case UnlinkedTokenType.FUNCTION:
+ return TokenType.FUNCTION;
+ case UnlinkedTokenType.FUNCTION_KEYWORD:
+ return Keyword.FUNCTION;
+ case UnlinkedTokenType.GET:
+ return Keyword.GET;
+ case UnlinkedTokenType.GT:
+ return TokenType.GT;
+ case UnlinkedTokenType.GT_EQ:
+ return TokenType.GT_EQ;
+ case UnlinkedTokenType.GT_GT:
+ return TokenType.GT_GT;
+ case UnlinkedTokenType.GT_GT_EQ:
+ return TokenType.GT_GT_EQ;
+ case UnlinkedTokenType.HASH:
+ return TokenType.HASH;
+ case UnlinkedTokenType.HEXADECIMAL:
+ return TokenType.HEXADECIMAL;
+ case UnlinkedTokenType.HIDE:
+ return Keyword.HIDE;
+ case UnlinkedTokenType.IDENTIFIER:
+ return TokenType.IDENTIFIER;
+ case UnlinkedTokenType.IF:
+ return Keyword.IF;
+ case UnlinkedTokenType.IMPLEMENTS:
+ return Keyword.IMPLEMENTS;
+ case UnlinkedTokenType.IMPORT:
+ return Keyword.IMPORT;
+ case UnlinkedTokenType.IN:
+ return Keyword.IN;
+ case UnlinkedTokenType.INDEX:
+ return TokenType.INDEX;
+ case UnlinkedTokenType.INDEX_EQ:
+ return TokenType.INDEX_EQ;
+ case UnlinkedTokenType.INT:
+ return TokenType.INT;
+ case UnlinkedTokenType.INTERFACE:
+ return Keyword.INTERFACE;
+ case UnlinkedTokenType.IS:
+ return TokenType.IS;
+ case UnlinkedTokenType.LIBRARY:
+ return Keyword.LIBRARY;
+ case UnlinkedTokenType.LT:
+ return TokenType.LT;
+ case UnlinkedTokenType.LT_EQ:
+ return TokenType.LT_EQ;
+ case UnlinkedTokenType.LT_LT:
+ return TokenType.LT_LT;
+ case UnlinkedTokenType.LT_LT_EQ:
+ return TokenType.LT_LT_EQ;
+ case UnlinkedTokenType.MINUS:
+ return TokenType.MINUS;
+ case UnlinkedTokenType.MINUS_EQ:
+ return TokenType.MINUS_EQ;
+ case UnlinkedTokenType.MINUS_MINUS:
+ return TokenType.MINUS_MINUS;
+ case UnlinkedTokenType.MIXIN:
+ return Keyword.MIXIN;
+ case UnlinkedTokenType.MULTI_LINE_COMMENT:
+ return TokenType.MULTI_LINE_COMMENT;
+ case UnlinkedTokenType.NATIVE:
+ return Keyword.NATIVE;
+ case UnlinkedTokenType.NEW:
+ return Keyword.NEW;
+ case UnlinkedTokenType.NULL:
+ return Keyword.NULL;
+ case UnlinkedTokenType.OF:
+ return Keyword.OF;
+ case UnlinkedTokenType.ON:
+ return Keyword.ON;
+ case UnlinkedTokenType.OPEN_CURLY_BRACKET:
+ return TokenType.OPEN_CURLY_BRACKET;
+ case UnlinkedTokenType.OPEN_PAREN:
+ return TokenType.OPEN_PAREN;
+ case UnlinkedTokenType.OPEN_SQUARE_BRACKET:
+ return TokenType.OPEN_SQUARE_BRACKET;
+ case UnlinkedTokenType.OPERATOR:
+ return Keyword.OPERATOR;
+ case UnlinkedTokenType.PART:
+ return Keyword.PART;
+ case UnlinkedTokenType.PATCH:
+ return Keyword.PATCH;
+ case UnlinkedTokenType.PERCENT:
+ return TokenType.PERCENT;
+ case UnlinkedTokenType.PERCENT_EQ:
+ return TokenType.PERCENT_EQ;
+ case UnlinkedTokenType.PERIOD:
+ return TokenType.PERIOD;
+ case UnlinkedTokenType.PERIOD_PERIOD:
+ return TokenType.PERIOD_PERIOD;
+ case UnlinkedTokenType.PERIOD_PERIOD_PERIOD:
+ return TokenType.PERIOD_PERIOD_PERIOD;
+ case UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION:
+ return TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+ case UnlinkedTokenType.PLUS:
+ return TokenType.PLUS;
+ case UnlinkedTokenType.PLUS_EQ:
+ return TokenType.PLUS_EQ;
+ case UnlinkedTokenType.PLUS_PLUS:
+ return TokenType.PLUS_PLUS;
+ case UnlinkedTokenType.QUESTION:
+ return TokenType.QUESTION;
+ case UnlinkedTokenType.QUESTION_PERIOD:
+ return TokenType.QUESTION_PERIOD;
+ case UnlinkedTokenType.QUESTION_QUESTION:
+ return TokenType.QUESTION_QUESTION;
+ case UnlinkedTokenType.QUESTION_QUESTION_EQ:
+ return TokenType.QUESTION_QUESTION_EQ;
+ case UnlinkedTokenType.RETHROW:
+ return Keyword.RETHROW;
+ case UnlinkedTokenType.RETURN:
+ return Keyword.RETURN;
+ case UnlinkedTokenType.SCRIPT_TAG:
+ return TokenType.SCRIPT_TAG;
+ case UnlinkedTokenType.SEMICOLON:
+ return TokenType.SEMICOLON;
+ case UnlinkedTokenType.SET:
+ return Keyword.SET;
+ case UnlinkedTokenType.SHOW:
+ return Keyword.SHOW;
+ case UnlinkedTokenType.SINGLE_LINE_COMMENT:
+ return TokenType.SINGLE_LINE_COMMENT;
+ case UnlinkedTokenType.SLASH:
+ return TokenType.SLASH;
+ case UnlinkedTokenType.SLASH_EQ:
+ return TokenType.SLASH_EQ;
+ case UnlinkedTokenType.SOURCE:
+ return Keyword.SOURCE;
+ case UnlinkedTokenType.STAR:
+ return TokenType.STAR;
+ case UnlinkedTokenType.STAR_EQ:
+ return TokenType.STAR_EQ;
+ case UnlinkedTokenType.STATIC:
+ return Keyword.STATIC;
+ case UnlinkedTokenType.STRING:
+ return TokenType.STRING;
+ case UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION:
+ return TokenType.STRING_INTERPOLATION_EXPRESSION;
+ case UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER:
+ return TokenType.STRING_INTERPOLATION_IDENTIFIER;
+ case UnlinkedTokenType.SUPER:
+ return Keyword.SUPER;
+ case UnlinkedTokenType.SWITCH:
+ return Keyword.SWITCH;
+ case UnlinkedTokenType.SYNC:
+ return Keyword.SYNC;
+ case UnlinkedTokenType.THIS:
+ return Keyword.THIS;
+ case UnlinkedTokenType.THROW:
+ return Keyword.THROW;
+ case UnlinkedTokenType.TILDE:
+ return TokenType.TILDE;
+ case UnlinkedTokenType.TILDE_SLASH:
+ return TokenType.TILDE_SLASH;
+ case UnlinkedTokenType.TILDE_SLASH_EQ:
+ return TokenType.TILDE_SLASH_EQ;
+ case UnlinkedTokenType.TRUE:
+ return Keyword.TRUE;
+ case UnlinkedTokenType.TRY:
+ return Keyword.TRY;
+ case UnlinkedTokenType.TYPEDEF:
+ return Keyword.TYPEDEF;
+ case UnlinkedTokenType.VAR:
+ return Keyword.VAR;
+ case UnlinkedTokenType.VOID:
+ return Keyword.VOID;
+ case UnlinkedTokenType.WHILE:
+ return Keyword.WHILE;
+ case UnlinkedTokenType.WITH:
+ return Keyword.WITH;
+ case UnlinkedTokenType.YIELD:
+ return Keyword.YIELD;
+ default:
+ throw StateError('Unexpected type: $type');
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/summary2/tokens_writer.dart b/pkg/analyzer/lib/src/summary2/tokens_writer.dart
new file mode 100644
index 0000000..3a9e989
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/tokens_writer.dart
@@ -0,0 +1,445 @@
+// Copyright (c) 2019, 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/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
+import 'package:meta/meta.dart';
+
+/// The result of writing a sequence of tokens.
+class TokensResult {
+ final UnlinkedTokensBuilder tokens;
+ final List<Token> _indexToToken;
+ final Map<Token, int> _tokenToIndex;
+
+ TokensResult(this.tokens, this._indexToToken, this._tokenToIndex);
+
+ TokensContext toContext() {
+ return TokensContext.fromResult(tokens, _indexToToken, _tokenToIndex);
+ }
+}
+
+class TokensWriter {
+ final UnlinkedTokensBuilder _tokens = UnlinkedTokensBuilder();
+ final List<Token> _indexToToken = [];
+ final Map<Token, int> _tokenToIndex = Map.identity();
+
+ TokensWriter() {
+ _addToken(
+ null,
+ isSynthetic: true,
+ kind: UnlinkedTokenKind.nothing,
+ length: 0,
+ lexeme: '',
+ offset: 0,
+ precedingComment: 0,
+ type: UnlinkedTokenType.NOTHING,
+ );
+ }
+
+ /// Write all the tokens from the [first] to the [last] inclusively.
+ TokensResult writeTokens(Token first, Token last) {
+ if (first is CommentToken) {
+ first = (first as CommentToken).parent;
+ }
+
+ var endGroupToBeginIndexMap = <Token, int>{};
+ var previousIndex = 0;
+ for (var token = first;; token = token.next) {
+ var index = _writeToken(token);
+
+ if (previousIndex != 0) {
+ _tokens.next[previousIndex] = index;
+ }
+ previousIndex = index;
+
+ if (token.endGroup != null) {
+ endGroupToBeginIndexMap[token.endGroup] = index;
+ }
+
+ var beginIndex = endGroupToBeginIndexMap[token];
+ if (beginIndex != null) {
+ _tokens.endGroup[beginIndex] = index;
+ }
+
+ if (token == last) break;
+ }
+
+ return TokensResult(_tokens, _indexToToken, _tokenToIndex);
+ }
+
+ int _addToken(
+ Token token, {
+ @required bool isSynthetic,
+ @required UnlinkedTokenKind kind,
+ @required int length,
+ @required String lexeme,
+ @required int offset,
+ @required int precedingComment,
+ @required UnlinkedTokenType type,
+ }) {
+ _tokens.endGroup.add(0);
+ _tokens.isSynthetic.add(isSynthetic);
+ _tokens.kind.add(kind);
+ _tokens.length.add(length);
+ _tokens.lexeme.add(lexeme);
+ _tokens.next.add(0);
+ _tokens.offset.add(offset);
+ _tokens.precedingComment.add(precedingComment);
+ _tokens.type.add(type);
+
+ var index = _indexToToken.length;
+ _indexToToken.add(token);
+ _tokenToIndex[token] = index;
+ return index;
+ }
+
+ int _writeCommentToken(CommentToken token) {
+ if (token == null) return 0;
+
+ int firstIndex = null;
+ var previousIndex = 0;
+ while (token != null) {
+ var index = _addToken(
+ token,
+ isSynthetic: false,
+ kind: UnlinkedTokenKind.comment,
+ length: token.length,
+ lexeme: token.lexeme,
+ offset: token.offset,
+ precedingComment: 0,
+ type: _astToBinaryTokenType(token.type),
+ );
+ firstIndex ??= index;
+
+ if (previousIndex != 0) {
+ _tokens.next[previousIndex] = index;
+ }
+ previousIndex = index;
+
+ token = token.next;
+ }
+
+ return firstIndex;
+ }
+
+ int _writeToken(Token token) {
+ assert(_tokenToIndex[token] == null);
+
+ var commentIndex = _writeCommentToken(token.precedingComments);
+
+ if (token is KeywordToken) {
+ return _addToken(
+ token,
+ isSynthetic: token.isSynthetic,
+ kind: UnlinkedTokenKind.keyword,
+ lexeme: token.lexeme,
+ offset: token.offset,
+ length: token.length,
+ precedingComment: commentIndex,
+ type: _astToBinaryTokenType(token.type),
+ );
+ } else if (token is StringToken) {
+ return _addToken(
+ token,
+ isSynthetic: token.isSynthetic,
+ kind: UnlinkedTokenKind.string,
+ lexeme: token.lexeme,
+ offset: token.offset,
+ length: token.length,
+ precedingComment: commentIndex,
+ type: _astToBinaryTokenType(token.type),
+ );
+ } else if (token is SimpleToken) {
+ return _addToken(
+ token,
+ isSynthetic: token.isSynthetic,
+ kind: UnlinkedTokenKind.simple,
+ lexeme: token.lexeme,
+ offset: token.offset,
+ length: token.length,
+ precedingComment: commentIndex,
+ type: _astToBinaryTokenType(token.type),
+ );
+ } else {
+ throw UnimplementedError('(${token.runtimeType}) $token');
+ }
+ }
+
+ static UnlinkedTokenType _astToBinaryTokenType(TokenType type) {
+ if (type == Keyword.ABSTRACT) {
+ return UnlinkedTokenType.ABSTRACT;
+ } else if (type == TokenType.AMPERSAND) {
+ return UnlinkedTokenType.AMPERSAND;
+ } else if (type == TokenType.AMPERSAND_AMPERSAND) {
+ return UnlinkedTokenType.AMPERSAND_AMPERSAND;
+ } else if (type == TokenType.AMPERSAND_EQ) {
+ return UnlinkedTokenType.AMPERSAND_EQ;
+ } else if (type == TokenType.AS) {
+ return UnlinkedTokenType.AS;
+ } else if (type == Keyword.ASSERT) {
+ return UnlinkedTokenType.ASSERT;
+ } else if (type == Keyword.ASYNC) {
+ return UnlinkedTokenType.ASYNC;
+ } else if (type == TokenType.AT) {
+ return UnlinkedTokenType.AT;
+ } else if (type == Keyword.AWAIT) {
+ return UnlinkedTokenType.AWAIT;
+ } else if (type == TokenType.BACKPING) {
+ return UnlinkedTokenType.BACKPING;
+ } else if (type == TokenType.BACKSLASH) {
+ return UnlinkedTokenType.BACKSLASH;
+ } else if (type == TokenType.BANG) {
+ return UnlinkedTokenType.BANG;
+ } else if (type == TokenType.BANG_EQ) {
+ return UnlinkedTokenType.BANG_EQ;
+ } else if (type == TokenType.BAR) {
+ return UnlinkedTokenType.BAR;
+ } else if (type == TokenType.BAR_BAR) {
+ return UnlinkedTokenType.BAR_BAR;
+ } else if (type == TokenType.BAR_EQ) {
+ return UnlinkedTokenType.BAR_EQ;
+ } else if (type == Keyword.BREAK) {
+ return UnlinkedTokenType.BREAK;
+ } else if (type == TokenType.CARET) {
+ return UnlinkedTokenType.CARET;
+ } else if (type == TokenType.CARET_EQ) {
+ return UnlinkedTokenType.CARET_EQ;
+ } else if (type == Keyword.CASE) {
+ return UnlinkedTokenType.CASE;
+ } else if (type == Keyword.CATCH) {
+ return UnlinkedTokenType.CATCH;
+ } else if (type == Keyword.CLASS) {
+ return UnlinkedTokenType.CLASS;
+ } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
+ return UnlinkedTokenType.CLOSE_CURLY_BRACKET;
+ } else if (type == TokenType.CLOSE_PAREN) {
+ return UnlinkedTokenType.CLOSE_PAREN;
+ } else if (type == TokenType.CLOSE_SQUARE_BRACKET) {
+ return UnlinkedTokenType.CLOSE_SQUARE_BRACKET;
+ } else if (type == TokenType.COLON) {
+ return UnlinkedTokenType.COLON;
+ } else if (type == TokenType.COMMA) {
+ return UnlinkedTokenType.COMMA;
+ } else if (type == Keyword.CONST) {
+ return UnlinkedTokenType.CONST;
+ } else if (type == Keyword.CONTINUE) {
+ return UnlinkedTokenType.CONTINUE;
+ } else if (type == Keyword.COVARIANT) {
+ return UnlinkedTokenType.COVARIANT;
+ } else if (type == Keyword.DEFAULT) {
+ return UnlinkedTokenType.DEFAULT;
+ } else if (type == Keyword.DEFERRED) {
+ return UnlinkedTokenType.DEFERRED;
+ } else if (type == Keyword.DO) {
+ return UnlinkedTokenType.DO;
+ } else if (type == TokenType.DOUBLE) {
+ return UnlinkedTokenType.DOUBLE;
+ } else if (type == Keyword.DYNAMIC) {
+ return UnlinkedTokenType.DYNAMIC;
+ } else if (type == Keyword.ELSE) {
+ return UnlinkedTokenType.ELSE;
+ } else if (type == Keyword.ENUM) {
+ return UnlinkedTokenType.ENUM;
+ } else if (type == TokenType.EOF) {
+ return UnlinkedTokenType.EOF;
+ } else if (type == TokenType.EQ) {
+ return UnlinkedTokenType.EQ;
+ } else if (type == TokenType.EQ_EQ) {
+ return UnlinkedTokenType.EQ_EQ;
+ } else if (type == Keyword.EXPORT) {
+ return UnlinkedTokenType.EXPORT;
+ } else if (type == Keyword.EXTENDS) {
+ return UnlinkedTokenType.EXTENDS;
+ } else if (type == Keyword.EXTERNAL) {
+ return UnlinkedTokenType.EXTERNAL;
+ } else if (type == Keyword.FACTORY) {
+ return UnlinkedTokenType.FACTORY;
+ } else if (type == Keyword.FALSE) {
+ return UnlinkedTokenType.FALSE;
+ } else if (type == Keyword.FINAL) {
+ return UnlinkedTokenType.FINAL;
+ } else if (type == Keyword.FINALLY) {
+ return UnlinkedTokenType.FINALLY;
+ } else if (type == Keyword.FOR) {
+ return UnlinkedTokenType.FOR;
+ } else if (type == Keyword.FUNCTION) {
+ return UnlinkedTokenType.FUNCTION_KEYWORD;
+ } else if (type == TokenType.FUNCTION) {
+ return UnlinkedTokenType.FUNCTION;
+ } else if (type == Keyword.GET) {
+ return UnlinkedTokenType.GET;
+ } else if (type == TokenType.GT) {
+ return UnlinkedTokenType.GT;
+ } else if (type == TokenType.GT_EQ) {
+ return UnlinkedTokenType.GT_EQ;
+ } else if (type == TokenType.GT_GT) {
+ return UnlinkedTokenType.GT_GT;
+ } else if (type == TokenType.GT_GT_EQ) {
+ return UnlinkedTokenType.GT_GT_EQ;
+ } else if (type == TokenType.HASH) {
+ return UnlinkedTokenType.HASH;
+ } else if (type == TokenType.HEXADECIMAL) {
+ return UnlinkedTokenType.HEXADECIMAL;
+ } else if (type == Keyword.HIDE) {
+ return UnlinkedTokenType.HIDE;
+ } else if (type == TokenType.IDENTIFIER) {
+ return UnlinkedTokenType.IDENTIFIER;
+ } else if (type == Keyword.IF) {
+ return UnlinkedTokenType.IF;
+ } else if (type == Keyword.IMPLEMENTS) {
+ return UnlinkedTokenType.IMPLEMENTS;
+ } else if (type == Keyword.IMPORT) {
+ return UnlinkedTokenType.IMPORT;
+ } else if (type == Keyword.IN) {
+ return UnlinkedTokenType.IN;
+ } else if (type == TokenType.INDEX) {
+ return UnlinkedTokenType.INDEX;
+ } else if (type == TokenType.INDEX_EQ) {
+ return UnlinkedTokenType.INDEX_EQ;
+ } else if (type == TokenType.INT) {
+ return UnlinkedTokenType.INT;
+ } else if (type == Keyword.INTERFACE) {
+ return UnlinkedTokenType.INTERFACE;
+ } else if (type == TokenType.IS) {
+ return UnlinkedTokenType.IS;
+ } else if (type == Keyword.LIBRARY) {
+ return UnlinkedTokenType.LIBRARY;
+ } else if (type == TokenType.LT) {
+ return UnlinkedTokenType.LT;
+ } else if (type == TokenType.LT_EQ) {
+ return UnlinkedTokenType.LT_EQ;
+ } else if (type == TokenType.LT_LT) {
+ return UnlinkedTokenType.LT_LT;
+ } else if (type == TokenType.LT_LT_EQ) {
+ return UnlinkedTokenType.LT_LT_EQ;
+ } else if (type == TokenType.MINUS) {
+ return UnlinkedTokenType.MINUS;
+ } else if (type == TokenType.MINUS_EQ) {
+ return UnlinkedTokenType.MINUS_EQ;
+ } else if (type == TokenType.MINUS_MINUS) {
+ return UnlinkedTokenType.MINUS_MINUS;
+ } else if (type == Keyword.MIXIN) {
+ return UnlinkedTokenType.MIXIN;
+ } else if (type == TokenType.MULTI_LINE_COMMENT) {
+ return UnlinkedTokenType.MULTI_LINE_COMMENT;
+ } else if (type == Keyword.NATIVE) {
+ return UnlinkedTokenType.NATIVE;
+ } else if (type == Keyword.NEW) {
+ return UnlinkedTokenType.NEW;
+ } else if (type == Keyword.NULL) {
+ return UnlinkedTokenType.NULL;
+ } else if (type == Keyword.OF) {
+ return UnlinkedTokenType.OF;
+ } else if (type == Keyword.ON) {
+ return UnlinkedTokenType.ON;
+ } else if (type == TokenType.OPEN_CURLY_BRACKET) {
+ return UnlinkedTokenType.OPEN_CURLY_BRACKET;
+ } else if (type == TokenType.OPEN_PAREN) {
+ return UnlinkedTokenType.OPEN_PAREN;
+ } else if (type == TokenType.OPEN_SQUARE_BRACKET) {
+ return UnlinkedTokenType.OPEN_SQUARE_BRACKET;
+ } else if (type == Keyword.OPERATOR) {
+ return UnlinkedTokenType.OPERATOR;
+ } else if (type == Keyword.PART) {
+ return UnlinkedTokenType.PART;
+ } else if (type == Keyword.PATCH) {
+ return UnlinkedTokenType.PATCH;
+ } else if (type == TokenType.PERCENT) {
+ return UnlinkedTokenType.PERCENT;
+ } else if (type == TokenType.PERCENT_EQ) {
+ return UnlinkedTokenType.PERCENT_EQ;
+ } else if (type == TokenType.PERIOD) {
+ return UnlinkedTokenType.PERIOD;
+ } else if (type == TokenType.PERIOD_PERIOD) {
+ return UnlinkedTokenType.PERIOD_PERIOD;
+ } else if (type == TokenType.PERIOD_PERIOD_PERIOD) {
+ return UnlinkedTokenType.PERIOD_PERIOD_PERIOD;
+ } else if (type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
+ return UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+ } else if (type == TokenType.PLUS) {
+ return UnlinkedTokenType.PLUS;
+ } else if (type == TokenType.PLUS_EQ) {
+ return UnlinkedTokenType.PLUS_EQ;
+ } else if (type == TokenType.PLUS_PLUS) {
+ return UnlinkedTokenType.PLUS_PLUS;
+ } else if (type == TokenType.QUESTION) {
+ return UnlinkedTokenType.QUESTION;
+ } else if (type == TokenType.QUESTION_PERIOD) {
+ return UnlinkedTokenType.QUESTION_PERIOD;
+ } else if (type == TokenType.QUESTION_QUESTION) {
+ return UnlinkedTokenType.QUESTION_QUESTION;
+ } else if (type == TokenType.QUESTION_QUESTION_EQ) {
+ return UnlinkedTokenType.QUESTION_QUESTION_EQ;
+ } else if (type == Keyword.RETHROW) {
+ return UnlinkedTokenType.RETHROW;
+ } else if (type == Keyword.RETURN) {
+ return UnlinkedTokenType.RETURN;
+ } else if (type == TokenType.SCRIPT_TAG) {
+ return UnlinkedTokenType.SCRIPT_TAG;
+ } else if (type == TokenType.SEMICOLON) {
+ return UnlinkedTokenType.SEMICOLON;
+ } else if (type == Keyword.SET) {
+ return UnlinkedTokenType.SET;
+ } else if (type == Keyword.SHOW) {
+ return UnlinkedTokenType.SHOW;
+ } else if (type == TokenType.SINGLE_LINE_COMMENT) {
+ return UnlinkedTokenType.SINGLE_LINE_COMMENT;
+ } else if (type == TokenType.SLASH) {
+ return UnlinkedTokenType.SLASH;
+ } else if (type == TokenType.SLASH_EQ) {
+ return UnlinkedTokenType.SLASH_EQ;
+ } else if (type == Keyword.SOURCE) {
+ return UnlinkedTokenType.SOURCE;
+ } else if (type == TokenType.STAR) {
+ return UnlinkedTokenType.STAR;
+ } else if (type == TokenType.STAR_EQ) {
+ return UnlinkedTokenType.STAR_EQ;
+ } else if (type == Keyword.STATIC) {
+ return UnlinkedTokenType.STATIC;
+ } else if (type == TokenType.STRING) {
+ return UnlinkedTokenType.STRING;
+ } else if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
+ return UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION;
+ } else if (type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
+ return UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER;
+ } else if (type == Keyword.SUPER) {
+ return UnlinkedTokenType.SUPER;
+ } else if (type == Keyword.SWITCH) {
+ return UnlinkedTokenType.SWITCH;
+ } else if (type == Keyword.SYNC) {
+ return UnlinkedTokenType.SYNC;
+ } else if (type == Keyword.THIS) {
+ return UnlinkedTokenType.THIS;
+ } else if (type == Keyword.THROW) {
+ return UnlinkedTokenType.THROW;
+ } else if (type == TokenType.TILDE) {
+ return UnlinkedTokenType.TILDE;
+ } else if (type == TokenType.TILDE_SLASH) {
+ return UnlinkedTokenType.TILDE_SLASH;
+ } else if (type == TokenType.TILDE_SLASH_EQ) {
+ return UnlinkedTokenType.TILDE_SLASH_EQ;
+ } else if (type == Keyword.TRUE) {
+ return UnlinkedTokenType.TRUE;
+ } else if (type == Keyword.TRY) {
+ return UnlinkedTokenType.TRY;
+ } else if (type == Keyword.TYPEDEF) {
+ return UnlinkedTokenType.TYPEDEF;
+ } else if (type == Keyword.VAR) {
+ return UnlinkedTokenType.VAR;
+ } else if (type == Keyword.VOID) {
+ return UnlinkedTokenType.VOID;
+ } else if (type == Keyword.WHILE) {
+ return UnlinkedTokenType.WHILE;
+ } else if (type == Keyword.WITH) {
+ return UnlinkedTokenType.WITH;
+ } else if (type == Keyword.YIELD) {
+ return UnlinkedTokenType.YIELD;
+ } else {
+ throw StateError('Unexpected type: $type');
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
new file mode 100644
index 0000000..def0f8d
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -0,0 +1,176 @@
+// Copyright (c) 2019, 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/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_resolver.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+DartType _dynamicIfNull(DartType type) {
+ if (type == null || type.isBottom || type.isDartCoreNull) {
+ return DynamicTypeImpl.instance;
+ }
+ return type;
+}
+
+class TopLevelInference {
+ final Linker linker;
+ final Reference libraryRef;
+ final UnitBuilder unit;
+
+ TopLevelInference(this.linker, this.libraryRef, this.unit);
+
+ void infer() {
+ _inferFieldsTemporary();
+ _inferConstructorFieldFormals();
+ }
+
+ void _inferConstructorFieldFormals() {
+ _visitClassList((unitDeclaration) {
+ var members = unitDeclaration.classOrMixinDeclaration_members;
+
+ var fields = <String, LinkedNodeType>{};
+ _visitClassFields(unitDeclaration, (field) {
+ var name = unit.context.getVariableName(field);
+ var type = field.variableDeclaration_type2;
+ if (type == null) {
+ throw StateError('Field $name should have a type.');
+ }
+ fields[name] = type;
+ });
+
+ for (var member in members) {
+ if (member.kind == LinkedNodeKind.constructorDeclaration) {
+ for (var parameter in member.constructorDeclaration_parameters
+ .formalParameterList_parameters) {
+ if (parameter.kind == LinkedNodeKind.fieldFormalParameter &&
+ parameter.fieldFormalParameter_type2 == null) {
+ var name = unit.context.getSimpleName(
+ parameter.normalFormalParameter_identifier,
+ );
+ var type = fields[name];
+ if (type == null) {
+ type = LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.dynamic_,
+ );
+ }
+ parameter.fieldFormalParameter_type2 = type;
+ }
+ }
+ }
+ }
+ });
+ }
+
+ void _inferFieldsTemporary() {
+ var unitDeclarations = unit.node.compilationUnit_declarations;
+ for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
+ if (unitDeclaration.kind == LinkedNodeKind.classDeclaration) {
+ _visitClassFields(unitDeclaration, (field) {
+ var name = unit.context.getVariableName(field);
+ // TODO(scheglov) Use inheritance
+ if (field.variableDeclaration_type2 == null) {
+ field.variableDeclaration_type2 = LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.dynamic_,
+ );
+ }
+ });
+
+ var members = unitDeclaration.classOrMixinDeclaration_members;
+ for (var member in members) {
+ if (member.kind == LinkedNodeKind.methodDeclaration) {
+ // TODO(scheglov) Use inheritance
+ if (member.methodDeclaration_returnType2 == null) {
+ if (unit.context.isSetter(member)) {
+ member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.void_,
+ );
+ } else {
+ member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.dynamic_,
+ );
+ }
+ }
+ }
+ }
+ } else if (unitDeclaration.kind == LinkedNodeKind.functionDeclaration) {
+ if (unit.context.isSetter(unitDeclaration)) {
+ unitDeclaration.functionDeclaration_returnType2 =
+ LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.void_,
+ );
+ }
+ } else if (unitDeclaration.kind ==
+ LinkedNodeKind.topLevelVariableDeclaration) {
+ var variableList =
+ unitDeclaration.topLevelVariableDeclaration_variableList;
+ for (var variable in variableList.variableDeclarationList_variables) {
+ // TODO(scheglov) infer in the correct order
+ if (variable.variableDeclaration_type2 == null ||
+ unit.context.isConst(variable)) {
+ _inferVariableTypeFromInitializerTemporary(variable);
+ }
+ }
+ }
+ }
+ }
+
+ void _inferVariableTypeFromInitializerTemporary(LinkedNodeBuilder node) {
+ var unresolvedNode = node.variableDeclaration_initializer;
+
+ if (unresolvedNode == null) {
+ node.variableDeclaration_type2 = LinkedNodeTypeBuilder(
+ kind: LinkedNodeTypeKind.dynamic_,
+ );
+ return;
+ }
+
+ var expression = unit.context.readInitializer(node);
+ astFactory.expressionFunctionBody(null, null, expression, null);
+
+ // TODO(scheglov) can be shared for the whole library
+ var astResolver = AstResolver(linker, libraryRef);
+
+ var resolvedNode = astResolver.resolve(unit, expression);
+ node.variableDeclaration_initializer = resolvedNode;
+
+ if (node.variableDeclaration_type2 == null) {
+ var initializerType = expression.staticType;
+ initializerType = _dynamicIfNull(initializerType);
+
+ var linkingBundleContext = linker.linkingBundleContext;
+ node.variableDeclaration_type2 = linkingBundleContext.writeType(
+ initializerType,
+ );
+ }
+ }
+
+ void _visitClassFields(
+ LinkedNode class_, void Function(LinkedNodeBuilder) f) {
+ var members = class_.classOrMixinDeclaration_members;
+
+ for (var member in members) {
+ if (member.kind == LinkedNodeKind.fieldDeclaration) {
+ var variableList = member.fieldDeclaration_fields;
+ for (var field in variableList.variableDeclarationList_variables) {
+ f(field);
+ }
+ }
+ }
+ }
+
+ void _visitClassList(void Function(LinkedNodeBuilder) f) {
+ var unitDeclarations = unit.node.compilationUnit_declarations;
+ for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
+ if (unitDeclaration.kind == LinkedNodeKind.classDeclaration) {
+ f(unitDeclaration);
+ }
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/task/api/dart.dart b/pkg/analyzer/lib/src/task/api/dart.dart
index f1f19e6..82f6bfc 100644
--- a/pkg/analyzer/lib/src/task/api/dart.dart
+++ b/pkg/analyzer/lib/src/task/api/dart.dart
@@ -9,7 +9,6 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
/**
* The analysis errors associated with a [Source] representing a compilation
@@ -89,8 +88,7 @@
* The result is only available for [Source]s representing a compilation unit.
*/
final ResultDescriptor<CompilationUnit> PARSED_UNIT =
- new ResultDescriptor<CompilationUnit>('PARSED_UNIT', null,
- cachingPolicy: AST_CACHING_POLICY);
+ new ResultDescriptor<CompilationUnit>('PARSED_UNIT', null);
/**
* The resolved [CompilationUnit] associated with a compilation unit, with
@@ -99,8 +97,7 @@
* The result is only available for [LibrarySpecificUnit]s.
*/
final ResultDescriptor<CompilationUnit> RESOLVED_UNIT =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT', null,
- cachingPolicy: AST_CACHING_POLICY);
+ new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT', null);
/**
* The kind of a [Source].
@@ -116,9 +113,8 @@
*
* The result is only available for [Source]s representing a compilation unit.
*/
-final ResultDescriptor<Token> TOKEN_STREAM = new ResultDescriptor<Token>(
- 'TOKEN_STREAM', null,
- cachingPolicy: TOKEN_STREAM_CACHING_POLICY);
+final ResultDescriptor<Token> TOKEN_STREAM =
+ new ResultDescriptor<Token>('TOKEN_STREAM', null);
/**
* The sources of the Dart files that a library consists of.
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
deleted file mode 100644
index 47c7c65..0000000
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ /dev/null
@@ -1,5778 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:collection';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_resolution_map.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/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/dart/ast/ast.dart'
- show
- CompilationUnitImpl,
- NamespaceDirectiveImpl,
- UriBasedDirectiveImpl,
- UriValidationCode;
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/constant/constant_verifier.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/dart/sdk/patch.dart';
-import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/error/inheritance_override.dart';
-import 'package:analyzer/src/error/pending_error.dart';
-import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/declaration_resolver.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error_verifier.dart';
-import 'package:analyzer/src/generated/incremental_resolver.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/resolver.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/plugin/engine_plugin.dart';
-import 'package:analyzer/src/services/lint.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/driver.dart';
-import 'package:analyzer/src/task/general.dart';
-import 'package:analyzer/src/task/inputs.dart';
-import 'package:analyzer/src/task/model.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
-import 'package:analyzer/src/task/strong_mode.dart';
-
-/**
- * The [ResultCachingPolicy] for ASTs.
- */
-const ResultCachingPolicy AST_CACHING_POLICY =
- const SimpleResultCachingPolicy(1024 * 64, 32);
-
-/**
- * The [ResultCachingPolicy] for lists of [ConstantEvaluationTarget]s.
- */
-const ResultCachingPolicy CONSTANT_EVALUATION_TARGET_LIST_POLICY =
- const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The [ResultCachingPolicy] for [ConstantEvaluationTarget]s.
- */
-const ResultCachingPolicy CONSTANT_EVALUATION_TARGET_POLICY =
- const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The [ResultCachingPolicy] for [Element]s.
- */
-const ResultCachingPolicy ELEMENT_CACHING_POLICY =
- const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The [ResultCachingPolicy] for [TOKEN_STREAM].
- */
-const ResultCachingPolicy TOKEN_STREAM_CACHING_POLICY =
- const SimpleResultCachingPolicy(1, 1);
-
-/**
- * The [ResultCachingPolicy] for [UsedImportedElements]s.
- */
-const ResultCachingPolicy USED_IMPORTED_ELEMENTS_POLICY =
- const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The [ResultCachingPolicy] for [UsedLocalElements]s.
- */
-const ResultCachingPolicy USED_LOCAL_ELEMENTS_POLICY =
- const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The errors produced while building a library's directives.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<AnalysisError> BUILD_DIRECTIVES_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'BUILD_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS);
-/**
- * The errors produced while building a library element.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<AnalysisError> BUILD_LIBRARY_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * A list of the [ConstantEvaluationTarget]s defined in a unit. This includes
- * constants defined at top level, statically inside classes, and local to
- * functions, as well as constant constructors, annotations, and default values
- * of parameters.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<ConstantEvaluationTarget>
- COMPILATION_UNIT_CONSTANTS =
- new ListResultDescriptor<ConstantEvaluationTarget>(
- 'COMPILATION_UNIT_CONSTANTS', null,
- cachingPolicy: CONSTANT_EVALUATION_TARGET_LIST_POLICY);
-
-/**
- * The element model associated with a single compilation unit.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnitElement> COMPILATION_UNIT_ELEMENT =
- new ResultDescriptor<CompilationUnitElement>(
- 'COMPILATION_UNIT_ELEMENT', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The list of [ConstantEvaluationTarget]s on which the target constant element
- * depends.
- *
- * The result is only available for targets representing a
- * [ConstantEvaluationTarget] (i.e. a constant variable declaration, a constant
- * constructor, or a parameter element with a default value).
- */
-final ListResultDescriptor<ConstantEvaluationTarget> CONSTANT_DEPENDENCIES =
- new ListResultDescriptor<ConstantEvaluationTarget>(
- 'CONSTANT_DEPENDENCIES', const <ConstantEvaluationTarget>[]);
-
-/**
- * The flag specifying that the target constant element expression AST is
- * resolved, i.e. identifiers have all required elements set.
- *
- * The result is only available for targets representing a
- * [ConstantEvaluationTarget] (i.e. a constant variable declaration, a constant
- * constructor, or a parameter element with a default value).
- */
-final ResultDescriptor<bool> CONSTANT_EXPRESSION_RESOLVED =
- new ResultDescriptor<bool>('CONSTANT_EXPRESSION_RESOLVED', false);
-
-/**
- * The list of [ConstantEvaluationTarget]s on which constant expressions of a
- * unit depend.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<ConstantEvaluationTarget>
- CONSTANT_EXPRESSIONS_DEPENDENCIES =
- new ListResultDescriptor<ConstantEvaluationTarget>(
- 'CONSTANT_EXPRESSIONS_DEPENDENCIES',
- const <ConstantEvaluationTarget>[]);
-
-/**
- * A [ConstantEvaluationTarget] that has been successfully constant-evaluated.
- *
- * TODO(paulberry): is ELEMENT_CACHING_POLICY the correct caching policy?
- *
- * The result is only available for [ConstantEvaluationTarget]s.
- *
- */
-final ResultDescriptor<ConstantEvaluationTarget> CONSTANT_VALUE =
- new ResultDescriptor<ConstantEvaluationTarget>('CONSTANT_VALUE', null,
- cachingPolicy: CONSTANT_EVALUATION_TARGET_POLICY);
-
-/**
- * The sources representing the libraries that include a given source as a part.
- *
- * The result is only available for [Source]s representing a compilation unit.
- */
-final ListResultDescriptor<Source> CONTAINING_LIBRARIES =
- new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', const <Source>[]);
-
-/**
- * The flag specifying that [RESOLVED_UNIT] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT1] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT1 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT1', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT10] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT10 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT10', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT11] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT11 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT11', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT12] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT12 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT12', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT2] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT2 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT2', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT3] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT3 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT3', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT4] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT4 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT4', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT5] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT5 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT5', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT6] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT6 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT6', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT7] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT7 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT7', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT8] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT8 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT8', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT9] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT9 =
- new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT9', false);
-
-/**
- * All [AnalysisError]s results for [Source]s.
- */
-final List<ListResultDescriptor<AnalysisError>> ERROR_SOURCE_RESULTS =
- <ListResultDescriptor<AnalysisError>>[
- BUILD_DIRECTIVES_ERRORS,
- BUILD_LIBRARY_ERRORS,
- PARSE_ERRORS,
- SCAN_ERRORS,
-];
-
-/**
- * All [AnalysisError]s results in for [LibrarySpecificUnit]s.
- */
-final List<ListResultDescriptor<AnalysisError>> ERROR_UNIT_RESULTS =
- <ListResultDescriptor<AnalysisError>>[
- HINTS,
- LIBRARY_UNIT_ERRORS,
- LINTS,
- RESOLVE_DIRECTIVES_ERRORS,
- RESOLVE_TYPE_BOUNDS_ERRORS,
- RESOLVE_TYPE_NAMES_ERRORS,
- RESOLVE_UNIT_ERRORS,
- STRONG_MODE_ERRORS,
- VARIABLE_REFERENCE_ERRORS,
- VERIFY_ERRORS
-];
-
-/**
- * The sources representing the export closure of a library.
- * The [Source]s include only library sources, not their units.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<Source> EXPORT_SOURCE_CLOSURE =
- new ListResultDescriptor<Source>('EXPORT_SOURCE_CLOSURE', null);
-
-/**
- * The errors produced while generating hints a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> HINTS =
- new ListResultDescriptor<AnalysisError>(
- 'HINT_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The ignore information for a [Source].
- */
-final ResultDescriptor<IgnoreInfo> IGNORE_INFO =
- new ResultDescriptor<IgnoreInfo>('IGNORE_INFO', null);
-
-/**
- * A list of the [VariableElement]s whose type should be inferred that another
- * inferable static variable (the target) depends on.
- *
- * The result is only available for [VariableElement]s, and only when strong
- * mode is enabled.
- */
-final ListResultDescriptor<VariableElement>
- INFERABLE_STATIC_VARIABLE_DEPENDENCIES =
- new ListResultDescriptor<VariableElement>(
- 'INFERABLE_STATIC_VARIABLE_DEPENDENCIES', null);
-
-/**
- * A list of the [VariableElement]s defined in a unit whose type should be
- * inferred. This includes variables defined at the library level as well as
- * static members inside classes.
- *
- * The result is only available for [LibrarySpecificUnit]s, and only when strong
- * mode is enabled.
- */
-final ListResultDescriptor<VariableElement> INFERABLE_STATIC_VARIABLES_IN_UNIT =
- new ListResultDescriptor<VariableElement>(
- 'INFERABLE_STATIC_VARIABLES_IN_UNIT', null);
-
-/**
- * An inferable static variable ([VariableElement]) whose type has been
- * inferred.
- *
- * The result is only available for [VariableElement]s, and only when strong
- * mode is enabled.
- */
-final ResultDescriptor<VariableElement> INFERRED_STATIC_VARIABLE =
- new ResultDescriptor<VariableElement>('INFERRED_STATIC_VARIABLE', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * A list of the [LibraryElement]s that make up the strongly connected
- * component in the import/export graph in which the target resides.
- *
- * Only non-empty in strongMode.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<LibraryElement> LIBRARY_CYCLE =
- new ListResultDescriptor<LibraryElement>('LIBRARY_CYCLE', null);
-
-/**
- * A list of the [LibrarySpecificUnit]s that comprise all of the parts and
- * libraries in the direct import/export dependencies of the library cycle
- * of the target, with the intra-component dependencies excluded.
- *
- * Only non-empty in strongMode.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_CYCLE_DEPENDENCIES =
- new ListResultDescriptor<LibrarySpecificUnit>(
- 'LIBRARY_CYCLE_DEPENDENCIES', null);
-
-/**
- * A list of the [LibrarySpecificUnit]s (including all parts) that make up
- * the strongly connected component in the import/export graph in which the
- * target resides.
- *
- * Only non-empty in strongMode.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_CYCLE_UNITS =
- new ListResultDescriptor<LibrarySpecificUnit>('LIBRARY_CYCLE_UNITS', null);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * The [LibraryElement] and its [CompilationUnitElement]s are attached to each
- * other. Directives 'library', 'part' and 'part of' are resolved.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT1 =
- new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT1', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * In addition to [LIBRARY_ELEMENT1] also [LibraryElement.imports] and
- * [LibraryElement.exports] are set.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT2 =
- new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT2', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * In addition to [LIBRARY_ELEMENT2] the [LibraryElement.publicNamespace] is set.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT3 =
- new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT3', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * In addition to [LIBRARY_ELEMENT3] the [LibraryElement.entryPoint] is set,
- * if the library does not declare one already and one of the exported
- * libraries exports one.
- *
- * Also [LibraryElement.exportNamespace] is set.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT4 =
- new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT4', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * [LIBRARY_ELEMENT5] plus resolved types type parameter bounds.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT5 =
- new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT5', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * [LIBRARY_ELEMENT5] plus resolved types for every element.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT6 =
- new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT6', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * [LIBRARY_ELEMENT6] plus [RESOLVED_UNIT7] for all library units.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT7 =
- new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT7', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * [LIBRARY_ELEMENT7] for the library and its import/export closure.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT8 =
- new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT8', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * The same as a [LIBRARY_ELEMENT8].
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT9 =
- new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT9', null,
- cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * List of all `LIBRARY_ELEMENT` results.
- */
-final List<ResultDescriptor<LibraryElement>> LIBRARY_ELEMENT_RESULTS =
- <ResultDescriptor<LibraryElement>>[
- LIBRARY_ELEMENT1,
- LIBRARY_ELEMENT2,
- LIBRARY_ELEMENT3,
- LIBRARY_ELEMENT4,
- LIBRARY_ELEMENT5,
- LIBRARY_ELEMENT6,
- LIBRARY_ELEMENT7,
- LIBRARY_ELEMENT8,
- LIBRARY_ELEMENT9,
- LIBRARY_ELEMENT
-];
-
-/**
- * The flag specifying whether all analysis errors are computed in a specific
- * library.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> LIBRARY_ERRORS_READY =
- new ResultDescriptor<bool>('LIBRARY_ERRORS_READY', false);
-
-/**
- * The [LibrarySpecificUnit]s that a library consists of.
- *
- * The list will include the defining unit and units for [INCLUDED_PARTS].
- * So, it is never empty or `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_SPECIFIC_UNITS =
- new ListResultDescriptor<LibrarySpecificUnit>(
- 'LIBRARY_SPECIFIC_UNITS', const <LibrarySpecificUnit>[]);
-
-/**
- * The analysis errors associated with a compilation unit in a specific library.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> LIBRARY_UNIT_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'LIBRARY_UNIT_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while generating lints for a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> LINTS =
- new ListResultDescriptor<AnalysisError>(
- 'LINT_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while parsing a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a compilation unit.
- */
-final ListResultDescriptor<AnalysisError> PARSE_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'PARSE_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The list of [PendingError]s for a compilation unit.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<PendingError> PENDING_ERRORS =
- new ListResultDescriptor<PendingError>(
- 'PENDING_ERRORS', const <PendingError>[]);
-
-/**
- * The flag specifying that [LIBRARY_ELEMENT2] is ready for a library and its
- * import/export closure.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> READY_LIBRARY_ELEMENT2 =
- new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT2', false);
-
-/**
- * The flag specifying that [LIBRARY_ELEMENT6] is ready for a library and its
- * import/export closure.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> READY_LIBRARY_ELEMENT6 =
- new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT6', false);
-
-/**
- * The flag specifying that [LIBRARY_ELEMENT7] is ready for a library and its
- * import/export closure.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> READY_LIBRARY_ELEMENT7 =
- new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT7', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT] is ready for all of the units of a
- * library.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> READY_RESOLVED_UNIT =
- new ResultDescriptor<bool>('READY_RESOLVED_UNIT', false);
-
-/**
- * The sources of the Dart files that a library references.
- *
- * The list is the union of [IMPORTED_LIBRARIES], [EXPORTED_LIBRARIES] and
- * [UNITS] of the defining unit and [INCLUDED_PARTS]. Never empty or `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<Source> REFERENCED_SOURCES =
- new ListResultDescriptor<Source>('REFERENCED_SOURCES', const <Source>[]);
-
-/**
- * The list of [ConstantEvaluationTarget]s on which error verification depends.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<ConstantEvaluationTarget> REQUIRED_CONSTANTS =
- new ListResultDescriptor<ConstantEvaluationTarget>(
- 'REQUIRED_CONSTANTS', const <ConstantEvaluationTarget>[]);
-
-/**
- * The errors produced while resolving a library's directives.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<AnalysisError> RESOLVE_DIRECTIVES_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'RESOLVE_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while resolving bounds of type parameters of classes,
- * class and function aliases.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> RESOLVE_TYPE_BOUNDS_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'RESOLVE_TYPE_BOUNDS_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while resolving type names.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> RESOLVE_TYPE_NAMES_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'RESOLVE_TYPE_NAMES_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while resolving a full compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> RESOLVE_UNIT_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'RESOLVE_UNIT_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * Tasks that use this value as an input can assume that the [SimpleIdentifier]s
- * at all declaration sites have been bound to the element defined by the
- * declaration, except for the constants defined in an 'enum' declaration.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT1 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT1', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The resolved [CompilationUnit] associated with a compilation unit in which
- * the types of class members have been inferred in addition to everything that
- * is true of a [RESOLVED_UNIT9].
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT10 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT10', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The resolved [CompilationUnit] associated with a compilation unit, with
- * constants not yet resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT11 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT11', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The resolved [CompilationUnit] associated with a compilation unit, with
- * constants resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT12 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT12', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT1], tasks that use this value
- * as an input can assume that its directives have been resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT2 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT2', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * Tasks that use this value as an input can assume that the [SimpleIdentifier]s
- * at all declaration sites have been bound to the element defined by the
- * declaration, including the constants defined in an 'enum' declaration.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT3 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT3', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT3], tasks that use this value
- * as an input can assume that the types associated with type bounds have been
- * resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT4 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT4', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT4], tasks that use this value
- * as an input can assume that the types associated with declarations have been
- * resolved. This includes the types of superclasses, mixins, interfaces,
- * fields, return types, parameters, and local variables.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT5 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT5', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT5], tasks that use this value
- * as an input can assume that references to local variables and formal
- * parameters have been resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT6 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT6', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT6], tasks that use this value
- * as an input can assume that elements and types associated with expressions
- * outside of method bodies (essentially initializers) have been initially
- * resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT7 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT7', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT7], tasks that use this value
- * as an input can assume that the types of static variables have been inferred.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT8 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT8', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT8], tasks that use this value
- * as an input can assume that the initializers of instance variables have been
- * re-resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT9 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT9', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * List of all `RESOLVED_UNITx` results.
- */
-final List<ResultDescriptor<CompilationUnit>> RESOLVED_UNIT_RESULTS =
- <ResultDescriptor<CompilationUnit>>[
- RESOLVED_UNIT1,
- RESOLVED_UNIT2,
- RESOLVED_UNIT3,
- RESOLVED_UNIT4,
- RESOLVED_UNIT5,
- RESOLVED_UNIT6,
- RESOLVED_UNIT7,
- RESOLVED_UNIT8,
- RESOLVED_UNIT9,
- RESOLVED_UNIT10,
- RESOLVED_UNIT11,
- RESOLVED_UNIT12,
- RESOLVED_UNIT
-];
-
-/**
- * The errors produced while scanning a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a compilation unit.
- */
-final ListResultDescriptor<AnalysisError> SCAN_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'SCAN_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while resolving a static [VariableElement] initializer.
- *
- * The result is only available for [VariableElement]s, and only when strong
- * mode is enabled.
- */
-final ListResultDescriptor<AnalysisError> STATIC_VARIABLE_RESOLUTION_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'STATIC_VARIABLE_RESOLUTION_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * A list of the [AnalysisError]s reported while resolving static
- * [INFERABLE_STATIC_VARIABLES_IN_UNIT] defined in a unit.
- *
- * The result is only available for [LibrarySpecificUnit]s, and only when strong
- * mode is enabled.
- */
-final ListResultDescriptor<AnalysisError>
- STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT =
- new ListResultDescriptor<AnalysisError>(
- 'STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT', AnalysisError.NO_ERRORS);
-
-/**
- * The additional strong mode errors produced while verifying a
- * compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnits]s representing a
- * compilation unit.
- *
- */
-final ListResultDescriptor<AnalysisError> STRONG_MODE_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'STRONG_MODE_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The [TypeProvider] of the [AnalysisContext].
- */
-final ResultDescriptor<TypeProvider> TYPE_PROVIDER =
- new ResultDescriptor<TypeProvider>('TYPE_PROVIDER', null);
-
-/**
- * The [UsedImportedElements] of a [LibrarySpecificUnit].
- */
-final ResultDescriptor<UsedImportedElements> USED_IMPORTED_ELEMENTS =
- new ResultDescriptor<UsedImportedElements>('USED_IMPORTED_ELEMENTS', null,
- cachingPolicy: USED_IMPORTED_ELEMENTS_POLICY);
-
-/**
- * The [UsedLocalElements] of a [LibrarySpecificUnit].
- */
-final ResultDescriptor<UsedLocalElements> USED_LOCAL_ELEMENTS =
- new ResultDescriptor<UsedLocalElements>('USED_LOCAL_ELEMENTS', null,
- cachingPolicy: USED_LOCAL_ELEMENTS_POLICY);
-
-/**
- * The errors produced while resolving variable references in a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> VARIABLE_REFERENCE_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'VARIABLE_REFERENCE_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while verifying a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> VERIFY_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'VERIFY_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * Return a list of unique errors for the [Source] of the given [target].
- */
-List<AnalysisError> getTargetSourceErrors(
- RecordingErrorListener listener, AnalysisTarget target) {
- Source source = target.source;
- List<AnalysisError> errors = listener.getErrorsForSource(source);
- return getUniqueErrors(errors);
-}
-
-/**
- * Return a list of errors containing the errors from the given [errors] list
- * but with duplications removed.
- */
-List<AnalysisError> getUniqueErrors(List<AnalysisError> errors) {
- if (errors.isEmpty) {
- return errors;
- }
- return errors.toSet().toList();
-}
-
-/**
- * A task that builds a compilation unit element for a single compilation unit.
- */
-class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the AST for the compilation unit.
- */
- static const String PARSED_UNIT_INPUT_NAME = 'PARSED_UNIT_INPUT_NAME';
-
- /**
- * The name of the input whose value is the source line info.
- */
- static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'BuildCompilationUnitElementTask',
- createTask,
- buildInputs, <ResultDescriptor>[
- COMPILATION_UNIT_CONSTANTS,
- COMPILATION_UNIT_ELEMENT,
- CREATED_RESOLVED_UNIT1,
- RESOLVED_UNIT1
- ]);
-
- /**
- * Initialize a newly created task to build a compilation unit element for
- * the given [target] in the given [context].
- */
- BuildCompilationUnitElementTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibrarySpecificUnit librarySpecificUnit = target;
- Source source = getRequiredSource();
- CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME);
- LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
- //
- // Try to get the existing CompilationUnitElement.
- //
- CompilationUnitElement element;
- {
- InternalAnalysisContext internalContext =
- context as InternalAnalysisContext;
- AnalysisCache analysisCache = internalContext.analysisCache;
- CacheEntry cacheEntry = internalContext.getCacheEntry(target);
- element = analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
- if (element == null &&
- internalContext.aboutToComputeResult(
- cacheEntry, COMPILATION_UNIT_ELEMENT)) {
- element = analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
- }
- }
- //
- // Build or reuse CompilationUnitElement.
- //
- if (element == null) {
- CompilationUnitBuilder builder = new CompilationUnitBuilder();
- element = builder.buildCompilationUnit(
- source, unit, librarySpecificUnit.library);
- (element as CompilationUnitElementImpl).lineInfo = lineInfo;
- } else {
- new DeclarationResolver().resolve(unit, element);
- }
- //
- // Prepare constants.
- //
- ConstantFinder constantFinder = new ConstantFinder();
- unit.accept(constantFinder);
- List<ConstantEvaluationTarget> constants =
- constantFinder.constantsToCompute;
- //
- // Record outputs.
- //
- outputs[COMPILATION_UNIT_CONSTANTS] = constants;
- outputs[COMPILATION_UNIT_ELEMENT] = element;
- outputs[RESOLVED_UNIT1] = unit;
- outputs[CREATED_RESOLVED_UNIT1] = true;
- }
-
- /**
- * 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
- * [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- PARSED_UNIT_INPUT_NAME: PARSED_UNIT.of(unit.unit, flushOnAccess: true),
- LINE_INFO_INPUT_NAME: LINE_INFO.of(unit.unit)
- };
- }
-
- /**
- * Create a [BuildCompilationUnitElementTask] based on the given [target] in
- * the given [context].
- */
- static BuildCompilationUnitElementTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new BuildCompilationUnitElementTask(context, target);
- }
-}
-
-/**
- * A task that builds imports and export directive elements for a library.
- */
-class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the defining [LIBRARY_ELEMENT1].
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the input for [RESOLVED_UNIT1] of a library unit.
- */
- static const String UNIT_INPUT_NAME = 'UNIT_INPUT_NAME';
-
- /**
- * The input with a map from referenced sources to their modification times.
- */
- static const String SOURCES_MODIFICATION_TIME_INPUT_NAME =
- 'SOURCES_MODIFICATION_TIME_INPUT_NAME';
-
- /**
- * The input with a list of [LIBRARY_ELEMENT3]s of imported libraries.
- */
- static const String IMPORTS_LIBRARY_ELEMENT_INPUT_NAME =
- 'IMPORTS_LIBRARY_ELEMENT1_INPUT_NAME';
-
- /**
- * The input with a list of [LIBRARY_ELEMENT3]s of exported libraries.
- */
- static const String EXPORTS_LIBRARY_ELEMENT_INPUT_NAME =
- 'EXPORTS_LIBRARY_ELEMENT_INPUT_NAME';
-
- /**
- * The input with a list of [SOURCE_KIND]s of imported libraries.
- */
- static const String IMPORTS_SOURCE_KIND_INPUT_NAME =
- 'IMPORTS_SOURCE_KIND_INPUT_NAME';
-
- /**
- * The input with a list of [SOURCE_KIND]s of exported libraries.
- */
- static const String EXPORTS_SOURCE_KIND_INPUT_NAME =
- 'EXPORTS_SOURCE_KIND_INPUT_NAME';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'BuildDirectiveElementsTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ELEMENT2, BUILD_DIRECTIVES_ERRORS]);
-
- BuildDirectiveElementsTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibraryElementImpl libraryElement = getRequiredInput(LIBRARY_INPUT);
- CompilationUnit libraryUnit = getRequiredInput(UNIT_INPUT_NAME);
- Map<Source, int> sourceModificationTimeMap =
- getRequiredInput(SOURCES_MODIFICATION_TIME_INPUT_NAME);
- Map<Source, LibraryElement> importLibraryMap =
- getRequiredInput(IMPORTS_LIBRARY_ELEMENT_INPUT_NAME);
- Map<Source, LibraryElement> exportLibraryMap =
- getRequiredInput(EXPORTS_LIBRARY_ELEMENT_INPUT_NAME);
- Map<Source, SourceKind> importSourceKindMap =
- getRequiredInput(IMPORTS_SOURCE_KIND_INPUT_NAME);
- Map<Source, SourceKind> exportSourceKindMap =
- getRequiredInput(EXPORTS_SOURCE_KIND_INPUT_NAME);
- //
- // Try to get the existing LibraryElement.
- //
- LibraryElement element;
- {
- InternalAnalysisContext internalContext =
- context as InternalAnalysisContext;
- AnalysisCache analysisCache = internalContext.analysisCache;
- CacheEntry cacheEntry = internalContext.getCacheEntry(target);
- element = analysisCache.getValue(target, LIBRARY_ELEMENT2);
- if (element == null &&
- internalContext.aboutToComputeResult(cacheEntry, LIBRARY_ELEMENT2)) {
- element = analysisCache.getValue(target, LIBRARY_ELEMENT2);
- }
- }
- //
- // Build or reuse the directive elements.
- //
- List<AnalysisError> errors;
- if (element == null) {
- DirectiveElementBuilder builder = new DirectiveElementBuilder(
- context,
- libraryElement,
- sourceModificationTimeMap,
- importLibraryMap,
- importSourceKindMap,
- exportLibraryMap,
- exportSourceKindMap);
- libraryUnit.accept(builder);
- // See the commentary in the computation of the LIBRARY_CYCLE result
- // for details on library cycle invalidation.
- libraryElement.invalidateLibraryCycles();
- errors = builder.errors;
- } else {
- DirectiveResolver resolver = new DirectiveResolver(
- sourceModificationTimeMap, importSourceKindMap, exportSourceKindMap);
- libraryUnit.accept(resolver);
- errors = resolver.errors;
- }
- //
- // Record outputs.
- //
- outputs[LIBRARY_ELEMENT2] = libraryElement;
- outputs[BUILD_DIRECTIVES_ERRORS] = errors;
- }
-
- /**
- * 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 library [libSource].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- LIBRARY_INPUT: LIBRARY_ELEMENT1.of(source),
- UNIT_INPUT_NAME:
- RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
- SOURCES_MODIFICATION_TIME_INPUT_NAME:
- REFERENCED_SOURCES.of(source).toMapOf(MODIFICATION_TIME),
- IMPORTS_LIBRARY_ELEMENT_INPUT_NAME:
- IMPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
- EXPORTS_LIBRARY_ELEMENT_INPUT_NAME:
- EXPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
- IMPORTS_SOURCE_KIND_INPUT_NAME:
- IMPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND),
- EXPORTS_SOURCE_KIND_INPUT_NAME:
- EXPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND)
- };
- }
-
- /**
- * Create a [BuildDirectiveElementsTask] based on the given [target] in
- * the given [context].
- */
- static BuildDirectiveElementsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new BuildDirectiveElementsTask(context, target);
- }
-}
-
-/**
- * A task that builds the elements representing the members of enum
- * declarations.
- */
-class BuildEnumMemberElementsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The name of the [RESOLVED_UNIT1] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'BuildEnumMemberElementsTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[CREATED_RESOLVED_UNIT3, RESOLVED_UNIT3]);
-
- BuildEnumMemberElementsTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- //
- // Build the enum members if they have not already been created.
- //
- EnumDeclaration findFirstEnum() {
- NodeList<CompilationUnitMember> members = unit.declarations;
- int length = members.length;
- for (int i = 0; i < length; i++) {
- CompilationUnitMember member = members[i];
- if (member is EnumDeclaration) {
- return member;
- }
- }
- return null;
- }
-
- EnumDeclaration firstEnum = findFirstEnum();
- if (firstEnum != null &&
- resolutionMap
- .elementDeclaredByEnumDeclaration(firstEnum)
- .accessors
- .isEmpty) {
- EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
- unit.accept(builder);
- }
- //
- // Record outputs.
- //
- outputs[CREATED_RESOLVED_UNIT3] = true;
- outputs[RESOLVED_UNIT3] = unit;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
- UNIT_INPUT: RESOLVED_UNIT2.of(unit)
- };
- }
-
- /**
- * Create a [BuildEnumMemberElementsTask] based on the given [target] in
- * the given [context].
- */
- static BuildEnumMemberElementsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new BuildEnumMemberElementsTask(context, target);
- }
-}
-
-/**
- * A task that builds [EXPORT_NAMESPACE] and [LIBRARY_ELEMENT4] for a library.
- */
-class BuildExportNamespaceTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input for [LIBRARY_ELEMENT3] of a library.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'BuildExportNamespaceTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ELEMENT4]);
-
- BuildExportNamespaceTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
- //
- // Compute export namespace.
- //
- library.exportNamespace = null;
- NamespaceBuilder builder = new NamespaceBuilder();
- Namespace namespace = builder.createExportNamespaceForLibrary(library);
- library.exportNamespace = namespace;
- //
- // Update entry point.
- //
- if (library.entryPoint == null) {
- Iterable<Element> exportedElements = namespace.definedNames.values;
- library.entryPoint = exportedElements.firstWhere(
- (element) => element is FunctionElement && element.isEntryPoint,
- orElse: () => null);
- }
- //
- // Record outputs.
- //
- outputs[LIBRARY_ELEMENT4] = library;
- }
-
- /**
- * 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 library [libSource].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- LIBRARY_INPUT: LIBRARY_ELEMENT3.of(source),
- 'exportsLibraryPublicNamespace':
- EXPORT_SOURCE_CLOSURE.of(source).toMapOf(LIBRARY_ELEMENT3)
- };
- }
-
- /**
- * Create a [BuildExportNamespaceTask] based on the given [target] in
- * the given [context].
- */
- static BuildExportNamespaceTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new BuildExportNamespaceTask(context, target);
- }
-}
-
-/**
- * A task that builds a library element for a Dart library.
- */
-class BuildLibraryElementTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the defining [RESOLVED_UNIT1].
- */
- static const String DEFINING_UNIT_INPUT = 'DEFINING_UNIT_INPUT';
-
- /**
- * The name of the input whose value is a list of built [RESOLVED_UNIT1]s
- * of the parts sourced by a library.
- */
- static const String PARTS_UNIT_INPUT = 'PARTS_UNIT_INPUT';
-
- /**
- * The name of the input whose value is the modification time of the source.
- */
- static const String MODIFICATION_TIME_INPUT = 'MODIFICATION_TIME_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'BuildLibraryElementTask', createTask, buildInputs, <ResultDescriptor>[
- BUILD_LIBRARY_ERRORS,
- LIBRARY_ELEMENT1,
- IS_LAUNCHABLE
- ]);
-
- /**
- * The constant used as an unknown common library name in parts.
- */
- static const String _UNKNOWN_LIBRARY_NAME = 'unknown-library-name';
-
- /**
- * Initialize a newly created task to build a library element for the given
- * [target] in the given [context].
- */
- BuildLibraryElementTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- List<AnalysisError> errors = <AnalysisError>[];
- //
- // Prepare inputs.
- //
- Source librarySource = getRequiredSource();
- CompilationUnit definingCompilationUnit =
- getRequiredInput(DEFINING_UNIT_INPUT);
- List<CompilationUnit> partUnits = getRequiredInput(PARTS_UNIT_INPUT);
- int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT);
- //
- // Process inputs.
- //
- CompilationUnitElementImpl definingCompilationUnitElement =
- definingCompilationUnit.declaredElement;
- Map<Source, CompilationUnit> partUnitMap =
- new HashMap<Source, CompilationUnit>();
- int partLength = partUnits.length;
- for (int i = 0; i < partLength; i++) {
- CompilationUnit partUnit = partUnits[i];
- Source partSource =
- resolutionMap.elementDeclaredByCompilationUnit(partUnit).source;
- partUnitMap[partSource] = partUnit;
- }
- //
- // Update "part" directives.
- //
- LibraryIdentifier libraryNameNode = null;
- String partsLibraryName = _UNKNOWN_LIBRARY_NAME;
- Set<Source> seenPartSources = new Set<Source>();
- FunctionElement entryPoint =
- _findEntryPoint(definingCompilationUnitElement);
- List<Directive> directivesToResolve = <Directive>[];
- List<CompilationUnitElementImpl> sourcedCompilationUnits =
- <CompilationUnitElementImpl>[];
- NodeList<Directive> directives = definingCompilationUnit.directives;
- int directiveLength = directives.length;
- for (int i = 0; i < directiveLength; i++) {
- Directive directive = directives[i];
- if (directive is LibraryDirective) {
- libraryNameNode = directive.name;
- directivesToResolve.add(directive);
- } else if (directive is PartDirective) {
- StringLiteral partUri = directive.uri;
- Source partSource = directive.uriSource;
- CompilationUnit partUnit = partUnitMap[partSource];
- if (partUnit != null) {
- CompilationUnitElementImpl partElement = partUnit.declaredElement;
- partElement.uriOffset = partUri.offset;
- partElement.uriEnd = partUri.end;
- partElement.uri = directive.uriContent;
- //
- // Validate that the part source is unique in the library.
- //
- if (!seenPartSources.add(partSource)) {
- errors.add(new AnalysisError(
- librarySource,
- partUri.offset,
- partUri.length,
- CompileTimeErrorCode.DUPLICATE_PART,
- [partSource.uri]));
- }
- //
- // Validate that the part contains a part-of directive with the same
- // name as the library.
- //
- if (context.exists(partSource)) {
- _NameOrSource nameOrSource = _getPartLibraryNameOrUri(
- context, partSource, partUnit, directivesToResolve);
- if (nameOrSource == null) {
- errors.add(new AnalysisError(
- librarySource,
- partUri.offset,
- partUri.length,
- CompileTimeErrorCode.PART_OF_NON_PART,
- [partUri.toSource()]));
- } else {
- String name = nameOrSource.name;
- if (name != null) {
- if (libraryNameNode == null) {
- if (partsLibraryName == _UNKNOWN_LIBRARY_NAME) {
- partsLibraryName = name;
- } else if (partsLibraryName != name) {
- partsLibraryName = null;
- }
- } else if (libraryNameNode.name != name) {
- errors.add(new AnalysisError(
- librarySource,
- partUri.offset,
- partUri.length,
- StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
- [libraryNameNode.name, name]));
- }
- } else {
- Source source = nameOrSource.source;
- if (source != librarySource) {
- errors.add(new AnalysisError(
- librarySource,
- partUri.offset,
- partUri.length,
- StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
- [librarySource.uri.toString(), source.uri.toString()]));
- }
- }
- }
- }
- if (entryPoint == null) {
- entryPoint = _findEntryPoint(partElement);
- }
- directive.element = partElement;
- sourcedCompilationUnits.add(partElement);
- }
- }
- }
- // TODO(brianwilkerson) Report the error
- // ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART
- //
- // Create and populate the library element.
- //
- AnalysisContext owningContext = context;
- if (context is InternalAnalysisContext) {
- InternalAnalysisContext internalContext = context;
- owningContext = internalContext.getContextFor(librarySource);
- }
- //
- // Try to get the existing LibraryElement.
- //
- LibraryElementImpl libraryElement;
- {
- InternalAnalysisContext internalContext =
- context as InternalAnalysisContext;
- AnalysisCache analysisCache = internalContext.analysisCache;
- CacheEntry cacheEntry = internalContext.getCacheEntry(target);
- libraryElement = analysisCache.getValue(target, LIBRARY_ELEMENT1)
- as LibraryElementImpl;
- if (libraryElement == null &&
- internalContext.aboutToComputeResult(cacheEntry, LIBRARY_ELEMENT1)) {
- libraryElement = analysisCache.getValue(target, LIBRARY_ELEMENT1)
- as LibraryElementImpl;
- }
- }
- //
- // Create a new LibraryElement.
- //
- if (libraryElement == null) {
- libraryElement =
- new LibraryElementImpl.forNode(owningContext, null, libraryNameNode);
- libraryElement.isSynthetic = modificationTime < 0;
- libraryElement.definingCompilationUnit = definingCompilationUnitElement;
- libraryElement.entryPoint = entryPoint;
- libraryElement.parts = sourcedCompilationUnits;
- libraryElement.hasExtUri = _hasExtUri(definingCompilationUnit);
- BuildLibraryElementUtils.patchTopLevelAccessors(libraryElement);
- // set the library documentation to the docs associated with the first
- // directive in the compilation unit.
- if (definingCompilationUnit.directives.isNotEmpty) {
- setElementDocumentationComment(
- libraryElement, definingCompilationUnit.directives.first);
- }
- }
- //
- // Resolve the relevant directives to the library element.
- //
- // TODO(brianwilkerson) This updates the state of the AST structures but
- // does not associate a new result with it.
- //
- int length = directivesToResolve.length;
- for (int i = 0; i < length; i++) {
- Directive directive = directivesToResolve[i];
- directive.element = libraryElement;
- }
- //
- // Record outputs.
- //
- outputs[BUILD_LIBRARY_ERRORS] = errors;
- outputs[LIBRARY_ELEMENT1] = libraryElement;
- outputs[IS_LAUNCHABLE] = entryPoint != null;
- }
-
- /**
- * Return the top-level [FunctionElement] entry point, or `null` if the given
- * [element] does not define an entry point.
- */
- FunctionElement _findEntryPoint(CompilationUnitElementImpl element) {
- List<FunctionElement> functions = element.functions;
- int length = functions.length;
- for (int i = 0; i < length; i++) {
- FunctionElement function = functions[i];
- if (function.isEntryPoint) {
- return function;
- }
- }
- return null;
- }
-
- /**
- * Return the name of the library that the given part is declared to be a
- * part of, or `null` if the part does not contain a part-of directive.
- */
- _NameOrSource _getPartLibraryNameOrUri(
- AnalysisContext context,
- Source partSource,
- CompilationUnit partUnit,
- List<Directive> directivesToResolve) {
- NodeList<Directive> directives = partUnit.directives;
- int length = directives.length;
- for (int i = 0; i < length; i++) {
- Directive directive = directives[i];
- if (directive is PartOfDirective) {
- directivesToResolve.add(directive);
- LibraryIdentifier libraryName = directive.libraryName;
- if (libraryName != null) {
- return new _NameOrSource(libraryName.name, null);
- }
- String uri = directive.uri?.stringValue;
- if (uri != null) {
- Source librarySource =
- context.sourceFactory.resolveUri(partSource, uri);
- if (librarySource != null) {
- return new _NameOrSource(null, librarySource);
- }
- }
- }
- }
- return null;
- }
-
- /**
- * Return `true` if the given compilation [unit] contains at least one
- * import directive with a `dart-ext:` URI.
- */
- bool _hasExtUri(CompilationUnit unit) {
- NodeList<Directive> directives = unit.directives;
- int length = directives.length;
- for (int i = 0; i < length; i++) {
- Directive directive = directives[i];
- if (directive is ImportDirective) {
- if (DartUriResolver.isDartExtUri(directive.uriContent)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * 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].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- DEFINING_UNIT_INPUT:
- RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
- PARTS_UNIT_INPUT: INCLUDED_PARTS.of(source).toList((Source unit) {
- return RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, unit));
- }),
- MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(source)
- };
- }
-
- /**
- * Create a [BuildLibraryElementTask] based on the given [target] in the
- * given [context].
- */
- static BuildLibraryElementTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new BuildLibraryElementTask(context, target);
- }
-}
-
-/**
- * A task that builds [PUBLIC_NAMESPACE] for a library.
- */
-class BuildPublicNamespaceTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input for [LIBRARY_ELEMENT2] of a library.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'BuildPublicNamespaceTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ELEMENT3]);
-
- BuildPublicNamespaceTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
- NamespaceBuilder builder = new NamespaceBuilder();
- library.publicNamespace = builder.createPublicNamespaceForLibrary(library);
- outputs[LIBRARY_ELEMENT3] = library;
- }
-
- /**
- * 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 library [libSource].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{LIBRARY_INPUT: LIBRARY_ELEMENT2.of(source)};
- }
-
- /**
- * Create a [BuildPublicNamespaceTask] based on the given [target] in
- * the given [context].
- */
- static BuildPublicNamespaceTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new BuildPublicNamespaceTask(context, target);
- }
-}
-
-/**
- * A task that builds [EXPORT_SOURCE_CLOSURE] of a library.
- */
-class BuildSourceExportClosureTask extends SourceBasedAnalysisTask {
- /**
- * The name of the export closure.
- */
- static const String EXPORT_INPUT = 'EXPORT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'BuildSourceExportClosureTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[EXPORT_SOURCE_CLOSURE]);
-
- BuildSourceExportClosureTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- List<Source> exportClosure = getRequiredInput(EXPORT_INPUT);
- //
- // Record output.
- //
- outputs[EXPORT_SOURCE_CLOSURE] = exportClosure;
- }
-
- /**
- * 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 library [libSource].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- EXPORT_INPUT: new _ExportSourceClosureTaskInput(source, LIBRARY_ELEMENT2)
- };
- }
-
- /**
- * Create a [BuildSourceExportClosureTask] based on the given [target] in
- * the given [context].
- */
- static BuildSourceExportClosureTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new BuildSourceExportClosureTask(context, target);
- }
-}
-
-/**
- * A task that builds [TYPE_PROVIDER] for a context.
- */
-class BuildTypeProviderTask extends SourceBasedAnalysisTask {
- /**
- * The [PUBLIC_NAMESPACE] input of the `dart:core` library.
- */
- static const String CORE_INPUT = 'CORE_INPUT';
-
- /**
- * The [PUBLIC_NAMESPACE] input of the `dart:async` library.
- */
- static const String ASYNC_INPUT = 'ASYNC_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'BuildTypeProviderTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[TYPE_PROVIDER]);
-
- BuildTypeProviderTask(
- InternalAnalysisContext context, AnalysisContextTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- LibraryElement coreLibrary = getRequiredInput(CORE_INPUT);
- LibraryElement asyncLibrary = getOptionalInput(ASYNC_INPUT);
- Namespace coreNamespace = coreLibrary.publicNamespace;
- Namespace asyncNamespace = asyncLibrary.publicNamespace;
- //
- // Record outputs.
- //
- TypeProvider typeProvider =
- new TypeProviderImpl.forNamespaces(coreNamespace, asyncNamespace);
- (context as InternalAnalysisContext).typeProvider = typeProvider;
- outputs[TYPE_PROVIDER] = typeProvider;
- }
-
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- AnalysisContextTarget contextTarget = target;
- SourceFactory sourceFactory = contextTarget.context.sourceFactory;
- Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
- Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
- if (asyncSource == null) {
- return <String, TaskInput>{CORE_INPUT: LIBRARY_ELEMENT3.of(coreSource)};
- }
- return <String, TaskInput>{
- CORE_INPUT: LIBRARY_ELEMENT3.of(coreSource),
- ASYNC_INPUT: LIBRARY_ELEMENT3.of(asyncSource)
- };
- }
-
- /**
- * Create a [BuildTypeProviderTask] based on the given [context].
- */
- static BuildTypeProviderTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new BuildTypeProviderTask(context, target);
- }
-}
-
-/**
- * A task that computes [CONSTANT_DEPENDENCIES] for a constant.
- */
-class ComputeConstantDependenciesTask extends ConstantEvaluationAnalysisTask {
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ComputeConstantDependenciesTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[CONSTANT_DEPENDENCIES]);
-
- ComputeConstantDependenciesTask(
- InternalAnalysisContext context, ConstantEvaluationTarget constant)
- : super(context, constant);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- ConstantEvaluationTarget constant = target;
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- //
- // Compute dependencies.
- //
- List<ConstantEvaluationTarget> dependencies = <ConstantEvaluationTarget>[];
- new ConstantEvaluationEngine(typeProvider, context.declaredVariables,
- typeSystem: context.typeSystem)
- .computeDependencies(constant, dependencies.add);
- //
- // Record outputs.
- //
- outputs[CONSTANT_DEPENDENCIES] = dependencies;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- return <String, TaskInput>{
- 'constantExpressionResolved': CONSTANT_EXPRESSION_RESOLVED.of(target),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
- };
- }
-
- /**
- * Create a [ComputeConstantDependenciesTask] based on the given [target] in
- * the given [context].
- */
- static ComputeConstantDependenciesTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ComputeConstantDependenciesTask(context, target);
- }
-}
-
-/**
- * A task that computes the value of a constant ([CONSTANT_VALUE]) and
- * stores it in the element model.
- */
-class ComputeConstantValueTask extends ConstantEvaluationAnalysisTask {
- /**
- * The name of the input which ensures that dependent constants are evaluated
- * before the target.
- */
- static const String DEPENDENCIES_INPUT = 'DEPENDENCIES_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ComputeConstantValueTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[CONSTANT_VALUE]);
-
- ComputeConstantValueTask(
- InternalAnalysisContext context, ConstantEvaluationTarget constant)
- : super(context, constant);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- bool get handlesDependencyCycles => true;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- // Note: DEPENDENCIES_INPUT is not needed. It is merely a bookkeeping
- // dependency to ensure that the constants that this constant depends on
- // are computed first.
- ConstantEvaluationTarget constant = target;
- AnalysisContext context = constant.context;
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- //
- // Compute the value of the constant, or report an error if there was a
- // cycle.
- //
- ConstantEvaluationEngine constantEvaluationEngine =
- new ConstantEvaluationEngine(typeProvider, context.declaredVariables,
- typeSystem: context.typeSystem);
- if (dependencyCycle == null) {
- constantEvaluationEngine.computeConstantValue(constant);
- } else {
- List<ConstantEvaluationTarget> constantsInCycle =
- <ConstantEvaluationTarget>[];
- int length = dependencyCycle.length;
- for (int i = 0; i < length; i++) {
- WorkItem workItem = dependencyCycle[i];
- if (workItem.descriptor == DESCRIPTOR) {
- AnalysisTarget target = workItem.target;
- constantsInCycle.add(target);
- if (target is ConstructorElementImpl) {
- target.isCycleFree = false;
- }
- }
- }
- assert(constantsInCycle.isNotEmpty);
- constantEvaluationEngine.generateCycleError(constantsInCycle, constant);
- }
- //
- // Record outputs.
- //
- outputs[CONSTANT_VALUE] = constant;
- }
-
- /**
- * 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
- * [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- ConstantEvaluationTarget evaluationTarget = target;
- return <String, TaskInput>{
- DEPENDENCIES_INPUT:
- CONSTANT_DEPENDENCIES.of(evaluationTarget).toListOf(CONSTANT_VALUE),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
- };
- }
-
- /**
- * Create a [ComputeConstantValueTask] based on the given [target] in the
- * given [context].
- */
- static ComputeConstantValueTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ComputeConstantValueTask(context, target);
- }
-}
-
-/**
- * A task that computes the [INFERABLE_STATIC_VARIABLE_DEPENDENCIES] for a
- * static variable whose type should be inferred.
- */
-class ComputeInferableStaticVariableDependenciesTask
- extends InferStaticVariableTask {
- /**
- * The name of the [RESOLVED_UNIT7] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ComputeInferableStaticVariableDependenciesTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[INFERABLE_STATIC_VARIABLE_DEPENDENCIES]);
-
- ComputeInferableStaticVariableDependenciesTask(
- InternalAnalysisContext context, VariableElement variable)
- : super(context, variable);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- //
- // Compute dependencies.
- //
- VariableDeclaration declaration = getDeclaration(unit);
- VariableGatherer gatherer = new VariableGatherer(_isInferableStatic);
- declaration.initializer.accept(gatherer);
- //
- // Record outputs.
- //
- outputs[INFERABLE_STATIC_VARIABLE_DEPENDENCIES] = gatherer.results.toList();
- }
-
- /**
- * Return `true` if the given [variable] is a static variable whose type
- * should be inferred.
- */
- bool _isInferableStatic(VariableElement variable) =>
- variable.isStatic &&
- variable.hasImplicitType &&
- variable.initializer != null;
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- if (target is VariableElement) {
- CompilationUnitElementImpl unit = target
- .getAncestor((Element element) => element is CompilationUnitElement);
- return <String, TaskInput>{
- UNIT_INPUT: RESOLVED_UNIT7
- .of(new LibrarySpecificUnit(unit.librarySource, unit.source))
- };
- }
- throw new AnalysisException(
- 'Cannot build inputs for a ${target.runtimeType}');
- }
-
- /**
- * Create a [ComputeInferableStaticVariableDependenciesTask] based on the
- * given [target] in the given [context].
- */
- static ComputeInferableStaticVariableDependenciesTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ComputeInferableStaticVariableDependenciesTask(context, target);
- }
-}
-
-/**
- * A task that computes the [LIBRARY_CYCLE] for a
- * library element. Also computes the [LIBRARY_CYCLE_UNITS] and the
- * [LIBRARY_CYCLE_DEPENDENCIES].
- */
-class ComputeLibraryCycleTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT2] input.
- */
- static const String LIBRARY_ELEMENT_INPUT = 'LIBRARY_ELEMENT_INPUT';
-
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ComputeLibraryCycleForUnitTask',
- createTask,
- buildInputs, <ResultDescriptor>[
- LIBRARY_CYCLE,
- LIBRARY_CYCLE_UNITS,
- LIBRARY_CYCLE_DEPENDENCIES
- ]);
-
- ComputeLibraryCycleTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- // The computation of library cycles is necessarily non-local, since we
- // in general have to look at all of the reachable libraries
- // in order to find the strongly connected components. Repeating this
- // computation for every node would be quadratic. The libraryCycle getter
- // will avoid this by computing the library cycles for every reachable
- // library and recording it in the element model. This means that this
- // task implicitly produces the output for many other targets. This
- // can't be expressed in the task model right now: instead, we just
- // run tasks for those other targets, and they pick up the recorded
- // version off of the element model. Unfortunately, this means that
- // the task model will not handle the invalidation of the recorded
- // results for us. Instead, we must explicitly invalidate the recorded
- // library cycle information when we add or subtract edges from the
- // import/export graph. Any update that changes the
- // import/export graph will induce a recomputation of the LIBRARY_ELEMENT2
- // result for the changed node. This recomputation is responsible for
- // conservatively invalidating the library cycle information recorded
- // in the element model. The LIBRARY_CYCLE results that have been cached
- // by the task model are conservatively invalidated by the
- // IMPORT_EXPORT_SOURCE_CLOSURE dependency below. If anything reachable
- // from a node is changed, its LIBRARY_CYCLE results will be re-computed
- // here (possibly re-using the result from the element model if invalidation
- // did not cause it to be erased). In summary, task model dependencies
- // on the import/export source closure ensure that this method will be
- // re-run if anything reachable from this target has been invalidated,
- // and the invalidation code (invalidateLibraryCycles) will ensure that
- // element model results will be re-used here only if they are still valid.
- LibraryElement library = getRequiredInput(LIBRARY_ELEMENT_INPUT);
- if (!LibraryElementImpl.hasResolutionCapability(
- library, LibraryResolutionCapability.resolvedTypeNames)) {
- List<LibraryElement> component = library.libraryCycle;
- Set<LibraryElement> filter = component.toSet();
- Set<CompilationUnitElement> deps = new Set<CompilationUnitElement>();
- void addLibrary(LibraryElement l) {
- if (!filter.contains(l)) {
- deps.addAll(l.units);
- }
- }
-
- int length = component.length;
- for (int i = 0; i < length; i++) {
- LibraryElement library = component[i];
- library.importedLibraries.forEach(addLibrary);
- library.exportedLibraries.forEach(addLibrary);
- }
- //
- // Record outputs.
- //
- LibrarySpecificUnit unitToLSU(CompilationUnitElement unit) =>
- new LibrarySpecificUnit(unit.librarySource, unit.source);
- outputs[LIBRARY_CYCLE] = component;
- outputs[LIBRARY_CYCLE_UNITS] =
- component.expand((l) => l.units).map(unitToLSU).toList();
- outputs[LIBRARY_CYCLE_DEPENDENCIES] = deps.map(unitToLSU).toList();
- } else {
- outputs[LIBRARY_CYCLE] = <LibraryElement>[];
- outputs[LIBRARY_CYCLE_UNITS] = <LibrarySpecificUnit>[];
- outputs[LIBRARY_CYCLE_DEPENDENCIES] = <LibrarySpecificUnit>[];
- }
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source librarySource = target;
- return <String, TaskInput>{
- LIBRARY_ELEMENT_INPUT: LIBRARY_ELEMENT2.of(librarySource),
- 'resolveReachableLibraries': READY_LIBRARY_ELEMENT2.of(librarySource),
- };
- }
-
- /**
- * Create a [ComputeLibraryCycleTask] based on the
- * given [target] in the given [context].
- */
- static ComputeLibraryCycleTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ComputeLibraryCycleTask(context, target);
- }
-}
-
-/**
- * A task that builds [REQUIRED_CONSTANTS] for a unit.
- */
-class ComputeRequiredConstantsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [RESOLVED_UNIT] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ComputeRequiredConstantsTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[PENDING_ERRORS, REQUIRED_CONSTANTS]);
-
- ComputeRequiredConstantsTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- Source source = getRequiredSource();
- //
- // Prepare inputs.
- //
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- //
- // Use the ErrorVerifier to compute errors.
- //
- RequiredConstantsComputer computer = new RequiredConstantsComputer(source);
- unit.accept(computer);
- List<PendingError> pendingErrors = computer.pendingErrors;
- List<ConstantEvaluationTarget> requiredConstants =
- computer.requiredConstants;
- //
- // Record outputs.
- //
- outputs[PENDING_ERRORS] = pendingErrors;
- outputs[REQUIRED_CONSTANTS] = requiredConstants;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT.of(unit)};
- }
-
- /**
- * Create a [ComputeRequiredConstantsTask] based on the given [target] in
- * the given [context].
- */
- static ComputeRequiredConstantsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ComputeRequiredConstantsTask(context, target);
- }
-}
-
-/**
- * A base class for analysis tasks whose target is expected to be a
- * [ConstantEvaluationTarget].
- */
-abstract class ConstantEvaluationAnalysisTask extends AnalysisTask {
- /**
- * Initialize a newly created task to perform analysis within the given
- * [context] in order to produce results for the given [constant].
- */
- ConstantEvaluationAnalysisTask(
- AnalysisContext context, ConstantEvaluationTarget constant)
- : super(context, constant);
-
- @override
- String get description {
- Source source = target.source;
- String sourceName = source == null ? '<unknown source>' : source.fullName;
- return '${descriptor.name} for element $target in source $sourceName';
- }
-}
-
-/**
- * Interface for [AnalysisTarget]s for which constant evaluation can be
- * performed.
- */
-abstract class ConstantEvaluationTarget extends AnalysisTarget {
- /**
- * Return the [AnalysisContext] which should be used to evaluate this
- * constant.
- */
- AnalysisContext get context;
-
- /**
- * Return whether this constant is evaluated.
- */
- bool get isConstantEvaluated;
-}
-
-/**
- * A task that computes a list of the libraries containing the target source.
- */
-class ContainingLibrariesTask extends SourceBasedAnalysisTask {
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ContainingLibrariesTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[CONTAINING_LIBRARIES]);
-
- ContainingLibrariesTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- // TODO(brianwilkerson) This value can change as new libraries are analyzed
- // so we need some way of making sure that this result is removed from the
- // cache appropriately.
- Source source = getRequiredSource();
- outputs[CONTAINING_LIBRARIES] = context.getLibrariesContaining(source);
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- return <String, TaskInput>{};
- }
-
- /**
- * Create a [ContainingLibrariesTask] based on the given [target] in the given
- * [context].
- */
- static ContainingLibrariesTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ContainingLibrariesTask(context, target);
- }
-}
-
-/**
- * A task that merges all of the errors for a single source into a single list
- * of errors.
- */
-class DartErrorsTask extends SourceBasedAnalysisTask {
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
- createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
-
- /**
- * The name of the [IGNORE_INFO_INPUT] input.
- */
- static const String IGNORE_INFO_INPUT = 'IGNORE_INFO_INPUT';
-
- /**
- * The name of the [LINE_INFO_INPUT] input.
- */
- static const String LINE_INFO_INPUT = 'LINE_INFO_INPUT';
-
- DartErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
- //
- // Prepare inputs.
- //
- EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
- List<ResultDescriptor> errorsForSource = enginePlugin.dartErrorsForSource;
- int sourceLength = errorsForSource.length;
- for (int i = 0; i < sourceLength; i++) {
- ResultDescriptor result = errorsForSource[i];
- String inputName = result.name + '_input';
- errorLists.add(getRequiredInput(inputName));
- }
- List<ResultDescriptor> errorsForUnit = enginePlugin.dartErrorsForUnit;
- int unitLength = errorsForUnit.length;
- for (int i = 0; i < unitLength; i++) {
- ResultDescriptor result = errorsForUnit[i];
- String inputName = result.name + '_input';
- Map<Source, List<AnalysisError>> errorMap = getRequiredInput(inputName);
- for (List<AnalysisError> errors in errorMap.values) {
- errorLists.add(errors);
- }
- }
-
- //
- // Filter ignored errors.
- //
- List<AnalysisError> errors =
- _filterIgnores(AnalysisError.mergeLists(errorLists));
-
- //
- // Record outputs.
- //
- outputs[DART_ERRORS] = errors;
- }
-
- List<AnalysisError> _filterIgnores(List<AnalysisError> errors) {
- if (errors.isEmpty) {
- return errors;
- }
-
- IgnoreInfo ignoreInfo = getRequiredInput(IGNORE_INFO_INPUT);
- if (!ignoreInfo.hasIgnores) {
- return errors;
- }
-
- LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT);
-
- return filterIgnored(errors, ignoreInfo, lineInfo);
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- Map<String, TaskInput> inputs = <String, TaskInput>{};
- inputs[LINE_INFO_INPUT] = LINE_INFO.of(source);
- inputs[IGNORE_INFO_INPUT] = IGNORE_INFO.of(source);
- EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
- // for Source
- List<ListResultDescriptor<AnalysisError>> errorsForSource =
- enginePlugin.dartErrorsForSource;
- int sourceLength = errorsForSource.length;
- for (int i = 0; i < sourceLength; i++) {
- ListResultDescriptor<AnalysisError> result = errorsForSource[i];
- String inputName = result.name + '_input';
- inputs[inputName] = result.of(source);
- }
- // for LibrarySpecificUnit
- List<ListResultDescriptor<AnalysisError>> errorsForUnit =
- enginePlugin.dartErrorsForUnit;
- int unitLength = errorsForUnit.length;
- for (int i = 0; i < unitLength; i++) {
- ListResultDescriptor<AnalysisError> result = errorsForUnit[i];
- String inputName = result.name + '_input';
- inputs[inputName] =
- CONTAINING_LIBRARIES.of(source).toMap((Source library) {
- LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source);
- return result.of(unit);
- });
- }
- return inputs;
- }
-
- /**
- * Create a [DartErrorsTask] based on the given [target] in the given
- * [context].
- */
- static DartErrorsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new DartErrorsTask(context, target);
- }
-
- /**
- * Return a new list with items from [errors] which are not filtered out by
- * the [ignoreInfo].
- */
- static List<AnalysisError> filterIgnored(
- List<AnalysisError> errors, IgnoreInfo ignoreInfo, LineInfo lineInfo) {
- if (errors.isEmpty || !ignoreInfo.hasIgnores) {
- return errors;
- }
-
- bool isIgnored(AnalysisError error) {
- int errorLine = lineInfo.getLocation(error.offset).lineNumber;
- String errorCode = error.errorCode.name.toLowerCase();
- return ignoreInfo.ignoredAt(errorCode, errorLine);
- }
-
- return errors.where((AnalysisError e) => !isIgnored(e)).toList();
- }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT12] for a unit.
- */
-class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [RESOLVED_UNIT11] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The name of the [CONSTANT_VALUE] input.
- */
- static const String CONSTANT_VALUES = 'CONSTANT_VALUES';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'EvaluateUnitConstantsTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[CREATED_RESOLVED_UNIT12, RESOLVED_UNIT12]);
-
- EvaluateUnitConstantsTask(AnalysisContext context, LibrarySpecificUnit target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- // No actual work needs to be performed; the task manager will ensure that
- // all constants are evaluated before this method is called.
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- outputs[RESOLVED_UNIT12] = unit;
- outputs[CREATED_RESOLVED_UNIT12] = true;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- 'libraryElement': LIBRARY_ELEMENT9.of(unit.library),
- UNIT_INPUT: RESOLVED_UNIT11.of(unit),
- CONSTANT_VALUES:
- COMPILATION_UNIT_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE),
- 'constantExpressionsDependencies':
- CONSTANT_EXPRESSIONS_DEPENDENCIES.of(unit).toListOf(CONSTANT_VALUE)
- };
- }
-
- /**
- * Create an [EvaluateUnitConstantsTask] based on the given [target] in
- * the given [context].
- */
- static EvaluateUnitConstantsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new EvaluateUnitConstantsTask(context, target);
- }
-}
-
-/**
- * A task that builds [USED_IMPORTED_ELEMENTS] for a unit.
- */
-class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [RESOLVED_UNIT11] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'GatherUsedImportedElementsTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[USED_IMPORTED_ELEMENTS]);
-
- GatherUsedImportedElementsTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- CompilationUnitElement unitElement = unit.declaredElement;
- LibraryElement libraryElement = unitElement.library;
- //
- // Prepare used imported elements.
- //
- GatherUsedImportedElementsVisitor visitor =
- new GatherUsedImportedElementsVisitor(libraryElement);
- unit.accept(visitor);
- //
- // Record outputs.
- //
- outputs[USED_IMPORTED_ELEMENTS] = visitor.usedElements;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT11.of(unit)};
- }
-
- /**
- * Create a [GatherUsedImportedElementsTask] based on the given [target] in
- * the given [context].
- */
- static GatherUsedImportedElementsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new GatherUsedImportedElementsTask(context, target);
- }
-}
-
-/**
- * A task that builds [USED_LOCAL_ELEMENTS] for a unit.
- */
-class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [RESOLVED_UNIT11] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'GatherUsedLocalElementsTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[USED_LOCAL_ELEMENTS]);
-
- GatherUsedLocalElementsTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- CompilationUnitElement unitElement = unit.declaredElement;
- LibraryElement libraryElement = unitElement.library;
- //
- // Prepare used local elements.
- //
- GatherUsedLocalElementsVisitor visitor =
- new GatherUsedLocalElementsVisitor(libraryElement);
- unit.accept(visitor);
- //
- // Record outputs.
- //
- outputs[USED_LOCAL_ELEMENTS] = visitor.usedElements;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT11.of(unit)};
- }
-
- /**
- * Create a [GatherUsedLocalElementsTask] based on the given [target] in
- * the given [context].
- */
- static GatherUsedLocalElementsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new GatherUsedLocalElementsTask(context, target);
- }
-}
-
-/**
- * A task that generates [HINTS] for a unit.
- */
-class GenerateHintsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [RESOLVED_UNIT11] input.
- */
- static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
-
- /**
- * The name of a list of [USED_LOCAL_ELEMENTS] for each library unit input.
- */
- static const String USED_LOCAL_ELEMENTS_INPUT = 'USED_LOCAL_ELEMENTS';
-
- /**
- * The name of a list of [USED_IMPORTED_ELEMENTS] for each library unit input.
- */
- static const String USED_IMPORTED_ELEMENTS_INPUT = 'USED_IMPORTED_ELEMENTS';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'GenerateHintsTask', createTask, buildInputs, <ResultDescriptor>[HINTS]);
-
- GenerateHintsTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- AnalysisOptions analysisOptions = context.analysisOptions;
- if (!analysisOptions.hint) {
- outputs[HINTS] = AnalysisError.NO_ERRORS;
- return;
- }
- //
- // Prepare collectors.
- //
- RecordingErrorListener errorListener = new RecordingErrorListener();
- Source source = getRequiredSource();
- ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
- //
- // Prepare inputs.
- //
- CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
- List<UsedImportedElements> usedImportedElementsList =
- getRequiredInput(USED_IMPORTED_ELEMENTS_INPUT);
- List<UsedLocalElements> usedLocalElementsList =
- getRequiredInput(USED_LOCAL_ELEMENTS_INPUT);
- CompilationUnitElement unitElement = unit.declaredElement;
- LibraryElement libraryElement = unitElement.library;
- TypeSystem typeSystem = context.typeSystem;
-
- //
- // Generate errors.
- //
- unit.accept(new DeadCodeVerifier(
- errorReporter, (unit as CompilationUnitImpl).isNonNullable,
- typeSystem: typeSystem));
- // Verify imports.
- {
- ImportsVerifier verifier = new ImportsVerifier();
- verifier.addImports(unit);
- usedImportedElementsList.forEach(verifier.removeUsedElements);
- verifier.generateDuplicateImportHints(errorReporter);
- verifier.generateDuplicateShownHiddenNameHints(errorReporter);
- verifier.generateUnusedImportHints(errorReporter);
- verifier.generateUnusedShownNameHints(errorReporter);
- }
- // Unused local elements.
- {
- UsedLocalElements usedElements =
- new UsedLocalElements.merge(usedLocalElementsList);
- UnusedLocalElementsVerifier visitor =
- new UnusedLocalElementsVerifier(errorListener, usedElements);
- unit.accept(visitor);
- }
- // Dart2js analysis.
- if (analysisOptions.dart2jsHint) {
- unit.accept(new Dart2JSVerifier(errorReporter));
- }
- // Dart best practices.
- var inheritanceManager2 = new InheritanceManager2(context.typeSystem);
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
-
- unit.accept(new BestPracticesVerifier(
- errorReporter, typeProvider, libraryElement,
- typeSystem: typeSystem,
- resourceProvider: resourceProvider,
- analysisOptions: context.analysisOptions));
- unit.accept(new OverrideVerifier(
- inheritanceManager2,
- libraryElement,
- errorReporter,
- ));
- // Find to-do comments.
- new ToDoFinder(errorReporter).findIn(unit);
- //
- // Record outputs.
- //
- outputs[HINTS] = errorListener.errors;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- Source libSource = unit.library;
- return <String, TaskInput>{
- RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(unit),
- USED_LOCAL_ELEMENTS_INPUT:
- LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(USED_LOCAL_ELEMENTS),
- USED_IMPORTED_ELEMENTS_INPUT:
- LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(USED_IMPORTED_ELEMENTS),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
- };
- }
-
- /**
- * Create a [GenerateHintsTask] based on the given [target] in
- * the given [context].
- */
- static GenerateHintsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new GenerateHintsTask(context, target);
- }
-}
-
-/**
- * A task that generates [LINTS] for a unit.
- */
-class GenerateLintsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [RESOLVED_UNIT] input.
- */
- static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'GenerateLintsTask', createTask, buildInputs, <ResultDescriptor>[LINTS]);
-
- GenerateLintsTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- AnalysisOptions analysisOptions = context.analysisOptions;
- if (!analysisOptions.lint) {
- outputs[LINTS] = AnalysisError.NO_ERRORS;
- return;
- }
- //
- // Prepare collectors.
- //
- RecordingErrorListener errorListener = new RecordingErrorListener();
- Source source = getRequiredSource();
- ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
- //
- // Prepare inputs.
- //
- CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
- //
- // Generate lints.
- //
- List<AstVisitor> visitors = <AstVisitor>[];
- bool timeVisits = analysisOptions.enableTiming;
- List<Linter> linters = getLints(context);
- int length = linters.length;
- for (int i = 0; i < length; i++) {
- Linter linter = linters[i];
- AstVisitor visitor = linter.getVisitor();
- if (visitor != null) {
- linter.reporter = errorReporter;
- if (timeVisits) {
- visitor = new TimedAstVisitor(visitor, lintRegistry.getTimer(linter));
- }
- visitors.add(visitor);
- }
- }
- AstVisitor visitor = new ExceptionHandlingDelegatingAstVisitor(
- visitors, ExceptionHandlingDelegatingAstVisitor.logException);
- unit.accept(visitor);
- //
- // Record outputs.
- //
- outputs[LINTS] = errorListener.errors;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) =>
- <String, TaskInput>{RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(target)};
-
- /**
- * Create a [GenerateLintsTask] based on the given [target] in
- * the given [context].
- */
- static GenerateLintsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new GenerateLintsTask(context, target);
- }
-}
-
-/**
- * Information about analysis `//ignore:` and `//ignore_for_file` comments
- * within a source file.
- */
-class IgnoreInfo {
- /**
- * Instance shared by all cases without matches.
- */
- static final IgnoreInfo _EMPTY_INFO = new IgnoreInfo();
-
- /**
- * A regular expression for matching 'ignore' comments. Produces matches
- * containing 2 groups. For example:
- *
- * * ['//ignore: error_code', 'error_code']
- *
- * Resulting codes may be in a list ('error_code_1,error_code2').
- */
- static final RegExp _IGNORE_MATCHER =
- new RegExp(r'//+[ ]*ignore:(.*)$', multiLine: true);
-
- /**
- * A regular expression for matching 'ignore_for_file' comments. Produces
- * matches containing 2 groups. For example:
- *
- * * ['//ignore_for_file: error_code', 'error_code']
- *
- * Resulting codes may be in a list ('error_code_1,error_code2').
- */
- static final RegExp _IGNORE_FOR_FILE_MATCHER =
- new RegExp(r'//[ ]*ignore_for_file:(.*)$', multiLine: true);
-
- final Map<int, List<String>> _ignoreMap = new HashMap<int, List<String>>();
-
- final Set<String> _ignoreForFileSet = new HashSet<String>();
-
- /**
- * Whether this info object defines any ignores.
- */
- bool get hasIgnores => ignores.isNotEmpty || _ignoreForFileSet.isNotEmpty;
-
- /**
- * Iterable of error codes ignored for the whole file.
- */
- Iterable<String> get ignoreForFiles => _ignoreForFileSet;
-
- /**
- * Map of line numbers to associated ignored error codes.
- */
- Map<int, Iterable<String>> get ignores => _ignoreMap;
-
- /**
- * Ignore this [errorCode] at [line].
- */
- void add(int line, String errorCode) {
- _ignoreMap.putIfAbsent(line, () => new List<String>()).add(errorCode);
- }
-
- /**
- * Ignore these [errorCodes] at [line].
- */
- void addAll(int line, Iterable<String> errorCodes) {
- _ignoreMap.putIfAbsent(line, () => new List<String>()).addAll(errorCodes);
- }
-
- /**
- * Ignore these [errorCodes] in the whole file.
- */
- void addAllForFile(Iterable<String> errorCodes) {
- _ignoreForFileSet.addAll(errorCodes);
- }
-
- /**
- * Test whether this [errorCode] is ignored at the given [line].
- */
- bool ignoredAt(String errorCode, int line) =>
- _ignoreForFileSet.contains(errorCode) ||
- _ignoreMap[line]?.contains(errorCode) == true;
-
- /**
- * Calculate ignores for the given [content] with line [info].
- */
- static IgnoreInfo calculateIgnores(String content, LineInfo info) {
- Iterable<Match> matches = _IGNORE_MATCHER.allMatches(content);
- Iterable<Match> fileMatches = _IGNORE_FOR_FILE_MATCHER.allMatches(content);
- if (matches.isEmpty && fileMatches.isEmpty) {
- return _EMPTY_INFO;
- }
-
- IgnoreInfo ignoreInfo = new IgnoreInfo();
- for (Match match in matches) {
- // See _IGNORE_MATCHER for format --- note the possibility of error lists.
- Iterable<String> codes = match
- .group(1)
- .split(',')
- .map((String code) => code.trim().toLowerCase());
- CharacterLocation location = info.getLocation(match.start);
- int lineNumber = location.lineNumber;
- String beforeMatch = content.substring(
- info.getOffsetOfLine(lineNumber - 1),
- info.getOffsetOfLine(lineNumber - 1) + location.columnNumber - 1);
-
- if (beforeMatch.trim().isEmpty) {
- // The comment is on its own line, so it refers to the next line.
- ignoreInfo.addAll(lineNumber + 1, codes);
- } else {
- // The comment sits next to code, so it refers to its own line.
- ignoreInfo.addAll(lineNumber, codes);
- }
- }
- for (Match match in fileMatches) {
- Iterable<String> codes = match
- .group(1)
- .split(',')
- .map((String code) => code.trim().toLowerCase());
- ignoreInfo.addAllForFile(codes);
- }
- return ignoreInfo;
- }
-}
-
-/**
- * A task that ensures that all of the inferable instance members in a
- * compilation unit have had their type inferred.
- */
-class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The name of the input whose value is the [RESOLVED_UNIT8] for the
- * compilation unit.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'InferInstanceMembersInUnitTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[CREATED_RESOLVED_UNIT10, RESOLVED_UNIT10]);
-
- /**
- * Initialize a newly created task to build a library element for the given
- * [unit] in the given [context].
- */
- InferInstanceMembersInUnitTask(
- InternalAnalysisContext context, LibrarySpecificUnit unit)
- : super(context, unit);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-
- //
- // Infer instance members.
- //
- var inheritance = new InheritanceManager2(context.typeSystem);
- InstanceMemberInferrer inferrer =
- new InstanceMemberInferrer(typeProvider, inheritance);
- inferrer.inferCompilationUnit(unit.declaredElement);
- //
- // Record outputs.
- //
- outputs[RESOLVED_UNIT10] = unit;
- outputs[CREATED_RESOLVED_UNIT10] = true;
- }
-
- /**
- * 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].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- UNIT_INPUT: RESOLVED_UNIT9.of(unit),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
- // In strong mode, add additional dependencies to enforce inference
- // ordering.
-
- // Require that field re-resolution be complete for all units in the
- // current library cycle.
- 'orderLibraryCycleTasks':
- LIBRARY_CYCLE_UNITS.of(unit.library).toListOf(CREATED_RESOLVED_UNIT9),
- // Require that full inference be complete for all dependencies of the
- // current library cycle.
- 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
- .of(unit.library)
- .toListOf(CREATED_RESOLVED_UNIT10)
- };
- }
-
- /**
- * Create a [InferInstanceMembersInUnitTask] based on the given [target] in
- * the given [context].
- */
- static InferInstanceMembersInUnitTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new InferInstanceMembersInUnitTask(context, target);
- }
-}
-
-/**
- * An abstract class that defines utility methods that are useful for tasks
- * operating on static variables.
- */
-abstract class InferStaticVariableTask extends ConstantEvaluationAnalysisTask {
- InferStaticVariableTask(
- InternalAnalysisContext context, VariableElement variable)
- : super(context, variable);
-
- /**
- * Return the declaration of the target within the given compilation [unit].
- * Throw an exception if the declaration cannot be found.
- */
- VariableDeclaration getDeclaration(CompilationUnit unit) {
- VariableElement variable = target;
- int offset = variable.nameOffset;
- AstNode node = new NodeLocator2(offset).searchWithin(unit);
- if (node == null) {
- Source variableSource = variable.source;
- Source unitSource =
- resolutionMap.elementDeclaredByCompilationUnit(unit).source;
- if (variableSource != unitSource) {
- throw new AnalysisException(
- "Failed to find the AST node for the variable "
- "${variable.displayName} at $offset in $variableSource "
- "because we were looking in $unitSource");
- }
- throw new AnalysisException(
- "Failed to find the AST node for the variable "
- "${variable.displayName} at $offset in $variableSource");
- }
- VariableDeclaration declaration =
- node.thisOrAncestorOfType<VariableDeclaration>();
- if (declaration == null || declaration.name != node) {
- Source variableSource = variable.source;
- Source unitSource =
- resolutionMap.elementDeclaredByCompilationUnit(unit).source;
- if (variableSource != unitSource) {
- if (declaration == null) {
- throw new AnalysisException(
- "Failed to find the declaration of the variable "
- "${variable.displayName} at $offset in $variableSource "
- "because the node was not in a variable declaration "
- "possibly because we were looking in $unitSource");
- }
- throw new AnalysisException(
- "Failed to find the declaration of the variable "
- "${variable.displayName} at $offset in $variableSource "
- "because we were looking in $unitSource");
- }
- if (declaration == null) {
- throw new AnalysisException(
- "Failed to find the declaration of the variable "
- "${variable.displayName} at $offset in $variableSource "
- "because the node was not in a variable declaration");
- }
- throw new AnalysisException(
- "Failed to find the declaration of the variable "
- "${variable.displayName} at $offset in $variableSource "
- "because the node was not the name in a variable declaration");
- }
- return declaration;
- }
-}
-
-/**
- * A task that ensures that all of the inferable static variables in a
- * compilation unit have had their type inferred.
- */
-class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the [RESOLVED_UNIT8] for the
- * compilation unit.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The name of the [STATIC_VARIABLE_RESOLUTION_ERRORS] for all static
- * variables in the compilation unit.
- */
- static const String ERRORS_LIST_INPUT = 'INFERRED_VARIABLES_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'InferStaticVariableTypesInUnitTask',
- createTask,
- buildInputs, <ResultDescriptor>[
- CREATED_RESOLVED_UNIT8,
- RESOLVED_UNIT8,
- STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT
- ]);
-
- /**
- * Initialize a newly created task to build a library element for the given
- * [unit] in the given [context].
- */
- InferStaticVariableTypesInUnitTask(
- InternalAnalysisContext context, LibrarySpecificUnit unit)
- : super(context, unit);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- List<List<AnalysisError>> errorLists = getRequiredInput(ERRORS_LIST_INPUT);
- //
- // Record outputs. There is no additional work to be done at this time
- // because the work has implicitly been done by virtue of the task model
- // preparing all of the inputs.
- //
- outputs[RESOLVED_UNIT8] = unit;
- outputs[CREATED_RESOLVED_UNIT8] = true;
- outputs[STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT] =
- AnalysisError.mergeLists(errorLists);
- }
-
- /**
- * 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].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- 'inferredTypes': INFERABLE_STATIC_VARIABLES_IN_UNIT
- .of(unit)
- .toListOf(INFERRED_STATIC_VARIABLE),
- ERRORS_LIST_INPUT: INFERABLE_STATIC_VARIABLES_IN_UNIT
- .of(unit)
- .toListOf(STATIC_VARIABLE_RESOLUTION_ERRORS),
- UNIT_INPUT: RESOLVED_UNIT7.of(unit)
- };
- }
-
- /**
- * Create a [InferStaticVariableTypesInUnitTask] based on the given [target]
- * in the given [context].
- */
- static InferStaticVariableTypesInUnitTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new InferStaticVariableTypesInUnitTask(context, target);
- }
-}
-
-/**
- * A task that computes the type of an inferable static variable and
- * stores it in the element model.
- */
-class InferStaticVariableTypeTask extends InferStaticVariableTask {
- /**
- * The name of the input which ensures that dependent values have their type
- * inferred before the target.
- */
- static const String DEPENDENCIES_INPUT = 'DEPENDENCIES_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The name of the [RESOLVED_UNIT8] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'InferStaticVariableTypeTask',
- createTask,
- buildInputs, <ResultDescriptor>[
- INFERRED_STATIC_VARIABLE,
- STATIC_VARIABLE_RESOLUTION_ERRORS
- ]);
-
- InferStaticVariableTypeTask(
- InternalAnalysisContext context, VariableElement variable)
- : super(context, variable);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- bool get handlesDependencyCycles => true;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- // Note: DEPENDENCIES_INPUT is not needed. It is merely a bookkeeping
- // dependency to ensure that the variables that this variable references
- // have types inferred before inferring the type of this variable.
- //
- VariableElementImpl variable = target;
-
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- var inheritance = new InheritanceManager2(context.typeSystem);
-
- // If we're not in a dependency cycle, and we have no type annotation,
- // re-resolve the right hand side and do inference.
- List<AnalysisError> errors = AnalysisError.NO_ERRORS;
- if (dependencyCycle == null && variable.hasImplicitType) {
- VariableDeclaration declaration = getDeclaration(unit);
- //
- // Re-resolve the variable's initializer so that the inferred types
- // of other variables will be propagated.
- //
- RecordingErrorListener errorListener = new RecordingErrorListener();
- Expression initializer = declaration.initializer;
-
- ResolutionContext resolutionContext =
- ResolutionContextBuilder.contextFor(initializer);
- ResolverVisitor visitor = new ResolverVisitor(inheritance,
- variable.library, variable.source, typeProvider, errorListener,
- nameScope: resolutionContext.scope);
- if (resolutionContext.enclosingClassDeclaration != null) {
- visitor.prepareToResolveMembersInClass(
- resolutionContext.enclosingClassDeclaration);
- }
- initializer.accept(visitor);
- DartType newType = initializer.staticType;
- if (newType == null || newType.isBottom || newType.isDartCoreNull) {
- newType = typeProvider.dynamicType;
- }
-
- //
- // Record the type of the variable.
- //
- setFieldType(variable, newType);
- errors = getUniqueErrors(errorListener.errors);
- } else {
- // TODO(brianwilkerson) For now we simply don't infer any type for
- // variables or fields involved in a cycle. We could try to be smarter
- // by re-resolving the initializer in a context in which the types of all
- // of the variables in the cycle are assumed to be `null`, but it isn't
- // clear to me that this would produce better results often enough to
- // warrant the extra effort.
- }
- //
- // Record outputs.
- //
- outputs[INFERRED_STATIC_VARIABLE] = variable;
- outputs[STATIC_VARIABLE_RESOLUTION_ERRORS] = errors;
- }
-
- /**
- * 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
- * [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- VariableElement variable = target;
- LibrarySpecificUnit unit =
- new LibrarySpecificUnit(variable.library.source, variable.source);
- return <String, TaskInput>{
- DEPENDENCIES_INPUT: INFERABLE_STATIC_VARIABLE_DEPENDENCIES
- .of(variable)
- .toListOf(INFERRED_STATIC_VARIABLE),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
- UNIT_INPUT: RESOLVED_UNIT7.of(unit),
- // In strong mode, add additional dependencies to enforce inference
- // ordering.
-
- // Require that full inference be complete for all dependencies of the
- // current library cycle.
- 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
- .of(unit.library)
- .toListOf(CREATED_RESOLVED_UNIT10)
- };
- }
-
- /**
- * Create a [InferStaticVariableTypeTask] based on the given [target] in the
- * given [context].
- */
- static InferStaticVariableTypeTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new InferStaticVariableTypeTask(context, target);
- }
-}
-
-/**
- * A task computes all of the errors of all of the units for a single
- * library source and sets the [LIBRARY_ERRORS_READY] flag.
- */
-class LibraryErrorsReadyTask extends SourceBasedAnalysisTask {
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'LibraryErrorsReadyTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ERRORS_READY]);
-
- LibraryErrorsReadyTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- outputs[LIBRARY_ERRORS_READY] = true;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- 'allErrors': UNITS.of(source).toListOf(DART_ERRORS),
- 'libraryElement': LIBRARY_ELEMENT.of(source)
- };
- }
-
- /**
- * Create a [LibraryErrorsReadyTask] based on the given [target] in the given
- * [context].
- */
- static LibraryErrorsReadyTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new LibraryErrorsReadyTask(context, target);
- }
-}
-
-/**
- * A task that merges all of the errors for a single source into a single list
- * of errors.
- */
-class LibraryUnitErrorsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [BUILD_DIRECTIVES_ERRORS] input.
- */
- static const String BUILD_DIRECTIVES_ERRORS_INPUT = 'BUILD_DIRECTIVES_ERRORS';
-
- /**
- * The name of the [BUILD_LIBRARY_ERRORS] input.
- */
- static const String BUILD_LIBRARY_ERRORS_INPUT = 'BUILD_LIBRARY_ERRORS';
-
- /**
- * The name of the [HINTS] input.
- */
- static const String HINTS_INPUT = 'HINTS';
-
- /**
- * The name of the [LINTS] input.
- */
- static const String LINTS_INPUT = 'LINTS';
-
- /**
- * The name of the [STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT] input.
- */
- static const String STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT =
- 'STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT';
-
- /**
- * The name of the [RESOLVE_DIRECTIVES_ERRORS] input.
- */
- static const String RESOLVE_DIRECTIVES_ERRORS_INPUT =
- 'RESOLVE_DIRECTIVES_ERRORS';
-
- /**
- * The name of the [STRONG_MODE_ERRORS] input.
- */
- static const String STRONG_MODE_ERRORS_INPUT = 'STRONG_MODE_ERRORS';
-
- /**
- * The name of the [RESOLVE_TYPE_NAMES_ERRORS] input.
- */
- static const String RESOLVE_TYPE_NAMES_ERRORS_INPUT =
- 'RESOLVE_TYPE_NAMES_ERRORS';
-
- /**
- * The name of the [RESOLVE_TYPE_BOUNDS_ERRORS] input.
- */
- static const String RESOLVE_TYPE_NAMES_ERRORS2_INPUT =
- 'RESOLVE_TYPE_NAMES_ERRORS2';
-
- /**
- * The name of the [RESOLVE_UNIT_ERRORS] input.
- */
- static const String RESOLVE_UNIT_ERRORS_INPUT = 'RESOLVE_UNIT_ERRORS';
-
- /**
- * The name of the [VARIABLE_REFERENCE_ERRORS] input.
- */
- static const String VARIABLE_REFERENCE_ERRORS_INPUT =
- 'VARIABLE_REFERENCE_ERRORS';
-
- /**
- * The name of the [VERIFY_ERRORS] input.
- */
- static const String VERIFY_ERRORS_INPUT = 'VERIFY_ERRORS';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'LibraryUnitErrorsTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_UNIT_ERRORS]);
-
- LibraryUnitErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
- errorLists.add(getRequiredInput(BUILD_DIRECTIVES_ERRORS_INPUT));
- errorLists.add(getRequiredInput(BUILD_LIBRARY_ERRORS_INPUT));
- errorLists.add(getRequiredInput(HINTS_INPUT));
- errorLists.add(getRequiredInput(LINTS_INPUT));
- errorLists.add(getRequiredInput(RESOLVE_DIRECTIVES_ERRORS_INPUT));
- errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS_INPUT));
- errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS2_INPUT));
- errorLists.add(getRequiredInput(RESOLVE_UNIT_ERRORS_INPUT));
- errorLists.add(getRequiredInput(STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT));
- errorLists.add(getRequiredInput(STRONG_MODE_ERRORS_INPUT));
- errorLists.add(getRequiredInput(VARIABLE_REFERENCE_ERRORS_INPUT));
- errorLists.add(getRequiredInput(VERIFY_ERRORS_INPUT));
- //
- // Record outputs.
- //
- outputs[LIBRARY_UNIT_ERRORS] = AnalysisError.mergeLists(errorLists);
- }
-
- /**
- * 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 [unit].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- Map<String, TaskInput> inputs = <String, TaskInput>{
- HINTS_INPUT: HINTS.of(unit),
- LINTS_INPUT: LINTS.of(unit),
- RESOLVE_DIRECTIVES_ERRORS_INPUT: RESOLVE_DIRECTIVES_ERRORS.of(unit),
- RESOLVE_TYPE_NAMES_ERRORS_INPUT: RESOLVE_TYPE_NAMES_ERRORS.of(unit),
- RESOLVE_TYPE_NAMES_ERRORS2_INPUT: RESOLVE_TYPE_BOUNDS_ERRORS.of(unit),
- RESOLVE_UNIT_ERRORS_INPUT: RESOLVE_UNIT_ERRORS.of(unit),
- STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT:
- STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT.of(unit),
- STRONG_MODE_ERRORS_INPUT: STRONG_MODE_ERRORS.of(unit),
- VARIABLE_REFERENCE_ERRORS_INPUT: VARIABLE_REFERENCE_ERRORS.of(unit),
- VERIFY_ERRORS_INPUT: VERIFY_ERRORS.of(unit)
- };
- Source source = unit.source;
- if (unit.library == source) {
- inputs[BUILD_DIRECTIVES_ERRORS_INPUT] =
- BUILD_DIRECTIVES_ERRORS.of(source);
- inputs[BUILD_LIBRARY_ERRORS_INPUT] = BUILD_LIBRARY_ERRORS.of(source);
- } else {
- inputs[BUILD_DIRECTIVES_ERRORS_INPUT] =
- new ConstantTaskInput(AnalysisError.NO_ERRORS);
- inputs[BUILD_LIBRARY_ERRORS_INPUT] =
- new ConstantTaskInput(AnalysisError.NO_ERRORS);
- }
- return inputs;
- }
-
- /**
- * Create a [LibraryUnitErrorsTask] based on the given [target] in the given
- * [context].
- */
- static LibraryUnitErrorsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new LibraryUnitErrorsTask(context, target);
- }
-}
-
-/**
- * A task that parses the content of a Dart file, producing an AST structure,
- * any lexical errors found in the process, the kind of the file (library or
- * part), and several lists based on the AST.
- */
-class ParseDartTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the line information produced for the
- * file.
- */
- static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME';
-
- /**
- * The name of the input whose value is the modification time of the file.
- */
- static const String MODIFICATION_TIME_INPUT_NAME =
- 'MODIFICATION_TIME_INPUT_NAME';
-
- /**
- * The name of the input whose value is the token stream produced for the file.
- */
- static const String TOKEN_STREAM_INPUT_NAME = 'TOKEN_STREAM_INPUT_NAME';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ParseDartTask', createTask, buildInputs, <ResultDescriptor>[
- EXPLICITLY_IMPORTED_LIBRARIES,
- EXPORTED_LIBRARIES,
- IMPORTED_LIBRARIES,
- INCLUDED_PARTS,
- LIBRARY_SPECIFIC_UNITS,
- PARSE_ERRORS,
- PARSED_UNIT,
- REFERENCED_SOURCES,
- SOURCE_KIND,
- UNITS,
- ]);
-
- /**
- * The source that is being parsed.
- */
- Source _source;
-
- /**
- * The [ErrorReporter] to report errors to.
- */
- ErrorReporter _errorReporter;
-
- /**
- * Initialize a newly created task to parse the content of the Dart file
- * associated with the given [target] in the given [context].
- */
- ParseDartTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- _source = getRequiredSource();
- LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
- int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT_NAME);
- Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME);
-
- RecordingErrorListener errorListener = new RecordingErrorListener();
- _errorReporter = new ErrorReporter(errorListener, _source);
-
- AnalysisOptions options = context.analysisOptions;
- Parser parser =
- new Parser(_source, errorListener, useFasta: options.useFastaParser);
- parser.parseFunctionBodies =
- options.analyzeFunctionBodiesPredicate(_source);
- parser.enableOptionalNewAndConst = true;
- CompilationUnit unit = parser.parseCompilationUnit(tokenStream);
- unit.lineInfo = lineInfo;
-
- if (options.patchPaths.isNotEmpty && _source.uri.scheme == 'dart') {
- var resourceProvider =
- (context.sourceFactory.dartSdk as FolderBasedDartSdk)
- .resourceProvider;
- new SdkPatcher().patch(resourceProvider,
- context.analysisOptions.patchPaths, errorListener, _source, unit);
- }
-
- bool hasNonPartOfDirective = false;
- bool hasPartOfDirective = false;
- HashSet<Source> explicitlyImportedSourceSet = new HashSet<Source>();
- HashSet<Source> exportedSourceSet = new HashSet<Source>();
- HashSet<Source> includedSourceSet = new HashSet<Source>();
- NodeList<Directive> directives = unit.directives;
- int length = directives.length;
- for (int i = 0; i < length; i++) {
- Directive directive = directives[i];
- if (directive is PartOfDirective) {
- hasPartOfDirective = true;
- } else {
- hasNonPartOfDirective = true;
- if (directive is UriBasedDirective) {
- Source referencedSource = _resolveDirective(directive);
- if (referencedSource != null) {
- if (directive is ExportDirective) {
- exportedSourceSet.add(referencedSource);
- } else if (directive is ImportDirective) {
- explicitlyImportedSourceSet.add(referencedSource);
- } else if (directive is PartDirective) {
- includedSourceSet.add(referencedSource);
- } else {
- throw new AnalysisException(
- '$runtimeType failed to handle a ${directive.runtimeType}');
- }
- }
- }
- }
- }
- //
- // Always include "dart:core" source.
- //
- HashSet<Source> importedSourceSet =
- new HashSet.from(explicitlyImportedSourceSet);
- Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
- if (coreLibrarySource == null) {
- String message;
- DartSdk sdk = context.sourceFactory.dartSdk;
- if (sdk == null) {
- message = 'Could not resolve "dart:core": SDK not defined';
- } else {
- message = 'Could not resolve "dart:core": SDK incorrectly configured';
- }
- throw new AnalysisException(message);
- }
- importedSourceSet.add(coreLibrarySource);
- //
- // Compute kind.
- //
- SourceKind sourceKind = SourceKind.LIBRARY;
- if (modificationTime == -1) {
- sourceKind = SourceKind.UNKNOWN;
- } else if (hasPartOfDirective && !hasNonPartOfDirective) {
- sourceKind = SourceKind.PART;
- }
- //
- // Compute source lists.
- //
- List<Source> explicitlyImportedSources =
- explicitlyImportedSourceSet.toList();
- List<Source> exportedSources = exportedSourceSet.toList();
- List<Source> importedSources = importedSourceSet.toList();
- List<Source> includedSources = includedSourceSet.toList();
- List<Source> unitSources = <Source>[_source]..addAll(includedSourceSet);
- List<LibrarySpecificUnit> librarySpecificUnits =
- unitSources.map((s) => new LibrarySpecificUnit(_source, s)).toList();
- //
- // Compute referenced sources.
- //
- Set<Source> referencedSources = new Set<Source>();
- referencedSources.add(coreLibrarySource);
- referencedSources.addAll(unitSources);
- for (Directive directive in unit.directives) {
- if (directive is NamespaceDirective) {
- referencedSources.add(directive.uriSource);
- for (Configuration configuration in directive.configurations) {
- referencedSources.add(configuration.uriSource);
- }
- }
- }
- referencedSources.removeWhere((source) => source == null);
- //
- // Record outputs.
- //
- List<AnalysisError> parseErrors = getUniqueErrors(errorListener.errors);
- outputs[EXPLICITLY_IMPORTED_LIBRARIES] = explicitlyImportedSources;
- outputs[EXPORTED_LIBRARIES] = exportedSources;
- outputs[IMPORTED_LIBRARIES] = importedSources;
- outputs[INCLUDED_PARTS] = includedSources;
- outputs[LIBRARY_SPECIFIC_UNITS] = librarySpecificUnits;
- outputs[PARSE_ERRORS] = parseErrors;
- outputs[PARSED_UNIT] = unit;
- outputs[REFERENCED_SOURCES] = referencedSources.toList();
- outputs[SOURCE_KIND] = sourceKind;
- outputs[UNITS] = unitSources;
- }
-
- /**
- * Return the result of resolving the URI of the given URI-based [directive]
- * against the URI of the given library, or `null` if the URI is not valid.
- */
- Source _resolveDirective(UriBasedDirective directive) {
- bool isImport = directive is ImportDirective;
-
- // Resolve the default URI.
- Source defaultSource;
- {
- StringLiteral uriLiteral = directive.uri;
- String uriContent = uriLiteral.stringValue;
- if (uriContent != null) {
- uriContent = uriContent.trim();
- directive.uriContent = uriContent;
- }
- defaultSource = _resolveUri(isImport, uriLiteral, uriContent);
- directive.uriSource = defaultSource;
- }
-
- // Resolve all configurations and try to choose one.
- if (directive is NamespaceDirectiveImpl) {
- String configuredUriContent;
- Source configuredSource;
- for (Configuration configuration in directive.configurations) {
- String uriContent = configuration.uri.stringValue;
- Source source = _resolveUri(isImport, configuration.uri, uriContent);
- configuration.uriSource = source;
- if (configuredSource == null) {
- String variableName =
- configuration.name.components.map((i) => i.name).join('.');
- String variableValue = context.declaredVariables.get(variableName);
- if (configuration.value != null &&
- variableValue == configuration.value.stringValue ||
- variableValue == 'true') {
- configuredUriContent = configuration.uri.stringValue;
- configuredSource = source;
- }
- }
- }
- String selectedContentUri = configuredUriContent ?? directive.uriContent;
- Source selectedSource = configuredSource ?? defaultSource;
- directive.selectedUriContent = selectedContentUri;
- directive.selectedSource = selectedSource;
- return selectedSource;
- }
- return defaultSource;
- }
-
- /**
- * Return the result of resolve the given [uriContent], reporting errors
- * against the [uriLiteral].
- */
- Source _resolveUri(
- bool isImport, StringLiteral uriLiteral, String uriContent) {
- UriValidationCode code =
- UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent);
- if (code == null) {
- try {
- Uri.parse(uriContent);
- } on FormatException {
- return null;
- }
- return context.sourceFactory.resolveUri(_source, uriContent);
- } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
- return null;
- } else if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral);
- return null;
- } else if (code == UriValidationCode.INVALID_URI) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.INVALID_URI, uriLiteral, [uriContent]);
- return null;
- }
- throw new AnalysisException('Failed to handle validation code: $code');
- }
-
- /**
- * 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
- * [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- return <String, TaskInput>{
- LINE_INFO_INPUT_NAME: LINE_INFO.of(target),
- MODIFICATION_TIME_INPUT_NAME: MODIFICATION_TIME.of(target),
- TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.of(target, flushOnAccess: true)
- };
- }
-
- /**
- * Create a [ParseDartTask] based on the given [target] in the given
- * [context].
- */
- static ParseDartTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ParseDartTask(context, target);
- }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT7] for a unit.
- */
-class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT6] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the [RESOLVED_UNIT6] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'PartiallyResolveUnitReferencesTask',
- createTask,
- buildInputs, <ResultDescriptor>[
- INFERABLE_STATIC_VARIABLES_IN_UNIT,
- CREATED_RESOLVED_UNIT7,
- RESOLVED_UNIT7
- ]);
-
- PartiallyResolveUnitReferencesTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- CompilationUnitElement unitElement = unit.declaredElement;
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- var inheritance = new InheritanceManager2(context.typeSystem);
- //
- // Resolve references and record outputs.
- //
- PartialResolverVisitor visitor = new PartialResolverVisitor(
- inheritance,
- libraryElement,
- unitElement.source,
- typeProvider,
- AnalysisErrorListener.NULL_LISTENER);
- unit.accept(visitor);
- //
- // Record outputs.
- //
- outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = visitor.staticVariables;
- outputs[RESOLVED_UNIT7] = unit;
- outputs[CREATED_RESOLVED_UNIT7] = true;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- 'fullyBuiltLibraryElements': READY_LIBRARY_ELEMENT6.of(unit.library),
- LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
- UNIT_INPUT: RESOLVED_UNIT6.of(unit),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
- // In strong mode, add additional dependencies to enforce inference
- // ordering.
-
- // Require that full inference be complete for all dependencies of the
- // current library cycle.
- 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
- .of(unit.library)
- .toListOf(CREATED_RESOLVED_UNIT10)
- };
- }
-
- /**
- * Create a [PartiallyResolveUnitReferencesTask] based on the given [target]
- * in the given [context].
- */
- static PartiallyResolveUnitReferencesTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new PartiallyResolveUnitReferencesTask(context, target);
- }
-}
-
-/**
- * A task that ensures that [LIBRARY_ELEMENT2] is ready for the target library
- * source and its import/export closure.
- */
-class ReadyLibraryElement2Task extends SourceBasedAnalysisTask {
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ReadyLibraryElement2Task',
- createTask,
- buildInputs,
- <ResultDescriptor>[READY_LIBRARY_ELEMENT2]);
-
- ReadyLibraryElement2Task(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- bool get handlesDependencyCycles => true;
-
- @override
- void internalPerform() {
- outputs[READY_LIBRARY_ELEMENT2] = true;
- }
-
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- 'thisLibraryElementReady': LIBRARY_ELEMENT2.of(source),
- 'directlyImportedLibrariesReady':
- IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT2),
- 'directlyExportedLibrariesReady':
- EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT2),
- };
- }
-
- static ReadyLibraryElement2Task createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ReadyLibraryElement2Task(context, target);
- }
-}
-
-/**
- * A task that ensures that [LIBRARY_ELEMENT6] is ready for the target library
- * source and its import/export closure.
- */
-class ReadyLibraryElement5Task extends SourceBasedAnalysisTask {
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ReadyLibraryElement5Task',
- createTask,
- buildInputs,
- <ResultDescriptor>[READY_LIBRARY_ELEMENT6]);
-
- ReadyLibraryElement5Task(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- bool get handlesDependencyCycles => true;
-
- @override
- void internalPerform() {
- outputs[READY_LIBRARY_ELEMENT6] = true;
- }
-
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- 'thisLibraryElementReady': LIBRARY_ELEMENT6.of(source),
- 'directlyImportedLibrariesReady':
- IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT6),
- 'directlyExportedLibrariesReady':
- EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT6),
- };
- }
-
- static ReadyLibraryElement5Task createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ReadyLibraryElement5Task(context, target);
- }
-}
-
-/**
- * A task that ensures that [LIBRARY_ELEMENT7] is ready for the target library
- * source and its import/export closure.
- */
-class ReadyLibraryElement7Task extends SourceBasedAnalysisTask {
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ReadyLibraryElement7Task',
- createTask,
- buildInputs,
- <ResultDescriptor>[READY_LIBRARY_ELEMENT7]);
-
- ReadyLibraryElement7Task(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- bool get handlesDependencyCycles => true;
-
- @override
- void internalPerform() {
- outputs[READY_LIBRARY_ELEMENT7] = true;
- }
-
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- 'thisLibraryElementReady': LIBRARY_ELEMENT7.of(source),
- 'directlyImportedLibrariesReady':
- IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT7),
- 'directlyExportedLibrariesReady':
- EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT7),
- };
- }
-
- static ReadyLibraryElement7Task createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ReadyLibraryElement7Task(context, target);
- }
-}
-
-/**
- * A task that ensures that [RESOLVED_UNIT] is ready for every unit of the
- * target library source and its import/export closure.
- */
-class ReadyResolvedUnitTask extends SourceBasedAnalysisTask {
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ReadyResolvedUnitTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[READY_RESOLVED_UNIT]);
-
- ReadyResolvedUnitTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- bool get handlesDependencyCycles => true;
-
- @override
- void internalPerform() {
- outputs[READY_RESOLVED_UNIT] = true;
- }
-
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- 'thisLibraryUnitsReady':
- LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT),
- };
- }
-
- static ReadyResolvedUnitTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ReadyResolvedUnitTask(context, target);
- }
-}
-
-/**
- * A task that ensures that the expression AST for a constant is resolved and
- * sets the [CONSTANT_EXPRESSION_RESOLVED] result.
- */
-class ResolveConstantExpressionTask extends ConstantEvaluationAnalysisTask {
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveConstantExpressionTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[CONSTANT_EXPRESSION_RESOLVED]);
-
- ResolveConstantExpressionTask(
- InternalAnalysisContext context, ConstantEvaluationTarget constant)
- : super(context, constant);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Record outputs.
- //
- outputs[CONSTANT_EXPRESSION_RESOLVED] = true;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source librarySource;
- if (target is Element) {
- CompilationUnitElementImpl unit = target
- .getAncestor((Element element) => element is CompilationUnitElement);
- librarySource = unit.librarySource;
- } else if (target is ElementAnnotationImpl) {
- librarySource = target.librarySource;
- } else {
- throw new AnalysisException(
- 'Cannot build inputs for a ${target.runtimeType}');
- }
- return <String, TaskInput>{
- 'createdResolvedUnit': CREATED_RESOLVED_UNIT11
- .of(new LibrarySpecificUnit(librarySource, target.source))
- };
- }
-
- /**
- * Create a [ResolveConstantExpressionTask] based on the given [target] in
- * the given [context].
- */
- static ResolveConstantExpressionTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveConstantExpressionTask(context, target);
- }
-}
-
-/**
- * A task that resolves imports and export directives to already built elements.
- */
-class ResolveDirectiveElementsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the defining [LIBRARY_ELEMENT2].
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the input for [RESOLVED_UNIT1] of a unit.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- static const String SOURCES_MODIFICATION_TIME_INPUT =
- 'SOURCES_MODIFICATION_TIME_INPUT';
- static const String IMPORTS_SOURCE_KIND_INPUT = 'IMPORTS_SOURCE_KIND_INPUT';
- static const String EXPORTS_SOURCE_KIND_INPUT = 'EXPORTS_SOURCE_KIND_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveDirectiveElementsTask',
- createTask,
- buildInputs, <ResultDescriptor>[
- CREATED_RESOLVED_UNIT2,
- RESOLVED_UNIT2,
- RESOLVE_DIRECTIVES_ERRORS
- ]);
-
- ResolveDirectiveElementsTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- LibrarySpecificUnit targetUnit = target;
- //
- // Prepare inputs.
- //
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- Map<Source, int> sourceModificationTimeMap =
- getRequiredInput(SOURCES_MODIFICATION_TIME_INPUT);
- Map<Source, SourceKind> importSourceKindMap =
- getRequiredInput(IMPORTS_SOURCE_KIND_INPUT);
- Map<Source, SourceKind> exportSourceKindMap =
- getRequiredInput(EXPORTS_SOURCE_KIND_INPUT);
- //
- // Resolve directive AST nodes to elements.
- //
- List<AnalysisError> errors = const <AnalysisError>[];
- if (targetUnit.unit == targetUnit.library) {
- DirectiveResolver resolver = new DirectiveResolver(
- sourceModificationTimeMap, importSourceKindMap, exportSourceKindMap);
- unit.accept(resolver);
- errors = resolver.errors;
- }
- //
- // Record outputs.
- //
- outputs[CREATED_RESOLVED_UNIT2] = true;
- outputs[RESOLVED_UNIT2] = unit;
- outputs[RESOLVE_DIRECTIVES_ERRORS] = errors;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- LIBRARY_INPUT: LIBRARY_ELEMENT2.of(unit.library),
- UNIT_INPUT: RESOLVED_UNIT1.of(unit),
- SOURCES_MODIFICATION_TIME_INPUT:
- REFERENCED_SOURCES.of(unit.library).toMapOf(MODIFICATION_TIME),
- IMPORTS_SOURCE_KIND_INPUT:
- IMPORTED_LIBRARIES.of(unit.library).toMapOf(SOURCE_KIND),
- EXPORTS_SOURCE_KIND_INPUT:
- EXPORTED_LIBRARIES.of(unit.library).toMapOf(SOURCE_KIND)
- };
- }
-
- /**
- * Create a [ResolveDirectiveElementsTask] based on the given [target] in
- * the given [context].
- */
- static ResolveDirectiveElementsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveDirectiveElementsTask(context, target);
- }
-}
-
-/**
- * An artificial task that does nothing except to force [LIBRARY_ELEMENT7] for
- * the target library and its import/export closure.
- */
-class ResolvedUnit7InLibraryClosureTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT7] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolvedUnit7InLibraryClosureTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ELEMENT8]);
-
- ResolvedUnit7InLibraryClosureTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- LibraryElement library = getRequiredInput(LIBRARY_INPUT);
- outputs[LIBRARY_ELEMENT8] = library;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- 'readyForClosure': READY_LIBRARY_ELEMENT7.of(source),
- LIBRARY_INPUT: LIBRARY_ELEMENT7.of(source),
- };
- }
-
- /**
- * Create a [ResolvedUnit7InLibraryClosureTask] based on the given
- * [target] in the given [context].
- */
- static ResolvedUnit7InLibraryClosureTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolvedUnit7InLibraryClosureTask(context, target);
- }
-}
-
-/**
- * An artificial task that does nothing except to force [LIBRARY_ELEMENT6] and
- * [RESOLVED_UNIT7] in the defining and part units of a library.
- */
-class ResolvedUnit7InLibraryTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT6] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolvedUnit7InLibraryTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ELEMENT7]);
-
- ResolvedUnit7InLibraryTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- LibraryElement library = getRequiredInput(LIBRARY_INPUT);
- outputs[LIBRARY_ELEMENT7] = library;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- 'resolvedUnits':
- LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT7),
- LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source),
- };
- }
-
- /**
- * Create a [ResolvedUnit7InLibraryTask] based on the given [target]
- * in the given [context].
- */
- static ResolvedUnit7InLibraryTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolvedUnit7InLibraryTask(context, target);
- }
-}
-
-/**
- * A task that ensures that all of the inferable instance members in a
- * compilation unit have had their right hand sides re-resolved
- */
-class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT6] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The name of the input whose value is the [RESOLVED_UNIT8] for the
- * compilation unit.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveInstanceFieldsInUnitTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[CREATED_RESOLVED_UNIT9, RESOLVED_UNIT9]);
-
- /**
- * Initialize a newly created task to build a library element for the given
- * [unit] in the given [context].
- */
- ResolveInstanceFieldsInUnitTask(
- InternalAnalysisContext context, LibrarySpecificUnit unit)
- : super(context, unit);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- var inheritance = new InheritanceManager2(context.typeSystem);
-
- CompilationUnitElement unitElement = unit.declaredElement;
- //
- // Resolve references.
- //
- InstanceFieldResolverVisitor visitor = new InstanceFieldResolverVisitor(
- inheritance,
- libraryElement,
- unitElement.source,
- typeProvider,
- AnalysisErrorListener.NULL_LISTENER);
- visitor.resolveCompilationUnit(unit);
- //
- // Record outputs.
- //
- outputs[RESOLVED_UNIT9] = unit;
- outputs[CREATED_RESOLVED_UNIT9] = true;
- }
-
- /**
- * 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].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- UNIT_INPUT: RESOLVED_UNIT8.of(unit),
- LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
- // In strong mode, add additional dependencies to enforce inference
- // ordering.
-
- // Require that static variable inference be complete for all units in
- // the current library cycle.
- 'orderLibraryCycleTasks':
- LIBRARY_CYCLE_UNITS.of(unit.library).toListOf(CREATED_RESOLVED_UNIT8),
- // Require that full inference be complete for all dependencies of the
- // current library cycle.
- 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
- .of(unit.library)
- .toListOf(CREATED_RESOLVED_UNIT10)
- };
- }
-
- /**
- * Create a [ResolveInstanceFieldsInUnitTask] based on the given [target] in
- * the given [context].
- */
- static ResolveInstanceFieldsInUnitTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveInstanceFieldsInUnitTask(context, target);
- }
-}
-
-/**
- * A task that finishes resolution by requesting [RESOLVED_UNIT11] for every
- * unit in the libraries closure and produces [LIBRARY_ELEMENT9].
- */
-class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT8] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveLibraryReferencesTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ELEMENT9]);
-
- ResolveLibraryReferencesTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- LibraryElement library = getRequiredInput(LIBRARY_INPUT);
- outputs[LIBRARY_ELEMENT9] = library;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- LIBRARY_INPUT: LIBRARY_ELEMENT8.of(source),
- 'resolvedUnits':
- LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT11),
- };
- }
-
- /**
- * Create a [ResolveLibraryReferencesTask] based on the given [target] in
- * the given [context].
- */
- static ResolveLibraryReferencesTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveLibraryReferencesTask(context, target);
- }
-}
-
-/**
- * A task that finishes resolution by requesting [RESOLVED_UNIT12] for every
- * unit in the libraries closure and produces [LIBRARY_ELEMENT].
- */
-class ResolveLibraryTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT9] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the list of [RESOLVED_UNIT12] input.
- */
- static const String UNITS_INPUT = 'UNITS_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveLibraryTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ELEMENT]);
-
- ResolveLibraryTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibraryElement library = getRequiredInput(LIBRARY_INPUT);
- //
- // Record outputs.
- //
- outputs[LIBRARY_ELEMENT] = library;
- }
-
-/**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- LIBRARY_INPUT: LIBRARY_ELEMENT9.of(source),
- 'thisLibraryClosureIsReady': READY_RESOLVED_UNIT.of(source),
- };
- }
-
-/**
- * Create a [ResolveLibraryTask] based on the given [target] in the given
- * [context].
- */
- static ResolveLibraryTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveLibraryTask(context, target);
- }
-}
-
-/**
- * An artificial task that does nothing except to force type names resolution
- * for the defining and part units of a library.
- */
-class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT5] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveLibraryTypeNamesTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ELEMENT6]);
-
- ResolveLibraryTypeNamesTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibraryElement library = getRequiredInput(LIBRARY_INPUT);
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- //
- // Create the synthetic element for `loadLibrary`.
- //
- (library as LibraryElementImpl).createLoadLibraryFunction(typeProvider);
- //
- // Record outputs.
- //
- outputs[LIBRARY_ELEMENT6] = library;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- 'resolvedUnit':
- LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT5),
- LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
- };
- }
-
- /**
- * Create a [ResolveLibraryTypeNamesTask] based on the given [target] in
- * the given [context].
- */
- static ResolveLibraryTypeNamesTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveLibraryTypeNamesTask(context, target);
- }
-}
-
-/**
- * An artificial task that does nothing except to force type parameter bounds
- * type names resolution for the defining and part units of a library.
- */
-class ResolveTopLevelLibraryTypeBoundsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT4] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveTopLevelLibraryTypeBoundsTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[LIBRARY_ELEMENT5]);
-
- ResolveTopLevelLibraryTypeBoundsTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- bool get handlesDependencyCycles => true;
-
- @override
- void internalPerform() {
- LibraryElement library = getRequiredInput(LIBRARY_INPUT);
- outputs[LIBRARY_ELEMENT5] = library;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- Source source = target;
- return <String, TaskInput>{
- LIBRARY_INPUT: LIBRARY_ELEMENT4.of(source),
- 'thisLibraryUnitsReady':
- LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT4),
- 'directlyImportedLibrariesReady':
- IMPORTED_LIBRARIES.of(source).toListOf(LIBRARY_ELEMENT5),
- 'directlyExportedLibrariesReady':
- EXPORTED_LIBRARIES.of(source).toListOf(LIBRARY_ELEMENT5),
- };
- }
-
- /**
- * Create a [ResolveTopLevelLibraryTypeBoundsTask] based on the given [target]
- * in the given [context].
- */
- static ResolveTopLevelLibraryTypeBoundsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveTopLevelLibraryTypeBoundsTask(context, target);
- }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT4] for a unit.
- */
-class ResolveTopLevelUnitTypeBoundsTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the defining [LIBRARY_ELEMENT4].
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the [RESOLVED_UNIT3] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveTopLevelUnitTypeBoundsTask',
- createTask,
- buildInputs, <ResultDescriptor>[
- RESOLVE_TYPE_BOUNDS_ERRORS,
- CREATED_RESOLVED_UNIT4,
- RESOLVED_UNIT4
- ]);
-
- ResolveTopLevelUnitTypeBoundsTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibraryElement library = getRequiredInput(LIBRARY_INPUT);
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- CompilationUnitElement unitElement = unit.declaredElement;
- //
- // Resolve TypeName nodes.
- //
- RecordingErrorListener errorListener = new RecordingErrorListener();
- new TypeParameterBoundsResolver(
- context.typeSystem, library, unitElement.source, errorListener)
- .resolveTypeBounds(unit);
- //
- // Record outputs.
- //
- outputs[RESOLVE_TYPE_BOUNDS_ERRORS] =
- getTargetSourceErrors(errorListener, target);
- outputs[RESOLVED_UNIT4] = unit;
- outputs[CREATED_RESOLVED_UNIT4] = true;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- // TODO(brianwilkerson) This task updates the element model to have type
- // information and updates the class hierarchy. It should produce a new
- // version of the element model in order to record those changes.
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- 'importsExportNamespace':
- IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4),
- 'dependOnAllExportedSources':
- IMPORTED_LIBRARIES.of(unit.library).toMapOf(EXPORT_SOURCE_CLOSURE),
- LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
- UNIT_INPUT: RESOLVED_UNIT3.of(unit)
- };
- }
-
- /**
- * Create a [ResolveTopLevelUnitTypeBoundsTask] based on the given [target] in
- * the given [context].
- */
- static ResolveTopLevelUnitTypeBoundsTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveTopLevelUnitTypeBoundsTask(context, target);
- }
-}
-
-/**
- * A task that resolves the bodies of top-level functions, constructors, and
- * methods within a single compilation unit.
- */
-class ResolveUnitTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the defining [LIBRARY_ELEMENT8].
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The name of the [RESOLVED_UNIT10] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveUnitTask', createTask, buildInputs, <ResultDescriptor>[
- CONSTANT_EXPRESSIONS_DEPENDENCIES,
- RESOLVE_UNIT_ERRORS,
- CREATED_RESOLVED_UNIT11,
- RESOLVED_UNIT11
- ]);
-
- ResolveUnitTask(
- InternalAnalysisContext context, LibrarySpecificUnit compilationUnit)
- : super(context, compilationUnit);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibrarySpecificUnit target = this.target;
- LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- var inheritance = new InheritanceManager2(context.typeSystem);
- //
- // Resolve everything.
- //
- CompilationUnitElement unitElement = unit.declaredElement;
- RecordingErrorListener errorListener = new RecordingErrorListener();
- ResolverVisitor visitor = new ResolverVisitor(inheritance, libraryElement,
- unitElement.source, typeProvider, errorListener);
- unit.accept(visitor);
- //
- // Compute constant expressions' dependencies.
- //
- List<ConstantEvaluationTarget> constExprDependencies;
- {
- ConstantExpressionsDependenciesFinder finder =
- new ConstantExpressionsDependenciesFinder();
- unit.accept(finder);
- constExprDependencies = finder.dependencies.toList();
- }
- //
- // Record outputs.
- //
- // TODO(brianwilkerson) This task modifies the element model (by copying the
- // AST's for constructor initializers into it) but does not produce an
- // updated version of the element model.
- //
- outputs[CONSTANT_EXPRESSIONS_DEPENDENCIES] = constExprDependencies;
- outputs[RESOLVE_UNIT_ERRORS] = getTargetSourceErrors(errorListener, target);
- outputs[RESOLVED_UNIT11] = unit;
- outputs[CREATED_RESOLVED_UNIT11] = true;
- }
-
- /**
- * 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
- * [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- LIBRARY_INPUT: LIBRARY_ELEMENT8.of(unit.library),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
- UNIT_INPUT: RESOLVED_UNIT10.of(unit),
- // In strong mode, add additional dependencies to enforce inference
- // ordering.
-
- // Require that inference be complete for all units in the
- // current library cycle.
- 'orderLibraryCycleTasks':
- LIBRARY_CYCLE_UNITS.of(unit.library).toListOf(CREATED_RESOLVED_UNIT10)
- };
- }
-
- /**
- * Create a [ResolveUnitTask] based on the given [target] in
- * the given [context].
- */
- static ResolveUnitTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveUnitTask(context, target);
- }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT5] for a unit.
- */
-class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the defining [LIBRARY_ELEMENT5].
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the [RESOLVED_UNIT4] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveUnitTypeNamesTask', createTask, buildInputs, <ResultDescriptor>[
- RESOLVE_TYPE_NAMES_ERRORS,
- CREATED_RESOLVED_UNIT5,
- RESOLVED_UNIT5
- ]);
-
- ResolveUnitTypeNamesTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibraryElement library = getRequiredInput(LIBRARY_INPUT);
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- CompilationUnitElement unitElement = unit.declaredElement;
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- //
- // Resolve TypeName nodes.
- //
- RecordingErrorListener errorListener = new RecordingErrorListener();
- TypeResolverVisitor visitor = new TypeResolverVisitor(
- library, unitElement.source, typeProvider, errorListener,
- shouldUseWithClauseInferredTypes: false,
- shouldSetElementSupertypes: true);
- unit.accept(visitor);
- //
- // Re-write the AST to handle the optional new and const feature.
- //
- unit.accept(new AstRewriteVisitor(context.typeSystem, library,
- unit.declaredElement.source, typeProvider, errorListener));
- //
- // Record outputs.
- //
- outputs[RESOLVE_TYPE_NAMES_ERRORS] =
- getTargetSourceErrors(errorListener, target);
- outputs[RESOLVED_UNIT5] = unit;
- outputs[CREATED_RESOLVED_UNIT5] = true;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- // TODO(brianwilkerson) This task updates the element model to have type
- // information and updates the class hierarchy. It should produce a new
- // version of the element model in order to record those changes.
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
- UNIT_INPUT: RESOLVED_UNIT4.of(unit),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
- };
- }
-
- /**
- * Create a [ResolveUnitTypeNamesTask] based on the given [target] in
- * the given [context].
- */
- static ResolveUnitTypeNamesTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveUnitTypeNamesTask(context, target);
- }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT6] for a unit.
- */
-class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT1] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the [RESOLVED_UNIT5] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveVariableReferencesTask',
- createTask,
- buildInputs, <ResultDescriptor>[
- CREATED_RESOLVED_UNIT6,
- RESOLVED_UNIT6,
- VARIABLE_REFERENCE_ERRORS
- ]);
-
- ResolveVariableReferencesTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- CompilationUnitElement unitElement = unit.declaredElement;
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- //
- // Resolve local variables.
- //
- RecordingErrorListener errorListener = new RecordingErrorListener();
- Scope nameScope = new LibraryScope(libraryElement);
- VariableResolverVisitor visitor = new VariableResolverVisitor(
- libraryElement, unitElement.source, typeProvider, errorListener,
- nameScope: nameScope);
- unit.accept(visitor);
- //
- // Record outputs.
- //
- outputs[RESOLVED_UNIT6] = unit;
- outputs[CREATED_RESOLVED_UNIT6] = true;
- outputs[VARIABLE_REFERENCE_ERRORS] =
- getTargetSourceErrors(errorListener, target);
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- LIBRARY_INPUT: LIBRARY_ELEMENT1.of(unit.library),
- UNIT_INPUT: RESOLVED_UNIT5.of(unit),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
- };
- }
-
- /**
- * Create a [ResolveVariableReferencesTask] based on the given [target] in
- * the given [context].
- */
- static ResolveVariableReferencesTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveVariableReferencesTask(context, target);
- }
-}
-
-/**
- * A task that scans the content of a Dart file, producing a stream of Dart
- * tokens, line information, and any lexical errors encountered in the process.
- */
-class ScanDartTask extends SourceBasedAnalysisTask {
- /**
- * The name of the input whose value is the content of the file.
- */
- static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME';
-
- /**
- * The name of the input whose value is the modification time of the file.
- */
- static const String MODIFICATION_TIME_INPUT = 'MODIFICATION_TIME_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ScanDartTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[IGNORE_INFO, LINE_INFO, SCAN_ERRORS, TOKEN_STREAM],
- suitabilityFor: suitabilityFor);
-
- /**
- * Initialize a newly created task to access the content of the source
- * associated with the given [target] in the given [context].
- */
- ScanDartTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- Source source = getRequiredSource();
- RecordingErrorListener errorListener = new RecordingErrorListener();
-
- int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT);
- if (modificationTime < 0) {
- String message = 'Content could not be read';
- if (context is InternalAnalysisContext) {
- CacheEntry entry =
- (context as InternalAnalysisContext).getCacheEntry(target);
- CaughtException exception = entry.exception;
- if (exception != null) {
- message = exception.toString();
- }
- }
- if (source.exists()) {
- errorListener.onError(new AnalysisError(
- source, 0, 0, ScannerErrorCode.UNABLE_GET_CONTENT, [message]));
- }
- }
- }
-
- /**
- * 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
- * [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- if (target is Source) {
- return <String, TaskInput>{
- CONTENT_INPUT_NAME: CONTENT.of(target, flushOnAccess: true),
- MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(target)
- };
- }
- throw new AnalysisException(
- 'Cannot build inputs for a ${target.runtimeType}');
- }
-
- /**
- * Create a [ScanDartTask] based on the given [target] in the given [context].
- */
- static ScanDartTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ScanDartTask(context, target);
- }
-
- /**
- * Return an indication of how suitable this task is for the given [target].
- */
- static TaskSuitability suitabilityFor(AnalysisTarget target) {
- if (target is Source) {
- if (target.shortName.endsWith(AnalysisEngine.SUFFIX_DART)) {
- return TaskSuitability.HIGHEST;
- }
- return TaskSuitability.LOWEST;
- }
- return TaskSuitability.NONE;
- }
-}
-
-/**
- * A task that builds [STRONG_MODE_ERRORS] for a unit. Also builds
- * [RESOLVED_UNIT] for a unit.
- */
-class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [RESOLVED_UNIT12] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'StrongModeVerifyUnitTask', createTask, buildInputs, <ResultDescriptor>[
- STRONG_MODE_ERRORS,
- CREATED_RESOLVED_UNIT,
- RESOLVED_UNIT
- ]);
-
- StrongModeVerifyUnitTask(
- InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- RecordingErrorListener errorListener = new RecordingErrorListener();
- //
- // Prepare inputs.
- //
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- AnalysisOptionsImpl options = context.analysisOptions;
- if (options.strongMode) {
- CodeChecker checker = new CodeChecker(
- typeProvider,
- new Dart2TypeSystem(typeProvider,
- implicitCasts: options.implicitCasts),
- errorListener,
- options);
- checker.visitCompilationUnit(unit);
- }
- //
- // Record outputs.
- //
- outputs[STRONG_MODE_ERRORS] = getUniqueErrors(errorListener.errors);
- outputs[CREATED_RESOLVED_UNIT] = true;
- outputs[RESOLVED_UNIT] = unit;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- UNIT_INPUT: RESOLVED_UNIT12.of(unit),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
- };
- }
-
- /**
- * Create a [StrongModeVerifyUnitTask] based on the given [target] in
- * the given [context].
- */
- static StrongModeVerifyUnitTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new StrongModeVerifyUnitTask(context, target);
- }
-}
-
-/**
- * A task that builds [VERIFY_ERRORS] for a unit.
- */
-class VerifyUnitTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [PENDING_ERRORS] input.
- */
- static const String PENDING_ERRORS_INPUT = 'PENDING_ERRORS_INPUT';
-
- /**
- * The name of the input of a mapping from [REFERENCED_SOURCES] to their
- * [MODIFICATION_TIME]s.
- */
- static const String REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT =
- 'REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The name of the [RESOLVED_UNIT] input.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('VerifyUnitTask',
- createTask, buildInputs, <ResultDescriptor>[VERIFY_ERRORS]);
-
- /**
- * The [ErrorReporter] to report errors to.
- */
- ErrorReporter errorReporter;
-
- /**
- * The mapping from the current library referenced sources to their
- * modification times.
- */
- Map<Source, int> sourceTimeMap;
-
- VerifyUnitTask(InternalAnalysisContext context, AnalysisTarget target)
- : super(context, target);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- RecordingErrorListener errorListener = new RecordingErrorListener();
- Source source = getRequiredSource();
- errorReporter = new ErrorReporter(errorListener, source);
- //
- // Prepare inputs.
- //
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- CompilationUnitElement unitElement = unit.declaredElement;
- LibraryElement libraryElement = unitElement.library;
- if (libraryElement == null) {
- throw new AnalysisException(
- 'VerifyUnitTask verifying a unit with no library: '
- '${unitElement.source.fullName}');
- }
- List<PendingError> pendingErrors = getRequiredInput(PENDING_ERRORS_INPUT);
- sourceTimeMap =
- getRequiredInput(REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT);
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- //
- // Validate the directives.
- //
- validateDirectives(unit);
- //
- // Use the ConstantVerifier to compute errors.
- //
- ConstantVerifier constantVerifier = new ConstantVerifier(
- errorReporter, libraryElement, typeProvider, context.declaredVariables);
- unit.accept(constantVerifier);
-
- //
- // Compute inheritance and override errors.
- //
- var typeSystem = libraryElement.context.typeSystem;
- var inheritanceManager = new InheritanceManager2(typeSystem);
- var inheritanceOverrideVerifier = new InheritanceOverrideVerifier(
- typeSystem, inheritanceManager, errorReporter);
- inheritanceOverrideVerifier.verifyUnit(unit);
-
- //
- // Use the ErrorVerifier to compute errors.
- //
- ErrorVerifier errorVerifier = new ErrorVerifier(
- errorReporter, libraryElement, typeProvider, inheritanceManager, false,
- disableConflictingGenericsCheck: true);
- unit.accept(errorVerifier);
- //
- // Convert the pending errors into actual errors.
- //
- for (PendingError pendingError in pendingErrors) {
- errorListener.onError(pendingError.toAnalysisError());
- }
- //
- // Record outputs.
- //
- outputs[VERIFY_ERRORS] = getUniqueErrors(errorListener.errors);
- }
-
- /**
- * Check each directive in the given [unit] to see if the referenced source
- * exists and report an error if it does not.
- */
- void validateDirectives(CompilationUnit unit) {
- NodeList<Directive> directives = unit.directives;
- int length = directives.length;
- for (int i = 0; i < length; i++) {
- Directive directive = directives[i];
- if (directive is UriBasedDirective) {
- validateReferencedSource(directive);
- }
- }
- }
-
- /**
- * Check the given [directive] to see if the referenced source exists and
- * report an error if it does not.
- */
- void validateReferencedSource(UriBasedDirectiveImpl directive) {
- if (directive is NamespaceDirectiveImpl) {
- for (Configuration configuration in directive.configurations) {
- Source source = configuration.uriSource;
- StringLiteral uriLiteral = configuration.uri;
- String uriContent = uriLiteral?.stringValue?.trim();
- if (source != null) {
- int modificationTime = sourceTimeMap[source] ?? -1;
- if (modificationTime >= 0) {
- continue;
- }
- } else {
- // Don't report errors already reported by ParseDartTask.resolveDirective
- if (UriBasedDirectiveImpl.validateUri(
- directive is ImportDirective, uriLiteral, uriContent) !=
- null) {
- continue;
- }
- }
- CompileTimeErrorCode errorCode =
- CompileTimeErrorCode.URI_DOES_NOT_EXIST;
- if (_isGenerated(source)) {
- errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
- }
- errorReporter.reportErrorForNode(errorCode, uriLiteral, [uriContent]);
- }
- }
- Source source = directive.uriSource;
- if (source != null) {
- int modificationTime = sourceTimeMap[source] ?? -1;
- if (modificationTime >= 0) {
- return;
- }
- } else {
- // Don't report errors already reported by ParseDartTask.resolveDirective
- if (directive.validate() != null) {
- return;
- }
- }
- StringLiteral uriLiteral = directive.uri;
- CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
- if (_isGenerated(source)) {
- errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
- }
- errorReporter
- .reportErrorForNode(errorCode, uriLiteral, [directive.uriContent]);
- }
-
- /**
- * Return `true` if the given [source] refers to a file that is assumed to be
- * generated.
- */
- bool _isGenerated(Source source) {
- if (source == null) {
- return false;
- }
- // TODO(brianwilkerson) Generalize this mechanism.
- const List<String> suffixes = const <String>[
- '.g.dart',
- '.pb.dart',
- '.pbenum.dart',
- '.pbserver.dart',
- '.pbjson.dart',
- '.template.dart'
- ];
- String fullName = source.fullName;
- for (String suffix in suffixes) {
- if (fullName.endsWith(suffix)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * 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 [target].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- 'thisLibraryClosureIsReady': READY_RESOLVED_UNIT.of(unit.library),
- UNIT_INPUT: RESOLVED_UNIT.of(unit),
- REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT:
- REFERENCED_SOURCES.of(unit.library).toMapOf(MODIFICATION_TIME),
- PENDING_ERRORS_INPUT: PENDING_ERRORS.of(unit),
- 'requiredConstants': REQUIRED_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
- };
- }
-
- /**
- * Create a [VerifyUnitTask] based on the given [target] in
- * the given [context].
- */
- static VerifyUnitTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new VerifyUnitTask(context, target);
- }
-}
-
-/**
- * A [TaskInput] whose value is a list of library sources exported directly
- * or indirectly by the target [Source].
- *
- * [resultDescriptor] is the type of result which should be produced for each
- * target [Source].
- */
-class _ExportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
- final Source target;
- final ResultDescriptor resultDescriptor;
-
- _ExportSourceClosureTaskInput(this.target, this.resultDescriptor);
-
- @override
- TaskInputBuilder<List<Source>> createBuilder() =>
- new _SourceClosureTaskInputBuilder(
- target, _SourceClosureKind.EXPORT, resultDescriptor);
-}
-
-/**
- * An object holding either the name or the source associated with a part-of
- * directive.
- */
-class _NameOrSource {
- final String name;
-
- final Source source;
-
- _NameOrSource(this.name, this.source);
-}
-
-/**
- * The kind of the source closure to build.
- */
-enum _SourceClosureKind { IMPORT, EXPORT, IMPORT_EXPORT }
-
-/**
- * A [TaskInputBuilder] used by [_ExportSourceClosureTaskInput].
- */
-class _SourceClosureTaskInputBuilder implements TaskInputBuilder<List<Source>> {
- final _SourceClosureKind kind;
- final Set<LibraryElement> _libraries = new HashSet<LibraryElement>();
- final List<Source> _newSources = <Source>[];
-
- @override
- final ResultDescriptor currentResult;
-
- Source currentTarget;
-
- _SourceClosureTaskInputBuilder(
- Source librarySource, this.kind, this.currentResult) {
- _newSources.add(librarySource);
- }
-
- @override
- void set currentValue(Object value) {
- LibraryElement library = value;
- if (_libraries.add(library)) {
- if (kind == _SourceClosureKind.IMPORT ||
- kind == _SourceClosureKind.IMPORT_EXPORT) {
- List<ImportElement> imports = library.imports;
- int length = imports.length;
- for (int i = 0; i < length; i++) {
- ImportElement importElement = imports[i];
- Source importedSource = importElement.importedLibrary?.source;
- if (importedSource != null) {
- _newSources.add(importedSource);
- }
- }
- }
- if (kind == _SourceClosureKind.EXPORT ||
- kind == _SourceClosureKind.IMPORT_EXPORT) {
- List<ExportElement> exports = library.exports;
- int length = exports.length;
- for (int i = 0; i < length; i++) {
- ExportElement exportElement = exports[i];
- Source exportedSource = exportElement.exportedLibrary?.source;
- if (exportedSource != null) {
- _newSources.add(exportedSource);
- }
- }
- }
- }
- }
-
- @override
- bool get flushOnAccess => false;
-
- @override
- List<Source> get inputValue {
- return _libraries.map((LibraryElement library) => library.source).toList();
- }
-
- @override
- void currentValueNotAvailable() {
- // Nothing needs to be done. moveNext() will simply go on to the next new
- // source.
- }
-
- @override
- bool moveNext() {
- if (_newSources.isEmpty) {
- return false;
- }
- currentTarget = _newSources.removeLast();
- return true;
- }
-}
diff --git a/pkg/analyzer/lib/src/task/dart_work_manager.dart b/pkg/analyzer/lib/src/task/dart_work_manager.dart
deleted file mode 100644
index 5aa9869..0000000
--- a/pkg/analyzer/lib/src/task/dart_work_manager.dart
+++ /dev/null
@@ -1,498 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:collection';
-
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/generated/engine.dart'
- show AnalysisEngine, AnalysisErrorInfo, CacheState, InternalAnalysisContext;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_collection.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-
-/**
- * The manager for Dart specific analysis.
- */
-class DartWorkManager implements WorkManager {
- /**
- * The list of errors that are reported for raw Dart [Source]s.
- */
- static final List<ResultDescriptor<List<AnalysisError>>> _SOURCE_ERRORS =
- <ResultDescriptor<List<AnalysisError>>>[
- BUILD_DIRECTIVES_ERRORS,
- BUILD_LIBRARY_ERRORS,
- PARSE_ERRORS,
- SCAN_ERRORS
- ];
-
- /**
- * The list of errors that are reported for raw Dart [LibrarySpecificUnit]s.
- */
- static final List<ResultDescriptor<List<AnalysisError>>> _UNIT_ERRORS =
- <ResultDescriptor<List<AnalysisError>>>[
- HINTS,
- LINTS,
- LIBRARY_UNIT_ERRORS,
- RESOLVE_DIRECTIVES_ERRORS,
- RESOLVE_TYPE_NAMES_ERRORS,
- RESOLVE_TYPE_BOUNDS_ERRORS,
- RESOLVE_UNIT_ERRORS,
- STRONG_MODE_ERRORS,
- VARIABLE_REFERENCE_ERRORS,
- VERIFY_ERRORS
- ];
-
- final InternalAnalysisContext context;
-
- /**
- * The [TargetedResult]s that should be computed with priority.
- */
- final LinkedHashSet<TargetedResult> priorityResultQueue =
- new LinkedHashSet<TargetedResult>();
-
- /**
- * The sources whose kind we don't know yet.
- */
- final LinkedHashSet<Source> unknownSourceQueue = new LinkedHashSet<Source>();
-
- /**
- * The queue of library sources to process.
- */
- final LinkedHashSet<Source> librarySourceQueue = new LinkedHashSet<Source>();
-
- /**
- * A table mapping library sources to the part sources they include.
- */
- final HashMap<Source, List<Source>> libraryPartsMap =
- new HashMap<Source, List<Source>>();
-
- /**
- * A table mapping part sources to the library sources that include them.
- */
- final HashMap<Source, List<Source>> partLibrariesMap =
- new HashMap<Source, List<Source>>();
-
- /**
- * Initialize a newly created manager.
- */
- DartWorkManager(this.context) {
- context.onResultInvalidated.listen((InvalidatedResult event) {
- if (event.descriptor == LIBRARY_ERRORS_READY) {
- CacheEntry entry = event.entry;
- if (entry.explicitlyAdded &&
- entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY) {
- librarySourceQueue.add(entry.target);
- }
- }
- });
- }
-
- /**
- * Returns the correctly typed result of `context.analysisCache`.
- */
- AnalysisCache get analysisCache => context.analysisCache;
-
- /**
- * The partition that contains analysis results that are not shared with other
- * contexts.
- */
- CachePartition get privateAnalysisCachePartition =>
- context.privateAnalysisCachePartition;
-
- /**
- * Specifies that the client want the given [result] of the given [target]
- * to be computed with priority.
- */
- void addPriorityResult(AnalysisTarget target, ResultDescriptor result) {
- priorityResultQueue.add(new TargetedResult(target, result));
- }
-
- @override
- void applyChange(List<Source> addedSources, List<Source> changedSources,
- List<Source> removedSources) {
- addedSources = addedSources.where(_isDartSource).toList();
- changedSources = changedSources
- .where(_isDartSource)
- .where((source) => _needsComputing(source, SOURCE_KIND))
- .toList();
- removedSources = removedSources.where(_isDartSource).toList();
- // unknown queue
- unknownSourceQueue.addAll(addedSources);
- unknownSourceQueue.addAll(changedSources);
- unknownSourceQueue.removeAll(removedSources);
- // library queue
- librarySourceQueue.removeAll(changedSources);
- librarySourceQueue.removeAll(removedSources);
- // parts in libraries
- for (Source changedSource in changedSources) {
- _onLibrarySourceChangedOrRemoved(changedSource);
- }
- for (Source removedSource in removedSources) {
- partLibrariesMap.remove(removedSource);
- _onLibrarySourceChangedOrRemoved(removedSource);
- }
- }
-
- @override
- void applyPriorityTargets(List<AnalysisTarget> targets) {
- // Unschedule the old targets.
- List<TargetedResult> resultsToUnschedule = <TargetedResult>[];
- for (TargetedResult result in priorityResultQueue) {
- if (result.result == LIBRARY_ERRORS_READY) {
- resultsToUnschedule.add(result);
- }
- }
- priorityResultQueue.removeAll(resultsToUnschedule);
- // Schedule new targets.
- for (AnalysisTarget target in targets) {
- if (_isDartSource(target)) {
- SourceKind sourceKind = analysisCache.getValue(target, SOURCE_KIND);
- if (sourceKind == SourceKind.UNKNOWN) {
- addPriorityResult(target, SOURCE_KIND);
- } else if (sourceKind == SourceKind.LIBRARY) {
- _schedulePriorityLibrarySourceAnalysis(target);
- } else if (sourceKind == SourceKind.PART) {
- List<Source> libraries = context.getLibrariesContaining(target);
- for (Source library in libraries) {
- addPriorityResult(library, LIBRARY_ERRORS_READY);
- }
- }
- }
- }
- }
-
- @override
- List<AnalysisError> getErrors(Source source) {
- if (!_isDartSource(source)) {
- return AnalysisError.NO_ERRORS;
- }
- // If analysis is finished, use all the errors.
- if (analysisCache.getState(source, DART_ERRORS) == CacheState.VALID) {
- return analysisCache.getValue(source, DART_ERRORS);
- }
- // If analysis is in progress, combine all known partial results.
- List<AnalysisError> errors = <AnalysisError>[];
- for (ResultDescriptor<List<AnalysisError>> descriptor in _SOURCE_ERRORS) {
- errors.addAll(analysisCache.getValue(source, descriptor));
- }
- for (Source library in context.getLibrariesContaining(source)) {
- LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source);
- for (ResultDescriptor<List<AnalysisError>> descriptor in _UNIT_ERRORS) {
- errors.addAll(analysisCache.getValue(unit, descriptor));
- }
- }
- return errors;
- }
-
- /**
- * Returns libraries containing the given [part].
- * Maybe empty, but not null.
- */
- List<Source> getLibrariesContainingPart(Source part) {
- if (part.isInSystemLibrary) {
- DartWorkManager sdkDartWorkManager = _getSdkDartWorkManager();
- if (sdkDartWorkManager != this) {
- return sdkDartWorkManager.getLibrariesContainingPart(part);
- }
- }
- List<Source> libraries = partLibrariesMap[part];
- libraries ??= _getLibrariesContainingPartFromResultProvider(part);
- return libraries?.toList() ?? const <Source>[];
- }
-
- @override
- TargetedResult getNextResult() {
- // Try to find a priority result to compute.
- while (priorityResultQueue.isNotEmpty) {
- TargetedResult result = priorityResultQueue.first;
- if (!_needsComputing(result.target, result.result)) {
- priorityResultQueue.remove(result);
- continue;
- }
- return result;
- }
- // Try to find a new library to analyze.
- while (librarySourceQueue.isNotEmpty) {
- Source librarySource = librarySourceQueue.first;
- // Maybe done with this library.
- if (!_needsComputing(librarySource, LIBRARY_ERRORS_READY)) {
- librarySourceQueue.remove(librarySource);
- continue;
- }
- // Analyze this library.
- return new TargetedResult(librarySource, LIBRARY_ERRORS_READY);
- }
- // No libraries in the queue, check whether there are sources to organize.
- while (unknownSourceQueue.isNotEmpty) {
- Source source = unknownSourceQueue.first;
- // Maybe done with this source.
- if (!_needsComputing(source, SOURCE_KIND)) {
- unknownSourceQueue.remove(source);
- continue;
- }
- // Compute the kind of this source.
- return new TargetedResult(source, SOURCE_KIND);
- }
- // TODO(scheglov) Report errors for parts that remained in the queue after
- // all libraries had been processed.
- // No results to compute.
- return null;
- }
-
- @override
- WorkOrderPriority getNextResultPriority() {
- if (priorityResultQueue.isNotEmpty) {
- return WorkOrderPriority.PRIORITY;
- }
- if (unknownSourceQueue.isNotEmpty || librarySourceQueue.isNotEmpty) {
- return WorkOrderPriority.NORMAL;
- }
- return WorkOrderPriority.NONE;
- }
-
- /**
- * Notifies the manager about analysis options changes.
- */
- void onAnalysisOptionsChanged() {
- _invalidateAllLocalResolutionInformation(false);
- }
-
- /**
- * Notifies the manager about [SourceFactory] changes.
- */
- void onSourceFactoryChanged() {
- _invalidateAllLocalResolutionInformation(true);
- }
-
- @override
- void resultsComputed(
- AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs) {
- bool isDartSource = _isDartSource(target);
- // Route SDK outputs to the SDK WorkManager.
- if (isDartSource && target.source.isInSystemLibrary) {
- DartWorkManager sdkWorkManager = _getSdkDartWorkManager();
- if (sdkWorkManager != this) {
- sdkWorkManager.resultsComputed(target, outputs);
- return;
- }
- }
- // Organize sources.
- bool isDartLibrarySource = false;
- if (isDartSource) {
- Source source = target;
- SourceKind kind = outputs[SOURCE_KIND];
- if (kind != null) {
- unknownSourceQueue.remove(source);
- if (kind == SourceKind.LIBRARY) {
- isDartLibrarySource = true;
- if (context.prioritySources.contains(source)) {
- _schedulePriorityLibrarySourceAnalysis(source);
- } else {
- bool needErrors = _shouldErrorsBeComputed(source);
- if (needErrors) {
- librarySourceQueue.add(target);
- }
- }
- }
- }
- }
- // Update parts in libraries.
- if (isDartLibrarySource) {
- Source library = target;
- List<Source> includedParts = outputs[INCLUDED_PARTS] as List<Source>;
- if (includedParts != null) {
- libraryPartsMap[library] = includedParts;
- for (Source part in includedParts) {
- List<Source> libraries =
- partLibrariesMap.putIfAbsent(part, () => <Source>[]);
- if (!libraries.contains(library)) {
- libraries.add(library);
- _invalidateContainingLibraries(part);
- }
- }
- }
- }
- // Update notice.
- if (isDartSource) {
- bool shouldSetErrors = false;
- outputs.forEach((ResultDescriptor descriptor, value) {
- if (descriptor == PARSED_UNIT && value != null) {
- context.getNotice(target).parsedDartUnit = value;
- shouldSetErrors = true;
- }
- if (descriptor == DART_ERRORS) {
- shouldSetErrors = true;
- }
- });
- if (shouldSetErrors) {
- AnalysisErrorInfo info = context.getErrors(target);
- context.getNotice(target).setErrors(info.errors, info.lineInfo);
- }
- }
- if (target is LibrarySpecificUnit) {
- Source source = target.source;
- bool shouldSetErrors = false;
- outputs.forEach((ResultDescriptor descriptor, value) {
- if (descriptor == RESOLVED_UNIT && value != null) {
- context.getNotice(source).resolvedDartUnit = value;
- shouldSetErrors = true;
- }
- });
- if (shouldSetErrors) {
- AnalysisErrorInfo info = context.getErrors(source);
- context.getNotice(source).setErrors(info.errors, info.lineInfo);
- }
- }
- }
-
- /**
- * The given unit was incrementally resolved. Some of its error results might
- * have been invalidated, so we schedule it for computing errors.
- */
- void unitIncrementallyResolved(Source librarySource, Source unitSource) {
- librarySourceQueue.add(librarySource);
- }
-
- /**
- * Ask the [context]'s result provider for [CONTAINING_LIBRARIES].
- * Return the list of containing libraries, or `null` if unknown.
- */
- List<Source> _getLibrariesContainingPartFromResultProvider(Source part) {
- CacheEntry cacheEntry = context.getCacheEntry(part);
- bool knows = context.aboutToComputeResult(cacheEntry, CONTAINING_LIBRARIES);
- if (knows) {
- return cacheEntry.getValue(CONTAINING_LIBRARIES);
- }
- return null;
- }
-
- /**
- * Return the SDK [DartWorkManager] or this one.
- */
- DartWorkManager _getSdkDartWorkManager() {
- SourceFactory sourceFactory = context.sourceFactory;
- InternalAnalysisContext sdkContext = sourceFactory.dartSdk.context;
- if (sdkContext != context) {
- for (WorkManager workManager in sdkContext.workManagers) {
- if (workManager is DartWorkManager) {
- return workManager;
- }
- }
- }
- return this;
- }
-
- /**
- * Invalidate all of the resolution results computed by this context. The flag
- * [invalidateUris] should be `true` if the cached results of converting URIs
- * to source files should also be invalidated.
- */
- void _invalidateAllLocalResolutionInformation(bool invalidateUris) {
- CachePartition partition = privateAnalysisCachePartition;
- // Prepare targets and values to invalidate.
- List<Source> dartSources = <Source>[];
- List<LibrarySpecificUnit> unitTargets = <LibrarySpecificUnit>[];
- MapIterator<AnalysisTarget, CacheEntry> iterator = partition.iterator();
- while (iterator.moveNext()) {
- AnalysisTarget target = iterator.key;
- // Optionally gather Dart sources to invalidate URIs resolution.
- if (invalidateUris && _isDartSource(target)) {
- dartSources.add(target);
- }
- // LibrarySpecificUnit(s) are roots of Dart resolution.
- // When one is invalidated, invalidation is propagated to all resolution.
- if (target is LibrarySpecificUnit) {
- unitTargets.add(target);
- Source library = target.library;
- if (context.exists(library)) {
- CacheEntry entry = iterator.value;
- if (entry.explicitlyAdded) {
- librarySourceQueue.add(library);
- }
- }
- }
- }
- // Invalidate targets and values.
- unitTargets.forEach(partition.remove);
- for (Source dartSource in dartSources) {
- CacheEntry entry = partition.get(dartSource);
- if (entry != null) {
- // TODO(scheglov) we invalidate too much.
- // Would be nice to invalidate just URLs resolution.
- entry.setState(PARSED_UNIT, CacheState.INVALID);
- entry.setState(IMPORTED_LIBRARIES, CacheState.INVALID);
- entry.setState(EXPLICITLY_IMPORTED_LIBRARIES, CacheState.INVALID);
- entry.setState(EXPORTED_LIBRARIES, CacheState.INVALID);
- entry.setState(INCLUDED_PARTS, CacheState.INVALID);
- entry.setState(LIBRARY_SPECIFIC_UNITS, CacheState.INVALID);
- entry.setState(UNITS, CacheState.INVALID);
- }
- }
- }
-
- /**
- * Invalidate [CONTAINING_LIBRARIES] for the given [source].
- * [CONTAINING_LIBRARIES] does not have dependencies, so we manage it here.
- * The [source] may be a part, or a library whose contents is updated so
- * will be a part.
- */
- void _invalidateContainingLibraries(Source source) {
- CacheEntry entry = analysisCache.get(source);
- if (entry != null) {
- entry.setState(CONTAINING_LIBRARIES, CacheState.INVALID);
- }
- }
-
- /**
- * Returns `true` if the given [result] of the given [target] needs
- * computing, i.e. it is not in the valid and not in the error state.
- */
- bool _needsComputing(AnalysisTarget target, ResultDescriptor result) {
- CacheState state = analysisCache.getState(target, result);
- return state != CacheState.VALID && state != CacheState.ERROR;
- }
-
- /**
- * The given [library] source was changed or removed.
- * Update [libraryPartsMap] and [partLibrariesMap].
- */
- void _onLibrarySourceChangedOrRemoved(Source library) {
- List<Source> parts = libraryPartsMap.remove(library);
- if (parts != null) {
- for (Source part in parts) {
- List<Source> libraries = partLibrariesMap[part];
- if (libraries != null) {
- libraries.remove(library);
- _invalidateContainingLibraries(part);
- }
- }
- }
- _invalidateContainingLibraries(library);
- }
-
- /**
- * Schedule computing [RESOLVED_UNIT] for the given [librarySource].
- * If errors should be computed, then schedule [LIBRARY_ERRORS_READY] instead,
- * it also computes [RESOLVED_UNIT] in process.
- */
- void _schedulePriorityLibrarySourceAnalysis(Source librarySource) {
- bool needErrors = _shouldErrorsBeComputed(librarySource);
- if (needErrors) {
- addPriorityResult(librarySource, LIBRARY_ERRORS_READY);
- } else {
- var target = new LibrarySpecificUnit(librarySource, librarySource);
- addPriorityResult(target, RESOLVED_UNIT);
- }
- }
-
- bool _shouldErrorsBeComputed(Source source) =>
- context.shouldErrorsBeAnalyzed(source);
-
- static bool _isDartSource(AnalysisTarget target) {
- return target is Source && AnalysisEngine.isDartFileName(target.fullName);
- }
-}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index feb81ad..8d9da75 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -198,10 +198,6 @@
} else if (element is MapLiteralEntry) {
checkAssignment(element.key, expectedKeyType);
checkAssignment(element.value, expectedValueType);
- } else if (element is SpreadElement) {
- DartType mapType = typeProvider.mapType
- .instantiate([expectedKeyType, expectedValueType]);
- checkAssignment(element.expression, mapType);
}
}
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 90dc42a..11b92be 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -252,6 +252,10 @@
return _node(search, (n) => n is VariableDeclaration);
}
+ VariableDeclarationList variableDeclarationList(String search) {
+ return _node(search, (n) => n is VariableDeclarationList);
+ }
+
WhileStatement whileStatement(String search) {
return _node(search, (n) => n is WhileStatement);
}
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 1906862..81048a3 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.35.3
+version: 0.35.4
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -11,13 +11,12 @@
collection: ^1.10.1
convert: ^2.0.0
crypto: '>=1.1.1 <3.0.0'
- front_end: 0.1.13
+ front_end: 0.1.14
glob: ^1.0.3
- kernel: 0.3.13
+ kernel: 0.3.14
meta: ^1.0.2
package_config: '>=0.1.5 <2.0.0'
path: '>=0.9.0 <2.0.0'
- plugin: ^0.2.0
pub_semver: ^1.4.2
source_span: ^1.2.0
watcher: '>=0.9.6 <0.10.0'
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index 2b99d3b..4ee79f0 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -24,6 +24,7 @@
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/string_source.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:test/test.dart';
/**
@@ -104,7 +105,6 @@
TestTypeProvider provider = new TestTypeProvider();
CompilationUnitElementImpl coreUnit = new CompilationUnitElementImpl();
Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
- coreContext.setContents(coreSource, "");
coreUnit.librarySource = coreUnit.source = coreSource;
ClassElementImpl overrideClassElement =
ElementFactory.classElement2("_Override");
@@ -185,7 +185,6 @@
AstTestFactory.libraryIdentifier2(["dart", "async"]));
CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl();
Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
- coreContext.setContents(asyncSource, "");
asyncUnit.librarySource = asyncUnit.source = asyncSource;
asyncLibrary.definingCompilationUnit = asyncUnit;
// Future<T>
@@ -278,7 +277,6 @@
//
CompilationUnitElementImpl htmlUnit = new CompilationUnitElementImpl();
Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
- coreContext.setContents(htmlSource, "");
htmlUnit.librarySource = htmlUnit.source = htmlSource;
ClassElementImpl elementElement = ElementFactory.classElement2("Element");
InterfaceType elementType = elementElement.type;
@@ -339,7 +337,6 @@
//
CompilationUnitElementImpl mathUnit = new CompilationUnitElementImpl();
Source mathSource = sourceFactory.forUri(_DART_MATH);
- coreContext.setContents(mathSource, "");
mathUnit.librarySource = mathUnit.source = mathSource;
FunctionElement cosElement = ElementFactory.functionElement3(
"cos",
@@ -396,13 +393,6 @@
coreContext, null, AstTestFactory.libraryIdentifier2(["dart", "math"]));
mathLibrary.definingCompilationUnit = mathUnit;
//
- // Set empty sources for the rest of the libraries.
- //
- Source source = sourceFactory.forUri(_DART_INTERCEPTORS);
- coreContext.setContents(source, "");
- source = sourceFactory.forUri(_DART_JS_HELPER);
- coreContext.setContents(source, "");
- //
// Record the elements.
//
Map<Source, LibraryElement> elementMap =
@@ -423,7 +413,11 @@
library.exportNamespace = namespace;
library.publicNamespace = namespace;
}
- context.recordLibraryElements(elementMap);
+
+ context.typeProvider = SummaryTypeProvider()
+ ..initializeCore(coreLibrary)
+ ..initializeAsync(asyncLibrary);
+
// Create the synthetic element for `loadLibrary`.
for (LibraryElementImpl library in elementMap.values) {
library.createLoadLibraryFunction(context.typeProvider);
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart
deleted file mode 100644
index 12bc001..0000000
--- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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/error/codes.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'checked_mode_compile_time_error_code.dart';
-import 'resolver_test_case.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(CheckedModeCompileTimeErrorCodeTest_Driver);
- defineReflectiveTests(SetElementTypeNotAssignableTest);
- defineReflectiveTests(SetElementTypeNotAssignableWithCodeAsUITest);
- });
-}
-
-@reflectiveTest
-class CheckedModeCompileTimeErrorCodeTest_Driver
- extends CheckedModeCompileTimeErrorCodeTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
-
-@reflectiveTest
-class SetElementTypeNotAssignableTest extends ResolverTestCase {
- @override
- bool get enableNewAnalysisDriver => true;
-
- test_simple() async {
- Source source = addSource("var v = const <String>{42};");
- await computeAnalysisResult(source);
- // TODO(brianwilkerson) Fix this so that only one error is produced.
- assertErrors(source, [
- CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
- StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE
- ]);
- verify([source]);
- }
-}
-
-@reflectiveTest
-class SetElementTypeNotAssignableWithCodeAsUITest extends ResolverTestCase {
- @override
- List<String> get enabledExperiments => ['spread-collections'];
-
- @override
- bool get enableNewAnalysisDriver => true;
-
- test_simple_const() async {
- // TODO(brianwilkerson) This test is not dependent on the experiments and
- // should be moved when these tests are cleaned up.
- Source source = addSource("var v = const <String>{42};");
- await computeAnalysisResult(source);
- assertErrors(source,
- [CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
- test_simple_nonConst() async {
- // TODO(brianwilkerson) This test is not dependent on the experiments and
- // should be moved when these tests are cleaned up.
- Source source = addSource("var v = <String>{42};");
- await computeAnalysisResult(source);
- assertErrors(source, [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
- test_spread_valid_const() async {
- await assertNoErrorsInCode('''
-var v = const <String>{...['a', 'b']};
-''');
- }
-
- test_spread_valid_nonConst() async {
- await assertNoErrorsInCode('''
-var v = <String>{...['a', 'b']};
-''');
- }
-}
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
similarity index 95%
rename from pkg/analyzer/test/generated/checked_mode_compile_time_error_code.dart
rename to pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
index 66185d3..46643f5 100644
--- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
@@ -5,13 +5,24 @@
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source_io.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'resolver_test_case.dart';
-abstract class CheckedModeCompileTimeErrorCodeTest extends ResolverTestCase {
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(CheckedModeCompileTimeErrorCodeTest);
+ });
+}
+
+@reflectiveTest
+class CheckedModeCompileTimeErrorCodeTest extends ResolverTestCase {
@override
AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
+ @override
+ bool get enableNewAnalysisDriver => true;
+
test_assertion_throws() async {
Source source = addSource(r'''
class A {
@@ -479,8 +490,7 @@
test_listElementTypeNotAssignable() async {
Source source = addSource("var v = const <String> [42];");
await computeAnalysisResult(source);
- assertErrors(source,
- [CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ assertErrors(source, [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
verify([source]);
}
@@ -495,16 +505,6 @@
verify([source]);
}
- test_mapKeyTypeNotAssignable() async {
- Source source = addSource("var v = const <String, int > {1 : 2};");
- await computeAnalysisResult(source);
- assertErrors(source, [
- CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
- StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE
- ]);
- verify([source]);
- }
-
test_mapLiteral_inferredKeyType() async {
Source source = addSource('''
const Object x = {1: 1};
@@ -527,16 +527,6 @@
verify([source]);
}
- test_mapValueTypeNotAssignable() async {
- Source source = addSource("var v = const <String, String> {'a' : 2};");
- await computeAnalysisResult(source);
- assertErrors(source, [
- CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
- StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE
- ]);
- verify([source]);
- }
-
test_parameterAssignable_null() async {
// Null is assignable to anything.
Source source = addSource(r'''
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index b14a030..4a4f04d 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -1234,79 +1234,6 @@
verify([source]);
}
- test_constMapKeyTypeImplementsEquals_direct() async {
- Source source = addSource(r'''
-class A {
- const A();
- operator ==(other) => false;
-}
-main() {
- const {const A() : 0};
-}''');
- await computeAnalysisResult(source);
- assertErrors(source,
- [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
- verify([source]);
- }
-
- test_constMapKeyTypeImplementsEquals_dynamic() async {
- // Note: static type of B.a is "dynamic", but actual type of the const
- // object is A. We need to make sure we examine the actual type when
- // deciding whether there is a problem with operator==.
- Source source = addSource(r'''
-class A {
- const A();
- operator ==(other) => false;
-}
-class B {
- static const a = const A();
-}
-main() {
- const {B.a : 0};
-}''');
- await computeAnalysisResult(source);
- assertErrors(source,
- [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
- verify([source]);
- }
-
- test_constMapKeyTypeImplementsEquals_factory() async {
- Source source = addSource(r'''
-class A { const factory A() = B; }
-
-class B implements A {
- const B();
-
- operator ==(o) => true;
-}
-
-main() {
- var m = const { const A(): 42 };
-}''');
- await computeAnalysisResult(source);
- assertErrors(source,
- [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
- verify([source]);
- }
-
- test_constMapKeyTypeImplementsEquals_super() async {
- Source source = addSource(r'''
-class A {
- const A();
- operator ==(other) => false;
-}
-class B extends A {
- const B();
-}
-main() {
- const {const B() : 0};
-}''');
- await computeAnalysisResult(source);
- assertErrors(source,
- [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
- verify([source]);
- }
-
test_constWithInvalidTypeParameters() async {
Source source = addSource(r'''
class A {
@@ -1491,7 +1418,6 @@
await computeAnalysisResult(source);
assertErrors(source, [
ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
- StrongModeCode.INVALID_CAST_LITERAL_MAP
]);
verify([source]);
}
@@ -1503,7 +1429,6 @@
await computeAnalysisResult(source);
assertErrors(source, [
ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
- StrongModeCode.INVALID_CAST_LITERAL_MAP
]);
verify([source]);
}
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
similarity index 90%
rename from pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
rename to pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 1ea8ecc..2389261 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -13,7 +13,8 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(CompileTimeErrorCodeTest_Driver);
+ defineReflectiveTests(CompileTimeErrorCodeTest);
+ defineReflectiveTests(CompileTimeErrorCodeTest_WithUIAsCode);
defineReflectiveTests(ConstSetElementTypeImplementsEqualsTest);
defineReflectiveTests(ControlFlowCollectionsTest);
defineReflectiveTests(InvalidTypeArgumentInConstSetTest);
@@ -23,7 +24,7 @@
}
@reflectiveTest
-class CompileTimeErrorCodeTest_Driver extends CompileTimeErrorCodeTestBase {
+class CompileTimeErrorCodeTest extends CompileTimeErrorCodeTestBase {
@override
bool get enableNewAnalysisDriver => true;
@@ -101,6 +102,42 @@
}
@reflectiveTest
+class CompileTimeErrorCodeTest_WithUIAsCode extends ResolverTestCase {
+ @override
+ List<String> get enabledExperiments =>
+ [EnableString.control_flow_collections, EnableString.spread_collections];
+
+ @override
+ bool get enableNewAnalysisDriver => true;
+
+ test_defaultValueInFunctionTypeAlias_new_named() async {
+ // This test used to fail with UI as code enabled. Test the fix here.
+ Source source = addSource('''
+typedef F = int Function({Map<String, String> m: const {}});
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [
+ ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+ ]);
+ verify([source]);
+ }
+
+ test_defaultValueInFunctionTypeAlias_new_named_ambiguous() async {
+ // Test that the strong checker does not crash when given an ambiguous
+ // set or map literal.
+ Source source = addSource('''
+typedef F = int Function({Object m: const {1, 2: 3}});
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [
+ ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+ CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
+ ]);
+ verify([source]);
+ }
+}
+
+@reflectiveTest
class ConstSetElementTypeImplementsEqualsTest extends ResolverTestCase {
@override
bool get enableNewAnalysisDriver => true;
@@ -415,44 +452,13 @@
test_listElementTypeNotAssignable_const() async {
Source source = addSource("var v = const <String>[42];");
await computeAnalysisResult(source);
- assertErrors(source,
- [CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
- test_listElementTypeNotAssignable_nonConst() async {
- Source source = addSource("var v = <String> [42];");
- await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
verify([source]);
}
- test_mapKeyTypeNotAssignable_const() async {
- Source source = addSource("var v = const <String, int >{1 : 2};");
- await computeAnalysisResult(source);
- assertErrors(
- source, [CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
- test_mapKeyTypeNotAssignable_nonConst() async {
- Source source = addSource("var v = <String, int >{1 : 2};");
- await computeAnalysisResult(source);
- assertErrors(source, [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
test_mapValueTypeNotAssignable_const() async {
Source source = addSource("var v = const <String, String>{'a' : 2};");
await computeAnalysisResult(source);
- assertErrors(source,
- [CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
- test_mapValueTypeNotAssignable_nonConst() async {
- Source source = addSource("var v = <String, String>{'a' : 2};");
- await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
verify([source]);
}
@@ -533,14 +539,6 @@
test_setElementTypeNotAssignable_const() async {
Source source = addSource("var v = const <String>{42};");
await computeAnalysisResult(source);
- assertErrors(source,
- [CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
- test_setElementTypeNotAssignable_nonConst() async {
- Source source = addSource("var v = <String>{42};");
- await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
verify([source]);
}
diff --git a/pkg/analyzer/test/generated/error_suppression_driver_test.dart b/pkg/analyzer/test/generated/error_suppression_driver_test.dart
deleted file mode 100644
index 77e0f57..0000000
--- a/pkg/analyzer/test/generated/error_suppression_driver_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'error_suppression.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(ErrorSuppressionTest_Driver);
- });
-}
-
-@reflectiveTest
-class ErrorSuppressionTest_Driver extends ErrorSuppressionTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/error_suppression.dart b/pkg/analyzer/test/generated/error_suppression_test.dart
similarity index 94%
rename from pkg/analyzer/test/generated/error_suppression.dart
rename to pkg/analyzer/test/generated/error_suppression_test.dart
index 80027a4..8eb21cf 100644
--- a/pkg/analyzer/test/generated/error_suppression.dart
+++ b/pkg/analyzer/test/generated/error_suppression_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
@@ -6,10 +6,21 @@
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'resolver_test_case.dart';
-abstract class ErrorSuppressionTest extends ResolverTestCase {
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ErrorSuppressionTest);
+ });
+}
+
+@reflectiveTest
+class ErrorSuppressionTest extends ResolverTestCase {
+ @override
+ bool get enableNewAnalysisDriver => true;
+
String get ignoredCode => 'const_initialized_with_non_constant_value';
List<ErrorCode> get reportedCodes => [
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 9182c50..eebd8bb 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -1356,78 +1356,6 @@
verify([source]);
}
- test_missingReturn_async() async {
- Source source = addSource('''
-import 'dart:async';
-Future<int> f() async {}
-''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.MISSING_RETURN]);
- verify([source]);
- }
-
- test_missingReturn_factory() async {
- Source source = addSource(r'''
-class A {
- factory A() {}
-}
-''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.MISSING_RETURN]);
- verify([source]);
- }
-
- test_missingReturn_function() async {
- Source source = addSource("int f() {}");
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.MISSING_RETURN]);
- verify([source]);
- }
-
- test_missingReturn_method() async {
- Source source = addSource(r'''
-class A {
- int m() {}
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.MISSING_RETURN]);
- verify([source]);
- }
-
- test_missingReturn_method_inferred() async {
- Source source = addSource(r'''
-abstract class A {
- int m();
-}
-class B extends A {
- m() {}
-}
-''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.MISSING_RETURN]);
- verify([source]);
- }
-
- test_no_missingReturn_async_futureOrVoid() async {
- Source source = addSource('''
-import 'dart:async';
-FutureOr<void> f(Future f) async {}
-''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_no_missingReturn_async_futureVoid() async {
- Source source = addSource('''
-import 'dart:async';
-Future<void> f() async {}
-''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
test_nullAwareBeforeOperator_minus() async {
Source source = addSource(r'''
m(x) {
diff --git a/pkg/analyzer/test/generated/invalid_code_driver_test.dart b/pkg/analyzer/test/generated/invalid_code_driver_test.dart
deleted file mode 100644
index b457f67..0000000
--- a/pkg/analyzer/test/generated/invalid_code_driver_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'invalid_code.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(InvalidCodeTest_Driver);
- });
-}
-
-@reflectiveTest
-class InvalidCodeTest_Driver extends InvalidCodeTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/invalid_code.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
similarity index 83%
rename from pkg/analyzer/test/generated/invalid_code.dart
rename to pkg/analyzer/test/generated/invalid_code_test.dart
index b7e6944..23bcf7d 100644
--- a/pkg/analyzer/test/generated/invalid_code.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -7,19 +7,30 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'resolver_test_case.dart';
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(InvalidCodeTest);
+ });
+}
+
/**
* Tests for various end-to-end cases when invalid code caused exceptions
* in one or another Analyzer subsystem. We are not interested not in specific
* errors generated, but we want to make sure that there is at least one,
* and analysis finishes without exceptions.
*/
-abstract class InvalidCodeTest extends ResolverTestCase {
+@reflectiveTest
+class InvalidCodeTest extends ResolverTestCase {
@override
AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
+ @override
+ bool get enableNewAnalysisDriver => true;
+
/**
* This code results in a method with the empty name, and the default
* constructor, which also has the empty name. The `Map` in `f` initializer
diff --git a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
deleted file mode 100644
index af22a4a..0000000
--- a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2017, 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/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'non_error_resolver.dart';
-import 'resolver_test_case.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(NonErrorResolverTest_Driver);
- defineReflectiveTests(NonErrorResolverTest_WithUiAsCode);
- defineReflectiveTests(NonConstantValueInInitializer);
- });
-}
-
-@reflectiveTest
-class NonConstantValueInInitializer extends ResolverTestCase {
- @override
- List<String> get enabledExperiments => [EnableString.constant_update_2018];
-
- @override
- bool get enableNewAnalysisDriver => true;
-
- test_intLiteralInDoubleContext_const_exact() async {
- Source source = addSource(r'''
-const double x = 0;
-class C {
- const C(double y) : assert(y is double), assert(x is double);
-}
-@C(0)
-@C(-0)
-@C(0x0)
-@C(-0x0)
-void main() {
- const C(0);
- const C(-0);
- const C(0x0);
- const C(-0x0);
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_isCheckInConstAssert() async {
- Source source = addSource(r'''
-class C {
- const C() : assert(1 is int);
-}
-
-void main() {
- const C();
-}
-''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-}
-
-@reflectiveTest
-class NonErrorResolverTest_Driver extends NonErrorResolverTestBase {
- @override
- bool get enableNewAnalysisDriver => true;
-
- @override
- @failingTest
- test_null_callOperator() {
- return super.test_null_callOperator();
- }
-}
-
-@reflectiveTest
-class NonErrorResolverTest_WithUiAsCode extends NonErrorResolverTest_Driver {
- @override
- List<String> get enabledExperiments =>
- [EnableString.spread_collections, EnableString.control_flow_collections];
-}
diff --git a/pkg/analyzer/test/generated/non_error_resolver.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
similarity index 98%
rename from pkg/analyzer/test/generated/non_error_resolver.dart
rename to pkg/analyzer/test/generated/non_error_resolver_test.dart
index bba51ce..0c3d5cb 100644
--- a/pkg/analyzer/test/generated/non_error_resolver.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -8,29 +8,78 @@
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'resolver_test_case.dart';
-class NonErrorResolverTestBase extends ResolverTestCase {
- @override
- AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(NonErrorResolverTest);
+ defineReflectiveTests(NonErrorResolverWithUiAsCodeTest);
+ defineReflectiveTests(NonConstantValueInInitializer);
+ });
+}
- fail_undefinedEnumConstant() async {
+@reflectiveTest
+class NonConstantValueInInitializer extends ResolverTestCase {
+ @override
+ List<String> get enabledExperiments => [EnableString.constant_update_2018];
+
+ @override
+ bool get enableNewAnalysisDriver => true;
+
+ test_intLiteralInDoubleContext_const_exact() async {
Source source = addSource(r'''
-enum E { ONE }
-E e() {
- return E.TWO;
+const double x = 0;
+class C {
+ const C(double y) : assert(y is double), assert(x is double);
+}
+@C(0)
+@C(-0)
+@C(0x0)
+@C(-0x0)
+void main() {
+ const C(0);
+ const C(-0);
+ const C(0x0);
+ const C(-0x0);
}''');
await computeAnalysisResult(source);
assertNoErrors(source);
verify([source]);
}
+ test_isCheckInConstAssert() async {
+ Source source = addSource(r'''
+class C {
+ const C() : assert(1 is int);
+}
+
+void main() {
+ const C();
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+}
+
+@reflectiveTest
+class NonErrorResolverTest extends ResolverTestCase {
+ @override
+ AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
+
+ @override
+ bool get enableNewAnalysisDriver => true;
+
test_ambiguousExport() async {
Source source = addSource(r'''
library L;
@@ -1210,28 +1259,6 @@
verify([source]);
}
- test_constMapKeyExpressionTypeImplementsEquals_abstract() async {
- Source source = addSource(r'''
-abstract class B {
- final id;
- const B(this.id);
- String toString() => 'C($id)';
- /** Equality is identity equality, the id isn't used. */
- bool operator==(Object other);
- }
-
-class C extends B {
- const C(id) : super(id);
-}
-
-Map getMap() {
- return const { const C(0): 'Map: 0' };
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
test_constNotInitialized_field() async {
Source source = addSource(r'''
class A {
@@ -1750,6 +1777,20 @@
verify([source]);
}
+ test_for_in_scope() async {
+ Source source = addSource('''
+main() {
+ List<List<int>> x = [[1]];
+ for (int x in x.first) {
+ print(x.isEven);
+ }
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_forEach_genericFunctionType() async {
Source source = addSource(r'''
main() {
@@ -4113,17 +4154,6 @@
verify([source]);
}
- test_nonConstMapKey_constField() async {
- Source source = addSource(r'''
-main() {
- const {double.INFINITY: 0};
-}''');
- await computeAnalysisResult(source);
- assertErrors(source,
- [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
- verify([source]);
- }
-
test_nonConstMapValue_constField() async {
Source source = addSource(r'''
main() {
@@ -4395,6 +4425,7 @@
verify([source]);
}
+ @failingTest
test_null_callOperator() async {
Source source = addSource(r'''
main() {
@@ -5510,6 +5541,18 @@
verify([source]);
}
+ @failingTest
+ test_undefinedEnumConstant() async {
+ Source source = addSource(r'''
+enum E { ONE }
+E e() {
+ return E.TWO;
+}''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_undefinedGetter_static_conditionalAccess() async {
// The conditional access operator '?.' can be used to access static
// fields.
@@ -6039,3 +6082,10 @@
await _check_wrongNumberOfParametersForOperator(name, "a");
}
}
+
+@reflectiveTest
+class NonErrorResolverWithUiAsCodeTest extends NonErrorResolverTest {
+ @override
+ List<String> get enabledExperiments =>
+ [EnableString.spread_collections, EnableString.control_flow_collections];
+}
diff --git a/pkg/analyzer/test/generated/non_hint_code_driver_test.dart b/pkg/analyzer/test/generated/non_hint_code_driver_test.dart
deleted file mode 100644
index c7c53cf..0000000
--- a/pkg/analyzer/test/generated/non_hint_code_driver_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'non_hint_code.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(NonHintCodeTest_Driver);
- });
-}
-
-@reflectiveTest
-class NonHintCodeTest_Driver extends NonHintCodeTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/non_hint_code.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
similarity index 87%
rename from pkg/analyzer/test/generated/non_hint_code.dart
rename to pkg/analyzer/test/generated/non_hint_code_test.dart
index 75e1a3d..359dd7f 100644
--- a/pkg/analyzer/test/generated/non_hint_code.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -5,31 +5,20 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/source_io.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'resolver_test_case.dart';
-abstract class NonHintCodeTest extends ResolverTestCase {
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(NonHintCodeTest);
+ });
+}
+
+@reflectiveTest
+class NonHintCodeTest extends ResolverTestCase {
@override
- void reset() {
- super.resetWith(packages: [
- [
- 'meta',
- r'''
-library meta;
-
-const _AlwaysThrows alwaysThrows = const _AlwaysThrows();
-const _Literal literal = const _Literal();
-
-class _AlwaysThrows {
- const _AlwaysThrows();
-}
-class _Literal {
- const _Literal();
-}
-'''
- ]
- ]);
- }
+ bool get enableNewAnalysisDriver => true;
test_async_future_object_without_return() async {
Source source = addSource('''
@@ -147,64 +136,6 @@
verify([source]);
}
- test_missingReturn_alwaysThrows() async {
- Source source = addSource(r'''
-import 'package:meta/meta.dart';
-
-@alwaysThrows
-void a() {
- throw 'msg';
-}
-
-int f() {
- a();
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_missingReturn_emptyFunctionBody() async {
- Source source = addSource(r'''
-abstract class A {
- int m();
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_missingReturn_expressionFunctionBody() async {
- Source source = addSource("int f() => 0;");
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_missingReturn_futureVoidReturnType() async {
- Source source = addSource('''
-import 'dart:async';
-Future<void> f() async {}
-''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_missingReturn_noReturnType() async {
- Source source = addSource("f() {}");
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_missingReturn_voidReturnType() async {
- Source source = addSource("void f() {}");
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
test_nullAwareInCondition_for_noCondition() async {
Source source = addSource(r'''
m(x) {
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index f90204a..f5becf3 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -1356,11 +1356,14 @@
@override
CompilationUnit parseCompilationUnit(String content,
- {List<ErrorCode> codes, List<ExpectedError> errors}) {
+ {List<ErrorCode> codes,
+ List<ExpectedError> errors,
+ bool enableControlFlowCollections}) {
GatheringErrorListener listener =
new GatheringErrorListener(checkRanges: true);
- CompilationUnit unit = parseCompilationUnit2(content, listener);
+ CompilationUnit unit = parseCompilationUnit2(content, listener,
+ enableControlFlowCollections: enableControlFlowCollections);
// Assert and return result
if (codes != null) {
@@ -1375,7 +1378,8 @@
}
CompilationUnit parseCompilationUnit2(
- String content, GatheringErrorListener listener) {
+ String content, GatheringErrorListener listener,
+ {bool enableControlFlowCollections}) {
var source = new StringSource(content, 'parser_test_StringSource.dart');
void reportError(
@@ -1404,6 +1408,9 @@
parser.listener = astBuilder;
astBuilder.parser = parser;
astBuilder.allowNativeClause = allowNativeClause;
+ if (enableControlFlowCollections != null) {
+ astBuilder.enableControlFlowCollections = enableControlFlowCollections;
+ }
parser.parseUnit(_fastaTokens);
CompilationUnitImpl unit = astBuilder.pop();
unit.localDeclarations = astBuilder.localDeclarations;
diff --git a/pkg/analyzer/test/generated/resolver_driver_test.dart b/pkg/analyzer/test/generated/resolver_driver_test.dart
deleted file mode 100644
index 74af34f..0000000
--- a/pkg/analyzer/test/generated/resolver_driver_test.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'resolver_test.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(StrictModeTest_Driver);
- defineReflectiveTests(TypePropagationTest_Driver);
- });
-}
-
-@reflectiveTest
-class StrictModeTest_Driver extends StrictModeTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
-
-@reflectiveTest
-class TypePropagationTest_Driver extends TypePropagationTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 5d5b657..772ed2b 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -45,6 +45,8 @@
defineReflectiveTests(LibraryScopeTest);
defineReflectiveTests(PrefixedNamespaceTest);
defineReflectiveTests(ScopeTest);
+ defineReflectiveTests(StrictModeTest);
+ defineReflectiveTests(TypePropagationTest);
defineReflectiveTests(TypeProviderImplTest);
defineReflectiveTests(TypeResolverVisitorTest);
});
@@ -571,18 +573,10 @@
* The class `StrictModeTest` contains tests to ensure that the correct errors and warnings
* are reported when the analysis engine is run in strict mode.
*/
-abstract class StrictModeTest extends ResolverTestCase {
- fail_for() async {
- Source source = addSource(r'''
-int f(List<int> list) {
- num sum = 0;
- for (num i = 0; i < list.length; i++) {
- sum += list[i];
- }
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
- }
+@reflectiveTest
+class StrictModeTest extends ResolverTestCase {
+ @override
+ bool get enableNewAnalysisDriver => true;
@override
void setUp() {
@@ -637,6 +631,19 @@
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
}
+ @failingTest
+ test_for() async {
+ Source source = addSource(r'''
+int f(List<int> list) {
+ num sum = 0;
+ for (num i = 0; i < list.length; i++) {
+ sum += list[i];
+ }
+}''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+ }
+
test_forEach() async {
Source source = addSource(r'''
int f(List<int> list) {
@@ -722,16 +729,10 @@
}
}
-abstract class TypePropagationTest extends ResolverTestCase {
- fail_propagatedReturnType_functionExpression() async {
- // TODO(scheglov) disabled because we don't resolve function expression
- String code = r'''
-main() {
- var v = (() {return 42;})();
-}''';
- CompilationUnit unit = await resolveSource(code);
- assertAssignedType(code, unit, typeProvider.dynamicType);
- }
+@reflectiveTest
+class TypePropagationTest extends ResolverTestCase {
+ @override
+ bool get enableNewAnalysisDriver => true;
test_assignment_null() async {
String code = r'''
@@ -1000,6 +1001,17 @@
expect(methodInvoke.staticType, typeProvider.dynamicType);
}
+ @failingTest
+ test_propagatedReturnType_functionExpression() async {
+ // TODO(scheglov) disabled because we don't resolve function expression
+ String code = r'''
+main() {
+ var v = (() {return 42;})();
+}''';
+ CompilationUnit unit = await resolveSource(code);
+ assertAssignedType(code, unit, typeProvider.dynamicType);
+ }
+
/**
* Return the resolved unit for the given [source].
*
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index a682c9d..021bac0 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -574,13 +574,10 @@
"test");
/**
- * Create a source object representing a file with the given [fileName] and
- * give it an empty content. Return the source that was created.
+ * Return a source object representing a file with the given [fileName].
*/
Source createNamedSource(String fileName) {
- Source source = getFile(fileName).createSource();
- analysisContext2.setContents(source, '');
- return source;
+ return getFile(fileName).createSource();
}
/**
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_driver_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_driver_test.dart
deleted file mode 100644
index 9aa12df..0000000
--- a/pkg/analyzer/test/generated/static_type_analyzer_driver_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'static_type_analyzer_test.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(StaticTypeAnalyzer2Test_Driver);
- });
-}
-
-@reflectiveTest
-class StaticTypeAnalyzer2Test_Driver extends StaticTypeAnalyzer2Test {
- @override
- bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 020414b..dcdaa61 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -34,6 +34,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(SetLiteralsTest);
defineReflectiveTests(StaticTypeAnalyzerTest);
+ defineReflectiveTests(StaticTypeAnalyzer2Test);
defineReflectiveTests(StaticTypeAnalyzer3Test);
defineReflectiveTests(StaticTypeAnalyzerWithSetLiteralsTest);
defineReflectiveTests(StaticTypeAnalyzerWithStrictInferenceTest);
@@ -70,7 +71,11 @@
/**
* Like [StaticTypeAnalyzerTest], but as end-to-end tests.
*/
-abstract class StaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared {
+@reflectiveTest
+class StaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared {
+ @override
+ bool get enableNewAnalysisDriver => true;
+
test_FunctionExpressionInvocation_block() async {
String code = r'''
main() {
@@ -1671,7 +1676,7 @@
LinkedHashSet<int> test4() => {};
''';
await resolveTestUnit(code, noErrors: false);
- expectExpressionType('{}', 'Set<?>');
+ expectExpressionType('{}', 'Set<dynamic>');
await assertErrorsInCode(code, [StrongModeCode.INVALID_CAST_LITERAL_SET]);
}
@@ -1692,6 +1697,9 @@
class StaticTypeAnalyzerWithStrictInferenceTest
extends StaticTypeAnalyzer2TestShared {
@override
+ bool get enableNewAnalysisDriver => true;
+
+ @override
void setUp() {
super.setUp();
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
@@ -1699,37 +1707,6 @@
resetWith(options: options);
}
- @override
- bool get enableNewAnalysisDriver => true;
-
- test_topLevelVariable() async {
- String code = r'''
-var a;
-''';
- await resolveTestUnit(code, noErrors: false);
- await assertErrorsInCode(
- code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
- }
-
- test_topLevelVariable_withType() async {
- String code = r'''
-int a;
-dynamic b;
-Object c;
-Null d;
-''';
- await resolveTestUnit(code, noErrors: false);
- await assertNoErrorsInCode(code);
- }
-
- test_topLevelVariable_withInitializer() async {
- String code = r'''
-var a = 7;
-''';
- await resolveTestUnit(code, noErrors: false);
- await assertNoErrorsInCode(code);
- }
-
test_localVariable() async {
String code = r'''
f() {
@@ -1741,6 +1718,16 @@
code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
}
+ test_localVariable_withInitializer() async {
+ String code = r'''
+f() {
+ var a = 7;
+}
+''';
+ await resolveTestUnit(code, noErrors: false);
+ await assertNoErrorsInCode(code);
+ }
+
test_localVariable_withType() async {
String code = r'''
f() {
@@ -1754,11 +1741,29 @@
await assertNoErrorsInCode(code);
}
- test_localVariable_withInitializer() async {
+ test_topLevelVariable() async {
String code = r'''
-f() {
- var a = 7;
-}
+var a;
+''';
+ await resolveTestUnit(code, noErrors: false);
+ await assertErrorsInCode(
+ code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
+ }
+
+ test_topLevelVariable_withInitializer() async {
+ String code = r'''
+var a = 7;
+''';
+ await resolveTestUnit(code, noErrors: false);
+ await assertNoErrorsInCode(code);
+ }
+
+ test_topLevelVariable_withType() async {
+ String code = r'''
+int a;
+dynamic b;
+Object c;
+Null d;
''';
await resolveTestUnit(code, noErrors: false);
await assertNoErrorsInCode(code);
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_driver_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_driver_test.dart
deleted file mode 100644
index 6286728..0000000
--- a/pkg/analyzer/test/generated/static_type_warning_code_driver_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'static_type_warning_code.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(StaticTypeWarningCodeTest_Driver);
- defineReflectiveTests(StrongModeStaticTypeWarningCodeTest_Driver);
- });
-}
-
-@reflectiveTest
-class StaticTypeWarningCodeTest_Driver extends StaticTypeWarningCodeTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
-
-@reflectiveTest
-class StrongModeStaticTypeWarningCodeTest_Driver
- extends StrongModeStaticTypeWarningCodeTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/static_type_warning_code.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
similarity index 98%
rename from pkg/analyzer/test/generated/static_type_warning_code.dart
rename to pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 01f0538..36ad4c3 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -9,15 +9,17 @@
import 'resolver_test_case.dart';
-abstract class StaticTypeWarningCodeTest extends ResolverTestCase {
- fail_undefinedEnumConstant() async {
- // We need a way to set the parseEnum flag in the parser to true.
- await assertErrorsInCode(r'''
-enum E { ONE }
-E e() {
- return E.TWO;
-}''', [StaticTypeWarningCode.UNDEFINED_ENUM_CONSTANT]);
- }
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(StaticTypeWarningCodeTest);
+ defineReflectiveTests(StrongModeStaticTypeWarningCodeTest);
+ });
+}
+
+@reflectiveTest
+class StaticTypeWarningCodeTest extends ResolverTestCase {
+ @override
+ bool get enableNewAnalysisDriver => true;
test_assert_message_suppresses_type_promotion() async {
// If a variable is assigned to inside the expression for an assert
@@ -1298,6 +1300,16 @@
}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
}
+ @failingTest
+ test_undefinedEnumConstant() async {
+ // We need a way to set the parseEnum flag in the parser to true.
+ await assertErrorsInCode(r'''
+enum E { ONE }
+E e() {
+ return E.TWO;
+}''', [StaticTypeWarningCode.UNDEFINED_ENUM_CONSTANT]);
+ }
+
test_undefinedGetter() async {
await assertErrorsInUnverifiedCode(r'''
class T {}
@@ -1705,7 +1717,11 @@
}
}
-abstract class StrongModeStaticTypeWarningCodeTest extends ResolverTestCase {
+@reflectiveTest
+class StrongModeStaticTypeWarningCodeTest extends ResolverTestCase {
+ @override
+ bool get enableNewAnalysisDriver => true;
+
void setUp() {
super.setUp();
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
diff --git a/pkg/analyzer/test/generated/static_warning_code_driver_test.dart b/pkg/analyzer/test/generated/static_warning_code_driver_test.dart
deleted file mode 100644
index 2be665c..0000000
--- a/pkg/analyzer/test/generated/static_warning_code_driver_test.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2017, 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/error/codes.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'resolver_test_case.dart';
-import 'static_warning_code_test.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(SetElementTypeNotAssignableTest);
- defineReflectiveTests(StaticWarningCodeTest_Driver);
- });
-}
-
-@reflectiveTest
-class SetElementTypeNotAssignableTest extends ResolverTestCase {
- @override
- bool get enableNewAnalysisDriver => true;
-
- test_setElementTypeNotAssignable() async {
- Source source = addSource("var v = <String>{42};");
- await computeAnalysisResult(source);
- assertErrors(source, [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-}
-
-@reflectiveTest
-class StaticWarningCodeTest_Driver extends StaticWarningCodeTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index 1aab715..096db7f 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -14,6 +14,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(EqualValuesInConstSetTest);
+ defineReflectiveTests(StaticWarningCodeTest);
});
}
@@ -56,33 +57,10 @@
}
}
-abstract class StaticWarningCodeTest extends ResolverTestCase {
- fail_argumentTypeNotAssignable_tearOff_required() async {
- Source source = addSource(r'''
-class C {
- Object/*=T*/ f/*<T>*/(Object/*=T*/ x) => x;
-}
-g(C c) {
- var h = c.f/*<int>*/;
- print(h('s'));
-}
-''');
- await computeAnalysisResult(source);
- assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
- fail_undefinedIdentifier_commentReference() async {
- Source source = addSource(r'''
-/** [m] xxx [new B.c] */
-class A {
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [
- StaticWarningCode.UNDEFINED_IDENTIFIER,
- StaticWarningCode.UNDEFINED_IDENTIFIER
- ]);
- }
+@reflectiveTest
+class StaticWarningCodeTest extends ResolverTestCase {
+ @override
+ bool get enableNewAnalysisDriver => true;
test_ambiguousImport_as() async {
Source source = addSource(r'''
@@ -641,6 +619,22 @@
verify([source]);
}
+ @failingTest
+ test_argumentTypeNotAssignable_tearOff_required() async {
+ Source source = addSource(r'''
+class C {
+ Object/*=T*/ f/*<T>*/(Object/*=T*/ x) => x;
+}
+g(C c) {
+ var h = c.f/*<int>*/;
+ print(h('s'));
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
+ verify([source]);
+ }
+
test_assignmentToClass() async {
Source source = addSource('''
class C {}
@@ -2320,27 +2314,6 @@
verify([source]);
}
- test_listElementTypeNotAssignable() async {
- Source source = addSource("var v = <String> [42];");
- await computeAnalysisResult(source);
- assertErrors(source, [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
- test_mapKeyTypeNotAssignable() async {
- Source source = addSource("var v = <String, int > {1 : 2};");
- await computeAnalysisResult(source);
- assertErrors(source, [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
- test_mapValueTypeNotAssignable() async {
- Source source = addSource("var v = <String, String> {'a' : 2};");
- await computeAnalysisResult(source);
- assertErrors(source, [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
- verify([source]);
- }
-
test_mismatchedAccessorTypes_topLevel() async {
Source source = addSource(r'''
int get g { return 0; }
@@ -3575,6 +3548,19 @@
assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS_BOOLEAN]);
}
+ @failingTest
+ test_undefinedIdentifier_commentReference() async {
+ Source source = addSource(r'''
+/** [m] xxx [new B.c] */
+class A {
+}''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [
+ StaticWarningCode.UNDEFINED_IDENTIFIER,
+ StaticWarningCode.UNDEFINED_IDENTIFIER
+ ]);
+ }
+
test_undefinedIdentifier_for() async {
Source source = addSource(r'''
f(var l) {
diff --git a/pkg/analyzer/test/generated/strong_mode_driver_test.dart b/pkg/analyzer/test/generated/strong_mode_driver_test.dart
deleted file mode 100644
index c6047e6..0000000
--- a/pkg/analyzer/test/generated/strong_mode_driver_test.dart
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2017, 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/engine.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'resolver_test_case.dart';
-import 'strong_mode.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(StrongModeLocalInferenceTest_Driver);
- defineReflectiveTests(StrongModeStaticTypeAnalyzer2Test_Driver);
- defineReflectiveTests(StrongModeTypePropagationTest_Driver);
- });
-}
-
-@reflectiveTest
-class StrongModeLocalInferenceTest_Driver extends StrongModeLocalInferenceTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
-
-@reflectiveTest
-class StrongModeStaticTypeAnalyzer2Test_Driver
- extends StaticTypeAnalyzer2TestShared
- with StrongModeStaticTypeAnalyzer2TestCases {
- @override
- bool get enableNewAnalysisDriver => true;
-
- void setUp() {
- super.setUp();
- AnalysisOptionsImpl options = new AnalysisOptionsImpl();
- resetWith(options: options);
- }
-
- @failingTest
- @override
- test_genericFunction_parameter() {
- return super.test_genericFunction_parameter();
- }
-
- @failingTest
- @override
- test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit() {
- return super
- .test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit();
- }
-
- @failingTest
- @override
- test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred() {
- return super
- .test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred();
- }
-
- @failingTest
- @override
- test_genericMethod_functionInvocation_functionTypedParameter_explicit() {
- return super
- .test_genericMethod_functionInvocation_functionTypedParameter_explicit();
- }
-
- @failingTest
- @override
- test_genericMethod_functionInvocation_functionTypedParameter_inferred() {
- return super
- .test_genericMethod_functionInvocation_functionTypedParameter_inferred();
- }
-
- @failingTest
- @override
- test_genericMethod_functionTypedParameter_tearoff() {
- return super.test_genericMethod_functionTypedParameter_tearoff();
- }
-
- @override
- @failingTest
- test_genericMethod_nestedCaptureBounds() {
- // https://github.com/dart-lang/sdk/issues/30236
- return super.test_genericMethod_nestedCaptureBounds();
- }
-
- @override
- @failingTest
- test_genericMethod_tearoff_instantiated() {
- return super.test_genericMethod_tearoff_instantiated();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_class_error_extension_malbounded() {
- return super.test_instantiateToBounds_class_error_extension_malbounded();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_class_error_instantiation_malbounded() {
- return super
- .test_instantiateToBounds_class_error_instantiation_malbounded();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_generic_function_error_malbounded() {
- return super.test_instantiateToBounds_generic_function_error_malbounded();
- }
-}
-
-@reflectiveTest
-class StrongModeTypePropagationTest_Driver
- extends StrongModeTypePropagationTest {
- @override
- bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/strong_mode.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
similarity index 97%
rename from pkg/analyzer/test/generated/strong_mode.dart
rename to pkg/analyzer/test/generated/strong_mode_test.dart
index f327129..c0f832d 100644
--- a/pkg/analyzer/test/generated/strong_mode.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -16,12 +16,22 @@
import 'package:analyzer/src/test_utilities/find_node.dart';
import 'package:front_end/src/base/errors.dart';
import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../utils.dart';
import 'resolver_test_case.dart';
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(StrongModeLocalInferenceTest);
+ defineReflectiveTests(StrongModeStaticTypeAnalyzer2Test);
+ defineReflectiveTests(StrongModeTypePropagationTest);
+ });
+}
+
/// Strong mode static analyzer local type inference tests
-abstract class StrongModeLocalInferenceTest extends ResolverTestCase {
+@reflectiveTest
+class StrongModeLocalInferenceTest extends ResolverTestCase {
TypeAssertions _assertions;
Asserter<DartType> _isDynamic;
@@ -51,6 +61,9 @@
AsserterBuilder<DartType, DartType> _hasElementOf;
@override
+ bool get enableNewAnalysisDriver => true;
+
+ @override
Future<TestAnalysisResult> computeAnalysisResult(Source source) async {
TestAnalysisResult result = await super.computeAnalysisResult(source);
if (_assertions == null) {
@@ -2809,6 +2822,91 @@
}
}
+@reflectiveTest
+class StrongModeStaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared
+ with StrongModeStaticTypeAnalyzer2TestCases {
+ @override
+ bool get enableNewAnalysisDriver => true;
+
+ void setUp() {
+ super.setUp();
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ resetWith(options: options);
+ }
+
+ @failingTest
+ @override
+ test_genericFunction_parameter() {
+ return super.test_genericFunction_parameter();
+ }
+
+ @failingTest
+ @override
+ test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit() {
+ return super
+ .test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit();
+ }
+
+ @failingTest
+ @override
+ test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred() {
+ return super
+ .test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred();
+ }
+
+ @failingTest
+ @override
+ test_genericMethod_functionInvocation_functionTypedParameter_explicit() {
+ return super
+ .test_genericMethod_functionInvocation_functionTypedParameter_explicit();
+ }
+
+ @failingTest
+ @override
+ test_genericMethod_functionInvocation_functionTypedParameter_inferred() {
+ return super
+ .test_genericMethod_functionInvocation_functionTypedParameter_inferred();
+ }
+
+ @failingTest
+ @override
+ test_genericMethod_functionTypedParameter_tearoff() {
+ return super.test_genericMethod_functionTypedParameter_tearoff();
+ }
+
+ @override
+ @failingTest
+ test_genericMethod_nestedCaptureBounds() {
+ // https://github.com/dart-lang/sdk/issues/30236
+ return super.test_genericMethod_nestedCaptureBounds();
+ }
+
+ @override
+ @failingTest
+ test_genericMethod_tearoff_instantiated() {
+ return super.test_genericMethod_tearoff_instantiated();
+ }
+
+ @override
+ @failingTest
+ test_instantiateToBounds_class_error_extension_malbounded() {
+ return super.test_instantiateToBounds_class_error_extension_malbounded();
+ }
+
+ @override
+ @failingTest
+ test_instantiateToBounds_class_error_instantiation_malbounded() {
+ return super
+ .test_instantiateToBounds_class_error_instantiation_malbounded();
+ }
+
+ @override
+ @failingTest
+ test_instantiateToBounds_generic_function_error_malbounded() {
+ return super.test_instantiateToBounds_generic_function_error_malbounded();
+ }
+}
+
/// Test cases for [StrongModeStaticTypeAnalyzer2Test]
mixin StrongModeStaticTypeAnalyzer2TestCases
implements StaticTypeAnalyzer2TestShared {
@@ -4320,7 +4418,11 @@
}
}
-abstract class StrongModeTypePropagationTest extends ResolverTestCase {
+@reflectiveTest
+class StrongModeTypePropagationTest extends ResolverTestCase {
+ @override
+ bool get enableNewAnalysisDriver => true;
+
@override
void setUp() {
super.setUp();
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 6f3ca73..4481253 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -1,45 +1,37 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// 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.
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'all_the_rest_test.dart' as all_the_rest;
-import 'checked_mode_compile_time_error_code_driver_test.dart'
- as checked_mode_compile_time_error_code_driver_test;
-import 'compile_time_error_code_driver_test.dart'
- as compile_time_error_code_driver_test;
-
+import 'checked_mode_compile_time_error_code_test.dart'
+ as checked_mode_compile_time_error_code;
+import 'compile_time_error_code_test.dart' as compile_time_error_code;
// ignore: deprecated_member_use_from_same_package
import 'constant_test.dart' as constant_test;
import 'declaration_resolver_test.dart' as declaration_resolver_test;
import 'element_resolver_test.dart' as element_resolver_test;
import 'engine_test.dart' as engine_test;
-import 'error_suppression_driver_test.dart' as error_suppression_driver_test;
+import 'error_suppression_test.dart' as error_suppression;
import 'hint_code_test.dart' as hint_code_test;
import 'inheritance_manager_test.dart' as inheritance_manager_test;
-import 'invalid_code_driver_test.dart' as invalid_code_driver_test;
+import 'invalid_code_test.dart' as invalid_code;
import 'java_core_test.dart' as java_core_test;
import 'java_io_test.dart' as java_io_test;
-import 'non_error_resolver_driver_test.dart' as non_error_resolver_driver_test;
-import 'non_hint_code_driver_test.dart' as non_hint_code_driver_test;
+import 'non_error_resolver_test.dart' as non_error_resolver;
+import 'non_hint_code_test.dart' as non_hint_code;
import 'parser_fasta_test.dart' as parser_fasta_test;
import 'parser_test.dart' as parser_test;
-import 'resolver_driver_test.dart' as resolver_driver_test;
import 'resolver_test.dart' as resolver_test;
import 'scanner_test.dart' as scanner_test;
import 'sdk_test.dart' as sdk_test;
import 'simple_resolver_test.dart' as simple_resolver_test;
import 'source_factory_test.dart' as source_factory_test;
-import 'static_type_analyzer_driver_test.dart'
- as static_type_analyzer_driver_test;
import 'static_type_analyzer_test.dart' as static_type_analyzer_test;
-import 'static_type_warning_code_driver_test.dart'
- as static_type_warning_code_driver_test;
-import 'static_warning_code_driver_test.dart'
- as static_warning_code_driver_test;
-import 'static_warning_code_test.dart' as static_warning_code_test;
-import 'strong_mode_driver_test.dart' as strong_mode_driver_test;
+import 'static_type_warning_code_test.dart' as static_type_warning_code;
+import 'static_warning_code_test.dart' as static_warning_code;
+import 'strong_mode_test.dart' as strong_mode;
import 'type_system_test.dart' as type_system_test;
import 'utilities_dart_test.dart' as utilities_dart_test;
import 'utilities_test.dart' as utilities_test;
@@ -47,34 +39,31 @@
main() {
defineReflectiveSuite(() {
all_the_rest.main();
- checked_mode_compile_time_error_code_driver_test.main();
- compile_time_error_code_driver_test.main();
+ checked_mode_compile_time_error_code.main();
+ compile_time_error_code.main();
constant_test.main();
declaration_resolver_test.main();
element_resolver_test.main();
engine_test.main();
- error_suppression_driver_test.main();
+ error_suppression.main();
hint_code_test.main();
inheritance_manager_test.main();
- invalid_code_driver_test.main();
+ invalid_code.main();
java_core_test.main();
java_io_test.main();
- non_error_resolver_driver_test.main();
- non_hint_code_driver_test.main();
+ non_error_resolver.main();
+ non_hint_code.main();
parser_fasta_test.main();
parser_test.main();
- resolver_driver_test.main();
resolver_test.main();
scanner_test.main();
sdk_test.main();
simple_resolver_test.main();
source_factory_test.main();
- static_type_analyzer_driver_test.main();
static_type_analyzer_test.main();
- static_type_warning_code_driver_test.main();
- static_warning_code_driver_test.main();
- static_warning_code_test.main();
- strong_mode_driver_test.main();
+ static_type_warning_code.main();
+ static_warning_code.main();
+ strong_mode.main();
type_system_test.main();
utilities_dart_test.main();
utilities_test.main();
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 528bd33..b6ba562 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -14,8 +14,6 @@
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
import 'package:test/test.dart';
import 'analysis_context_factory.dart';
@@ -98,11 +96,7 @@
fail("Could not find method named $methodName in ${type.displayName}");
}
- void setUp() {
- List<Plugin> plugins = <Plugin>[];
- plugins.addAll(AnalysisEngine.instance.requiredPlugins);
- new ExtensionManager().processPlugins(plugins);
- }
+ void setUp() {}
void tearDown() {}
diff --git a/pkg/analyzer/test/source/error_processor_test.dart b/pkg/analyzer/test/source/error_processor_test.dart
index d55cd52..966a8ed 100644
--- a/pkg/analyzer/test/source/error_processor_test.dart
+++ b/pkg/analyzer/test/source/error_processor_test.dart
@@ -7,10 +7,7 @@
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/task/options.dart';
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';
@@ -44,8 +41,6 @@
AnalysisError annotate_overrides = new AnalysisError(
new TestSource(), 0, 1, new LintCode('annotate_overrides', ''));
- oneTimeSetup();
-
setUp(() {
context = new TestContext();
});
@@ -162,11 +157,4 @@
ErrorProcessor getProcessor(AnalysisError error) =>
ErrorProcessor.getProcessor(context.analysisOptions, error);
-void oneTimeSetup() {
- List<Plugin> plugins = <Plugin>[];
- plugins.addAll(AnalysisEngine.instance.requiredPlugins);
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(plugins);
-}
-
class TestContext extends AnalysisContextImpl {}
diff --git a/pkg/analyzer/test/src/context/abstract_context.dart b/pkg/analyzer/test/src/context/abstract_context.dart
deleted file mode 100644
index 131646e..0000000
--- a/pkg/analyzer/test/src/context/abstract_context.dart
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/visitor.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/driver.dart';
-import 'package:analyzer/src/test_utilities/mock_sdk.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
-import 'package:test/test.dart';
-
-/**
- * Finds an [Element] with the given [name].
- */
-Element findChildElement(Element root, String name, [ElementKind kind]) {
- Element result = null;
- root.accept(new _ElementVisitorFunctionWrapper((Element element) {
- if (element.name != name) {
- return;
- }
- if (kind != null && element.kind != kind) {
- return;
- }
- result = element;
- }));
- return result;
-}
-
-/**
- * A function to be called for every [Element].
- */
-typedef void _ElementVisitorFunction(Element element);
-
-class AbstractContextTest with ResourceProviderMixin {
- DartSdk sdk;
- SourceFactory sourceFactory;
- AnalysisContextImpl context;
- AnalysisCache analysisCache;
- AnalysisDriver analysisDriver;
-
- UriResolver sdkResolver;
- UriResolver resourceResolver;
-
- AnalysisTask task;
- Map<ResultDescriptor<dynamic>, dynamic> oldOutputs;
- Map<ResultDescriptor<dynamic>, dynamic> outputs;
-
- Source addSource(String path, String contents) {
- Source source = newSource(path, contents);
- ChangeSet changeSet = new ChangeSet();
- changeSet.addedSource(source);
- context.applyChanges(changeSet);
- return source;
- }
-
- /**
- * Assert that the given [elements] has the same number of items as the number
- * of specified [names], and that for each specified name, a corresponding
- * element can be found in the given collection with that name.
- */
- void assertNamedElements(List<Element> elements, List<String> names) {
- for (String elemName in names) {
- bool found = false;
- for (Element elem in elements) {
- if (elem.name == elemName) {
- found = true;
- break;
- }
- }
- if (!found) {
- StringBuffer buffer = new StringBuffer();
- buffer.write("Expected element named: ");
- buffer.write(elemName);
- buffer.write("\n but found: ");
- for (Element elem in elements) {
- buffer.write(elem.name);
- buffer.write(", ");
- }
- fail(buffer.toString());
- }
- }
- expect(elements, hasLength(names.length));
- }
-
- /**
- * Compute the given [result] for the given [target].
- */
- void computeResult(AnalysisTarget target, ResultDescriptor result,
- {Matcher matcher: null}) {
- oldOutputs = outputs;
- task = analysisDriver.computeResult(target, result);
- if (matcher == null) {
- expect(task, isNotNull);
- } else {
- expect(task, matcher);
- }
- expect(task.caughtException, isNull);
- outputs = task.outputs;
- for (ResultDescriptor descriptor in task.descriptor.results) {
- expect(outputs, contains(descriptor));
- }
- }
-
- AnalysisContextImpl createAnalysisContext() {
- return new AnalysisContextImpl();
- }
-
- DartSdk createDartSdk() => new MockSdk(resourceProvider: resourceProvider);
-
- Source newSource(String path, [String content = '']) {
- File file = newFile(path, content: content);
- return file.createSource();
- }
-
- List<Source> newSources(Map<String, String> sourceMap) {
- List<Source> sources = <Source>[];
- sourceMap.forEach((String path, String content) {
- Source source = newSource(path, content);
- sources.add(source);
- });
- return sources;
- }
-
- void prepareAnalysisContext([AnalysisOptions options]) {
- sdk = createDartSdk();
- sdkResolver = new DartUriResolver(sdk);
- resourceResolver = new ResourceUriResolver(resourceProvider);
- sourceFactory = new SourceFactory(
- <UriResolver>[sdkResolver, resourceResolver], null, resourceProvider);
- context = createAnalysisContext();
- if (options != null) {
- context.analysisOptions = options;
- }
- context.sourceFactory = sourceFactory;
- analysisCache = context.analysisCache;
- analysisDriver = context.driver;
- }
-
- CompilationUnit resolveLibraryUnit(Source source) {
- return context.resolveCompilationUnit2(source, source);
- }
-
- void setUp() {
- List<Plugin> plugins = <Plugin>[];
- plugins.addAll(AnalysisEngine.instance.requiredPlugins);
-
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(plugins);
-
- prepareAnalysisContext();
- }
-
- void tearDown() {}
-}
-
-/**
- * Wraps the given [_ElementVisitorFunction] into an instance of
- * [GeneralizingElementVisitor].
- */
-class _ElementVisitorFunctionWrapper extends GeneralizingElementVisitor {
- final _ElementVisitorFunction function;
-
- _ElementVisitorFunctionWrapper(this.function);
-
- visitElement(Element element) {
- function(element);
- super.visitElement(element);
- }
-}
diff --git a/pkg/analyzer/test/src/context/source_test.dart b/pkg/analyzer/test/src/context/source_test.dart
index 45a5ffc..530d908 100644
--- a/pkg/analyzer/test/src/context/source_test.dart
+++ b/pkg/analyzer/test/src/context/source_test.dart
@@ -5,12 +5,11 @@
import 'package:analyzer/src/context/source.dart';
import 'package:analyzer/src/file_system/file_system.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:package_config/packages.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'abstract_context.dart';
-
main() {
defineReflectiveSuite(() {
defineReflectiveTests(SourceFactoryImplTest);
@@ -18,7 +17,7 @@
}
@reflectiveTest
-class SourceFactoryImplTest extends AbstractContextTest {
+class SourceFactoryImplTest with ResourceProviderMixin {
void test_restoreUri() {
String libPath = convertPath('/pkgs/somepkg/lib');
Uri libUri = getFolder(libPath).toUri();
@@ -27,7 +26,7 @@
<UriResolver>[new ResourceUriResolver(resourceProvider)],
new _MockPackages(packageUriMap),
);
- Source libSource = newSource('/pkgs/somepkg/lib');
+ Source libSource = newFile('/pkgs/somepkg/lib').createSource();
Uri uri = sourceFactory.restoreUri(libSource);
try {
expect(uri, Uri.parse('package:foo/'));
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index b47fb50..f5bb3d3 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -2114,7 +2114,6 @@
var fTypeParameter = fType.normalParameterTypes[0] as TypeParameterType;
expect(fTypeParameter.element, same(fTypeTypeParameter));
var tRef = findNode.simple('T>');
- assertType(tRef, null);
var functionTypeNode = tRef.parent.parent.parent as GenericFunctionType;
var functionType = functionTypeNode.type as FunctionType;
assertElement(tRef, functionType.typeFormals[0]);
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index f0e2140..7b9330f 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -802,6 +802,46 @@
EnableString.spread_collections
];
+ test_listLiteral_ifElement_false_withElse() async {
+ await _resolveTestCode('''
+const c = [1, if (1 < 0) 2 else 3, 4];
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+ expect(result.toListValue().map((e) => e.toIntValue()), [1, 3, 4]);
+ }
+
+ test_listLiteral_ifElement_false_withoutElse() async {
+ await _resolveTestCode('''
+const c = [1, if (1 < 0) 2, 3];
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+ expect(result.toListValue().map((e) => e.toIntValue()), [1, 3]);
+ }
+
+ test_listLiteral_ifElement_true_withElse() async {
+ await _resolveTestCode('''
+const c = [1, if (1 > 0) 2 else 3, 4];
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+ expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 4]);
+ }
+
+ test_listLiteral_ifElement_true_withoutElse() async {
+ await _resolveTestCode('''
+const c = [1, if (1 > 0) 2, 3];
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+ expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
+ }
+
test_listLiteral_nested() async {
await _resolveTestCode('''
const c = [1, if (1 > 0) if (2 > 1) 2, 3];
@@ -814,47 +854,7 @@
expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
}
- test_listLiteral_withIf_false_withElse() async {
- await _resolveTestCode('''
-const c = [1, if (1 < 0) 2 else 3, 4];
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type, typeProvider.listType.instantiate([typeProvider.intType]));
- expect(result.toListValue().map((e) => e.toIntValue()), [1, 3, 4]);
- }
-
- test_listLiteral_withIf_false_withoutElse() async {
- await _resolveTestCode('''
-const c = [1, if (1 < 0) 2, 3];
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type, typeProvider.listType.instantiate([typeProvider.intType]));
- expect(result.toListValue().map((e) => e.toIntValue()), [1, 3]);
- }
-
- test_listLiteral_withIf_true_withElse() async {
- await _resolveTestCode('''
-const c = [1, if (1 > 0) 2 else 3, 4];
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type, typeProvider.listType.instantiate([typeProvider.intType]));
- expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 4]);
- }
-
- test_listLiteral_withIf_true_withoutElse() async {
- await _resolveTestCode('''
-const c = [1, if (1 > 0) 2, 3];
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type, typeProvider.listType.instantiate([typeProvider.intType]));
- expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
- }
-
- test_listLiteral_withSpread() async {
+ test_listLiteral_spreadElement() async {
await _resolveTestCode('''
const c = [1, ...[2, 3], 4];
''');
@@ -864,6 +864,66 @@
expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3, 4]);
}
+ test_mapLiteral_ifElement_false_withElse() async {
+ await _resolveTestCode('''
+const c = {'a' : 1, if (1 < 0) 'b' : 2 else 'c' : 3, 'd' : 4};
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type,
+ typeProvider.mapType
+ .instantiate([typeProvider.stringType, typeProvider.intType]));
+ Map<DartObject, DartObject> value = result.toMapValue();
+ expect(value.keys.map((e) => e.toStringValue()),
+ unorderedEquals(['a', 'c', 'd']));
+ expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3, 4]));
+ }
+
+ test_mapLiteral_ifElement_false_withoutElse() async {
+ await _resolveTestCode('''
+const c = {'a' : 1, if (1 < 0) 'b' : 2, 'c' : 3};
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type,
+ typeProvider.mapType
+ .instantiate([typeProvider.stringType, typeProvider.intType]));
+ Map<DartObject, DartObject> value = result.toMapValue();
+ expect(
+ value.keys.map((e) => e.toStringValue()), unorderedEquals(['a', 'c']));
+ expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3]));
+ }
+
+ test_mapLiteral_ifElement_true_withElse() async {
+ await _resolveTestCode('''
+const c = {'a' : 1, if (1 > 0) 'b' : 2 else 'c' : 3, 'd' : 4};
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type,
+ typeProvider.mapType
+ .instantiate([typeProvider.stringType, typeProvider.intType]));
+ Map<DartObject, DartObject> value = result.toMapValue();
+ expect(value.keys.map((e) => e.toStringValue()),
+ unorderedEquals(['a', 'b', 'd']));
+ expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 4]));
+ }
+
+ test_mapLiteral_ifElement_true_withoutElse() async {
+ await _resolveTestCode('''
+const c = {'a' : 1, if (1 > 0) 'b' : 2, 'c' : 3};
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type,
+ typeProvider.mapType
+ .instantiate([typeProvider.stringType, typeProvider.intType]));
+ Map<DartObject, DartObject> value = result.toMapValue();
+ expect(value.keys.map((e) => e.toStringValue()),
+ unorderedEquals(['a', 'b', 'c']));
+ expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3]));
+ }
+
@failingTest
test_mapLiteral_nested() async {
// Fails because we're not yet parsing nested elements.
@@ -881,67 +941,7 @@
expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3]));
}
- test_mapLiteral_withIf_false_withElse() async {
- await _resolveTestCode('''
-const c = {'a' : 1, if (1 < 0) 'b' : 2 else 'c' : 3, 'd' : 4};
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type,
- typeProvider.mapType
- .instantiate([typeProvider.stringType, typeProvider.intType]));
- Map<DartObject, DartObject> value = result.toMapValue();
- expect(value.keys.map((e) => e.toStringValue()),
- unorderedEquals(['a', 'c', 'd']));
- expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3, 4]));
- }
-
- test_mapLiteral_withIf_false_withoutElse() async {
- await _resolveTestCode('''
-const c = {'a' : 1, if (1 < 0) 'b' : 2, 'c' : 3};
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type,
- typeProvider.mapType
- .instantiate([typeProvider.stringType, typeProvider.intType]));
- Map<DartObject, DartObject> value = result.toMapValue();
- expect(
- value.keys.map((e) => e.toStringValue()), unorderedEquals(['a', 'c']));
- expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3]));
- }
-
- test_mapLiteral_withIf_true_withElse() async {
- await _resolveTestCode('''
-const c = {'a' : 1, if (1 > 0) 'b' : 2 else 'c' : 3, 'd' : 4};
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type,
- typeProvider.mapType
- .instantiate([typeProvider.stringType, typeProvider.intType]));
- Map<DartObject, DartObject> value = result.toMapValue();
- expect(value.keys.map((e) => e.toStringValue()),
- unorderedEquals(['a', 'b', 'd']));
- expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 4]));
- }
-
- test_mapLiteral_withIf_true_withoutElse() async {
- await _resolveTestCode('''
-const c = {'a' : 1, if (1 > 0) 'b' : 2, 'c' : 3};
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type,
- typeProvider.mapType
- .instantiate([typeProvider.stringType, typeProvider.intType]));
- Map<DartObject, DartObject> value = result.toMapValue();
- expect(value.keys.map((e) => e.toStringValue()),
- unorderedEquals(['a', 'b', 'c']));
- expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3]));
- }
-
- test_mapLiteral_withSpread() async {
+ test_mapLiteral_spreadElement() async {
await _resolveTestCode('''
const c = {'a' : 1, ...{'b' : 2, 'c' : 3}, 'd' : 4};
''');
@@ -957,6 +957,46 @@
value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3, 4]));
}
+ test_setLiteral_ifElement_false_withElse() async {
+ await _resolveTestCode('''
+const c = {1, if (1 < 0) 2 else 3, 4};
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+ expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3, 4]);
+ }
+
+ test_setLiteral_ifElement_false_withoutElse() async {
+ await _resolveTestCode('''
+const c = {1, if (1 < 0) 2, 3};
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+ expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3]);
+ }
+
+ test_setLiteral_ifElement_true_withElse() async {
+ await _resolveTestCode('''
+const c = {1, if (1 > 0) 2 else 3, 4};
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+ expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 4]);
+ }
+
+ test_setLiteral_ifElement_true_withoutElse() async {
+ await _resolveTestCode('''
+const c = {1, if (1 > 0) 2, 3};
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+ expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
+ }
+
test_setLiteral_nested() async {
await _resolveTestCode('''
const c = {1, if (1 > 0) if (2 > 1) 2, 3};
@@ -967,47 +1007,7 @@
expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
}
- test_setLiteral_withIf_false_withElse() async {
- await _resolveTestCode('''
-const c = {1, if (1 < 0) 2 else 3, 4};
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type, typeProvider.setType.instantiate([typeProvider.intType]));
- expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3, 4]);
- }
-
- test_setLiteral_withIf_false_withoutElse() async {
- await _resolveTestCode('''
-const c = {1, if (1 < 0) 2, 3};
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type, typeProvider.setType.instantiate([typeProvider.intType]));
- expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3]);
- }
-
- test_setLiteral_withIf_true_withElse() async {
- await _resolveTestCode('''
-const c = {1, if (1 > 0) 2 else 3, 4};
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type, typeProvider.setType.instantiate([typeProvider.intType]));
- expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 4]);
- }
-
- test_setLiteral_withIf_true_withoutElse() async {
- await _resolveTestCode('''
-const c = {1, if (1 > 0) 2, 3};
-''');
- DartObjectImpl result = _evaluateConstant('c');
- expect(
- result.type, typeProvider.setType.instantiate([typeProvider.intType]));
- expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
- }
-
- test_setLiteral_withSpread() async {
+ test_setLiteral_spreadElement() async {
await _resolveTestCode('''
const c = {1, ...{2, 3}, 4};
''');
diff --git a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
new file mode 100644
index 0000000..b9ca532
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
@@ -0,0 +1,804 @@
+// 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/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/constant/potentially_constant.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(IsConstantTypeExpressionTest);
+ defineReflectiveTests(PotentiallyConstantTest);
+ defineReflectiveTests(PotentiallyConstantWithUIAsCodeTest);
+ });
+}
+
+@reflectiveTest
+class IsConstantTypeExpressionTest extends DriverResolutionTest {
+ test_class() async {
+ await _assertConst(r'''
+int x;
+''');
+ }
+
+ test_class_prefix() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+''');
+ await _assertConst(r'''
+import 'a.dart' as p;
+p.A x;
+''');
+ }
+
+ test_class_prefix_deferred() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+''');
+ await _assertNotConst(r'''
+import 'a.dart' deferred as p;
+p.A x;
+''');
+ }
+
+ test_class_typeArguments() async {
+ await _assertConst(r'''
+List<int> x;
+''');
+ }
+
+ test_class_typeArguments_notConst() async {
+ await _assertNotConst(r'''
+class A<T> {
+ m() {
+ List<T> x;
+ }
+}
+''');
+ }
+
+ test_dynamic() async {
+ await _assertConst(r'''
+dynamic x;
+''');
+ }
+
+ test_genericFunctionType() async {
+ await _assertConst(r'''
+int Function<T extends num, U>(int, bool) x;
+''');
+ }
+
+ test_genericFunctionType_formalParameterType() async {
+ await _assertNotConst(r'''
+class A<T> {
+ m() {
+ Function(T) x;
+ }
+}
+''');
+ }
+
+ test_genericFunctionType_returnType() async {
+ await _assertNotConst(r'''
+class A<T> {
+ m() {
+ T Function() x;
+ }
+}
+''');
+ }
+
+ test_genericFunctionType_typeParameterBound() async {
+ await _assertNotConst(r'''
+class A<T> {
+ m() {
+ Function<U extends T>() x;
+ }
+}
+''');
+ }
+
+ test_typeParameter() async {
+ await _assertNotConst(r'''
+class A<T> {
+ m() {
+ T x;
+ }
+}
+''');
+ }
+
+ test_void() async {
+ await _assertConst(r'''
+void x;
+''');
+ }
+
+ Future<void> _assertConst(String code) async {
+ addTestFile(code);
+ await resolveTestFile();
+
+ var type = findNode.variableDeclarationList('x;').type;
+ expect(isConstantTypeExpression(type), isTrue);
+ }
+
+ Future<void> _assertNotConst(String code) async {
+ addTestFile(code);
+ await resolveTestFile();
+
+ var type = findNode.variableDeclarationList('x;').type;
+ expect(isConstantTypeExpression(type), isFalse);
+ }
+}
+
+@reflectiveTest
+class PotentiallyConstantTest extends DriverResolutionTest {
+ test_asExpression() async {
+ await _assertConst(r'''
+const a = 0;
+var x = a as int;
+''', () => _xInitializer());
+ }
+
+ test_asExpression_final() async {
+ await _assertNotConst(r'''
+final a = 0;
+var x = a as int;
+''', () => _xInitializer(), () => [findNode.simple('a as')]);
+ }
+
+ test_asExpression_notConstType() async {
+ await _assertNotConst(r'''
+const a = 0;
+class A<T> {
+ m() {
+ var x = a as T;
+ }
+}
+''', () => _xInitializer(), () => [findNode.typeName('T;')]);
+ }
+
+ test_conditional() async {
+ await _assertConst(r'''
+const a = 0;
+const b = 0;
+const c = 0;
+var x = a ? b : c;
+''', () => _xInitializer());
+ }
+
+ test_conditional_final() async {
+ await _assertNotConst(
+ r'''
+final a = 0;
+final b = 0;
+final c = 0;
+var x = a ? b : c;
+''',
+ () => _xInitializer(),
+ () => [
+ findNode.simple('a ?'),
+ findNode.simple('b :'),
+ findNode.simple('c;')
+ ]);
+ }
+
+ test_instanceCreation() async {
+ await _assertNotConst(r'''
+class A {
+ const A();
+}
+
+var x = new A(); // x
+''', () => _xInitializer(), () => [findNode.instanceCreation('A(); // x')]);
+ }
+
+ test_instanceCreation_const() async {
+ await _assertConst(r'''
+class A {
+ const A();
+}
+
+var x = const A();
+''', () => _xInitializer());
+ }
+
+ test_isExpression() async {
+ await _assertConst(r'''
+const a = 0;
+var x = a is int;
+''', () => _xInitializer());
+ }
+
+ test_isExpression_final() async {
+ await _assertNotConst(r'''
+final a = 0;
+var x = a is int;
+''', () => _xInitializer(), () => [findNode.simple('a is')]);
+ }
+
+ test_isExpression_notConstType() async {
+ await _assertNotConst(r'''
+const a = 0;
+class A<T> {
+ m() {
+ var x = a is T;
+ }
+}
+''', () => _xInitializer(), () => [findNode.typeName('T;')]);
+ }
+
+ test_listLiteral() async {
+ await _assertConst(r'''
+var x = const [0, 1, 2];
+''', () => _xInitializer());
+ }
+
+ test_listLiteral_notConst() async {
+ await _assertNotConst(r'''
+var x = [0, 1, 2];
+''', () => _xInitializer(), () => [findNode.listLiteral('0,')]);
+ }
+
+ test_listLiteral_notConst_element() async {
+ await _assertNotConst(r'''
+final a = 0;
+final b = 1;
+var x = const [a, b, 2];
+''', () => _xInitializer(),
+ () => [findNode.simple('a,'), findNode.simple('b,')]);
+ }
+
+ test_listLiteral_typeArgument() async {
+ await _assertConst(r'''
+var x = const <int>[0, 1, 2];
+''', () => _xInitializer());
+ }
+
+ test_listLiteral_typeArgument_notConstType() async {
+ await _assertNotConst(r'''
+class A<T> {
+ m() {
+ var x = const <T>[0, 1, 2];
+ }
+}
+''', () => _xInitializer(), () => [findNode.typeName('T>[0')]);
+ }
+
+ test_literal_bool() async {
+ await _assertConst(r'''
+var x = true;
+''', () => _xInitializer());
+ }
+
+ test_literal_double() async {
+ await _assertConst(r'''
+var x = 1.2;
+''', () => _xInitializer());
+ }
+
+ test_literal_int() async {
+ await _assertConst(r'''
+var x = 0;
+''', () => _xInitializer());
+ }
+
+ test_literal_null() async {
+ await _assertConst(r'''
+var x = null;
+''', () => _xInitializer());
+ }
+
+ test_literal_simpleString() async {
+ await _assertConst(r'''
+var x = '123';
+''', () => _xInitializer());
+ }
+
+ test_literal_symbol() async {
+ await _assertConst(r'''
+var x = #a.b.c;
+''', () => _xInitializer());
+ }
+
+ test_mapLiteral() async {
+ await _assertConst(r'''
+var x = const {0: 1};
+''', () => _xInitializer());
+ }
+
+ test_mapLiteral_notConst() async {
+ await _assertNotConst(r'''
+var x = {0: 1};
+''', () => _xInitializer(), () => [findNode.setOrMapLiteral('0: 1')]);
+ }
+
+ test_mapLiteral_notConst_key() async {
+ await _assertNotConst(r'''
+final a = 1;
+final b = 2;
+var x = const {0: 0, a: 1, b: 2};
+''', () => _xInitializer(),
+ () => [findNode.simple('a:'), findNode.simple('b:')]);
+ }
+
+ test_mapLiteral_notConst_value() async {
+ await _assertNotConst(r'''
+final a = 1;
+final b = 2;
+var x = const {0: 0, 1: a, 2: b};
+''', () => _xInitializer(),
+ () => [findNode.simple('a,'), findNode.simple('b}')]);
+ }
+
+ test_mapLiteral_typeArgument() async {
+ await _assertConst(r'''
+var x = const <int, int>{0: 0};
+''', () => _xInitializer());
+ }
+
+ test_mapLiteral_typeArgument_notConstType() async {
+ await _assertNotConst(r'''
+class A<T> {
+ m() {
+ var x = const <T, T>{};
+ }
+}
+''', () => _xInitializer(),
+ () => [findNode.typeName('T,'), findNode.typeName('T>{')]);
+ }
+
+ test_methodInvocation_identical() async {
+ await _assertConst(r'''
+const a = 0;
+const b = 0;
+var x = identical(a, b);
+''', () => _xInitializer());
+ }
+
+ test_methodInvocation_identical_final() async {
+ await _assertNotConst(r'''
+final a = 0;
+final b = 0;
+var x = identical(a, b);
+''', () => _xInitializer(),
+ () => [findNode.simple('a,'), findNode.simple('b)')]);
+ }
+
+ test_methodInvocation_name() async {
+ await _assertNotConst(r'''
+const a = 0;
+const b = 0;
+var x = foo(a, b);
+''', () => _xInitializer(), () => [findNode.methodInvocation('foo')]);
+ }
+
+ test_methodInvocation_target() async {
+ await _assertNotConst(r'''
+var x = a.foo();
+''', () => _xInitializer(), () => [findNode.methodInvocation('a.foo()')]);
+ }
+
+ test_parenthesizedExpression_const() async {
+ await _assertConst(r'''
+const a = 0;
+var x = (a);
+''', () => _xInitializer());
+ }
+
+ test_parenthesizedExpression_final() async {
+ await _assertNotConst(r'''
+final a = 0;
+var x = (a);
+''', () => _xInitializer(), () => [findNode.simple('a);')]);
+ }
+
+ test_postfixExpression() async {
+ await _assertNotConst(r'''
+const a = 0;
+var x = a++;
+''', () => _xInitializer(), () => [findNode.postfix('a++')]);
+ }
+
+ test_prefixedIdentifier_importPrefix() async {
+ newFile('/test/lib/a.dart', content: r'''
+const a = 0;
+''');
+ await _assertConst(r'''
+import 'a.dart' as p;
+var x = p.a + 1;
+''', () => _xInitializer());
+ }
+
+ test_prefixedIdentifier_importPrefix_deferred() async {
+ newFile('/test/lib/a.dart', content: r'''
+const a = 0;
+''');
+ await _assertNotConst(r'''
+import 'a.dart' deferred as p;
+var x = p.a + 1;
+''', () => _xInitializer(), () => [findNode.prefixed('p.a')]);
+ }
+
+ test_prefixedIdentifier_length_const() async {
+ await _assertConst(r'''
+const a = 'abc';
+var x = a.length;
+''', () => _xInitializer());
+ }
+
+ test_prefixedIdentifier_length_final() async {
+ await _assertNotConst(r'''
+final a = 'abc';
+var x = a.length;
+''', () => _xInitializer(), () => [findNode.simple('a.')]);
+ }
+
+ test_prefixedIdentifier_method_instance() async {
+ await _assertNotConst(r'''
+class A {
+ const A();
+ m() {};
+}
+
+const a = const A();
+
+var x = a.m;
+''', () => _xInitializer(), () => [findNode.prefixed('a.m')]);
+ }
+
+ test_prefixedIdentifier_method_static() async {
+ await _assertConst(r'''
+class A {
+ static m() {};
+}
+
+var x = A.m;
+''', () => _xInitializer());
+ }
+
+ test_prefixedIdentifier_method_static_viaInstance() async {
+ await _assertNotConst(r'''
+class A {
+ const A();
+ static m() {};
+}
+
+const a = const A();
+
+var x = a.m;
+''', () => _xInitializer(), () => [findNode.prefixed('a.m')]);
+ }
+
+ test_prefixedIdentifier_prefix_variable() async {
+ await _assertNotConst(r'''
+class A {
+ final a = 0;
+ const A();
+}
+
+const a = const A();
+
+var x = a.b + 1;
+''', () => _xInitializer(), () => [findNode.prefixed('a.b + 1')]);
+ }
+
+ test_prefixedIdentifier_staticField_const() async {
+ await _assertConst(r'''
+class A {
+ static const a = 0;
+}
+var x = A.a + 1;
+''', () => _xInitializer());
+ }
+
+ test_prefixedIdentifier_staticField_final() async {
+ await _assertNotConst(
+ r'''
+class A {
+ static final a = 0;
+}
+var x = A.a + 1;
+''',
+ () => _xInitializer(),
+ () => [findNode.prefixed('A.a')],
+ );
+ }
+
+ test_prefixExpression_bang() async {
+ await _assertConst(r'''
+const a = 0;
+var x = !a;
+''', () => _xInitializer());
+ }
+
+ test_prefixExpression_minus() async {
+ await _assertConst(r'''
+const a = 0;
+var x = -a;
+''', () => _xInitializer());
+ }
+
+ test_prefixExpression_minus_final() async {
+ await _assertNotConst(r'''
+final a = 0;
+var x = -a;
+''', () => _xInitializer(), () => [findNode.simple('a;')]);
+ }
+
+ test_prefixExpression_plusPlus() async {
+ await _assertNotConst(r'''
+const a = 0;
+var x = ++a;
+''', () => _xInitializer(), () => [findNode.prefix('++a')]);
+ }
+
+ test_prefixExpression_tilde() async {
+ await _assertConst(r'''
+const a = 0;
+var x = ~a;
+''', () => _xInitializer());
+ }
+
+ test_propertyAccess_length_final() async {
+ await _assertNotConst(r'''
+final a = 'abc';
+var x = (a).length;
+''', () => _xInitializer(), () => [findNode.simple('a).')]);
+ }
+
+ test_propertyAccess_length_stringLiteral() async {
+ await _assertConst(r'''
+var x = 'abc'.length;
+''', () => _xInitializer());
+ }
+
+ test_propertyAccess_staticField_withPrefix_const() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ static const a = 0;
+}
+''');
+ await _assertConst(r'''
+import 'a.dart' as p;
+var x = p.A.a + 1;
+''', () => _xInitializer());
+ }
+
+ test_propertyAccess_staticField_withPrefix_deferred() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ static const a = 0;
+}
+''');
+ await _assertNotConst(r'''
+import 'a.dart' deferred as p;
+var x = p.A.a + 1;
+''', () => _xInitializer(), () => [findNode.propertyAccess('p.A.a')]);
+ }
+
+ test_propertyAccess_staticField_withPrefix_final() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ static final a = 0;
+}
+''');
+ await _assertNotConst(r'''
+import 'a.dart' as p;
+var x = p.A.a + 1;
+''', () => _xInitializer(), () => [findNode.simple('a + 1')]);
+ }
+
+ test_propertyAccess_target_instanceCreation() async {
+ await _assertNotConst(r'''
+class A {
+ final a = 0;
+}
+
+var x = A().a + 1;
+''', () => _xInitializer(), () => [findNode.propertyAccess('A().a')]);
+ }
+
+ test_propertyAccess_target_variable() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ final a = 0;
+ const A();
+}
+
+const a = const A();
+''');
+ await _assertNotConst(r'''
+import 'a.dart' as p;
+
+var x = p.a.b + 1;
+''', () => _xInitializer(), () => [findNode.propertyAccess('p.a.b + 1')]);
+ }
+
+ test_setLiteral() async {
+ await _assertConst(r'''
+var x = const {0, 1, 2};
+''', () => _xInitializer());
+ }
+
+ test_setLiteral_notConst() async {
+ await _assertNotConst(r'''
+var x = {0, 1, 2};
+''', () => _xInitializer(), () => [findNode.setOrMapLiteral('0,')]);
+ }
+
+ test_setLiteral_notConst_element() async {
+ await _assertNotConst(r'''
+final a = 0;
+final b = 1;
+var x = const {a, b, 2};
+''', () => _xInitializer(),
+ () => [findNode.simple('a,'), findNode.simple('b,')]);
+ }
+
+ test_setLiteral_typeArgument() async {
+ await _assertConst(r'''
+var x = const <int>{0, 1, 2};
+''', () => _xInitializer());
+ }
+
+ test_setLiteral_typeArgument_notConstType() async {
+ await _assertNotConst(r'''
+class A<T> {
+ m() {
+ var x = const <T>{0, 1, 2};
+ }
+}
+''', () => _xInitializer(), () => [findNode.typeName('T>{0')]);
+ }
+
+ test_simpleIdentifier_function() async {
+ await _assertConst(r'''
+var x = f;
+
+void f() {}
+''', () => _xInitializer());
+ }
+
+ test_simpleIdentifier_localVar_const() async {
+ await _assertConst(r'''
+main() {
+ const a = 0;
+ var x = a + 1;
+}
+''', () => _xInitializer());
+ }
+
+ test_simpleIdentifier_localVar_final() async {
+ await _assertNotConst(
+ r'''
+main() {
+ final a = 0;
+ var x = a + 1;
+}
+''',
+ () => _xInitializer(),
+ () => [findNode.simple('a +')],
+ );
+ }
+
+ test_simpleIdentifier_topVar_const() async {
+ await _assertConst(r'''
+const a = 0;
+var x = a + 1;
+''', () => _xInitializer());
+ }
+
+ test_simpleIdentifier_topVar_final() async {
+ await _assertNotConst(
+ r'''
+final a = 0;
+var x = a + 1;
+''',
+ () => _xInitializer(),
+ () => [findNode.simple('a +')],
+ );
+ }
+
+ test_simpleIdentifier_type_class() async {
+ await _assertConst(r'''
+var x = int;
+''', () => _xInitializer());
+ }
+
+ test_stringInterpolation_topVar_const() async {
+ await _assertConst(r'''
+const a = 0;
+var x = 'a $a b';
+''', () => _xInitializer());
+ }
+
+ test_stringInterpolation_topVar_final() async {
+ await _assertNotConst(
+ r'''
+final a = 0;
+var x = 'a $a b';
+''',
+ () => _xInitializer(),
+ () => [findNode.simple('a b')],
+ );
+ }
+
+ _assertConst(String code, AstNode Function() getNode) async {
+ addTestFile(code);
+ await resolveTestFile();
+
+ var node = getNode();
+ var notConstList = getNotPotentiallyConstants(node);
+ expect(notConstList, isEmpty);
+ }
+
+ _assertNotConst(String code, AstNode Function() getNode,
+ List<AstNode> Function() getNotConstList) async {
+ addTestFile(code);
+ await resolveTestFile();
+
+ var node = getNode();
+ var notConstList = getNotPotentiallyConstants(node);
+
+ var expectedNotConst = getNotConstList();
+ expect(notConstList, unorderedEquals(expectedNotConst));
+ }
+
+ Expression _xInitializer() {
+ return findNode.variableDeclaration('x = ').initializer;
+ }
+}
+
+@reflectiveTest
+class PotentiallyConstantWithUIAsCodeTest extends PotentiallyConstantTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_ifElement_then() async {
+ await _assertConst(r'''
+const a = 0;
+const b = 0;
+var x = const [if (a) b];
+''', () => _xInitializer());
+ }
+
+ test_ifElement_then_final() async {
+ await _assertNotConst(r'''
+final a = 0;
+final b = 0;
+var x = const [if (a) b];
+''', () => _xInitializer(),
+ () => [findNode.simple('a)'), findNode.simple('b]')]);
+ }
+
+ test_ifElement_thenElse() async {
+ await _assertConst(r'''
+const a = 0;
+const b = 0;
+const c = 0;
+var x = const [if (a) b else c];
+''', () => _xInitializer());
+ }
+
+ test_spreadElement() async {
+ await _assertConst(r'''
+const a = [0, 1, 2];
+var x = const [...a];
+''', () => _xInitializer());
+ }
+
+ test_spreadElement_final() async {
+ await _assertNotConst(r'''
+final a = [0, 1, 2];
+var x = const [...a];
+''', () => _xInitializer(), () => [findNode.simple('a];')]);
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/constant/test_all.dart b/pkg/analyzer/test/src/dart/constant/test_all.dart
index 022da95..95c1b2e 100644
--- a/pkg/analyzer/test/src/dart/constant/test_all.dart
+++ b/pkg/analyzer/test/src/dart/constant/test_all.dart
@@ -5,13 +5,14 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'evaluation_test.dart' as evaluation;
+import 'potentially_constant_test.dart' as potentially_constant;
import 'utilities_test.dart' as utilities;
import 'value_test.dart' as value;
-/// Utility for manually running all tests.
main() {
defineReflectiveSuite(() {
evaluation.main();
+ potentially_constant.main();
utilities.main();
value.main();
}, name: 'constant');
diff --git a/pkg/analyzer/test/src/dart/constant/utilities_test.dart b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
index 0fa3898..f501f97 100644
--- a/pkg/analyzer/test/src/dart/constant/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -17,7 +18,6 @@
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:analyzer/src/task/dart.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
new file mode 100644
index 0000000..3069acf
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2018, 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/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ForEachElementTest);
+ defineReflectiveTests(ForLoopElementTest);
+ });
+}
+
+@reflectiveTest
+class ForEachElementTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_declaredIdentifierScope() async {
+ addTestFile(r'''
+main() {
+ <int>[for (var i in [1, 2, 3]) i]; // 1
+ <double>[for (var i in [1.1, 2.2, 3.3]) i]; // 2
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertElement(
+ findNode.simple('i]; // 1'),
+ findNode.simple('i in [1, 2').staticElement,
+ );
+ assertElement(
+ findNode.simple('i]; // 2'),
+ findNode.simple('i in [1.1').staticElement,
+ );
+ }
+}
+
+@reflectiveTest
+class ForLoopElementTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_declaredVariableScope() async {
+ addTestFile(r'''
+main() {
+ <int>[for (var i = 1; i < 10; i += 3) i]; // 1
+ <double>[for (var i = 1.1; i < 10; i += 5) i]; // 2
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertElement(
+ findNode.simple('i]; // 1'),
+ findNode.simple('i = 1;').staticElement,
+ );
+ assertElement(
+ findNode.simple('i]; // 2'),
+ findNode.simple('i = 1.1;').staticElement,
+ );
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 71d5075..ccbc919 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -1,51 +1,57 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'assignment_test.dart' as assignment_test;
-import 'class_test.dart' as class_test;
-import 'comment_test.dart' as comment_test;
-import 'constant_test.dart' as constant_test;
-import 'enum_test.dart' as enum_test;
-import 'flow_analysis_test.dart' as flow_analysis_test;
-import 'for_in_test.dart' as for_in_test;
-import 'generic_type_alias_test.dart' as generic_type_alias_test;
-import 'import_prefix_test.dart' as import_prefix_test;
-import 'instance_creation_test.dart' as instance_creation_test;
+import 'assignment_test.dart' as assignment;
+import 'class_alias_test.dart' as class_alias;
+import 'class_test.dart' as class_resolution;
+import 'comment_test.dart' as comment;
+import 'constant_test.dart' as constant;
+import 'definite_assignment_test.dart' as definite_assignment;
+import 'enum_test.dart' as enum_resolution;
+import 'flow_analysis_test.dart' as flow_analysis;
+import 'for_element_test.dart' as for_element;
+import 'for_in_test.dart' as for_in;
+import 'generic_type_alias_test.dart' as generic_type_alias;
+import 'import_prefix_test.dart' as import_prefix;
+import 'instance_creation_test.dart' as instance_creation;
import 'instance_member_inference_class_test.dart'
- as instance_member_inference_class_test;
+ as instance_member_inference_class;
import 'instance_member_inference_mixin_test.dart'
- as instance_member_inference_mixin_test;
-import 'method_invocation_test.dart' as method_invocation_test;
-import 'mixin_test.dart' as mixin_test;
-import 'non_nullable_test.dart' as non_nullable_test;
-import 'optional_const_test.dart' as optional_const_test;
-import 'property_access_test.dart' as property_access_test;
-import 'top_type_inference_test.dart' as top_type_inference_test;
+ as instance_member_inference_mixin;
+import 'method_invocation_test.dart' as method_invocation;
+import 'mixin_test.dart' as mixin_resolution;
+import 'non_nullable_test.dart' as non_nullable;
+import 'optional_const_test.dart' as optional_const;
+import 'property_access_test.dart' as property_access;
+import 'top_type_inference_test.dart' as top_type_inference;
import 'type_inference/test_all.dart' as type_inference;
main() {
defineReflectiveSuite(() {
- assignment_test.main();
- class_test.main();
- comment_test.main();
- constant_test.main();
- enum_test.main();
- flow_analysis_test.main();
- for_in_test.main();
- generic_type_alias_test.main();
- import_prefix_test.main();
- instance_creation_test.main();
- instance_member_inference_class_test.main();
- instance_member_inference_mixin_test.main();
- method_invocation_test.main();
- mixin_test.main();
- non_nullable_test.main();
- optional_const_test.main();
- property_access_test.main();
- top_type_inference_test.main();
+ assignment.main();
+ class_alias.main();
+ class_resolution.main();
+ comment.main();
+ constant.main();
+ definite_assignment.main();
+ enum_resolution.main();
+ flow_analysis.main();
+ for_element.main();
+ for_in.main();
+ generic_type_alias.main();
+ import_prefix.main();
+ instance_creation.main();
+ instance_member_inference_class.main();
+ instance_member_inference_mixin.main();
+ method_invocation.main();
+ mixin_resolution.main();
+ non_nullable.main();
+ optional_const.main();
+ property_access.main();
+ top_type_inference.main();
type_inference.main();
}, name: 'resolution');
}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
index 2f0f5a8..1f90c94 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
@@ -41,7 +41,35 @@
assertType(findNode.listLiteral('['), 'List<String>');
}
- test_context_typeArgs_expression_conflict() async {
+ test_context_noTypeArgs_noElements_typeParameter() async {
+ addTestFile('''
+class A<E extends List<int>> {
+ E a = [];
+}
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<dynamic>');
+ }
+
+ test_context_noTypeArgs_noElements_typeParameter_dynamic() async {
+ addTestFile('''
+class A<E extends List<dynamic>> {
+ E a = [];
+}
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<dynamic>');
+ }
+
+ test_context_typeArgs_expression_conflictingContext() async {
+ addTestFile('''
+List<String> a = <int>[0];
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<int>');
+ }
+
+ test_context_typeArgs_expression_conflictingExpression() async {
addTestFile('''
List<String> a = <String>[0];
''');
@@ -49,6 +77,17 @@
assertType(findNode.listLiteral('['), 'List<String>');
}
+ @failingTest
+ test_context_typeArgs_expression_conflictingTypeArgs() async {
+ // Context type and element types both suggest `String`, so this should
+ // override the explicit type argument.
+ addTestFile('''
+List<String> a = <int>['a'];
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<String>');
+ }
+
test_context_typeArgs_expression_noConflict() async {
addTestFile('''
List<String> a = <String>['a'];
@@ -73,15 +112,7 @@
assertType(findNode.listLiteral('['), 'List<String>');
}
- test_noContext_noTypeArgs_expressions_conflict() async {
- addTestFile('''
-var a = [1, '2', 3];
-''');
- await resolveTestFile();
- assertType(findNode.listLiteral('['), 'List<Object>');
- }
-
- test_noContext_noTypeArgs_expressions_noConflict() async {
+ test_noContext_noTypeArgs_expressions_lubOfInt() async {
addTestFile('''
var a = [1, 2, 3];
''');
@@ -89,6 +120,22 @@
assertType(findNode.listLiteral('['), 'List<int>');
}
+ test_noContext_noTypeArgs_expressions_lubOfNum() async {
+ addTestFile('''
+var a = [1, 2.3, 4];
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<num>');
+ }
+
+ test_noContext_noTypeArgs_expressions_lubOfObject() async {
+ addTestFile('''
+var a = [1, '2', 3];
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<Object>');
+ }
+
test_noContext_noTypeArgs_noElements() async {
addTestFile('''
var a = [];
@@ -113,6 +160,15 @@
assertType(findNode.listLiteral('['), 'List<int>');
}
+ @failingTest
+ test_noContext_typeArgs_expressions_conflict() async {
+ addTestFile('''
+var a = <int, String>[1, 2];
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<int>');
+ }
+
test_noContext_typeArgs_noElements() async {
addTestFile('''
var a = <num>[];
@@ -134,7 +190,7 @@
test_noContext_noTypeArgs_forEachWithDeclaration() async {
addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
var a = [for (int e in c) e * 2];
''');
await resolveTestFile();
@@ -143,7 +199,7 @@
test_noContext_noTypeArgs_forEachWithIdentifier() async {
addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
int b;
var a = [for (b in c) b * 2];
''');
@@ -170,72 +226,90 @@
test_noContext_noTypeArgs_if() async {
addTestFile('''
-var c = true;
+bool c = true;
var a = [if (c) 1];
''');
await resolveTestFile();
assertType(findNode.listLiteral('['), 'List<int>');
}
- test_noContext_noTypeArgs_ifElse_conflict() async {
+ test_noContext_noTypeArgs_ifElse_lubOfInt() async {
addTestFile('''
-var c = true;
-var a = [if (c) 1 else '2'];
-''');
- await resolveTestFile();
- assertType(findNode.listLiteral('['), 'List<Object>');
- }
-
- test_noContext_noTypeArgs_ifElse_noConflict() async {
- addTestFile('''
-var c = true;
+bool c = true;
var a = [if (c) 1 else 2];
''');
await resolveTestFile();
assertType(findNode.listLiteral('['), 'List<int>');
}
+ test_noContext_noTypeArgs_ifElse_lubOfNum() async {
+ addTestFile('''
+bool c = true;
+var a = [if (c) 1 else 2.3];
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<num>');
+ }
+
+ test_noContext_noTypeArgs_ifElse_lubOfObject() async {
+ addTestFile('''
+bool c = true;
+var a = [if (c) 1 else '2'];
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<Object>');
+ }
+
test_noContext_noTypeArgs_spread() async {
addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
var a = [...c];
''');
await resolveTestFile();
assertType(findNode.listLiteral('[...'), 'List<int>');
}
- test_noContext_noTypeArgs_spread_conflict() async {
+ test_noContext_noTypeArgs_spread_lubOfInt() async {
addTestFile('''
-var c = [1];
-var b = ['a'];
-var a = [...b, ...c];
-''');
- await resolveTestFile();
- assertType(findNode.listLiteral('[...'), 'List<Object>');
- }
-
- test_noContext_noTypeArgs_spread_noConflict() async {
- addTestFile('''
-var c = [1];
-var b = [2];
+List<int> c;
+List<int> b;
var a = [...b, ...c];
''');
await resolveTestFile();
assertType(findNode.listLiteral('[...'), 'List<int>');
}
- test_noContext_noTypeArgs_spread_onlyNull() async {
+ test_noContext_noTypeArgs_spread_lubOfNum() async {
addTestFile('''
-f() {
- var futureNull = Future.value(null);
- var a = [...?await futureNull];
-}
+List<int> c;
+List<double> b;
+var a = [...b, ...c];
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('[...'), 'List<num>');
+ }
+
+ test_noContext_noTypeArgs_spread_lubOfObject() async {
+ addTestFile('''
+List<int> c;
+List<String> b;
+var a = [...b, ...c];
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('[...'), 'List<Object>');
+ }
+
+ test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
+ addTestFile('''
+List<int> c;
+dynamic d;
+var a = [if (0 < 1) ...c else ...d];
''');
await resolveTestFile();
assertType(findNode.listLiteral('['), 'List<dynamic>');
}
- test_noContext_noTypeArgs_spread_nullAndNotNull() async {
+ test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull() async {
addTestFile('''
f() {
var futureNull = Future.value(null);
@@ -243,6 +317,17 @@
}
''');
await resolveTestFile();
- assertType(findNode.listLiteral('['), 'List<int>');
+ assertType(findNode.listLiteral('['), 'List<dynamic>');
+ }
+
+ test_noContext_noTypeArgs_spread_nullAware_onlyNull() async {
+ addTestFile('''
+f() {
+ var futureNull = Future.value(null);
+ var a = [...?await futureNull];
+}
+''');
+ await resolveTestFile();
+ assertType(findNode.listLiteral('['), 'List<Null>');
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
index e796c8e..7c7d5cd 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
@@ -20,7 +20,7 @@
class MapLiteralTest extends DriverResolutionTest {
AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
- test_context_noTypeArgs_entry_conflict() async {
+ test_context_noTypeArgs_entry_conflictingKey() async {
addTestFile('''
Map<int, int> a = {'a' : 1};
''');
@@ -28,6 +28,14 @@
assertType(setOrMapLiteral('{'), 'Map<int, int>');
}
+ test_context_noTypeArgs_entry_conflictingValue() async {
+ addTestFile('''
+Map<int, int> a = {1 : 'a'};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{'), 'Map<int, int>');
+ }
+
test_context_noTypeArgs_entry_noConflict() async {
addTestFile('''
Map<int, int> a = {1 : 2};
@@ -44,7 +52,27 @@
assertType(setOrMapLiteral('{'), 'Map<String, String>');
}
- test_context_typeArgs_entry_conflict() async {
+ test_context_noTypeArgs_noEntries_typeParameters() async {
+ addTestFile('''
+class A<E extends Map<int, String>> {
+ E a = {};
+}
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{}'), 'Map<dynamic, dynamic>');
+ }
+
+ test_context_noTypeArgs_noEntries_typeParameters_dynamic() async {
+ addTestFile('''
+class A<E extends Map<dynamic, dynamic>> {
+ E a = {};
+}
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{}'), 'Map<dynamic, dynamic>');
+ }
+
+ test_context_typeArgs_entry_conflictingKey() async {
addTestFile('''
Map<String, String> a = <String, String>{0 : 'a'};
''');
@@ -52,6 +80,14 @@
assertType(setOrMapLiteral('{'), 'Map<String, String>');
}
+ test_context_typeArgs_entry_conflictingValue() async {
+ addTestFile('''
+Map<String, String> a = <String, String>{'a' : 1};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{'), 'Map<String, String>');
+ }
+
test_context_typeArgs_entry_noConflict() async {
addTestFile('''
Map<String, String> a = <String, String>{'a' : 'b'};
@@ -76,15 +112,25 @@
assertType(setOrMapLiteral('{'), 'Map<String, String>');
}
- test_noContext_noTypeArgs_expressions_conflict() async {
+ test_default_constructor_param_typed() async {
addTestFile('''
-var a = {1 : '1', '2' : 2, 3 : '3'};
+class C {
+ const C({x = const <String, int>{}});
+}
''');
await resolveTestFile();
- assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
}
- test_noContext_noTypeArgs_expressions_noConflict() async {
+ test_default_constructor_param_untyped() async {
+ addTestFile('''
+class C {
+ const C({x = const {}});
+}
+''');
+ await resolveTestFile();
+ }
+
+ test_noContext_noTypeArgs_expressions_lubOfIntAndString() async {
addTestFile('''
var a = {1 : 'a', 2 : 'b', 3 : 'c'};
''');
@@ -92,6 +138,22 @@
assertType(setOrMapLiteral('{'), 'Map<int, String>');
}
+ test_noContext_noTypeArgs_expressions_lubOfNumAndNum() async {
+ addTestFile('''
+var a = {1 : 2, 3.0 : 4, 5 : 6.0};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{'), 'Map<num, num>');
+ }
+
+ test_noContext_noTypeArgs_expressions_lubOfObjectAndObject() async {
+ addTestFile('''
+var a = {1 : '1', '2' : 2, 3 : '3'};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
+ }
+
test_noContext_noTypeArgs_noEntries() async {
addTestFile('''
var a = {};
@@ -100,9 +162,17 @@
assertType(setOrMapLiteral('{'), 'Map<dynamic, dynamic>');
}
- test_noContext_typeArgs_entry_conflict() async {
+ test_noContext_typeArgs_entry_conflictingKey() async {
addTestFile('''
-var a = <String, int>{'a' : 1};
+var a = <String, int>{1 : 2};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{'), 'Map<String, int>');
+ }
+
+ test_noContext_typeArgs_entry_conflictingValue() async {
+ addTestFile('''
+var a = <String, int>{'a' : 'b'};
''');
await resolveTestFile();
assertType(setOrMapLiteral('{'), 'Map<String, int>');
@@ -116,7 +186,7 @@
assertType(setOrMapLiteral('{'), 'Map<int, int>');
}
- test_noContext_typeArgs_expression_conflict() async {
+ test_noContext_typeArgs_expression_conflictingElement() async {
addTestFile('''
var a = <int, String>{1};
''');
@@ -124,6 +194,15 @@
assertType(setOrMapLiteral('{'), 'Map<int, String>');
}
+ @failingTest
+ test_noContext_typeArgs_expressions_conflictingTypeArgs() async {
+ addTestFile('''
+var a = <int>{1 : 2, 3 : 4};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{'), 'Map<int, int>');
+ }
+
test_noContext_typeArgs_noEntries() async {
addTestFile('''
var a = <num, String>{};
@@ -147,7 +226,7 @@
test_noContext_noTypeArgs_forEachWithDeclaration() async {
addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
var a = {for (int e in c) e : e * 2};
''');
await resolveTestFile();
@@ -156,7 +235,7 @@
test_noContext_noTypeArgs_forEachWithIdentifier() async {
addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
int b;
var a = {for (b in c) b * 2 : b};
''');
@@ -183,66 +262,118 @@
test_noContext_noTypeArgs_if() async {
addTestFile('''
-var c = true;
+bool c = true;
var a = {if (c) 1 : 2};
''');
await resolveTestFile();
assertType(setOrMapLiteral('{'), 'Map<int, int>');
}
- test_noContext_noTypeArgs_ifElse_conflict() async {
+ test_noContext_noTypeArgs_ifElse_lubOfIntAndInt() async {
addTestFile('''
-var c = true;
-var a = {if (c) 1 : '1' else '2': 2 };
-''');
- await resolveTestFile();
- assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
- }
-
- test_noContext_noTypeArgs_ifElse_noConflict() async {
- addTestFile('''
-var c = true;
+bool c = true;
var a = {if (c) 1 : 3 else 2 : 4};
''');
await resolveTestFile();
assertType(setOrMapLiteral('{'), 'Map<int, int>');
}
+ test_noContext_noTypeArgs_ifElse_lubOfNumAndNum() async {
+ addTestFile('''
+bool c = true;
+var a = {if (c) 1.0 : 3 else 2 : 4.0};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{'), 'Map<num, num>');
+ }
+
+ test_noContext_noTypeArgs_ifElse_lubOfObjectAndObject() async {
+ addTestFile('''
+bool c = true;
+var a = {if (c) 1 : '1' else '2': 2 };
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
+ }
+
test_noContext_noTypeArgs_spread() async {
addTestFile('''
-Map<int, int> c = {1 : 1, 2 : 2, 3 : 3};
+Map<int, int> c;
var a = {...c};
''');
await resolveTestFile();
assertType(setOrMapLiteral('{...'), 'Map<int, int>');
}
- test_noContext_noTypeArgs_spread_conflict() async {
+ test_noContext_noTypeArgs_spread_dynamic() async {
addTestFile('''
-Map<int, int> c = {1 : 2};
-Map<String, String> b = {'a' : 'b'};
+var c = {};
+var a = {...c};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{...'), 'Map<dynamic, dynamic>');
+ }
+
+ test_noContext_noTypeArgs_spread_lubOfIntAndInt() async {
+ addTestFile('''
+Map<int, int> c;
+Map<int, int> b;
+var a = {...b, ...c};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{...'), 'Map<int, int>');
+ }
+
+ test_noContext_noTypeArgs_spread_lubOfNumAndNum() async {
+ addTestFile('''
+Map<int, double> c;
+Map<double, int> b;
+var a = {...b, ...c};
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{...'), 'Map<num, num>');
+ }
+
+ test_noContext_noTypeArgs_spread_lubOfObjectObject() async {
+ addTestFile('''
+Map<int, int> c;
+Map<String, String> b;
var a = {...b, ...c};
''');
await resolveTestFile();
assertType(setOrMapLiteral('{...'), 'Map<Object, Object>');
}
- test_noContext_noTypeArgs_spread_dynamic() async {
+ test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
addTestFile('''
-var c = {1 : 1, 2 : 2, 3 : 3};
-var a = {...c};
+Map<String, int> c;
+dynamic d;
+var a = {if (0 < 1) ...c else ...d};
''');
await resolveTestFile();
- assertType(setOrMapLiteral('{...'), 'Map<int, int>');
+ assertType(setOrMapLiteral('{'), 'Map<dynamic, dynamic>');
}
- test_noContext_noTypeArgs_spread_noConflict() async {
+ @failingTest
+ test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull() async {
addTestFile('''
-Map<int, int> c = {1 : 3};
-Map<int, int> b = {2 : 4};
-var a = {...b, ...c};
+f() {
+ var futureNull = Future.value(null);
+ var a = {1 : 'a', ...?await futureNull, 2 : 'b'};
+}
''');
await resolveTestFile();
- assertType(setOrMapLiteral('{...'), 'Map<int, int>');
+ assertType(setOrMapLiteral('{1'), 'Map<int, String>');
+ }
+
+ test_noContext_noTypeArgs_spread_nullAware_onlyNull() async {
+ addTestFile('''
+f() {
+ var futureNull = Future.value(null);
+ var a = {...?await futureNull};
+}
+''');
+ await resolveTestFile();
+ assertType(setOrMapLiteral('{...'), 'dynamic');
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
index b4bd6a9..b2da4b7 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
@@ -54,7 +54,17 @@
assertType(setLiteral('{}'), 'Set<dynamic>');
}
- test_context_typeArgs_expression_conflict() async {
+ test_context_noTypeArgs_noElements_typeParameter_dynamic() async {
+ addTestFile('''
+class A<E extends Set<dynamic>> {
+ E a = {};
+}
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{}'), 'Set<dynamic>');
+ }
+
+ test_context_typeArgs_expression_conflictingExpression() async {
addTestFile('''
Set<String> a = <String>{0};
''');
@@ -62,6 +72,15 @@
assertType(setLiteral('{'), 'Set<String>');
}
+ @failingTest
+ test_context_typeArgs_expression_conflictingTypeArgs() async {
+ addTestFile('''
+Set<String> a = <int>{'a'};
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{'), 'Set<String>');
+ }
+
test_context_typeArgs_expression_noConflict() async {
addTestFile('''
Set<String> a = <String>{'a'};
@@ -86,15 +105,7 @@
assertType(setLiteral('{'), 'Set<String>');
}
- test_noContext_noTypeArgs_expressions_conflict() async {
- addTestFile('''
-var a = {1, '2', 3};
-''');
- await resolveTestFile();
- assertType(setLiteral('{'), 'Set<Object>');
- }
-
- test_noContext_noTypeArgs_expressions_noConflict() async {
+ test_noContext_noTypeArgs_expressions_lubOfInt() async {
addTestFile('''
var a = {1, 2, 3};
''');
@@ -102,6 +113,22 @@
assertType(setLiteral('{'), 'Set<int>');
}
+ test_noContext_noTypeArgs_expressions_lubOfNum() async {
+ addTestFile('''
+var a = {1, 2.3, 4};
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{'), 'Set<num>');
+ }
+
+ test_noContext_noTypeArgs_expressions_lubOfObject() async {
+ addTestFile('''
+var a = {1, '2', 3};
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{'), 'Set<Object>');
+ }
+
test_noContext_typeArgs_expression_conflict() async {
addTestFile('''
var a = <String>{1};
@@ -118,6 +145,15 @@
assertType(setLiteral('{'), 'Set<int>');
}
+ @failingTest
+ test_noContext_typeArgs_expressions_conflict() async {
+ addTestFile('''
+var a = <int, String>{1, 2};
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{'), 'Set<int>');
+ }
+
test_noContext_typeArgs_noElements() async {
addTestFile('''
var a = <num>{};
@@ -139,16 +175,9 @@
@override
AstNode setLiteral(String search) => findNode.setOrMapLiteral(search);
- @failingTest
- @override
- test_context_noTypeArgs_noElements_typeParameter() async {
- // Failing because Map<dynamic, dynamic> is being inferred.
- await super.test_context_noTypeArgs_noElements_typeParameter();
- }
-
test_noContext_noTypeArgs_forEachWithDeclaration() async {
addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
var a = {for (int e in c) e * 2};
''');
await resolveTestFile();
@@ -157,7 +186,7 @@
test_noContext_noTypeArgs_forEachWithIdentifier() async {
addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
int b;
var a = {for (b in c) b * 2};
''');
@@ -184,57 +213,98 @@
test_noContext_noTypeArgs_if() async {
addTestFile('''
-var c = true;
+bool c = true;
var a = {if (c) 1};
''');
await resolveTestFile();
assertType(setLiteral('{'), 'Set<int>');
}
- test_noContext_noTypeArgs_ifElse_conflict() async {
+ test_noContext_noTypeArgs_ifElse_lubOfInt() async {
addTestFile('''
-var c = true;
-var a = {if (c) 1 else '2'};
-''');
- await resolveTestFile();
- assertType(setLiteral('{'), 'Set<Object>');
- }
-
- test_noContext_noTypeArgs_ifElse_noConflict() async {
- addTestFile('''
-var c = true;
+bool c = true;
var a = {if (c) 1 else 2};
''');
await resolveTestFile();
assertType(setLiteral('{'), 'Set<int>');
}
+ test_noContext_noTypeArgs_ifElse_lubOfNum() async {
+ addTestFile('''
+bool c = true;
+var a = {if (c) 1 else 2.3};
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{'), 'Set<num>');
+ }
+
+ test_noContext_noTypeArgs_ifElse_lubOfObject() async {
+ addTestFile('''
+bool c = true;
+var a = {if (c) 1 else '2'};
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{'), 'Set<Object>');
+ }
+
test_noContext_noTypeArgs_spread() async {
addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
var a = {...c};
''');
await resolveTestFile();
assertType(setLiteral('{...'), 'Set<int>');
}
- test_noContext_noTypeArgs_spread_conflict() async {
+ test_noContext_noTypeArgs_spread_lubOfInt() async {
addTestFile('''
-var c = [1];
-var b = ['a'];
+List<int> c;
+List<int> b;
+var a = {...b, ...c};
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{...'), 'Set<int>');
+ }
+
+ test_noContext_noTypeArgs_spread_lubOfNum() async {
+ addTestFile('''
+List<int> c;
+List<double> b;
+var a = {...b, ...c};
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{...'), 'Set<num>');
+ }
+
+ test_noContext_noTypeArgs_spread_lubOfObject() async {
+ addTestFile('''
+List<int> c;
+List<String> b;
var a = {...b, ...c};
''');
await resolveTestFile();
assertType(setLiteral('{...'), 'Set<Object>');
}
- test_noContext_noTypeArgs_spread_noConflict() async {
+ test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
addTestFile('''
-var c = [1];
-var b = [2];
-var a = {...b, ...c};
+List<int> c;
+dynamic d;
+var a = {if (0 < 1) ...c else ...d};
''');
await resolveTestFile();
- assertType(setLiteral('{...'), 'Set<int>');
+ assertType(setLiteral('{'), 'Set<dynamic>');
+ }
+
+ @failingTest
+ test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull() async {
+ addTestFile('''
+f() {
+ var futureNull = Future.value(null);
+ var a = {1, ...?await futureNull, 2};
+}
+''');
+ await resolveTestFile();
+ assertType(setLiteral('{1'), 'Set<int>');
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart b/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
new file mode 100644
index 0000000..8e95614
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2019, 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/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(AmbiguousSetOrMapLiteralBothTest);
+ defineReflectiveTests(AmbiguousSetOrMapLiteralEitherTest);
+ });
+}
+
+@reflectiveTest
+class AmbiguousSetOrMapLiteralBothTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections
+ ];
+
+ test_setAndMap() async {
+ assertErrorsInCode('''
+Map<int, int> map;
+Set<int> set;
+var c = {...set, ...map};
+''', [CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH]);
+ }
+}
+
+@reflectiveTest
+class AmbiguousSetOrMapLiteralEitherTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections
+ ];
+
+ test_setAndMap() async {
+ assertErrorsInCode('''
+var map;
+var set;
+var c = {...set, ...map};
+''', [CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
index f51e17b..5f92e7f 100644
--- a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
@@ -2,6 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -10,6 +13,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ConstEvalThrowsExceptionTest);
+ defineReflectiveTests(ConstEvalThrowsExceptionWithUIAsCodeTest);
});
}
@@ -80,4 +84,94 @@
await resolveTestFile();
assertNoTestErrors();
}
+
+ test_default_constructor_arg_empty_map_importAnalyzedAfter() async {
+ addTestFile('''
+import 'other.dart';
+
+main() {
+ var c = const C();
+}
+''');
+ newFile('/test/lib/other.dart', content: '''
+class C {
+ final Map<String, int> m;
+ const C({this.m = const <String, int>{}})
+ : assert(m != null);
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+ var otherFileResult =
+ await resolveFile(convertPath('/test/lib/other.dart'));
+ expect(otherFileResult.errors, isEmpty);
+ }
+
+ test_default_constructor_arg_empty_map_importAnalyzedBefore() async {
+ addTestFile('''
+import 'other.dart';
+
+main() {
+ var c = const C();
+}
+''');
+ newFile('/test/lib/other.dart', content: '''
+class C {
+ final Map<String, int> m;
+ const C({this.m = const <String, int>{}})
+ : assert(m != null);
+}
+''');
+ var otherFileResult =
+ await resolveFile(convertPath('/test/lib/other.dart'));
+ expect(otherFileResult.errors, isEmpty);
+ await resolveTestFile();
+ assertNoTestErrors();
+ }
+}
+
+@reflectiveTest
+class ConstEvalThrowsExceptionWithUIAsCodeTest
+ extends ConstEvalThrowsExceptionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_ifElement_false_thenNotEvaluated() async {
+ assertNoErrorsInCode('''
+const dynamic nil = null;
+const c = [if (1 < 0) nil + 1];
+''');
+ }
+
+ test_ifElement_nonBoolCondition_list() async {
+ assertErrorsInCode('''
+const dynamic nonBool = 3;
+const c = const [if (nonBool) 'a'];
+''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+ }
+
+ test_ifElement_nonBoolCondition_map() async {
+ assertErrorsInCode('''
+const dynamic nonBool = null;
+const c = const {if (nonBool) 'a' : 1};
+''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+ }
+
+ test_ifElement_nonBoolCondition_set() async {
+ assertErrorsInCode('''
+const dynamic nonBool = 'a';
+const c = const {if (nonBool) 3};
+''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+ }
+
+ test_ifElement_true_elseNotEvaluated() async {
+ assertNoErrorsInCode('''
+const dynamic nil = null;
+const c = [if (0 < 1) 3 else nil + 1];
+''');
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart b/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart
new file mode 100644
index 0000000..9822a85
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConstMapKeyExpressionTypeImplementsEqualsTest);
+ defineReflectiveTests(
+ ConstMapKeyExpressionTypeImplementsEqualsWithUIAsCodeTest,
+ );
+ });
+}
+
+@reflectiveTest
+class ConstMapKeyExpressionTypeImplementsEqualsTest
+ extends DriverResolutionTest {
+ test_abstract() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ const A();
+ bool operator==(Object other);
+}
+
+main() {
+ const {const A(): 0};
+}
+''');
+ }
+
+ test_constField() async {
+ await assertErrorsInCode(r'''
+main() {
+ const {double.INFINITY: 0};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+ }
+
+ test_direct() async {
+ await assertErrorsInCode(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+
+main() {
+ const {const A() : 0};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+ }
+
+ test_dynamic() async {
+ // Note: static type of B.a is "dynamic", but actual type of the const
+ // object is A. We need to make sure we examine the actual type when
+ // deciding whether there is a problem with operator==.
+ await assertErrorsInCode(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+
+class B {
+ static const a = const A();
+}
+
+main() {
+ const {B.a : 0};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+ }
+
+ test_factory() async {
+ await assertErrorsInCode(r'''
+class A {
+ const factory A() = B;
+}
+
+class B implements A {
+ const B();
+ operator ==(o) => true;
+}
+
+main() {
+ const {const A(): 42};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+ }
+
+ test_super() async {
+ await assertErrorsInCode(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+
+class B extends A {
+ const B();
+}
+
+main() {
+ const {const B() : 0};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+ }
+}
+
+@reflectiveTest
+class ConstMapKeyExpressionTypeImplementsEqualsWithUIAsCodeTest
+ extends ConstMapKeyExpressionTypeImplementsEqualsTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+}
diff --git a/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart b/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
new file mode 100644
index 0000000..95fa251
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConstSetElementTypeImplementsEqualsTest);
+ defineReflectiveTests(
+ ConstSetElementTypeImplementsEqualsWithUIAsCodeTest,
+ );
+ });
+}
+
+@reflectiveTest
+class ConstSetElementTypeImplementsEqualsTest extends DriverResolutionTest {
+ test_constField() async {
+ await assertErrorsInCode(r'''
+class A {
+ static const a = const A();
+ const A();
+ operator ==(other) => false;
+}
+main() {
+ const {A.a};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ }
+
+ test_direct() async {
+ await assertErrorsInCode(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+main() {
+ const {const A()};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ }
+
+ test_dynamic() async {
+ // Note: static type of B.a is "dynamic", but actual type of the const
+ // object is A. We need to make sure we examine the actual type when
+ // deciding whether there is a problem with operator==.
+ await assertErrorsInCode(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+class B {
+ static const a = const A();
+}
+main() {
+ const {B.a};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ }
+
+ test_factory() async {
+ await assertErrorsInCode(r'''
+class A { const factory A() = B; }
+
+class B implements A {
+ const B();
+
+ operator ==(o) => true;
+}
+
+main() {
+ var m = const {const A()};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ }
+
+ test_super() async {
+ await assertErrorsInCode(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+class B extends A {
+ const B();
+}
+main() {
+ const {const B()};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ }
+}
+
+@reflectiveTest
+class ConstSetElementTypeImplementsEqualsWithUIAsCodeTest
+ extends ConstSetElementTypeImplementsEqualsTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_spread_list() async {
+ await assertErrorsInCode(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+
+main() {
+ const {...[A()]};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ }
+
+ test_spread_set() async {
+ await assertErrorsInCode(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+
+main() {
+ const {...{A()}};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart b/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
new file mode 100644
index 0000000..9c8d9f4
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConstSpreadExpectedListOrSetTest);
+ });
+}
+
+@reflectiveTest
+class ConstSpreadExpectedListOrSetTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_const_listInt() async {
+ await assertErrorsInCode('''
+const dynamic a = 5;
+var b = const <int>[...a];
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+ }
+
+ test_const_listList() async {
+ await assertNoErrorsInCode('''
+const dynamic a = [5];
+var b = const <int>[...a];
+''');
+ }
+
+ test_const_listMap() async {
+ await assertErrorsInCode('''
+const dynamic a = <int, int>{0: 1};
+var b = const <int>[...a];
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+ }
+
+ test_const_listNull() async {
+ await assertErrorsInCode('''
+const dynamic a = null;
+var b = const <int>[...a];
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+ }
+
+ test_const_listNull_nullable() async {
+ await assertNoErrorsInCode('''
+const dynamic a = null;
+var b = const <int>[...?a];
+''');
+ }
+
+ test_const_listSet() async {
+ await assertNoErrorsInCode('''
+const dynamic a = <int>{5};
+var b = const <int>[...a];
+''');
+ }
+
+ test_const_setInt() async {
+ await assertErrorsInCode('''
+const dynamic a = 5;
+var b = const <int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+ }
+
+ test_const_setList() async {
+ await assertNoErrorsInCode('''
+const dynamic a = <int>[5];
+var b = const <int>{...a};
+''');
+ }
+
+ test_const_setMap() async {
+ await assertErrorsInCode('''
+const dynamic a = <int, int>{1: 2};
+var b = const <int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+ }
+
+ test_const_setNull() async {
+ await assertErrorsInCode('''
+const dynamic a = null;
+var b = const <int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+ }
+
+ test_const_setNull_nullable() async {
+ await assertNoErrorsInCode('''
+const dynamic a = null;
+var b = const <int>{...?a};
+''');
+ }
+
+ test_const_setSet() async {
+ await assertNoErrorsInCode('''
+const dynamic a = <int>{5};
+var b = const <int>{...a};
+''');
+ }
+
+ test_nonConst_listInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 5;
+var b = <int>[...a];
+''');
+ }
+
+ test_nonConst_setInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 5;
+var b = <int>{...a};
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart b/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
new file mode 100644
index 0000000..405a700
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConstSpreadExpectedMapTest);
+ });
+}
+
+@reflectiveTest
+class ConstSpreadExpectedMapTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_const_mapInt() async {
+ await assertErrorsInCode('''
+const dynamic a = 5;
+var b = const <int, int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]);
+ }
+
+ test_const_mapList() async {
+ await assertErrorsInCode('''
+const dynamic a = <int>[5];
+var b = const <int, int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]);
+ }
+
+ test_const_mapMap() async {
+ await assertNoErrorsInCode('''
+const dynamic a = <int, int>{1: 2};
+var b = <int, int>{...a};
+''');
+ }
+
+ test_const_mapNull() async {
+ await assertErrorsInCode('''
+const dynamic a = null;
+var b = const <int, int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]);
+ }
+
+ test_const_mapNull_nullable() async {
+ await assertNoErrorsInCode('''
+const dynamic a = null;
+var b = <int, int>{...?a};
+''');
+ }
+
+ test_const_mapSet() async {
+ await assertErrorsInCode('''
+const dynamic a = <int>{5};
+var b = const <int, int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]);
+ }
+
+ test_nonConst_mapInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 5;
+var b = <int, int>{...a};
+''');
+ }
+
+ test_nonConst_mapMap() async {
+ await assertNoErrorsInCode('''
+const dynamic a = {1: 2};
+var b = <int, int>{...a};
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/equal_keys_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/equal_keys_in_map_test.dart
index 2469819..661e118 100644
--- a/pkg/analyzer/test/src/diagnostics/equal_keys_in_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/equal_keys_in_map_test.dart
@@ -24,44 +24,43 @@
EnableString.spread_collections,
];
- test_ifElement_elseBranch_evaluated_addsDuplicate() async {
+ test_ifElement_false_elseEvaluated() async {
await assertErrorsInCode('''
-void main() {
- const notTrue = false;
- const {1: null, if (notTrue) 2: null else 1: null};
-}
+const c = {1: null, if (1 < 0) 2: null else 1: null};
''', [StaticWarningCode.EQUAL_KEYS_IN_MAP]);
}
- test_ifElement_evaluated_addsDuplicate() async {
+ test_ifElement_false_onlyElseEvaluated() async {
+ assertNoErrorsInCode('''
+const c = {if (0 < 1) 1 : 1 else 1 : 2};
+''');
+ }
+
+ test_ifElement_false_thenNotEvaluated() async {
+ assertNoErrorsInCode('''
+const c = {2 : 1, if (1 < 0) 2 : 2};
+''');
+ }
+
+ test_ifElement_true_elseNotEvaluated() async {
+ assertNoErrorsInCode('''
+const c = {1 : 1, if (0 < 1) 2 : 2 else 1 : 2};
+''');
+ }
+
+ test_ifElement_true_onlyThenEvaluated() async {
+ assertNoErrorsInCode('''
+const c = {if (0 < 1) 1 : 1 else 1 : 2};
+''');
+ }
+
+ test_ifElement_true_thenEvaluated() async {
await assertErrorsInCode('''
-void main() {
- const {1: null, if (true) 1: null};
-}
+const c = {1: null, if (0 < 1) 1: null};
''', [StaticWarningCode.EQUAL_KEYS_IN_MAP]);
}
@failingTest
- test_ifElement_notEvaluated_doesntAddDuplicate() async {
- await assertNoErrorsInCode('''
-void main() {
- const notTrue = false;
- const {1: null, if (notTrue) 1: null};
-}
-''');
- }
-
- @failingTest
- test_ifElement_withElse_evaluated_doesntAddDuplicate() async {
- await assertNoErrorsInCode('''
-void main() {
- const isTrue = true;
- const {if (isTrue) 1: null : 1 :null};
-}
-''');
- }
-
- @failingTest
test_nonConst_noDuplicateReported() async {
await assertNoErrorsInCode('''
void main() {
@@ -70,7 +69,6 @@
''');
}
- @failingTest
test_spreadElement_addsDuplicate() async {
await assertErrorsInCode('''
void main() {
diff --git a/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart
new file mode 100644
index 0000000..7f81b3c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, 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/dart/analysis/experiments.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ExpressionInMapTest);
+ defineReflectiveTests(ExpressionInMapWithUiAsCodeTest);
+ });
+}
+
+@reflectiveTest
+class ExpressionInMapTest extends DriverResolutionTest {
+ test_map() async {
+ await assertErrorsInCode('''
+var m = <String, int>{'a', 'b' : 2};
+''', [ParserErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_IDENTIFIER]);
+ }
+
+ test_map_const() async {
+ await assertErrorsInCode('''
+var m = <String, int>{'a', 'b' : 2};
+''', [ParserErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_IDENTIFIER]);
+ }
+}
+
+@reflectiveTest
+class ExpressionInMapWithUiAsCodeTest extends ExpressionInMapTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_map() async {
+ await assertErrorsInCode('''
+var m = <String, int>{'a', 'b' : 2};
+''', [CompileTimeErrorCode.EXPRESSION_IN_MAP]);
+ }
+
+ test_map_const() async {
+ await assertErrorsInCode('''
+var m = <String, int>{'a', 'b' : 2};
+''', [CompileTimeErrorCode.EXPRESSION_IN_MAP]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart
index f1c94b4..7ea31a2 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart
@@ -29,7 +29,10 @@
class B extends A {
const B();
}
-''', [StrongModeCode.INVALID_CAST_NEW_EXPR]);
+''', [
+ StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
+ StrongModeCode.INVALID_CAST_NEW_EXPR,
+ ]);
}
test_listLiteral_nonConst() async {
@@ -53,7 +56,10 @@
class B extends A {
const B();
}
-''', [StrongModeCode.INVALID_CAST_NEW_EXPR]);
+''', [
+ StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
+ StrongModeCode.INVALID_CAST_NEW_EXPR,
+ ]);
}
test_setLiteral_nonConst() async {
diff --git a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
new file mode 100644
index 0000000..c92a8a0
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ListElementTypeNotAssignableTest);
+ defineReflectiveTests(ListElementTypeNotAssignableWithUIAsCodeTest);
+ });
+}
+
+@reflectiveTest
+class ListElementTypeNotAssignableTest extends DriverResolutionTest {
+ test_explicitTypeArgs_const() async {
+ await assertErrorsInCode('''
+var v = const <String>[42];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_explicitTypeArgs_const_actualTypeMatch() async {
+ await assertNoErrorsInCode('''
+const dynamic x = null;
+var v = const <String>[x];
+''');
+ }
+
+ test_explicitTypeArgs_const_actualTypeMismatch() async {
+ await assertErrorsInCode('''
+const dynamic x = 42;
+var v = const <String>[x];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_explicitTypeArgs_notConst() async {
+ await assertErrorsInCode('''
+var v = <String> [42];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+}
+
+@reflectiveTest
+class ListElementTypeNotAssignableWithUIAsCodeTest
+ extends ListElementTypeNotAssignableTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_const_ifElement_thenElseFalse_intInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <int>[if (1 < 0) a else b];
+''');
+ }
+
+ test_const_ifElement_thenElseFalse_intString() async {
+ await assertErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <int>[if (1 < 0) a else b];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenFalse_intString() async {
+ await assertErrorsInCode('''
+var v = const <int>[if (1 < 0) 'a'];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenFalse_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int>[if (1 < 0) a];
+''');
+ }
+
+ test_const_ifElement_thenTrue_intInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int>[if (true) a];
+''');
+ }
+
+ test_const_ifElement_thenTrue_intString() async {
+ await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int>[if (true) a];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_spread_intInt() async {
+ await assertNoErrorsInCode('''
+var v = const <int>[...[0, 1]];
+''');
+ }
+
+ test_nonConst_ifElement_thenElseFalse_intDynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+const dynamic b = 'b';
+var v = <int>[if (1 < 0) a else b];
+''');
+ }
+
+ test_nonConst_ifElement_thenElseFalse_intInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = <int>[if (1 < 0) a else b];
+''');
+ }
+
+ test_nonConst_ifElement_thenFalse_intString() async {
+ await assertErrorsInCode('''
+var v = <int>[if (1 < 0) 'a'];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_ifElement_thenTrue_intDynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <int>[if (true) a];
+''');
+ }
+
+ test_nonConst_ifElement_thenTrue_intInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <int>[if (true) a];
+''');
+ }
+
+ test_nonConst_spread_intInt() async {
+ await assertNoErrorsInCode('''
+var v = <int>[...[0, 1]];
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
new file mode 100644
index 0000000..140e53e
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, 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/dart/analysis/experiments.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(MapEntryNotInMapTest);
+ defineReflectiveTests(MapEntryNotInMapWithUiAsCodeTest);
+ });
+}
+
+@reflectiveTest
+class MapEntryNotInMapTest extends DriverResolutionTest {
+ test_set() async {
+ await assertErrorsInCode('''
+var c = <int>{1:2};
+''', [ParserErrorCode.UNEXPECTED_TOKEN]);
+ }
+
+ test_set_const() async {
+ await assertErrorsInCode('''
+var c = const <int>{1:2};
+''', [ParserErrorCode.UNEXPECTED_TOKEN]);
+ }
+}
+
+@reflectiveTest
+class MapEntryNotInMapWithUiAsCodeTest extends MapEntryNotInMapTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_set() async {
+ await assertErrorsInCode('''
+var c = <int>{1:2};
+''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
+ }
+
+ test_set_const() async {
+ await assertErrorsInCode('''
+var c = const <int>{1:2};
+''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
new file mode 100644
index 0000000..2ea6a69
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
@@ -0,0 +1,191 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(MapKeyTypeNotAssignableTest);
+ defineReflectiveTests(MapKeyTypeNotAssignableWithUIAsCodeTest);
+ });
+}
+
+@reflectiveTest
+class MapKeyTypeNotAssignableTest extends DriverResolutionTest {
+ test_const_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, bool>{a : true};
+''');
+ }
+
+ test_const_intString_dynamic() async {
+ await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int, bool>{a : true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_intString_value() async {
+ await assertErrorsInCode('''
+var v = const <int, bool>{'a' : true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <int, bool>{a : true};
+''');
+ }
+
+ test_nonConst_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <int, bool>{a : true};
+''');
+ }
+
+ test_nonConst_intString_value() async {
+ await assertErrorsInCode('''
+var v = <int, bool>{'a' : true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+ }
+}
+
+@reflectiveTest
+class MapKeyTypeNotAssignableWithUIAsCodeTest
+ extends MapKeyTypeNotAssignableTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_const_ifElement_thenElseFalse_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <int, bool>{if (1 < 0) a: true else b: false};
+''');
+ }
+
+ test_const_ifElement_thenElseFalse_intString_dynamic() async {
+ await assertErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <int, bool>{if (1 < 0) a: true else b: false};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenFalse_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int, bool>{if (1 < 0) a: true};
+''');
+ }
+
+ test_const_ifElement_thenFalse_intString_value() async {
+ await assertErrorsInCode('''
+var v = const <int, bool>{if (1 < 0) 'a': true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenTrue_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, bool>{if (true) a: true};
+''');
+ }
+
+ test_const_ifElement_thenTrue_intString_dynamic() async {
+ await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int, bool>{if (true) a: true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenTrue_notConst() async {
+ await assertErrorsInCode('''
+final a = 0;
+var v = const <int, bool>{if (1 < 2) a: true};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+ }
+
+ test_const_spread_intInt() async {
+ await assertNoErrorsInCode('''
+var v = const <int, String>{...{1: 'a'}};
+''');
+ }
+
+ test_const_spread_intString_dynamic() async {
+ await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int, String>{...{a: 'a'}};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_ifElement_thenElseFalse_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = <int, bool>{if (1 < 0) a: true else b: false};
+''');
+ }
+
+ test_nonConst_ifElement_thenElseFalse_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = <int, bool>{if (1 < 0) a: true else b: false};
+''');
+ }
+
+ test_nonConst_ifElement_thenFalse_intString_value() async {
+ await assertErrorsInCode('''
+var v = <int, bool>{if (1 < 0) 'a': true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <int, bool>{if (true) a: true};
+''');
+ }
+
+ test_nonConst_ifElement_thenTrue_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <int, bool>{if (true) a: true};
+''');
+ }
+
+ test_nonConst_spread_intInt() async {
+ await assertNoErrorsInCode('''
+var v = <int, String>{...{1: 'a'}};
+''');
+ }
+
+ test_nonConst_spread_intNum() async {
+ await assertNoErrorsInCode('''
+var v = <int, int>{...<num, num>{1: 1}};
+''');
+ }
+
+ test_nonConst_spread_intString() async {
+ await assertErrorsInCode('''
+var v = <int, String>{...{'a': 'a'}};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_spread_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+dynamic a = 'a';
+var v = <int, String>{...{a: 'a'}};
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
new file mode 100644
index 0000000..3a9bc4a
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
@@ -0,0 +1,191 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(MapValueTypeNotAssignableTest);
+ defineReflectiveTests(MapValueTypeNotAssignableWithUIAsCodeTest);
+ });
+}
+
+@reflectiveTest
+class MapValueTypeNotAssignableTest extends DriverResolutionTest {
+ test_const_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <bool, int>{true: a};
+''');
+ }
+
+ test_const_intString_dynamic() async {
+ await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <bool, int>{true: a};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_intString_value() async {
+ await assertErrorsInCode('''
+var v = const <bool, int>{true: 'a'};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <bool, int>{true: a};
+''');
+ }
+
+ test_nonConst_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <bool, int>{true: a};
+''');
+ }
+
+ test_nonConst_intString_value() async {
+ await assertErrorsInCode('''
+var v = <bool, int>{true: 'a'};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+ }
+}
+
+@reflectiveTest
+class MapValueTypeNotAssignableWithUIAsCodeTest
+ extends MapValueTypeNotAssignableTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_const_ifElement_thenElseFalse_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <bool, int>{if (1 < 0) true: a else false: b};
+''');
+ }
+
+ test_const_ifElement_thenElseFalse_intString_dynamic() async {
+ await assertErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <bool, int>{if (1 < 0) true: a else false: b};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenFalse_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = const <bool, int>{if (1 < 0) true: a};
+''');
+ }
+
+ test_const_ifElement_thenFalse_intString_value() async {
+ await assertErrorsInCode('''
+var v = const <bool, int>{if (1 < 0) true: 'a'};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenTrue_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <bool, int>{if (true) true: a};
+''');
+ }
+
+ test_const_ifElement_thenTrue_intString_dynamic() async {
+ await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <bool, int>{if (true) true: a};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenTrue_notConst() async {
+ await assertErrorsInCode('''
+final a = 0;
+var v = const <bool, int>{if (1 < 2) true: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+ }
+
+ test_const_spread_intInt() async {
+ await assertNoErrorsInCode('''
+var v = const <bool, int>{...{true: 1}};
+''');
+ }
+
+ test_const_spread_intString_dynamic() async {
+ await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <bool, int>{...{true: a}};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_ifElement_thenElseFalse_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = <bool, int>{if (1 < 0) true: a else false: b};
+''');
+ }
+
+ test_nonConst_ifElement_thenElseFalse_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = <bool, int>{if (1 < 0) true: a else false: b};
+''');
+ }
+
+ test_nonConst_ifElement_thenFalse_intString_value() async {
+ await assertErrorsInCode('''
+var v = <bool, int>{if (1 < 0) true: 'a'};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <bool, int>{if (true) true: a};
+''');
+ }
+
+ test_nonConst_ifElement_thenTrue_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <bool, int>{if (true) true: a};
+''');
+ }
+
+ test_nonConst_spread_intInt() async {
+ await assertNoErrorsInCode('''
+var v = <bool, int>{...{true: 1}};
+''');
+ }
+
+ test_nonConst_spread_intNum() async {
+ await assertNoErrorsInCode('''
+var v = <int, int>{...<num, num>{1: 1}};
+''');
+ }
+
+ test_nonConst_spread_intString() async {
+ await assertErrorsInCode('''
+var v = <bool, int>{...{true: 'a'}};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_spread_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <bool, int>{...{true: a}};
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
new file mode 100644
index 0000000..5b03a7c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
@@ -0,0 +1,111 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:analyzer/src/test_utilities/package_mixin.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(MissingReturnTest);
+ });
+}
+
+@reflectiveTest
+class MissingReturnTest extends DriverResolutionTest with PackageMixin {
+ test_async() async {
+ await assertErrorsInCode(r'''
+import 'dart:async';
+Future<int> f() async {}
+''', [HintCode.MISSING_RETURN]);
+ }
+
+ test_factory() async {
+ await assertErrorsInCode(r'''
+class A {
+ factory A() {}
+}
+''', [HintCode.MISSING_RETURN]);
+ }
+
+ test_function() async {
+ await assertErrorsInCode(r'''
+int f() {}
+''', [HintCode.MISSING_RETURN]);
+ }
+
+ test_method() async {
+ await assertErrorsInCode(r'''
+class A {
+ int m() {}
+}''', [HintCode.MISSING_RETURN]);
+ }
+
+ test_method_inferred() async {
+ await assertErrorsInCode(r'''
+abstract class A {
+ int m();
+}
+class B extends A {
+ m() {}
+}
+''', [HintCode.MISSING_RETURN]);
+ }
+
+ test_emptyFunctionBody() async {
+ await assertNoErrorsInCode(r'''
+abstract class A {
+ int m();
+}''');
+ }
+
+ test_expressionFunctionBody() async {
+ await assertNoErrorsInCode(r'''
+int f() => 0;
+''');
+ }
+
+ test_async_futureVoid() async {
+ await assertNoErrorsInCode(r'''
+import 'dart:async';
+Future<void> f() async {}
+''');
+ }
+
+ test_async_futureOrVoid() async {
+ await assertNoErrorsInCode(r'''
+import 'dart:async';
+FutureOr<void> f(Future f) async {}
+''');
+ }
+
+ test_noReturnType() async {
+ await assertNoErrorsInCode(r'''
+f() {}
+''');
+ }
+
+ test_voidReturnType() async {
+ await assertNoErrorsInCode(r'''
+void f() {}
+''');
+ }
+
+ test_alwaysThrows() async {
+ addMetaPackage();
+ await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@alwaysThrows
+void a() {
+ throw 'msg';
+}
+
+int f() {
+ a();
+}''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
new file mode 100644
index 0000000..4865ced
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2019, 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/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+// defineReflectiveTests(NonBoolConditionTest);
+ defineReflectiveTests(NonBoolConditionWithUIAsCodeTest);
+ });
+}
+
+//@reflectiveTest
+class NonBoolConditionTest extends DriverResolutionTest {}
+
+@reflectiveTest
+class NonBoolConditionWithUIAsCodeTest extends NonBoolConditionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_ifElement() async {
+ assertErrorsInCode('''
+const c = [if (3) 1];
+''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
new file mode 100644
index 0000000..f90a4c4
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2019, 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/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(NonConstantListElementTest);
+ defineReflectiveTests(NonConstantListElementWithUiAsCodeTest);
+ });
+}
+
+@reflectiveTest
+class NonConstantListElementTest extends DriverResolutionTest {
+ test_const_topVar() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+ }
+
+ test_nonConst_topVar() async {
+ await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = [a];
+''');
+ }
+}
+
+@reflectiveTest
+class NonConstantListElementWithUiAsCodeTest
+ extends NonConstantListElementTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_const_ifElement_thenElseFalse_finalElse() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 < 0) 0 else a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+ }
+
+ test_const_ifElement_thenElseFalse_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 < 0) a else 0];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+ }
+
+ test_const_ifElement_thenElseTrue_finalElse() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 > 0) 0 else a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+ }
+
+ test_const_ifElement_thenElseTrue_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 > 0) a else 0];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+ }
+
+ test_const_ifElement_thenFalse_constThen() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const [if (1 < 0) a];
+''');
+ }
+
+ test_const_ifElement_thenFalse_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 < 0) a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+ }
+
+ test_const_ifElement_thenTrue_constThen() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const [if (1 > 0) a];
+''');
+ }
+
+ test_const_ifElement_thenTrue_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 > 0) a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
index 459422f..ddff55a 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
@@ -12,6 +12,10 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(NonConstantMapElementWithUiAsCodeTest);
+ defineReflectiveTests(NonConstantMapKeyTest);
+ defineReflectiveTests(NonConstantMapKeyWithUiAsCodeTest);
+ defineReflectiveTests(NonConstantMapValueTest);
+ defineReflectiveTests(NonConstantMapValueWithUiAsCodeTest);
});
}
@@ -74,7 +78,6 @@
''', [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
}
- @failingTest
test_ifElementWithElse_mayBeConst() async {
await assertNoErrorsInCode('''
void main() {
@@ -101,3 +104,169 @@
''', [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
}
}
+
+@reflectiveTest
+class NonConstantMapKeyTest extends DriverResolutionTest {
+ test_const_topVar() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+ }
+
+ test_nonConst_topVar() async {
+ await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = <int, int>{a: 0};
+''');
+ }
+}
+
+@reflectiveTest
+class NonConstantMapKeyWithUiAsCodeTest extends NonConstantMapKeyTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_const_ifElement_thenElseFalse_finalElse() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: 0 else a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+ }
+
+ test_const_ifElement_thenElseFalse_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) a: 0 else 0: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+ }
+
+ test_const_ifElement_thenElseTrue_finalElse() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: 0 else a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+ }
+
+ test_const_ifElement_thenElseTrue_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) a: 0 else 0: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+ }
+
+ test_const_ifElement_thenFalse_constThen() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, int>{if (1 < 0) a: 0};
+''');
+ }
+
+ test_const_ifElement_thenFalse_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+ }
+
+ test_const_ifElement_thenTrue_constThen() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, int>{if (1 > 0) a: 0};
+''');
+ }
+
+ test_const_ifElement_thenTrue_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+ }
+}
+
+@reflectiveTest
+class NonConstantMapValueTest extends DriverResolutionTest {
+ test_const_topVar() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+ }
+
+ test_nonConst_topVar() async {
+ await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = <int, int>{0: a};
+''');
+ }
+}
+
+@reflectiveTest
+class NonConstantMapValueWithUiAsCodeTest extends NonConstantMapValueTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_const_ifElement_thenElseFalse_finalElse() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: 0 else 0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+ }
+
+ test_const_ifElement_thenElseFalse_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: a else 0: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+ }
+
+ test_const_ifElement_thenElseTrue_finalElse() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: 0 else 0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+ }
+
+ test_const_ifElement_thenElseTrue_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: a else 0: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+ }
+
+ test_const_ifElement_thenFalse_constThen() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: a};
+''');
+ }
+
+ test_const_ifElement_thenFalse_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+ }
+
+ test_const_ifElement_thenTrue_constThen() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: a};
+''');
+ }
+
+ test_const_ifElement_thenTrue_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
new file mode 100644
index 0000000..1d8c475
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2019, 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/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(NonConstantSetElementTest);
+ defineReflectiveTests(NonConstantSetElementWithUiAsCodeTest);
+ });
+}
+
+@reflectiveTest
+class NonConstantSetElementTest extends DriverResolutionTest {
+ test_const_topVar() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+ }
+
+ test_nonConst_topVar() async {
+ await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = <int>{a};
+''');
+ }
+}
+
+@reflectiveTest
+class NonConstantSetElementWithUiAsCodeTest extends NonConstantSetElementTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_const_ifElement_thenElseFalse_finalElse() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 < 0) 0 else a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+ }
+
+ test_const_ifElement_thenElseFalse_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 < 0) a else 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+ }
+
+ test_const_ifElement_thenElseTrue_finalElse() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 > 0) 0 else a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+ }
+
+ test_const_ifElement_thenElseTrue_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 > 0) a else 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+ }
+
+ test_const_ifElement_thenFalse_constThen() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int>{if (1 < 0) a};
+''');
+ }
+
+ test_const_ifElement_thenFalse_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 < 0) a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+ }
+
+ test_const_ifElement_thenTrue_constThen() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int>{if (1 > 0) a};
+''');
+ }
+
+ test_const_ifElement_thenTrue_finalThen() async {
+ await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 > 0) a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
new file mode 100644
index 0000000..f326006
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2019, 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/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(NotIterableSpreadTest);
+ });
+}
+
+@reflectiveTest
+class NotIterableSpreadTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_iterable_list() async {
+ await assertNoErrorsInCode('''
+var a = [0];
+var v = [...a];
+''');
+ }
+
+ test_iterable_null() async {
+ await assertNoErrorsInCode('''
+var v = [...?null];
+''');
+ }
+
+ test_notIterable_direct() async {
+ await assertErrorsInCode('''
+var a = 0;
+var v = [...a];
+''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+ }
+
+ test_notIterable_forElement() async {
+ await assertErrorsInCode('''
+var a = 0;
+var v = [for (var i in []) ...a];
+''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+ }
+
+ test_notIterable_ifElement_else() async {
+ await assertErrorsInCode('''
+var a = 0;
+var v = [if (1 > 0) ...[] else ...a];
+''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+ }
+
+ test_notIterable_ifElement_then() async {
+ await assertErrorsInCode('''
+var a = 0;
+var v = [if (1 > 0) ...a];
+''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
new file mode 100644
index 0000000..a9bf651
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2019, 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/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(NotMapSpreadTest);
+ });
+}
+
+@reflectiveTest
+class NotMapSpreadTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [
+ EnableString.control_flow_collections,
+ EnableString.spread_collections,
+ ];
+
+ test_map() async {
+ await assertNoErrorsInCode('''
+var a = {0: 0};
+var v = <int, int>{...a};
+''');
+ }
+
+ test_map_null() async {
+ await assertNoErrorsInCode('''
+var v = <int, int>{...?null};
+''');
+ }
+
+ test_notMap_direct() async {
+ await assertErrorsInCode('''
+var a = 0;
+var v = <int, int>{...a};
+''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+ }
+
+ test_notMap_forElement() async {
+ await assertErrorsInCode('''
+var a = 0;
+var v = <int, int>{for (var i in []) ...a};
+''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+ }
+
+ test_notMap_ifElement_else() async {
+ await assertErrorsInCode('''
+var a = 0;
+var v = <int, int>{if (1 > 0) ...<int, int>{} else ...a};
+''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+ }
+
+ test_notMap_ifElement_then() async {
+ await assertErrorsInCode('''
+var a = 0;
+var v = <int, int>{if (1 > 0) ...a};
+''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
new file mode 100644
index 0000000..10364de
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SetElementTypeNotAssignableTest);
+ defineReflectiveTests(SetElementTypeNotAssignableWithUIAsCodeTest);
+ });
+}
+
+@reflectiveTest
+class SetElementTypeNotAssignableTest extends DriverResolutionTest {
+ test_explicitTypeArgs_const() async {
+ await assertErrorsInCode('''
+var v = const <String>{42};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_explicitTypeArgs_const_actualTypeMatch() async {
+ await assertNoErrorsInCode('''
+const dynamic x = null;
+var v = const <String>{x};
+''');
+ }
+
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/21119')
+ test_explicitTypeArgs_const_actualTypeMismatch() async {
+ await assertErrorsInCode('''
+const dynamic x = 42;
+var v = const <String>{x};
+''', [CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_explicitTypeArgs_notConst() async {
+ await assertErrorsInCode('''
+var v = <String>{42};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+}
+
+@reflectiveTest
+class SetElementTypeNotAssignableWithUIAsCodeTest
+ extends SetElementTypeNotAssignableTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+ test_const_ifElement_thenElseFalse_intInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <int>{if (1 < 0) a else b};
+''');
+ }
+
+ test_const_ifElement_thenElseFalse_intString() async {
+ await assertErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <int>{if (1 < 0) a else b};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenFalse_intString() async {
+ await assertErrorsInCode('''
+var v = const <int>{if (1 < 0) 'a'};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_ifElement_thenFalse_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int>{if (1 < 0) a};
+''');
+ }
+
+ test_const_ifElement_thenTrue_intInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int>{if (true) a};
+''');
+ }
+
+ test_const_ifElement_thenTrue_intString() async {
+ await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int>{if (true) a};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_const_spread_intInt() async {
+ await assertNoErrorsInCode('''
+var v = const <int>{...[0, 1]};
+''');
+ }
+
+ test_nonConst_ifElement_thenElseFalse_intDynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+const dynamic b = 'b';
+var v = <int>{if (1 < 0) a else b};
+''');
+ }
+
+ test_nonConst_ifElement_thenElseFalse_intInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = <int>{if (1 < 0) a else b};
+''');
+ }
+
+ test_nonConst_ifElement_thenFalse_intString() async {
+ await assertErrorsInCode('''
+var v = <int>[if (1 < 0) 'a'];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+ }
+
+ test_nonConst_ifElement_thenTrue_intDynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <int>{if (true) a};
+''');
+ }
+
+ test_nonConst_ifElement_thenTrue_intInt() async {
+ await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <int>{if (true) a};
+''');
+ }
+
+ test_nonConst_spread_intInt() async {
+ await assertNoErrorsInCode('''
+var v = <int>{...[0, 1]};
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index fed2324..f1f3b5f 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -4,14 +4,26 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'ambiguous_set_or_map_literal_test.dart' as ambiguous_set_or_map_literal;
import 'argument_type_not_assignable_test.dart' as argument_type_not_assignable;
import 'can_be_null_after_null_aware_test.dart' as can_be_null_after_null_aware;
import 'const_constructor_param_type_mismatch_test.dart'
as const_constructor_param_type_mismatch;
+import 'const_constructor_with_mixin_with_field_test.dart'
+ as const_constructor_with_mixin_with_field;
+import 'const_eval_throws_exception_test.dart' as const_eval_throws_exception;
+import 'const_map_key_expression_type_implements_equals_test.dart'
+ as const_map_key_expression_type_implements_equals;
+import 'const_set_element_type_implements_equals_test.dart'
+ as const_set_element_type_implements_equals;
+import 'const_spread_expected_list_or_set_test.dart'
+ as const_spread_expected_list_or_set;
+import 'const_spread_expected_map_test.dart' as const_spread_expected_map;
import 'dead_code_test.dart' as dead_code;
import 'deprecated_member_use_test.dart' as deprecated_member_use;
import 'division_optimization_test.dart' as division_optimization;
import 'equal_keys_in_map_test.dart' as equal_keys_in_map;
+import 'expression_in_map_test.dart' as expression_in_map;
import 'invalid_assignment_test.dart' as invalid_assignment;
import 'invalid_cast_new_expr_test.dart' as invalid_cast_new_expr;
import 'invalid_immutable_annotation_test.dart' as invalid_immutable_annotation;
@@ -22,15 +34,33 @@
as invalid_override_different_default_values_positional;
import 'invalid_required_param_test.dart' as invalid_required_param;
import 'invalid_sealed_annotation_test.dart' as invalid_sealed_annotation;
+import 'invalid_visibility_annotation_test.dart'
+ as invalid_visibility_annotation;
+import 'list_element_type_not_assignable_test.dart'
+ as list_element_type_not_assignable;
+import 'map_entry_not_in_map_test.dart' as map_entry_not_in_map;
+import 'map_key_type_not_assignable_test.dart' as map_key_type_not_assignable;
+import 'map_value_type_not_assignable_test.dart'
+ as map_value_type_not_assignable;
+import 'missing_return_test.dart' as missing_return;
import 'mixin_on_sealed_class_test.dart' as mixin_on_sealed_class;
import 'must_be_immutable_test.dart' as must_be_immutable;
import 'must_call_super_test.dart' as must_call_super;
-import 'subtype_of_sealed_class_test.dart' as subtype_of_sealed_class;
+import 'non_bool_condition_test.dart' as non_bool_condition;
+import 'non_constant_list_element_test.dart' as non_constant_list_element;
import 'non_constant_map_element_test.dart' as non_constant_map_element;
+import 'non_constant_set_element_test.dart' as non_constant_set_element;
+import 'not_iterable_spread_test.dart' as not_iterable_spread;
+import 'not_map_spread_test.dart' as not_map_spread;
+import 'set_element_type_not_assignable_test.dart'
+ as set_element_type_not_assignable;
+import 'subtype_of_sealed_class_test.dart' as subtype_of_sealed_class;
import 'top_level_instance_getter_test.dart' as top_level_instance_getter;
import 'top_level_instance_method_test.dart' as top_level_instance_method;
import 'type_check_is_not_null_test.dart' as type_check_is_not_null;
import 'type_check_is_null_test.dart' as type_check_is_null;
+import 'unchecked_use_of_nullable_value_test.dart'
+ as unchecked_use_of_nullable_value;
import 'undefined_getter_test.dart' as undefined_getter;
import 'undefined_hidden_name_test.dart' as undefined_hidden_name;
import 'undefined_operator_test.dart' as undefined_operator;
@@ -55,13 +85,21 @@
main() {
defineReflectiveSuite(() {
+ ambiguous_set_or_map_literal.main();
argument_type_not_assignable.main();
can_be_null_after_null_aware.main();
const_constructor_param_type_mismatch.main();
+ const_constructor_with_mixin_with_field.main();
+ const_eval_throws_exception.main();
+ const_map_key_expression_type_implements_equals.main();
+ const_set_element_type_implements_equals.main();
+ const_spread_expected_list_or_set.main();
+ const_spread_expected_map.main();
dead_code.main();
deprecated_member_use.main();
division_optimization.main();
equal_keys_in_map.main();
+ expression_in_map.main();
invalid_assignment.main();
invalid_cast_new_expr.main();
invalid_immutable_annotation.main();
@@ -70,15 +108,28 @@
invalid_override_different_default_values_positional.main();
invalid_required_param.main();
invalid_sealed_annotation.main();
+ invalid_visibility_annotation.main();
+ list_element_type_not_assignable.main();
+ map_entry_not_in_map.main();
+ map_key_type_not_assignable.main();
+ map_value_type_not_assignable.main();
+ missing_return.main();
mixin_on_sealed_class.main();
must_be_immutable.main();
must_call_super.main();
- subtype_of_sealed_class.main();
+ non_bool_condition.main();
+ non_constant_list_element.main();
non_constant_map_element.main();
+ non_constant_set_element.main();
+ not_iterable_spread.main();
+ not_map_spread.main();
+ set_element_type_not_assignable.main();
+ subtype_of_sealed_class.main();
top_level_instance_getter.main();
top_level_instance_method.main();
type_check_is_not_null.main();
type_check_is_null.main();
+ unchecked_use_of_nullable_value.main();
undefined_getter.main();
undefined_hidden_name.main();
undefined_operator.main();
diff --git a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
index dbb41eb..5ac8dc9 100644
--- a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
@@ -37,6 +37,22 @@
f() => [a, b, c];
''');
}
+
+ void test_missingComma_afterIf() {
+ testRecovery('''
+f() => [a, if (x) b c];
+''', [ParserErrorCode.EXPECTED_ELSE_OR_COMMA], '''
+f() => [a, if (x) b, c];
+''', enableControlFlowCollections: true);
+ }
+
+ void test_missingComma_afterIfElse() {
+ testRecovery('''
+f() => [a, if (x) b else y c];
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+f() => [a, if (x) b else y, c];
+''', enableControlFlowCollections: true);
+ }
}
/**
@@ -72,6 +88,22 @@
''');
}
+ void test_missingComma_afterIf() {
+ testRecovery('''
+f() => {a: b, if (x) c: d e: f};
+''', [ParserErrorCode.EXPECTED_ELSE_OR_COMMA], '''
+f() => {a: b, if (x) c: d, e: f};
+''', enableControlFlowCollections: true);
+ }
+
+ void test_missingComma_afterIfElse() {
+ testRecovery('''
+f() => {a: b, if (x) c: d else y: z e: f};
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+f() => {a: b, if (x) c: d else y: z, e: f};
+''', enableControlFlowCollections: true);
+ }
+
void test_missingKey() {
testRecovery('''
f() => {: b};
@@ -259,8 +291,7 @@
testUserDefinableOperatorWithSuper('^');
}
- @failingTest
- void test_initializerList_missingComma() {
+ void test_initializerList_missingComma_assert() {
// https://github.com/dart-lang/sdk/issues/33241
testRecovery('''
class Test {
@@ -277,6 +308,40 @@
''');
}
+ void test_initializerList_missingComma_field() {
+ // https://github.com/dart-lang/sdk/issues/33241
+ testRecovery('''
+class Test {
+ Test()
+ : assert(true)
+ x = 2;
+}
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+class Test {
+ Test()
+ : assert(true),
+ x = 2;
+}
+''');
+ }
+
+ void test_initializerList_missingComma_thisField() {
+ // https://github.com/dart-lang/sdk/issues/33241
+ testRecovery('''
+class Test {
+ Test()
+ : assert(true)
+ this.x = 2;
+}
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+class Test {
+ Test()
+ : assert(true),
+ this.x = 2;
+}
+''');
+ }
+
void test_isExpression_missingLeft() {
testRecovery('''
f() {
diff --git a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
index f42bcdd..d0cdb3b 100644
--- a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
@@ -19,13 +19,15 @@
void testRecovery(
String invalidCode, List<ErrorCode> errorCodes, String validCode,
{CompilationUnit adjustValidUnitBeforeComparison(CompilationUnit unit),
+ bool enableControlFlowCollections,
List<ErrorCode> expectedErrorsInValidCode}) {
CompilationUnit validUnit;
// Assert that the valid code is indeed valid.
try {
- validUnit =
- parseCompilationUnit(validCode, codes: expectedErrorsInValidCode);
+ validUnit = parseCompilationUnit(validCode,
+ codes: expectedErrorsInValidCode,
+ enableControlFlowCollections: enableControlFlowCollections);
validateTokenStream(validUnit.beginToken);
} catch (e) {
// print('');
@@ -39,7 +41,8 @@
// Compare the structures before asserting valid errors.
GatheringErrorListener listener =
new GatheringErrorListener(checkRanges: true);
- CompilationUnit invalidUnit = parseCompilationUnit2(invalidCode, listener);
+ CompilationUnit invalidUnit = parseCompilationUnit2(invalidCode, listener,
+ enableControlFlowCollections: enableControlFlowCollections);
validateTokenStream(invalidUnit.beginToken);
if (adjustValidUnitBeforeComparison != null) {
validUnit = adjustValidUnitBeforeComparison(validUnit);
diff --git a/pkg/analyzer/test/src/fasta/test_all.dart b/pkg/analyzer/test/src/fasta/test_all.dart
index 91b1a9c..adb1d99 100644
--- a/pkg/analyzer/test/src/fasta/test_all.dart
+++ b/pkg/analyzer/test/src/fasta/test_all.dart
@@ -7,11 +7,13 @@
import 'ast_builder_test.dart' as ast_builder;
import 'message_coverage_test.dart' as message_coverage;
import 'recovery/test_all.dart' as recovery;
+import 'token_utils_test.dart' as token_utils;
main() {
defineReflectiveSuite(() {
ast_builder.main();
message_coverage.main();
recovery.main();
+ token_utils.main();
}, name: 'fasta');
}
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index 2fe5b77..e82719f 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -348,6 +348,19 @@
]);
}
+ test_added_part_withoutLibrary() async {
+ var b = convertPath('/home/test/lib/b.dart');
+
+ newFile(b, content: r'''
+part of 'a.dart';
+''');
+ tracker.changeFile(b);
+ await _doAllTrackerWork();
+
+ _assertHasNoLibrary('package:test/a.dart');
+ _assertHasNoLibrary('package:test/b.dart');
+ }
+
test_chooseContext_inAnalysisRoot() async {
var homePath = convertPath('/home');
var testPath = convertPath('/home/test');
@@ -536,6 +549,30 @@
_assertHasLibrary('package:test/b.dart');
}
+ test_deleted_library_ofPart() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+
+ newFile(a, content: r'''
+part 'b.dart';
+''');
+ newFile(b, content: r'''
+part of 'a.dart';
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart');
+ _assertHasNoLibrary('package:test/b.dart');
+
+ deleteFile(a);
+ tracker.changeFile(a);
+ await _doAllTrackerWork();
+
+ _assertHasNoLibrary('package:test/a.dart');
+ _assertHasNoLibrary('package:test/b.dart');
+ }
+
test_deleted_part() async {
var a = convertPath('/home/test/lib/a.dart');
var b = convertPath('/home/test/lib/b.dart');
@@ -575,6 +612,19 @@
]);
}
+ test_deleted_part_withoutLibrary() async {
+ var b = convertPath('/home/test/lib/b.dart');
+
+ newFile(b, content: r'''
+part of 'a.dart';
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasNoLibrary('package:test/a.dart');
+ _assertHasNoLibrary('package:test/b.dart');
+ }
+
test_updated_exported() async {
var a = convertPath('/home/test/lib/a.dart');
var b = convertPath('/home/test/lib/b.dart');
@@ -713,6 +763,30 @@
_ExpectedDeclaration.class_('C'),
]);
}
+
+ test_updated_part_withoutLibrary() async {
+ var b = convertPath('/home/test/lib/b.dart');
+
+ newFile(b, content: r'''
+part of 'a.dart';
+class B {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasNoLibrary('package:test/a.dart');
+ _assertHasNoLibrary('package:test/b.dart');
+
+ newFile(b, content: r'''
+part of 'a.dart';
+class B2 {}
+''');
+ tracker.changeFile(b);
+
+ await _doAllTrackerWork();
+ _assertHasNoLibrary('package:test/a.dart');
+ _assertHasNoLibrary('package:test/b.dart');
+ }
}
@reflectiveTest
diff --git a/pkg/analyzer/test/src/services/test_all.dart b/pkg/analyzer/test/src/services/test_all.dart
new file mode 100644
index 0000000..95e0ef4
--- /dev/null
+++ b/pkg/analyzer/test/src/services/test_all.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'available_declarations_test.dart' as available_declarations;
+
+main() {
+ defineReflectiveSuite(() {
+ available_declarations.main();
+ }, name: 'services');
+}
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 63c0599..b3a61b2 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -57,13 +57,15 @@
bool withConstElements: true,
bool withOffsets: false,
bool withSyntheticAccessors: false,
- bool withSyntheticFields: false}) {
+ bool withSyntheticFields: false,
+ bool withTypes: false}) {
var writer = new _ElementWriter(
withCodeRanges: withCodeRanges,
withConstElements: withConstElements,
withOffsets: withOffsets,
withSyntheticAccessors: withSyntheticAccessors,
- withSyntheticFields: withSyntheticFields);
+ withSyntheticFields: withSyntheticFields,
+ withTypes: withTypes);
writer.writeLibraryElement(library);
String actualText = writer.buffer.toString();
@@ -129,6 +131,7 @@
final bool withConstElements;
final bool withSyntheticAccessors;
final bool withSyntheticFields;
+ final bool withTypes;
final StringBuffer buffer = new StringBuffer();
_ElementWriter(
@@ -136,7 +139,8 @@
this.withConstElements: true,
this.withOffsets: false,
this.withSyntheticAccessors: false,
- this.withSyntheticFields: false});
+ this.withSyntheticFields: false,
+ this.withTypes: false});
bool isDynamicType(DartType type) => type is DynamicTypeImpl;
@@ -272,7 +276,7 @@
if (e is ConstructorElementImpl) {
if (e.constantInitializers != null) {
- writeList(' : ', '', e.constantInitializers, ', ', writeExpression);
+ writeList(' : ', '', e.constantInitializers, ', ', writeNode);
}
}
@@ -303,190 +307,6 @@
buffer.writeln(';');
}
- void writeExpression(AstNode e, [Expression enclosing]) {
- bool needsParenthesis = e is Expression &&
- enclosing != null &&
- e.precedence2 < enclosing.precedence2;
-
- if (needsParenthesis) {
- buffer.write('(');
- }
-
- if (e == null) {
- buffer.write('<null>');
- } else if (e is SimpleIdentifier && e.name == '#invalidConst') {
- buffer.write('#invalidConst');
- } else if (e is Annotation) {
- buffer.write('@');
- writeExpression(e.name);
- if (e.constructorName != null) {
- buffer.write('.');
- writeExpression(e.constructorName);
- }
- if (e.arguments != null) {
- writeList('(', ')', e.arguments.arguments, ', ', writeExpression,
- includeEmpty: true);
- }
- } else if (e is AssertInitializer) {
- buffer.write('assert(');
- writeExpression(e.condition);
- if (e.message != null) {
- buffer.write(', ');
- writeExpression(e.message);
- }
- buffer.write(')');
- } else if (e is BinaryExpression) {
- writeExpression(e.leftOperand, e);
- buffer.write(' ');
- buffer.write(e.operator.lexeme);
- buffer.write(' ');
- writeExpression(e.rightOperand, e);
- } else if (e is BooleanLiteral) {
- buffer.write(e.value);
- } else if (e is ConditionalExpression) {
- writeExpression(e.condition);
- buffer.write(' ? ');
- writeExpression(e.thenExpression);
- buffer.write(' : ');
- writeExpression(e.elseExpression);
- } else if (e is ConstructorFieldInitializer) {
- writeExpression(e.fieldName);
- buffer.write(' = ');
- writeExpression(e.expression);
- } else if (e is ConstructorName) {
- writeExpression(e.type);
- if (e.name != null) {
- buffer.write('.');
- writeExpression(e.name);
- }
- } else if (e is DoubleLiteral) {
- buffer.write(e.value);
- } else if (e is InstanceCreationExpression) {
- if (e.keyword != null) {
- buffer.write(e.keyword.lexeme);
- buffer.write(' ');
- }
- writeExpression(e.constructorName);
- writeList('(', ')', e.argumentList.arguments, ', ', writeExpression,
- includeEmpty: true);
- } else if (e is IntegerLiteral) {
- buffer.write(e.value);
- } else if (e is InterpolationExpression) {
- buffer.write(r'${');
- writeExpression(e.expression);
- buffer.write(r'}');
- } else if (e is InterpolationString) {
- buffer.write(e.value.replaceAll("'", r"\'"));
- } else if (e is ListLiteral) {
- if (e.constKeyword != null) {
- buffer.write('const ');
- }
- if (e.typeArguments != null) {
- writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression);
- }
- writeList('[', ']', e.elements2, ', ', writeExpression,
- includeEmpty: true);
- } else if (e is Label) {
- writeExpression(e.label);
- buffer.write(': ');
- } else if (e is SetOrMapLiteral) {
- if (e.constKeyword != null) {
- buffer.write('const ');
- }
- if (e.typeArguments != null) {
- writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression);
- }
- writeList('{', '}', e.elements2, ', ', writeExpression,
- includeEmpty: true);
- } else if (e is MapLiteralEntry) {
- writeExpression(e.key);
- buffer.write(': ');
- writeExpression(e.value);
- } else if (e is MethodInvocation) {
- if (e.target != null) {
- writeExpression(e.target);
- buffer.write(e.operator);
- }
- writeExpression(e.methodName);
- if (e.typeArguments != null) {
- writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression);
- }
- writeList('(', ')', e.argumentList.arguments, ', ', writeExpression,
- includeEmpty: true);
- } else if (e is NamedExpression) {
- writeExpression(e.name);
- buffer.write(e.expression);
- } else if (e is NullLiteral) {
- buffer.write('null');
- } else if (e is PrefixExpression) {
- buffer.write(e.operator.lexeme);
- writeExpression(e.operand, e);
- } else if (e is PrefixedIdentifier) {
- writeExpression(e.prefix);
- buffer.write('.');
- writeExpression(e.identifier);
- } else if (e is PropertyAccess) {
- writeExpression(e.target, e);
- buffer.write('.');
- writeExpression(e.propertyName);
- } else if (e is RedirectingConstructorInvocation) {
- buffer.write('this');
- if (e.constructorName != null) {
- buffer.write('.');
- writeExpression(e.constructorName);
- }
- writeList('(', ')', e.argumentList.arguments, ', ', writeExpression,
- includeEmpty: true);
- } else if (e is SimpleIdentifier) {
- if (withConstElements) {
- buffer.writeln();
- buffer.write(' ' * 4);
- buffer.write(e.name);
- buffer.write('/*');
- buffer.write('location: ');
- buffer.write(_getElementLocationString(e.staticElement));
- buffer.write('*/');
- } else {
- buffer.write(e.name);
- }
- } else if (e is SimpleStringLiteral) {
- buffer.write("'");
- buffer.write(e.value.replaceAll("'", r"\'"));
- buffer.write("'");
- } else if (e is StringInterpolation) {
- buffer.write("'");
- e.elements.forEach(writeExpression);
- buffer.write("'");
- } else if (e is SuperConstructorInvocation) {
- buffer.write('super');
- if (e.constructorName != null) {
- buffer.write('.');
- writeExpression(e.constructorName);
- }
- writeList('(', ')', e.argumentList.arguments, ', ', writeExpression,
- includeEmpty: true);
- } else if (e is SuperExpression) {
- buffer.write('super');
- } else if (e is SymbolLiteral) {
- buffer.write('#');
- writeList('', '', e.components, '.',
- (Token token) => buffer.write(token.lexeme));
- } else if (e is ThisExpression) {
- buffer.write('this');
- } else if (e is TypeName) {
- writeExpression(e.name);
- if (e.typeArguments != null) {
- writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression);
- }
- } else {
- fail('Unsupported expression type: ${e.runtimeType}');
- }
-
- if (needsParenthesis) {
- buffer.write(')');
- }
- }
-
void writeFunctionElement(FunctionElement e) {
writeDocumentation(e);
writeMetadata(e, '', '\n');
@@ -563,6 +383,11 @@
}
}
+ void writeInterfaceTypeArgsComment(Expression e) {
+ var typeArguments = (e.staticType as InterfaceType).typeArguments;
+ writeList('/*typeArgs=', '*/', typeArguments, ',', writeType);
+ }
+
void writeLibraryElement(LibraryElement e) {
if (e.documentationComment != null) {
buffer.writeln(e.documentationComment);
@@ -603,7 +428,7 @@
void writeMetadata(Element e, String prefix, String separator) {
if (e.metadata.isNotEmpty) {
writeList(prefix, '', e.metadata, '$separator$prefix', (a) {
- writeExpression((a as ElementAnnotationImpl).annotationAst);
+ writeNode((a as ElementAnnotationImpl).annotationAst);
});
buffer.write(separator);
}
@@ -653,6 +478,220 @@
}
}
+ void writeNode(AstNode e, [Expression enclosing]) {
+ bool needsParenthesis = e is Expression &&
+ enclosing != null &&
+ e.precedence2 < enclosing.precedence2;
+
+ if (needsParenthesis) {
+ buffer.write('(');
+ }
+
+ if (e == null) {
+ buffer.write('<null>');
+ } else if (e is SimpleIdentifier && e.name == '#invalidConst') {
+ buffer.write('#invalidConst');
+ } else if (e is AdjacentStrings) {
+ writeList("'", "'", e.strings, '',
+ (StringLiteral s) => buffer.write(s.stringValue),
+ includeEmpty: true);
+ } else if (e is Annotation) {
+ buffer.write('@');
+ writeNode(e.name);
+ if (e.constructorName != null) {
+ buffer.write('.');
+ writeNode(e.constructorName);
+ }
+ if (e.arguments != null) {
+ writeList('(', ')', e.arguments.arguments, ', ', writeNode,
+ includeEmpty: true);
+ }
+ } else if (e is AssertInitializer) {
+ buffer.write('assert(');
+ writeNode(e.condition);
+ if (e.message != null) {
+ buffer.write(', ');
+ writeNode(e.message);
+ }
+ buffer.write(')');
+ } else if (e is BinaryExpression) {
+ writeNode(e.leftOperand, e);
+ buffer.write(' ');
+ buffer.write(e.operator.lexeme);
+ buffer.write(' ');
+ writeNode(e.rightOperand, e);
+ } else if (e is BooleanLiteral) {
+ buffer.write(e.value);
+ } else if (e is ConditionalExpression) {
+ writeNode(e.condition);
+ buffer.write(' ? ');
+ writeNode(e.thenExpression);
+ buffer.write(' : ');
+ writeNode(e.elseExpression);
+ } else if (e is ConstructorFieldInitializer) {
+ writeNode(e.fieldName);
+ buffer.write(' = ');
+ writeNode(e.expression);
+ } else if (e is ConstructorName) {
+ writeNode(e.type);
+ if (e.name != null) {
+ buffer.write('.');
+ writeNode(e.name);
+ }
+ } else if (e is DoubleLiteral) {
+ buffer.write(e.value);
+ } else if (e is InstanceCreationExpression) {
+ if (e.keyword != null) {
+ buffer.write(e.keyword.lexeme);
+ buffer.write(' ');
+ }
+ writeNode(e.constructorName);
+ writeList('(', ')', e.argumentList.arguments, ', ', writeNode,
+ includeEmpty: true);
+ } else if (e is IntegerLiteral) {
+ buffer.write(e.value);
+ } else if (e is InterpolationExpression) {
+ buffer.write(r'${');
+ writeNode(e.expression);
+ buffer.write(r'}');
+ } else if (e is InterpolationString) {
+ buffer.write(e.value.replaceAll("'", r"\'"));
+ } else if (e is ListLiteral) {
+ if (e.constKeyword != null) {
+ buffer.write('const ');
+ }
+ if (e.typeArguments != null) {
+ writeList('<', '>', e.typeArguments.arguments, ', ', writeNode);
+ } else if (withTypes) {
+ writeInterfaceTypeArgsComment(e);
+ }
+ writeList('[', ']', e.elements2, ', ', writeNode, includeEmpty: true);
+ } else if (e is Label) {
+ writeNode(e.label);
+ buffer.write(': ');
+ } else if (e is SetOrMapLiteral) {
+ if (e.constKeyword != null) {
+ buffer.write('const ');
+ }
+ if (e.typeArguments != null) {
+ writeList('<', '>', e.typeArguments.arguments, ', ', writeNode);
+ } else if (withTypes) {
+ writeInterfaceTypeArgsComment(e);
+ }
+ writeList('{', '}', e.elements2, ', ', writeNode, includeEmpty: true);
+ if (e.isMap) {
+ buffer.write('/*isMap*/');
+ }
+ if (e.isSet) {
+ buffer.write('/*isSet*/');
+ }
+ } else if (e is MapLiteralEntry) {
+ writeNode(e.key);
+ buffer.write(': ');
+ writeNode(e.value);
+ } else if (e is MethodInvocation) {
+ if (e.target != null) {
+ writeNode(e.target);
+ buffer.write(e.operator);
+ }
+ writeNode(e.methodName);
+ if (e.typeArguments != null) {
+ writeList('<', '>', e.typeArguments.arguments, ', ', writeNode);
+ }
+ writeList('(', ')', e.argumentList.arguments, ', ', writeNode,
+ includeEmpty: true);
+ } else if (e is NamedExpression) {
+ writeNode(e.name);
+ buffer.write(e.expression);
+ } else if (e is NullLiteral) {
+ buffer.write('null');
+ } else if (e is ParenthesizedExpression) {
+ writeNode(e.expression, e);
+ } else if (e is PrefixExpression) {
+ buffer.write(e.operator.lexeme);
+ writeNode(e.operand, e);
+ } else if (e is PrefixedIdentifier) {
+ writeNode(e.prefix);
+ buffer.write('.');
+ writeNode(e.identifier);
+ } else if (e is PropertyAccess) {
+ writeNode(e.target, e);
+ buffer.write('.');
+ writeNode(e.propertyName);
+ } else if (e is RedirectingConstructorInvocation) {
+ buffer.write('this');
+ if (e.constructorName != null) {
+ buffer.write('.');
+ writeNode(e.constructorName);
+ }
+ writeList('(', ')', e.argumentList.arguments, ', ', writeNode,
+ includeEmpty: true);
+ } else if (e is SimpleIdentifier) {
+ if (withConstElements) {
+ buffer.writeln();
+ buffer.write(' ' * 4);
+ buffer.write(e.name);
+ buffer.write('/*');
+ buffer.write('location: ');
+ buffer.write(_getElementLocationString(e.staticElement));
+ buffer.write('*/');
+ } else {
+ buffer.write(e.name);
+ }
+ } else if (e is SimpleStringLiteral) {
+ buffer.write("'");
+ buffer.write(e.value.replaceAll("'", r"\'"));
+ buffer.write("'");
+ } else if (e is StringInterpolation) {
+ buffer.write("'");
+ e.elements.forEach(writeNode);
+ buffer.write("'");
+ } else if (e is SuperConstructorInvocation) {
+ buffer.write('super');
+ if (e.constructorName != null) {
+ buffer.write('.');
+ writeNode(e.constructorName);
+ }
+ writeList('(', ')', e.argumentList.arguments, ', ', writeNode,
+ includeEmpty: true);
+ } else if (e is SuperExpression) {
+ buffer.write('super');
+ } else if (e is SymbolLiteral) {
+ buffer.write('#');
+ writeList('', '', e.components, '.',
+ (Token token) => buffer.write(token.lexeme));
+ } else if (e is ThisExpression) {
+ buffer.write('this');
+ } else if (e is ThrowExpression) {
+ buffer.write('throw ');
+ writeNode(e.expression);
+ } else if (e is TypeName) {
+ writeNode(e.name);
+ if (e.typeArguments != null) {
+ writeList('<', '>', e.typeArguments.arguments, ', ', writeNode);
+ }
+ } else if (e is SpreadElement) {
+ buffer.write(e.spreadOperator.lexeme);
+ writeNode(e.expression);
+ } else if (e is IfElement) {
+ buffer.write('if (');
+ writeNode(e.condition);
+ buffer.write(') ');
+ writeNode(e.thenElement);
+ var elseElement = e.elseElement;
+ if (elseElement != null) {
+ buffer.write(' else ');
+ writeNode(elseElement);
+ }
+ } else {
+ fail('Unsupported expression type: ${e.runtimeType}');
+ }
+
+ if (needsParenthesis) {
+ buffer.write(')');
+ }
+ }
+
void writeParameterElement(ParameterElement e) {
String defaultValueSeparator;
Expression defaultValue;
@@ -701,7 +740,7 @@
if (defaultValue != null) {
buffer.write(defaultValueSeparator);
- writeExpression(defaultValue);
+ writeNode(defaultValue);
}
buffer.write(closeString);
@@ -802,16 +841,13 @@
if (!e.isSynthetic) {
expect(e.getter, isNotNull);
- expect(e.getter.isSynthetic, isTrue);
- expect(e.getter.variable, same(e));
- expect(e.getter.enclosingElement, same(e.enclosingElement));
+ _assertSyntheticAccessorEnclosing(e, e.getter);
+
if (e.isFinal || e.isConst) {
expect(e.setter, isNull);
} else {
expect(e.setter, isNotNull);
- expect(e.setter.isSynthetic, isTrue);
- expect(e.setter.variable, same(e.getter.variable));
- expect(e.setter.enclosingElement, same(e.enclosingElement));
+ _assertSyntheticAccessorEnclosing(e, e.getter);
}
}
@@ -842,7 +878,7 @@
Expression initializer = (e as ConstVariableElement).constantInitializer;
if (initializer != null) {
buffer.write(' = ');
- writeExpression(initializer);
+ writeNode(initializer);
}
}
@@ -922,6 +958,23 @@
}
}
+ /// Assert that the [accessor] of the [property] is correctly linked to
+ /// the same enclosing element as the [property].
+ void _assertSyntheticAccessorEnclosing(
+ PropertyInducingElement property, PropertyAccessorElement accessor) {
+ expect(accessor.isSynthetic, isTrue);
+ expect(accessor.variable, same(property));
+
+ var propertyEnclosing = property.enclosingElement;
+ expect(accessor.enclosingElement, same(propertyEnclosing));
+
+ if (propertyEnclosing is CompilationUnitElement) {
+ expect(propertyEnclosing.accessors, contains(accessor));
+ } else if (propertyEnclosing is ClassElement) {
+ expect(propertyEnclosing.accessors, contains(accessor));
+ }
+ }
+
String _getElementLocationString(Element element) {
if (element == null) {
return 'null';
diff --git a/pkg/analyzer/test/src/summary/expr_builder_test.dart b/pkg/analyzer/test/src/summary/expr_builder_test.dart
index 92cfb7f..67a8ae9 100644
--- a/pkg/analyzer/test/src/summary/expr_builder_test.dart
+++ b/pkg/analyzer/test/src/summary/expr_builder_test.dart
@@ -31,124 +31,6 @@
class ExprBuilderTest extends ResynthesizeTestStrategyTwoPhase
with ExprBuilderTestCases, ExprBuilderTestHelpers {}
-@reflectiveTest
-class TokensToStringTest {
- void test_empty_list_no_space() {
- // This is an interesting test case because "[]" is scanned as a single
- // token, but the parser splits it into two.
- _check('[]');
- }
-
- void test_empty_list_with_space() {
- _check('[ ]');
- }
-
- void test_gt_gt_gt_in_type() {
- // This is an interesting test case because ">>>" is scanned as a single
- // token, but the parser splits it into three.
- _check('A<B<C>>>[]');
- }
-
- void test_gt_gt_gt_in_type_split_both() {
- _check('A<B<C> > >[]');
- }
-
- void test_gt_gt_gt_in_type_split_left() {
- _check('A<B<C> >>[]');
- }
-
- void test_gt_gt_gt_in_type_split_right() {
- _check('A<B<C>> >[]');
- }
-
- void test_gt_gt_in_type() {
- // This is an interesting test case because ">>" is scanned as a single
- // token, but the parser splits it into two.
- _check('<A<B>>[]');
- }
-
- void test_gt_gt_in_type_split() {
- _check('A<B> >[]');
- }
-
- void test_identifier() {
- _check('foo');
- }
-
- void test_interpolation_expr_at_end_of_string() {
- _check(r'"foo${bar}"');
- }
-
- void test_interpolation_expr_at_start_of_string() {
- _check(r'"${foo}bar"');
- }
-
- void test_interpolation_expr_inside_string() {
- _check(r'"foo${bar}baz"');
- }
-
- void test_interpolation_var_at_end_of_string() {
- _check(r'"foo$bar"');
- }
-
- void test_interpolation_var_at_start_of_string() {
- _check(r'"$foo bar"');
- }
-
- void test_interpolation_var_inside_string() {
- _check(r'"foo$bar baz"');
- }
-
- void test_simple_string() {
- _check('"foo"');
- }
-
- void _check(String originalString) {
- var expression = _parseExpression(originalString);
- var originalTokens =
- _extractTokenList(expression.beginToken, expression.endToken);
- var newString = tokensToString(expression.beginToken, expression.endToken);
- var errorListener = AnalysisErrorListener.NULL_LISTENER;
- var reader = new CharSequenceReader(newString);
- var stringSource = new StringSource(newString, null);
- var scanner = new Scanner(stringSource, reader, errorListener);
- var startToken = scanner.tokenize();
- var newTokens = _extractTokenList(startToken);
- expect(newTokens, originalTokens);
- }
-
- List<String> _extractTokenList(Token startToken, [Token endToken]) {
- var result = <String>[];
- while (!startToken.isEof) {
- if (!startToken.isSynthetic) result.add(startToken.lexeme);
- if (identical(startToken, endToken)) break;
- startToken = startToken.next;
- }
- return result;
- }
-
- Expression _parseExpression(String expressionString) {
- // Note: to normalize the token string it's not sufficient to tokenize it
- // and then pass the tokens to `tokensToString`; we also need to parse it
- // because parsing modifies the token stream (splitting up `[]`, `>>`, and
- // `>>>` tokens when circumstances warrant).
- //
- // We wrap the expression in "f() async => ...;" to ensure that the await
- // keyword is properly parsed.
- var sourceText = 'f() async => $expressionString;';
- var errorListener = AnalysisErrorListener.NULL_LISTENER;
- var reader = new CharSequenceReader(sourceText);
- var stringSource = new StringSource(sourceText, null);
- var scanner = new Scanner(stringSource, reader, errorListener);
- var startToken = scanner.tokenize();
- var parser = new Parser(stringSource, errorListener);
- var compilationUnit = parser.parseCompilationUnit(startToken);
- var f = compilationUnit.declarations[0] as FunctionDeclaration;
- var body = f.functionExpression.body as ExpressionFunctionBody;
- return body.expression;
- }
-}
-
/// Mixin containing test cases exercising the [ExprBuilder]. Intended to be
/// applied to a class implementing [ResynthesizeTestStrategy], along with the
/// mixin [ExprBuilderTestHelpers].
@@ -693,3 +575,121 @@
return encodeLibrary(source);
}
}
+
+@reflectiveTest
+class TokensToStringTest {
+ void test_empty_list_no_space() {
+ // This is an interesting test case because "[]" is scanned as a single
+ // token, but the parser splits it into two.
+ _check('[]');
+ }
+
+ void test_empty_list_with_space() {
+ _check('[ ]');
+ }
+
+ void test_gt_gt_gt_in_type() {
+ // This is an interesting test case because ">>>" is scanned as a single
+ // token, but the parser splits it into three.
+ _check('A<B<C>>>[]');
+ }
+
+ void test_gt_gt_gt_in_type_split_both() {
+ _check('A<B<C> > >[]');
+ }
+
+ void test_gt_gt_gt_in_type_split_left() {
+ _check('A<B<C> >>[]');
+ }
+
+ void test_gt_gt_gt_in_type_split_right() {
+ _check('A<B<C>> >[]');
+ }
+
+ void test_gt_gt_in_type() {
+ // This is an interesting test case because ">>" is scanned as a single
+ // token, but the parser splits it into two.
+ _check('<A<B>>[]');
+ }
+
+ void test_gt_gt_in_type_split() {
+ _check('A<B> >[]');
+ }
+
+ void test_identifier() {
+ _check('foo');
+ }
+
+ void test_interpolation_expr_at_end_of_string() {
+ _check(r'"foo${bar}"');
+ }
+
+ void test_interpolation_expr_at_start_of_string() {
+ _check(r'"${foo}bar"');
+ }
+
+ void test_interpolation_expr_inside_string() {
+ _check(r'"foo${bar}baz"');
+ }
+
+ void test_interpolation_var_at_end_of_string() {
+ _check(r'"foo$bar"');
+ }
+
+ void test_interpolation_var_at_start_of_string() {
+ _check(r'"$foo bar"');
+ }
+
+ void test_interpolation_var_inside_string() {
+ _check(r'"foo$bar baz"');
+ }
+
+ void test_simple_string() {
+ _check('"foo"');
+ }
+
+ void _check(String originalString) {
+ var expression = _parseExpression(originalString);
+ var originalTokens =
+ _extractTokenList(expression.beginToken, expression.endToken);
+ var newString = tokensToString(expression.beginToken, expression.endToken);
+ var errorListener = AnalysisErrorListener.NULL_LISTENER;
+ var reader = new CharSequenceReader(newString);
+ var stringSource = new StringSource(newString, null);
+ var scanner = new Scanner(stringSource, reader, errorListener);
+ var startToken = scanner.tokenize();
+ var newTokens = _extractTokenList(startToken);
+ expect(newTokens, originalTokens);
+ }
+
+ List<String> _extractTokenList(Token startToken, [Token endToken]) {
+ var result = <String>[];
+ while (!startToken.isEof) {
+ if (!startToken.isSynthetic) result.add(startToken.lexeme);
+ if (identical(startToken, endToken)) break;
+ startToken = startToken.next;
+ }
+ return result;
+ }
+
+ Expression _parseExpression(String expressionString) {
+ // Note: to normalize the token string it's not sufficient to tokenize it
+ // and then pass the tokens to `tokensToString`; we also need to parse it
+ // because parsing modifies the token stream (splitting up `[]`, `>>`, and
+ // `>>>` tokens when circumstances warrant).
+ //
+ // We wrap the expression in "f() async => ...;" to ensure that the await
+ // keyword is properly parsed.
+ var sourceText = 'f() async => $expressionString;';
+ var errorListener = AnalysisErrorListener.NULL_LISTENER;
+ var reader = new CharSequenceReader(sourceText);
+ var stringSource = new StringSource(sourceText, null);
+ var scanner = new Scanner(stringSource, reader, errorListener);
+ var startToken = scanner.tokenize();
+ var parser = new Parser(stringSource, errorListener);
+ var compilationUnit = parser.parseCompilationUnit(startToken);
+ var f = compilationUnit.declarations[0] as FunctionDeclaration;
+ var body = f.functionExpression.body as ExpressionFunctionBody;
+ return body.expression;
+ }
+}
diff --git a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
index 1061dba..e5bc13c 100644
--- a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
+++ b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
@@ -2,20 +2,13 @@
// 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/context/cache.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/dart.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(ResynthesizerResultProviderTest);
defineReflectiveTests(SummaryDataStoreTest);
});
}
@@ -31,125 +24,6 @@
}
@reflectiveTest
-class ResynthesizerResultProviderTest {
- _SourceFactoryMock sourceFactory = new _SourceFactoryMock();
- _InternalAnalysisContextMock context = new _InternalAnalysisContextMock();
- UniversalCachePartition cachePartition;
-
- Source source1 = new _SourceMock('package:p1/u1.dart', '/p1/lib/u1.dart');
- Source source2 = new _SourceMock('package:p1/u2.dart', '/p1/lib/u2.dart');
- Source source3 = new _SourceMock('package:p2/u1.dart', '/p2/lib/u1.dart');
- CacheEntry entry1;
- CacheEntry entry2;
- CacheEntry entry3;
-
- _PackageBundleMock bundle = new _PackageBundleMock();
- _UnlinkedUnitMock unlinkedUnit1 = new _UnlinkedUnitMock();
- _UnlinkedUnitMock unlinkedUnit2 = new _UnlinkedUnitMock();
- _LinkedLibraryMock linkedLibrary = new _LinkedLibraryMock();
-
- SummaryDataStore dataStore = new SummaryDataStore(<String>[]);
- _TestResynthesizerResultProvider provider;
-
- void setUp() {
- cachePartition = new UniversalCachePartition(context);
- entry1 = new CacheEntry(source1);
- entry2 = new CacheEntry(source2);
- entry3 = new CacheEntry(source3);
- cachePartition.put(entry1);
- cachePartition.put(entry2);
- cachePartition.put(entry3);
-
- sourceFactory.resolvedUriMap['package:p1/u1.dart'] = source1;
- sourceFactory.resolvedUriMap['package:p1/u2.dart'] = source2;
- context.sourceFactory = sourceFactory;
-
- bundle.unlinkedUnitUris = <String>[
- 'package:p1/u1.dart',
- 'package:p1/u2.dart'
- ];
- bundle.unlinkedUnits = <UnlinkedUnit>[unlinkedUnit1, unlinkedUnit2];
- bundle.linkedLibraryUris = <String>['package:p1/u1.dart'];
- bundle.linkedLibraries = <LinkedLibrary>[linkedLibrary];
- dataStore.addBundle('/p1.ds', bundle);
-
- unlinkedUnit1.isPartOf = false;
- unlinkedUnit2.isPartOf = true;
-
- var namespace1 = _namespaceWithParts(['package:p1/u2.dart']);
- var namespace2 = _namespaceWithParts([]);
- unlinkedUnit1.publicNamespace = namespace1;
- unlinkedUnit2.publicNamespace = namespace2;
-
- provider = new _TestResynthesizerResultProvider(context, dataStore);
- provider.sourcesWithResults.add(source1);
- provider.sourcesWithResults.add(source2);
- }
-
- test_compute_CONTAINING_LIBRARIES_librarySource() {
- bool success = provider.compute(entry1, CONTAINING_LIBRARIES);
- expect(success, isTrue);
- expect(entry1.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
- }
-
- test_compute_CONTAINING_LIBRARIES_partSource() {
- bool success = provider.compute(entry2, CONTAINING_LIBRARIES);
- expect(success, isTrue);
- expect(entry2.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
- }
-
- test_compute_LINE_INFO_emptyLineStarts() {
- unlinkedUnit1.lineStarts = <int>[];
- bool success = provider.compute(entry1, LINE_INFO);
- expect(success, isFalse);
- }
-
- test_compute_LINE_INFO_hasLineStarts() {
- unlinkedUnit1.lineStarts = <int>[10, 20, 30];
- bool success = provider.compute(entry1, LINE_INFO);
- expect(success, isTrue);
- expect(entry1.getValue(LINE_INFO).lineStarts, <int>[10, 20, 30]);
- }
-
- test_compute_MODIFICATION_TIME_hasResult() {
- bool success = provider.compute(entry1, MODIFICATION_TIME);
- expect(success, isTrue);
- expect(entry1.getValue(MODIFICATION_TIME), 0);
- }
-
- test_compute_MODIFICATION_TIME_noResult() {
- bool success = provider.compute(entry3, MODIFICATION_TIME);
- expect(success, isFalse);
- expect(entry3.getState(MODIFICATION_TIME), CacheState.INVALID);
- }
-
- test_compute_SOURCE_KIND_librarySource() {
- bool success = provider.compute(entry1, SOURCE_KIND);
- expect(success, isTrue);
- expect(entry1.getValue(SOURCE_KIND), SourceKind.LIBRARY);
- }
-
- test_compute_SOURCE_KIND_librarySource_isPartOf() {
- unlinkedUnit1.isPartOf = true;
- bool success = provider.compute(entry1, SOURCE_KIND);
- expect(success, isTrue);
- expect(entry1.getValue(SOURCE_KIND), SourceKind.PART);
- }
-
- test_compute_SOURCE_KIND_noResults() {
- bool success = provider.compute(entry3, SOURCE_KIND);
- expect(success, isFalse);
- expect(entry3.getState(SOURCE_KIND), CacheState.INVALID);
- }
-
- test_compute_SOURCE_KIND_partSource() {
- bool success = provider.compute(entry2, SOURCE_KIND);
- expect(success, isTrue);
- expect(entry2.getValue(SOURCE_KIND), SourceKind.PART);
- }
-}
-
-@reflectiveTest
class SummaryDataStoreTest {
SummaryDataStore dataStore =
new SummaryDataStore(<String>[], disallowOverlappingSummaries: true);
@@ -289,16 +163,6 @@
}
}
-class _InternalAnalysisContextMock implements InternalAnalysisContext {
- @override
- SourceFactory sourceFactory;
-
- @override
- noSuchMethod(Invocation invocation) {
- throw new StateError('Unexpected invocation of ${invocation.memberName}');
- }
-}
-
class _LinkedLibraryMock implements LinkedLibrary {
@override
noSuchMethod(Invocation invocation) {
@@ -328,54 +192,6 @@
}
}
-class _SourceFactoryMock implements SourceFactory {
- Map<String, Source> resolvedUriMap = <String, Source>{};
-
- @override
- noSuchMethod(Invocation invocation) {
- throw new StateError('Unexpected invocation of ${invocation.memberName}');
- }
-
- @override
- Source resolveUri(Source containingSource, String containedUri) {
- return resolvedUriMap[containedUri];
- }
-}
-
-class _SourceMock implements Source {
- @override
- final Uri uri;
-
- @override
- final String fullName;
-
- _SourceMock(String uriStr, this.fullName) : uri = Uri.parse(uriStr);
-
- @override
- Source get librarySource => null;
-
- @override
- Source get source => this;
-
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$uri ($fullName)';
-}
-
-class _TestResynthesizerResultProvider extends ResynthesizerResultProvider {
- final Set<Source> sourcesWithResults = new Set<Source>();
-
- _TestResynthesizerResultProvider(
- InternalAnalysisContext context, SummaryDataStore dataStore)
- : super(context, null, dataStore);
-
- @override
- bool hasResultsForSource(Source source) {
- return sourcesWithResults.contains(source);
- }
-}
-
class _UnlinkedPublicNamespaceMock implements UnlinkedPublicNamespace {
@override
List<String> parts;
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index efbdbf9..32edf88 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -3,9 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_bundle_context.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -23,10 +27,94 @@
class ResynthesizeAst2Test extends ResynthesizeTestStrategyTwoPhase
with ResynthesizeTestCases {
@override
+ bool get isAstBasedSummary => true;
+
+ @override
Future<LibraryElementImpl> checkLibrary(String text,
{bool allowErrors = false, bool dumpSummaries = false}) async {
- var source = addTestSource(text);
+ var dartCoreSource = sourceFactory.forUri('dart:core');
+ var dartCoreCode = getFile(dartCoreSource.fullName).readAsStringSync();
+ dartCoreCode = r'''
+library dart.core;
+abstract class Comparable<T> {
+ int compareTo(T other);
+}
+
+class Iterable<T> {}
+
+class Iterator<T> {}
+
+class List<T> {}
+
+class Map<K, V> {}
+
+abstract class Null {}
+
+class Object {
+ const Object();
+}
+
+abstract class String {
+ int get length;
+ String operator +(String other);
+}
+
+class Set<T> {}
+
+abstract class Symbol {}
+
+abstract class Type {}
+
+abstract class bool {}
+
+abstract class double extends num {}
+
+abstract class int extends num {
+ bool get isEven => false;
+ bool get isNegative;
+
+ int operator &(int other);
+ int operator -();
+ int operator <<(int shiftAmount);
+ int operator >>(int shiftAmount);
+ int operator ^(int other);
+ int operator |(int other);
+ int operator ~();
+}
+
+abstract class num implements Comparable<num> {
+ bool operator <(num other);
+ bool operator <=(num other);
+ bool operator ==(Object other);
+ bool operator >(num other);
+ bool operator >=(num other);
+
+ double operator /(num other);
+ double toDouble();
+
+ int operator <<(int other);
+ int operator >>(int other);
+ int operator ^(int other);
+ int operator |(int other);
+ int operator ~();
+ int operator ~/(num other);
+
+ int round();
+ int toInt();
+ num abs();
+
+ num operator %(num other);
+ num operator *(num other);
+ num operator +(num other);
+ num operator -();
+ num operator -(num other);
+}
+''';
+
+ var dartCoreResult = _link(dartCoreSource, dartCoreCode);
+
+ var source = addTestSource(text);
var unit = parseText(text, experimentStatus: experimentStatus);
// TODO(scheglov) add other libraries
@@ -34,66 +122,39 @@
source: {source: unit},
};
+ for (var otherLibrarySource in otherLibrarySources) {
+ var text = getFile(otherLibrarySource.fullName).readAsStringSync();
+ var unit = parseText(text, experimentStatus: experimentStatus);
+ libraryUnitMap[otherLibrarySource] = {otherLibrarySource: unit};
+ }
+
+ var linkResult = link(
+ AnalysisOptionsImpl(),
+ sourceFactory,
+ [dartCoreResult.bundle],
+ libraryUnitMap,
+ );
+
+ var analysisContext = _FakeAnalysisContext(sourceFactory);
+
var rootReference = Reference.root();
- var linkResult = link(rootReference, libraryUnitMap);
+ rootReference.getChild('dart:core').getChild('dynamic').element =
+ DynamicElementImpl.instance;
- var libraryLinkResult = linkResult.libraries[source];
- var defaultUnitResult = libraryLinkResult.units[source];
-
- var linkedBundleContext = LinkedBundleContext(linkResult.references);
- var linkedUnitContext = LinkedUnitContext(
- linkedBundleContext,
- defaultUnitResult.tokens,
+ var elementFactory = LinkedElementFactory(
+ analysisContext,
+ null,
+ rootReference,
);
+ elementFactory.addBundle(dartCoreResult.bundle);
+ elementFactory.addBundle(linkResult.bundle);
- // TODO(scheglov) use actual names
- // TODO(scheglov) support parts
- var libraryElement = LibraryElementImpl(null, null, '', -1, 0);
- var unitElement = CompilationUnitElementImpl.forLinkedNode(
- libraryElement,
- linkedUnitContext,
- rootReference.getChild('${libraryLinkResult.source.uri}'),
- defaultUnitResult.node,
- );
- libraryElement.definingCompilationUnit = unitElement;
+ var dartCore = elementFactory.libraryOfUri('dart:core');
+ var typeProvider = SummaryTypeProvider()..initializeCore(dartCore);
+ analysisContext.typeProvider = typeProvider;
+ analysisContext.typeSystem = Dart2TypeSystem(typeProvider);
- return libraryElement;
- }
-
- @override
- @failingTest
- test_class_alias() async {
- await super.test_class_alias();
- }
-
- @override
- @failingTest
- test_class_alias_abstract() async {
- await super.test_class_alias_abstract();
- }
-
- @override
- @failingTest
- test_class_alias_documented() async {
- await super.test_class_alias_documented();
- }
-
- @override
- @failingTest
- test_class_alias_documented_tripleSlash() async {
- await super.test_class_alias_documented_tripleSlash();
- }
-
- @override
- @failingTest
- test_class_alias_documented_withLeadingNonDocumentation() async {
- await super.test_class_alias_documented_withLeadingNonDocumentation();
- }
-
- @override
- @failingTest
- test_class_alias_generic() async {
- await super.test_class_alias_generic();
+ return elementFactory.libraryOfUri('${source.uri}');
}
@override
@@ -118,36 +179,6 @@
@override
@failingTest
- test_class_alias_with_mixin_members() async {
- await super.test_class_alias_with_mixin_members();
- }
-
- @override
- @failingTest
- test_class_constructor_explicit_type_params() async {
- await super.test_class_constructor_explicit_type_params();
- }
-
- @override
- @failingTest
- test_class_constructor_field_formal_dynamic_dynamic() async {
- await super.test_class_constructor_field_formal_dynamic_dynamic();
- }
-
- @override
- @failingTest
- test_class_constructor_field_formal_dynamic_typed() async {
- await super.test_class_constructor_field_formal_dynamic_typed();
- }
-
- @override
- @failingTest
- test_class_constructor_field_formal_dynamic_untyped() async {
- await super.test_class_constructor_field_formal_dynamic_untyped();
- }
-
- @override
- @failingTest
test_class_constructor_field_formal_functionTyped_noReturnType() async {
await super
.test_class_constructor_field_formal_functionTyped_noReturnType();
@@ -168,48 +199,6 @@
@override
@failingTest
- test_class_constructor_field_formal_no_matching_field() async {
- await super.test_class_constructor_field_formal_no_matching_field();
- }
-
- @override
- @failingTest
- test_class_constructor_field_formal_typed_dynamic() async {
- await super.test_class_constructor_field_formal_typed_dynamic();
- }
-
- @override
- @failingTest
- test_class_constructor_field_formal_typed_typed() async {
- await super.test_class_constructor_field_formal_typed_typed();
- }
-
- @override
- @failingTest
- test_class_constructor_field_formal_typed_untyped() async {
- await super.test_class_constructor_field_formal_typed_untyped();
- }
-
- @override
- @failingTest
- test_class_constructor_field_formal_untyped_dynamic() async {
- await super.test_class_constructor_field_formal_untyped_dynamic();
- }
-
- @override
- @failingTest
- test_class_constructor_field_formal_untyped_typed() async {
- await super.test_class_constructor_field_formal_untyped_typed();
- }
-
- @override
- @failingTest
- test_class_constructor_field_formal_untyped_untyped() async {
- await super.test_class_constructor_field_formal_untyped_untyped();
- }
-
- @override
- @failingTest
test_class_constructor_fieldFormal_named_noDefault() async {
await super.test_class_constructor_fieldFormal_named_noDefault();
}
@@ -234,258 +223,6 @@
@override
@failingTest
- test_class_constructor_implicit_type_params() async {
- await super.test_class_constructor_implicit_type_params();
- }
-
- @override
- @failingTest
- test_class_constructor_params() async {
- await super.test_class_constructor_params();
- }
-
- @override
- @failingTest
- test_class_documented() async {
- await super.test_class_documented();
- }
-
- @override
- @failingTest
- test_class_documented_mix() async {
- await super.test_class_documented_mix();
- }
-
- @override
- @failingTest
- test_class_documented_tripleSlash() async {
- await super.test_class_documented_tripleSlash();
- }
-
- @override
- @failingTest
- test_class_documented_with_references() async {
- await super.test_class_documented_with_references();
- }
-
- @override
- @failingTest
- test_class_documented_with_windows_line_endings() async {
- await super.test_class_documented_with_windows_line_endings();
- }
-
- @override
- @failingTest
- test_class_documented_withLeadingNotDocumentation() async {
- await super.test_class_documented_withLeadingNotDocumentation();
- }
-
- @override
- @failingTest
- test_class_documented_withMetadata() async {
- await super.test_class_documented_withMetadata();
- }
-
- @override
- @failingTest
- test_class_field_const() async {
- await super.test_class_field_const();
- }
-
- @override
- @failingTest
- test_class_field_implicit_type() async {
- await super.test_class_field_implicit_type();
- }
-
- @override
- @failingTest
- test_class_field_static() async {
- await super.test_class_field_static();
- }
-
- @override
- @failingTest
- test_class_fields() async {
- await super.test_class_fields();
- }
-
- @override
- @failingTest
- test_class_getter_abstract() async {
- await super.test_class_getter_abstract();
- }
-
- @override
- @failingTest
- test_class_getter_external() async {
- await super.test_class_getter_external();
- }
-
- @override
- @failingTest
- test_class_getter_implicit_return_type() async {
- await super.test_class_getter_implicit_return_type();
- }
-
- @override
- @failingTest
- test_class_getter_static() async {
- await super.test_class_getter_static();
- }
-
- @override
- @failingTest
- test_class_getters() async {
- await super.test_class_getters();
- }
-
- @override
- @failingTest
- test_class_implicitField_getterFirst() async {
- await super.test_class_implicitField_getterFirst();
- }
-
- @override
- @failingTest
- test_class_implicitField_setterFirst() async {
- await super.test_class_implicitField_setterFirst();
- }
-
- @override
- @failingTest
- test_class_interfaces_unresolved() async {
- await super.test_class_interfaces_unresolved();
- }
-
- @override
- @failingTest
- test_class_method_abstract() async {
- await super.test_class_method_abstract();
- }
-
- @override
- @failingTest
- test_class_method_external() async {
- await super.test_class_method_external();
- }
-
- @override
- @failingTest
- test_class_method_params() async {
- await super.test_class_method_params();
- }
-
- @override
- @failingTest
- test_class_method_static() async {
- await super.test_class_method_static();
- }
-
- @override
- @failingTest
- test_class_methods() async {
- await super.test_class_methods();
- }
-
- @override
- @failingTest
- test_class_mixins_generic() async {
- await super.test_class_mixins_generic();
- }
-
- @override
- @failingTest
- test_class_mixins_unresolved() async {
- await super.test_class_mixins_unresolved();
- }
-
- @override
- @failingTest
- test_class_setter_abstract() async {
- await super.test_class_setter_abstract();
- }
-
- @override
- @failingTest
- test_class_setter_external() async {
- await super.test_class_setter_external();
- }
-
- @override
- @failingTest
- test_class_setter_implicit_param_type() async {
- await super.test_class_setter_implicit_param_type();
- }
-
- @override
- @failingTest
- test_class_setter_implicit_return_type() async {
- await super.test_class_setter_implicit_return_type();
- }
-
- @override
- @failingTest
- test_class_setter_invalid_named_parameter() async {
- await super.test_class_setter_invalid_named_parameter();
- }
-
- @override
- @failingTest
- test_class_setter_invalid_no_parameter() async {
- await super.test_class_setter_invalid_no_parameter();
- }
-
- @override
- @failingTest
- test_class_setter_invalid_optional_parameter() async {
- await super.test_class_setter_invalid_optional_parameter();
- }
-
- @override
- @failingTest
- test_class_setter_invalid_too_many_parameters() async {
- await super.test_class_setter_invalid_too_many_parameters();
- }
-
- @override
- @failingTest
- test_class_setter_static() async {
- await super.test_class_setter_static();
- }
-
- @override
- @failingTest
- test_class_setters() async {
- await super.test_class_setters();
- }
-
- @override
- @failingTest
- test_class_supertype_typeArguments() async {
- await super.test_class_supertype_typeArguments();
- }
-
- @override
- @failingTest
- test_class_supertype_unresolved() async {
- await super.test_class_supertype_unresolved();
- }
-
- @override
- @failingTest
- test_class_type_parameters() async {
- await super.test_class_type_parameters();
- }
-
- @override
- @failingTest
- test_class_type_parameters_bound() async {
- await super.test_class_type_parameters_bound();
- }
-
- @override
- @failingTest
test_class_type_parameters_f_bound_complex() async {
await super.test_class_type_parameters_f_bound_complex();
}
@@ -498,12 +235,6 @@
@override
@failingTest
- test_closure_executable_with_return_type_from_closure() async {
- await super.test_closure_executable_with_return_type_from_closure();
- }
-
- @override
- @failingTest
test_closure_generic() async {
await super.test_closure_generic();
}
@@ -612,36 +343,6 @@
@override
@failingTest
- test_const_invalid_intLiteral() async {
- await super.test_const_invalid_intLiteral();
- }
-
- @override
- @failingTest
- test_const_invalid_topLevel() async {
- await super.test_const_invalid_topLevel();
- }
-
- @override
- @failingTest
- test_const_invalid_typeMismatch() async {
- await super.test_const_invalid_typeMismatch();
- }
-
- @override
- @failingTest
- test_const_invokeConstructor_generic_named() async {
- await super.test_const_invokeConstructor_generic_named();
- }
-
- @override
- @failingTest
- test_const_invokeConstructor_generic_named_imported() async {
- await super.test_const_invokeConstructor_generic_named_imported();
- }
-
- @override
- @failingTest
test_const_invokeConstructor_generic_named_imported_withPrefix() async {
await super
.test_const_invokeConstructor_generic_named_imported_withPrefix();
@@ -649,24 +350,6 @@
@override
@failingTest
- test_const_invokeConstructor_generic_noTypeArguments() async {
- await super.test_const_invokeConstructor_generic_noTypeArguments();
- }
-
- @override
- @failingTest
- test_const_invokeConstructor_generic_unnamed() async {
- await super.test_const_invokeConstructor_generic_unnamed();
- }
-
- @override
- @failingTest
- test_const_invokeConstructor_generic_unnamed_imported() async {
- await super.test_const_invokeConstructor_generic_unnamed_imported();
- }
-
- @override
- @failingTest
test_const_invokeConstructor_generic_unnamed_imported_withPrefix() async {
await super
.test_const_invokeConstructor_generic_unnamed_imported_withPrefix();
@@ -680,12 +363,6 @@
@override
@failingTest
- test_const_invokeConstructor_named_imported() async {
- await super.test_const_invokeConstructor_named_imported();
- }
-
- @override
- @failingTest
test_const_invokeConstructor_named_imported_withPrefix() async {
await super.test_const_invokeConstructor_named_imported_withPrefix();
}
@@ -698,12 +375,6 @@
@override
@failingTest
- test_const_invokeConstructor_named_unresolved2() async {
- await super.test_const_invokeConstructor_named_unresolved2();
- }
-
- @override
- @failingTest
test_const_invokeConstructor_named_unresolved3() async {
await super.test_const_invokeConstructor_named_unresolved3();
}
@@ -716,114 +387,36 @@
@override
@failingTest
- test_const_invokeConstructor_named_unresolved5() async {
- await super.test_const_invokeConstructor_named_unresolved5();
- }
-
- @override
- @failingTest
test_const_invokeConstructor_named_unresolved6() async {
await super.test_const_invokeConstructor_named_unresolved6();
}
@override
@failingTest
- test_const_invokeConstructor_unnamed() async {
- await super.test_const_invokeConstructor_unnamed();
- }
-
- @override
- @failingTest
- test_const_invokeConstructor_unnamed_imported() async {
- await super.test_const_invokeConstructor_unnamed_imported();
- }
-
- @override
- @failingTest
test_const_invokeConstructor_unnamed_imported_withPrefix() async {
await super.test_const_invokeConstructor_unnamed_imported_withPrefix();
}
@override
@failingTest
- test_const_invokeConstructor_unnamed_unresolved() async {
- await super.test_const_invokeConstructor_unnamed_unresolved();
- }
-
- @override
- @failingTest
test_const_invokeConstructor_unnamed_unresolved2() async {
await super.test_const_invokeConstructor_unnamed_unresolved2();
}
@override
@failingTest
- test_const_invokeConstructor_unnamed_unresolved3() async {
- await super.test_const_invokeConstructor_unnamed_unresolved3();
- }
-
- @override
- @failingTest
- test_const_length_ofClassConstField() async {
- await super.test_const_length_ofClassConstField();
- }
-
- @override
- @failingTest
- test_const_length_ofClassConstField_imported() async {
- await super.test_const_length_ofClassConstField_imported();
- }
-
- @override
- @failingTest
test_const_length_ofClassConstField_imported_withPrefix() async {
await super.test_const_length_ofClassConstField_imported_withPrefix();
}
@override
@failingTest
- test_const_length_ofStringLiteral() async {
- await super.test_const_length_ofStringLiteral();
- }
-
- @override
- @failingTest
- test_const_length_ofTopLevelVariable() async {
- await super.test_const_length_ofTopLevelVariable();
- }
-
- @override
- @failingTest
- test_const_length_ofTopLevelVariable_imported() async {
- await super.test_const_length_ofTopLevelVariable_imported();
- }
-
- @override
- @failingTest
test_const_length_ofTopLevelVariable_imported_withPrefix() async {
await super.test_const_length_ofTopLevelVariable_imported_withPrefix();
}
@override
@failingTest
- test_const_length_staticMethod() async {
- await super.test_const_length_staticMethod();
- }
-
- @override
- @failingTest
- test_const_list_inferredType() async {
- await super.test_const_list_inferredType();
- }
-
- @override
- @failingTest
- test_const_map_inferredType() async {
- await super.test_const_map_inferredType();
- }
-
- @override
- @failingTest
test_const_parameterDefaultValue_initializingFormal_functionTyped() async {
await super
.test_const_parameterDefaultValue_initializingFormal_functionTyped();
@@ -844,36 +437,12 @@
@override
@failingTest
- test_const_parameterDefaultValue_normal() async {
- await super.test_const_parameterDefaultValue_normal();
- }
-
- @override
- @failingTest
- test_const_reference_staticField() async {
- await super.test_const_reference_staticField();
- }
-
- @override
- @failingTest
- test_const_reference_staticField_imported() async {
- await super.test_const_reference_staticField_imported();
- }
-
- @override
- @failingTest
test_const_reference_staticField_imported_withPrefix() async {
await super.test_const_reference_staticField_imported_withPrefix();
}
@override
@failingTest
- test_const_reference_staticMethod() async {
- await super.test_const_reference_staticMethod();
- }
-
- @override
- @failingTest
test_const_reference_staticMethod_imported() async {
await super.test_const_reference_staticMethod_imported();
}
@@ -886,36 +455,18 @@
@override
@failingTest
- test_const_reference_topLevelFunction() async {
- await super.test_const_reference_topLevelFunction();
- }
-
- @override
- @failingTest
test_const_reference_topLevelFunction_generic() async {
await super.test_const_reference_topLevelFunction_generic();
}
@override
@failingTest
- test_const_reference_topLevelFunction_imported() async {
- await super.test_const_reference_topLevelFunction_imported();
- }
-
- @override
- @failingTest
test_const_reference_topLevelFunction_imported_withPrefix() async {
await super.test_const_reference_topLevelFunction_imported_withPrefix();
}
@override
@failingTest
- test_const_reference_topLevelVariable() async {
- await super.test_const_reference_topLevelVariable();
- }
-
- @override
- @failingTest
test_const_reference_topLevelVariable_imported() async {
await super.test_const_reference_topLevelVariable_imported();
}
@@ -928,12 +479,6 @@
@override
@failingTest
- test_const_reference_type() async {
- await super.test_const_reference_type();
- }
-
- @override
- @failingTest
test_const_reference_type_functionType() async {
await super.test_const_reference_type_functionType();
}
@@ -958,96 +503,12 @@
@override
@failingTest
- test_const_reference_unresolved_prefix0() async {
- await super.test_const_reference_unresolved_prefix0();
- }
-
- @override
- @failingTest
- test_const_reference_unresolved_prefix1() async {
- await super.test_const_reference_unresolved_prefix1();
- }
-
- @override
- @failingTest
test_const_reference_unresolved_prefix2() async {
await super.test_const_reference_unresolved_prefix2();
}
@override
@failingTest
- test_const_topLevel_binary() async {
- await super.test_const_topLevel_binary();
- }
-
- @override
- @failingTest
- test_const_topLevel_conditional() async {
- await super.test_const_topLevel_conditional();
- }
-
- @override
- @failingTest
- test_const_topLevel_identical() async {
- await super.test_const_topLevel_identical();
- }
-
- @override
- @failingTest
- test_const_topLevel_ifNull() async {
- await super.test_const_topLevel_ifNull();
- }
-
- @override
- @failingTest
- test_const_topLevel_literal() async {
- await super.test_const_topLevel_literal();
- }
-
- @override
- @failingTest
- test_const_topLevel_parenthesis() async {
- await super.test_const_topLevel_parenthesis();
- }
-
- @override
- @failingTest
- test_const_topLevel_prefix() async {
- await super.test_const_topLevel_prefix();
- }
-
- @override
- @failingTest
- test_const_topLevel_super() async {
- await super.test_const_topLevel_super();
- }
-
- @override
- @failingTest
- test_const_topLevel_this() async {
- await super.test_const_topLevel_this();
- }
-
- @override
- @failingTest
- test_const_topLevel_throw() async {
- await super.test_const_topLevel_throw();
- }
-
- @override
- @failingTest
- test_const_topLevel_typedList() async {
- await super.test_const_topLevel_typedList();
- }
-
- @override
- @failingTest
- test_const_topLevel_typedList_imported() async {
- await super.test_const_topLevel_typedList_imported();
- }
-
- @override
- @failingTest
test_const_topLevel_typedList_importedWithPrefix() async {
await super.test_const_topLevel_typedList_importedWithPrefix();
}
@@ -1060,36 +521,6 @@
@override
@failingTest
- test_const_topLevel_typedMap() async {
- await super.test_const_topLevel_typedMap();
- }
-
- @override
- @failingTest
- test_const_topLevel_untypedList() async {
- await super.test_const_topLevel_untypedList();
- }
-
- @override
- @failingTest
- test_const_topLevel_untypedMap() async {
- await super.test_const_topLevel_untypedMap();
- }
-
- @override
- @failingTest
- test_constExpr_pushReference_enum_field() async {
- await super.test_constExpr_pushReference_enum_field();
- }
-
- @override
- @failingTest
- test_constExpr_pushReference_enum_method() async {
- await super.test_constExpr_pushReference_enum_method();
- }
-
- @override
- @failingTest
test_constExpr_pushReference_field_simpleIdentifier() async {
await super.test_constExpr_pushReference_field_simpleIdentifier();
}
@@ -1102,12 +533,6 @@
@override
@failingTest
- test_constructor_documented() async {
- await super.test_constructor_documented();
- }
-
- @override
- @failingTest
test_constructor_initializers_assertInvocation() async {
await super.test_constructor_initializers_assertInvocation();
}
@@ -1217,19 +642,6 @@
@override
@failingTest
- test_constructor_redirected_factory_named_unresolved_class() async {
- await super.test_constructor_redirected_factory_named_unresolved_class();
- }
-
- @override
- @failingTest
- test_constructor_redirected_factory_named_unresolved_constructor() async {
- await super
- .test_constructor_redirected_factory_named_unresolved_constructor();
- }
-
- @override
- @failingTest
test_constructor_redirected_factory_unnamed() async {
await super.test_constructor_redirected_factory_unnamed();
}
@@ -1266,12 +678,6 @@
@override
@failingTest
- test_constructor_redirected_factory_unnamed_unresolved() async {
- await super.test_constructor_redirected_factory_unnamed_unresolved();
- }
-
- @override
- @failingTest
test_constructor_redirected_thisInvocation_named() async {
await super.test_constructor_redirected_thisInvocation_named();
}
@@ -1302,12 +708,6 @@
@override
@failingTest
- test_constructor_withCycles_nonConst() async {
- await super.test_constructor_withCycles_nonConst();
- }
-
- @override
- @failingTest
test_defaultValue_genericFunction() async {
await super.test_defaultValue_genericFunction();
}
@@ -1350,36 +750,6 @@
@override
@failingTest
- test_enum_documented() async {
- await super.test_enum_documented();
- }
-
- @override
- @failingTest
- test_enum_value_documented() async {
- await super.test_enum_value_documented();
- }
-
- @override
- @failingTest
- test_enum_values() async {
- await super.test_enum_values();
- }
-
- @override
- @failingTest
- test_enums() async {
- await super.test_enums();
- }
-
- @override
- @failingTest
- test_error_extendsEnum() async {
- await super.test_error_extendsEnum();
- }
-
- @override
- @failingTest
test_executable_parameter_type_typedef() async {
await super.test_executable_parameter_type_typedef();
}
@@ -1494,36 +864,18 @@
@override
@failingTest
- test_expr_invalid_typeParameter_asPrefix() async {
- await super.test_expr_invalid_typeParameter_asPrefix();
- }
-
- @override
- @failingTest
test_field_covariant() async {
await super.test_field_covariant();
}
@override
@failingTest
- test_field_documented() async {
- await super.test_field_documented();
- }
-
- @override
- @failingTest
test_field_formal_param_inferred_type_implicit() async {
await super.test_field_formal_param_inferred_type_implicit();
}
@override
@failingTest
- test_field_inferred_type_nonStatic_explicit_initialized() async {
- await super.test_field_inferred_type_nonStatic_explicit_initialized();
- }
-
- @override
- @failingTest
test_field_inferred_type_nonStatic_implicit_initialized() async {
await super.test_field_inferred_type_nonStatic_implicit_initialized();
}
@@ -1578,12 +930,6 @@
@override
@failingTest
- test_field_typed() async {
- await super.test_field_typed();
- }
-
- @override
- @failingTest
test_field_untyped() async {
await super.test_field_untyped();
}
@@ -1602,18 +948,6 @@
@override
@failingTest
- test_function_documented() async {
- await super.test_function_documented();
- }
-
- @override
- @failingTest
- test_function_entry_point() async {
- await super.test_function_entry_point();
- }
-
- @override
- @failingTest
test_function_entry_point_in_export() async {
await super.test_function_entry_point_in_export();
}
@@ -1632,36 +966,6 @@
@override
@failingTest
- test_function_external() async {
- await super.test_function_external();
- }
-
- @override
- @failingTest
- test_function_parameter_final() async {
- await super.test_function_parameter_final();
- }
-
- @override
- @failingTest
- test_function_parameter_kind_named() async {
- await super.test_function_parameter_kind_named();
- }
-
- @override
- @failingTest
- test_function_parameter_kind_positional() async {
- await super.test_function_parameter_kind_positional();
- }
-
- @override
- @failingTest
- test_function_parameter_kind_required() async {
- await super.test_function_parameter_kind_required();
- }
-
- @override
- @failingTest
test_function_parameter_parameters() async {
await super.test_function_parameter_parameters();
}
@@ -1680,42 +984,6 @@
@override
@failingTest
- test_function_parameter_type() async {
- await super.test_function_parameter_type();
- }
-
- @override
- @failingTest
- test_function_parameters() async {
- await super.test_function_parameters();
- }
-
- @override
- @failingTest
- test_function_return_type() async {
- await super.test_function_return_type();
- }
-
- @override
- @failingTest
- test_function_return_type_implicit() async {
- await super.test_function_return_type_implicit();
- }
-
- @override
- @failingTest
- test_function_return_type_void() async {
- await super.test_function_return_type_void();
- }
-
- @override
- @failingTest
- test_function_type_parameter() async {
- await super.test_function_type_parameter();
- }
-
- @override
- @failingTest
test_function_type_parameter_with_function_typed_parameter() async {
await super.test_function_type_parameter_with_function_typed_parameter();
}
@@ -1728,12 +996,6 @@
@override
@failingTest
- test_functions() async {
- await super.test_functions();
- }
-
- @override
- @failingTest
test_futureOr() async {
await super.test_futureOr();
}
@@ -1752,12 +1014,6 @@
@override
@failingTest
- test_generic_gClass_gMethodStatic() async {
- await super.test_generic_gClass_gMethodStatic();
- }
-
- @override
- @failingTest
test_genericFunction_asFunctionReturnType() async {
await super.test_genericFunction_asFunctionReturnType();
}
@@ -1794,48 +1050,12 @@
@override
@failingTest
- test_getter_documented() async {
- await super.test_getter_documented();
- }
-
- @override
- @failingTest
- test_getter_external() async {
- await super.test_getter_external();
- }
-
- @override
- @failingTest
test_getter_inferred_type_nonStatic_implicit_return() async {
await super.test_getter_inferred_type_nonStatic_implicit_return();
}
@override
@failingTest
- test_getters() async {
- await super.test_getters();
- }
-
- @override
- @failingTest
- test_implicitTopLevelVariable_getterFirst() async {
- await super.test_implicitTopLevelVariable_getterFirst();
- }
-
- @override
- @failingTest
- test_implicitTopLevelVariable_setterFirst() async {
- await super.test_implicitTopLevelVariable_setterFirst();
- }
-
- @override
- @failingTest
- test_import_configurations_useDefault() async {
- await super.test_import_configurations_useDefault();
- }
-
- @override
- @failingTest
test_import_configurations_useFirst() async {
await super.test_import_configurations_useFirst();
}
@@ -1885,7 +1105,9 @@
@override
@failingTest
test_import_short_absolute() async {
- await super.test_import_short_absolute();
+ // TODO(scheglov) fails on Windows
+ fail('test_import_short_absolute on Windows');
+// await super.test_import_short_absolute();
}
@override
@@ -1896,30 +1118,12 @@
@override
@failingTest
- test_imports() async {
- await super.test_imports();
- }
-
- @override
- @failingTest
test_infer_generic_typedef_simple() async {
await super.test_infer_generic_typedef_simple();
}
@override
@failingTest
- test_infer_instanceCreation_fromArguments() async {
- await super.test_infer_instanceCreation_fromArguments();
- }
-
- @override
- @failingTest
- test_infer_property_set() async {
- await super.test_infer_property_set();
- }
-
- @override
- @failingTest
test_inference_issue_32394() async {
await super.test_inference_issue_32394();
}
@@ -1932,49 +1136,6 @@
@override
@failingTest
- test_inferred_function_type_for_variable_in_generic_function() async {
- await super.test_inferred_function_type_for_variable_in_generic_function();
- }
-
- @override
- @failingTest
- test_inferred_function_type_in_generic_class_constructor() async {
- await super.test_inferred_function_type_in_generic_class_constructor();
- }
-
- @override
- @failingTest
- test_inferred_function_type_in_generic_class_getter() async {
- await super.test_inferred_function_type_in_generic_class_getter();
- }
-
- @override
- @failingTest
- test_inferred_function_type_in_generic_class_in_generic_method() async {
- await super
- .test_inferred_function_type_in_generic_class_in_generic_method();
- }
-
- @override
- @failingTest
- test_inferred_function_type_in_generic_class_setter() async {
- await super.test_inferred_function_type_in_generic_class_setter();
- }
-
- @override
- @failingTest
- test_inferred_function_type_in_generic_closure() async {
- await super.test_inferred_function_type_in_generic_closure();
- }
-
- @override
- @failingTest
- test_inferred_generic_function_type_in_generic_closure() async {
- await super.test_inferred_generic_function_type_in_generic_closure();
- }
-
- @override
- @failingTest
test_inferred_type_is_typedef() async {
await super.test_inferred_type_is_typedef();
}
@@ -2059,12 +1220,6 @@
@override
@failingTest
- test_inheritance_errors() async {
- await super.test_inheritance_errors();
- }
-
- @override
- @failingTest
test_initializer_executable_with_return_type_from_closure() async {
await super.test_initializer_executable_with_return_type_from_closure();
}
@@ -2106,13 +1261,6 @@
@override
@failingTest
- test_initializer_executable_with_return_type_from_closure_local() async {
- await super
- .test_initializer_executable_with_return_type_from_closure_local();
- }
-
- @override
- @failingTest
test_instantiateToBounds_boundRefersToEarlierTypeArgument() async {
await super.test_instantiateToBounds_boundRefersToEarlierTypeArgument();
}
@@ -2155,36 +1303,18 @@
@override
@failingTest
- test_invalid_annotation_unprefixed_constructor() async {
- await super.test_invalid_annotation_unprefixed_constructor();
- }
-
- @override
- @failingTest
test_invalid_importPrefix_asTypeArgument() async {
await super.test_invalid_importPrefix_asTypeArgument();
}
@override
@failingTest
- test_invalid_nameConflict_imported() async {
- await super.test_invalid_nameConflict_imported();
- }
-
- @override
- @failingTest
test_invalid_nameConflict_imported_exported() async {
await super.test_invalid_nameConflict_imported_exported();
}
@override
@failingTest
- test_invalid_nameConflict_local() async {
- await super.test_invalid_nameConflict_local();
- }
-
- @override
- @failingTest
test_invalid_setterParameter_fieldFormalParameter() async {
await super.test_invalid_setterParameter_fieldFormalParameter();
}
@@ -2221,54 +1351,6 @@
@override
@failingTest
- test_library_name_with_spaces() async {
- await super.test_library_name_with_spaces();
- }
-
- @override
- @failingTest
- test_library_named() async {
- await super.test_library_named();
- }
-
- @override
- @failingTest
- test_localFunctions() async {
- await super.test_localFunctions();
- }
-
- @override
- @failingTest
- test_localFunctions_inMethod() async {
- await super.test_localFunctions_inMethod();
- }
-
- @override
- @failingTest
- test_localFunctions_inTopLevelGetter() async {
- await super.test_localFunctions_inTopLevelGetter();
- }
-
- @override
- @failingTest
- test_localLabels_inMethod() async {
- await super.test_localLabels_inMethod();
- }
-
- @override
- @failingTest
- test_localLabels_inTopLevelFunction() async {
- await super.test_localLabels_inTopLevelFunction();
- }
-
- @override
- @failingTest
- test_main_class_alias() async {
- await super.test_main_class_alias();
- }
-
- @override
- @failingTest
test_main_class_alias_via_export() async {
await super.test_main_class_alias_via_export();
}
@@ -2281,36 +1363,18 @@
@override
@failingTest
- test_main_getter() async {
- await super.test_main_getter();
- }
-
- @override
- @failingTest
test_main_getter_via_export() async {
await super.test_main_getter_via_export();
}
@override
@failingTest
- test_main_typedef() async {
- await super.test_main_typedef();
- }
-
- @override
- @failingTest
test_main_typedef_via_export() async {
await super.test_main_typedef_via_export();
}
@override
@failingTest
- test_main_variable() async {
- await super.test_main_variable();
- }
-
- @override
- @failingTest
test_main_variable_via_export() async {
await super.test_main_variable_via_export();
}
@@ -2335,84 +1399,24 @@
@override
@failingTest
- test_metadata_classDeclaration() async {
- await super.test_metadata_classDeclaration();
- }
-
- @override
- @failingTest
- test_metadata_classTypeAlias() async {
- await super.test_metadata_classTypeAlias();
- }
-
- @override
- @failingTest
- test_metadata_constructor_call_named() async {
- await super.test_metadata_constructor_call_named();
- }
-
- @override
- @failingTest
test_metadata_constructor_call_named_prefixed() async {
await super.test_metadata_constructor_call_named_prefixed();
}
@override
@failingTest
- test_metadata_constructor_call_unnamed() async {
- await super.test_metadata_constructor_call_unnamed();
- }
-
- @override
- @failingTest
test_metadata_constructor_call_unnamed_prefixed() async {
await super.test_metadata_constructor_call_unnamed_prefixed();
}
@override
@failingTest
- test_metadata_constructor_call_with_args() async {
- await super.test_metadata_constructor_call_with_args();
- }
-
- @override
- @failingTest
- test_metadata_constructorDeclaration_named() async {
- await super.test_metadata_constructorDeclaration_named();
- }
-
- @override
- @failingTest
- test_metadata_constructorDeclaration_unnamed() async {
- await super.test_metadata_constructorDeclaration_unnamed();
- }
-
- @override
- @failingTest
- test_metadata_enumConstantDeclaration() async {
- await super.test_metadata_enumConstantDeclaration();
- }
-
- @override
- @failingTest
- test_metadata_enumDeclaration() async {
- await super.test_metadata_enumDeclaration();
- }
-
- @override
- @failingTest
test_metadata_exportDirective() async {
await super.test_metadata_exportDirective();
}
@override
@failingTest
- test_metadata_fieldDeclaration() async {
- await super.test_metadata_fieldDeclaration();
- }
-
- @override
- @failingTest
test_metadata_fieldFormalParameter() async {
await super.test_metadata_fieldFormalParameter();
}
@@ -2425,30 +1429,6 @@
@override
@failingTest
- test_metadata_functionDeclaration_function() async {
- await super.test_metadata_functionDeclaration_function();
- }
-
- @override
- @failingTest
- test_metadata_functionDeclaration_getter() async {
- await super.test_metadata_functionDeclaration_getter();
- }
-
- @override
- @failingTest
- test_metadata_functionDeclaration_setter() async {
- await super.test_metadata_functionDeclaration_setter();
- }
-
- @override
- @failingTest
- test_metadata_functionTypeAlias() async {
- await super.test_metadata_functionTypeAlias();
- }
-
- @override
- @failingTest
test_metadata_functionTypedFormalParameter() async {
await super.test_metadata_functionTypedFormalParameter();
}
@@ -2479,24 +1459,6 @@
@override
@failingTest
- test_metadata_methodDeclaration_getter() async {
- await super.test_metadata_methodDeclaration_getter();
- }
-
- @override
- @failingTest
- test_metadata_methodDeclaration_method() async {
- await super.test_metadata_methodDeclaration_method();
- }
-
- @override
- @failingTest
- test_metadata_methodDeclaration_setter() async {
- await super.test_metadata_methodDeclaration_setter();
- }
-
- @override
- @failingTest
test_metadata_partDirective() async {
await super.test_metadata_partDirective();
}
@@ -2509,54 +1471,12 @@
@override
@failingTest
- test_metadata_simpleFormalParameter() async {
- await super.test_metadata_simpleFormalParameter();
- }
-
- @override
- @failingTest
test_metadata_simpleFormalParameter_withDefault() async {
await super.test_metadata_simpleFormalParameter_withDefault();
}
@override
@failingTest
- test_metadata_topLevelVariableDeclaration() async {
- await super.test_metadata_topLevelVariableDeclaration();
- }
-
- @override
- @failingTest
- test_metadata_typeParameter_ofClass() async {
- await super.test_metadata_typeParameter_ofClass();
- }
-
- @override
- @failingTest
- test_metadata_typeParameter_ofClassTypeAlias() async {
- await super.test_metadata_typeParameter_ofClassTypeAlias();
- }
-
- @override
- @failingTest
- test_metadata_typeParameter_ofFunction() async {
- await super.test_metadata_typeParameter_ofFunction();
- }
-
- @override
- @failingTest
- test_metadata_typeParameter_ofTypedef() async {
- await super.test_metadata_typeParameter_ofTypedef();
- }
-
- @override
- @failingTest
- test_method_documented() async {
- await super.test_method_documented();
- }
-
- @override
- @failingTest
test_method_inferred_type_nonStatic_implicit_param() async {
await super.test_method_inferred_type_nonStatic_implicit_param();
}
@@ -2569,30 +1489,12 @@
@override
@failingTest
- test_method_type_parameter() async {
- await super.test_method_type_parameter();
- }
-
- @override
- @failingTest
- test_method_type_parameter_in_generic_class() async {
- await super.test_method_type_parameter_in_generic_class();
- }
-
- @override
- @failingTest
test_method_type_parameter_with_function_typed_parameter() async {
await super.test_method_type_parameter_with_function_typed_parameter();
}
@override
@failingTest
- test_methodInvocation_implicitCall() async {
- await super.test_methodInvocation_implicitCall();
- }
-
- @override
- @failingTest
test_mixin() async {
await super.test_mixin();
}
@@ -2631,86 +1533,6 @@
@override
@failingTest
- test_nested_generic_functions_in_generic_class_with_function_typed_params() async {
- await super
- .test_nested_generic_functions_in_generic_class_with_function_typed_params();
- }
-
- @override
- @failingTest
- test_nested_generic_functions_in_generic_class_with_local_variables() async {
- await super
- .test_nested_generic_functions_in_generic_class_with_local_variables();
- }
-
- @override
- @failingTest
- test_nested_generic_functions_with_function_typed_param() async {
- await super.test_nested_generic_functions_with_function_typed_param();
- }
-
- @override
- @failingTest
- test_nested_generic_functions_with_local_variables() async {
- await super.test_nested_generic_functions_with_local_variables();
- }
-
- @override
- @failingTest
- test_operator() async {
- await super.test_operator();
- }
-
- @override
- @failingTest
- test_operator_equal() async {
- await super.test_operator_equal();
- }
-
- @override
- @failingTest
- test_operator_external() async {
- await super.test_operator_external();
- }
-
- @override
- @failingTest
- test_operator_greater_equal() async {
- await super.test_operator_greater_equal();
- }
-
- @override
- @failingTest
- test_operator_index() async {
- await super.test_operator_index();
- }
-
- @override
- @failingTest
- test_operator_index_set() async {
- await super.test_operator_index_set();
- }
-
- @override
- @failingTest
- test_operator_less_equal() async {
- await super.test_operator_less_equal();
- }
-
- @override
- @failingTest
- test_parameter() async {
- await super.test_parameter();
- }
-
- @override
- @failingTest
- test_parameter_covariant() async {
- await super.test_parameter_covariant();
- }
-
- @override
- @failingTest
test_parameter_covariant_inherited() async {
await super.test_parameter_covariant_inherited();
}
@@ -2741,30 +1563,12 @@
@override
@failingTest
- test_parameterTypeNotInferred_constructor() async {
- await super.test_parameterTypeNotInferred_constructor();
- }
-
- @override
- @failingTest
test_parameterTypeNotInferred_initializingFormal() async {
await super.test_parameterTypeNotInferred_initializingFormal();
}
@override
@failingTest
- test_parameterTypeNotInferred_staticMethod() async {
- await super.test_parameterTypeNotInferred_staticMethod();
- }
-
- @override
- @failingTest
- test_parameterTypeNotInferred_topLevelFunction() async {
- await super.test_parameterTypeNotInferred_topLevelFunction();
- }
-
- @override
- @failingTest
test_parts() async {
await super.test_parts();
}
@@ -2783,84 +1587,24 @@
@override
@failingTest
- test_propagated_type_refers_to_closure() async {
- await super.test_propagated_type_refers_to_closure();
- }
-
- @override
- @failingTest
- test_setter_covariant() async {
- await super.test_setter_covariant();
- }
-
- @override
- @failingTest
- test_setter_documented() async {
- await super.test_setter_documented();
- }
-
- @override
- @failingTest
- test_setter_external() async {
- await super.test_setter_external();
- }
-
- @override
- @failingTest
- test_setter_inferred_type_conflictingInheritance() async {
- await super.test_setter_inferred_type_conflictingInheritance();
- }
-
- @override
- @failingTest
test_setter_inferred_type_nonStatic_implicit_param() async {
await super.test_setter_inferred_type_nonStatic_implicit_param();
}
@override
@failingTest
- test_setter_inferred_type_static_implicit_return() async {
- await super.test_setter_inferred_type_static_implicit_return();
- }
-
- @override
- @failingTest
- test_setter_inferred_type_top_level_implicit_return() async {
- await super.test_setter_inferred_type_top_level_implicit_return();
- }
-
- @override
- @failingTest
- test_setters() async {
- await super.test_setters();
- }
-
- @override
- @failingTest
test_syntheticFunctionType_genericClosure() async {
await super.test_syntheticFunctionType_genericClosure();
}
@override
@failingTest
- test_syntheticFunctionType_genericClosure_inGenericFunction() async {
- await super.test_syntheticFunctionType_genericClosure_inGenericFunction();
- }
-
- @override
- @failingTest
test_syntheticFunctionType_inGenericClass() async {
await super.test_syntheticFunctionType_inGenericClass();
}
@override
@failingTest
- test_syntheticFunctionType_inGenericFunction() async {
- await super.test_syntheticFunctionType_inGenericFunction();
- }
-
- @override
- @failingTest
test_syntheticFunctionType_noArguments() async {
await super.test_syntheticFunctionType_noArguments();
}
@@ -2873,42 +1617,12 @@
@override
@failingTest
- test_type_arguments_explicit_dynamic_dynamic() async {
- await super.test_type_arguments_explicit_dynamic_dynamic();
- }
-
- @override
- @failingTest
- test_type_arguments_explicit_dynamic_int() async {
- await super.test_type_arguments_explicit_dynamic_int();
- }
-
- @override
- @failingTest
- test_type_arguments_explicit_String_dynamic() async {
- await super.test_type_arguments_explicit_String_dynamic();
- }
-
- @override
- @failingTest
- test_type_arguments_explicit_String_int() async {
- await super.test_type_arguments_explicit_String_int();
- }
-
- @override
- @failingTest
test_type_arguments_implicit() async {
await super.test_type_arguments_implicit();
}
@override
@failingTest
- test_type_dynamic() async {
- await super.test_type_dynamic();
- }
-
- @override
- @failingTest
test_type_inference_based_on_loadLibrary() async {
await super.test_type_inference_based_on_loadLibrary();
}
@@ -2999,30 +1713,12 @@
@override
@failingTest
- test_type_reference_to_class() async {
- await super.test_type_reference_to_class();
- }
-
- @override
- @failingTest
- test_type_reference_to_class_with_type_arguments() async {
- await super.test_type_reference_to_class_with_type_arguments();
- }
-
- @override
- @failingTest
test_type_reference_to_class_with_type_arguments_implicit() async {
await super.test_type_reference_to_class_with_type_arguments_implicit();
}
@override
@failingTest
- test_type_reference_to_enum() async {
- await super.test_type_reference_to_enum();
- }
-
- @override
- @failingTest
test_type_reference_to_import() async {
await super.test_type_reference_to_import();
}
@@ -3095,24 +1791,12 @@
@override
@failingTest
- test_type_unresolved() async {
- await super.test_type_unresolved();
- }
-
- @override
- @failingTest
test_type_unresolved_prefixed() async {
await super.test_type_unresolved_prefixed();
}
@override
@failingTest
- test_typedef_documented() async {
- await super.test_typedef_documented();
- }
-
- @override
- @failingTest
test_typedef_generic() async {
await super.test_typedef_generic();
}
@@ -3143,66 +1827,12 @@
@override
@failingTest
- test_typedef_parameter_type() async {
- await super.test_typedef_parameter_type();
- }
-
- @override
- @failingTest
- test_typedef_parameter_type_generic() async {
- await super.test_typedef_parameter_type_generic();
- }
-
- @override
- @failingTest
- test_typedef_parameters() async {
- await super.test_typedef_parameters();
- }
-
- @override
- @failingTest
test_typedef_parameters_named() async {
await super.test_typedef_parameters_named();
}
@override
@failingTest
- test_typedef_return_type() async {
- await super.test_typedef_return_type();
- }
-
- @override
- @failingTest
- test_typedef_return_type_generic() async {
- await super.test_typedef_return_type_generic();
- }
-
- @override
- @failingTest
- test_typedef_return_type_implicit() async {
- await super.test_typedef_return_type_implicit();
- }
-
- @override
- @failingTest
- test_typedef_return_type_void() async {
- await super.test_typedef_return_type_void();
- }
-
- @override
- @failingTest
- test_typedef_type_parameters() async {
- await super.test_typedef_type_parameters();
- }
-
- @override
- @failingTest
- test_typedef_type_parameters_bound() async {
- await super.test_typedef_type_parameters_bound();
- }
-
- @override
- @failingTest
test_typedef_type_parameters_bound_recursive() async {
await super.test_typedef_type_parameters_bound_recursive();
}
@@ -3233,49 +1863,12 @@
@override
@failingTest
- test_typedefs() async {
- await super.test_typedefs();
- }
-
- @override
- @failingTest
- test_unresolved_annotation_instanceCreation_argument_this() async {
- await super.test_unresolved_annotation_instanceCreation_argument_this();
- }
-
- @override
- @failingTest
- test_unresolved_annotation_namedConstructorCall_noClass() async {
- await super.test_unresolved_annotation_namedConstructorCall_noClass();
- }
-
- @override
- @failingTest
- test_unresolved_annotation_namedConstructorCall_noConstructor() async {
- await super.test_unresolved_annotation_namedConstructorCall_noConstructor();
- }
-
- @override
- @failingTest
- test_unresolved_annotation_prefixedIdentifier_badPrefix() async {
- await super.test_unresolved_annotation_prefixedIdentifier_badPrefix();
- }
-
- @override
- @failingTest
test_unresolved_annotation_prefixedIdentifier_noDeclaration() async {
await super.test_unresolved_annotation_prefixedIdentifier_noDeclaration();
}
@override
@failingTest
- test_unresolved_annotation_prefixedNamedConstructorCall_badPrefix() async {
- await super
- .test_unresolved_annotation_prefixedNamedConstructorCall_badPrefix();
- }
-
- @override
- @failingTest
test_unresolved_annotation_prefixedNamedConstructorCall_noClass() async {
await super
.test_unresolved_annotation_prefixedNamedConstructorCall_noClass();
@@ -3290,13 +1883,6 @@
@override
@failingTest
- test_unresolved_annotation_prefixedUnnamedConstructorCall_badPrefix() async {
- await super
- .test_unresolved_annotation_prefixedUnnamedConstructorCall_badPrefix();
- }
-
- @override
- @failingTest
test_unresolved_annotation_prefixedUnnamedConstructorCall_noClass() async {
await super
.test_unresolved_annotation_prefixedUnnamedConstructorCall_noClass();
@@ -3304,18 +1890,6 @@
@override
@failingTest
- test_unresolved_annotation_simpleIdentifier() async {
- await super.test_unresolved_annotation_simpleIdentifier();
- }
-
- @override
- @failingTest
- test_unresolved_annotation_unnamedConstructorCall_noClass() async {
- await super.test_unresolved_annotation_unnamedConstructorCall_noClass();
- }
-
- @override
- @failingTest
test_unresolved_export() async {
await super.test_unresolved_export();
}
@@ -3334,36 +1908,6 @@
@override
@failingTest
- test_unused_type_parameter() async {
- await super.test_unused_type_parameter();
- }
-
- @override
- @failingTest
- test_variable() async {
- await super.test_variable();
- }
-
- @override
- @failingTest
- test_variable_const() async {
- await super.test_variable_const();
- }
-
- @override
- @failingTest
- test_variable_documented() async {
- await super.test_variable_documented();
- }
-
- @override
- @failingTest
- test_variable_final() async {
- await super.test_variable_final();
- }
-
- @override
- @failingTest
test_variable_getterInLib_setterInPart() async {
await super.test_variable_getterInLib_setterInPart();
}
@@ -3382,48 +1926,6 @@
@override
@failingTest
- test_variable_implicit_type() async {
- await super.test_variable_implicit_type();
- }
-
- @override
- @failingTest
- test_variable_inferred_type_implicit_initialized() async {
- await super.test_variable_inferred_type_implicit_initialized();
- }
-
- @override
- @failingTest
- test_variable_initializer() async {
- await super.test_variable_initializer();
- }
-
- @override
- @failingTest
- test_variable_initializer_final() async {
- await super.test_variable_initializer_final();
- }
-
- @override
- @failingTest
- test_variable_initializer_final_untyped() async {
- await super.test_variable_initializer_final_untyped();
- }
-
- @override
- @failingTest
- test_variable_initializer_untyped() async {
- await super.test_variable_initializer_untyped();
- }
-
- @override
- @failingTest
- test_variable_propagatedType_const_noDep() async {
- await super.test_variable_propagatedType_const_noDep();
- }
-
- @override
- @failingTest
test_variable_propagatedType_final_dep_inLib() async {
await super.test_variable_propagatedType_final_dep_inLib();
}
@@ -3436,25 +1938,38 @@
@override
@failingTest
- test_variable_propagatedType_final_noDep() async {
- await super.test_variable_propagatedType_final_noDep();
- }
-
- @override
- @failingTest
- test_variable_propagatedType_implicit_dep() async {
- await super.test_variable_propagatedType_implicit_dep();
- }
-
- @override
- @failingTest
test_variable_setterInPart_getterInPart() async {
await super.test_variable_setterInPart_getterInPart();
}
- @override
- @failingTest
- test_variables() async {
- await super.test_variables();
+ LinkResult _link(Source source, String code) {
+ var unit = parseText(code, experimentStatus: experimentStatus);
+
+ // TODO(scheglov) add other libraries
+ var libraryUnitMap = {
+ source: {source: unit},
+ };
+
+ return link(
+ AnalysisOptionsImpl(),
+ sourceFactory,
+ [],
+ libraryUnitMap,
+ );
}
}
+
+class _FakeAnalysisContext implements AnalysisContext {
+ final SourceFactory sourceFactory;
+ TypeProvider typeProvider;
+ Dart2TypeSystem typeSystem;
+
+ _FakeAnalysisContext(this.sourceFactory);
+
+ @override
+ AnalysisOptions get analysisOptions {
+ return AnalysisOptionsImpl();
+ }
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index 985f379..a931ac3 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -24,7 +24,7 @@
@reflectiveTest
class ResynthesizeAstStrongTest extends ResynthesizeTestStrategyTwoPhase
- with ResynthesizeTestCases, ResynthesizeTestHelpers {
+ with ResynthesizeTestCases, GetElementTestCases, ResynthesizeTestHelpers {
@failingTest // See dartbug.com/32290
test_const_constructor_inferred_args() =>
super.test_const_constructor_inferred_args();
@@ -35,6 +35,9 @@
@failingTest // See dartbug.com/33441
test_const_map_inferredType() => super.test_const_map_inferredType();
+ @failingTest // See dartbug.com/33441
+ test_const_set_inferredType() => super.test_const_set_inferredType();
+
@override
@failingTest
test_syntheticFunctionType_inGenericClass() async {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 3f672e4..bb73374 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -9,8 +9,8 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/resynthesize.dart';
@@ -30,7 +30,6 @@
*/
abstract class AbstractResynthesizeTest with ResourceProviderMixin {
DeclaredVariables declaredVariables = new DeclaredVariables();
- AnalysisOptionsImpl analysisOptions = AnalysisOptionsImpl();
SourceFactory sourceFactory;
MockSdk sdk;
@@ -107,6 +106,104 @@
/// Mixin containing test cases exercising summary resynthesis. Intended to be
/// applied to a class implementing [ResynthesizeTestStrategy], along with the
/// mixin [ResynthesizeTestHelpers].
+mixin GetElementTestCases implements ResynthesizeTestHelpers {
+ test_getElement_class() async {
+ var resynthesized = _validateGetElement(
+ 'class C { m() {} }',
+ ['C'],
+ );
+ expect(resynthesized, isClassElement);
+ }
+
+ test_getElement_constructor_named() async {
+ var resynthesized = _validateGetElement(
+ 'class C { C.named(); }',
+ ['C', 'named'],
+ );
+ expect(resynthesized, isConstructorElement);
+ }
+
+ test_getElement_constructor_unnamed() async {
+ var resynthesized = _validateGetElement(
+ 'class C { C(); }',
+ ['C', ''],
+ );
+ expect(resynthesized, isConstructorElement);
+ }
+
+ test_getElement_field() async {
+ var resynthesized = _validateGetElement(
+ 'class C { var f; }',
+ ['C', 'f'],
+ );
+ expect(resynthesized, isFieldElement);
+ }
+
+ test_getElement_getter() async {
+ var resynthesized = _validateGetElement(
+ 'class C { get f => null; }',
+ ['C', 'f?'],
+ );
+ expect(resynthesized, isPropertyAccessorElement);
+ }
+
+ test_getElement_method() async {
+ var resynthesized = _validateGetElement(
+ 'class C { m() {} }',
+ ['C', 'm'],
+ );
+ expect(resynthesized, isMethodElement);
+ }
+
+ test_getElement_operator() async {
+ var resynthesized = _validateGetElement(
+ 'class C { operator+(x) => null; }',
+ ['C', '+'],
+ );
+ expect(resynthesized, isMethodElement);
+ }
+
+ test_getElement_setter() async {
+ var resynthesized = _validateGetElement(
+ 'class C { void set f(value) {} }',
+ ['C', 'f='],
+ );
+ expect(resynthesized, isPropertyAccessorElement);
+ }
+
+ test_getElement_unit() async {
+ var resynthesized = _validateGetElement('class C {}', []);
+ expect(resynthesized, isCompilationUnitElement);
+ }
+
+ /**
+ * Encode the library [text] into a summary and then use
+ * [TestSummaryResynthesizer.getElement] to retrieve just the element with
+ * the specified [names] from the resynthesized summary.
+ */
+ Element _validateGetElement(String text, List<String> names) {
+ Source source = addTestSource(text);
+ SummaryResynthesizer resynthesizer = encodeLibrary(source);
+
+ var locationComponents = [
+ source.uri.toString(),
+ source.uri.toString(),
+ ]..addAll(names);
+ var location = ElementLocationImpl.con3(locationComponents);
+
+ Element result = resynthesizer.getElement(location);
+ checkMinimalResynthesisWork(resynthesizer, source.uri, [source.uri]);
+ // Check that no other summaries needed to be resynthesized to resynthesize
+ // the library element.
+ expect(resynthesizer.resynthesisCount, 3);
+ expect(result.location, location);
+ return result;
+ }
+}
+
+/// Mixin containing test cases exercising summary resynthesis. Intended to be
+/// applied to a class implementing [ResynthesizeTestStrategy], along with the
+/// mixin [ResynthesizeTestHelpers].
mixin ResynthesizeTestCases implements ResynthesizeTestHelpers {
test_class_abstract() async {
var library = await checkLibrary('abstract class C {}');
@@ -2459,6 +2556,34 @@
''');
}
+ test_const_list_if() async {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int>[if (true) 1];
+''');
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/>[if (true) 1];
+''',
+ withTypes: true);
+ }
+
+ test_const_list_if_else() async {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int>[if (true) 1 else 2];
+''');
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/>[if (true) 1 else 2];
+''',
+ withTypes: true);
+ }
+
test_const_list_inferredType() async {
// The summary needs to contain enough information so that when the constant
// is resynthesized, the constant value can get the type that was computed
@@ -2466,10 +2591,95 @@
var library = await checkLibrary('''
const Object x = const [1];
''');
- checkElementText(library, '''
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+const Object x = const /*typeArgs=int*/[1];
+''',
+ withTypes: true);
+ } else {
+ checkElementText(library, '''
const Object x = const <
int/*location: dart:core;int*/>[1];
''');
+ }
+ }
+
+ test_const_list_spread() async {
+ experimentStatus = ExperimentStatus(spread_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int>[...<int>[1]];
+''');
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/>[...<
+ int/*location: dart:core;int*/>[1]];
+''',
+ withTypes: true);
+ } else {
+ checkElementText(library, '''
+const Object x = const <
+ int/*location: dart:core;int*/>[...const <
+ int/*location: dart:core;int*/>[1]];
+''');
+ }
+ }
+
+ test_const_list_spread_null_aware() async {
+ experimentStatus = ExperimentStatus(spread_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int>[...?<int>[1]];
+''');
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/>[...?<
+ int/*location: dart:core;int*/>[1]];
+''',
+ withTypes: true);
+ } else {
+ checkElementText(library, '''
+const Object x = const <
+ int/*location: dart:core;int*/>[...?const <
+ int/*location: dart:core;int*/>[1]];
+''');
+ }
+ }
+
+ test_const_map_if() async {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int, int>{if (true) 1: 2};
+''');
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{if (true) 1: 2}/*isMap*/;
+''',
+ withTypes: true);
+ }
+
+ test_const_map_if_else() async {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int, int>{if (true) 1: 2 else 3: 4];
+''');
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{if (true) 1: 2 else 3: 4}/*isMap*/;
+''',
+ withTypes: true);
}
test_const_map_inferredType() async {
@@ -2479,11 +2689,74 @@
var library = await checkLibrary('''
const Object x = const {1: 1.0};
''');
- checkElementText(library, '''
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+const Object x = const /*typeArgs=int,double*/{1: 1.0}/*isMap*/;
+''',
+ withTypes: true);
+ } else {
+ checkElementText(library, '''
const Object x = const <
int/*location: dart:core;int*/,
- double/*location: dart:core;double*/>{1: 1.0};
+ double/*location: dart:core;double*/>{1: 1.0}/*isMap*/;
''');
+ }
+ }
+
+ test_const_map_spread() async {
+ experimentStatus = ExperimentStatus(spread_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int, int>{...<int, int>{1: 2}};
+''');
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{...<
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{1: 2}/*isMap*/}/*isMap*/;
+''',
+ withTypes: true);
+ } else {
+ checkElementText(library, '''
+const Object x = const <
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{...const <
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{1: 2}/*isMap*/}/*isMap*/;
+''');
+ }
+ }
+
+ test_const_map_spread_null_aware() async {
+ experimentStatus = ExperimentStatus(spread_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int, int>{...?<int, int>{1: 2}};
+''');
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{...?<
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{1: 2}/*isMap*/}/*isMap*/;
+''',
+ withTypes: true);
+ } else {
+ checkElementText(library, '''
+const Object x = const <
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{...?const <
+ int/*location: dart:core;int*/,
+ int/*location: dart:core;int*/>{1: 2}/*isMap*/}/*isMap*/;
+''');
+ }
}
test_const_parameterDefaultValue_initializingFormal_functionTyped() async {
@@ -2926,6 +3199,102 @@
''');
}
+ test_const_set_if() async {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int>{if (true) 1};
+''');
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/>{if (true) 1}/*isSet*/;
+''',
+ withTypes: true);
+ }
+
+ test_const_set_if_else() async {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int>{if (true) 1 else 2];
+''');
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/>{if (true) 1 else 2}/*isSet*/;
+''',
+ withTypes: true);
+ }
+
+ test_const_set_inferredType() async {
+ // The summary needs to contain enough information so that when the constant
+ // is resynthesized, the constant value can get the type that was computed
+ // by type inference.
+ var library = await checkLibrary('''
+const Object x = const {1};
+''');
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+const Object x = const /*typeArgs=int*/{1}/*isSet*/;
+''',
+ withTypes: true);
+ } else {
+ checkElementText(library, '''
+const Object x = const <
+ int/*location: dart:core;int*/>{1}/*isSet*/;
+''');
+ }
+ }
+
+ test_const_set_spread() async {
+ experimentStatus = ExperimentStatus(spread_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int>{...<int>{1}};
+''');
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/>{...<
+ int/*location: dart:core;int*/>{1}/*isSet*/}/*isSet*/;
+''',
+ withTypes: true);
+ } else {
+ checkElementText(library, '''
+const Object x = const <
+ int/*location: dart:core;int*/>{...const <
+ int/*location: dart:core;int*/>{1}/*isSet*/}/*isSet*/;
+''');
+ }
+ }
+
+ test_const_set_spread_null_aware() async {
+ experimentStatus = ExperimentStatus(spread_collections: true);
+ var library = await checkLibrary('''
+const Object x = const <int>{...?<int>{1}};
+''');
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+const Object x = const <
+ int/*location: dart:core;int*/>{...?<
+ int/*location: dart:core;int*/>{1}/*isSet*/}/*isSet*/;
+''',
+ withTypes: true);
+ } else {
+ checkElementText(library, '''
+const Object x = const <
+ int/*location: dart:core;int*/>{...?const <
+ int/*location: dart:core;int*/>{1}/*isSet*/}/*isSet*/;
+''');
+ }
+ }
+
test_const_topLevel_binary() async {
var library = await checkLibrary(r'''
const vEqual = 1 == 2;
@@ -2973,18 +3342,30 @@
var library = await checkLibrary(r'''
const vConditional = (1 == 2) ? 11 : 22;
''');
- checkElementText(library, r'''
+ if (isAstBasedSummary) {
+ checkElementText(library, r'''
+const int vConditional = (1 == 2) ? 11 : 22;
+''');
+ } else {
+ checkElementText(library, r'''
const int vConditional = 1 == 2 ? 11 : 22;
''');
+ }
}
test_const_topLevel_identical() async {
var library = await checkLibrary(r'''
const vIdentical = (1 == 2) ? 11 : 22;
''');
- checkElementText(library, r'''
+ if (isAstBasedSummary) {
+ checkElementText(library, r'''
+const int vIdentical = (1 == 2) ? 11 : 22;
+''');
+ } else {
+ checkElementText(library, r'''
const int vIdentical = 1 == 2 ? 11 : 22;
''');
+ }
}
test_const_topLevel_ifNull() async {
@@ -3076,10 +3457,16 @@
var library = await checkLibrary(r'''
const c = throw 42;
''');
- // This is a bug.
- checkElementText(library, r'''
+ if (isAstBasedSummary) {
+ checkElementText(library, r'''
+const dynamic c = throw 42;
+''');
+ } else {
+ // This is a bug.
+ checkElementText(library, r'''
const dynamic c;
''');
+ }
}
test_const_topLevel_typedList() async {
@@ -3159,17 +3546,34 @@
checkElementText(library, r'''
const Map<dynamic, int> vDynamic1 = const <
dynamic/*location: dynamic*/,
- int/*location: dart:core;int*/>{};
+ int/*location: dart:core;int*/>{}/*isMap*/;
const Map<int, dynamic> vDynamic2 = const <
int/*location: dart:core;int*/,
- dynamic/*location: dynamic*/>{};
+ dynamic/*location: dynamic*/>{}/*isMap*/;
const Map<int, String> vInterface = const <
int/*location: dart:core;int*/,
- String/*location: dart:core;String*/>{};
+ String/*location: dart:core;String*/>{}/*isMap*/;
const Map<int, List<String>> vInterfaceWithTypeArguments = const <
int/*location: dart:core;int*/,
List/*location: dart:core;List*/<
- String/*location: dart:core;String*/>>{};
+ String/*location: dart:core;String*/>>{}/*isMap*/;
+''');
+ }
+
+ test_const_topLevel_typedSet() async {
+ var library = await checkLibrary(r'''
+const vDynamic1 = const <dynamic>{};
+const vInterface = const <int>{};
+const vInterfaceWithTypeArguments = const <List<String>>{};
+''');
+ checkElementText(library, r'''
+const Set<dynamic> vDynamic1 = const <
+ dynamic/*location: dynamic*/>{}/*isSet*/;
+const Set<int> vInterface = const <
+ int/*location: dart:core;int*/>{}/*isSet*/;
+const Set<List<String>> vInterfaceWithTypeArguments = const <
+ List/*location: dart:core;List*/<
+ String/*location: dart:core;String*/>>{}/*isSet*/;
''');
}
@@ -3187,7 +3591,16 @@
const v = const {0: 'aaa', 1: 'bbb', 2: 'ccc'};
''');
checkElementText(library, r'''
-const Map<int, String> v = const {0: 'aaa', 1: 'bbb', 2: 'ccc'};
+const Map<int, String> v = const {0: 'aaa', 1: 'bbb', 2: 'ccc'}/*isMap*/;
+''');
+ }
+
+ test_const_topLevel_untypedSet() async {
+ var library = await checkLibrary(r'''
+const v = const {0, 1, 2};
+''');
+ checkElementText(library, r'''
+const Set<int> v = const {0, 1, 2}/*isSet*/;
''');
}
@@ -4911,75 +5324,6 @@
''');
}
- test_getElement_class() async {
- var resynthesized = _validateGetElement(
- 'class C { m() {} }',
- ['C'],
- );
- expect(resynthesized, isClassElement);
- }
-
- test_getElement_constructor_named() async {
- var resynthesized = _validateGetElement(
- 'class C { C.named(); }',
- ['C', 'named'],
- );
- expect(resynthesized, isConstructorElement);
- }
-
- test_getElement_constructor_unnamed() async {
- var resynthesized = _validateGetElement(
- 'class C { C(); }',
- ['C', ''],
- );
- expect(resynthesized, isConstructorElement);
- }
-
- test_getElement_field() async {
- var resynthesized = _validateGetElement(
- 'class C { var f; }',
- ['C', 'f'],
- );
- expect(resynthesized, isFieldElement);
- }
-
- test_getElement_getter() async {
- var resynthesized = _validateGetElement(
- 'class C { get f => null; }',
- ['C', 'f?'],
- );
- expect(resynthesized, isPropertyAccessorElement);
- }
-
- test_getElement_method() async {
- var resynthesized = _validateGetElement(
- 'class C { m() {} }',
- ['C', 'm'],
- );
- expect(resynthesized, isMethodElement);
- }
-
- test_getElement_operator() async {
- var resynthesized = _validateGetElement(
- 'class C { operator+(x) => null; }',
- ['C', '+'],
- );
- expect(resynthesized, isMethodElement);
- }
-
- test_getElement_setter() async {
- var resynthesized = _validateGetElement(
- 'class C { void set f(value) {} }',
- ['C', 'f='],
- );
- expect(resynthesized, isPropertyAccessorElement);
- }
-
- test_getElement_unit() async {
- var resynthesized = _validateGetElement('class C {}', []);
- expect(resynthesized, isCompilationUnitElement);
- }
-
test_getter_documented() async {
var library = await checkLibrary('''
// Extra comment so doc comment offset != 0
@@ -6778,6 +7122,23 @@
''');
}
+ test_metadata_simpleFormalParameter_method() async {
+ var library = await checkLibrary('''
+const a = null;
+
+class C {
+ m(@a x) {}
+}
+''');
+ checkElementText(library, r'''
+class C {
+ dynamic m(@
+ a/*location: test.dart;a?*/ dynamic x) {}
+}
+const dynamic a = null;
+''');
+ }
+
test_metadata_simpleFormalParameter_withDefault() async {
var library = await checkLibrary('const a = null; f([@a x = null]) {}');
checkElementText(library, r'''
@@ -7670,6 +8031,21 @@
''');
}
+ test_type_inference_multiplyDefinedElement() async {
+ addLibrarySource('/a.dart', 'class C {}');
+ addLibrarySource('/b.dart', 'class C {}');
+ var library = await checkLibrary('''
+import 'a.dart';
+import 'b.dart';
+var v = C;
+''');
+ checkElementText(library, r'''
+import 'a.dart';
+import 'b.dart';
+dynamic v;
+''');
+ }
+
test_type_inference_nested_function() async {
var library = await checkLibrary('''
var x = (t) => (u) => t + u;
@@ -8684,30 +9060,6 @@
int j;
''');
}
-
- /**
- * Encode the library [text] into a summary and then use
- * [TestSummaryResynthesizer.getElement] to retrieve just the element with
- * the specified [names] from the resynthesized summary.
- */
- Element _validateGetElement(String text, List<String> names) {
- Source source = addTestSource(text);
- SummaryResynthesizer resynthesizer = encodeLibrary(source);
-
- var locationComponents = [
- source.uri.toString(),
- source.uri.toString(),
- ]..addAll(names);
- var location = ElementLocationImpl.con3(locationComponents);
-
- Element result = resynthesizer.getElement(location);
- checkMinimalResynthesisWork(resynthesizer, source.uri, [source.uri]);
- // Check that no other summaries needed to be resynthesized to resynthesize
- // the library element.
- expect(resynthesizer.resynthesisCount, 3);
- expect(result.location, location);
- return result;
- }
}
/// Mixin containing helper methods for testing summary resynthesis. Intended
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 9d73270..e5a4dfb 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -2754,6 +2754,72 @@
]);
}
+ test_constExpr_list_if() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = [if (true) 1];');
+ assertUnlinkedConst(variable.initializer.bodyExpr, '[if (true) 1]',
+ operators: [
+ UnlinkedExprOperation.pushTrue,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.ifElement,
+ UnlinkedExprOperation.makeUntypedList
+ ],
+ ints: [
+ 1,
+ 1
+ ]);
+ }
+
+ test_constExpr_list_if_else() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = [if (true) 1 else 2];');
+ assertUnlinkedConst(variable.initializer.bodyExpr, '[if (true) 1 else 2]',
+ operators: [
+ UnlinkedExprOperation.pushTrue,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.ifElseElement,
+ UnlinkedExprOperation.makeUntypedList
+ ],
+ ints: [
+ 1,
+ 2,
+ 1
+ ]);
+ }
+
+ test_constExpr_list_spread() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable = serializeVariableText('const v = [...[]];');
+ assertUnlinkedConst(variable.initializer.bodyExpr, '[...[]]', operators: [
+ UnlinkedExprOperation.makeUntypedList,
+ UnlinkedExprOperation.spreadElement,
+ UnlinkedExprOperation.makeUntypedList
+ ], ints: [
+ 0,
+ 1
+ ]);
+ }
+
+ test_constExpr_list_spread_null_aware() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable = serializeVariableText('const v = [...?[]];');
+ assertUnlinkedConst(variable.initializer.bodyExpr, '[...?[]]', operators: [
+ UnlinkedExprOperation.makeUntypedList,
+ UnlinkedExprOperation.nullAwareSpreadElement,
+ UnlinkedExprOperation.makeUntypedList
+ ], ints: [
+ 0,
+ 1
+ ]);
+ }
+
test_constExpr_makeSymbol() {
UnlinkedVariable variable = serializeVariableText('const v = #a.bb.ccc;');
assertUnlinkedConst(variable.initializer.bodyExpr, '#a.bb.ccc',
@@ -2884,11 +2950,14 @@
operators: [
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeMapLiteralEntry,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeMapLiteralEntry,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeTypedMap
+ UnlinkedExprOperation.makeMapLiteralEntry,
+ UnlinkedExprOperation.makeTypedMap2
],
ints: [
11,
@@ -2917,11 +2986,14 @@
operators: [
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeMapLiteralEntry,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeMapLiteralEntry,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeTypedMap
+ UnlinkedExprOperation.makeMapLiteralEntry,
+ UnlinkedExprOperation.makeTypedMap2
],
ints: [
11,
@@ -3078,11 +3150,14 @@
operators: [
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeMapLiteralEntry,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeMapLiteralEntry,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeUntypedMap
+ UnlinkedExprOperation.makeMapLiteralEntry,
+ UnlinkedExprOperation.makeUntypedSetOrMap
],
ints: [
11,
@@ -3108,12 +3183,129 @@
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeUntypedSet
+ UnlinkedExprOperation.makeUntypedSetOrMap
],
ints: [11, 22, 33, 3],
);
}
+ test_constExpr_map_if() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = <int, int>{if (true) 1 : 2};');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '<int, int>{if (true) 1 : 2}',
+ operators: [
+ UnlinkedExprOperation.pushTrue,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeMapLiteralEntry,
+ UnlinkedExprOperation.ifElement,
+ UnlinkedExprOperation.makeTypedMap2
+ ],
+ ints: [
+ 1,
+ 2,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum)
+ ]);
+ }
+
+ test_constExpr_map_if_else() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable = serializeVariableText(
+ 'const v = <int, int>{if (true) 1 : 2 else 3 : 4};');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '<int, int>{if (true) 1 : 2 else 3 : 4}',
+ operators: [
+ UnlinkedExprOperation.pushTrue,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeMapLiteralEntry,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeMapLiteralEntry,
+ UnlinkedExprOperation.ifElseElement,
+ UnlinkedExprOperation.makeTypedMap2
+ ],
+ ints: [
+ 1,
+ 2,
+ 3,
+ 4,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum)
+ ]);
+ }
+
+ test_constExpr_map_spread() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = <int, String>{...<int, String>{}};');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '<int, String>{...<int, String>{}}',
+ operators: [
+ UnlinkedExprOperation.makeTypedMap2,
+ UnlinkedExprOperation.spreadElement,
+ UnlinkedExprOperation.makeTypedMap2
+ ],
+ ints: [
+ 0,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
+ expectedKind: ReferenceKind.classOrEnum)
+ ]);
+ }
+
+ test_constExpr_map_spread_null_aware() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = <int, String>{...?<int, String>{}};');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '<int, String>{...?<int, String>{}}',
+ operators: [
+ UnlinkedExprOperation.makeTypedMap2,
+ UnlinkedExprOperation.nullAwareSpreadElement,
+ UnlinkedExprOperation.makeTypedMap2
+ ],
+ ints: [
+ 0,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
+ expectedKind: ReferenceKind.classOrEnum)
+ ]);
+ }
+
test_constExpr_parenthesized() {
UnlinkedVariable variable = serializeVariableText('const v = (1 + 2) * 3;');
assertUnlinkedConst(variable.initializer.bodyExpr, '(1 + 2) * 3',
@@ -3832,6 +4024,99 @@
operators: [UnlinkedExprOperation.pushTrue]);
}
+ test_constExpr_set_if() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = <int>{if (true) 1};');
+ assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{if (true) 1}',
+ operators: [
+ UnlinkedExprOperation.pushTrue,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.ifElement,
+ UnlinkedExprOperation.makeTypedSet
+ ],
+ ints: [
+ 1,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum)
+ ]);
+ }
+
+ test_constExpr_set_if_else() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = <int>{if (true) 1 else 2};');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '<int>{if (true) 1 else 2}',
+ operators: [
+ UnlinkedExprOperation.pushTrue,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.ifElseElement,
+ UnlinkedExprOperation.makeTypedSet
+ ],
+ ints: [
+ 1,
+ 2,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum)
+ ]);
+ }
+
+ test_constExpr_set_spread() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = <int>{...<int>{}};');
+ assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{...<int>{}}',
+ operators: [
+ UnlinkedExprOperation.makeTypedSet,
+ UnlinkedExprOperation.spreadElement,
+ UnlinkedExprOperation.makeTypedSet
+ ],
+ ints: [
+ 0,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum)
+ ]);
+ }
+
+ test_constExpr_set_spread_null_aware() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = <int>{...?<int>{}};');
+ assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{...?<int>{}}',
+ operators: [
+ UnlinkedExprOperation.makeTypedSet,
+ UnlinkedExprOperation.nullAwareSpreadElement,
+ UnlinkedExprOperation.makeTypedSet
+ ],
+ ints: [
+ 0,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum)
+ ]);
+ }
+
test_constructor() {
String text = 'class C { C(); }';
UnlinkedExecutable executable =
@@ -7383,7 +7668,7 @@
'var v = <int, String>{11: "aaa", 22: "bbb", 33: "ccc"};');
assertUnlinkedConst(variable.initializer.bodyExpr,
'<int, String>{11: "aaa", 22: "bbb", 33: "ccc"}',
- operators: [UnlinkedExprOperation.makeTypedMap],
+ operators: [UnlinkedExprOperation.makeTypedMap2],
ints: [0],
referenceValidators: [
(EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
@@ -7429,11 +7714,14 @@
operators: [
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeMapLiteralEntry,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeMapLiteralEntry,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeUntypedMap
+ UnlinkedExprOperation.makeMapLiteralEntry,
+ UnlinkedExprOperation.makeUntypedSetOrMap
],
ints: [11, 22, 33, 3],
strings: ['aaa', 'bbb', 'ccc'],
@@ -7448,7 +7736,7 @@
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushInt,
UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeUntypedSet
+ UnlinkedExprOperation.makeUntypedSetOrMap
],
ints: [11, 22, 33, 3],
forTypeInferenceOnly: true);
diff --git a/pkg/analyzer/test/src/summary/test_strategies.dart b/pkg/analyzer/test/src/summary/test_strategies.dart
index 0ceebdf..eed8b58 100644
--- a/pkg/analyzer/test/src/summary/test_strategies.dart
+++ b/pkg/analyzer/test/src/summary/test_strategies.dart
@@ -11,6 +11,7 @@
import 'package:analyzer/src/dart/analysis/restricted_analysis_context.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/parser.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -42,9 +43,11 @@
Scanner scanner =
new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER);
Token token = scanner.tokenize();
- Parser parser =
- new Parser(NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER)
- ..enableNonNullable = experimentStatus.non_nullable;
+ Parser parser = new Parser(
+ NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER)
+ ..enableNonNullable = experimentStatus.non_nullable
+ ..enableSpreadCollections = experimentStatus.spread_collections
+ ..enableControlFlowCollections = experimentStatus.control_flow_collections;
CompilationUnit unit = parser.parseCompilationUnit(token);
unit.lineInfo = new LineInfo(scanner.lineStarts);
return unit;
@@ -98,6 +101,8 @@
set declaredVariables(DeclaredVariables declaredVariables);
+ bool get isAstBasedSummary => false;
+
MemoryResourceProvider get resourceProvider;
void set testFile(String value);
@@ -132,6 +137,9 @@
PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
+ @override
+ bool get isAstBasedSummary => false;
+
TestSummaryResynthesizer encodeLibrary(Source source) {
_serializeLibrary(source);
@@ -169,8 +177,11 @@
.map((Source source) => source.uri.toString())
.toSet();
- Map<String, LinkedLibrary> linkedSummaries =
- link(nonSdkLibraryUris, getDependency, getUnit, declaredVariables.get);
+ var analysisOptions = AnalysisOptionsImpl()
+ ..enabledExperiments = experimentStatus.toStringList();
+
+ Map<String, LinkedLibrary> linkedSummaries = link(nonSdkLibraryUris,
+ getDependency, getUnit, declaredVariables, analysisOptions);
var analysisContext = RestrictedAnalysisContext(
analysisOptions,
@@ -216,7 +227,8 @@
contents = '';
}
- CompilationUnit unit = parseText(contents);
+ CompilationUnit unit =
+ parseText(contents, experimentStatus: experimentStatus);
UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
bundleAssembler.addUnlinkedUnit(source, unlinkedUnit);
@@ -244,7 +256,7 @@
UnlinkedUnit definingUnit = _getUnlinkedUnit(librarySource);
if (definingUnit != null) {
LinkedLibraryBuilder linkedLibrary = prelink(librarySource.uri.toString(),
- definingUnit, getPart, getImport, declaredVariables.get);
+ definingUnit, getPart, getImport, declaredVariables);
linkedLibrary.dependencies.skip(1).forEach((LinkedDependency d) {
Source source = sourceFactory.forUri(d.uri);
_serializeLibrary(source);
@@ -265,6 +277,7 @@
final Map<String, UnlinkedUnit> uriToUnlinkedUnit;
final Map<String, LinkedLibrary> uriToLinkedLibrary;
+
SerializedMockSdk._(this.uriToUnlinkedUnit, this.uriToLinkedLibrary);
static SerializedMockSdk _serializeMockSdk() {
@@ -370,11 +383,12 @@
}
linked = new LinkedLibrary.fromBuffer(prelink(
- _linkerInputs._testDartUri.toString(),
- _linkerInputs._unlinkedDefiningUnit,
- getPart,
- getImport,
- (String declaredVariable) => null).toBuffer());
+ _linkerInputs._testDartUri.toString(),
+ _linkerInputs._unlinkedDefiningUnit,
+ getPart,
+ getImport,
+ DeclaredVariables())
+ .toBuffer());
_validateLinkedLibrary(linked);
}
}
@@ -434,9 +448,9 @@
Map<String, LinkedLibraryBuilder> linkedLibraries = setupForLink(
_linkerInputs.linkedLibraries,
_linkerInputs.getUnit,
- _linkerInputs.getDeclaredVariable);
+ _linkerInputs.declaredVariables);
linker = new Linker(linkedLibraries, _linkerInputs.getDependency,
- _linkerInputs.getUnit, null);
+ _linkerInputs.getUnit, null, analysisOptions);
}
}
@@ -474,11 +488,9 @@
this._dependentLinkedLibraries,
this._dependentUnlinkedUnits);
- Set<String> get linkedLibraries => _uriToUnit.keys.toSet();
+ DeclaredVariables get declaredVariables => DeclaredVariables();
- String getDeclaredVariable(String name) {
- return null;
- }
+ Set<String> get linkedLibraries => _uriToUnit.keys.toSet();
LinkedLibrary getDependency(String absoluteUri) {
Map<String, LinkedLibrary> sdkLibraries =
@@ -521,6 +533,9 @@
_LinkerInputs _linkerInputs;
+ AnalysisOptions get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = experimentStatus.toStringList();
+
bool get _allowMissingFiles;
@override
@@ -545,7 +560,8 @@
linkerInputs.linkedLibraries,
linkerInputs.getDependency,
linkerInputs.getUnit,
- linkerInputs.getDeclaredVariable);
+ linkerInputs.declaredVariables,
+ analysisOptions);
linkedLibraries.forEach(assembler.addLinkedLibrary);
linkerInputs._uriToUnit.forEach((String uri, UnlinkedUnit unit) {
assembler.addUnlinkedUnitViaUri(uri, unit);
@@ -609,7 +625,8 @@
_linkerInputs.linkedLibraries,
_linkerInputs.getDependency,
_linkerInputs.getUnit,
- (name) => null)[_linkerInputs._testDartUri.toString()];
+ DeclaredVariables(),
+ analysisOptions)[_linkerInputs._testDartUri.toString()];
expect(linked, isNotNull);
_validateLinkedLibrary(linked);
unlinkedUnits = <UnlinkedUnit>[_linkerInputs._unlinkedDefiningUnit];
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index b2c8847..b4d8961 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -374,12 +374,6 @@
@override
List<String> get enabledExperiments =>
[EnableString.spread_collections, EnableString.control_flow_collections];
-
- @failingTest
- @override
- test_initializer_untypedMap() async {
- await super.test_initializer_untypedMap();
- }
}
@reflectiveTest
diff --git a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
index f97c7a7..53f650d 100644
--- a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
@@ -6,7 +6,12 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/summary2/ast_binary_reader.dart';
import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/tokens_writer.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -122,15 +127,26 @@
var originalUnit = parseResult.unit;
var originalCode = originalUnit.toSource();
- var writer = new AstBinaryWriter();
- var builder = writer.writeNode(originalUnit);
- writer.writeReferences();
-
- var reader = AstBinaryReader(
- Reference.root(),
- writer.referenceBuilder,
- writer.tokens,
+ var tokensResult = TokensWriter().writeTokens(
+ originalUnit.beginToken,
+ originalUnit.endToken,
);
+ var tokensContext = tokensResult.toContext();
+
+ var rootReference = Reference.root();
+ var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
+
+ var linkingBundleContext = LinkingBundleContext(dynamicRef);
+ var writer = new AstBinaryWriter(linkingBundleContext, tokensContext);
+ var builder = writer.writeNode(originalUnit);
+
+ var bundleContext = LinkedBundleContext(
+ LinkedElementFactory(null, null, rootReference),
+ linkingBundleContext.referencesBuilder,
+ );
+ var unitContext = LinkedUnitContext(bundleContext, tokensContext);
+
+ var reader = AstBinaryReader(unitContext);
var deserializedUnit = reader.readNode(builder);
var deserializedCode = deserializedUnit.toSource();
diff --git a/pkg/analyzer/test/src/summary2/test_all.dart b/pkg/analyzer/test/src/summary2/test_all.dart
new file mode 100644
index 0000000..f77acf5
--- /dev/null
+++ b/pkg/analyzer/test/src/summary2/test_all.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'ast_binary_writer_test.dart' as ast_binary_writer;
+
+main() {
+ defineReflectiveSuite(() {
+ ast_binary_writer.main();
+ }, name: 'summary2');
+}
diff --git a/pkg/analyzer/test/src/task/dart_work_manager_test.dart b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
deleted file mode 100644
index 1a83d55..0000000
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ /dev/null
@@ -1,994 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/error/error.dart' show AnalysisError;
-import 'package:analyzer/exception/exception.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
- AnalysisContext,
- AnalysisErrorInfo,
- AnalysisErrorInfoImpl,
- AnalysisOptions,
- AnalysisOptionsImpl,
- CacheState,
- ChangeNoticeImpl,
- InternalAnalysisContext;
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/dart_work_manager.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(DartWorkManagerTest);
- });
-}
-
-@reflectiveTest
-class DartWorkManagerTest {
- _InternalAnalysisContextMock context = new _InternalAnalysisContextMock();
- AnalysisCache cache;
- DartWorkManager manager;
-
- CaughtException caughtException = new CaughtException(null, null);
-
- Source source1 = new TestSource('1.dart');
- Source source2 = new TestSource('2.dart');
- Source source3 = new TestSource('3.dart');
- Source source4 = new TestSource('4.dart');
- CacheEntry entry1;
- CacheEntry entry2;
- CacheEntry entry3;
- CacheEntry entry4;
-
- void expect_librarySourceQueue(List<Source> sources) {
- expect(manager.librarySourceQueue, unorderedEquals(sources));
- }
-
- void expect_unknownSourceQueue(List<Source> sources) {
- expect(manager.unknownSourceQueue, unorderedEquals(sources));
- }
-
- void setUp() {
- cache = context.analysisCache;
- manager = new DartWorkManager(context);
- entry1 = _getOrCreateEntry(source1);
- entry2 = _getOrCreateEntry(source2);
- entry3 = _getOrCreateEntry(source3);
- entry4 = _getOrCreateEntry(source4);
- }
-
- void test_applyChange_add() {
- // add source1
- manager.applyChange([source1], [], []);
- expect_unknownSourceQueue([source1]);
- expect_librarySourceQueue([]);
- // add source2
- manager.applyChange([source2], [], []);
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([source1, source2]);
- }
-
- void test_applyChange_add_duplicate() {
- // add source1
- manager.applyChange([source1], [], []);
- expect_unknownSourceQueue([source1]);
- expect_librarySourceQueue([]);
- // add source2
- manager.applyChange([source1], [], []);
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([source1]);
- }
-
- void test_applyChange_addRemove() {
- manager.applyChange([source1, source2], [], [source2, source3]);
- expect_unknownSourceQueue([source1]);
- expect_librarySourceQueue([]);
- }
-
- void test_applyChange_change() {
- manager.librarySourceQueue.addAll([source1, source3]);
- manager.unknownSourceQueue.addAll([source4]);
- // change source1
- manager.applyChange([], [source1], []);
- expect_librarySourceQueue([source3]);
- expect_unknownSourceQueue([source4, source1]);
- }
-
- /**
- * When we perform limited invalidation, we keep [SOURCE_KIND] valid. So, we
- * don't need to put such sources into [DartWorkManager.unknownSourceQueue],
- * and remove from [DartWorkManager.librarySourceQueue].
- */
- void test_applyChange_change_hasSourceKind() {
- entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- manager.librarySourceQueue.addAll([source1, source2]);
- manager.unknownSourceQueue.addAll([source3]);
- // change source1
- manager.applyChange([], [source1, source2], []);
- expect_librarySourceQueue([source1]);
- expect_unknownSourceQueue([source2, source3]);
- }
-
- void test_applyChange_remove() {
- manager.librarySourceQueue.addAll([source1, source3]);
- manager.unknownSourceQueue.addAll([source4]);
- // remove source1
- manager.applyChange([], [], [source1]);
- expect_librarySourceQueue([source3]);
- expect_unknownSourceQueue([source4]);
- // remove source3
- manager.applyChange([], [], [source3]);
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([source4]);
- // remove source4
- manager.applyChange([], [], [source4]);
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([]);
- }
-
- void test_applyChange_updatePartsLibraries_changeLibrary() {
- Source part1 = new TestSource('part1.dart');
- Source part2 = new TestSource('part2.dart');
- Source part3 = new TestSource('part3.dart');
- Source library1 = new TestSource('library1.dart');
- Source library2 = new TestSource('library2.dart');
- manager.partLibrariesMap[part1] = [library1, library2];
- manager.partLibrariesMap[part2] = [library2];
- manager.partLibrariesMap[part3] = [library1];
- manager.libraryPartsMap[library1] = [part1, part3];
- manager.libraryPartsMap[library2] = [part1, part2];
- _getOrCreateEntry(part1).setValue(CONTAINING_LIBRARIES, [], []);
- expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.VALID);
- // change library1
- manager.applyChange([], [library1], []);
- expect(manager.partLibrariesMap[part1], unorderedEquals([library2]));
- expect(manager.partLibrariesMap[part2], unorderedEquals([library2]));
- expect(manager.partLibrariesMap[part3], unorderedEquals([]));
- expect(manager.libraryPartsMap[library1], isNull);
- expect(manager.libraryPartsMap[library2], [part1, part2]);
- expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.INVALID);
- }
-
- void test_applyChange_updatePartsLibraries_changePart() {
- Source part1 = new TestSource('part1.dart');
- Source part2 = new TestSource('part2.dart');
- Source part3 = new TestSource('part3.dart');
- Source library1 = new TestSource('library1.dart');
- Source library2 = new TestSource('library2.dart');
- manager.partLibrariesMap[part1] = [library1, library2];
- manager.partLibrariesMap[part2] = [library2];
- manager.partLibrariesMap[part3] = [library1];
- manager.libraryPartsMap[library1] = [part1, part3];
- manager.libraryPartsMap[library2] = [part1, part2];
- _getOrCreateEntry(part1).setValue(CONTAINING_LIBRARIES, [], []);
- expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.VALID);
- // change part1
- manager.applyChange([], [part1], []);
- expect(manager.partLibrariesMap[part2], unorderedEquals([library2]));
- expect(manager.partLibrariesMap[part3], unorderedEquals([library1]));
- expect(manager.libraryPartsMap[library1], [part1, part3]);
- expect(manager.libraryPartsMap[library2], [part1, part2]);
- expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.INVALID);
- }
-
- void test_applyChange_updatePartsLibraries_removeLibrary() {
- Source part1 = new TestSource('part1.dart');
- Source part2 = new TestSource('part2.dart');
- Source part3 = new TestSource('part3.dart');
- Source library1 = new TestSource('library1.dart');
- Source library2 = new TestSource('library2.dart');
- manager.partLibrariesMap[part1] = [library1, library2];
- manager.partLibrariesMap[part2] = [library2];
- manager.partLibrariesMap[part3] = [library1];
- manager.libraryPartsMap[library1] = [part1, part3];
- manager.libraryPartsMap[library2] = [part1, part2];
- // remove library1
- manager.applyChange([], [], [library1]);
- expect(manager.partLibrariesMap[part1], unorderedEquals([library2]));
- expect(manager.partLibrariesMap[part2], unorderedEquals([library2]));
- expect(manager.partLibrariesMap[part3], unorderedEquals([]));
- expect(manager.libraryPartsMap[library1], isNull);
- expect(manager.libraryPartsMap[library2], [part1, part2]);
- }
-
- void test_applyChange_updatePartsLibraries_removePart() {
- Source part1 = new TestSource('part1.dart');
- Source part2 = new TestSource('part2.dart');
- Source part3 = new TestSource('part3.dart');
- Source library1 = new TestSource('library1.dart');
- Source library2 = new TestSource('library2.dart');
- manager.partLibrariesMap[part1] = [library1, library2];
- manager.partLibrariesMap[part2] = [library2];
- manager.partLibrariesMap[part3] = [library1];
- manager.libraryPartsMap[library1] = [part1, part3];
- manager.libraryPartsMap[library2] = [part1, part2];
- // remove part1
- manager.applyChange([], [], [part1]);
- expect(manager.partLibrariesMap[part1], isNull);
- expect(manager.partLibrariesMap[part2], unorderedEquals([library2]));
- expect(manager.partLibrariesMap[part3], unorderedEquals([library1]));
- expect(manager.libraryPartsMap[library1], [part1, part3]);
- expect(manager.libraryPartsMap[library2], [part1, part2]);
- }
-
- void test_applyPriorityTargets_isLibrary_computeErrors() {
- context.setShouldErrorsBeAnalyzed(source2, true);
- context.setShouldErrorsBeAnalyzed(source3, true);
- entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- entry2.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- manager.priorityResultQueue
- .add(new TargetedResult(source1, LIBRARY_ERRORS_READY));
- manager.priorityResultQueue
- .add(new TargetedResult(source2, LIBRARY_ERRORS_READY));
- // -source1 +source3
- manager.applyPriorityTargets([source2, source3]);
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(source2, LIBRARY_ERRORS_READY),
- new TargetedResult(source3, LIBRARY_ERRORS_READY)
- ]));
- // get next request
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, LIBRARY_ERRORS_READY);
- }
-
- void test_applyPriorityTargets_isLibrary_computeUnit() {
- context.setShouldErrorsBeAnalyzed(source2, false);
- context.setShouldErrorsBeAnalyzed(source3, false);
- entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- entry2.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- manager.priorityResultQueue
- .add(new TargetedResult(source1, LIBRARY_ERRORS_READY));
- manager.priorityResultQueue
- .add(new TargetedResult(source2, LIBRARY_ERRORS_READY));
- // -source1 +source3
- manager.applyPriorityTargets([source2, source3]);
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(
- new LibrarySpecificUnit(source2, source2), RESOLVED_UNIT),
- new TargetedResult(
- new LibrarySpecificUnit(source3, source3), RESOLVED_UNIT),
- ]));
- }
-
- void test_applyPriorityTargets_isPart() {
- entry1.setValue(SOURCE_KIND, SourceKind.PART, []);
- entry2.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- // +source2 +source3
- context.getLibrariesContainingMap[source1] = <Source>[source2, source3];
- manager.applyPriorityTargets([source1]);
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(source2, LIBRARY_ERRORS_READY),
- new TargetedResult(source3, LIBRARY_ERRORS_READY)
- ]));
- // get next request
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, LIBRARY_ERRORS_READY);
- }
-
- void test_applyPriorityTargets_isUnknown() {
- manager.applyPriorityTargets([source2, source3]);
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(source2, SOURCE_KIND),
- new TargetedResult(source3, SOURCE_KIND)
- ]));
- // get next request
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, SOURCE_KIND);
- }
-
- void test_getErrors() {
- AnalysisError error1 =
- new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
- AnalysisError error2 =
- new AnalysisError(source1, 2, 0, ScannerErrorCode.MISSING_DIGIT);
- context.getLibrariesContainingMap[source1] = <Source>[source2];
- entry1.setValue(SCAN_ERRORS, <AnalysisError>[error1], []);
- context
- .getCacheEntry(new LibrarySpecificUnit(source2, source1))
- .setValue(VERIFY_ERRORS, <AnalysisError>[error2], []);
- List<AnalysisError> errors = manager.getErrors(source1);
- expect(errors, unorderedEquals([error1, error2]));
- }
-
- void test_getErrors_hasFullList() {
- AnalysisError error1 =
- new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
- AnalysisError error2 =
- new AnalysisError(source1, 2, 0, ScannerErrorCode.MISSING_DIGIT);
- context.getLibrariesContainingMap[source1] = <Source>[source2];
- entry1.setValue(DART_ERRORS, <AnalysisError>[error1, error2], []);
- List<AnalysisError> errors = manager.getErrors(source1);
- expect(errors, unorderedEquals([error1, error2]));
- }
-
- void test_getLibrariesContainingPart() {
- context.aboutToComputeEverything = false;
- Source part1 = new TestSource('part1.dart');
- Source part2 = new TestSource('part2.dart');
- Source part3 = new TestSource('part3.dart');
- Source library1 = new TestSource('library1.dart');
- Source library2 = new TestSource('library2.dart');
- manager.partLibrariesMap[part1] = [library1, library2];
- manager.partLibrariesMap[part2] = [library2];
- manager.libraryPartsMap[library1] = [part1];
- manager.libraryPartsMap[library2] = [part1, part2];
- // getLibrariesContainingPart
- expect(manager.getLibrariesContainingPart(part1),
- unorderedEquals([library1, library2]));
- expect(
- manager.getLibrariesContainingPart(part2), unorderedEquals([library2]));
- expect(manager.getLibrariesContainingPart(part3), isEmpty);
- }
-
- void test_getLibrariesContainingPart_askResultProvider() {
- Source part1 = new TestSource('part1.dart');
- Source part2 = new TestSource('part2.dart');
- Source part3 = new TestSource('part3.dart');
- Source library1 = new TestSource('library1.dart');
- Source library2 = new TestSource('library2.dart');
- // configure AnalysisContext mock
- context.aboutToComputeResultMap[CONTAINING_LIBRARIES] =
- (CacheEntry entry, ResultDescriptor result) {
- if (entry.target == part1) {
- entry.setValue(result as ResultDescriptor<List<Source>>,
- <Source>[library1, library2], []);
- return true;
- }
- if (entry.target == part2) {
- entry.setValue(
- result as ResultDescriptor<List<Source>>, <Source>[library2], []);
- return true;
- }
- return false;
- };
- // getLibrariesContainingPart
- expect(manager.getLibrariesContainingPart(part1),
- unorderedEquals([library1, library2]));
- expect(
- manager.getLibrariesContainingPart(part2), unorderedEquals([library2]));
- expect(manager.getLibrariesContainingPart(part3), isEmpty);
- }
-
- void test_getLibrariesContainingPart_inSDK() {
- _SourceMock part = new _SourceMock('part.dart');
- part.isInSystemLibrary = true;
- // SDK work manager
- _DartWorkManagerMock sdkDartWorkManagerMock = new _DartWorkManagerMock();
- sdkDartWorkManagerMock.librariesContainingPartMap[part] = <Source>[
- source2,
- source3
- ];
- // SDK context mock
- _InternalAnalysisContextMock sdkContextMock =
- new _InternalAnalysisContextMock();
- sdkContextMock.workManagers = <WorkManager>[sdkDartWorkManagerMock];
- // SDK mock
- _DartSdkMock sdkMock = new _DartSdkMock();
- sdkMock.context = sdkContextMock;
- // SourceFactory mock
- _SourceFactoryMock sourceFactory = new _SourceFactoryMock();
- sourceFactory.dartSdk = sdkMock;
- context.sourceFactory = sourceFactory;
- // SDK source mock
- _SourceMock source = new _SourceMock('test.dart');
- source.source = source;
- source.isInSystemLibrary = true;
- // validate
- expect(manager.getLibrariesContainingPart(part),
- unorderedEquals([source2, source3]));
- }
-
- void test_getNextResult_hasLibraries_firstIsError() {
- entry1.setErrorState(caughtException, [LIBRARY_ERRORS_READY]);
- manager.librarySourceQueue.addAll([source1, source2]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, LIBRARY_ERRORS_READY);
- // source1 is out, source2 is waiting
- expect_librarySourceQueue([source2]);
- }
-
- void test_getNextResult_hasLibraries_firstIsInvalid() {
- entry1.setState(LIBRARY_ERRORS_READY, CacheState.INVALID);
- manager.librarySourceQueue.addAll([source1, source2]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source1);
- expect(request.result, LIBRARY_ERRORS_READY);
- // no changes until computed
- expect_librarySourceQueue([source1, source2]);
- }
-
- void test_getNextResult_hasLibraries_firstIsValid() {
- entry1.setValue(LIBRARY_ERRORS_READY, true, []);
- manager.librarySourceQueue.addAll([source1, source2]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, LIBRARY_ERRORS_READY);
- // source1 is out, source2 is waiting
- expect_librarySourceQueue([source2]);
- }
-
- void test_getNextResult_hasPriority_firstIsError() {
- manager.addPriorityResult(source1, SOURCE_KIND);
- manager.addPriorityResult(source2, SOURCE_KIND);
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(source1, SOURCE_KIND),
- new TargetedResult(source2, SOURCE_KIND)
- ]));
- // configure state and get next result
- entry1.setErrorState(caughtException, [SOURCE_KIND]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, SOURCE_KIND);
- // source1 is out, source2 is waiting
- expect(manager.priorityResultQueue,
- unorderedEquals([new TargetedResult(source2, SOURCE_KIND)]));
- }
-
- void test_getNextResult_hasPriority_firstIsValid() {
- manager.addPriorityResult(source1, SOURCE_KIND);
- manager.addPriorityResult(source2, SOURCE_KIND);
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(source1, SOURCE_KIND),
- new TargetedResult(source2, SOURCE_KIND)
- ]));
- // configure state and get next result
- entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, SOURCE_KIND);
- // source1 is out, source2 is waiting
- expect(manager.priorityResultQueue,
- unorderedEquals([new TargetedResult(source2, SOURCE_KIND)]));
- }
-
- void test_getNextResult_hasUnknown_firstIsError() {
- entry1.setErrorState(caughtException, [SOURCE_KIND]);
- manager.unknownSourceQueue.addAll([source1, source2]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, SOURCE_KIND);
- // source1 is out, source2 is waiting
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([source2]);
- }
-
- void test_getNextResult_hasUnknown_firstIsInvalid() {
- manager.unknownSourceQueue.addAll([source1, source2]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source1);
- expect(request.result, SOURCE_KIND);
- // no changes until computed
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([source1, source2]);
- }
-
- void test_getNextResult_hasUnknown_firstIsValid() {
- entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- manager.unknownSourceQueue.addAll([source1, source2]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, SOURCE_KIND);
- // source1 is out, source2 is waiting
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([source2]);
- }
-
- void test_getNextResult_nothingToDo() {
- TargetedResult request = manager.getNextResult();
- expect(request, isNull);
- }
-
- void test_getNextResultPriority_hasLibrary() {
- manager.librarySourceQueue.addAll([source1]);
- expect(manager.getNextResultPriority(), WorkOrderPriority.NORMAL);
- }
-
- void test_getNextResultPriority_hasPriority() {
- manager.addPriorityResult(source1, SOURCE_KIND);
- expect(manager.getNextResultPriority(), WorkOrderPriority.PRIORITY);
- }
-
- void test_getNextResultPriority_hasUnknown() {
- manager.unknownSourceQueue.addAll([source1]);
- expect(manager.getNextResultPriority(), WorkOrderPriority.NORMAL);
- }
-
- void test_getNextResultPriority_nothingToDo() {
- expect(manager.getNextResultPriority(), WorkOrderPriority.NONE);
- }
-
- void test_onAnalysisOptionsChanged() {
- context.everythingExists = true;
- // set cache values
- entry1.setValue(PARSED_UNIT, AstTestFactory.compilationUnit(), []);
- entry1.setValue(IMPORTED_LIBRARIES, <Source>[], []);
- entry1.setValue(EXPLICITLY_IMPORTED_LIBRARIES, <Source>[], []);
- entry1.setValue(EXPORTED_LIBRARIES, <Source>[], []);
- entry1.setValue(INCLUDED_PARTS, <Source>[], []);
- // configure LibrarySpecificUnit
- LibrarySpecificUnit unitTarget = new LibrarySpecificUnit(source2, source3);
- CacheEntry unitEntry = new CacheEntry(unitTarget);
- cache.put(unitEntry);
- unitEntry.setValue(BUILD_LIBRARY_ERRORS, <AnalysisError>[], []);
- expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.VALID);
- // notify
- manager.onAnalysisOptionsChanged();
- // resolution is invalidated
- expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.INVALID);
- // ...but URIs are still value
- expect(entry1.getState(PARSED_UNIT), CacheState.VALID);
- expect(entry1.getState(IMPORTED_LIBRARIES), CacheState.VALID);
- expect(entry1.getState(EXPLICITLY_IMPORTED_LIBRARIES), CacheState.VALID);
- expect(entry1.getState(EXPORTED_LIBRARIES), CacheState.VALID);
- expect(entry1.getState(INCLUDED_PARTS), CacheState.VALID);
- }
-
- void test_onResultInvalidated_scheduleInvalidatedLibraries() {
- // make source3 implicit
- entry3.explicitlyAdded = false;
- // set SOURCE_KIND
- entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- entry2.setValue(SOURCE_KIND, SourceKind.PART, []);
- entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
- // set LIBRARY_ERRORS_READY for source1 and source3
- entry1.setValue(LIBRARY_ERRORS_READY, true, []);
- entry3.setValue(LIBRARY_ERRORS_READY, true, []);
- // invalidate LIBRARY_ERRORS_READY for source1, schedule it
- entry1.setState(LIBRARY_ERRORS_READY, CacheState.INVALID);
- expect_librarySourceQueue([source1]);
- // invalidate LIBRARY_ERRORS_READY for source3, implicit, not scheduled
- entry3.setState(LIBRARY_ERRORS_READY, CacheState.INVALID);
- expect_librarySourceQueue([source1]);
- }
-
- void test_onSourceFactoryChanged() {
- context.everythingExists = true;
- // set cache values
- entry1.setValue(PARSED_UNIT, AstTestFactory.compilationUnit(), []);
- entry1.setValue(IMPORTED_LIBRARIES, <Source>[], []);
- entry1.setValue(EXPLICITLY_IMPORTED_LIBRARIES, <Source>[], []);
- entry1.setValue(EXPORTED_LIBRARIES, <Source>[], []);
- entry1.setValue(INCLUDED_PARTS, <Source>[], []);
- entry1.setValue(LIBRARY_SPECIFIC_UNITS, <LibrarySpecificUnit>[], []);
- entry1.setValue(UNITS, <Source>[], []);
- // configure LibrarySpecificUnit
- LibrarySpecificUnit unitTarget = new LibrarySpecificUnit(source2, source3);
- CacheEntry unitEntry = new CacheEntry(unitTarget);
- cache.put(unitEntry);
- unitEntry.setValue(BUILD_LIBRARY_ERRORS, <AnalysisError>[], []);
- expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.VALID);
- // notify
- manager.onSourceFactoryChanged();
- // resolution is invalidated
- expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.INVALID);
- // ...and URIs resolution too
- expect(entry1.getState(PARSED_UNIT), CacheState.INVALID);
- expect(entry1.getState(IMPORTED_LIBRARIES), CacheState.INVALID);
- expect(entry1.getState(EXPLICITLY_IMPORTED_LIBRARIES), CacheState.INVALID);
- expect(entry1.getState(EXPORTED_LIBRARIES), CacheState.INVALID);
- expect(entry1.getState(INCLUDED_PARTS), CacheState.INVALID);
- expect(entry1.getState(LIBRARY_SPECIFIC_UNITS), CacheState.INVALID);
- expect(entry1.getState(UNITS), CacheState.INVALID);
- }
-
- void test_resultsComputed_errors_forLibrarySpecificUnit() {
- LineInfo lineInfo = new LineInfo([0]);
- AnalysisError error1 =
- new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
- AnalysisError error2 =
- new AnalysisError(source1, 2, 0, ScannerErrorCode.MISSING_DIGIT);
- context.getLibrariesContainingMap[source1] = <Source>[source2];
- context.errorsMap[source1] =
- new AnalysisErrorInfoImpl([error1, error2], lineInfo);
- entry1.setValue(LINE_INFO, lineInfo, []);
- entry1.setValue(SCAN_ERRORS, <AnalysisError>[error1], []);
- AnalysisTarget unitTarget = new LibrarySpecificUnit(source2, source1);
- context
- .getCacheEntry(unitTarget)
- .setValue(VERIFY_ERRORS, <AnalysisError>[error2], []);
- // RESOLVED_UNIT is ready, set errors
- manager.resultsComputed(
- unitTarget, {RESOLVED_UNIT: AstTestFactory.compilationUnit()});
- // all of the errors are included
- ChangeNoticeImpl notice = context.getNotice(source1);
- expect(notice.errors, unorderedEquals([error1, error2]));
- expect(notice.lineInfo, lineInfo);
- }
-
- void test_resultsComputed_errors_forSource() {
- LineInfo lineInfo = new LineInfo([0]);
- AnalysisError error1 =
- new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
- AnalysisError error2 =
- new AnalysisError(source1, 2, 0, ScannerErrorCode.MISSING_DIGIT);
- context.getLibrariesContainingMap[source1] = <Source>[source2];
- context.errorsMap[source1] =
- new AnalysisErrorInfoImpl([error1, error2], lineInfo);
- entry1.setValue(LINE_INFO, lineInfo, []);
- entry1.setValue(SCAN_ERRORS, <AnalysisError>[error1], []);
- entry1.setValue(PARSE_ERRORS, <AnalysisError>[error2], []);
- // PARSED_UNIT is ready, set errors
- manager.resultsComputed(
- source1, {PARSED_UNIT: AstTestFactory.compilationUnit()});
- // all of the errors are included
- ChangeNoticeImpl notice = context.getNotice(source1);
- expect(notice.errors, unorderedEquals([error1, error2]));
- expect(notice.lineInfo, lineInfo);
- }
-
- void test_resultsComputed_includedParts_updatePartLibraries() {
- Source part1 = new TestSource('part1.dart');
- Source part2 = new TestSource('part2.dart');
- Source part3 = new TestSource('part3.dart');
- Source library1 = new TestSource('library1.dart');
- Source library2 = new TestSource('library2.dart');
- _getOrCreateEntry(part1).setValue(CONTAINING_LIBRARIES, [], []);
- expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.VALID);
- // configure AnalysisContext mock
- context.prioritySources = <Source>[];
- context.analyzeAllErrors = false;
- // library1 parts
- manager.resultsComputed(library1, <ResultDescriptor, dynamic>{
- INCLUDED_PARTS: [part1, part2],
- SOURCE_KIND: SourceKind.LIBRARY
- });
- expect(manager.partLibrariesMap[part1], [library1]);
- expect(manager.partLibrariesMap[part2], [library1]);
- expect(manager.partLibrariesMap[part3], isNull);
- expect(manager.libraryPartsMap[library1], [part1, part2]);
- expect(manager.libraryPartsMap[library2], isNull);
- // library2 parts
- manager.resultsComputed(library2, <ResultDescriptor, dynamic>{
- INCLUDED_PARTS: [part2, part3],
- SOURCE_KIND: SourceKind.LIBRARY
- });
- expect(manager.partLibrariesMap[part1], [library1]);
- expect(manager.partLibrariesMap[part2], [library1, library2]);
- expect(manager.partLibrariesMap[part3], [library2]);
- expect(manager.libraryPartsMap[library1], [part1, part2]);
- expect(manager.libraryPartsMap[library2], [part2, part3]);
- // part1 CONTAINING_LIBRARIES
- expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.INVALID);
- }
-
- void test_resultsComputed_inSDK() {
- _DartWorkManagerMock sdkDartWorkManagerMock = new _DartWorkManagerMock();
- // SDK context mock
- _InternalAnalysisContextMock sdkContextMock =
- new _InternalAnalysisContextMock();
- sdkContextMock.workManagers = <WorkManager>[sdkDartWorkManagerMock];
- // SDK mock
- _DartSdkMock sdkMock = new _DartSdkMock();
- sdkMock.context = sdkContextMock;
- // SourceFactory mock
- _SourceFactoryMock sourceFactory = new _SourceFactoryMock();
- sourceFactory.dartSdk = sdkMock;
- context.sourceFactory = sourceFactory;
- // SDK source mock
- _SourceMock source = new _SourceMock('test.dart');
- source.source = source;
- source.isInSystemLibrary = true;
- // notify and validate
- Map<ResultDescriptor, dynamic> outputs = <ResultDescriptor, dynamic>{};
- manager.resultsComputed(source, outputs);
- var bySourceMap = sdkDartWorkManagerMock.resultsComputedCounts[source];
- expect(bySourceMap, isNotNull);
- expect(bySourceMap[outputs], 1);
- }
-
- void test_resultsComputed_noSourceKind() {
- manager.unknownSourceQueue.addAll([source1, source2]);
- manager.resultsComputed(source1, {});
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([source1, source2]);
- }
-
- void test_resultsComputed_notDart() {
- manager.unknownSourceQueue.addAll([source1, source2]);
- manager.resultsComputed(new TestSource('test.html'), {});
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([source1, source2]);
- }
-
- void test_resultsComputed_parsedUnit() {
- LineInfo lineInfo = new LineInfo([0]);
- context.getLibrariesContainingMap[source1] = <Source>[];
- context.errorsMap[source1] = new AnalysisErrorInfoImpl([], lineInfo);
- entry1.setValue(LINE_INFO, lineInfo, []);
- CompilationUnit unit = AstTestFactory.compilationUnit();
- manager.resultsComputed(source1, {PARSED_UNIT: unit});
- ChangeNoticeImpl notice = context.getNotice(source1);
- expect(notice.parsedDartUnit, unit);
- expect(notice.resolvedDartUnit, isNull);
- expect(notice.lineInfo, lineInfo);
- }
-
- void test_resultsComputed_resolvedUnit() {
- LineInfo lineInfo = new LineInfo([0]);
- context.getLibrariesContainingMap[source2] = <Source>[];
- context.errorsMap[source2] = new AnalysisErrorInfoImpl([], lineInfo);
- entry2.setValue(LINE_INFO, lineInfo, []);
- CompilationUnit unit = AstTestFactory.compilationUnit();
- manager.resultsComputed(
- new LibrarySpecificUnit(source1, source2), {RESOLVED_UNIT: unit});
- ChangeNoticeImpl notice = context.getNotice(source2);
- expect(notice.parsedDartUnit, isNull);
- expect(notice.resolvedDartUnit, unit);
- expect(notice.lineInfo, lineInfo);
- }
-
- void test_resultsComputed_sourceKind_isLibrary() {
- manager.unknownSourceQueue.addAll([source1, source2, source3]);
- context.prioritySources = <Source>[];
- context.shouldErrorsBeAnalyzedMap[source2] = true;
- manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.LIBRARY});
- expect_librarySourceQueue([source2]);
- expect_unknownSourceQueue([source1, source3]);
- }
-
- void test_resultsComputed_sourceKind_isLibrary_isPriority_computeErrors() {
- manager.unknownSourceQueue.addAll([source1, source2, source3]);
- context.prioritySources = <Source>[source2];
- context.shouldErrorsBeAnalyzedMap[source2] = true;
- manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.LIBRARY});
- expect_unknownSourceQueue([source1, source3]);
- expect(manager.priorityResultQueue,
- unorderedEquals([new TargetedResult(source2, LIBRARY_ERRORS_READY)]));
- }
-
- void test_resultsComputed_sourceKind_isLibrary_isPriority_computeUnit() {
- manager.unknownSourceQueue.addAll([source1, source2, source3]);
- context.prioritySources = <Source>[source2];
- context.shouldErrorsBeAnalyzedMap[source2] = false;
- manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.LIBRARY});
- expect_unknownSourceQueue([source1, source3]);
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(
- new LibrarySpecificUnit(source2, source2), RESOLVED_UNIT)
- ]));
- }
-
- void test_resultsComputed_sourceKind_isPart() {
- manager.unknownSourceQueue.addAll([source1, source2, source3]);
- manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.PART});
- expect_librarySourceQueue([]);
- expect_unknownSourceQueue([source1, source3]);
- }
-
- void test_resultsComputed_updatePartsLibraries_partParsed() {
- Source part = new TestSource('part.dart');
- expect(manager.libraryPartsMap, isEmpty);
- // part.dart parsed, no changes is the map of libraries
- manager.resultsComputed(part, <ResultDescriptor, dynamic>{
- SOURCE_KIND: SourceKind.PART,
- INCLUDED_PARTS: <Source>[]
- });
- expect(manager.libraryPartsMap, isEmpty);
- }
-
- void test_unitIncrementallyResolved() {
- manager.unitIncrementallyResolved(source1, source2);
- expect_librarySourceQueue([source1]);
- }
-
- CacheEntry _getOrCreateEntry(Source source, [bool explicit = true]) {
- CacheEntry entry = cache.get(source);
- if (entry == null) {
- entry = new CacheEntry(source);
- entry.explicitlyAdded = explicit;
- cache.put(entry);
- }
- return entry;
- }
-}
-
-class _DartSdkMock implements DartSdk {
- AnalysisContext context;
-
- @override
- noSuchMethod(Invocation invocation) {
- throw new StateError('Unexpected invocation of ${invocation.memberName}');
- }
-}
-
-class _DartWorkManagerMock implements DartWorkManager {
- Map<Source, List<Source>> librariesContainingPartMap =
- <Source, List<Source>>{};
-
- Map<Source, Map<Map<ResultDescriptor, dynamic>, int>> resultsComputedCounts =
- <Source, Map<Map<ResultDescriptor, dynamic>, int>>{};
-
- @override
- List<Source> getLibrariesContainingPart(Source part) {
- return librariesContainingPartMap[part] ?? <Source>[];
- }
-
- @override
- noSuchMethod(Invocation invocation) {
- throw new StateError('Unexpected invocation of ${invocation.memberName}');
- }
-
- @override
- void resultsComputed(
- AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs) {
- Map<Map<ResultDescriptor, dynamic>, int> bySourceMap =
- resultsComputedCounts.putIfAbsent(target, () => {});
- bySourceMap[outputs] = (bySourceMap[outputs] ?? 0) + 1;
- }
-}
-
-class _InternalAnalysisContextMock implements InternalAnalysisContext {
- @override
- CachePartition privateAnalysisCachePartition;
-
- @override
- AnalysisCache analysisCache;
-
- @override
- SourceFactory sourceFactory;
-
- bool analyzeAllErrors;
-
- bool everythingExists = false;
-
- bool aboutToComputeEverything;
-
- @override
- List<Source> prioritySources = <Source>[];
-
- @override
- List<WorkManager> workManagers = <WorkManager>[];
-
- Map<Source, List<Source>> getLibrariesContainingMap =
- <Source, List<Source>>{};
-
- Map<Source, bool> shouldErrorsBeAnalyzedMap = <Source, bool>{};
-
- Map<ResultDescriptor, bool Function(CacheEntry entry, ResultDescriptor)>
- aboutToComputeResultMap =
- <ResultDescriptor, bool Function(CacheEntry entry, ResultDescriptor)>{};
-
- Map<Source, AnalysisErrorInfo> errorsMap = <Source, AnalysisErrorInfo>{};
-
- Map<Source, ChangeNoticeImpl> _pendingNotices = <Source, ChangeNoticeImpl>{};
-
- @override
- final AnalysisOptions analysisOptions = new AnalysisOptionsImpl();
-
- @override
- final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
- new ReentrantSynchronousStream<InvalidatedResult>();
-
- _InternalAnalysisContextMock() {
- privateAnalysisCachePartition = new UniversalCachePartition(this);
- analysisCache = new AnalysisCache([privateAnalysisCachePartition]);
- analysisCache.onResultInvalidated.listen((InvalidatedResult event) {
- onResultInvalidated.add(event);
- });
- }
-
- @override
- bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
- if (aboutToComputeEverything != null) {
- return aboutToComputeEverything;
- }
- bool Function(CacheEntry entry, ResultDescriptor) function =
- aboutToComputeResultMap[result];
- if (function == null) {
- return false;
- }
- return function(entry, result);
- }
-
- @override
- bool exists(Source source) {
- return everythingExists;
- }
-
- @override
- CacheEntry getCacheEntry(AnalysisTarget target) {
- CacheEntry entry = analysisCache.get(target);
- if (entry == null) {
- entry = new CacheEntry(target);
- analysisCache.put(entry);
- }
- return entry;
- }
-
- @override
- AnalysisErrorInfo getErrors(Source source) => errorsMap[source];
-
- List<Source> getLibrariesContaining(Source source) {
- return getLibrariesContainingMap[source];
- }
-
- @override
- ChangeNoticeImpl getNotice(Source source) {
- return _pendingNotices.putIfAbsent(
- source, () => new ChangeNoticeImpl(source));
- }
-
- @override
- noSuchMethod(Invocation invocation) {
- throw new StateError('Unexpected invocation of ${invocation.memberName}');
- }
-
- void setShouldErrorsBeAnalyzed(Source source, bool value) {
- shouldErrorsBeAnalyzedMap[source] = value;
- }
-
- @override
- bool shouldErrorsBeAnalyzed(Source source) {
- if (analyzeAllErrors != null) {
- return analyzeAllErrors;
- }
- return shouldErrorsBeAnalyzedMap[source];
- }
-}
-
-class _SourceFactoryMock implements SourceFactory {
- DartSdk dartSdk;
-
- @override
- noSuchMethod(Invocation invocation) {
- throw new StateError('Unexpected invocation of ${invocation.memberName}');
- }
-}
-
-class _SourceMock implements Source {
- @override
- final String shortName;
-
- @override
- bool isInSystemLibrary = false;
-
- @override
- Source source;
-
- _SourceMock(this.shortName);
-
- @override
- String get fullName => '/' + shortName;
-
- @override
- noSuchMethod(Invocation invocation) {
- throw new StateError('Unexpected invocation of ${invocation.memberName}');
- }
-
- @override
- String toString() => fullName;
-}
diff --git a/pkg/analyzer/test/src/task/general_test.dart b/pkg/analyzer/test/src/task/general_test.dart
deleted file mode 100644
index e5e3b2b..0000000
--- a/pkg/analyzer/test/src/task/general_test.dart
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/general.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(GetContentTaskTest);
- });
-}
-
-@reflectiveTest
-class GetContentTaskTest extends EngineTestCase {
- test_buildInputs() {
- AnalysisTarget target = new TestSource();
- Map<String, TaskInput> inputs = GetContentTask.buildInputs(target);
- expect(inputs, isEmpty);
- }
-
- test_constructor() {
- AnalysisContext context = new _MockContext();
- AnalysisTarget target = new TestSource();
- GetContentTask task = new GetContentTask(context, target);
- expect(task, isNotNull);
- expect(task.context, context);
- expect(task.target, target);
- }
-
- test_createTask() {
- AnalysisContext context = new _MockContext();
- AnalysisTarget target = new TestSource();
- GetContentTask task = GetContentTask.createTask(context, target);
- expect(task, isNotNull);
- expect(task.context, context);
- expect(task.target, target);
- }
-
- test_descriptor() {
- AnalysisContext context = new _MockContext();
- AnalysisTarget target = new TestSource();
- GetContentTask task = new GetContentTask(context, target);
- expect(task.descriptor, GetContentTask.DESCRIPTOR);
- }
-
- test_perform() {
- _MockContext context = new _MockContext();
- Source target = new TestSource();
- GetContentTask task = new GetContentTask(context, target);
- context.getContentsResponse[target] =
- () => new TimestampedData<String>(42, 'foo');
- task.perform();
- expect(task.caughtException, isNull);
- expect(task.outputs, hasLength(2));
- expect(task.outputs[CONTENT], 'foo');
- expect(task.outputs[MODIFICATION_TIME], 42);
- }
-
- void test_perform_exception() {
- _MockContext context = new _MockContext();
- Source target = new TestSource();
- GetContentTask task = new GetContentTask(context, target);
- context.getContentsResponse[target] = () => throw 'My exception!';
- task.perform();
- expect(task.caughtException, isNull);
- expect(task.outputs, hasLength(2));
- expect(task.outputs[CONTENT], '');
- expect(task.outputs[MODIFICATION_TIME], -1);
- }
-}
-
-class _MockContext implements AnalysisContext {
- Map<Source, TimestampedData<String> Function()> getContentsResponse =
- <Source, TimestampedData<String> Function()>{};
-
- String get name => 'mock';
-
- @override
- TimestampedData<String> getContents(Source source) {
- TimestampedData<String> Function() response = getContentsResponse[source];
- if (response == null) {
- fail('Unexpected invocation of getContents');
- }
- return response();
- }
-
- @override
- noSuchMethod(Invocation invocation) {
- fail('Unexpected invocation of ${invocation.memberName}');
- }
-}
diff --git a/pkg/analyzer/test/src/task/inputs_test.dart b/pkg/analyzer/test/src/task/inputs_test.dart
deleted file mode 100644
index c8963d3..0000000
--- a/pkg/analyzer/test/src/task/inputs_test.dart
+++ /dev/null
@@ -1,1073 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/inputs.dart';
-import 'package:analyzer/src/task/model.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(ConstantTaskInputBuilderTest);
- defineReflectiveTests(ConstantTaskInputTest);
- defineReflectiveTests(ListTaskInputImplTest);
- defineReflectiveTests(ListToListTaskInputTest);
- defineReflectiveTests(ListToListTaskInputBuilderTest);
- defineReflectiveTests(ListToMapTaskInputBuilderTest);
- defineReflectiveTests(ListToMapTaskInputTest);
- defineReflectiveTests(ObjectToListTaskInputBuilderTest);
- defineReflectiveTests(ObjectToListTaskInputTest);
- defineReflectiveTests(SimpleTaskInputTest);
- defineReflectiveTests(SimpleTaskInputBuilderTest);
- defineReflectiveTests(TopLevelTaskInputBuilderTest);
- });
-}
-
-@reflectiveTest
-class ConstantTaskInputBuilderTest extends EngineTestCase {
- static final int value = 7;
- static final ConstantTaskInput<int> input = new ConstantTaskInput<int>(value);
-
- ConstantTaskInputBuilder builder;
-
- void setUp() {
- super.setUp();
- builder = new ConstantTaskInputBuilder(input);
- }
-
- test_create() {
- expect(builder, isNotNull);
- expect(builder.input, input);
- }
-
- test_currentResult_afterOneMoveNext() {
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_beforeMoveNext() {
- expect(builder.currentResult, null);
- }
-
- test_currentTarget_afterOneMoveNext() {
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_beforeMoveNext() {
- expect(builder.currentTarget, null);
- }
-
- test_currentValue_afterOneMoveNext() {
- builder.moveNext();
- expect(() {
- builder.currentValue = 'value';
- }, throwsStateError);
- }
-
- test_currentValue_beforeMoveNext() {
- expect(() {
- builder.currentValue = 'value';
- }, throwsStateError);
- }
-
- test_currentValueNotAvailable_afterOneMoveNext() {
- builder.moveNext();
- expect(() {
- builder.currentValueNotAvailable();
- }, throwsStateError);
- }
-
- test_currentValueNotAvailable_beforeMoveNext() {
- expect(() {
- builder.currentValueNotAvailable();
- }, throwsStateError);
- }
-
- test_inputValue_afterOneMoveNext() {
- builder.moveNext();
- expect(builder.inputValue, value);
- }
-
- test_inputValue_beforeMoveNext() {
- expect(builder.inputValue, value);
- }
-
- test_moveNext() {
- expect(builder.moveNext(), false);
- expect(builder.moveNext(), false);
- }
-}
-
-@reflectiveTest
-class ConstantTaskInputTest extends EngineTestCase {
- test_create() {
- int value = 3;
- ConstantTaskInput<int> input = new ConstantTaskInput<int>(value);
- expect(input, isNotNull);
- expect(input.value, value);
- }
-
- test_createBuilder() {
- ConstantTaskInput<int> input = new ConstantTaskInput<int>(5);
- expect(input.createBuilder(), new TypeMatcher<ConstantTaskInputBuilder>());
- }
-}
-
-@reflectiveTest
-class ListTaskInputImplTest extends EngineTestCase {
- static final AnalysisTarget target = new TestSource();
- static final ResultDescriptor<List<AnalysisTarget>> result1 =
- new ResultDescriptorImpl<List<AnalysisTarget>>('result1', null);
- static final result2 = new ResultDescriptorImpl<int>('result2', null);
-
- test_create() {
- var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
- expect(input, isNotNull);
- expect(input.target, target);
- expect(input.result, result1);
- }
-
- test_createBuilder() {
- var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
- expect(input.createBuilder(), new TypeMatcher<SimpleTaskInputBuilder>());
- }
-
- test_toList() {
- var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
- ListTaskInput<String> input2 =
- input.toList((target) => new SimpleTaskInput<String>(target, null));
- expect(
- input2, new TypeMatcher<ListToListTaskInput<AnalysisTarget, String>>());
- }
-
- test_toListOf() {
- var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
- ListTaskInput<int> input2 = input.toListOf(result2);
- expect(input2, new TypeMatcher<ListToListTaskInput<AnalysisTarget, int>>());
- }
-
- test_toMap() {
- var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
- MapTaskInput<AnalysisTarget, String> input2 =
- input.toMap((target) => new SimpleTaskInput<String>(target, null));
- expect(
- input2, new TypeMatcher<ListToMapTaskInput<AnalysisTarget, String>>());
- }
-
- test_toMapOf() {
- var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
- MapTaskInput<AnalysisTarget, int> input2 = input.toMapOf(result2);
- expect(input2, new TypeMatcher<ListToMapTaskInput<AnalysisTarget, int>>());
- }
-}
-
-@reflectiveTest
-class ListToListTaskInputBuilderTest extends EngineTestCase {
- static final AnalysisTarget target1 = new TestSource();
- static final ResultDescriptorImpl<List> result1 =
- new ResultDescriptorImpl<List>('result1', null);
- static final ResultDescriptorImpl result2 =
- new ResultDescriptorImpl('result2', null);
- static final ListToListTaskInput input = new ListToListTaskInput(
- result1.of(target1), (element) => result2.of(element));
-
- test_create() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- expect(builder, isNotNull);
- expect(builder.input, input);
- }
-
- test_currentResult_afterComplete() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValue = [];
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterCurrentValueNotAvailable() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterOneMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext();
- expect(builder.currentResult, result1);
- }
-
- test_currentResult_beforeMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- expect(builder.currentResult, null);
- }
-
- test_currentTarget_afterComplete() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValue = [];
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterCurrentValueNotAvailable() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterOneMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext();
- expect(builder.currentTarget, target1);
- }
-
- test_currentTarget_beforeMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- expect(builder.currentTarget, null);
- }
-
- test_currentValue_afterOneMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValue = [];
- }
-
- test_currentValue_beforeMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- expect(() {
- builder.currentValue = [];
- }, throwsStateError);
- }
-
- test_currentValueNotAvailable_afterOneMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValueNotAvailable();
- }
-
- test_currentValueNotAvailable_beforeMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- expect(() {
- builder.currentValueNotAvailable();
- }, throwsStateError);
- }
-
- test_inputValue_afterComplete() {
- AnalysisTarget target2 = new TestSource();
- AnalysisTarget target3 = new TestSource();
- String value2 = 'value2';
- String value3 = 'value3';
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext(); // Advance to requesting the list
- builder.currentValue = [target2, target3];
- builder.moveNext(); // Advance to requesting result2 for target2
- builder.currentValue = value2;
- builder.moveNext(); // Advance to requesting result2 for target3
- builder.currentValue = value3;
- builder.moveNext(); // Advance to the end
- var inputValue = builder.inputValue;
- expect(inputValue, new TypeMatcher<List>());
- List list = inputValue;
- expect(list.length, 2);
- expect(list[0], value2);
- expect(list[1], value3);
- }
-
- test_inputValue_afterFirstValueNotAvailable() {
- AnalysisTarget target2 = new TestSource();
- AnalysisTarget target3 = new TestSource();
- String value3 = 'value3';
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext(); // Advance to requesting the list
- builder.currentValue = [target2, target3];
- builder.moveNext(); // Advance to requesting result2 for target2
- builder.currentValueNotAvailable();
- builder.moveNext(); // Advance to requesting result2 for target3
- builder.currentValue = value3;
- builder.moveNext(); // Advance to the end
- var inputValue = builder.inputValue;
- expect(inputValue, new TypeMatcher<List>());
- List list = inputValue;
- expect(list, orderedEquals([value3]));
- }
-
- test_inputValue_afterListNotAvailable() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext(); // Advance to requesting the list
- builder.currentValueNotAvailable();
- builder.moveNext(); // Advance to the end
- var inputValue = builder.inputValue;
- expect(inputValue, new TypeMatcher<List>());
- List list = inputValue;
- expect(list, isEmpty);
- }
-
- test_inputValue_afterOneMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- builder.moveNext();
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_inputValue_beforeMoveNext() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_moveNext_withoutSet() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- expect(builder.moveNext(), true);
- expect(() => builder.moveNext(), throwsStateError);
- }
-
- test_moveNext_withSet() {
- ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
- expect(builder.moveNext(), true);
- builder.currentValue = [];
- expect(builder.moveNext(), false);
- expect(builder.moveNext(), false);
- }
-}
-
-@reflectiveTest
-class ListToListTaskInputTest extends EngineTestCase {
- static final AnalysisTarget target = new TestSource();
- static final ResultDescriptorImpl<List> result =
- new ResultDescriptorImpl<List>('result', null);
-
- test_create() {
- SimpleTaskInput<List> baseAccessor = result.of(target);
- GenerateTaskInputs generate = (object) => null;
- ListToListTaskInput input = new ListToListTaskInput(baseAccessor, generate);
- expect(input, isNotNull);
- expect(input.baseAccessor, baseAccessor);
- expect(input.generateTaskInputs, equals(generate));
- }
-
- test_createBuilder() {
- SimpleTaskInput<List> baseAccessor = result.of(target);
- GenerateTaskInputs generate = (object) => null;
- ListToListTaskInput input = new ListToListTaskInput(baseAccessor, generate);
- expect(input.createBuilder(), isNotNull);
- }
-}
-
-@reflectiveTest
-class ListToMapTaskInputBuilderTest extends EngineTestCase {
- static final AnalysisTarget target1 = new TestSource('target1');
- static final ResultDescriptorImpl<List> result1 =
- new ResultDescriptorImpl<List>('result1', null);
- static final ResultDescriptorImpl result2 =
- new ResultDescriptorImpl('result2', null);
- static final ListToMapTaskInput input = new ListToMapTaskInput(
- result1.of(target1), (element) => result2.of(element));
-
- test_create() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- expect(builder, isNotNull);
- expect(builder.input, input);
- }
-
- test_currentResult_afterComplete() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValue = [];
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterCurrentValueNotAvailable() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterOneMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext();
- expect(builder.currentResult, result1);
- }
-
- test_currentResult_beforeMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- expect(builder.currentResult, null);
- }
-
- test_currentTarget_afterComplete() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValue = [];
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterCurrentValueNotAvailable() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterOneMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext();
- expect(builder.currentTarget, target1);
- }
-
- test_currentTarget_beforeMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- expect(builder.currentTarget, null);
- }
-
- test_currentValue_afterOneMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValue = [];
- }
-
- test_currentValue_beforeMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- expect(() {
- builder.currentValue = [];
- }, throwsStateError);
- }
-
- test_currentValueNotAvailable_afterOneMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext();
- builder.currentValueNotAvailable();
- }
-
- test_currentValueNotAvailable_beforeMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- expect(() {
- builder.currentValueNotAvailable();
- }, throwsStateError);
- }
-
- test_inputValue_afterComplete() {
- AnalysisTarget target2 = new TestSource('target2');
- AnalysisTarget target3 = new TestSource('target3');
- String value2 = 'value2';
- String value3 = 'value3';
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext(); // Advance to requesting the list
- builder.currentValue = [target2, target3];
- builder.moveNext(); // Advance to requesting result2 for target2
- builder.currentValue = value2;
- builder.moveNext(); // Advance to requesting result2 for target3
- builder.currentValue = value3;
- builder.moveNext(); // Advance to the end
- var inputValue = builder.inputValue;
- expect(inputValue, new TypeMatcher<Map>());
- expect(inputValue.length, 2);
- expect(inputValue, containsPair(target2, value2));
- expect(inputValue, containsPair(target3, value3));
- }
-
- test_inputValue_afterFirstValueNotAvailable() {
- AnalysisTarget target2 = new TestSource('target2');
- AnalysisTarget target3 = new TestSource('target3');
- String value3 = 'value3';
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext(); // Advance to requesting the list
- builder.currentValue = [target2, target3];
- builder.moveNext(); // Advance to requesting result2 for target2
- builder.currentValueNotAvailable();
- builder.moveNext(); // Advance to requesting result2 for target3
- builder.currentValue = value3;
- builder.moveNext(); // Advance to the end
- var inputValue = builder.inputValue;
- expect(inputValue, new TypeMatcher<Map>());
- expect(inputValue, hasLength(1));
- expect(inputValue, containsPair(target3, value3));
- }
-
- test_inputValue_afterListNotAvailable() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext(); // Advance to requesting the list
- builder.currentValueNotAvailable();
- builder.moveNext(); // Advance to the end
- var inputValue = builder.inputValue;
- expect(inputValue, new TypeMatcher<Map>());
- expect(inputValue, isEmpty);
- }
-
- test_inputValue_afterOneMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- builder.moveNext();
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_inputValue_beforeMoveNext() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_moveNext_withoutSet() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- expect(builder.moveNext(), true);
- expect(() => builder.moveNext(), throwsStateError);
- }
-
- test_moveNext_withSet() {
- ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
- expect(builder.moveNext(), true);
- builder.currentValue = [];
- expect(builder.moveNext(), false);
- expect(builder.moveNext(), false);
- }
-}
-
-@reflectiveTest
-class ListToMapTaskInputTest extends EngineTestCase {
- static final AnalysisTarget target = new TestSource();
- static final ResultDescriptorImpl<List> result =
- new ResultDescriptorImpl<List>('result', null);
-
- test_create() {
- SimpleTaskInput<List> baseAccessor = result.of(target);
- GenerateTaskInputs generate = (object) => null;
- ListToMapTaskInput input = new ListToMapTaskInput(baseAccessor, generate);
- expect(input, isNotNull);
- expect(input.baseAccessor, baseAccessor);
- expect(input.generateTaskInputs, equals(generate));
- }
-
- test_createBuilder() {
- SimpleTaskInput<List> baseAccessor = result.of(target);
- GenerateTaskInputs generate = (object) => null;
- ListToMapTaskInput input = new ListToMapTaskInput(baseAccessor, generate);
- expect(input.createBuilder(), isNotNull);
- }
-}
-
-@reflectiveTest
-class ObjectToListTaskInputBuilderTest {
- static final AnalysisTarget target = new TestSource();
- static final ResultDescriptorImpl result =
- new ResultDescriptorImpl('result', null);
- static final SimpleTaskInput baseInput = new SimpleTaskInput(target, result);
- static final mapper = (Object x) => [x];
- static final ObjectToListTaskInput input =
- new ObjectToListTaskInput(baseInput, mapper);
-
- ObjectToListTaskInputBuilder builder;
-
- void setUp() {
- builder = new ObjectToListTaskInputBuilder(input);
- }
-
- test_create() {
- expect(builder, isNotNull);
- expect(builder.input, input);
- }
-
- test_currentResult_afterComplete() {
- builder.moveNext();
- builder.currentValue = 'value';
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterCurrentValueNotAvailable() {
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterOneMoveNext() {
- builder.moveNext();
- expect(builder.currentResult, result);
- }
-
- test_currentResult_beforeMoveNext() {
- expect(builder.currentResult, null);
- }
-
- test_currentTarget_afterComplete() {
- builder.moveNext();
- builder.currentValue = 'value';
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterCurrentValueNotAvailable() {
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterOneMoveNext() {
- builder.moveNext();
- expect(builder.currentTarget, target);
- }
-
- test_currentTarget_beforeMoveNext() {
- expect(builder.currentTarget, null);
- }
-
- test_currentValue_afterOneMoveNext() {
- builder.moveNext();
- builder.currentValue = 'value';
- }
-
- test_currentValue_beforeMoveNext() {
- expect(() {
- builder.currentValue = 'value';
- }, throwsStateError);
- }
-
- test_currentValueNotAvailable_afterOneMoveNext() {
- builder.moveNext();
- builder.currentValueNotAvailable();
- }
-
- test_currentValueNotAvailable_beforeMoveNext() {
- expect(() {
- builder.currentValueNotAvailable();
- }, throwsStateError);
- }
-
- test_inputValue_afterComplete() {
- builder.moveNext();
- String value = 'value';
- builder.currentValue = value;
- builder.moveNext();
- expect(builder.inputValue, [value]);
- }
-
- test_inputValue_afterCurrentValueNotAvailable() {
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.inputValue, [null]);
- }
-
- test_inputValue_afterOneMoveNext() {
- builder.moveNext();
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_inputValue_beforeMoveNext() {
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_moveNext_withoutSet() {
- expect(builder.moveNext(), true);
- expect(() => builder.moveNext(), throwsStateError);
- }
-
- test_moveNext_withSet() {
- expect(builder.moveNext(), true);
- builder.currentValue = 'value';
- expect(builder.moveNext(), false);
- expect(builder.moveNext(), false);
- }
-}
-
-@reflectiveTest
-class ObjectToListTaskInputTest extends EngineTestCase {
- static final AnalysisTarget target = new TestSource();
- static final ResultDescriptorImpl result =
- new ResultDescriptorImpl('result', null);
-
- test_create() {
- SimpleTaskInput baseInput = new SimpleTaskInput(target, result);
- var mapper = (Object x) => [x];
- ObjectToListTaskInput input = new ObjectToListTaskInput(baseInput, mapper);
- expect(input, isNotNull);
- expect(input.baseInput, baseInput);
- expect(input.mapper, equals(mapper));
- }
-
- test_createBuilder() {
- SimpleTaskInput baseInput = new SimpleTaskInput(target, result);
- var mapper = (Object x) => [x];
- ObjectToListTaskInput input = new ObjectToListTaskInput(baseInput, mapper);
- expect(
- input.createBuilder(), new TypeMatcher<ObjectToListTaskInputBuilder>());
- }
-}
-
-@reflectiveTest
-class SimpleTaskInputBuilderTest {
- static final AnalysisTarget target = new TestSource();
- static final ResultDescriptorImpl result =
- new ResultDescriptorImpl('result', null);
- static final SimpleTaskInput input = new SimpleTaskInput(target, result);
-
- SimpleTaskInputBuilder builder;
-
- void setUp() {
- builder = new SimpleTaskInputBuilder(input);
- }
-
- test_create() {
- expect(builder, isNotNull);
- expect(builder.input, input);
- }
-
- test_currentResult_afterComplete() {
- builder.moveNext();
- builder.currentValue = 'value';
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterCurrentValueNotAvailable() {
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterOneMoveNext() {
- builder.moveNext();
- expect(builder.currentResult, result);
- }
-
- test_currentResult_beforeMoveNext() {
- expect(builder.currentResult, null);
- }
-
- test_currentTarget_afterComplete() {
- builder.moveNext();
- builder.currentValue = 'value';
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterCurrentValueNotAvailable() {
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterOneMoveNext() {
- builder.moveNext();
- expect(builder.currentTarget, target);
- }
-
- test_currentTarget_beforeMoveNext() {
- expect(builder.currentTarget, null);
- }
-
- test_currentValue_afterOneMoveNext() {
- builder.moveNext();
- builder.currentValue = 'value';
- }
-
- test_currentValue_beforeMoveNext() {
- expect(() {
- builder.currentValue = 'value';
- }, throwsStateError);
- }
-
- test_currentValueNotAvailable_afterOneMoveNext() {
- builder.moveNext();
- builder.currentValueNotAvailable();
- }
-
- test_currentValueNotAvailable_beforeMoveNext() {
- expect(() {
- builder.currentValueNotAvailable();
- }, throwsStateError);
- }
-
- test_inputValue_afterComplete() {
- builder.moveNext();
- String value = 'value';
- builder.currentValue = value;
- builder.moveNext();
- expect(builder.inputValue, value);
- }
-
- test_inputValue_afterCurrentValueNotAvailable() {
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.inputValue, isNull);
- }
-
- test_inputValue_afterOneMoveNext() {
- builder.moveNext();
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_inputValue_beforeMoveNext() {
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_moveNext_withoutSet() {
- expect(builder.moveNext(), true);
- expect(() => builder.moveNext(), throwsStateError);
- }
-
- test_moveNext_withSet() {
- expect(builder.moveNext(), true);
- builder.currentValue = 'value';
- expect(builder.moveNext(), false);
- expect(builder.moveNext(), false);
- }
-}
-
-@reflectiveTest
-class SimpleTaskInputTest extends EngineTestCase {
- static final AnalysisTarget target = new TestSource();
- static final ResultDescriptorImpl result =
- new ResultDescriptorImpl('result', null);
-
- test_create() {
- SimpleTaskInput input = new SimpleTaskInput(target, result);
- expect(input, isNotNull);
- expect(input.target, target);
- expect(input.result, result);
- }
-
- test_createBuilder() {
- SimpleTaskInput input = new SimpleTaskInput(target, result);
- expect(input.createBuilder(), new TypeMatcher<SimpleTaskInputBuilder>());
- }
-}
-
-@reflectiveTest
-class TopLevelTaskInputBuilderTest extends EngineTestCase {
- static final AnalysisTarget target = new TestSource();
- static final ResultDescriptorImpl result1 =
- new ResultDescriptorImpl('result1', null);
- static final ResultDescriptorImpl result2 =
- new ResultDescriptorImpl('result2', null);
- static final SimpleTaskInput input1 = new SimpleTaskInput(target, result1);
- static final SimpleTaskInput input2 = new SimpleTaskInput(target, result2);
-
- test_create() {
- Map<String, TaskInput> inputDescriptors = {};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- expect(builder, isNotNull);
- expect(builder.inputDescriptors, inputDescriptors);
- }
-
- test_currentResult_afterComplete() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- builder.currentValue = 'value1';
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterCurrentValueNotAvailable() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentResult, null);
- }
-
- test_currentResult_afterOneMoveNext() {
- Map<String, TaskInput> inputDescriptors = {'one': input1, 'two': input2};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- expect(builder.currentResult, result1);
- }
-
- test_currentResult_afterTwoMoveNext_withConstantInput() {
- ConstantTaskInput<int> constantInput = new ConstantTaskInput<int>(11);
- Map<String, TaskInput> inputDescriptors = <String, TaskInput>{
- 'one': input1,
- 'constant': constantInput,
- 'two': input2
- };
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- builder.currentValue = 'value1';
- builder.moveNext();
- expect(builder.currentResult, result2);
- }
-
- test_currentResult_beforeMoveNext() {
- Map<String, TaskInput> inputDescriptors = {};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- expect(builder.currentResult, null);
- }
-
- test_currentTarget_afterComplete() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- builder.currentValue = 'value1';
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterCurrentValueNotAvailable() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- builder.currentValueNotAvailable();
- builder.moveNext();
- expect(builder.currentTarget, null);
- }
-
- test_currentTarget_afterOneMoveNext() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- expect(builder.currentTarget, target);
- }
-
- test_currentTarget_afterTwoMoveNext_withConstantInput() {
- ConstantTaskInput<int> constantInput = new ConstantTaskInput<int>(11);
- Map<String, TaskInput> inputDescriptors = <String, TaskInput>{
- 'one': input1,
- 'constant': constantInput,
- 'two': input2
- };
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- builder.currentValue = 'value1';
- builder.moveNext();
- expect(builder.currentTarget, target);
- }
-
- test_currentTarget_beforeMoveNext() {
- Map<String, TaskInput> inputDescriptors = {};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- expect(builder.currentTarget, null);
- }
-
- test_currentValue_afterOneMoveNext() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- builder.currentValue = 'value1';
- }
-
- test_currentValue_beforeMoveNext() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- expect(() {
- builder.currentValue = 'value1';
- }, throwsStateError);
- }
-
- test_currentValueNotAvailable_afterOneMoveNext() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- builder.currentValueNotAvailable();
- }
-
- test_currentValueNotAvailable_beforeMoveNext() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- expect(() {
- builder.currentValueNotAvailable();
- }, throwsStateError);
- }
-
- test_inputValue_afterComplete() {
- String key1 = 'one';
- String key2 = 'two';
- String value1 = 'value1';
- String value2 = 'value2';
- Map<String, TaskInput> inputDescriptors = {key1: input1, key2: input2};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext(); // Advance to requesting result1 for target
- builder.currentValue = value1;
- builder.moveNext(); // Advance to requesting result2 for target
- builder.currentValue = value2;
- builder.moveNext(); // Advance to the end
- var inputValue = builder.inputValue;
- expect(inputValue, new TypeMatcher<Map>());
- Map inputs = inputValue;
- expect(inputs.length, 2);
- expect(inputs, containsPair(key1, value1));
- expect(inputs, containsPair(key2, value2));
- }
-
- test_inputValue_afterOneMoveNext() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext();
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_inputValue_afterOneValueNotAvailable() {
- String key1 = 'one';
- String key2 = 'two';
- String value2 = 'value2';
- Map<String, TaskInput> inputDescriptors = {key1: input1, key2: input2};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- builder.moveNext(); // Advance to requesting result1 for target
- builder.currentValueNotAvailable();
- builder.moveNext(); // Advance to requesting result2 for target
- builder.currentValue = value2;
- builder.moveNext(); // Advance to the end
- var inputValue = builder.inputValue;
- expect(inputValue, new TypeMatcher<Map>());
- Map inputs = inputValue;
- expect(inputs, hasLength(1));
- expect(inputs, containsPair(key2, value2));
- }
-
- test_inputValue_beforeMoveNext() {
- Map<String, TaskInput> inputDescriptors = {};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- expect(() => builder.inputValue, throwsStateError);
- }
-
- test_moveNext_withoutSet() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- expect(builder.moveNext(), true);
- expect(() => builder.moveNext(), throwsStateError);
- }
-
- test_moveNext_withSet() {
- Map<String, TaskInput> inputDescriptors = {'one': input1};
- TopLevelTaskInputBuilder builder =
- new TopLevelTaskInputBuilder(inputDescriptors);
- expect(builder.moveNext(), true);
- builder.currentValue = 'value1';
- expect(builder.moveNext(), false);
- expect(builder.moveNext(), false);
- }
-}
diff --git a/pkg/analyzer/test/src/task/manager_test.dart b/pkg/analyzer/test/src/task/manager_test.dart
deleted file mode 100644
index b91e829..0000000
--- a/pkg/analyzer/test/src/task/manager_test.dart
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/manager.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(TaskManagerTest);
- });
-}
-
-@reflectiveTest
-class TaskManagerTest extends EngineTestCase {
- static final ResultDescriptor result1 = new ResultDescriptor('result1', null);
- static final ResultDescriptor result2 = new ResultDescriptor('result2', null);
-
- test_addGeneralResult() {
- TaskManager manager = new TaskManager();
- manager.addGeneralResult(result1);
- Set<ResultDescriptor> results = manager.generalResults;
- expect(results, unorderedEquals([result1]));
- }
-
- test_addPriorityResult() {
- TaskManager manager = new TaskManager();
- manager.addPriorityResult(result1);
- Set<ResultDescriptor> results = manager.priorityResults;
- expect(results, unorderedEquals([result1]));
- }
-
- test_addTaskDescriptor() {
- TaskManager manager = new TaskManager();
- TaskDescriptor descriptor =
- new TaskDescriptor('task', null, null, [result1]);
- manager.addTaskDescriptor(descriptor);
- expect(manager.taskMap.length, 1);
- }
-
- test_constructor() {
- TaskManager manager = new TaskManager();
- expect(manager, isNotNull);
- expect(manager.generalResults, isEmpty);
- expect(manager.priorityResults, isEmpty);
- }
-
- test_findTask_defined() {
- TaskManager manager = new TaskManager();
- TaskDescriptor descriptor =
- new TaskDescriptor('task', null, null, [result1]);
- manager.addTaskDescriptor(descriptor);
- AnalysisTarget target = new TestSource();
- expect(manager.findTask(target, result1), descriptor);
- }
-
- test_findTask_empty() {
- TaskManager manager = new TaskManager();
- AnalysisTarget target = new TestSource();
- expect(() => manager.findTask(target, result1),
- throwsA(new TypeMatcher<AnalysisException>()));
- }
-
- test_findTask_multiple() {
- TaskManager manager = new TaskManager();
- TaskDescriptor descriptor1 =
- new TaskDescriptor('task1', null, null, [result1]);
- manager.addTaskDescriptor(descriptor1);
- TaskDescriptor descriptor2 =
- new TaskDescriptor('task2', null, null, [result1]);
- manager.addTaskDescriptor(descriptor2);
- TaskDescriptor descriptor3 =
- new TaskDescriptor('task3', null, null, [result2]);
- manager.addTaskDescriptor(descriptor3);
-
- AnalysisTarget target = new TestSource();
- TaskDescriptor task = manager.findTask(target, result1);
- expect(task == descriptor1 || task == descriptor2, true);
- }
-
- test_findTask_undefined() {
- TaskManager manager = new TaskManager();
- TaskDescriptor descriptor =
- new TaskDescriptor('task', null, null, [result1]);
- manager.addTaskDescriptor(descriptor);
- AnalysisTarget target = new TestSource();
- expect(() => manager.findTask(target, result2),
- throwsA(new TypeMatcher<AnalysisException>()));
- }
-
- test_removeGeneralResult_absent() {
- TaskManager manager = new TaskManager();
- manager.addGeneralResult(result1);
- Set<ResultDescriptor> results = manager.generalResults;
- expect(results, unorderedEquals([result1]));
- }
-
- test_removeGeneralResult_present() {
- TaskManager manager = new TaskManager();
- manager.addGeneralResult(result1);
- manager.addGeneralResult(result2);
- Set<ResultDescriptor> results = manager.generalResults;
- expect(results, unorderedEquals([result1, result2]));
- manager.removeGeneralResult(result1);
- expect(results, unorderedEquals([result2]));
- }
-
- test_removePriorityResult_absent() {
- TaskManager manager = new TaskManager();
- manager.addPriorityResult(result1);
- manager.removePriorityResult(result2);
- Set<ResultDescriptor> results = manager.priorityResults;
- expect(results, unorderedEquals([result1]));
- }
-
- test_removePriorityResult_present() {
- TaskManager manager = new TaskManager();
- manager.addPriorityResult(result1);
- manager.addPriorityResult(result2);
- Set<ResultDescriptor> results = manager.priorityResults;
- expect(results, unorderedEquals([result1, result2]));
- manager.removePriorityResult(result1);
- expect(results, unorderedEquals([result2]));
- }
-}
diff --git a/pkg/analyzer/test/src/task/model_test.dart b/pkg/analyzer/test/src/task/model_test.dart
deleted file mode 100644
index 65b78ca..0000000
--- a/pkg/analyzer/test/src/task/model_test.dart
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/model.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-import 'test_support.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(AnalysisTaskTest);
- defineReflectiveTests(ResultDescriptorImplTest);
- defineReflectiveTests(SimpleResultCachingPolicyTest);
- defineReflectiveTests(TaskDescriptorImplTest);
- });
-}
-
-@reflectiveTest
-class AnalysisTaskTest extends EngineTestCase {
- test_getRequiredInput_missingKey() {
- AnalysisTarget target = new TestSource();
- AnalysisTask task = new TestAnalysisTask(null, target);
- task.inputs = {'a': 'b'};
- expect(() => task.getRequiredInput('c'),
- throwsA(new TypeMatcher<AnalysisException>()));
- }
-
- test_getRequiredInput_noInputs() {
- AnalysisTarget target = new TestSource();
- AnalysisTask task = new TestAnalysisTask(null, target);
- expect(() => task.getRequiredInput('x'),
- throwsA(new TypeMatcher<AnalysisException>()));
- }
-
- test_getRequiredInput_valid() {
- AnalysisTarget target = new TestSource();
- AnalysisTask task = new TestAnalysisTask(null, target);
- String key = 'a';
- String value = 'b';
- task.inputs = {key: value};
- expect(task.getRequiredInput(key), value);
- }
-
- test_getRequiredSource() {
- AnalysisTarget target = new TestSource();
- AnalysisTask task = new TestAnalysisTask(null, target);
- expect(task.getRequiredSource(), target);
- }
-}
-
-@reflectiveTest
-class ResultDescriptorImplTest extends EngineTestCase {
- test_create_withCachingPolicy() {
- ResultCachingPolicy policy = new SimpleResultCachingPolicy(128, 16);
- ResultDescriptorImpl result =
- new ResultDescriptorImpl('result', null, cachingPolicy: policy);
- expect(result.cachingPolicy, same(policy));
- }
-
- test_create_withoutCachingPolicy() {
- ResultDescriptorImpl result = new ResultDescriptorImpl('result', null);
- ResultCachingPolicy cachingPolicy = result.cachingPolicy;
- expect(cachingPolicy, isNotNull);
- expect(cachingPolicy.maxActiveSize, -1);
- expect(cachingPolicy.maxIdleSize, -1);
- }
-
- test_create_withoutContribution() {
- expect(new ResultDescriptorImpl('name', null), isNotNull);
- }
-
- test_inputFor() {
- AnalysisTarget target = new TestSource();
- ResultDescriptorImpl result = new ResultDescriptorImpl('result', null);
- TaskInput input = result.of(target);
- expect(input, isNotNull);
- }
-
- test_name() {
- String name = 'result';
- ResultDescriptorImpl result = new ResultDescriptorImpl(name, null);
- expect(result.name, name);
- }
-}
-
-@reflectiveTest
-class SimpleResultCachingPolicyTest extends EngineTestCase {
- test_create() {
- ResultCachingPolicy policy = new SimpleResultCachingPolicy(256, 32);
- expect(policy.maxActiveSize, 256);
- expect(policy.maxIdleSize, 32);
- expect(policy.measure(null), 1);
- }
-}
-
-@reflectiveTest
-class TaskDescriptorImplTest extends EngineTestCase {
- test_create_noOptionalArgs() {
- String name = 'name';
- BuildTask buildTask = (context, target) => null;
- CreateTaskInputs createTaskInputs = (target) => null;
- List<ResultDescriptor> results = <ResultDescriptor>[];
- TaskDescriptorImpl descriptor =
- new TaskDescriptorImpl(name, buildTask, createTaskInputs, results);
- expect(descriptor, isNotNull);
- expect(descriptor.name, name);
- expect(descriptor.buildTask, equals(buildTask));
- expect(descriptor.createTaskInputs, equals(createTaskInputs));
- expect(descriptor.suitabilityFor(null), TaskSuitability.LOWEST);
- expect(descriptor.results, results);
- }
-
- test_create_withIsAppropriateFor() {
- String name = 'name';
- BuildTask buildTask = (context, target) => null;
- CreateTaskInputs createTaskInputs = (target) => null;
- List<ResultDescriptor> results = <ResultDescriptor>[];
- SuitabilityFor suitabilityFor = (target) => TaskSuitability.NONE;
- TaskDescriptorImpl descriptor = new TaskDescriptorImpl(
- name, buildTask, createTaskInputs, results,
- suitabilityFor: suitabilityFor);
- expect(descriptor, isNotNull);
- expect(descriptor.name, name);
- expect(descriptor.buildTask, equals(buildTask));
- expect(descriptor.createTaskInputs, equals(createTaskInputs));
- expect(descriptor.suitabilityFor(null), TaskSuitability.NONE);
- expect(descriptor.results, results);
- }
-
- test_createTask() {
- BuildTask buildTask =
- (context, target) => new TestAnalysisTask(context, target);
- CreateTaskInputs createTaskInputs = (target) => null;
- List<ResultDescriptor> results = <ResultDescriptor>[];
- TaskDescriptorImpl descriptor =
- new TaskDescriptorImpl('name', buildTask, createTaskInputs, results);
- AnalysisContext context = null;
- AnalysisTarget target = new TestSource();
- Map<String, dynamic> inputs = {};
- AnalysisTask createTask = descriptor.createTask(context, target, inputs);
- expect(createTask, isNotNull);
- expect(createTask.context, context);
- expect(createTask.inputs, inputs);
- expect(createTask.target, target);
- }
-}
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index ee00e8e6..8032e06 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -18,13 +18,13 @@
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/registry.dart';
import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:yaml/yaml.dart';
import '../../generated/test_support.dart';
import '../../resource_utils.dart';
-import '../context/abstract_context.dart';
main() {
defineReflectiveSuite(() {
@@ -40,10 +40,10 @@
new TypeMatcher<GenerateOptionsErrorsTask>();
@reflectiveTest
-class ContextConfigurationTest extends AbstractContextTest {
- final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider();
+class ContextConfigurationTest {
+ final AnalysisOptions analysisOptions = AnalysisOptionsImpl();
- AnalysisOptions get analysisOptions => context.analysisOptions;
+ final AnalysisOptionsProvider optionsProvider = AnalysisOptionsProvider();
void configureContext(String optionsSource) =>
applyToAnalysisOptions(analysisOptions, parseOptions(optionsSource));
@@ -262,7 +262,7 @@
}
@reflectiveTest
-class GenerateOldOptionsErrorsTaskTest extends AbstractContextTest {
+class GenerateOldOptionsErrorsTaskTest with ResourceProviderMixin {
final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider();
String get optionsFilePath => '/${AnalysisEngine.ANALYSIS_OPTIONS_FILE}';
@@ -288,7 +288,7 @@
}
void validate(String content, List<ErrorCode> expected) {
- final Source source = newSource(optionsFilePath, content);
+ final source = newFile(optionsFilePath, content: content).createSource();
var options = optionsProvider.getOptionsFromSource(source);
final OptionsFileValidator validator = new OptionsFileValidator(source);
var errors = validator.validate(options);
@@ -376,14 +376,6 @@
''', [AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES]);
}
- test_analyzer_strong_mode_unsupported_value() {
- validate('''
-analyzer:
- strong-mode:
- implicit-dynamic: foo
-''', [AnalysisOptionsWarningCode.UNSUPPORTED_VALUE]);
- }
-
test_analyzer_lint_codes_recognized() {
Registry.ruleRegistry.register(new TestRule());
validate('''
@@ -431,6 +423,14 @@
''', [AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES]);
}
+ test_analyzer_strong_mode_unsupported_value() {
+ validate('''
+analyzer:
+ strong-mode:
+ implicit-dynamic: foo
+''', [AnalysisOptionsWarningCode.UNSUPPORTED_VALUE]);
+ }
+
test_analyzer_supported_exclude() {
validate('''
analyzer:
diff --git a/pkg/analyzer/test/src/task/options_work_manager_test.dart b/pkg/analyzer/test/src/task/options_work_manager_test.dart
deleted file mode 100644
index 8845781..0000000
--- a/pkg/analyzer/test/src/task/options_work_manager_test.dart
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/error/error.dart' show AnalysisError;
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/error/codes.dart' show AnalysisOptionsErrorCode;
-import 'package:analyzer/src/generated/engine.dart'
- show
- AnalysisEngine,
- AnalysisErrorInfo,
- AnalysisErrorInfoImpl,
- CacheState,
- ChangeNoticeImpl,
- InternalAnalysisContext;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/options.dart';
-import 'package:analyzer/src/task/options_work_manager.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(OptionsWorkManagerNewFileTest);
- defineReflectiveTests(OptionsWorkManagerOldFileTest);
- });
-}
-
-@reflectiveTest
-class OptionsWorkManagerNewFileTest extends OptionsWorkManagerTest {
- String get optionsFile => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
-}
-
-@reflectiveTest
-class OptionsWorkManagerOldFileTest extends OptionsWorkManagerTest {
- String get optionsFile => AnalysisEngine.ANALYSIS_OPTIONS_FILE;
-}
-
-abstract class OptionsWorkManagerTest {
- _InternalAnalysisContextMock context = new _InternalAnalysisContextMock();
- AnalysisCache cache;
- OptionsWorkManager manager;
-
- CaughtException caughtException = new CaughtException(null, null);
-
- Source source1;
-
- Source source2;
- Source source3;
- Source source4;
- CacheEntry entry1;
- CacheEntry entry2;
- CacheEntry entry3;
- CacheEntry entry4;
- String get optionsFile;
-
- void expect_sourceQueue(List<Source> sources) {
- expect(manager.sourceQueue, unorderedEquals(sources));
- }
-
- void setUp() {
- cache = context.analysisCache;
- manager = new OptionsWorkManager(context);
- source1 = new TestSource('test1/$optionsFile');
- source2 = new TestSource('test2/$optionsFile');
- source3 = new TestSource('test3/$optionsFile');
- source4 = new TestSource('test4/$optionsFile');
- entry1 = context.getCacheEntry(source1);
- entry2 = context.getCacheEntry(source2);
- entry3 = context.getCacheEntry(source3);
- entry4 = context.getCacheEntry(source4);
- }
-
- void test_applyChange_add() {
- // add source1
- manager.applyChange([source1], [], []);
- expect_sourceQueue([source1]);
- // add source2
- manager.applyChange([source2], [], []);
- expect_sourceQueue([source1, source2]);
- }
-
- void test_applyChange_add_duplicate() {
- // add source1
- manager.applyChange([source1], [], []);
- expect_sourceQueue([source1]);
- // add source1 again
- manager.applyChange([source1], [], []);
- expect_sourceQueue([source1]);
- }
-
- void test_applyChange_change() {
- // change source1
- manager.applyChange([], [source1], []);
- expect_sourceQueue([source1]);
- }
-
- void test_applyChange_change_afterAdd() {
- manager.applyChange([source1, source2], [], []);
- // change source1
- manager.applyChange([], [source1], []);
- expect_sourceQueue([source1, source2]);
- }
-
- void test_applyChange_remove() {
- manager.applyChange([source1, source2], [], []);
- // remove source1
- manager.applyChange([], [], [source1]);
- expect_sourceQueue([source2]);
- // remove source2
- manager.applyChange([], [], [source2]);
- expect_sourceQueue([]);
- // remove source3
- manager.applyChange([], [], [source3]);
- expect_sourceQueue([]);
- }
-
- void test_applyPriorityTargets() {
- context.setShouldErrorsBeAnalyzed(source2, true);
- context.setShouldErrorsBeAnalyzed(source3, true);
- manager.priorityResultQueue
- .add(new TargetedResult(source1, ANALYSIS_OPTIONS_ERRORS));
- manager.priorityResultQueue
- .add(new TargetedResult(source2, ANALYSIS_OPTIONS_ERRORS));
- // -source1 +source3
- manager.applyPriorityTargets([source2, source3]);
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(source2, ANALYSIS_OPTIONS_ERRORS),
- new TargetedResult(source3, ANALYSIS_OPTIONS_ERRORS)
- ]));
- // get next request
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, ANALYSIS_OPTIONS_ERRORS);
- }
-
- void test_getErrors() {
- AnalysisError error1 = new AnalysisError(
- source1, 1, 0, AnalysisOptionsErrorCode.PARSE_ERROR, ['']);
- AnalysisError error2 = new AnalysisError(
- source1, 2, 0, AnalysisOptionsErrorCode.PARSE_ERROR, ['']);
- entry1
- .setValue(ANALYSIS_OPTIONS_ERRORS, <AnalysisError>[error1, error2], []);
-
- List<AnalysisError> errors = manager.getErrors(source1);
- expect(errors, unorderedEquals([error1, error2]));
- }
-
- void test_getNextResult_hasNormal_firstIsError() {
- entry1.setErrorState(caughtException, [ANALYSIS_OPTIONS_ERRORS]);
- manager.sourceQueue.addAll([source1, source2]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, ANALYSIS_OPTIONS_ERRORS);
- // source1 is out, source2 is waiting
- expect_sourceQueue([source2]);
- }
-
- void test_getNextResult_hasNormal_firstIsInvalid() {
- entry1.setState(ANALYSIS_OPTIONS_ERRORS, CacheState.INVALID);
- manager.sourceQueue.addAll([source1, source2]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source1);
- expect(request.result, ANALYSIS_OPTIONS_ERRORS);
- // no changes until computed
- expect_sourceQueue([source1, source2]);
- }
-
- void test_getNextResult_hasNormal_firstIsValid() {
- entry1.setValue(ANALYSIS_OPTIONS_ERRORS, [], []);
- manager.sourceQueue.addAll([source1, source2]);
- TargetedResult request = manager.getNextResult();
- expect(request.target, source2);
- expect(request.result, ANALYSIS_OPTIONS_ERRORS);
- // source1 is out, source2 is waiting
- expect_sourceQueue([source2]);
- }
-
- void test_getNextResult_hasNormalAndPriority() {
- entry1.setState(ANALYSIS_OPTIONS_ERRORS, CacheState.INVALID);
- manager.sourceQueue.addAll([source1, source2]);
- manager.addPriorityResult(source3, ANALYSIS_OPTIONS_ERRORS);
-
- TargetedResult request = manager.getNextResult();
- expect(request.target, source3);
- expect(request.result, ANALYSIS_OPTIONS_ERRORS);
- // no changes until computed
- expect_sourceQueue([source1, source2]);
- }
-
- void test_getNextResult_hasPriority() {
- manager.addPriorityResult(source1, ANALYSIS_OPTIONS_ERRORS);
- manager.addPriorityResult(source2, ANALYSIS_OPTIONS_ERRORS);
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(source1, ANALYSIS_OPTIONS_ERRORS),
- new TargetedResult(source2, ANALYSIS_OPTIONS_ERRORS)
- ]));
-
- TargetedResult request = manager.getNextResult();
- expect(request.target, source1);
- expect(request.result, ANALYSIS_OPTIONS_ERRORS);
- // no changes until computed
- expect(
- manager.priorityResultQueue,
- unorderedEquals([
- new TargetedResult(source1, ANALYSIS_OPTIONS_ERRORS),
- new TargetedResult(source2, ANALYSIS_OPTIONS_ERRORS)
- ]));
- }
-
- void test_getNextResult_nothingToDo() {
- TargetedResult request = manager.getNextResult();
- expect(request, isNull);
- }
-
- void test_getNextResultPriority_hasPriority() {
- manager.addPriorityResult(source1, SOURCE_KIND);
- expect(manager.getNextResultPriority(), WorkOrderPriority.PRIORITY);
- }
-
- void test_getNextResultPriority_hasSource() {
- manager.sourceQueue.addAll([source1]);
- expect(manager.getNextResultPriority(), WorkOrderPriority.NORMAL);
- }
-
- void test_getNextResultPriority_nothingToDo() {
- expect(manager.getNextResultPriority(), WorkOrderPriority.NONE);
- }
-
- void test_resultsComputed_errors() {
- AnalysisError error1 = new AnalysisError(
- source1, 1, 0, AnalysisOptionsErrorCode.PARSE_ERROR, ['']);
- AnalysisError error2 = new AnalysisError(
- source1, 2, 0, AnalysisOptionsErrorCode.PARSE_ERROR, ['']);
- LineInfo lineInfo = new LineInfo([0]);
- entry1.setValue(LINE_INFO, lineInfo, []);
- entry1
- .setValue(ANALYSIS_OPTIONS_ERRORS, <AnalysisError>[error1, error2], []);
- // RESOLVED_UNIT is ready, set errors
- manager.resultsComputed(source1, {ANALYSIS_OPTIONS_ERRORS: null});
- // all of the errors are included
- ChangeNoticeImpl notice = context.getNotice(source1);
- expect(notice.errors, unorderedEquals([error1, error2]));
- expect(notice.lineInfo, lineInfo);
- }
-}
-
-class _InternalAnalysisContextMock implements InternalAnalysisContext {
- @override
- CachePartition privateAnalysisCachePartition;
-
- @override
- AnalysisCache analysisCache;
-
- Map<Source, bool> shouldErrorsBeAnalyzedMap = <Source, bool>{};
-
- Map<Source, ChangeNoticeImpl> _pendingNotices = <Source, ChangeNoticeImpl>{};
-
- _InternalAnalysisContextMock() {
- privateAnalysisCachePartition = new UniversalCachePartition(this);
- analysisCache = new AnalysisCache([privateAnalysisCachePartition]);
- }
-
- @override
- CacheEntry getCacheEntry(AnalysisTarget target) {
- CacheEntry entry = analysisCache.get(target);
- if (entry == null) {
- entry = new CacheEntry(target);
- analysisCache.put(entry);
- }
- return entry;
- }
-
- @override
- AnalysisErrorInfo getErrors(Source source) {
- List<AnalysisError> errors = AnalysisError.NO_ERRORS;
- if (AnalysisEngine.isAnalysisOptionsFileName(source.shortName)) {
- errors = getCacheEntry(source).getValue(ANALYSIS_OPTIONS_ERRORS);
- }
- return new AnalysisErrorInfoImpl(
- errors, getCacheEntry(source).getValue(LINE_INFO));
- }
-
- @override
- ChangeNoticeImpl getNotice(Source source) =>
- _pendingNotices.putIfAbsent(source, () => new ChangeNoticeImpl(source));
-
- @override
- noSuchMethod(Invocation invocation) {
- throw new StateError('Unexpected invocation of ${invocation.memberName}');
- }
-
- void setShouldErrorsBeAnalyzed(Source source, bool value) {
- shouldErrorsBeAnalyzedMap[source] = value;
- }
-
- @override
- bool shouldErrorsBeAnalyzed(Source source) {
- return shouldErrorsBeAnalyzedMap[source];
- }
-}
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 0d931a6..d56773e 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -8,11 +8,15 @@
void main() {
defineReflectiveSuite(() {
- defineReflectiveTests(CheckerTest_Driver);
+ defineReflectiveTests(CheckerTest);
});
}
-abstract class CheckerTest extends AbstractStrongTest {
+@reflectiveTest
+class CheckerTest extends AbstractStrongTest {
+ @override
+ bool get enableNewAnalysisDriver => true;
+
test_awaitForInCastsStreamElementToVariable() async {
await checkFile('''
import 'dart:async';
@@ -2305,11 +2309,11 @@
test_implicitDynamic_mapLiteral() async {
addFile(r'''
-var m0 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
-Map m1 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
-Map<dynamic, dynamic> m2 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
+var m0 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
+Map m1 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
+Map<dynamic, dynamic> m2 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
dynamic d = 42;
-var m3 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: d};
+var m3 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: d};
var m4 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{'x': d, 'y': d};
var m5 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: 'x'};
@@ -2535,7 +2539,6 @@
''');
}
- @failingTest // Does not work with old task model
test_interfacesFromMixinsUsedTwiceAreChecked() {
// Regression test for https://github.com/dart-lang/sdk/issues/29782
return checkFile(r'''
@@ -3744,7 +3747,6 @@
var upwardsInferNonDynamicIsOK = {4: 2};
var explicitDynamicIsOK = <dynamic, dynamic>{4: 2};
- var rawMap = /*info:STRICT_RAW_TYPE*/{};
var rawMapOfMaps = </*info:STRICT_RAW_TYPE*/Map>{};
/*info:STRICT_RAW_TYPE*/Map rawMapFromType = {};
@@ -3818,6 +3820,15 @@
await check(strictRawTypes: true);
}
+ test_strictRawTypes_emptyMap() async {
+ addFile('''
+main() {
+ var rawMap = /*info:STRICT_RAW_TYPE*/{};
+}
+''');
+ await check(strictRawTypes: true);
+ }
+
test_strictRawTypes_typedefs() async {
addFile(r'''
typedef T F1<T>(T _);
@@ -4153,13 +4164,13 @@
// TODO(leafp): We can't currently test for key errors since the
// error marker binds to the entire entry.
{
- Map m = {s: i};
- m = {s: s};
- m = {s: n};
- m = {s: i,
+ Map m = /*info:INFERRED_TYPE_LITERAL*/{s: i};
+ m = /*info:INFERRED_TYPE_LITERAL*/{s: s};
+ m = /*info:INFERRED_TYPE_LITERAL*/{s: n};
+ m = /*info:INFERRED_TYPE_LITERAL*/{s: i,
s: n,
s: s};
- m = {i: s,
+ m = /*info:INFERRED_TYPE_LITERAL*/{i: s,
n: s,
s: s};
}
@@ -4500,13 +4511,3 @@
''', name: '/meta.dart');
}
}
-
-@reflectiveTest
-class CheckerTest_Driver extends CheckerTest {
- @override
- bool get enableNewAnalysisDriver => true;
-
- @override // Passes with driver
- test_interfacesFromMixinsUsedTwiceAreChecked() =>
- super.test_interfacesFromMixinsUsedTwiceAreChecked();
-}
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 777c51f..a6da936 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -15,7 +15,7 @@
void main() {
defineReflectiveSuite(() {
- defineReflectiveTests(InferredTypeTest_Driver);
+ defineReflectiveTests(InferredTypeTest);
defineReflectiveTests(InferredTypeTest_SetLiterals);
});
}
@@ -1410,7 +1410,7 @@
void foo([Map<int, String> m1 = /*info:INFERRED_TYPE_LITERAL*/const {1: "hello"},
Map<int, String> m2 = /*info:INFERRED_TYPE_LITERAL*/const {
// One error is from type checking and the other is from const evaluation.
- /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE,error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
+ /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
"world"
}]) {
}
@@ -1431,11 +1431,11 @@
};
}
{
- Map<dynamic, dynamic> l0 = {};
- Map<dynamic, dynamic> l1 = {3: "hello"};
- Map<dynamic, dynamic> l2 = {"hello": "hello"};
- Map<dynamic, dynamic> l3 = {3: 3};
- Map<dynamic, dynamic> l4 = {3:"hello", "hello": 3};
+ Map<dynamic, dynamic> l0 = /*info:INFERRED_TYPE_LITERAL*/{};
+ Map<dynamic, dynamic> l1 = /*info:INFERRED_TYPE_LITERAL*/{3: "hello"};
+ Map<dynamic, dynamic> l2 = /*info:INFERRED_TYPE_LITERAL*/{"hello": "hello"};
+ Map<dynamic, dynamic> l3 = /*info:INFERRED_TYPE_LITERAL*/{3: 3};
+ Map<dynamic, dynamic> l4 = /*info:INFERRED_TYPE_LITERAL*/{3:"hello", "hello": 3};
}
{
Map<dynamic, String> l0 = /*info:INFERRED_TYPE_LITERAL*/{};
@@ -1470,16 +1470,16 @@
const Map<int, String> l0 = /*info:INFERRED_TYPE_LITERAL*/const {};
const Map<int, String> l1 = /*info:INFERRED_TYPE_LITERAL*/const {3: "hello"};
const Map<int, String> l2 = /*info:INFERRED_TYPE_LITERAL*/const {
- /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE,error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
+ /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
"hello"
};
const Map<int, String> l3 = /*info:INFERRED_TYPE_LITERAL*/const {
- 3: /*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE,error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/3
+ 3: /*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/3
};
const Map<int, String> l4 = /*info:INFERRED_TYPE_LITERAL*/const {
3:"hello",
- /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE,error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
- /*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE,error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/3
+ /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
+ /*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/3
};
}
}
@@ -1504,7 +1504,7 @@
Iterable<Map<int, int>> bar() sync* {
yield /*info:INFERRED_TYPE_LITERAL*/{};
yield /*error:YIELD_OF_INVALID_TYPE*/new List();
- yield* {};
+ yield* /*info:INFERRED_TYPE_LITERAL*/{};
yield* /*info:INFERRED_TYPE_ALLOCATION*/new List();
}
''');
@@ -2546,13 +2546,13 @@
b = /*error:INVALID_ASSIGNMENT*/"hi";
b = new B(3);
c1 = [];
- c1 = /*error:INVALID_ASSIGNMENT*/{};
+ c1 = /*error:INVALID_ASSIGNMENT,info:INFERRED_TYPE_LITERAL*/{};
c2 = [];
- c2 = /*error:INVALID_ASSIGNMENT*/{};
- d = {};
+ c2 = /*error:INVALID_ASSIGNMENT,info:INFERRED_TYPE_LITERAL*/{};
+ d = /*info:INFERRED_TYPE_LITERAL*/{};
d = /*error:INVALID_ASSIGNMENT*/3;
e = new A();
- e = /*error:INVALID_ASSIGNMENT*/{};
+ e = /*error:INVALID_ASSIGNMENT,info:INFERRED_TYPE_LITERAL*/{};
f = 3;
f = /*error:INVALID_ASSIGNMENT*/false;
g = 1;
@@ -4393,72 +4393,6 @@
@reflectiveTest
class InferredTypeTest extends AbstractStrongTest with InferredTypeMixin {
@override
- bool get mayCheckTypesOfLocals => true;
-
- @override
- Future<CompilationUnitElement> checkFileElement(String content) async {
- CompilationUnit unit = await checkFile(content);
- return unit.declaredElement;
- }
-
- @override
- @failingTest
- test_circularReference_viaClosures() {
- return super.test_circularReference_viaClosures();
- }
-
- @override
- @failingTest
- test_circularReference_viaClosures_initializerTypes() {
- return super.test_circularReference_viaClosures_initializerTypes();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_typeName_error1() {
- // Test doesn't work with the old task model
- return super.test_instantiateToBounds_typeName_error1();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_typeName_error2() {
- // Test doesn't work with the old task model
- return super.test_instantiateToBounds_typeName_error2();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_typeName_error3() {
- // Test doesn't work with the old task model
- return super.test_instantiateToBounds_typeName_error3();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_typeName_OK_hasBound_definedAfter() {
- return super.test_instantiateToBounds_typeName_OK_hasBound_definedAfter();
- }
-
- @override
- @failingTest
- test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
- return super
- .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
- }
-
- @failingTest
- @override
- test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
- return super
- .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
- }
-}
-
-@reflectiveTest
-class InferredTypeTest_Driver extends AbstractStrongTest
- with InferredTypeMixin {
- @override
bool get enableNewAnalysisDriver => true;
@override
@@ -4527,7 +4461,7 @@
Iterable<Map<int, int>> bar() sync* {
yield /*info:INFERRED_TYPE_LITERAL*/{};
yield /*error:YIELD_OF_INVALID_TYPE*/new List();
- yield* {};
+ yield* /*info:INFERRED_TYPE_LITERAL*/{};
yield* /*info:INFERRED_TYPE_ALLOCATION*/new List();
}
''');
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 38d5a42..fadd403 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -243,10 +243,10 @@
AnalysisContext _context = null;
AnalysisDriver _driver = null;
- bool get enableNewAnalysisDriver => false;
-
List<String> get enabledExperiments => [];
+ bool get enableNewAnalysisDriver => false;
+
/// Adds a file to check. The file should contain:
///
/// * all expected failures are listed in the source code using comments
@@ -382,9 +382,7 @@
);
}
- void setUp() {
- AnalysisEngine.instance.processRequiredPlugins();
- }
+ void setUp() {}
void tearDown() {
// This is a sanity check, in case only addFile is called.
diff --git a/pkg/analyzer/test/src/task/test_all.dart b/pkg/analyzer/test/src/task/test_all.dart
index f66959e..d6f96c1f 100644
--- a/pkg/analyzer/test/src/task/test_all.dart
+++ b/pkg/analyzer/test/src/task/test_all.dart
@@ -4,25 +4,12 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'dart_work_manager_test.dart' as dart_work_manager_test;
-import 'general_test.dart' as general_test;
-import 'inputs_test.dart' as inputs_test;
-import 'manager_test.dart' as manager_test;
-import 'model_test.dart' as model_test;
import 'options_test.dart' as options_test;
-import 'options_work_manager_test.dart' as options_work_manager_test;
import 'strong/test_all.dart' as strong_mode_test_all;
-/// Utility for manually running all tests.
main() {
defineReflectiveSuite(() {
- dart_work_manager_test.main();
- general_test.main();
- inputs_test.main();
- manager_test.main();
- model_test.main();
options_test.main();
- options_work_manager_test.main();
strong_mode_test_all.main();
}, name: 'task');
}
diff --git a/pkg/analyzer/test/src/task/test_support.dart b/pkg/analyzer/test/src/task/test_support.dart
deleted file mode 100644
index 7415324..0000000
--- a/pkg/analyzer/test/src/task/test_support.dart
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/task/api/model.dart';
-
-/**
- * A configurable analysis task that can be used by tests.
- */
-class TestAnalysisTask extends AnalysisTask {
- /**
- * The descriptor describing this task.
- */
- TaskDescriptor descriptor;
-
- /**
- * The exception that is to be "thrown" by this task.
- */
- CaughtException exception;
-
- /**
- * The results whose values are to be provided as outputs from this task.
- */
- List<ResultDescriptor> results;
-
- /**
- * The next value that is to be used for a result.
- */
- int value;
-
- @override
- final bool handlesDependencyCycles;
-
- TestAnalysisTask(AnalysisContext context, AnalysisTarget target,
- {this.descriptor,
- this.exception,
- this.handlesDependencyCycles: false,
- this.results,
- this.value: 1})
- : super(context, target);
-
- @override
- String get description => 'Test task';
-
- @override
- internalPerform() {
- if (exception != null) {
- caughtException = exception;
- } else if (results != null) {
- for (ResultDescriptor result in results) {
- outputs[result] = value++;
- }
- } else if (descriptor != null) {
- for (ResultDescriptor result in descriptor.results) {
- outputs[result] = value++;
- }
- }
- }
-}
diff --git a/pkg/analyzer/test/src/test_all.dart b/pkg/analyzer/test/src/test_all.dart
index 011e198..32548b3 100644
--- a/pkg/analyzer/test/src/test_all.dart
+++ b/pkg/analyzer/test/src/test_all.dart
@@ -9,15 +9,18 @@
import 'dart/test_all.dart' as dart;
import 'diagnostics/test_all.dart' as diagnostics;
import 'fasta/test_all.dart' as fasta;
+import 'hint/test_all.dart' as hint;
import 'lint/test_all.dart' as lint;
import 'options/test_all.dart' as options;
import 'pubspec/test_all.dart' as pubspec;
+import 'services/test_all.dart' as services;
import 'source/test_all.dart' as source;
import 'summary/test_all.dart' as summary;
+import 'summary2/test_all.dart' as summary2;
import 'task/test_all.dart' as task;
import 'util/test_all.dart' as util;
+import 'workspace/test_all.dart' as workspace;
-/// Utility for manually running all tests.
main() {
defineReflectiveSuite(() {
command_line.main();
@@ -25,12 +28,16 @@
dart.main();
diagnostics.main();
fasta.main();
+ hint.main();
lint.main();
options.main();
pubspec.main();
+ services.main();
source.main();
summary.main();
+ summary2.main();
task.main();
util.main();
+ workspace.main();
}, name: 'src');
}
diff --git a/pkg/analyzer/test/src/workspace/test_all.dart b/pkg/analyzer/test/src/workspace/test_all.dart
index c2e0512..edf5bd0 100644
--- a/pkg/analyzer/test/src/workspace/test_all.dart
+++ b/pkg/analyzer/test/src/workspace/test_all.dart
@@ -1,19 +1,21 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// 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.
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'basic_test.dart' as basic_test;
-import 'bazel_test.dart' as bazel_test;
-import 'gn_test.dart' as gn_test;
-import 'package_build_test.dart' as package_build_test;
+import 'basic_test.dart' as basic;
+import 'bazel_test.dart' as bazel;
+import 'gn_test.dart' as gn;
+import 'package_build_test.dart' as package_build;
+import 'pub_test.dart' as pub;
main() {
defineReflectiveSuite(() {
- basic_test.main();
- bazel_test.main();
- gn_test.main();
- package_build_test.main();
+ basic.main();
+ bazel.main();
+ gn.main();
+ package_build.main();
+ pub.main();
}, name: 'workspace');
}
diff --git a/pkg/analyzer/test/test_all.dart b/pkg/analyzer/test/test_all.dart
index d0c8dfd..a27c273 100644
--- a/pkg/analyzer/test/test_all.dart
+++ b/pkg/analyzer/test/test_all.dart
@@ -1,10 +1,10 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// 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.
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'cancelable_future_test.dart' as cancelable_future_test;
+import 'cancelable_future_test.dart' as cancelable_future;
import 'dart/test_all.dart' as dart;
import 'error/test_all.dart' as error;
import 'file_system/test_all.dart' as file_system;
@@ -13,11 +13,11 @@
import 'parse_compilation_unit_test.dart' as parse_compilation_unit;
import 'source/test_all.dart' as source;
import 'src/test_all.dart' as src;
+import 'verify_tests_test.dart' as verify_tests;
-/// Utility for manually running all tests.
main() {
defineReflectiveSuite(() {
- cancelable_future_test.main();
+ cancelable_future.main();
dart.main();
error.main();
file_system.main();
@@ -26,5 +26,6 @@
parse_compilation_unit.main();
source.main();
src.main();
+ verify_tests.main();
}, name: 'analyzer');
}
diff --git a/pkg/analyzer/test/verify_tests_test.dart b/pkg/analyzer/test/verify_tests_test.dart
new file mode 100644
index 0000000..d22aa57
--- /dev/null
+++ b/pkg/analyzer/test/verify_tests_test.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2019, 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/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:front_end/src/testing/package_root.dart' as package_root;
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+main() {
+ PhysicalResourceProvider provider = PhysicalResourceProvider.INSTANCE;
+ String packageRoot = provider.pathContext.normalize(package_root.packageRoot);
+ String analyzerPath = provider.pathContext.join(packageRoot, 'analyzer');
+ String testDirPath = provider.pathContext.join(analyzerPath, 'test');
+
+ AnalysisContextCollection collection = new AnalysisContextCollection(
+ includedPaths: <String>[testDirPath], resourceProvider: provider);
+ List<AnalysisContext> contexts = collection.contexts;
+ if (contexts.length != 1) {
+ fail('The test directory contains multiple analysis contexts.');
+ }
+
+ buildTestsIn(
+ contexts[0].currentSession, testDirPath, provider.getFolder(testDirPath));
+}
+
+void buildTestsIn(
+ AnalysisSession session, String testDirPath, Folder directory) {
+ List<String> testFileNames = [];
+ File testAllFile;
+ List<Resource> children = directory.getChildren();
+ children.sort((first, second) => first.shortName.compareTo(second.shortName));
+ for (Resource child in children) {
+ if (child is Folder) {
+ if (child.getChildAssumingFile('test_all.dart').exists) {
+ testFileNames.add('${child.shortName}/test_all.dart');
+ }
+ buildTestsIn(session, testDirPath, child);
+ } else if (child is File) {
+ String name = child.shortName;
+ if (name == 'test_all.dart') {
+ testAllFile = child;
+ } else if (name.endsWith('_test.dart')) {
+ testFileNames.add(name);
+ }
+ }
+ }
+ String relativePath = path.relative(directory.path, from: testDirPath);
+ test(relativePath, () {
+ if (testFileNames.isEmpty) {
+ return;
+ }
+ if (testAllFile == null) {
+ fail('Missing "test_all.dart" in $relativePath');
+ }
+ ParsedUnitResult result = session.getParsedUnit(testAllFile.path);
+ if (result.state != ResultState.VALID) {
+ fail('Could not parse ${testAllFile.path}');
+ }
+ List<String> importedFiles = [];
+ for (var directive in result.unit.directives) {
+ if (directive is ImportDirective) {
+ importedFiles.add(directive.uri.stringValue);
+ }
+ }
+ List<String> missingFiles = [];
+ for (String testFileName in testFileNames) {
+ if (!importedFiles.contains(testFileName)) {
+ missingFiles.add(testFileName);
+ }
+ }
+ if (missingFiles.isNotEmpty) {
+ fail('Tests missing from "test_all.dart": ${missingFiles.join(', ')}');
+ }
+ });
+}
diff --git a/pkg/analyzer/tool/summary/dump_inferred_types.dart b/pkg/analyzer/tool/summary/dump_inferred_types.dart
index a5167b0..ffc71af 100644
--- a/pkg/analyzer/tool/summary/dump_inferred_types.dart
+++ b/pkg/analyzer/tool/summary/dump_inferred_types.dart
@@ -7,6 +7,7 @@
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/engine.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/base.dart';
import 'package:analyzer/src/summary/idl.dart';
@@ -40,7 +41,8 @@
InferredTypeCollector(
GetDependencyCallback getDependency, GetUnitCallback getUnit)
- : _linker = new Linker({}, getDependency, getUnit, null);
+ : _linker =
+ new Linker({}, getDependency, getUnit, null, AnalysisOptionsImpl());
/**
* If an inferred type exists matching the given [slot], record that it is the
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index ee2a239..ca4002a 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -354,8 +354,12 @@
uriToUnit[absoluteUri];
}
- Map<String, LinkedLibraryBuilder> linkResult = link(libraryUris,
- getDependency, getUnit, analysisDriver.declaredVariables.get);
+ Map<String, LinkedLibraryBuilder> linkResult = link(
+ libraryUris,
+ getDependency,
+ getUnit,
+ analysisDriver.declaredVariables,
+ analysisOptions);
linkResult.forEach(assembler.addLinkedLibrary);
});
}
@@ -557,6 +561,22 @@
}
/**
+ * Tracks paths to dependencies, really just a thin api around a Set<String>.
+ */
+class DependencyTracker {
+ final _dependencies = Set<String>();
+
+ /// The path to the file to create once tracking is done.
+ final String outputPath;
+
+ DependencyTracker(this.outputPath);
+
+ Iterable<String> get dependencies => _dependencies;
+
+ void record(String path) => _dependencies.add(path);
+}
+
+/**
* [PackageBundleProvider] that always reads from the [ResourceProvider].
*/
class DirectPackageBundleProvider implements PackageBundleProvider {
@@ -719,19 +739,3 @@
return cache.get(inputs, path);
}
}
-
-/**
- * Tracks paths to dependencies, really just a thin api around a Set<String>.
- */
-class DependencyTracker {
- final _dependencies = Set<String>();
-
- Iterable<String> get dependencies => _dependencies;
-
- /// The path to the file to create once tracking is done.
- final String outputPath;
-
- DependencyTracker(this.outputPath);
-
- void record(String path) => _dependencies.add(path);
-}
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 8b2b808..dea039b 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -52,8 +52,6 @@
import 'package:package_config/packages_file.dart' as pkgfile show parse;
import 'package:package_config/src/packages_impl.dart' show MapPackages;
import 'package:path/path.dart' as path;
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
import 'package:telemetry/crash_reporting.dart';
import 'package:telemetry/telemetry.dart' as telemetry;
import 'package:yaml/yaml.dart';
@@ -100,9 +98,6 @@
ContextCache contextCache;
- /// The plugins that are defined outside the `analyzer_cli` package.
- List<Plugin> _userDefinedPlugins = <Plugin>[];
-
/// The driver that was most recently created by a call to [_analyzeAll], or
/// `null` if [_analyzeAll] hasn't been called yet.
@visibleForTesting
@@ -149,11 +144,6 @@
CrashReportSender get crashReportSender => (_crashReportSender ??=
new CrashReportSender('Dart_analyzer_cli', analytics));
- @override
- void set userDefinedPlugins(List<Plugin> plugins) {
- _userDefinedPlugins = plugins ?? <Plugin>[];
- }
-
/**
* Converts the given [filePath] into absolute and normalized.
*/
@@ -173,7 +163,7 @@
StringUtilities.INTERNER = new MappedInterner();
- _processPlugins();
+ linter.registerLintRules();
// Parse commandline options.
CommandLineOptions options = CommandLineOptions.parse(args);
@@ -735,17 +725,6 @@
bool _isInHiddenDir(String relative) =>
path.split(relative).any((part) => part.startsWith("."));
- void _processPlugins() {
- List<Plugin> plugins = <Plugin>[];
- plugins.addAll(AnalysisEngine.instance.requiredPlugins);
- plugins.addAll(_userDefinedPlugins);
-
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(plugins);
-
- linter.registerLintRules();
- }
-
/// Analyze a single source.
Future<ErrorSeverity> _runAnalyzer(
FileState file, CommandLineOptions options, ErrorFormatter formatter) {
diff --git a/pkg/analyzer_cli/lib/starter.dart b/pkg/analyzer_cli/lib/starter.dart
index 09db5bf..88a232c 100644
--- a/pkg/analyzer_cli/lib/starter.dart
+++ b/pkg/analyzer_cli/lib/starter.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/src/plugin/resolver_provider.dart';
import 'package:analyzer_cli/src/driver.dart';
-import 'package:plugin/plugin.dart';
/**
* An object that can be used to start a command-line analysis. This class
@@ -30,11 +29,6 @@
void set packageResolverProvider(ResolverProvider provider);
/**
- * Set the [plugins] that are defined outside the analyzer_cli package.
- */
- void set userDefinedPlugins(List<Plugin> plugins);
-
- /**
* Use the given command-line [arguments] to start this analyzer.
*
* If [sendPort] is provided it is used for bazel worker communication
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index bfa2b84..cac47aa 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -8,7 +8,6 @@
collection: ^1.14.1
linter: ^0.1.16
package_config: '>=0.1.5 <2.0.0'
- plugin: '>=0.1.0 <0.3.0'
protobuf: ^0.9.0
telemetry: ^0.0.1
yaml: ^2.1.2
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index e504aac..785a0f3 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -1266,11 +1266,14 @@
// Prepare information about existing imports.
LibraryDirective libraryDirective;
List<ImportDirective> importDirectives = <ImportDirective>[];
+ PartDirective partDirective;
for (Directive directive in unit.directives) {
if (directive is LibraryDirective) {
libraryDirective = directive;
} else if (directive is ImportDirective) {
importDirectives.add(directive);
+ } else if (directive is PartDirective) {
+ partDirective = directive;
}
}
@@ -1396,15 +1399,28 @@
// Insert imports: after the library directive.
if (libraryDirective != null) {
addInsertion(libraryDirective.end, (EditBuilder builder) {
+ builder.writeln();
+ builder.writeln();
for (int i = 0; i < importList.length; i++) {
var import = importList[i];
- if (i == 0) {
+ writeImport(builder, import);
+ if (i != importList.length - 1) {
builder.writeln();
}
- builder.writeln();
+ }
+ });
+ return;
+ }
+
+ // Insert imports: before a part directive.
+ if (partDirective != null) {
+ addInsertion(partDirective.offset, (EditBuilder builder) {
+ for (int i = 0; i < importList.length; i++) {
+ var import = importList[i];
writeImport(builder, import);
builder.writeln();
}
+ builder.writeln();
});
return;
}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index a3be8b8..5aae60f 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -1604,25 +1604,6 @@
@reflectiveTest
class ImportLibraryTest extends AbstractContextTest
with DartChangeBuilderMixin {
- test_afterLibraryDirective_dart() async {
- await _assertImportLibrary(
- initialCode: '''
-library test;
-
-class A {}
-''',
- uriList: ['dart:async'],
- expectedCode: '''
-library test;
-
-import 'dart:async';
-
-
-class A {}
-''',
- );
- }
-
test_dart_beforeDart() async {
await _assertImportLibrary(
initialCode: '''
@@ -1765,6 +1746,58 @@
);
}
+ test_noImports_afterLibrary_hasDeclaration() async {
+ await _assertImportLibrary(
+ initialCode: '''
+library test;
+
+class A {}
+''',
+ uriList: ['dart:async'],
+ expectedCode: '''
+library test;
+
+import 'dart:async';
+
+class A {}
+''',
+ );
+ }
+
+ test_noImports_afterLibrary_hasPart() async {
+ await _assertImportLibrary(
+ initialCode: '''
+library test;
+
+part 'a.dart';
+''',
+ uriList: ['dart:aaa', 'dart:bbb'],
+ expectedCode: '''
+library test;
+
+import 'dart:aaa';
+import 'dart:bbb';
+
+part 'a.dart';
+''',
+ );
+ }
+
+ test_noImports_beforePart() async {
+ await _assertImportLibrary(
+ initialCode: '''
+part 'a.dart';
+''',
+ uriList: ['dart:aaa', 'dart:bbb'],
+ expectedCode: '''
+import 'dart:aaa';
+import 'dart:bbb';
+
+part 'a.dart';
+''',
+ );
+ }
+
test_package_afterDart() async {
await _assertImportLibrary(
initialCode: '''
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
index 02e19d1..51cc21e 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
@@ -468,11 +468,9 @@
);
}
- @failingTest
test_shadowed_class_inPart() async {
newFile('/home/test/lib/a.dart', content: 'class C {}');
newFile('/home/test/lib/p.dart', content: 'class C {}');
- // TODO(scheglov) "import" must be before "part"
await _assertImportLibraryElement(
initialCode: r'''
part 'p.dart';
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
index 37958bb..8f42f89 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart' as analyzer;
import 'package:analyzer/src/generated/parser.dart' as analyzer;
import 'package:analyzer/src/test_utilities/find_element.dart';
import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
@@ -663,20 +664,33 @@
assertTarget('new C();', '{var f; {var x;} new C();}');
}
- test_MapLiteralEntry() async {
- // MapLiteralEntry MapLiteral VariableDeclaration
+ test_MapLiteral_expression() async {
+ super.setUp();
+ final experimentStatus =
+ (this.driver.analysisOptions as analyzer.AnalysisOptionsImpl)
+ .experimentStatus;
+ if (experimentStatus.control_flow_collections ||
+ experimentStatus.spread_collections) {
+ // SimpleIdentifier MapLiteral VariableDeclaration
+ await createTarget('foo = {1: 2, T^');
+ assertTarget('T', '{1 : 2, T}');
+ } else {
+ // TODO(b/35569): remove this branch of test behavior
+
+ // SimpleIdentifier MapLiteralEntry MapLiteral VariableDeclaration
+ await createTarget('foo = {1: 2, T^');
+ assertTarget('T : ', '{1 : 2, T : }');
+ }
+ }
+
+ test_MapLiteral_empty() async {
+ // MapLiteral VariableDeclaration
await createTarget('foo = {^');
// fasta scanner inserts synthetic closing '}'
assertTarget('}', '{}');
}
- test_MapLiteralEntry1() async {
- // MapLiteralEntry MapLiteral VariableDeclaration
- await createTarget('foo = {1: 2, T^');
- assertTarget('T : ', '{1 : 2, T : }');
- }
-
- test_MapLiteralEntry2() async {
+ test_MapLiteralEntry() async {
// SimpleIdentifier MapLiteralEntry MapLiteral VariableDeclaration
await createTarget('foo = {7:T^};');
assertTarget('T', '7 : T');
diff --git a/pkg/compiler/analysis_options.yaml b/pkg/compiler/analysis_options.yaml
index af22f6b..deba0e5 100644
--- a/pkg/compiler/analysis_options.yaml
+++ b/pkg/compiler/analysis_options.yaml
@@ -10,3 +10,7 @@
deprecated_member_use: ignore
# Allow deprecated calls from within the same package
deprecated_member_use_from_same_package: ignore
+
+linter:
+ rules:
+ - annotate_overrides
diff --git a/pkg/compiler/lib/compiler.dart b/pkg/compiler/lib/compiler.dart
index 11816ed..3da6d59 100644
--- a/pkg/compiler/lib/compiler.dart
+++ b/pkg/compiler/lib/compiler.dart
@@ -170,5 +170,6 @@
/// diagnostic kinds.
const Diagnostic(this.ordinal, this.name);
+ @override
String toString() => name;
}
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index f54520a..17c84a4 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -22,7 +22,9 @@
/// Implements the [Compiler] using a [api.CompilerInput] for supplying the
/// sources.
class CompilerImpl extends Compiler {
+ @override
final Measurer measurer;
+ @override
api.CompilerInput provider;
api.CompilerDiagnostics handler;
@@ -81,6 +83,7 @@
return future;
}
+ @override
Future<bool> run(Uri uri) {
Duration setupDuration = measurer.elapsedWallClock;
return selfTask.measureSubtask("impl.run", () {
@@ -146,6 +149,7 @@
' (${percent.toStringAsFixed(2)}%)');
}
+ @override
void reportDiagnostic(DiagnosticMessage message,
List<DiagnosticMessage> infos, api.Diagnostic kind) {
_reportDiagnosticMessage(message, kind);
@@ -197,6 +201,7 @@
_Environment(this.definitions);
+ @override
String valueOf(String name) {
var result = definitions[name];
if (result != null || definitions.containsKey(name)) return result;
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 467dfe1c3..343d58b 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -307,14 +307,18 @@
BoxLocal(this.container);
+ @override
String get name => container.name;
+ @override
bool operator ==(other) {
return other is BoxLocal && other.container == container;
}
+ @override
int get hashCode => container.hashCode;
+ @override
String toString() => 'BoxLocal($name)';
}
@@ -324,12 +328,15 @@
ThisLocal(this.enclosingClass);
+ @override
String get name => 'this';
+ @override
bool operator ==(other) {
return other is ThisLocal && other.enclosingClass == enclosingClass;
}
+ @override
int get hashCode => enclosingClass.hashCode;
}
@@ -339,15 +346,19 @@
TypeVariableLocal(this.typeVariable);
+ @override
String get name => typeVariable.element.name;
+ @override
int get hashCode => typeVariable.hashCode;
+ @override
bool operator ==(other) {
if (other is! TypeVariableLocal) return false;
return typeVariable == other.typeVariable;
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('type_variable_local(');
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index a0c99af..ec92751 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -46,6 +46,7 @@
_CodegenImpact();
+ @override
void apply(WorldImpactVisitor visitor) {
staticUses.forEach(visitor.visitStaticUse);
dynamicUses.forEach(visitor.visitDynamicUse);
@@ -59,6 +60,7 @@
.add(new Pair<DartType, DartType>(subtype, supertype));
}
+ @override
Iterable<Pair<DartType, DartType>> get typeVariableBoundsSubtypeChecks {
return _typeVariableBoundsSubtypeChecks != null
? _typeVariableBoundsSubtypeChecks
@@ -70,6 +72,7 @@
_constSymbols.add(name);
}
+ @override
Iterable<String> get constSymbols {
return _constSymbols != null ? _constSymbols : const <String>[];
}
@@ -79,6 +82,7 @@
_specializedGetInterceptors.add(classes);
}
+ @override
Iterable<Set<ClassEntity>> get specializedGetInterceptors {
return _specializedGetInterceptors != null
? _specializedGetInterceptors
@@ -89,6 +93,7 @@
_usesInterceptor = true;
}
+ @override
bool get usesInterceptor => _usesInterceptor;
void registerAsyncMarker(AsyncMarker asyncMarker) {
@@ -96,6 +101,7 @@
_asyncMarkers.add(asyncMarker);
}
+ @override
Iterable<AsyncMarker> get asyncMarkers {
return _asyncMarkers != null
? _asyncMarkers.iterable(AsyncMarker.values)
@@ -125,6 +131,7 @@
bool get isForResolution => false;
+ @override
String toString() => 'CodegenRegistry for $currentElement';
@deprecated
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 5d1116c..ec947a4 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -231,4 +231,8 @@
/// The URI for 'package:js'.
static final Uri package_js = new Uri(scheme: 'package', path: 'js/js.dart');
+
+ /// The URI for 'package:meta/dart2js.dart'.
+ static final Uri package_meta_dart2js =
+ new Uri(scheme: 'package', path: 'meta/dart2js.dart');
}
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index 83a1e0d..ebf692e 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -208,6 +208,7 @@
}
class GenericTask extends CompilerTask {
+ @override
final String name;
GenericTask(this.name, Measurer measurer) : super(measurer);
}
@@ -230,6 +231,7 @@
final bool enableTaskMeasurements;
static int _hashCodeGenerator = 197;
+ @override
final int hashCode = _hashCodeGenerator++;
Measurer({this.enableTaskMeasurements: false});
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 11c0efa..4ca6b63 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -136,9 +136,6 @@
/// The `double` type defined in 'dart:core'.
InterfaceType get doubleType;
- /// The `Resource` type defined in 'dart:core'.
- InterfaceType get resourceType;
-
/// The `String` type defined in 'dart:core'.
InterfaceType get stringType;
@@ -598,136 +595,165 @@
/// The `Object` class defined in 'dart:core'.
ClassEntity _objectClass;
+ @override
ClassEntity get objectClass =>
_objectClass ??= _findClass(coreLibrary, 'Object');
/// The `bool` class defined in 'dart:core'.
ClassEntity _boolClass;
+ @override
ClassEntity get boolClass => _boolClass ??= _findClass(coreLibrary, 'bool');
/// The `num` class defined in 'dart:core'.
ClassEntity _numClass;
+ @override
ClassEntity get numClass => _numClass ??= _findClass(coreLibrary, 'num');
/// The `int` class defined in 'dart:core'.
ClassEntity _intClass;
+ @override
ClassEntity get intClass => _intClass ??= _findClass(coreLibrary, 'int');
/// The `double` class defined in 'dart:core'.
ClassEntity _doubleClass;
+ @override
ClassEntity get doubleClass =>
_doubleClass ??= _findClass(coreLibrary, 'double');
/// The `String` class defined in 'dart:core'.
ClassEntity _stringClass;
+ @override
ClassEntity get stringClass =>
_stringClass ??= _findClass(coreLibrary, 'String');
/// The `Function` class defined in 'dart:core'.
ClassEntity _functionClass;
+ @override
ClassEntity get functionClass =>
_functionClass ??= _findClass(coreLibrary, 'Function');
/// The `Resource` class defined in 'dart:core'.
ClassEntity _resourceClass;
+ @override
ClassEntity get resourceClass =>
_resourceClass ??= _findClass(coreLibrary, 'Resource');
/// The `Symbol` class defined in 'dart:core'.
ClassEntity _symbolClass;
+ @override
ClassEntity get symbolClass =>
_symbolClass ??= _findClass(coreLibrary, 'Symbol');
/// The `Null` class defined in 'dart:core'.
ClassEntity _nullClass;
+ @override
ClassEntity get nullClass => _nullClass ??= _findClass(coreLibrary, 'Null');
/// The `Type` class defined in 'dart:core'.
ClassEntity _typeClass;
+ @override
ClassEntity get typeClass => _typeClass ??= _findClass(coreLibrary, 'Type');
/// The `StackTrace` class defined in 'dart:core';
ClassEntity _stackTraceClass;
+ @override
ClassEntity get stackTraceClass =>
_stackTraceClass ??= _findClass(coreLibrary, 'StackTrace');
/// The `List` class defined in 'dart:core';
ClassEntity _listClass;
+ @override
ClassEntity get listClass => _listClass ??= _findClass(coreLibrary, 'List');
/// The `Set` class defined in 'dart:core'.
ClassEntity _setClass;
+ @override
ClassEntity get setClass => _setClass ??= _findClass(coreLibrary, 'Set');
/// The `Map` class defined in 'dart:core';
ClassEntity _mapClass;
+ @override
ClassEntity get mapClass => _mapClass ??= _findClass(coreLibrary, 'Map');
/// The `_UnmodifiableSet` class defined in 'dart:collection';
ClassEntity _unmodifiableSetClass;
+ @override
ClassEntity get unmodifiableSetClass => _unmodifiableSetClass ??=
_findClass(_env.lookupLibrary(Uris.dart_collection), '_UnmodifiableSet');
/// The `Iterable` class defined in 'dart:core';
ClassEntity _iterableClass;
+ @override
ClassEntity get iterableClass =>
_iterableClass ??= _findClass(coreLibrary, 'Iterable');
/// The `Future` class defined in 'async';.
ClassEntity _futureClass;
+ @override
ClassEntity get futureClass =>
_futureClass ??= _findClass(asyncLibrary, 'Future');
/// The `Stream` class defined in 'async';
ClassEntity _streamClass;
+ @override
ClassEntity get streamClass =>
_streamClass ??= _findClass(asyncLibrary, 'Stream');
/// The dart:core library.
LibraryEntity _coreLibrary;
+ @override
LibraryEntity get coreLibrary =>
_coreLibrary ??= _env.lookupLibrary(Uris.dart_core, required: true);
/// The dart:async library.
LibraryEntity _asyncLibrary;
+ @override
LibraryEntity get asyncLibrary =>
_asyncLibrary ??= _env.lookupLibrary(Uris.dart_async);
/// The dart:mirrors library. Null if the program doesn't access dart:mirrors.
LibraryEntity _mirrorsLibrary;
+ @override
LibraryEntity get mirrorsLibrary =>
_mirrorsLibrary ??= _env.lookupLibrary(Uris.dart_mirrors);
/// The dart:typed_data library.
LibraryEntity _typedDataLibrary;
+ @override
LibraryEntity get typedDataLibrary =>
_typedDataLibrary ??= _env.lookupLibrary(Uris.dart__native_typed_data);
LibraryEntity _jsHelperLibrary;
+ @override
LibraryEntity get jsHelperLibrary =>
_jsHelperLibrary ??= _env.lookupLibrary(Uris.dart__js_helper);
LibraryEntity _interceptorsLibrary;
+ @override
LibraryEntity get interceptorsLibrary =>
_interceptorsLibrary ??= _env.lookupLibrary(Uris.dart__interceptors);
LibraryEntity _foreignLibrary;
+ @override
LibraryEntity get foreignLibrary =>
_foreignLibrary ??= _env.lookupLibrary(Uris.dart__foreign_helper);
/// Reference to the internal library to lookup functions to always inline.
LibraryEntity _internalLibrary;
+ @override
LibraryEntity get internalLibrary => _internalLibrary ??=
_env.lookupLibrary(Uris.dart__internal, required: true);
/// The `NativeTypedData` class from dart:typed_data.
ClassEntity _typedDataClass;
+ @override
ClassEntity get typedDataClass =>
_typedDataClass ??= _findClass(typedDataLibrary, 'NativeTypedData');
/// Constructor of the `Symbol` class in dart:internal. This getter will
/// ensure that `Symbol` is resolved and lookup the constructor on demand.
ConstructorEntity _symbolConstructorTarget;
+ @override
ConstructorEntity get symbolConstructorTarget {
// TODO(johnniwinther): Kernel does not include redirecting factories
// so this cannot be found in kernel. Find a consistent way to handle
@@ -764,6 +790,7 @@
/// Whether [element] is the same as [symbolConstructor]. Used to check
/// for the constructor without computing it until it is likely to be seen.
+ @override
bool isSymbolConstructor(ConstructorEntity element) {
assert(element != null);
_ensureSymbolConstructorDependencies();
@@ -773,17 +800,20 @@
/// The function `identical` in dart:core.
FunctionEntity _identicalFunction;
+ @override
FunctionEntity get identicalFunction =>
_identicalFunction ??= _findLibraryMember(coreLibrary, 'identical');
/// Whether [element] is the `Function.apply` method. This will not
/// resolve the apply method if it hasn't been seen yet during compilation.
+ @override
bool isFunctionApplyMethod(MemberEntity element) =>
element.name == 'apply' && element.enclosingClass == functionClass;
/// Returns `true` if [element] is the unnamed constructor of `List`. This
/// will not resolve the constructor if it hasn't been seen yet during
/// compilation.
+ @override
bool isUnnamedListConstructor(ConstructorEntity element) =>
(element.name == '' && element.enclosingClass == listClass) ||
(element.name == 'list' && element.enclosingClass == jsArrayClass);
@@ -791,54 +821,66 @@
/// Returns `true` if [element] is the 'filled' constructor of `List`. This
/// will not resolve the constructor if it hasn't been seen yet during
/// compilation.
+ @override
bool isFilledListConstructor(ConstructorEntity element) =>
element.name == 'filled' && element.enclosingClass == listClass;
/// The `dynamic` type.
+ @override
DynamicType get dynamicType => _env.dynamicType;
/// The `Object` type defined in 'dart:core'.
+ @override
InterfaceType get objectType => _getRawType(objectClass);
/// The `bool` type defined in 'dart:core'.
+ @override
InterfaceType get boolType => _getRawType(boolClass);
/// The `num` type defined in 'dart:core'.
+ @override
InterfaceType get numType => _getRawType(numClass);
/// The `int` type defined in 'dart:core'.
+ @override
InterfaceType get intType => _getRawType(intClass);
/// The `double` type defined in 'dart:core'.
+ @override
InterfaceType get doubleType => _getRawType(doubleClass);
- /// The `Resource` type defined in 'dart:core'.
- InterfaceType get resourceType => _getRawType(resourceClass);
-
/// The `String` type defined in 'dart:core'.
+ @override
InterfaceType get stringType => _getRawType(stringClass);
/// The `Symbol` type defined in 'dart:core'.
+ @override
InterfaceType get symbolType => _getRawType(symbolClass);
/// The `Function` type defined in 'dart:core'.
+ @override
InterfaceType get functionType => _getRawType(functionClass);
/// The `Null` type defined in 'dart:core'.
+ @override
InterfaceType get nullType => _getRawType(nullClass);
/// The `Type` type defined in 'dart:core'.
+ @override
InterfaceType get typeType => _getRawType(typeClass);
+ @override
InterfaceType get typeLiteralType => _getRawType(typeLiteralClass);
/// The `StackTrace` type defined in 'dart:core';
+ @override
InterfaceType get stackTraceType => _getRawType(stackTraceClass);
/// Returns an instance of the `List` type defined in 'dart:core' with
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
+ @override
InterfaceType listType([DartType elementType]) {
if (elementType == null) {
return _getRawType(listClass);
@@ -850,6 +892,7 @@
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
+ @override
InterfaceType setType([DartType elementType]) {
if (elementType == null) {
return _getRawType(setClass);
@@ -861,6 +904,7 @@
/// [keyType] and [valueType] as its type arguments.
///
/// If no type arguments are provided, the canonical raw type is returned.
+ @override
InterfaceType mapType([DartType keyType, DartType valueType]) {
if (keyType == null && valueType == null) {
return _getRawType(mapClass);
@@ -876,6 +920,7 @@
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
+ @override
InterfaceType iterableType([DartType elementType]) {
if (elementType == null) {
return _getRawType(iterableClass);
@@ -887,6 +932,7 @@
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
+ @override
InterfaceType futureType([DartType elementType]) {
if (elementType == null) {
return _getRawType(futureClass);
@@ -898,6 +944,7 @@
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
+ @override
InterfaceType streamType([DartType elementType]) {
if (elementType == null) {
return _getRawType(streamClass);
@@ -906,16 +953,19 @@
}
/// Returns `true` if [element] is a superclass of `String` or `num`.
+ @override
bool isNumberOrStringSupertype(ClassEntity element) {
return element == _findClass(coreLibrary, 'Comparable', required: false);
}
/// Returns `true` if [element] is a superclass of `String`.
+ @override
bool isStringOnlySupertype(ClassEntity element) {
return element == _findClass(coreLibrary, 'Pattern', required: false);
}
/// Returns `true` if [element] is a superclass of `List`.
+ @override
bool isListSupertype(ClassEntity element) => element == iterableClass;
ClassEntity _findClass(LibraryEntity library, String name,
@@ -953,6 +1003,7 @@
return _env.createInterfaceType(cls, typeArguments);
}
+ @override
InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
{bool hasProtoKey: false, bool onlyStringKeys: false}) {
ClassEntity classElement = onlyStringKeys
@@ -966,17 +1017,21 @@
}
}
+ @override
InterfaceType getConstantSetTypeFor(InterfaceType sourceType) =>
sourceType.treatAsRaw
? _env.getRawType(constSetLiteralClass)
: _env.createInterfaceType(
constSetLiteralClass, sourceType.typeArguments);
+ @override
FieldEntity get symbolField => symbolImplementationField;
+ @override
InterfaceType get symbolImplementationType =>
_env.getRawType(symbolImplementationClass);
+ @override
bool isDefaultEqualityImplementation(MemberEntity element) {
assert(element.name == '==');
ClassEntity classElement = element.enclosingClass;
@@ -988,6 +1043,7 @@
// From dart:core
ClassEntity _mapLiteralClass;
+ @override
ClassEntity get mapLiteralClass {
if (_mapLiteralClass == null) {
_mapLiteralClass = _env.lookupClass(coreLibrary, 'LinkedHashMap');
@@ -1016,27 +1072,32 @@
_env.lookupLocalClassMember(mapLiteralClass, '_makeEmpty');
}
+ @override
ConstructorEntity get mapLiteralConstructor {
_ensureMapLiteralHelpers();
return _mapLiteralConstructor;
}
+ @override
ConstructorEntity get mapLiteralConstructorEmpty {
_ensureMapLiteralHelpers();
return _mapLiteralConstructorEmpty;
}
+ @override
FunctionEntity get mapLiteralUntypedMaker {
_ensureMapLiteralHelpers();
return _mapLiteralUntypedMaker;
}
+ @override
FunctionEntity get mapLiteralUntypedEmptyMaker {
_ensureMapLiteralHelpers();
return _mapLiteralUntypedEmptyMaker;
}
ClassEntity _setLiteralClass;
+ @override
ClassEntity get setLiteralClass => _setLiteralClass ??=
_findClass(_env.lookupLibrary(Uris.dart_collection), 'LinkedHashSet');
@@ -1058,32 +1119,38 @@
_env.lookupLocalClassMember(setLiteralClass, '_makeEmpty');
}
+ @override
ConstructorEntity get setLiteralConstructor {
_ensureSetLiteralHelpers();
return _setLiteralConstructor;
}
+ @override
ConstructorEntity get setLiteralConstructorEmpty {
_ensureSetLiteralHelpers();
return _setLiteralConstructorEmpty;
}
+ @override
FunctionEntity get setLiteralUntypedMaker {
_ensureSetLiteralHelpers();
return _setLiteralUntypedMaker;
}
+ @override
FunctionEntity get setLiteralUntypedEmptyMaker {
_ensureSetLiteralHelpers();
return _setLiteralUntypedEmptyMaker;
}
FunctionEntity _objectNoSuchMethod;
+ @override
FunctionEntity get objectNoSuchMethod {
return _objectNoSuchMethod ??=
_env.lookupLocalClassMember(objectClass, Identifiers.noSuchMethod_);
}
+ @override
bool isDefaultNoSuchMethodImplementation(FunctionEntity element) {
ClassEntity classElement = element.enclosingClass;
return classElement == objectClass ||
@@ -1098,59 +1165,78 @@
FunctionEntity _findAsyncHelperFunction(String name) =>
_findLibraryMember(asyncLibrary, name);
+ @override
FunctionEntity get asyncHelperStartSync =>
_findAsyncHelperFunction("_asyncStartSync");
+ @override
FunctionEntity get asyncHelperAwait =>
_findAsyncHelperFunction("_asyncAwait");
+ @override
FunctionEntity get asyncHelperReturn =>
_findAsyncHelperFunction("_asyncReturn");
+ @override
FunctionEntity get asyncHelperRethrow =>
_findAsyncHelperFunction("_asyncRethrow");
+ @override
FunctionEntity get wrapBody =>
_findAsyncHelperFunction("_wrapJsFunctionForAsync");
+ @override
FunctionEntity get yieldStar => _env.lookupLocalClassMember(
_findAsyncHelperClass("_IterationMarker"), "yieldStar");
+ @override
FunctionEntity get yieldSingle => _env.lookupLocalClassMember(
_findAsyncHelperClass("_IterationMarker"), "yieldSingle");
+ @override
FunctionEntity get syncStarUncaughtError => _env.lookupLocalClassMember(
_findAsyncHelperClass("_IterationMarker"), "uncaughtError");
+ @override
FunctionEntity get asyncStarHelper =>
_findAsyncHelperFunction("_asyncStarHelper");
+ @override
FunctionEntity get streamOfController =>
_findAsyncHelperFunction("_streamOfController");
+ @override
FunctionEntity get endOfIteration => _env.lookupLocalClassMember(
_findAsyncHelperClass("_IterationMarker"), "endOfIteration");
+ @override
ClassEntity get syncStarIterable =>
_findAsyncHelperClass("_SyncStarIterable");
+ @override
ClassEntity get futureImplementation => _findAsyncHelperClass('_Future');
+ @override
ClassEntity get controllerStream =>
_findAsyncHelperClass("_ControllerStream");
+ @override
ClassEntity get streamIterator => _findAsyncHelperClass("StreamIterator");
+ @override
ConstructorEntity get streamIteratorConstructor =>
_env.lookupConstructor(streamIterator, "");
FunctionEntity _syncStarIterableFactory;
+ @override
FunctionEntity get syncStarIterableFactory => _syncStarIterableFactory ??=
_findAsyncHelperFunction('_makeSyncStarIterable');
FunctionEntity _asyncAwaitCompleterFactory;
+ @override
FunctionEntity get asyncAwaitCompleterFactory =>
_asyncAwaitCompleterFactory ??=
_findAsyncHelperFunction('_makeAsyncAwaitCompleter');
FunctionEntity _asyncStarStreamControllerFactory;
+ @override
FunctionEntity get asyncStarStreamControllerFactory =>
_asyncStarStreamControllerFactory ??=
_findAsyncHelperFunction('_makeAsyncStarStreamController');
@@ -1163,92 +1249,114 @@
_findLibraryMember(interceptorsLibrary, name);
ClassEntity _jsInterceptorClass;
+ @override
ClassEntity get jsInterceptorClass =>
_jsInterceptorClass ??= _findInterceptorsClass('Interceptor');
ClassEntity _jsStringClass;
+ @override
ClassEntity get jsStringClass =>
_jsStringClass ??= _findInterceptorsClass('JSString');
ClassEntity _jsArrayClass;
+ @override
ClassEntity get jsArrayClass =>
_jsArrayClass ??= _findInterceptorsClass('JSArray');
ClassEntity _jsNumberClass;
+ @override
ClassEntity get jsNumberClass =>
_jsNumberClass ??= _findInterceptorsClass('JSNumber');
ClassEntity _jsIntClass;
+ @override
ClassEntity get jsIntClass => _jsIntClass ??= _findInterceptorsClass('JSInt');
ClassEntity _jsDoubleClass;
+ @override
ClassEntity get jsDoubleClass =>
_jsDoubleClass ??= _findInterceptorsClass('JSDouble');
ClassEntity _jsNullClass;
+ @override
ClassEntity get jsNullClass =>
_jsNullClass ??= _findInterceptorsClass('JSNull');
ClassEntity _jsBoolClass;
+ @override
ClassEntity get jsBoolClass =>
_jsBoolClass ??= _findInterceptorsClass('JSBool');
ClassEntity _jsPlainJavaScriptObjectClass;
+ @override
ClassEntity get jsPlainJavaScriptObjectClass =>
_jsPlainJavaScriptObjectClass ??=
_findInterceptorsClass('PlainJavaScriptObject');
ClassEntity _jsUnknownJavaScriptObjectClass;
+ @override
ClassEntity get jsUnknownJavaScriptObjectClass =>
_jsUnknownJavaScriptObjectClass ??=
_findInterceptorsClass('UnknownJavaScriptObject');
ClassEntity _jsJavaScriptFunctionClass;
+ @override
ClassEntity get jsJavaScriptFunctionClass => _jsJavaScriptFunctionClass ??=
_findInterceptorsClass('JavaScriptFunction');
ClassEntity _jsJavaScriptObjectClass;
+ @override
ClassEntity get jsJavaScriptObjectClass =>
_jsJavaScriptObjectClass ??= _findInterceptorsClass('JavaScriptObject');
ClassEntity _jsIndexableClass;
+ @override
ClassEntity get jsIndexableClass =>
_jsIndexableClass ??= _findInterceptorsClass('JSIndexable');
ClassEntity _jsMutableIndexableClass;
+ @override
ClassEntity get jsMutableIndexableClass =>
_jsMutableIndexableClass ??= _findInterceptorsClass('JSMutableIndexable');
ClassEntity _jsMutableArrayClass;
+ @override
ClassEntity get jsMutableArrayClass =>
_jsMutableArrayClass ??= _findInterceptorsClass('JSMutableArray');
ClassEntity _jsFixedArrayClass;
+ @override
ClassEntity get jsFixedArrayClass =>
_jsFixedArrayClass ??= _findInterceptorsClass('JSFixedArray');
ClassEntity _jsExtendableArrayClass;
+ @override
ClassEntity get jsExtendableArrayClass =>
_jsExtendableArrayClass ??= _findInterceptorsClass('JSExtendableArray');
ClassEntity _jsUnmodifiableArrayClass;
+ @override
ClassEntity get jsUnmodifiableArrayClass => _jsUnmodifiableArrayClass ??=
_findInterceptorsClass('JSUnmodifiableArray');
ClassEntity _jsPositiveIntClass;
+ @override
ClassEntity get jsPositiveIntClass =>
_jsPositiveIntClass ??= _findInterceptorsClass('JSPositiveInt');
ClassEntity _jsUInt32Class;
+ @override
ClassEntity get jsUInt32Class =>
_jsUInt32Class ??= _findInterceptorsClass('JSUInt32');
ClassEntity _jsUInt31Class;
+ @override
ClassEntity get jsUInt31Class =>
_jsUInt31Class ??= _findInterceptorsClass('JSUInt31');
/// Returns `true` member is the 'findIndexForNativeSubclassType' method
/// declared in `dart:_interceptors`.
+ @override
bool isFindIndexForNativeSubclassType(MemberEntity member) {
return member.name == 'findIndexForNativeSubclassType' &&
member.isTopLevel &&
@@ -1256,24 +1364,29 @@
}
FunctionEntity _getNativeInterceptorMethod;
+ @override
FunctionEntity get getNativeInterceptorMethod =>
_getNativeInterceptorMethod ??=
_findInterceptorsFunction('getNativeInterceptor');
/// Returns `true` if [selector] applies to `JSIndexable.length`.
+ @override
bool appliesToJsIndexableLength(Selector selector) {
return selector.name == 'length' && (selector.isGetter || selector.isCall);
}
ConstructorEntity _jsArrayTypedConstructor;
+ @override
ConstructorEntity get jsArrayTypedConstructor =>
_jsArrayTypedConstructor ??= _findConstructor(jsArrayClass, 'typed');
FunctionEntity _jsArrayRemoveLast;
+ @override
FunctionEntity get jsArrayRemoveLast =>
_jsArrayRemoveLast ??= _findClassMember(jsArrayClass, 'removeLast');
FunctionEntity _jsArrayAdd;
+ @override
FunctionEntity get jsArrayAdd =>
_jsArrayAdd ??= _findClassMember(jsArrayClass, 'add');
@@ -1281,6 +1394,7 @@
return cls.name == 'JSString' && cls.library == interceptorsLibrary;
}
+ @override
bool isJsStringSplit(MemberEntity member) {
return member.name == 'split' &&
member.isInstanceMember &&
@@ -1291,6 +1405,7 @@
/// in the given [world].
///
/// Returns `false` if `JSString.split` is not available.
+ @override
bool appliesToJsStringSplit(Selector selector, AbstractValue receiver,
AbstractValueDomain abstractValueDomain) {
if (_jsStringSplit == null) {
@@ -1308,23 +1423,28 @@
}
FunctionEntity _jsStringSplit;
+ @override
FunctionEntity get jsStringSplit =>
_jsStringSplit ??= _findClassMember(jsStringClass, 'split');
FunctionEntity _jsStringToString;
+ @override
FunctionEntity get jsStringToString =>
_jsStringToString ??= _findClassMember(jsStringClass, 'toString');
FunctionEntity _jsStringOperatorAdd;
+ @override
FunctionEntity get jsStringOperatorAdd =>
_jsStringOperatorAdd ??= _findClassMember(jsStringClass, '+');
ClassEntity _jsConstClass;
+ @override
ClassEntity get jsConstClass =>
_jsConstClass ??= _findClass(foreignLibrary, 'JS_CONST');
// From package:js
ClassEntity _jsAnnotationClass;
+ @override
ClassEntity get jsAnnotationClass {
if (_jsAnnotationClass == null) {
LibraryEntity library = _env.lookupLibrary(Uris.package_js);
@@ -1335,6 +1455,7 @@
}
ClassEntity _jsAnonymousClass;
+ @override
ClassEntity get jsAnonymousClass {
if (_jsAnonymousClass == null) {
LibraryEntity library = _env.lookupLibrary(Uris.package_js);
@@ -1346,6 +1467,7 @@
// From dart:_js_helper
// TODO(johnniwinther): Avoid the need for this (from [CheckedModeHelper]).
+ @override
FunctionEntity findHelperFunction(String name) => _findHelperFunction(name);
FunctionEntity _findHelperFunction(String name) =>
@@ -1355,47 +1477,58 @@
_findClass(jsHelperLibrary, name);
ClassEntity _closureClass;
+ @override
ClassEntity get closureClass => _closureClass ??= _findHelperClass('Closure');
ClassEntity _boundClosureClass;
+ @override
ClassEntity get boundClosureClass =>
_boundClosureClass ??= _findHelperClass('BoundClosure');
ClassEntity _typeLiteralClass;
+ @override
ClassEntity get typeLiteralClass =>
_typeLiteralClass ??= _findHelperClass('TypeImpl');
ClassEntity _constMapLiteralClass;
+ @override
ClassEntity get constMapLiteralClass =>
_constMapLiteralClass ??= _findHelperClass('ConstantMap');
// TODO(fishythefish): Implement a `ConstantSet` class and update the backend
// impacts + constant emitter accordingly.
ClassEntity _constSetLiteralClass;
+ @override
ClassEntity get constSetLiteralClass =>
_constSetLiteralClass ??= unmodifiableSetClass;
ClassEntity _typeVariableClass;
+ @override
ClassEntity get typeVariableClass =>
_typeVariableClass ??= _findHelperClass('TypeVariable');
ClassEntity _pragmaClass;
+ @override
ClassEntity get pragmaClass =>
_pragmaClass ??= _findClass(coreLibrary, 'pragma');
FieldEntity _pragmaClassNameField;
+ @override
FieldEntity get pragmaClassNameField =>
_pragmaClassNameField ??= _findClassMember(pragmaClass, 'name');
FieldEntity _pragmaClassOptionsField;
+ @override
FieldEntity get pragmaClassOptionsField =>
_pragmaClassOptionsField ??= _findClassMember(pragmaClass, 'options');
ClassEntity _jsInvocationMirrorClass;
+ @override
ClassEntity get jsInvocationMirrorClass =>
_jsInvocationMirrorClass ??= _findHelperClass('JSInvocationMirror');
MemberEntity _invocationTypeArgumentGetter;
+ @override
MemberEntity get invocationTypeArgumentGetter =>
_invocationTypeArgumentGetter ??=
_findClassMember(jsInvocationMirrorClass, 'typeArguments');
@@ -1403,110 +1536,143 @@
/// Interface used to determine if an object has the JavaScript
/// indexing behavior. The interface is only visible to specific libraries.
ClassEntity _jsIndexingBehaviorInterface;
+ @override
ClassEntity get jsIndexingBehaviorInterface =>
_jsIndexingBehaviorInterface ??=
_findHelperClass('JavaScriptIndexingBehavior');
+ @override
ClassEntity get stackTraceHelperClass => _findHelperClass('_StackTrace');
+ @override
ClassEntity get constantMapClass =>
_findHelperClass(constant_system.JavaScriptMapConstant.DART_CLASS);
+ @override
ClassEntity get constantStringMapClass =>
_findHelperClass(constant_system.JavaScriptMapConstant.DART_STRING_CLASS);
+ @override
ClassEntity get constantProtoMapClass =>
_findHelperClass(constant_system.JavaScriptMapConstant.DART_PROTO_CLASS);
+ @override
ClassEntity get generalConstantMapClass => _findHelperClass(
constant_system.JavaScriptMapConstant.DART_GENERAL_CLASS);
+ @override
ClassEntity get annotationCreatesClass => _findHelperClass('Creates');
+ @override
ClassEntity get annotationReturnsClass => _findHelperClass('Returns');
+ @override
ClassEntity get annotationJSNameClass => _findHelperClass('JSName');
/// The class for native annotations defined in dart:_js_helper.
ClassEntity _nativeAnnotationClass;
+ @override
ClassEntity get nativeAnnotationClass =>
_nativeAnnotationClass ??= _findHelperClass('Native');
ConstructorEntity _typeVariableConstructor;
+ @override
ConstructorEntity get typeVariableConstructor => _typeVariableConstructor ??=
_env.lookupConstructor(typeVariableClass, '');
FunctionEntity _assertTest;
+ @override
FunctionEntity get assertTest =>
_assertTest ??= _findHelperFunction('assertTest');
FunctionEntity _assertThrow;
+ @override
FunctionEntity get assertThrow =>
_assertThrow ??= _findHelperFunction('assertThrow');
FunctionEntity _assertHelper;
+ @override
FunctionEntity get assertHelper =>
_assertHelper ??= _findHelperFunction('assertHelper');
FunctionEntity _assertUnreachableMethod;
+ @override
FunctionEntity get assertUnreachableMethod =>
_assertUnreachableMethod ??= _findHelperFunction('assertUnreachable');
/// Holds the method "getIsolateAffinityTag" when dart:_js_helper has been
/// loaded.
FunctionEntity _getIsolateAffinityTagMarker;
+ @override
FunctionEntity get getIsolateAffinityTagMarker =>
_getIsolateAffinityTagMarker ??=
_findHelperFunction('getIsolateAffinityTag');
/// Holds the method "requiresPreamble" in _js_helper.
FunctionEntity _requiresPreambleMarker;
+ @override
FunctionEntity get requiresPreambleMarker =>
_requiresPreambleMarker ??= _findHelperFunction('requiresPreamble');
+ @override
FunctionEntity get loadLibraryWrapper =>
_findHelperFunction("_loadLibraryWrapper");
+ @override
FunctionEntity get loadDeferredLibrary =>
_findHelperFunction("loadDeferredLibrary");
+ @override
FunctionEntity get boolConversionCheck =>
_findHelperFunction('boolConversionCheck');
+ @override
FunctionEntity get traceHelper => _findHelperFunction('traceHelper');
+ @override
FunctionEntity get closureFromTearOff =>
_findHelperFunction('closureFromTearOff');
+ @override
FunctionEntity get isJsIndexable => _findHelperFunction('isJsIndexable');
+ @override
FunctionEntity get throwIllegalArgumentException =>
_findHelperFunction('iae');
+ @override
FunctionEntity get throwIndexOutOfRangeException =>
_findHelperFunction('ioore');
+ @override
FunctionEntity get exceptionUnwrapper =>
_findHelperFunction('unwrapException');
+ @override
FunctionEntity get throwRuntimeError =>
_findHelperFunction('throwRuntimeError');
+ @override
FunctionEntity get throwUnsupportedError =>
_findHelperFunction('throwUnsupportedError');
+ @override
FunctionEntity get throwTypeError => _findHelperFunction('throwTypeError');
+ @override
FunctionEntity get throwAbstractClassInstantiationError =>
_findHelperFunction('throwAbstractClassInstantiationError');
FunctionEntity _cachedCheckConcurrentModificationError;
+ @override
FunctionEntity get checkConcurrentModificationError =>
_cachedCheckConcurrentModificationError ??=
_findHelperFunction('checkConcurrentModificationError');
+ @override
FunctionEntity get throwConcurrentModificationError =>
_findHelperFunction('throwConcurrentModificationError');
/// Return `true` if [member] is the 'checkInt' function defined in
/// dart:_js_helpers.
+ @override
bool isCheckInt(MemberEntity member) {
return member.isFunction &&
member.isTopLevel &&
@@ -1516,6 +1682,7 @@
/// Return `true` if [member] is the 'checkNum' function defined in
/// dart:_js_helpers.
+ @override
bool isCheckNum(MemberEntity member) {
return member.isFunction &&
member.isTopLevel &&
@@ -1525,6 +1692,7 @@
/// Return `true` if [member] is the 'checkString' function defined in
/// dart:_js_helpers.
+ @override
bool isCheckString(MemberEntity member) {
return member.isFunction &&
member.isTopLevel &&
@@ -1532,92 +1700,123 @@
member.name == 'checkString';
}
+ @override
FunctionEntity get stringInterpolationHelper => _findHelperFunction('S');
+ @override
FunctionEntity get wrapExceptionHelper =>
_findHelperFunction('wrapException');
+ @override
FunctionEntity get throwExpressionHelper =>
_findHelperFunction('throwExpression');
+ @override
FunctionEntity get closureConverter =>
_findHelperFunction('convertDartClosureToJS');
+ @override
FunctionEntity get traceFromException =>
_findHelperFunction('getTraceFromException');
+ @override
FunctionEntity get setRuntimeTypeInfo =>
_findHelperFunction('setRuntimeTypeInfo');
+ @override
FunctionEntity get getRuntimeTypeInfo =>
_findHelperFunction('getRuntimeTypeInfo');
+ @override
FunctionEntity get getTypeArgumentByIndex =>
_findHelperFunction('getTypeArgumentByIndex');
+ @override
FunctionEntity get computeSignature =>
_findHelperFunction('computeSignature');
+ @override
FunctionEntity get getRuntimeTypeArguments =>
_findHelperFunction('getRuntimeTypeArguments');
+ @override
FunctionEntity get getRuntimeTypeArgument =>
_findHelperFunction('getRuntimeTypeArgument');
+ @override
FunctionEntity get getRuntimeTypeArgumentIntercepted =>
_findHelperFunction('getRuntimeTypeArgumentIntercepted');
+ @override
FunctionEntity get assertIsSubtype => _findHelperFunction('assertIsSubtype');
+ @override
FunctionEntity get checkSubtype => _findHelperFunction('checkSubtype');
+ @override
FunctionEntity get assertSubtype => _findHelperFunction('assertSubtype');
+ @override
FunctionEntity get subtypeCast => _findHelperFunction('subtypeCast');
+ @override
FunctionEntity get functionTypeTest =>
_findHelperFunction('functionTypeTest');
+ @override
FunctionEntity get futureOrTest => _findHelperFunction('futureOrTest');
+ @override
FunctionEntity get checkSubtypeOfRuntimeType =>
_findHelperFunction('checkSubtypeOfRuntimeType');
+ @override
FunctionEntity get assertSubtypeOfRuntimeType =>
_findHelperFunction('assertSubtypeOfRuntimeType');
+ @override
FunctionEntity get subtypeOfRuntimeTypeCast =>
_findHelperFunction('subtypeOfRuntimeTypeCast');
+ @override
FunctionEntity get checkDeferredIsLoaded =>
_findHelperFunction('checkDeferredIsLoaded');
+ @override
FunctionEntity get throwNoSuchMethod =>
_findHelperFunction('throwNoSuchMethod');
+ @override
FunctionEntity get createRuntimeType =>
_findHelperFunction('createRuntimeType');
+ @override
FunctionEntity get fallThroughError =>
_findHelperFunction("getFallThroughError");
+ @override
FunctionEntity get createInvocationMirror =>
_findHelperFunction('createInvocationMirror');
+ @override
bool isCreateInvocationMirrorHelper(MemberEntity member) {
return member.isTopLevel &&
member.name == '_createInvocationMirror' &&
member.library == coreLibrary;
}
+ @override
FunctionEntity get createUnmangledInvocationMirror =>
_findHelperFunction('createUnmangledInvocationMirror');
+ @override
FunctionEntity get cyclicThrowHelper =>
_findHelperFunction("throwCyclicInit");
+ @override
FunctionEntity get defineProperty => _findHelperFunction('defineProperty');
+ @override
bool isExtractTypeArguments(FunctionEntity member) {
return member.name == 'extractTypeArguments' &&
member.library == internalLibrary;
@@ -1634,22 +1833,27 @@
}
}
+ @override
ClassEntity getInstantiationClass(int typeArgumentCount) {
_checkTypeArgumentCount(typeArgumentCount);
return _findHelperClass('Instantiation$typeArgumentCount');
}
+ @override
FunctionEntity getInstantiateFunction(int typeArgumentCount) {
_checkTypeArgumentCount(typeArgumentCount);
return _findHelperFunction('instantiate$typeArgumentCount');
}
+ @override
FunctionEntity get instantiatedGenericFunctionType =>
_findHelperFunction('instantiatedGenericFunctionType');
+ @override
FunctionEntity get extractFunctionTypeObjectFromInternal =>
_findHelperFunction('extractFunctionTypeObjectFromInternal');
+ @override
bool isInstantiationClass(ClassEntity cls) {
return cls.library == _jsHelperLibrary &&
cls.name != 'Instantiation' &&
@@ -1659,15 +1863,19 @@
// From dart:_internal
ClassEntity _symbolImplementationClass;
+ @override
ClassEntity get symbolImplementationClass =>
_symbolImplementationClass ??= _findClass(internalLibrary, 'Symbol');
/// Used to annotate items that have the keyword "native".
ClassEntity _externalNameClass;
+ @override
ClassEntity get externalNameClass =>
_externalNameClass ??= _findClass(internalLibrary, 'ExternalName');
+ @override
InterfaceType get externalNameType => _getRawType(externalNameClass);
+ @override
ConstructorEntity get symbolValidatedConstructor =>
_symbolValidatedConstructor ??=
_findConstructor(symbolImplementationClass, 'validated');
@@ -1680,6 +1888,7 @@
required: true);
ConstructorEntity _symbolValidatedConstructor;
+ @override
bool isSymbolValidatedConstructor(ConstructorEntity element) {
if (_symbolValidatedConstructor != null) {
return element == _symbolValidatedConstructor;
@@ -1690,11 +1899,13 @@
// From dart:_native_typed_data
ClassEntity _typedArrayOfIntClass;
+ @override
ClassEntity get typedArrayOfIntClass => _typedArrayOfIntClass ??= _findClass(
_env.lookupLibrary(Uris.dart__native_typed_data, required: true),
'NativeTypedArrayOfInt');
ClassEntity _typedArrayOfDoubleClass;
+ @override
ClassEntity get typedArrayOfDoubleClass =>
_typedArrayOfDoubleClass ??= _findClass(
_env.lookupLibrary(Uris.dart__native_typed_data, required: true),
@@ -1704,19 +1915,18 @@
/// Holds the class for the [JsGetName] enum.
ClassEntity _jsGetNameEnum;
+ @override
ClassEntity get jsGetNameEnum => _jsGetNameEnum ??= _findClass(
_env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
'JsGetName');
/// Holds the class for the [JsBuiltins] enum.
ClassEntity _jsBuiltinEnum;
+ @override
ClassEntity get jsBuiltinEnum => _jsBuiltinEnum ??= _findClass(
_env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
'JsBuiltin');
- static final Uri PACKAGE_META_DART2JS =
- new Uri(scheme: 'package', path: 'meta/dart2js.dart');
-
bool _metaAnnotationChecked = false;
ClassEntity _metaNoInlineClass;
ClassEntity _metaTryInlineClass;
@@ -1724,7 +1934,7 @@
void _ensureMetaAnnotations() {
if (!_metaAnnotationChecked) {
_metaAnnotationChecked = true;
- LibraryEntity library = _env.lookupLibrary(PACKAGE_META_DART2JS);
+ LibraryEntity library = _env.lookupLibrary(Uris.package_meta_dart2js);
if (library != null) {
_metaNoInlineClass = _env.lookupClass(library, '_NoInline');
_metaTryInlineClass = _env.lookupClass(library, '_TryInline');
@@ -1737,22 +1947,26 @@
}
}
+ @override
ClassEntity get metaNoInlineClass {
_ensureMetaAnnotations();
return _metaNoInlineClass;
}
+ @override
ClassEntity get metaTryInlineClass {
_ensureMetaAnnotations();
return _metaTryInlineClass;
}
+ @override
bool isForeign(MemberEntity element) => element.library == foreignLibrary;
/// Returns `true` if [member] is a "foreign helper", that is, a member whose
/// semantics is defined synthetically and not through Dart code.
///
/// Most foreign helpers are located in the `dart:_foreign_helper` library.
+ @override
bool isForeignHelper(MemberEntity member) {
return member.library == foreignLibrary ||
isCreateInvocationMirrorHelper(member);
@@ -1765,6 +1979,7 @@
///
/// This returns `false` for JS interop members which therefore must be
/// allowed to be external through the JS interop annotation handling.
+ @override
bool isExternalAllowed(FunctionEntity function) {
return isForeignHelper(function) ||
(function is ConstructorEntity &&
@@ -1777,6 +1992,7 @@
/// Returns `true` if the implementation of the 'operator ==' [function] is
/// known to handle `null` as argument.
+ @override
bool operatorEqHandlesNullArgument(FunctionEntity function) {
assert(function.name == '==',
failedAt(function, "Unexpected function $function."));
@@ -1786,6 +2002,7 @@
cls == jsNullClass;
}
+ @override
ClassEntity getDefaultSuperclass(
ClassEntity cls, NativeBasicData nativeBasicData) {
if (nativeBasicData.isJsInteropClass(cls)) {
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index baffff3..2eb6455 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -673,6 +673,7 @@
class CompilerDiagnosticReporter extends DiagnosticReporter {
final Compiler compiler;
+ @override
final DiagnosticOptions options;
Entity _currentElement;
@@ -690,6 +691,7 @@
Entity get currentElement => _currentElement;
+ @override
DiagnosticMessage createMessage(Spannable spannable, MessageKind messageKind,
[Map arguments = const {}]) {
SourceSpan span = spanFromSpannable(spannable);
@@ -698,22 +700,26 @@
return new DiagnosticMessage(span, spannable, message);
}
+ @override
void reportError(DiagnosticMessage message,
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
reportDiagnosticInternal(message, infos, api.Diagnostic.ERROR);
}
+ @override
void reportWarning(DiagnosticMessage message,
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
reportDiagnosticInternal(message, infos, api.Diagnostic.WARNING);
}
+ @override
void reportHint(DiagnosticMessage message,
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
reportDiagnosticInternal(message, infos, api.Diagnostic.HINT);
}
@deprecated
+ @override
void reportInfo(Spannable node, MessageKind messageKind,
[Map arguments = const {}]) {
reportDiagnosticInternal(createMessage(node, messageKind, arguments),
@@ -779,6 +785,7 @@
/// Perform an operation, [f], returning the return value from [f]. If an
/// error occurs then report it as having occurred during compilation of
/// [element]. Can be nested.
+ @override
withCurrentElement(Entity element, f()) {
Entity old = currentElement;
_currentElement = element;
@@ -832,6 +839,7 @@
throw 'No error location.';
}
+ @override
SourceSpan spanFromSpannable(Spannable spannable) {
if (spannable == CURRENT_ELEMENT_SPANNABLE) {
spannable = currentElement;
@@ -852,6 +860,7 @@
}
}
+ @override
internalError(Spannable spannable, reason) {
String message = tryToString(reason);
reportDiagnosticInternal(
@@ -886,6 +895,7 @@
return element != null ? element : currentElement;
}
+ @override
void log(message) {
Message msg = MessageTemplate.TEMPLATES[MessageKind.GENERIC]
.message({'text': '$message'});
@@ -953,11 +963,13 @@
final Map<Entity, WorldImpact> _impactCache;
_MapImpactCacheDeleter(this._impactCache);
+ @override
void uncacheWorldImpact(Entity element) {
if (retainDataForTesting) return;
_impactCache.remove(element);
}
+ @override
void emptyCache() {
if (retainDataForTesting) return;
_impactCache.clear();
@@ -967,6 +979,7 @@
class _EmptyEnvironment implements Environment {
const _EmptyEnvironment();
+ @override
String valueOf(String key) => null;
}
@@ -990,6 +1003,7 @@
ProgressImpl(this._reporter);
+ @override
void showProgress(String prefix, int count, String suffix) {
if (_stopwatch.elapsedMilliseconds > 500) {
_reporter.log('$prefix$count$suffix');
@@ -997,6 +1011,7 @@
}
}
+ @override
void startPhase() {
_stopwatch.reset();
}
@@ -1008,12 +1023,14 @@
class InteractiveProgress implements Progress {
final Stopwatch _stopwatchPhase = new Stopwatch()..start();
final Stopwatch _stopwatchInterval = new Stopwatch()..start();
+ @override
void startPhase() {
print('');
_stopwatchPhase.reset();
_stopwatchInterval.reset();
}
+ @override
void showProgress(String prefix, int count, String suffix) {
if (_stopwatchInterval.elapsedMilliseconds > 500) {
var time = _stopwatchPhase.elapsedMilliseconds / 1000;
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index 701fc39..40ef21c 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -1001,8 +1001,10 @@
List<ConstantValue> values, this.protoValue, this.onlyStringKeys)
: this.keyList = keyList,
super(type, keyList.entries, values);
+ @override
bool get isMap => true;
+ @override
List<ConstantValue> getDependencies() {
List<ConstantValue> result = <ConstantValue>[];
if (onlyStringKeys) {
diff --git a/pkg/compiler/lib/src/constants/constructors.dart b/pkg/compiler/lib/src/constants/constructors.dart
index e575b5a..3b9fb60 100644
--- a/pkg/compiler/lib/src/constants/constructors.dart
+++ b/pkg/compiler/lib/src/constants/constructors.dart
@@ -74,13 +74,16 @@
GenerativeConstantConstructor(this.type, this.defaultValues, this.fieldMap,
this.assertions, this.superConstructorInvocation);
+ @override
ConstantConstructorKind get kind => ConstantConstructorKind.GENERATIVE;
+ @override
InterfaceType computeInstanceType(
EvaluationEnvironment environment, InterfaceType newType) {
return environment.substByContext(type, newType);
}
+ @override
InstanceData computeInstanceData(EvaluationEnvironment environment,
List<ConstantExpression> arguments, CallStructure callStructure) {
NormalizedArguments args =
@@ -96,10 +99,12 @@
return appliedInstanceData;
}
+ @override
accept(ConstantConstructorVisitor visitor, arg) {
return visitor.visitGenerative(this, arg);
}
+ @override
int get hashCode {
int hash = Hashing.objectHash(type);
hash = Hashing.mapHash(defaultValues, hash);
@@ -107,6 +112,7 @@
return Hashing.objectHash(superConstructorInvocation, hash);
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! GenerativeConstantConstructor) return false;
@@ -116,6 +122,7 @@
mapEquals(fieldMap, other.fieldMap);
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write("{'type': $type");
@@ -181,16 +188,19 @@
RedirectingGenerativeConstantConstructor(
this.defaultValues, this.thisConstructorInvocation);
+ @override
ConstantConstructorKind get kind {
return ConstantConstructorKind.REDIRECTING_GENERATIVE;
}
+ @override
InterfaceType computeInstanceType(
EvaluationEnvironment environment, InterfaceType newType) {
return environment.substByContext(
thisConstructorInvocation.computeInstanceType(environment), newType);
}
+ @override
InstanceData computeInstanceData(EvaluationEnvironment environment,
List<ConstantExpression> arguments, CallStructure callStructure) {
NormalizedArguments args =
@@ -201,15 +211,18 @@
return appliedInstanceData;
}
+ @override
accept(ConstantConstructorVisitor visitor, arg) {
return visitor.visitRedirectingGenerative(this, arg);
}
+ @override
int get hashCode {
int hash = Hashing.objectHash(thisConstructorInvocation);
return Hashing.mapHash(defaultValues, hash);
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! RedirectingGenerativeConstantConstructor) return false;
@@ -218,6 +231,7 @@
defaultValues, other.defaultValues);
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write("{'type': ${thisConstructorInvocation.type}");
@@ -236,16 +250,19 @@
RedirectingFactoryConstantConstructor(this.targetConstructorInvocation);
+ @override
ConstantConstructorKind get kind {
return ConstantConstructorKind.REDIRECTING_FACTORY;
}
+ @override
InterfaceType computeInstanceType(
EvaluationEnvironment environment, InterfaceType newType) {
return environment.substByContext(
targetConstructorInvocation.computeInstanceType(environment), newType);
}
+ @override
InstanceData computeInstanceData(EvaluationEnvironment environment,
List<ConstantExpression> arguments, CallStructure callStructure) {
ConstantConstructor constantConstructor =
@@ -254,20 +271,24 @@
environment, arguments, callStructure);
}
+ @override
accept(ConstantConstructorVisitor visitor, arg) {
return visitor.visitRedirectingFactory(this, arg);
}
+ @override
int get hashCode {
return Hashing.objectHash(targetConstructorInvocation);
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! RedirectingFactoryConstantConstructor) return false;
return targetConstructorInvocation == other.targetConstructorInvocation;
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write("{");
diff --git a/pkg/compiler/lib/src/constants/evaluation.dart b/pkg/compiler/lib/src/constants/evaluation.dart
index e9ac77a..f360735 100644
--- a/pkg/compiler/lib/src/constants/evaluation.dart
+++ b/pkg/compiler/lib/src/constants/evaluation.dart
@@ -71,6 +71,7 @@
abstract class EvaluationEnvironmentBase implements EvaluationEnvironment {
Link<Spannable> _spannableStack = const Link<Spannable>();
+ @override
InterfaceType enclosingConstructedType;
final Set<FieldEntity> _currentlyEvaluatedFields = new Set<FieldEntity>();
final bool constantRequired;
@@ -79,6 +80,7 @@
_spannableStack = _spannableStack.prepend(spannable);
}
+ @override
bool get checkCasts => true;
DiagnosticReporter get reporter;
@@ -239,6 +241,7 @@
return value;
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('NormalizedArguments[');
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index d0abc41..bb24531 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -99,10 +99,12 @@
int _computeHashCode();
+ @override
int get hashCode => _hashCode ??= _computeHashCode();
bool _equals(covariant ConstantExpression other);
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! ConstantExpression) return false;
@@ -111,6 +113,7 @@
return _equals(other);
}
+ @override
String toString() {
assertDebugMode('Use ConstantExpression.toDartText() or '
'ConstantExpression.toStructuredText() instead of '
@@ -136,8 +139,10 @@
/// A synthetic constant used to recover from errors.
class ErroneousConstantExpression extends ConstantExpression {
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.ERRONEOUS;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
// Do nothing. This is an error.
}
@@ -166,8 +171,10 @@
BoolConstantExpression(this.boolValue);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.BOOL;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitBool(this, context);
}
@@ -201,8 +208,10 @@
IntConstantExpression(this.intValue);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.INT;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitInt(this, context);
}
@@ -236,8 +245,10 @@
DoubleConstantExpression(this.doubleValue);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitDouble(this, context);
}
@@ -271,8 +282,10 @@
StringConstantExpression(this.stringValue);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.STRING;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitString(this, context);
}
@@ -304,8 +317,10 @@
class NullConstantExpression extends ConstantExpression {
NullConstantExpression();
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.NULL;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitNull(this, context);
}
@@ -338,8 +353,10 @@
ListConstantExpression(this.type, this.values);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.LIST;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitList(this, context);
}
@@ -362,6 +379,7 @@
type, values.map((v) => v.evaluate(environment)).toList());
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new ListConstantExpression(
type, values.map((v) => v.apply(arguments)).toList());
@@ -475,8 +493,10 @@
MapConstantExpression(this.type, this.keys, this.values);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.MAP;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitMap(this, context);
}
@@ -519,6 +539,7 @@
});
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new MapConstantExpression(
type,
@@ -571,8 +592,10 @@
assert(!arguments.contains(null));
}
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitConstructed(this, context);
}
@@ -605,6 +628,7 @@
.computeInstanceType(environment, type);
}
+ @override
ConstructedConstantExpression apply(NormalizedArguments arguments) {
return new ConstructedConstantExpression(type, target, callStructure,
this.arguments.map((a) => a.apply(arguments)).toList());
@@ -683,8 +707,10 @@
ConcatenateConstantExpression(this.expressions);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitConcatenate(this, context);
}
@@ -701,6 +727,7 @@
sb.write('])');
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new ConcatenateConstantExpression(
expressions.map((a) => a.apply(arguments)).toList());
@@ -782,8 +809,10 @@
SymbolConstantExpression(this.name);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.SYMBOL;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitSymbol(this, context);
}
@@ -822,8 +851,10 @@
"Unexpected type constant type: $type");
}
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.TYPE;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitType(this, context);
}
@@ -859,8 +890,10 @@
AsConstantExpression(this.expression, this.type);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.AS;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitAs(this, context);
}
@@ -936,8 +969,10 @@
FieldConstantExpression(this.element);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.FIELD;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitField(this, context);
}
@@ -970,8 +1005,10 @@
LocalVariableConstantExpression(this.element);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.LOCAL_VARIABLE;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitLocalVariable(this, context);
}
@@ -1003,8 +1040,10 @@
FunctionConstantExpression(this.element, this.type);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.FUNCTION;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitFunction(this, context);
}
@@ -1046,8 +1085,10 @@
static bool potentialOperator(BinaryOperator operator) =>
PRECEDENCE_MAP[operator.kind] != null;
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.BINARY;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitBinary(this, context);
}
@@ -1302,11 +1343,13 @@
return new NonConstantValue();
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new BinaryConstantExpression(
left.apply(arguments), operator, right.apply(arguments));
}
+ @override
// ignore: MISSING_RETURN
InterfaceType getKnownType(CommonElements commonElements) {
DartType knownLeftType = left.getKnownType(commonElements);
@@ -1359,6 +1402,7 @@
}
}
+ @override
int get precedence => PRECEDENCE_MAP[operator.kind];
@override
@@ -1410,8 +1454,10 @@
IdenticalConstantExpression(this.left, this.right);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitIdentical(this, context);
}
@@ -1435,11 +1481,13 @@
return new NonConstantValue();
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new IdenticalConstantExpression(
left.apply(arguments), right.apply(arguments));
}
+ @override
int get precedence => 15;
@override
@@ -1471,8 +1519,10 @@
assert(PRECEDENCE_MAP[operator.kind] != null);
}
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.UNARY;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitUnary(this, context);
}
@@ -1533,10 +1583,12 @@
return new NonConstantValue();
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new UnaryConstantExpression(operator, expression.apply(arguments));
}
+ @override
int get precedence => PRECEDENCE_MAP[operator.kind];
@override
@@ -1572,8 +1624,10 @@
StringLengthConstantExpression(this.expression);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.STRING_LENGTH;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitStringLength(this, context);
}
@@ -1602,10 +1656,12 @@
}
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new StringLengthConstantExpression(expression.apply(arguments));
}
+ @override
int get precedence => 15;
@override
@@ -1636,8 +1692,10 @@
ConditionalConstantExpression(this.condition, this.trueExp, this.falseExp);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.CONDITIONAL;
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitConditional(this, context);
}
@@ -1653,11 +1711,13 @@
sb.write(')');
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new ConditionalConstantExpression(condition.apply(arguments),
trueExp.apply(arguments), falseExp.apply(arguments));
}
+ @override
int get precedence => 3;
@override
@@ -1720,10 +1780,12 @@
PositionalArgumentReference(this.index);
+ @override
ConstantExpressionKind get kind {
return ConstantExpressionKind.POSITIONAL_REFERENCE;
}
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitPositional(this, context);
}
@@ -1733,6 +1795,7 @@
sb.write('Positional(index=$index)');
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return arguments.getPositionalArgument(index);
}
@@ -1758,10 +1821,12 @@
NamedArgumentReference(this.name);
+ @override
ConstantExpressionKind get kind {
return ConstantExpressionKind.NAMED_REFERENCE;
}
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitNamed(this, context);
}
@@ -1771,6 +1836,7 @@
sb.write('Named(name=$name)');
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return arguments.getNamedArgument(name);
}
@@ -1838,10 +1904,12 @@
ConstantExpression name, ConstantExpression defaultValue)
: super(name, defaultValue);
+ @override
ConstantExpressionKind get kind {
return ConstantExpressionKind.BOOL_FROM_ENVIRONMENT;
}
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitBoolFromEnvironment(this, context);
}
@@ -1898,6 +1966,7 @@
return new NonConstantValue();
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new BoolFromEnvironmentConstantExpression(name.apply(arguments),
defaultValue != null ? defaultValue.apply(arguments) : null);
@@ -1915,10 +1984,12 @@
ConstantExpression name, ConstantExpression defaultValue)
: super(name, defaultValue);
+ @override
ConstantExpressionKind get kind {
return ConstantExpressionKind.INT_FROM_ENVIRONMENT;
}
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitIntFromEnvironment(this, context);
}
@@ -1977,6 +2048,7 @@
return new NonConstantValue();
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new IntFromEnvironmentConstantExpression(name.apply(arguments),
defaultValue != null ? defaultValue.apply(arguments) : null);
@@ -1994,10 +2066,12 @@
ConstantExpression name, ConstantExpression defaultValue)
: super(name, defaultValue);
+ @override
ConstantExpressionKind get kind {
return ConstantExpressionKind.STRING_FROM_ENVIRONMENT;
}
+ @override
accept(ConstantExpressionVisitor visitor, [context]) {
return visitor.visitStringFromEnvironment(this, context);
}
@@ -2052,6 +2126,7 @@
return new NonConstantValue();
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new StringFromEnvironmentConstantExpression(name.apply(arguments),
defaultValue != null ? defaultValue.apply(arguments) : null);
@@ -2133,6 +2208,7 @@
return visitor.visitAssert(this, context);
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new AssertConstantExpression(
condition.apply(arguments), message?.apply(arguments));
@@ -2145,6 +2221,7 @@
InstantiationConstantExpression(this.typeArguments, this.expression);
+ @override
ConstantExpressionKind get kind => ConstantExpressionKind.INSTANTIATION;
@override
@@ -2167,6 +2244,7 @@
return Hashing.objectHash(expression, Hashing.listHash(typeArguments));
}
+ @override
ConstantExpression apply(NormalizedArguments arguments) {
return new InstantiationConstantExpression(
typeArguments, expression.apply(arguments));
@@ -2527,5 +2605,6 @@
sb.write(')');
}
+ @override
String toString() => sb.toString();
}
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index dc26f40..98af5f5 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -113,6 +113,7 @@
ConstantValueKind get kind;
+ @override
String toString() {
assertDebugMode("Use ConstantValue.toDartText() or "
"ConstantValue.toStructuredText() "
@@ -128,23 +129,31 @@
FunctionConstantValue(this.element, this.type);
+ @override
bool get isFunction => true;
+ @override
bool operator ==(var other) {
if (other is! FunctionConstantValue) return false;
return identical(other.element, element);
}
+ @override
List<ConstantValue> getDependencies() => const <ConstantValue>[];
+ @override
FunctionType getType(CommonElements types) => type;
+ @override
int get hashCode => (17 * element.hashCode) & 0x7fffffff;
+ @override
accept(ConstantValueVisitor visitor, arg) => visitor.visitFunction(this, arg);
+ @override
ConstantValueKind get kind => ConstantValueKind.FUNCTION;
+ @override
String toDartText() {
if (element.enclosingClass != null) {
return '${element.enclosingClass.name}.${element.name}';
@@ -153,6 +162,7 @@
}
}
+ @override
String toStructuredText() {
return 'FunctionConstant(${toDartText()})';
}
@@ -161,16 +171,20 @@
abstract class PrimitiveConstantValue extends ConstantValue {
const PrimitiveConstantValue();
+ @override
bool get isPrimitive => true;
+ @override
bool operator ==(var other) {
// Making this method abstract does not give us an error.
throw new UnsupportedError('PrimitiveConstant.==');
}
+ @override
int get hashCode => throw new UnsupportedError('PrimitiveConstant.hashCode');
// Primitive constants don't have dependencies.
+ @override
List<ConstantValue> getDependencies() => const <ConstantValue>[];
}
@@ -182,27 +196,36 @@
const NullConstantValue._internal();
+ @override
bool get isNull => true;
+ @override
DartType getType(CommonElements types) => types.nullType;
+ @override
bool operator ==(other) => other is NullConstantValue;
// The magic constant has no meaning. It is just a random value.
+ @override
int get hashCode => 785965825;
+ @override
accept(ConstantValueVisitor visitor, arg) => visitor.visitNull(this, arg);
+ @override
ConstantValueKind get kind => ConstantValueKind.NULL;
+ @override
String toStructuredText() => 'NullConstant';
+ @override
String toDartText() => 'null';
}
abstract class NumConstantValue extends PrimitiveConstantValue {
double get doubleValue;
+ @override
bool get isNum => true;
const NumConstantValue();
@@ -215,6 +238,7 @@
// to create new ones every time those values are used.
static Map<BigInt, IntConstantValue> _cachedValues = {};
+ @override
double get doubleValue => intValue.toDouble();
factory IntConstantValue(BigInt value) {
@@ -230,6 +254,7 @@
const IntConstantValue._internal(this.intValue);
+ @override
bool get isInt => true;
bool isUInt31() => intValue.toUnsigned(31) == intValue;
@@ -238,12 +263,16 @@
bool isPositive() => intValue >= BigInt.zero;
+ @override
bool get isZero => intValue == BigInt.zero;
+ @override
bool get isOne => intValue == BigInt.one;
+ @override
DartType getType(CommonElements types) => types.intType;
+ @override
bool operator ==(var other) {
// Ints and doubles are treated as separate constants.
if (other is! IntConstantValue) return false;
@@ -251,18 +280,24 @@
return intValue == otherInt.intValue;
}
+ @override
int get hashCode => intValue.hashCode & Hashing.SMI_MASK;
+ @override
accept(ConstantValueVisitor visitor, arg) => visitor.visitInt(this, arg);
+ @override
ConstantValueKind get kind => ConstantValueKind.INT;
+ @override
String toStructuredText() => 'IntConstant(${toDartText()})';
+ @override
String toDartText() => intValue.toString();
}
class DoubleConstantValue extends NumConstantValue {
+ @override
final double doubleValue;
factory DoubleConstantValue(double value) {
@@ -283,23 +318,32 @@
const DoubleConstantValue._internal(this.doubleValue);
+ @override
bool get isDouble => true;
+ @override
bool get isNaN => doubleValue.isNaN;
// We need to check for the negative sign since -0.0 == 0.0.
+ @override
bool get isMinusZero => doubleValue == 0.0 && doubleValue.isNegative;
+ @override
bool get isZero => doubleValue == 0.0;
+ @override
bool get isOne => doubleValue == 1.0;
+ @override
bool get isPositiveInfinity => doubleValue == double.infinity;
+ @override
bool get isNegativeInfinity => doubleValue == -double.infinity;
+ @override
DartType getType(CommonElements types) => types.doubleType;
+ @override
bool operator ==(var other) {
if (other is! DoubleConstantValue) return false;
DoubleConstantValue otherDouble = other;
@@ -313,14 +357,19 @@
}
}
+ @override
int get hashCode => doubleValue.hashCode;
+ @override
accept(ConstantValueVisitor visitor, arg) => visitor.visitDouble(this, arg);
+ @override
ConstantValueKind get kind => ConstantValueKind.DOUBLE;
+ @override
String toStructuredText() => 'DoubleConstant(${toDartText()})';
+ @override
String toDartText() => doubleValue.toString();
}
@@ -331,18 +380,23 @@
const BoolConstantValue._internal();
+ @override
bool get isBool => true;
bool get boolValue;
+ @override
DartType getType(CommonElements types) => types.boolType;
BoolConstantValue negate();
+ @override
accept(ConstantValueVisitor visitor, arg) => visitor.visitBool(this, arg);
+ @override
ConstantValueKind get kind => ConstantValueKind.BOOL;
+ @override
String toStructuredText() => 'BoolConstant(${toDartText()})';
}
@@ -351,18 +405,24 @@
const TrueConstantValue._internal() : super._internal();
+ @override
bool get isTrue => true;
+ @override
bool get boolValue => true;
+ @override
FalseConstantValue negate() => new FalseConstantValue();
+ @override
bool operator ==(var other) => identical(this, other);
// The magic constant is just a random value. It does not have any
// significance.
+ @override
int get hashCode => 499;
+ @override
String toDartText() => boolValue.toString();
}
@@ -371,24 +431,31 @@
const FalseConstantValue._internal() : super._internal();
+ @override
bool get isFalse => true;
+ @override
bool get boolValue => false;
+ @override
TrueConstantValue negate() => new TrueConstantValue();
+ @override
bool operator ==(var other) => identical(this, other);
// The magic constant is just a random value. It does not have any
// significance.
+ @override
int get hashCode => 536555975;
+ @override
String toDartText() => boolValue.toString();
}
class StringConstantValue extends PrimitiveConstantValue {
final String stringValue;
+ @override
final int hashCode;
// TODO(floitsch): cache StringConstants.
@@ -396,10 +463,13 @@
: this.stringValue = value,
this.hashCode = value.hashCode;
+ @override
bool get isString => true;
+ @override
DartType getType(CommonElements types) => types.stringType;
+ @override
bool operator ==(var other) {
if (identical(this, other)) return true;
if (other is! StringConstantValue) return false;
@@ -412,13 +482,17 @@
int get length => stringValue.length;
+ @override
accept(ConstantValueVisitor visitor, arg) => visitor.visitString(this, arg);
+ @override
ConstantValueKind get kind => ConstantValueKind.STRING;
// TODO(johnniwinther): Ensure correct escaping.
+ @override
String toDartText() => '"${stringValue}"';
+ @override
String toStructuredText() => 'StringConstant(${toDartText()})';
}
@@ -427,8 +501,10 @@
ObjectConstantValue(this.type);
+ @override
bool get isObject => true;
+ @override
DartType getType(CommonElements types) => type;
void _unparseTypeArguments(StringBuffer sb) {
@@ -446,28 +522,37 @@
TypeConstantValue(this.representedType, InterfaceType type) : super(type);
+ @override
bool get isType => true;
+ @override
bool operator ==(other) {
return other is TypeConstantValue &&
representedType.unaliased == other.representedType.unaliased;
}
+ @override
int get hashCode => representedType.unaliased.hashCode * 13;
+ @override
List<ConstantValue> getDependencies() => const <ConstantValue>[];
+ @override
accept(ConstantValueVisitor visitor, arg) => visitor.visitType(this, arg);
+ @override
ConstantValueKind get kind => ConstantValueKind.TYPE;
+ @override
String toDartText() => '$representedType';
+ @override
String toStructuredText() => 'TypeConstant(${representedType})';
}
class ListConstantValue extends ObjectConstantValue {
final List<ConstantValue> entries;
+ @override
final int hashCode;
ListConstantValue(InterfaceType type, List<ConstantValue> entries)
@@ -475,8 +560,10 @@
hashCode = Hashing.listHash(entries, Hashing.objectHash(type)),
super(type);
+ @override
bool get isList => true;
+ @override
bool operator ==(var other) {
if (identical(this, other)) return true;
if (other is! ListConstantValue) return false;
@@ -490,14 +577,18 @@
return true;
}
+ @override
List<ConstantValue> getDependencies() => entries;
int get length => entries.length;
+ @override
accept(ConstantValueVisitor visitor, arg) => visitor.visitList(this, arg);
+ @override
ConstantValueKind get kind => ConstantValueKind.LIST;
+ @override
String toDartText() {
StringBuffer sb = new StringBuffer();
_unparseTypeArguments(sb);
@@ -510,6 +601,7 @@
return sb.toString();
}
+ @override
String toStructuredText() {
StringBuffer sb = new StringBuffer();
sb.write('ListConstant(');
@@ -526,6 +618,7 @@
abstract class SetConstantValue extends ObjectConstantValue {
final List<ConstantValue> values;
+ @override
final int hashCode;
SetConstantValue(InterfaceType type, List<ConstantValue> values)
@@ -536,6 +629,7 @@
@override
bool get isSet => true;
+ @override
bool operator ==(var other) {
if (identical(this, other)) return true;
if (other is! SetConstantValue) return false;
@@ -585,6 +679,7 @@
abstract class MapConstantValue extends ObjectConstantValue {
final List<ConstantValue> keys;
final List<ConstantValue> values;
+ @override
final int hashCode;
Map<ConstantValue, ConstantValue> _lookupMap;
@@ -598,8 +693,10 @@
assert(keys.length == values.length);
}
+ @override
bool get isMap => true;
+ @override
bool operator ==(var other) {
if (identical(this, other)) return true;
if (other is! MapConstantValue) return false;
@@ -614,6 +711,7 @@
return true;
}
+ @override
List<ConstantValue> getDependencies() {
List<ConstantValue> result = <ConstantValue>[];
result.addAll(keys);
@@ -629,10 +727,13 @@
return lookupMap[key];
}
+ @override
accept(ConstantValueVisitor visitor, arg) => visitor.visitMap(this, arg);
+ @override
ConstantValueKind get kind => ConstantValueKind.MAP;
+ @override
String toDartText() {
StringBuffer sb = new StringBuffer();
_unparseTypeArguments(sb);
@@ -647,6 +748,7 @@
return sb.toString();
}
+ @override
String toStructuredText() {
StringBuffer sb = new StringBuffer();
sb.write('MapConstant(');
@@ -670,28 +772,37 @@
InterceptorConstantValue(this.cls);
+ @override
bool get isInterceptor => true;
+ @override
bool operator ==(other) {
return other is InterceptorConstantValue && cls == other.cls;
}
+ @override
int get hashCode => cls.hashCode * 43;
+ @override
List<ConstantValue> getDependencies() => const <ConstantValue>[];
+ @override
accept(ConstantValueVisitor visitor, arg) {
return visitor.visitInterceptor(this, arg);
}
+ @override
DartType getType(CommonElements types) => types.dynamicType;
+ @override
ConstantValueKind get kind => ConstantValueKind.INTERCEPTOR;
+ @override
String toDartText() {
return 'interceptor($cls)';
}
+ @override
String toStructuredText() {
return 'InterceptorConstant(${cls.name})';
}
@@ -703,26 +814,35 @@
SyntheticConstantValue(this.valueKind, this.payload);
+ @override
bool get isDummy => true;
+ @override
bool operator ==(other) {
return other is SyntheticConstantValue && payload == other.payload;
}
+ @override
get hashCode => payload.hashCode * 17 + valueKind.hashCode;
+ @override
List<ConstantValue> getDependencies() => const <ConstantValue>[];
+ @override
accept(ConstantValueVisitor visitor, arg) {
return visitor.visitSynthetic(this, arg);
}
+ @override
DartType getType(CommonElements types) => types.dynamicType;
+ @override
ConstantValueKind get kind => ConstantValueKind.SYNTHETIC;
+ @override
String toDartText() => 'synthetic($valueKind, $payload)';
+ @override
String toStructuredText() => 'SyntheticConstant($valueKind, $payload)';
}
@@ -730,6 +850,7 @@
// TODO(johnniwinther): Make [fields] private to avoid misuse of the map
// ordering and mutability.
final Map<FieldEntity, ConstantValue> fields;
+ @override
final int hashCode;
ConstructedConstantValue(
@@ -742,8 +863,10 @@
assert(!fields.containsValue(null));
}
+ @override
bool get isConstructedObject => true;
+ @override
bool operator ==(var otherVar) {
if (identical(this, otherVar)) return true;
if (otherVar is! ConstructedConstantValue) return false;
@@ -757,18 +880,22 @@
return true;
}
+ @override
List<ConstantValue> getDependencies() => fields.values.toList();
+ @override
accept(ConstantValueVisitor visitor, arg) {
return visitor.visitConstructed(this, arg);
}
+ @override
ConstantValueKind get kind => ConstantValueKind.CONSTRUCTED;
Iterable<FieldEntity> get _fieldsSortedByName {
return fields.keys.toList()..sort((a, b) => a.name.compareTo(b.name));
}
+ @override
String toDartText() {
StringBuffer sb = new StringBuffer();
sb.write(type.element.name);
@@ -787,6 +914,7 @@
return sb.toString();
}
+ @override
String toStructuredText() {
StringBuffer sb = new StringBuffer();
sb.write('ConstructedConstant(');
@@ -812,6 +940,7 @@
InstantiationConstantValue(this.typeArguments, this.function);
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
return other is InstantiationConstantValue &&
@@ -824,21 +953,27 @@
return Hashing.objectHash(function, Hashing.listHash(typeArguments));
}
+ @override
List<ConstantValue> getDependencies() => <ConstantValue>[function];
+ @override
accept(ConstantValueVisitor visitor, arg) =>
visitor.visitInstantiation(this, arg);
+ @override
DartType getType(CommonElements types) {
FunctionType type = function.getType(types);
return type.instantiate(typeArguments);
}
+ @override
ConstantValueKind get kind => ConstantValueKind.INSTANTIATION;
+ @override
String toDartText() =>
'<${typeArguments.join(', ')}>(${function.toDartText()})';
+ @override
String toStructuredText() {
return 'InstantiationConstant($typeArguments,'
'${function.toStructuredText()})';
@@ -865,25 +1000,33 @@
bool get isReference => true;
+ @override
bool operator ==(other) {
return other is DeferredGlobalConstantValue &&
referenced == other.referenced &&
unit == other.unit;
}
+ @override
get hashCode => (referenced.hashCode * 17 + unit.hashCode) & 0x3fffffff;
+ @override
List<ConstantValue> getDependencies() => <ConstantValue>[referenced];
+ @override
accept(ConstantValueVisitor visitor, arg) =>
visitor.visitDeferredGlobal(this, arg);
+ @override
DartType getType(CommonElements types) => referenced.getType(types);
+ @override
ConstantValueKind get kind => ConstantValueKind.DEFERRED_GLOBAL;
+ @override
String toDartText() => 'deferred_global(${referenced.toDartText()})';
+ @override
String toStructuredText() {
return 'DeferredGlobalConstant(${referenced.toStructuredText()})';
}
@@ -893,6 +1036,7 @@
/// expression.
// TODO(johnniwinther): Expand this to contain the error kind.
class NonConstantValue extends ConstantValue {
+ @override
bool get isConstant => false;
@override
@@ -906,6 +1050,7 @@
@override
DartType getType(CommonElements types) => types.dynamicType;
+ @override
ConstantValueKind get kind => ConstantValueKind.NON_CONSTANT;
@override
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 3aa386e..65dc8c6 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -664,6 +664,7 @@
class AbortLeg {
final message;
AbortLeg(this.message);
+ @override
toString() => 'Aborted due to --throw-on-error: $message';
}
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index d2fd134..dbce4ff 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -51,6 +51,7 @@
OutputUnit(this.isMainOutput, this.name, this._imports);
+ @override
int compareTo(OutputUnit other) {
if (identical(this, other)) return 0;
if (isMainOutput && !other.isMainOutput) return -1;
@@ -76,6 +77,7 @@
Set<ImportEntity> get importsForTesting => _imports;
+ @override
String toString() => "OutputUnit($name, $_imports)";
}
@@ -84,6 +86,7 @@
/// shared OutputUnits.
abstract class DeferredLoadTask extends CompilerTask {
/// The name of this task.
+ @override
String get name => 'Deferred Loading';
/// The OutputUnit that will be loaded when the program starts.
@@ -1092,6 +1095,7 @@
return result;
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('ImportSet(size: $length, ');
@@ -1200,6 +1204,7 @@
ClassWorkItem(this.cls, ImportSet newSet) : super(newSet);
+ @override
void update(DeferredLoadTask task, WorkQueue queue) {
queue.pendingClasses.remove(cls);
ImportSet oldSet = task._classToSet[cls];
@@ -1215,6 +1220,7 @@
MemberWorkItem(this.member, ImportSet newSet) : super(newSet);
+ @override
void update(DeferredLoadTask task, WorkQueue queue) {
queue.pendingMembers.remove(member);
ImportSet oldSet = task._memberToSet[member];
@@ -1230,6 +1236,7 @@
ConstantWorkItem(this.constant, ImportSet newSet) : super(newSet);
+ @override
void update(DeferredLoadTask task, WorkQueue queue) {
queue.pendingConstants.remove(constant);
ImportSet oldSet = task._constantToSet[constant];
diff --git a/pkg/compiler/lib/src/diagnostics/code_location.dart b/pkg/compiler/lib/src/diagnostics/code_location.dart
index 63fee22..8e923f9 100644
--- a/pkg/compiler/lib/src/diagnostics/code_location.dart
+++ b/pkg/compiler/lib/src/diagnostics/code_location.dart
@@ -40,10 +40,12 @@
SchemeLocation(this.uri);
+ @override
bool inSameLocation(Uri uri) {
return this.uri.scheme == uri.scheme;
}
+ @override
String relativize(Uri baseUri) {
return uri_extras.relativize(baseUri, uri, false);
}
@@ -58,10 +60,12 @@
PackageLocation(this.packageName);
+ @override
bool inSameLocation(Uri uri) {
return uri.scheme == 'package' && uri.path.startsWith('$packageName/');
}
+ @override
String relativize(Uri baseUri) => 'package:$packageName';
}
@@ -73,8 +77,10 @@
UriLocation(this.uri);
+ @override
bool inSameLocation(Uri uri) => this.uri == uri;
+ @override
String relativize(Uri baseUri) {
return uri_extras.relativize(baseUri, uri, false);
}
@@ -84,7 +90,9 @@
class AnyLocation implements CodeLocation {
const AnyLocation();
+ @override
bool inSameLocation(Uri uri) => true;
+ @override
String relativize(Uri baseUri) => '$baseUri';
}
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index a3532c9..16aee21 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -607,7 +607,7 @@
MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE: const MessageTemplate(
MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE,
- "`#{constant}` of type '#{type}' is not a valid logical and operand. "
+ "`#{constant}` of type '#{type}' is not a valid logical or operand. "
"Must be a value of type 'bool'."),
MessageKind.INVALID_CONSTANT_CONSTRUCTOR: const MessageTemplate(
@@ -692,6 +692,7 @@
"'case' expression of type '#{type}'."),
}); // End of TEMPLATES.
+ @override
String toString() => template;
Message message([Map arguments = const {}, bool terse = false]) {
@@ -738,15 +739,18 @@
return message;
}
+ @override
String toString() {
return computeMessage();
}
+ @override
bool operator ==(other) {
if (other is! Message) return false;
return (template == other.template) && (toString() == other.toString());
}
+ @override
int get hashCode => throw new UnsupportedError('Message.hashCode');
static String convertToString(value) {
diff --git a/pkg/compiler/lib/src/diagnostics/source_span.dart b/pkg/compiler/lib/src/diagnostics/source_span.dart
index 3fffc29..2b24c11 100644
--- a/pkg/compiler/lib/src/diagnostics/source_span.dart
+++ b/pkg/compiler/lib/src/diagnostics/source_span.dart
@@ -13,15 +13,18 @@
const SourceSpan(this.uri, this.begin, this.end);
+ @override
int get hashCode {
return 13 * uri.hashCode + 17 * begin.hashCode + 19 * end.hashCode;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! SourceSpan) return false;
return uri == other.uri && begin == other.begin && end == other.end;
}
+ @override
String toString() => 'SourceSpan($uri, $begin, $end)';
}
diff --git a/pkg/compiler/lib/src/diagnostics/spannable.dart b/pkg/compiler/lib/src/diagnostics/spannable.dart
index cdba684..356e2e4 100644
--- a/pkg/compiler/lib/src/diagnostics/spannable.dart
+++ b/pkg/compiler/lib/src/diagnostics/spannable.dart
@@ -14,6 +14,7 @@
const _SpannableSentinel(this.name);
+ @override
String toString() => name;
}
@@ -33,6 +34,7 @@
final String message;
SpannableAssertionFailure(this.node, this.message);
+ @override
String toString() => 'Assertion failure'
'${message != null ? ': $message' : ''}';
}
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index d4c2161..35be4dd 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -402,6 +402,7 @@
: useBinaryFormat = compiler.options.useDumpInfoBinaryFormat,
super(compiler.measurer);
+ @override
String get name => "Dump Info";
ElementInfoCollector infoCollector;
@@ -433,6 +434,7 @@
_programSize = programSize;
}
+ @override
void reportInlined(FunctionEntity element, MemberEntity inlinedFrom) {
inlineCount.putIfAbsent(element, () => 0);
inlineCount[element] += 1;
@@ -675,6 +677,7 @@
// TODO(sigmund): delete once we no longer emit text by default.
class _CodeData extends CodeSpan {
StringBuffer _text = new StringBuffer();
+ @override
String get text => '$_text';
int get length => end - start;
}
diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart
index a3a5c4d..a621644 100644
--- a/pkg/compiler/lib/src/elements/entities.dart
+++ b/pkg/compiler/lib/src/elements/entities.dart
@@ -53,6 +53,7 @@
ImportEntity(this.isDeferred, this.name, this.uri, this.enclosingLibraryUri);
+ @override
String toString() => 'import($name:${isDeferred ? ' deferred' : ''})';
}
@@ -196,6 +197,7 @@
const AsyncMarker._(this.asyncParserState,
{this.isAsync: false, this.isYielding: false});
+ @override
String toString() {
return '${isAsync ? 'async' : 'sync'}${isYielding ? '*' : ''}';
}
@@ -326,6 +328,7 @@
namedParameters, typeParameters);
}
+ @override
int get hashCode => Hashing.listHash(
namedParameters,
Hashing.objectHash(
@@ -333,6 +336,7 @@
Hashing.objectHash(
requiredParameters, Hashing.objectHash(typeParameters))));
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! ParameterStructure) return false;
@@ -368,6 +372,7 @@
return sb.toString();
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('ParameterStructure(');
diff --git a/pkg/compiler/lib/src/elements/indexed.dart b/pkg/compiler/lib/src/elements/indexed.dart
index 56defb0..e83b8a0 100644
--- a/pkg/compiler/lib/src/elements/indexed.dart
+++ b/pkg/compiler/lib/src/elements/indexed.dart
@@ -13,18 +13,21 @@
abstract class IndexedLibrary extends _Indexed implements LibraryEntity {
/// Library index used for fast lookup in [KernelToElementMapBase].
int get libraryIndex => _index;
+ @override
int get hashCode => 7 * _index + 2;
}
abstract class IndexedClass extends _Indexed implements ClassEntity {
/// Class index used for fast lookup in [KernelToElementMapBase].
int get classIndex => _index;
+ @override
int get hashCode => 7 * _index + 1;
}
abstract class IndexedMember extends _Indexed implements MemberEntity {
/// Member index used for fast lookup in [KernelToElementMapBase].
int get memberIndex => _index;
+ @override
int get hashCode => 7 * _index;
}
diff --git a/pkg/compiler/lib/src/elements/jumps.dart b/pkg/compiler/lib/src/elements/jumps.dart
index 05a25e7..53bf887 100644
--- a/pkg/compiler/lib/src/elements/jumps.dart
+++ b/pkg/compiler/lib/src/elements/jumps.dart
@@ -20,6 +20,7 @@
/// A jump target is the reference point of a statement or switch-case,
/// either by label or as the default target of a break or continue.
abstract class JumpTarget extends Local {
+ @override
String get name => 'target';
bool get isTarget => isBreakTarget || isContinueTarget;
diff --git a/pkg/compiler/lib/src/elements/names.dart b/pkg/compiler/lib/src/elements/names.dart
index dd60ab4..0a004de 100644
--- a/pkg/compiler/lib/src/elements/names.dart
+++ b/pkg/compiler/lib/src/elements/names.dart
@@ -61,57 +61,77 @@
}
class PublicName implements Name {
+ @override
final String text;
+ @override
final bool isSetter;
const PublicName(this.text, {this.isSetter: false});
+ @override
Name get getter => isSetter ? new PublicName(text) : this;
+ @override
Name get setter => isSetter ? this : new PublicName(text, isSetter: true);
+ @override
bool isAccessibleFrom(LibraryEntity element) => true;
+ @override
bool get isPrivate => false;
+ @override
int get hashCode => similarHashCode;
+ @override
bool operator ==(other) {
if (other is! PublicName) return false;
return isSimilarTo(other);
}
+ @override
bool isSimilarTo(Name other) =>
text == other.text && isSetter == other.isSetter;
+ @override
int get similarHashCode => text.hashCode + 11 * isSetter.hashCode;
+ @override
LibraryEntity get library => null;
+ @override
String toString() => isSetter ? '$text=' : text;
}
class PrivateName extends PublicName {
+ @override
final LibraryEntity library;
PrivateName(String text, this.library, {bool isSetter: false})
: super(text, isSetter: isSetter);
+ @override
Name get getter => isSetter ? new PrivateName(text, library) : this;
+ @override
Name get setter {
return isSetter ? this : new PrivateName(text, library, isSetter: true);
}
+ @override
bool isAccessibleFrom(LibraryEntity element) => library == element;
+ @override
bool get isPrivate => true;
+ @override
int get hashCode => super.hashCode + 13 * library.hashCode;
+ @override
bool operator ==(other) {
if (other is! PrivateName) return false;
return super == (other) && library == other.library;
}
+ @override
String toString() => '${library.name}#${super.toString()}';
}
diff --git a/pkg/compiler/lib/src/elements/operators.dart b/pkg/compiler/lib/src/elements/operators.dart
index ddc9cff3..e3fc7d9 100644
--- a/pkg/compiler/lib/src/elements/operators.dart
+++ b/pkg/compiler/lib/src/elements/operators.dart
@@ -26,6 +26,7 @@
Selector get selector => new Selector(SelectorKind.OPERATOR,
new PublicName(selectorName), CallStructure.NO_ARGS);
+ @override
String toString() => name;
/// The unary ! operator.
@@ -102,6 +103,7 @@
String get selectorName => name;
+ @override
String toString() => name;
/// The == operator.
@@ -297,8 +299,10 @@
class _NotEqualsOperator extends BinaryOperator {
const _NotEqualsOperator() : super._(BinaryOperatorKind.NOT_EQ, '!=');
+ @override
bool get isUserDefinable => false;
+ @override
String get selectorName => '==';
}
@@ -308,8 +312,10 @@
const _LogicalOperator(BinaryOperatorKind kind, String name)
: super._(kind, name);
+ @override
bool get isUserDefinable => false;
+ @override
String get selectorName => null;
}
@@ -318,7 +324,9 @@
const _IfNullOperator(BinaryOperatorKind kind, String name)
: super._(kind, name);
+ @override
bool get isUserDefinable => false;
+ @override
String get selectorName => '??';
}
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index d42f31a..ef7c2f8 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -144,6 +144,7 @@
return _assumptionMap[a]?.contains(b) ?? false;
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('_Assumptions(');
@@ -165,25 +166,31 @@
InterfaceType(this.element, this.typeArguments);
+ @override
bool get isInterfaceType => true;
+ @override
bool get isObject {
return element.name == 'Object' &&
element.library.canonicalUri == Uris.dart_core;
}
+ @override
bool get containsTypeVariables =>
typeArguments.any((type) => type.containsTypeVariables);
+ @override
void forEachTypeVariable(f(TypeVariableType variable)) {
typeArguments.forEach((type) => type.forEachTypeVariable(f));
}
+ @override
bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) {
return typeArguments
.any((type) => type._containsFreeTypeVariables(bindings));
}
+ @override
InterfaceType subst(List<DartType> arguments, List<DartType> parameters) {
if (typeArguments.isEmpty) {
// Return fast on non-generic types.
@@ -203,6 +210,7 @@
return this;
}
+ @override
bool get treatAsRaw {
for (DartType type in typeArguments) {
if (!type.treatAsDynamic) return false;
@@ -214,6 +222,7 @@
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitInterfaceType(this, argument);
+ @override
int get hashCode {
int hash = element.hashCode;
for (DartType argument in typeArguments) {
@@ -223,12 +232,14 @@
return hash;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! InterfaceType) return false;
return _equalsInternal(other, null);
}
+ @override
bool _equals(DartType other, _Assumptions assumptions) {
if (identical(this, other)) return true;
if (other is! InterfaceType) return false;
@@ -240,6 +251,7 @@
_equalTypes(typeArguments, other.typeArguments, assumptions);
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write(element.name);
@@ -262,22 +274,28 @@
class TypedefType extends DartType {
final TypedefEntity element;
final List<DartType> typeArguments;
+ @override
final FunctionType unaliased;
TypedefType(this.element, this.typeArguments, this.unaliased);
+ @override
bool get isTypedef => true;
+ @override
bool get containsTypeVariables =>
typeArguments.any((type) => type.containsTypeVariables);
+ @override
void forEachTypeVariable(f(TypeVariableType variable)) {
typeArguments.forEach((type) => type.forEachTypeVariable(f));
}
+ @override
bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) =>
typeArguments.any((type) => type._containsFreeTypeVariables(bindings));
+ @override
TypedefType subst(List<DartType> arguments, List<DartType> parameters) {
if (typeArguments.isEmpty) {
// Return fast on non-generic types.
@@ -299,6 +317,7 @@
return this;
}
+ @override
bool get treatAsRaw {
for (DartType type in typeArguments) {
if (!type.treatAsDynamic) return false;
@@ -310,6 +329,7 @@
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitTypedefType(this, argument);
+ @override
int get hashCode {
int hash = element.hashCode;
for (DartType argument in typeArguments) {
@@ -319,12 +339,14 @@
return hash;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! TypedefType) return false;
return _equalsInternal(other, null);
}
+ @override
bool _equals(DartType other, _Assumptions assumptions) {
if (identical(this, other)) return true;
if (other is! TypedefType) return false;
@@ -336,6 +358,7 @@
_equalTypes(typeArguments, other.typeArguments, assumptions);
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write(element.name);
@@ -360,16 +383,21 @@
TypeVariableType(this.element);
+ @override
bool get isTypeVariable => true;
+ @override
bool get containsTypeVariables => true;
+ @override
void forEachTypeVariable(f(TypeVariableType variable)) {
f(this);
}
+ @override
bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) => true;
+ @override
DartType subst(List<DartType> arguments, List<DartType> parameters) {
assert(arguments.length == parameters.length);
if (parameters.isEmpty) {
@@ -388,8 +416,10 @@
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitTypeVariableType(this, argument);
+ @override
int get hashCode => 17 * element.hashCode;
+ @override
bool operator ==(other) {
if (other is! TypeVariableType) return false;
return identical(other.element, element);
@@ -403,6 +433,7 @@
return false;
}
+ @override
String toString() => '${element.typeDeclaration.name}.${element.name}';
}
@@ -438,12 +469,14 @@
@override
bool get isFunctionTypeVariable => true;
+ @override
bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) {
if (bindings == null) return true;
if (bindings.indexOf(this) >= 0) return false;
return true;
}
+ @override
DartType subst(List<DartType> arguments, List<DartType> parameters) {
assert(arguments.length == parameters.length);
if (parameters.isEmpty) {
@@ -458,8 +491,10 @@
return this;
}
+ @override
int get hashCode => index.hashCode * 19;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! FunctionTypeVariable) return false;
@@ -478,14 +513,17 @@
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitFunctionTypeVariable(this, argument);
+ @override
String toString() => '#${new String.fromCharCode(0x41 + index)}';
}
class VoidType extends DartType {
const VoidType();
+ @override
bool get isVoid => true;
+ @override
DartType subst(List<DartType> arguments, List<DartType> parameters) {
// `void` cannot be substituted.
return this;
@@ -495,6 +533,7 @@
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitVoidType(this, argument);
+ @override
int get hashCode => 6007;
@override
@@ -502,6 +541,7 @@
return identical(this, other);
}
+ @override
String toString() => 'void';
}
@@ -514,6 +554,7 @@
@override
bool get treatAsDynamic => true;
+ @override
DartType subst(List<DartType> arguments, List<DartType> parameters) {
// `dynamic` cannot be substituted.
return this;
@@ -523,6 +564,7 @@
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitDynamicType(this, argument);
+ @override
int get hashCode => 91;
@override
@@ -530,6 +572,7 @@
return identical(this, other);
}
+ @override
String toString() => 'dynamic';
}
@@ -565,6 +608,7 @@
assert(!typeVariables.contains(null), "Invalid type variables in $this.");
}
+ @override
bool get containsTypeVariables {
return typeVariables.any((type) => type.bound.containsTypeVariables) ||
returnType.containsTypeVariables ||
@@ -573,6 +617,7 @@
namedParameterTypes.any((type) => type.containsTypeVariables);
}
+ @override
void forEachTypeVariable(f(TypeVariableType variable)) {
typeVariables.forEach((type) => type.bound.forEachTypeVariable(f));
returnType.forEachTypeVariable(f);
@@ -581,6 +626,7 @@
namedParameterTypes.forEach((type) => type.forEachTypeVariable(f));
}
+ @override
bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) {
int restore;
if (typeVariables.isNotEmpty) {
@@ -604,8 +650,10 @@
return result;
}
+ @override
bool get isFunctionType => true;
+ @override
DartType subst(List<DartType> arguments, List<DartType> parameters) {
if (parameters.isEmpty) {
assert(arguments.isEmpty);
@@ -669,6 +717,7 @@
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitFunctionType(this, argument);
+ @override
int get hashCode {
int hash = 3 * returnType.hashCode;
for (DartType parameter in parameterTypes) {
@@ -686,12 +735,14 @@
return hash;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! FunctionType) return false;
return _equalsInternal(other, null);
}
+ @override
bool _equals(DartType other, _Assumptions assumptions) {
if (identical(this, other)) return true;
if (other is! FunctionType) return false;
@@ -728,6 +779,7 @@
return result;
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write(returnType);
@@ -811,26 +863,33 @@
return new FutureOrType(newTypeArgument);
}
+ @override
bool get containsTypeVariables => typeArgument.containsTypeVariables;
+ @override
void forEachTypeVariable(f(TypeVariableType variable)) {
typeArgument.forEachTypeVariable(f);
}
+ @override
bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) =>
typeArgument._containsFreeTypeVariables(bindings);
+ @override
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitFutureOrType(this, argument);
+ @override
int get hashCode => typeArgument.hashCode * 13;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! FutureOrType) return false;
return _equalsInternal(other, null);
}
+ @override
bool _equals(DartType other, _Assumptions assumptions) {
if (identical(this, other)) return true;
if (other is! FutureOrType) return false;
@@ -841,6 +900,7 @@
return typeArgument._equals(other.typeArgument, assumptions);
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('FutureOr');
@@ -964,10 +1024,12 @@
/// Returns the declared bound of [element].
DartType getTypeVariableBound(TypeVariableEntity element);
+ @override
bool visitType(T t, T s) {
throw 'internal error: unknown type ${t}';
}
+ @override
bool visitVoidType(VoidType t, T s) {
assert(s is! VoidType);
return false;
@@ -983,6 +1045,7 @@
bool invalidCallableType(covariant DartType callType, covariant DartType s);
+ @override
bool visitInterfaceType(InterfaceType t, covariant DartType s) {
ensureResolved(t);
@@ -1015,6 +1078,7 @@
return false;
}
+ @override
bool visitFunctionType(FunctionType t, DartType s) {
if (s == commonElements.functionType) {
return true;
@@ -1141,6 +1205,7 @@
return true;
}
+ @override
bool visitTypeVariableType(TypeVariableType t, T s) {
// Identity check is handled in [isSubtype].
DartType bound = getTypeVariableBound(t.element);
@@ -1168,6 +1233,7 @@
return true;
}
+ @override
bool visitFunctionTypeVariable(FunctionTypeVariable t, DartType s) {
if (!s.isFunctionTypeVariable) return false;
return assumptions.isAssumed(t, s);
@@ -1194,27 +1260,33 @@
return t.accept(this, s);
}
+ @override
bool invalidTypeArguments(T t, T s) {
return !isMoreSpecific(t, s);
}
+ @override
bool invalidFunctionReturnTypes(T t, T s) {
if (s.treatAsDynamic && t.isVoid) return true;
return !s.isVoid && !isMoreSpecific(t, s);
}
+ @override
bool invalidFunctionParameterTypes(T t, T s) {
return !isMoreSpecific(t, s);
}
+ @override
bool invalidTypeVariableBounds(T bound, T s) {
return !isMoreSpecific(bound, s);
}
+ @override
bool invalidCallableType(covariant DartType callType, covariant DartType s) {
return !isMoreSpecific(callType, s);
}
+ @override
bool visitFutureOrType(FutureOrType t, covariant DartType s) {
return false;
}
@@ -1244,26 +1316,32 @@
return isSubtype(t, s) || isSubtype(s, t);
}
+ @override
bool invalidTypeArguments(T t, T s) {
return !isSubtype(t, s);
}
+ @override
bool invalidFunctionReturnTypes(T t, T s) {
return !isSubtype(t, s);
}
+ @override
bool invalidFunctionParameterTypes(T t, T s) {
return !isSubtype(s, t);
}
+ @override
bool invalidTypeVariableBounds(T bound, T s) {
return !isSubtype(bound, s);
}
+ @override
bool invalidCallableType(covariant DartType callType, covariant DartType s) {
return !isSubtype(callType, s);
}
+ @override
bool visitFutureOrType(FutureOrType t, covariant DartType s) {
if (s.isFutureOr) {
FutureOrType sFutureOr = s;
@@ -1280,6 +1358,7 @@
extends SubtypeVisitor<T> {
bool _assumeInstantiations = true;
+ @override
bool isSubtype(DartType t, DartType s) {
if (t is TypeVariableType || s is TypeVariableType) {
return true;
@@ -1291,6 +1370,7 @@
return super.isSubtype(t, s);
}
+ @override
int getCommonTypeVariablesCount(FunctionType t, FunctionType s) {
if (t.typeVariables.length == s.typeVariables.length) {
return t.typeVariables.length;
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 4defca5..d42e48c 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -39,6 +39,7 @@
CodegenEnqueuer codegenEnqueuerForTesting;
final Compiler compiler;
+ @override
String get name => 'Enqueue';
EnqueueTask(Compiler compiler)
@@ -189,12 +190,14 @@
ImpactStrategy get impactStrategy => _impactStrategy;
+ @override
void open(ImpactStrategy impactStrategy, FunctionEntity mainMethod,
Iterable<Uri> libraries) {
_impactStrategy = impactStrategy;
listener.onQueueOpen(this, mainMethod, libraries);
}
+ @override
void close() {
// TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed]
// to `true` here.
@@ -224,9 +227,11 @@
static const ImpactUseCase IMPACT_USE =
const ImpactUseCase('ResolutionEnqueuer');
+ @override
final CompilerTask task;
final String name;
final CompilerOptions _options;
+ @override
final EnqueuerListener listener;
final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>();
@@ -235,6 +240,7 @@
final WorkItemBuilder _workItemBuilder;
final DiagnosticReporter _reporter;
+ @override
bool queueIsClosed = false;
WorldImpactVisitor _impactVisitor;
@@ -251,8 +257,10 @@
_impactVisitor = new EnqueuerImplImpactVisitor(this);
}
+ @override
ResolutionWorldBuilder get worldBuilder => _worldBuilder;
+ @override
bool get queueIsEmpty => _queue.isEmpty;
@override
@@ -262,8 +270,10 @@
}
}
+ @override
Iterable<ClassEntity> get processedClasses => _worldBuilder.processedClasses;
+ @override
void applyImpact(WorldImpact worldImpact, {var impactSource}) {
if (worldImpact.isEmpty) return;
impactStrategy.visitImpact(
@@ -283,12 +293,14 @@
});
}
+ @override
bool checkNoEnqueuedInvokedInstanceMethods(
ElementEnvironment elementEnvironment) {
if (Enqueuer.skipEnqueuerCheckForTesting) return true;
return checkEnqueuerConsistency(elementEnvironment);
}
+ @override
void checkClass(ClassEntity cls) {
_worldBuilder.processClassMembers(cls,
(MemberEntity member, EnumSet<MemberUse> useSet) {
@@ -330,12 +342,14 @@
}
}
+ @override
void processDynamicUse(DynamicUse dynamicUse) {
task.measure(() {
_worldBuilder.registerDynamicUse(dynamicUse, _applyMemberUse);
});
}
+ @override
void processConstantUse(ConstantUse constantUse) {
task.measure(() {
if (_worldBuilder.registerConstantUse(constantUse)) {
@@ -346,6 +360,7 @@
});
}
+ @override
void processStaticUse(StaticUse staticUse) {
_worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
// TODO(johnniwinther): Add `ResolutionWorldBuilder.registerConstructorUse`
@@ -367,6 +382,7 @@
}
}
+ @override
void processTypeUse(TypeUse typeUse) {
DartType type = typeUse.type;
switch (typeUse.kind) {
@@ -439,6 +455,7 @@
_queue.isNotEmpty || _recentClasses.isNotEmpty || _recentConstants);
}
+ @override
void forEach(void f(WorkItem work)) {
_forEach(f);
if (onEmptyForTesting != null) {
@@ -447,18 +464,23 @@
}
}
+ @override
void logSummary(void log(String message)) {
log('Resolved ${processedEntities.length} elements.');
listener.logSummary(log);
}
+ @override
String toString() => 'Enqueuer($name)';
+ @override
Iterable<MemberEntity> get processedEntities =>
_worldBuilder.processedMembers;
+ @override
ImpactUseCase get impactUse => IMPACT_USE;
+ @override
bool get isResolutionQueue => true;
/// Registers [entity] as processed by the resolution enqueuer. Used only for
diff --git a/pkg/compiler/lib/src/frontend_strategy.dart b/pkg/compiler/lib/src/frontend_strategy.dart
index 39d0872..4d0e320 100644
--- a/pkg/compiler/lib/src/frontend_strategy.dart
+++ b/pkg/compiler/lib/src/frontend_strategy.dart
@@ -117,6 +117,7 @@
new NativeBasicDataBuilderImpl();
NativeBasicData _nativeBasicData;
+ @override
NativeBasicData get nativeBasicData {
if (_nativeBasicData == null) {
_nativeBasicData = nativeBasicDataBuilder.close(elementEnvironment);
diff --git a/pkg/compiler/lib/src/helpers/debug_collection.dart b/pkg/compiler/lib/src/helpers/debug_collection.dart
index c7b9f79..1636e9e 100644
--- a/pkg/compiler/lib/src/helpers/debug_collection.dart
+++ b/pkg/compiler/lib/src/helpers/debug_collection.dart
@@ -21,15 +21,20 @@
putIfAbsentCallback = value;
}
+ @override
Map<RK, RV> cast<RK, RV>() => Map.castFrom<K, V, RK, RV>(this);
+ @override
bool containsValue(Object value) {
return sourceMap.containsValue(value);
}
+ @override
bool containsKey(Object key) => sourceMap.containsKey(key);
+ @override
V operator [](Object key) => sourceMap[key];
+ @override
void operator []=(K key, V value) {
if (indexSetCallback != null) {
indexSetCallback('[]=', key, value);
@@ -37,6 +42,7 @@
sourceMap[key] = value;
}
+ @override
V putIfAbsent(K key, V ifAbsent()) {
return sourceMap.putIfAbsent(key, () {
V v = ifAbsent();
@@ -47,8 +53,10 @@
});
}
+ @override
void addAll(Map<K, V> other) => sourceMap.addAll(other);
+ @override
V remove(Object key) {
if (removeCallback != null) {
removeCallback('remove', key, sourceMap[key]);
@@ -56,6 +64,7 @@
return sourceMap.remove(key);
}
+ @override
void clear() {
if (removeCallback != null) {
removeCallback('clear', sourceMap, null);
@@ -63,34 +72,46 @@
sourceMap.clear();
}
+ @override
void forEach(void f(K key, V value)) => sourceMap.forEach(f);
+ @override
Iterable<K> get keys => sourceMap.keys;
+ @override
Iterable<V> get values => sourceMap.values;
+ @override
Iterable<MapEntry<K, V>> get entries => sourceMap.entries;
+ @override
void addEntries(Iterable<MapEntry<K, V>> entries) {
sourceMap.addEntries(entries);
}
+ @override
Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) =>
sourceMap.map(transform);
+ @override
int get length => sourceMap.length;
+ @override
bool get isEmpty => sourceMap.isEmpty;
+ @override
bool get isNotEmpty => sourceMap.isNotEmpty;
+ @override
V update(K key, V update(V value), {V ifAbsent()}) =>
sourceMap.update(key, update, ifAbsent: ifAbsent);
+ @override
void updateAll(V update(K key, V value)) {
sourceMap.updateAll(update);
}
+ @override
void removeWhere(bool test(K key, V value)) {
sourceMap.removeWhere(test);
}
@@ -101,74 +122,105 @@
DebugIterable(this.iterable);
+ @override
Iterator<E> get iterator => iterable.iterator;
+ @override
Iterable<R> cast<R>() => Iterable.castFrom<E, R>(this);
+ @override
Iterable<T> map<T>(T f(E element)) => iterable.map(f);
+ @override
Iterable<E> where(bool test(E element)) => iterable.where(test);
+ @override
Iterable<T> expand<T>(Iterable<T> f(E element)) => iterable.expand(f);
+ @override
bool contains(Object element) => iterable.contains(element);
+ @override
void forEach(void f(E element)) => iterable.forEach(f);
+ @override
E reduce(E combine(E value, E element)) => iterable.reduce(combine);
+ @override
T fold<T>(T initialValue, T combine(T previousValue, E element)) {
return iterable.fold(initialValue, combine);
}
+ @override
bool every(bool test(E element)) => iterable.every(test);
+ @override
String join([String separator = ""]) => iterable.join(separator);
+ @override
bool any(bool test(E element)) => iterable.any(test);
+ @override
List<E> toList({bool growable: true}) {
return iterable.toList(growable: growable);
}
+ @override
Set<E> toSet() => iterable.toSet();
+ @override
int get length => iterable.length;
+ @override
bool get isEmpty => iterable.isEmpty;
+ @override
bool get isNotEmpty => iterable.isNotEmpty;
+ @override
Iterable<E> take(int n) => iterable.take(n);
+ @override
Iterable<E> takeWhile(bool test(E value)) => iterable.takeWhile(test);
+ @override
Iterable<E> skip(int n) => iterable.skip(n);
+ @override
Iterable<E> skipWhile(bool test(E value)) => iterable.skipWhile(test);
+ @override
E get first => iterable.first;
+ @override
E get last => iterable.last;
+ @override
E get single => iterable.single;
+ @override
E firstWhere(bool test(E element), {E orElse()}) {
return iterable.firstWhere(test, orElse: orElse);
}
+ @override
E lastWhere(bool test(E element), {E orElse()}) {
return iterable.lastWhere(test, orElse: orElse);
}
+ @override
E singleWhere(bool test(E element), {E orElse()}) =>
iterable.singleWhere(test, orElse: orElse);
+ @override
E elementAt(int index) => iterable.elementAt(index);
+ @override
Iterable<E> followedBy(Iterable<E> other) => iterable.followedBy(other);
+ @override
Iterable<T> whereType<T>() => iterable.whereType<T>();
+ @override
String toString() => iterable.toString();
}
@@ -181,29 +233,38 @@
List<E> get list => iterable;
+ @override
List<R> cast<R>() => List.castFrom<E, R>(this);
+ @override
List<E> operator +(List<E> other) => list + other;
+ @override
E operator [](int index) => list[index];
+ @override
void operator []=(int index, E value) {
list[index] = value;
}
+ @override
void set first(E element) {
list.first = element;
}
+ @override
void set last(E element) {
list.last = element;
}
+ @override
int get length => list.length;
+ @override
void set length(int newLength) {
list.length = newLength;
}
+ @override
void add(E value) {
if (addCallback != null) {
addCallback('add', value, null);
@@ -211,6 +272,7 @@
list.add(value);
}
+ @override
void addAll(Iterable<E> iterable) {
if (addAllCallback != null) {
addAllCallback('addAll', iterable, null);
@@ -218,62 +280,85 @@
list.addAll(iterable);
}
+ @override
Iterable<E> get reversed => list.reversed;
+ @override
void sort([int compare(E a, E b)]) => list.sort(compare);
+ @override
void shuffle([random]) => list.shuffle(random);
+ @override
int indexOf(E element, [int start = 0]) => list.indexOf(element, start);
+ @override
int indexWhere(bool test(E element), [int start = 0]) =>
list.indexWhere(test, start);
+ @override
int lastIndexOf(E element, [int start]) => list.lastIndexOf(element, start);
+ @override
int lastIndexWhere(bool test(E element), [int start]) =>
list.lastIndexWhere(test, start);
+ @override
void clear() => list.clear();
+ @override
void insert(int index, E element) => list.insert(index, element);
+ @override
void insertAll(int index, Iterable<E> iterable) {
list.insertAll(index, iterable);
}
+ @override
void setAll(int index, Iterable<E> iterable) => list.setAll(index, iterable);
+ @override
bool remove(Object value) => list.remove(value);
+ @override
E removeAt(int index) => list.removeAt(index);
+ @override
E removeLast() => list.removeLast();
+ @override
void removeWhere(bool test(E element)) => list.removeWhere(test);
+ @override
void retainWhere(bool test(E element)) => list.retainWhere(test);
+ @override
List<E> sublist(int start, [int end]) => list.sublist(start, end);
+ @override
Iterable<E> getRange(int start, int end) => list.getRange(start, end);
+ @override
void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
list.setRange(start, end, iterable, skipCount);
}
+ @override
void removeRange(int start, int end) {
list.removeRange(start, end);
}
+ @override
void fillRange(int start, int end, [E fillValue]) {
list.fillRange(start, end, fillValue);
}
+ @override
void replaceRange(int start, int end, Iterable<E> replacement) {
list.replaceRange(start, end, replacement);
}
+ @override
Map<int, E> asMap() => list.asMap();
}
@@ -284,9 +369,12 @@
Set<E> get set => iterable;
+ @override
Set<R> cast<R>() => Set.castFrom<E, R>(this);
+ @override
bool contains(Object value) => set.contains(value);
+ @override
bool add(E value) {
if (addCallback != null) {
addCallback('add', value, null);
@@ -294,32 +382,45 @@
return set.add(value);
}
+ @override
void addAll(Iterable<E> elements) {
elements.forEach(add);
}
+ @override
bool remove(Object value) => set.remove(value);
+ @override
E lookup(Object object) => set.lookup(object);
+ @override
void removeAll(Iterable<Object> elements) => set.removeAll(elements);
+ @override
void retainAll(Iterable<Object> elements) => set.retainAll(elements);
+ @override
void removeWhere(bool test(E element)) => set.removeWhere(test);
+ @override
void retainWhere(bool test(E element)) => set.retainWhere(test);
+ @override
bool containsAll(Iterable<Object> other) => set.containsAll(other);
+ @override
Set<E> intersection(Set<Object> other) => set.intersection(other);
+ @override
Set<E> union(Set<E> other) => set.union(other);
+ @override
Set<E> difference(Set<Object> other) => set.difference(other);
+ @override
void clear() => set.clear();
+ @override
Set<E> toSet() => set.toSet();
}
diff --git a/pkg/compiler/lib/src/helpers/expensive_map.dart b/pkg/compiler/lib/src/helpers/expensive_map.dart
index ed95b22..149e811 100644
--- a/pkg/compiler/lib/src/helpers/expensive_map.dart
+++ b/pkg/compiler/lib/src/helpers/expensive_map.dart
@@ -17,28 +17,39 @@
}
}
+ @override
int get length => _maps[0].length;
+ @override
bool get isEmpty => _maps[0].isEmpty;
+ @override
bool get isNotEmpty => _maps[0].isNotEmpty;
+ @override
Iterable<K> get keys => _maps[0].keys;
+ @override
Iterable<V> get values => _maps[0].values;
+ @override
bool containsKey(Object key) => _maps[0].containsKey(key);
+ @override
bool containsValue(Object value) => _maps[0].containsValue(value);
+ @override
V operator [](Object key) => _maps[0][key];
+ @override
void forEach(void action(K key, V value)) {
_maps[0].forEach(action);
}
+ @override
void operator []=(K key, V value) {
for (int i = 0; i < _maps.length; i++) {
_maps[i][key] = value;
}
}
+ @override
V putIfAbsent(K key, V ifAbsent()) {
if (containsKey(key)) return this[key];
V value = ifAbsent();
@@ -46,12 +57,14 @@
return value;
}
+ @override
void addAll(Map<K, V> other) {
for (int i = 0; i < _maps.length; i++) {
_maps[i].addAll(other);
}
}
+ @override
V remove(Object key) {
V result = _maps[0].remove(key);
for (int i = 1; i < _maps.length; i++) {
@@ -60,24 +73,30 @@
return result;
}
+ @override
void clear() {
for (int i = 0; i < _maps.length; i++) {
_maps[i].clear();
}
}
+ @override
Map<KR, VR> cast<KR, VR>() => Map.castFrom<K, V, KR, VR>(this);
+ @override
Iterable<MapEntry<K, V>> get entries => _maps[0].entries;
+ @override
void addEntries(Iterable<MapEntry<K, V>> entries) {
for (int i = 0; i < _maps.length; i++) {
_maps[i].addEntries(entries);
}
}
+ @override
Map<KR, VR> map<KR, VR>(MapEntry<KR, VR> transform(K key, V value)) =>
_maps[0].map(transform);
+ @override
V update(K key, V update(V value), {V ifAbsent()}) {
V result;
for (int i = 0; i < _maps.length; i++) {
@@ -86,17 +105,20 @@
return result;
}
+ @override
void updateAll(V update(K key, V value)) {
for (int i = 0; i < _maps.length; i++) {
_maps[i].updateAll(update);
}
}
+ @override
void removeWhere(bool test(K key, V value)) {
for (int i = 0; i < _maps.length; i++) {
_maps[i].removeWhere(test);
}
}
+ @override
String toString() => "expensive(${_maps[0]}x${_maps.length})";
}
diff --git a/pkg/compiler/lib/src/helpers/expensive_set.dart b/pkg/compiler/lib/src/helpers/expensive_set.dart
index f4c2f4f..4c5101e 100644
--- a/pkg/compiler/lib/src/helpers/expensive_set.dart
+++ b/pkg/compiler/lib/src/helpers/expensive_set.dart
@@ -17,19 +17,27 @@
}
}
+ @override
int get length => _sets[0].length;
+ @override
bool get isEmpty => _sets[0].isEmpty;
+ @override
bool get isNotEmpty => _sets[0].isNotEmpty;
+ @override
Iterator<E> get iterator => _sets[0].iterator;
+ @override
bool contains(Object object) => _sets[0].contains(object);
+ @override
E lookup(Object object) => _sets[0].lookup(object);
+ @override
void forEach(void action(E element)) {
_sets[0].forEach(action);
}
+ @override
bool add(E element) {
bool result = _sets[0].add(element);
for (int i = 1; i < _sets.length; i++) {
@@ -38,12 +46,14 @@
return result;
}
+ @override
void addAll(Iterable<E> objects) {
for (E each in objects) {
add(each);
}
}
+ @override
bool remove(Object object) {
bool result = _sets[0].remove(object);
for (int i = 1; i < _sets.length; i++) {
@@ -52,26 +62,31 @@
return result;
}
+ @override
void clear() {
for (int i = 0; i < _sets.length; i++) {
_sets[i].clear();
}
}
+ @override
void removeAll(Iterable<Object> objectsToRemove) {
for (var each in objectsToRemove) {
remove(each);
}
}
+ @override
void removeWhere(bool test(E element)) {
removeAll(this.toList().where((e) => test(e)));
}
+ @override
void retainWhere(bool test(E element)) {
removeAll(toList().where((e) => !test(e)));
}
+ @override
bool containsAll(Iterable<Object> other) {
for (Object object in other) {
if (!this.contains(object)) return false;
@@ -81,6 +96,7 @@
Set _newSet() => new ExpensiveSet(_sets.length);
+ @override
Set<E> intersection(Set<Object> other) {
Set<E> result = _newSet();
if (other.length < this.length) {
@@ -95,10 +111,12 @@
return result;
}
+ @override
Set<E> union(Set<E> other) {
return _newSet()..addAll(this)..addAll(other);
}
+ @override
Set<E> difference(Set<Object> other) {
Set<E> result = _newSet();
for (E element in this) {
@@ -107,6 +125,7 @@
return result;
}
+ @override
void retainAll(Iterable objectsToRetain) {
Set retainSet;
if (objectsToRetain is Set) {
@@ -117,6 +136,7 @@
retainWhere(retainSet.contains);
}
+ @override
Set<E> toSet() {
var result = new ExpensiveSet<E>(_sets.length);
for (int i = 0; i < _sets.length; i++) {
@@ -125,5 +145,6 @@
return result;
}
+ @override
String toString() => "expensive(${_sets[0]}x${_sets.length})";
}
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index 2182fc0..bf34252 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -32,6 +32,7 @@
}
class _DebugIndentation extends Indentation {
+ @override
final String indentationUnit = " ";
}
diff --git a/pkg/compiler/lib/src/helpers/stats.dart b/pkg/compiler/lib/src/helpers/stats.dart
index 935ac8c..e524b54 100644
--- a/pkg/compiler/lib/src/helpers/stats.dart
+++ b/pkg/compiler/lib/src/helpers/stats.dart
@@ -212,6 +212,7 @@
class DebugOutput implements StatsOutput {
const DebugOutput();
+ @override
void println(String text) => debugPrint(text);
}
@@ -222,6 +223,7 @@
SinkOutput(this.sink);
+ @override
void println(String text) {
sink.add(text);
sink.add('\n');
@@ -272,6 +274,7 @@
/// Abstract base class for [ConsolePrinter] and [XMLPrinter].
abstract class BasePrinter extends StatsPrinter with Indentation {
+ @override
final int examples;
final StatsOutput output;
@@ -287,6 +290,7 @@
ConsolePrinter({StatsOutput output: const DebugOutput(), int examples: 10})
: super(output: output, examples: examples);
+ @override
void open(String id,
[Map<String, dynamic> data = const <String, dynamic>{}]) {
if (extraLevel > 0) return;
@@ -316,17 +320,20 @@
indentMore();
}
+ @override
void close(String id) {
if (extraLevel > 0) return;
indentLess();
}
+ @override
void beginExtra() {
if (extraLevel == 0) output.println('$indentation...');
extraLevel++;
}
+ @override
void endExtra() {
extraLevel--;
}
@@ -340,6 +347,7 @@
XMLPrinter({output: const DebugOutput(), int examples: 10})
: super(output: output, examples: examples);
+ @override
void start(String id) {
if (!opened) {
output.println('<?xml version="1.0" encoding="UTF-8"?>');
@@ -348,10 +356,12 @@
open(id);
}
+ @override
void end(String id) {
close(id);
}
+ @override
void open(String id,
[Map<String, dynamic> data = const <String, dynamic>{}]) {
StringBuffer sb = new StringBuffer();
@@ -367,15 +377,18 @@
indentMore();
}
+ @override
void close(String id) {
indentLess();
output.println('${indentation}</$id>');
}
+ @override
void beginExtra() {
open('extra');
}
+ @override
void endExtra() {
close('extra');
}
@@ -450,6 +463,7 @@
}
}
+ @override
int compareTo(_StackTraceNode other) {
// Sorts in decreasing count order.
return other.count - count;
@@ -479,6 +493,7 @@
}
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
printOn(sb, '');
@@ -493,6 +508,7 @@
_StackTraceTree(this.id, this.sampleFrequency) : super.root();
+ @override
void dumpTraces(StatsPrinter printer) {
printer.open('trace', {
'id': id,
@@ -519,10 +535,12 @@
Map<dynamic, Map<dynamic, List>> countersMap =
<dynamic, Map<dynamic, List>>{};
Map<dynamic, _StackTraceTree> traceMap = {};
+ @override
int stackTraceSampleFrequency = 1;
ActiveStats(StatsPrinter this.printer);
+ @override
void recordMap(id, key, value, {fromExisting(value)}) {
Map map = maps.putIfAbsent(id, () => {});
if (fromExisting != null && map.containsKey(key)) {
@@ -532,16 +550,19 @@
}
}
+ @override
Map getMap(key) {
return maps[key];
}
+ @override
void recordFrequency(id, value, [example]) {
Map<dynamic, List> map = frequencyMaps.putIfAbsent(id, () => {});
map.putIfAbsent(value, () => []);
map[value].add(example);
}
+ @override
void recordFrequencies(id, Map<dynamic, Iterable> frequencyMap) {
Map<dynamic, List> map = frequencyMaps.putIfAbsent(id, () => {});
frequencyMap.forEach((value, examples) {
@@ -550,6 +571,7 @@
});
}
+ @override
Iterable recordedFrequencies(id, value) {
Map<dynamic, List> map = frequencyMaps[id];
if (map == null) return const [];
@@ -558,15 +580,18 @@
return list;
}
+ @override
void recordCounter(id, [reason, example]) {
Map<dynamic, List> map = countersMap.putIfAbsent(id, () => {});
map.putIfAbsent(reason, () => []).add(example);
}
+ @override
void recordElement(key, element, {data}) {
setsMap.putIfAbsent(key, () => new Map())[element] = data;
}
+ @override
void recordTrace(key, {int sampleFrequency}) {
if (sampleFrequency == null) {
sampleFrequency = stackTraceSampleFrequency;
@@ -576,12 +601,14 @@
.sample();
}
+ @override
Iterable getList(String key) {
Map map = setsMap[key];
if (map == null) return const [];
return map.keys;
}
+ @override
void dumpStats({void beforeClose()}) {
printer.start('stats');
dumpFrequencies();
@@ -688,6 +715,7 @@
tree.dumpTraces(printer);
}
+ @override
void dumpCorrelation(keyA, Iterable a, keyB, Iterable b,
{Map dataA, Map dataB}) {
printer.child('correlations', {'title': '$keyA vs $keyB'}, () {
diff --git a/pkg/compiler/lib/src/helpers/trace.dart b/pkg/compiler/lib/src/helpers/trace.dart
index 104c227..51022cd 100644
--- a/pkg/compiler/lib/src/helpers/trace.dart
+++ b/pkg/compiler/lib/src/helpers/trace.dart
@@ -232,6 +232,7 @@
return sb.toString();
}
+ @override
String toString() {
return prettify();
}
@@ -269,6 +270,7 @@
sb.write('$fileText $lineNoText$columnNoText $method\n');
}
+ @override
int get hashCode {
return 13 * index +
17 * file.hashCode +
@@ -277,6 +279,7 @@
29 * method.hashCode;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! StackTraceLine) return false;
@@ -287,6 +290,7 @@
method == other.method;
}
+ @override
String toString() => "$method @ $file [$lineNo:$columnNo]";
}
diff --git a/pkg/compiler/lib/src/helpers/track_map.dart b/pkg/compiler/lib/src/helpers/track_map.dart
index 6cb7121..23d3ce4 100644
--- a/pkg/compiler/lib/src/helpers/track_map.dart
+++ b/pkg/compiler/lib/src/helpers/track_map.dart
@@ -48,23 +48,34 @@
});
}
+ @override
int get length => _map.length;
+ @override
bool get isEmpty => _map.isEmpty;
+ @override
bool get isNotEmpty => _map.isNotEmpty;
+ @override
Iterable<K> get keys => _map.keys;
+ @override
Iterable<V> get values => _map.values;
+ @override
bool containsKey(Object key) => _map.containsKey(key);
+ @override
bool containsValue(Object value) => _map.containsValue(value);
+ @override
V operator [](Object key) => _map[key];
+ @override
String toString() => _map.toString();
+ @override
void forEach(void action(K key, V value)) {
_map.forEach(action);
}
+ @override
void operator []=(K key, V value) {
if (!_map.containsKey(key)) {
_notifyLengthChanged(1);
@@ -72,6 +83,7 @@
}
}
+ @override
V putIfAbsent(K key, V ifAbsent()) {
if (containsKey(key)) return this[key];
V value = ifAbsent();
@@ -79,6 +91,7 @@
return value;
}
+ @override
V remove(Object key) {
if (_map.containsKey(key)) {
_notifyLengthChanged(-1);
@@ -86,32 +99,41 @@
return _map.remove(key);
}
+ @override
void addAll(Map<K, V> other) {
other.forEach((key, value) => this[key] = value);
}
+ @override
void clear() {
_notifyLengthChanged(-_map.length);
_map.clear();
}
+ @override
Map<KR, VR> cast<KR, VR>() => _map.cast<KR, VR>();
+ @override
Iterable<MapEntry<K, V>> get entries => _map.entries;
+ @override
void addEntries(Iterable<MapEntry<K, V>> entries) {
for (var entry in entries) this[entry.key] = entry.value;
}
+ @override
Map<KR, VR> map<KR, VR>(MapEntry<KR, VR> transform(K key, V value)) =>
_map.map(transform);
+ @override
V update(K key, V update(V value), {V ifAbsent()}) =>
_map.update(key, update, ifAbsent: ifAbsent);
+ @override
void updateAll(V update(K key, V value)) {
_map.updateAll(update);
}
+ @override
void removeWhere(bool test(K key, V value)) {
int before = _map.length;
_map.removeWhere(test);
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index 1352562..1503b1d 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -45,6 +45,7 @@
static AbstractBool maybeOrFalse(bool value) => value ? Maybe : False;
+ @override
String toString() =>
'AbstractBool.${_value == null ? 'Maybe' : (_value ? 'True' : 'False')}';
}
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index b88d849..dd872ab 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1973,6 +1973,7 @@
sb.write('\n]');
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('LocalState(');
diff --git a/pkg/compiler/lib/src/inferrer/closure_tracer.dart b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
index e7ecf72..7558fcc 100644
--- a/pkg/compiler/lib/src/inferrer/closure_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
@@ -28,6 +28,7 @@
"${tracedElements.where((f) => f.isAbstract)}");
}
+ @override
ApplyableTypeInformation get tracedType => super.tracedType;
void run() {
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 9692c59..801da74 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -252,6 +252,7 @@
final Map<Local, TypeInformation> defaultTypeOfParameter =
new Map<Local, TypeInformation>();
final WorkQueue workQueue = new WorkQueue();
+ @override
final FunctionEntity mainElement;
final Set<MemberEntity> analyzedElements = new Set<MemberEntity>();
@@ -263,16 +264,22 @@
int overallRefineCount = 0;
int addedInGraph = 0;
+ @override
final CompilerOptions options;
final Progress progress;
+ @override
final DiagnosticReporter reporter;
final CompilerOutput _compilerOutput;
/// The [JClosedWorld] on which inference reasoning is based.
+ @override
final JsClosedWorld closedWorld;
+ @override
final InferredDataBuilder inferredDataBuilder;
+ @override
final TypeSystem types;
+ @override
final Map<ir.Node, TypeInformation> concreteTypes =
new Map<ir.Node, TypeInformation>();
@@ -300,6 +307,7 @@
ElementEnvironment get _elementEnvironment => closedWorld.elementEnvironment;
+ @override
void forEachElementMatching(
Selector selector, AbstractValue mask, bool f(MemberEntity element)) {
Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask);
@@ -309,6 +317,7 @@
}
// TODO(johnniwinther): Make this private again.
+ @override
GlobalTypeInferenceElementData dataOfMember(MemberEntity element) =>
_memberData[element] ??= new KernelGlobalTypeInferenceElementData();
@@ -342,6 +351,7 @@
}
}
+ @override
TypeInformation typeOfNativeBehavior(NativeBehavior nativeBehavior) {
if (nativeBehavior == null) return types.dynamicType;
List typesReturned = nativeBehavior.typesReturned;
@@ -382,6 +392,7 @@
return returnType;
}
+ @override
void updateSelectorInMember(MemberEntity owner, CallType callType,
ir.Node node, Selector selector, AbstractValue mask) {
KernelGlobalTypeInferenceElementData data = dataOfMember(owner);
@@ -403,26 +414,31 @@
}
}
+ @override
bool checkIfExposesThis(ConstructorEntity element) {
return generativeConstructorsExposingThis.contains(element);
}
+ @override
void recordExposesThis(ConstructorEntity element, bool exposesThis) {
if (exposesThis) {
generativeConstructorsExposingThis.add(element);
}
}
+ @override
bool returnsListElementType(Selector selector, AbstractValue mask) {
return mask != null &&
abstractValueDomain.isContainer(mask) &&
returnsListElementTypeSet.contains(selector);
}
+ @override
bool returnsMapValueType(Selector selector, AbstractValue mask) {
return mask != null && abstractValueDomain.isMap(mask) && selector.isIndex;
}
+ @override
void analyzeListAndEnqueue(ListTypeInformation info) {
if (info.analyzed) return;
info.analyzed = true;
@@ -443,6 +459,7 @@
workQueue.add(info.elementType);
}
+ @override
void analyzeSetAndEnqueue(SetTypeInformation info) {
if (info.analyzed) return;
info.analyzed = true;
@@ -460,6 +477,7 @@
workQueue.add(info.elementType);
}
+ @override
void analyzeMapAndEnqueue(MapTypeInformation info) {
if (info.analyzed) return;
info.analyzed = true;
@@ -485,6 +503,7 @@
workQueue.add(info);
}
+ @override
void runOverAllElements() {
analyzeAllElements();
TypeGraphDump dump =
@@ -733,6 +752,7 @@
return function;
}
+ @override
void analyze(MemberEntity element) {
if (analyzedElements.contains(element)) return;
analyzedElements.add(element);
@@ -906,6 +926,7 @@
workQueue.addAll(types.allocatedCalls);
}
+ @override
void updateParameterAssignments(TypeInformation caller, MemberEntity callee,
ArgumentsTypes arguments, Selector selector, AbstractValue mask,
{bool remove, bool addToQueue: true}) {
@@ -970,6 +991,7 @@
}
}
+ @override
void setDefaultTypeOfParameter(Local parameter, TypeInformation type,
{bool isInstanceMember}) {
assert(
@@ -997,6 +1019,7 @@
}
}
+ @override
TypeInformation getDefaultTypeOfParameter(Local parameter) {
return defaultTypeOfParameter.putIfAbsent(parameter, () {
return new PlaceholderTypeInformation(
@@ -1004,29 +1027,35 @@
});
}
+ @override
bool hasAlreadyComputedTypeOfParameterDefault(Local parameter) {
TypeInformation seen = defaultTypeOfParameter[parameter];
return (seen != null && seen is! PlaceholderTypeInformation);
}
+ @override
TypeInformation typeOfParameter(Local element) {
return types.getInferredTypeOfParameter(element);
}
+ @override
TypeInformation typeOfMember(MemberEntity element) {
if (element is FunctionEntity) return types.functionType;
return types.getInferredTypeOfMember(element);
}
+ @override
TypeInformation returnTypeOfMember(MemberEntity element) {
if (element is! FunctionEntity) return types.dynamicType;
return types.getInferredTypeOfMember(element);
}
+ @override
void recordTypeOfField(FieldEntity element, TypeInformation type) {
types.getInferredTypeOfMember(element).addAssignment(type);
}
+ @override
void recordReturnType(FunctionEntity element, TypeInformation type) {
TypeInformation info = types.getInferredTypeOfMember(element);
if (element.name == '==') {
@@ -1039,6 +1068,7 @@
if (info.assignments.isEmpty) info.addAssignment(type);
}
+ @override
TypeInformation addReturnTypeForMethod(
FunctionEntity element, TypeInformation unused, TypeInformation newType) {
TypeInformation type = types.getInferredTypeOfMember(element);
@@ -1051,6 +1081,7 @@
return type;
}
+ @override
TypeInformation registerCalledMember(
Object node,
Selector selector,
@@ -1090,6 +1121,7 @@
return info;
}
+ @override
TypeInformation registerCalledSelector(
CallType callType,
ir.Node node,
@@ -1132,6 +1164,7 @@
return info;
}
+ @override
TypeInformation registerAwait(ir.Node node, TypeInformation argument) {
AwaitTypeInformation info = new AwaitTypeInformation(
abstractValueDomain, types.currentMember, node);
@@ -1140,6 +1173,7 @@
return info;
}
+ @override
TypeInformation registerYield(ir.Node node, TypeInformation argument) {
YieldTypeInformation info = new YieldTypeInformation(
abstractValueDomain, types.currentMember, node);
@@ -1148,6 +1182,7 @@
return info;
}
+ @override
TypeInformation registerCalledClosure(
ir.Node node,
Selector selector,
@@ -1173,6 +1208,7 @@
return info;
}
+ @override
void close() {
for (MemberTypeInformation typeInformation
in types.memberTypeInformations.values) {
@@ -1180,6 +1216,7 @@
}
}
+ @override
void clear() {
if (retainDataForTesting) return;
@@ -1213,11 +1250,13 @@
_memberData.clear();
}
+ @override
Iterable<MemberEntity> getCallersOfForTesting(MemberEntity element) {
MemberTypeInformation info = types.getInferredTypeOfMember(element);
return info.callersForTesting;
}
+ @override
TypeInformation typeOfMemberWithSelector(
MemberEntity element, Selector selector) {
if (element.name == Identifiers.noSuchMethod_ &&
@@ -1252,6 +1291,7 @@
///
/// One category of elements that do not apply is runtime helpers that the
/// backend calls, but the optimizations don't see those calls.
+ @override
bool canFieldBeUsedForGlobalOptimizations(FieldEntity element) {
if (closedWorld.backendUsage.isFieldUsedByBackend(element)) {
return false;
@@ -1267,6 +1307,7 @@
///
/// One category of elements that do not apply is runtime helpers that the
/// backend calls, but the optimizations don't see those calls.
+ @override
bool canFunctionParametersBeUsedForGlobalOptimizations(
FunctionEntity function) {
return !closedWorld.backendUsage.isFunctionUsedByBackend(function);
@@ -1427,6 +1468,7 @@
}
/// Serializes this [GlobalTypeInferenceElementData] to [sink].
+ @override
void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
sink.begin(tag);
sink.writeTreeNodeMap(
diff --git a/pkg/compiler/lib/src/inferrer/list_tracer.dart b/pkg/compiler/lib/src/inferrer/list_tracer.dart
index dfe10a0..0f7aa07 100644
--- a/pkg/compiler/lib/src/inferrer/list_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/list_tracer.dart
@@ -154,10 +154,12 @@
}
}
+ @override
visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
bailout('Passed to a closure');
}
+ @override
visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
super.visitStaticCallSiteTypeInformation(info);
MemberEntity called = info.calledElement;
@@ -167,6 +169,7 @@
}
}
+ @override
visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
super.visitDynamicCallSiteTypeInformation(info);
Selector selector = info.selector;
diff --git a/pkg/compiler/lib/src/inferrer/locals_handler.dart b/pkg/compiler/lib/src/inferrer/locals_handler.dart
index aff2896..a94ddbd 100644
--- a/pkg/compiler/lib/src/inferrer/locals_handler.dart
+++ b/pkg/compiler/lib/src/inferrer/locals_handler.dart
@@ -170,6 +170,7 @@
sb.write(']');
}
+ @override
String toString() {
String rest = parent == null ? "null" : parent.toString();
return '{$variables} $rest';
@@ -253,12 +254,16 @@
: positional = const [],
named = const {};
+ @override
int get length => positional.length + named.length;
+ @override
Iterator<TypeInformation> get iterator => new ArgumentsTypesIterator(this);
+ @override
String toString() => "{ positional = $positional, named = $named }";
+ @override
bool operator ==(other) {
if (positional.length != other.positional.length) return false;
if (named.length != other.named.length) return false;
@@ -272,19 +277,23 @@
return result;
}
+ @override
int get hashCode => throw new UnsupportedError('ArgumentsTypes.hashCode');
bool hasNoArguments() => positional.isEmpty && named.isEmpty;
+ @override
void forEach(void f(TypeInformation type)) {
positional.forEach(f);
named.values.forEach(f);
}
+ @override
bool every(bool f(TypeInformation type)) {
return positional.every(f) && named.values.every(f);
}
+ @override
bool contains(Object type) {
return positional.contains(type) || named.containsValue(type);
}
@@ -302,8 +311,10 @@
Iterator<TypeInformation> get _currentIterator =>
_iteratePositional ? positional : named;
+ @override
TypeInformation get current => _currentIterator.current;
+ @override
bool moveNext() {
if (_iteratePositional && positional.moveNext()) {
return true;
@@ -587,6 +598,7 @@
sb.write('\n]');
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('LocalsHandler(');
diff --git a/pkg/compiler/lib/src/inferrer/map_tracer.dart b/pkg/compiler/lib/src/inferrer/map_tracer.dart
index e9da06a..4925dfc 100644
--- a/pkg/compiler/lib/src/inferrer/map_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/map_tracer.dart
@@ -58,10 +58,12 @@
return false;
}
+ @override
visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
bailout('Passed to a closure');
}
+ @override
visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
super.visitStaticCallSiteTypeInformation(info);
MemberEntity called = info.calledElement;
@@ -71,6 +73,7 @@
}
}
+ @override
visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
super.visitDynamicCallSiteTypeInformation(info);
Selector selector = info.selector;
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index 0a3d2ee..987cb11 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -184,10 +184,12 @@
continueAnalyzing = false;
}
+ @override
void visitAwaitTypeInformation(AwaitTypeInformation info) {
bailout("Passed through await");
}
+ @override
void visitYieldTypeInformation(YieldTypeInformation info) {
// TODO(29344): The enclosing sync*/async/async* method could have a
// tracable TypeInformation for the Iterable / Future / Stream with an
@@ -196,55 +198,70 @@
bailout("Passed through yield");
}
+ @override
void visitNarrowTypeInformation(NarrowTypeInformation info) {
addNewEscapeInformation(info);
}
+ @override
void visitPhiElementTypeInformation(PhiElementTypeInformation info) {
addNewEscapeInformation(info);
}
+ @override
void visitElementInContainerTypeInformation(
ElementInContainerTypeInformation info) {
addNewEscapeInformation(info);
}
+ @override
void visitElementInSetTypeInformation(ElementInSetTypeInformation info) {
addNewEscapeInformation(info);
}
+ @override
void visitKeyInMapTypeInformation(KeyInMapTypeInformation info) {
// We do not track the use of keys from a map, so we have to bail.
bailout('Used as key in Map');
}
+ @override
void visitValueInMapTypeInformation(ValueInMapTypeInformation info) {
addNewEscapeInformation(info);
}
+ @override
void visitListTypeInformation(ListTypeInformation info) {
listsToAnalyze.add(info);
}
+ @override
void visitSetTypeInformation(SetTypeInformation info) {
setsToAnalyze.add(info);
}
+ @override
void visitMapTypeInformation(MapTypeInformation info) {
mapsToAnalyze.add(info);
}
+ @override
void visitConcreteTypeInformation(ConcreteTypeInformation info) {}
+ @override
void visitStringLiteralTypeInformation(StringLiteralTypeInformation info) {}
+ @override
void visitBoolLiteralTypeInformation(BoolLiteralTypeInformation info) {}
+ @override
void visitClosureTypeInformation(ClosureTypeInformation info) {}
+ @override
void visitClosureCallSiteTypeInformation(
ClosureCallSiteTypeInformation info) {}
+ @override
visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
MemberEntity called = info.calledElement;
TypeInformation inferred = inferrer.types.getInferredTypeOfMember(called);
@@ -258,14 +275,15 @@
if (list.bailedOut) {
bailout('Stored in a list that bailed out');
} else {
- list.flowsInto.forEach((flow) {
- flow.users.forEach((dynamic user) {
- if (user is! DynamicCallSiteTypeInformation) return;
- if (user.receiver != flow) return;
- if (inferrer.returnsListElementTypeSet.contains(user.selector)) {
- addNewEscapeInformation(user);
- } else if (!doesNotEscapeListSet.contains(user.selector.name)) {
- bailout('Escape from a list via [${user.selector.name}]');
+ list.flowsInto.forEach((TypeInformation flow) {
+ flow.users.forEach((TypeInformation user) {
+ if (user is DynamicCallSiteTypeInformation) {
+ if (user.receiver != flow) return;
+ if (inferrer.returnsListElementTypeSet.contains(user.selector)) {
+ addNewEscapeInformation(user);
+ } else if (!doesNotEscapeListSet.contains(user.selector.name)) {
+ bailout('Escape from a list via [${user.selector.name}]');
+ }
}
});
});
@@ -277,13 +295,15 @@
if (set.bailedOut) {
bailout('Stored in a set that bailed out');
} else {
- set.flowsInto.forEach((flow) {
- flow.users.forEach((dynamic user) {
- if (user.receiver != flow) return;
- if (user.selector.isIndex) {
- addNewEscapeInformation(user);
- } else if (!doesNotEscapeSetSet.contains(user.selector.name)) {
- bailout('Escape from a set via [${user.selector.name}]');
+ set.flowsInto.forEach((TypeInformation flow) {
+ flow.users.forEach((TypeInformation user) {
+ if (user is DynamicCallSiteTypeInformation) {
+ if (user.receiver != flow) return;
+ if (user.selector.isIndex) {
+ addNewEscapeInformation(user);
+ } else if (!doesNotEscapeSetSet.contains(user.selector.name)) {
+ bailout('Escape from a set via [${user.selector.name}]');
+ }
}
});
});
@@ -295,14 +315,15 @@
if (map.bailedOut) {
bailout('Stored in a map that bailed out');
} else {
- map.flowsInto.forEach((flow) {
- flow.users.forEach((dynamic user) {
- if (user is! DynamicCallSiteTypeInformation) return;
- if (user.receiver != flow) return;
- if (user.selector.isIndex) {
- addNewEscapeInformation(user);
- } else if (!doesNotEscapeMapSet.contains(user.selector.name)) {
- bailout('Escape from a map via [${user.selector.name}]');
+ map.flowsInto.forEach((TypeInformation flow) {
+ flow.users.forEach((TypeInformation user) {
+ if (user is DynamicCallSiteTypeInformation) {
+ if (user.receiver != flow) return;
+ if (user.selector.isIndex) {
+ addNewEscapeInformation(user);
+ } else if (!doesNotEscapeMapSet.contains(user.selector.name)) {
+ bailout('Escape from a map via [${user.selector.name}]');
+ }
}
});
});
@@ -358,6 +379,7 @@
}
}
+ @override
void visitDynamicCallSiteTypeInformation(
DynamicCallSiteTypeInformation info) {
void addsToContainer(AbstractValue mask) {
@@ -493,6 +515,7 @@
return cls != null && cls.isClosure;
}
+ @override
void visitMemberTypeInformation(MemberTypeInformation info) {
if (info.isClosurized) {
bailout('Returned from a closurized method');
@@ -507,6 +530,7 @@
addNewEscapeInformation(info);
}
+ @override
void visitParameterTypeInformation(ParameterTypeInformation info) {
if (inferrer.closedWorld.nativeData.isNativeMember(info.method)) {
bailout('Passed to a native method');
diff --git a/pkg/compiler/lib/src/inferrer/trivial.dart b/pkg/compiler/lib/src/inferrer/trivial.dart
index dcd5e97..9d4d5ef 100644
--- a/pkg/compiler/lib/src/inferrer/trivial.dart
+++ b/pkg/compiler/lib/src/inferrer/trivial.dart
@@ -16,6 +16,7 @@
class TrivialAbstractValue implements AbstractValue {
const TrivialAbstractValue();
+ @override
String toString() => '?';
}
@@ -472,5 +473,6 @@
@override
bool canHit(MemberEntity element, Name name, World world) => true;
+ @override
String toString() => 'TrivialUniverseSelectorConstraints:$hashCode';
}
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
index d9ddd4d..70d3fa0 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
@@ -317,6 +317,7 @@
}
}
+ @override
void visitNarrowTypeInformation(NarrowTypeInformation info) {
// Omit unused Narrows.
if (!PRINT_GRAPH_ALL_NODES && info.users.isEmpty) return;
@@ -324,50 +325,61 @@
color: narrowColor);
}
+ @override
void visitPhiElementTypeInformation(PhiElementTypeInformation info) {
// Omit unused Phis.
if (!PRINT_GRAPH_ALL_NODES && info.users.isEmpty) return;
addNode(info, 'Phi ${info.variable?.name ?? ''}', color: phiColor);
}
+ @override
void visitElementInContainerTypeInformation(
ElementInContainerTypeInformation info) {
addNode(info, 'ElementInContainer');
}
+ @override
void visitElementInSetTypeInformation(ElementInSetTypeInformation info) {
addNode(info, 'ElementInSet');
}
+ @override
void visitKeyInMapTypeInformation(KeyInMapTypeInformation info) {
addNode(info, 'KeyInMap');
}
+ @override
void visitValueInMapTypeInformation(ValueInMapTypeInformation info) {
addNode(info, 'ValueInMap');
}
+ @override
void visitListTypeInformation(ListTypeInformation info) {
addNode(info, 'List');
}
+ @override
void visitSetTypeInformation(SetTypeInformation info) {
addNode(info, 'Set');
}
+ @override
void visitMapTypeInformation(MapTypeInformation info) {
addNode(info, 'Map');
}
+ @override
void visitConcreteTypeInformation(ConcreteTypeInformation info) {
addNode(info, 'Concrete');
}
+ @override
void visitStringLiteralTypeInformation(StringLiteralTypeInformation info) {
String text = shorten(info.value).replaceAll('\n', '\\n');
addNode(info, 'StringLiteral\n"$text"');
}
+ @override
void visitBoolLiteralTypeInformation(BoolLiteralTypeInformation info) {
addNode(info, 'BoolLiteral\n${info.value}');
}
@@ -387,38 +399,46 @@
addNode(info, text, color: callColor, inputs: inputs);
}
+ @override
void visitClosureCallSiteTypeInformation(
ClosureCallSiteTypeInformation info) {
handleCall(info, 'ClosureCallSite', {});
}
+ @override
void visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
handleCall(info, 'StaticCallSite', {});
}
+ @override
void visitDynamicCallSiteTypeInformation(
DynamicCallSiteTypeInformation info) {
handleCall(info, 'DynamicCallSite', {'obj': info.receiver});
}
+ @override
void visitMemberTypeInformation(MemberTypeInformation info) {
addNode(info, 'Member\n${info.debugName}');
}
+ @override
void visitParameterTypeInformation(ParameterTypeInformation info) {
addNode(info, 'Parameter ${info.debugName}');
}
+ @override
void visitClosureTypeInformation(ClosureTypeInformation info) {
String text = shorten('${info.debugName}');
addNode(info, 'Closure\n$text');
}
+ @override
void visitAwaitTypeInformation(AwaitTypeInformation info) {
String text = shorten('${info.debugName}');
addNode(info, 'Await\n$text');
}
+ @override
void visitYieldTypeInformation(YieldTypeInformation info) {
String text = shorten('${info.debugName}');
addNode(info, 'Yield\n$text');
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index d9f69ca..d1b919c 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -62,6 +62,7 @@
AbstractValueDomain get abstractValueDomain =>
closedWorld.abstractValueDomain;
+ @override
GlobalTypeInferenceResults analyzeMain(FunctionEntity main) {
inferrer = createInferrerEngineFor(main);
inferrer.runOverAllElements();
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 467890a..b8d5dcc 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -79,6 +79,7 @@
// TypeInformations are unique. Store an arbitrary identity hash code.
static int _staticHashCode = 0;
+ @override
final int hashCode = _staticHashCode = (_staticHashCode + 1).toUnsigned(30);
bool get isConcrete => false;
@@ -248,14 +249,17 @@
AbstractValueDomain abstractValueDomain, MemberTypeInformation context)
: super(abstractValueDomain.emptyType, context);
+ @override
void accept(TypeInformationVisitor visitor) {
throw new UnsupportedError("Cannot visit placeholder");
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
throw new UnsupportedError("Cannot refine placeholder");
}
+ @override
toString() => "Placeholder [$hashCode]";
}
@@ -296,11 +300,15 @@
}
}
+ @override
Iterator<TypeInformation> get iterator => assignments.keys.iterator;
+ @override
Iterable<TypeInformation> where(Function f) => assignments.keys.where(f);
+ @override
bool contains(Object info) => assignments.containsKey(info);
+ @override
String toString() => assignments.keys.toList().toString();
}
@@ -386,6 +394,7 @@
MemberEntity get member => _member;
+ @override
String get debugName => '$member';
void addCall(MemberEntity caller, Object node) {
@@ -438,6 +447,7 @@
// [users] is accurate. The inference stops tracking users for stable types.
// Note that we only override the getter, the setter will still modify the
// state of the [isStable] field inherited from [TypeInformation].
+ @override
bool get isStable => super.isStable && !isClosurized;
AbstractValue handleSpecialCases(InferrerEngine inferrer);
@@ -469,6 +479,7 @@
AbstractValue _potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer);
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
AbstractValue special = handleSpecialCases(inferrer);
if (special != null) return potentiallyNarrowType(special, inferrer);
@@ -476,16 +487,20 @@
inferrer.types.computeTypeMask(assignments), inferrer);
}
+ @override
AbstractValue safeType(InferrerEngine inferrer) {
return potentiallyNarrowType(super.safeType(inferrer), inferrer);
}
+ @override
String toString() => 'Member $_member $type';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitMemberTypeInformation(this);
}
+ @override
void cleanup() {
_callers = null;
super.cleanup();
@@ -505,6 +520,7 @@
AbstractValueDomain abstractValueDomain, FieldEntity element, this._type)
: super._internal(abstractValueDomain, element);
+ @override
AbstractValue handleSpecialCases(InferrerEngine inferrer) {
if (!inferrer.canFieldBeUsedForGlobalOptimizations(_field) ||
inferrer.assumeDynamic(_field)) {
@@ -527,11 +543,13 @@
return null;
}
+ @override
AbstractValue _potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer) {
return _narrowType(inferrer.closedWorld, mask, _type);
}
+ @override
bool hasStableType(InferrerEngine inferrer) {
// The number of assignments of non-final fields is
// not stable. Therefore such a field cannot be stable.
@@ -550,10 +568,12 @@
FunctionEntity element, this._type)
: super._internal(abstractValueDomain, element);
+ @override
AbstractValue handleSpecialCases(InferrerEngine inferrer) {
return _handleFunctionCase(_getter, inferrer);
}
+ @override
AbstractValue _potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer) {
return _narrowType(inferrer.closedWorld, mask, _type.returnType);
@@ -567,10 +587,12 @@
AbstractValueDomain abstractValueDomain, FunctionEntity element)
: super._internal(abstractValueDomain, element);
+ @override
AbstractValue handleSpecialCases(InferrerEngine inferrer) {
return _handleFunctionCase(_setter, inferrer);
}
+ @override
AbstractValue _potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer) {
return mask;
@@ -585,15 +607,18 @@
FunctionEntity element, this._type)
: super._internal(abstractValueDomain, element);
+ @override
AbstractValue handleSpecialCases(InferrerEngine inferrer) {
return _handleFunctionCase(_method, inferrer);
}
+ @override
AbstractValue _potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer) {
return _narrowType(inferrer.closedWorld, mask, _type.returnType);
}
+ @override
bool hasStableType(InferrerEngine inferrer) => false;
}
@@ -605,6 +630,7 @@
ConstructorEntity element, this._type)
: super._internal(abstractValueDomain, element);
+ @override
AbstractValue handleSpecialCases(InferrerEngine inferrer) {
AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
if (_constructor.isFromEnvironmentConstructor) {
@@ -624,11 +650,13 @@
return _handleFunctionCase(_constructor, inferrer);
}
+ @override
AbstractValue _potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer) {
return _narrowType(inferrer.closedWorld, mask, _type.returnType);
}
+ @override
bool hasStableType(InferrerEngine inferrer) {
return super.hasStableType(inferrer);
}
@@ -641,15 +669,18 @@
AbstractValueDomain abstractValueDomain, ConstructorEntity element)
: super._internal(abstractValueDomain, element);
+ @override
AbstractValue handleSpecialCases(InferrerEngine inferrer) {
return _handleFunctionCase(_constructor, inferrer);
}
+ @override
AbstractValue _potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer) {
return mask;
}
+ @override
bool hasStableType(InferrerEngine inferrer) {
return super.hasStableType(inferrer);
}
@@ -708,6 +739,7 @@
bool get isRegularParameter => !_isInitializingFormal;
+ @override
String get debugName => '$parameter';
void tagAsTearOffClosureParameter(InferrerEngine inferrer) {
@@ -805,6 +837,7 @@
return mask;
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
AbstractValue special = handleSpecialCases(inferrer);
if (special != null) return special;
@@ -812,10 +845,12 @@
inferrer.types.computeTypeMask(assignments), inferrer);
}
+ @override
AbstractValue safeType(InferrerEngine inferrer) {
return potentiallyNarrowType(super.safeType(inferrer), inferrer);
}
+ @override
bool hasStableType(InferrerEngine inferrer) {
// The number of assignments of parameters of instance methods is
// not stable. Therefore such a parameter cannot be stable.
@@ -825,10 +860,12 @@
return super.hasStableType(inferrer);
}
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitParameterTypeInformation(this);
}
+ @override
String toString() => 'Parameter $_parameter $type';
@override
@@ -882,6 +919,7 @@
assert(_call is ir.Node);
}
+ @override
String toString() => 'Call site $debugName $type';
/// Add [this] to the graph being computed by [engine].
@@ -913,6 +951,7 @@
return inferrer.types.getInferredTypeOfMember(calledElement);
}
+ @override
void addToGraph(InferrerEngine inferrer) {
MemberTypeInformation callee = _getCalledTypeInfo(inferrer);
callee.addCall(caller, _call);
@@ -937,6 +976,7 @@
return inferrer.typeOfMemberWithSelector(calledElement, selector);
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
if (isSynthesized) {
assert(arguments != null);
@@ -946,12 +986,15 @@
}
}
+ @override
Iterable<MemberEntity> get callees => [calledElement];
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitStaticCallSiteTypeInformation(this);
}
+ @override
bool hasStableType(InferrerEngine inferrer) {
bool isStable = _getCalledTypeInfo(inferrer).isStable;
return isStable &&
@@ -959,6 +1002,7 @@
super.hasStableType(inferrer);
}
+ @override
void removeAndClearReferences(InferrerEngine inferrer) {
ElementTypeInformation callee = _getCalledTypeInfo(inferrer);
callee.removeUser(this);
@@ -995,6 +1039,7 @@
assert(validCallType(_callType, _call));
}
+ @override
void addToGraph(InferrerEngine inferrer) {
assert(receiver != null);
AbstractValue typeMask = computeTypedSelector(inferrer);
@@ -1024,6 +1069,7 @@
/// methods on closures.
Iterable<MemberEntity> get concreteTargets => _concreteTargets;
+ @override
Iterable<MemberEntity> get callees => _concreteTargets;
AbstractValue computeTypedSelector(InferrerEngine inferrer) {
@@ -1151,6 +1197,7 @@
}
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
JClosedWorld closedWorld = inferrer.closedWorld;
AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
@@ -1248,6 +1295,7 @@
return result;
}
+ @override
void giveUp(InferrerEngine inferrer, {bool clearAssignments: true}) {
if (!abandonInferencing) {
inferrer.updateSelectorInMember(caller, _callType, _call, selector, mask);
@@ -1269,6 +1317,7 @@
super.giveUp(inferrer, clearAssignments: clearAssignments);
}
+ @override
void removeAndClearReferences(InferrerEngine inferrer) {
for (MemberEntity element in _concreteTargets) {
MemberTypeInformation callee =
@@ -1281,12 +1330,15 @@
super.removeAndClearReferences(inferrer);
}
+ @override
String toString() => 'Call site $debugName on ${receiver.type} $type';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitDynamicCallSiteTypeInformation(this);
}
+ @override
bool hasStableType(InferrerEngine inferrer) {
return receiver.isStable &&
_concreteTargets.every((MemberEntity element) =>
@@ -1312,23 +1364,29 @@
: super(abstractValueDomain, context, call, enclosing, selector, mask,
arguments, inLoop);
+ @override
void addToGraph(InferrerEngine inferrer) {
arguments.forEach((info) => info.addUser(this));
closure.addUser(this);
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
+ @override
Iterable<MemberEntity> get callees {
throw new UnsupportedError("Cannot compute callees of a closure call.");
}
+ @override
String toString() => 'Closure call $debugName on $closure';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitClosureCallSiteTypeInformation(this);
}
+ @override
void removeAndClearReferences(InferrerEngine inferrer) {
// This method is a placeholder for the following comment:
// We should maintain the information that the closure is a user
@@ -1353,40 +1411,51 @@
this.isStable = true;
}
+ @override
bool get isConcrete => true;
+ @override
void addUser(TypeInformation user) {
// Nothing to do, a concrete type does not get updated so never
// needs to notify its users.
}
+ @override
void addUsersOf(TypeInformation other) {
// Nothing to do, a concrete type does not get updated so never
// needs to notify its users.
}
+ @override
void removeUser(TypeInformation user) {}
+ @override
void addAssignment(TypeInformation assignment) {
throw "Not supported";
}
+ @override
void removeAssignment(TypeInformation assignment) {
throw "Not supported";
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) => type;
+ @override
bool reset(InferrerEngine inferrer) {
throw "Not supported";
}
+ @override
String toString() => 'Type $type';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitConcreteTypeInformation(this);
}
+ @override
bool hasStableType(InferrerEngine inferrer) => true;
}
@@ -1399,8 +1468,10 @@
mask, new StringConstantValue(value)));
String asString() => value;
+ @override
String toString() => 'Type $type value ${value}';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitStringLiteralTypeInformation(this);
}
@@ -1414,8 +1485,10 @@
: super(abstractValueDomain.createPrimitiveValue(
mask, value ? new TrueConstantValue() : new FalseConstantValue()));
+ @override
String toString() => 'Type $type value ${value}';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitBoolLiteralTypeInformation(this);
}
@@ -1447,11 +1520,13 @@
addAssignment(narrowedType);
}
+ @override
addAssignment(TypeInformation info) {
super.addAssignment(info);
assert(assignments.length == 1);
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
AbstractValue input = assignments.first.type;
@@ -1469,10 +1544,12 @@
return intersection;
}
+ @override
String toString() {
return 'Narrow to $typeAnnotation $type';
}
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitNarrowTypeInformation(this);
}
@@ -1492,11 +1569,13 @@
if (parentType != null) addAssignment(parentType);
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
if (!inferred) return safeType(inferrer);
return inferrer.types.computeTypeMask(assignments);
}
+ @override
bool hasStableType(InferrerEngine inferrer) {
return inferred && super.hasStableType(inferrer);
}
@@ -1531,16 +1610,20 @@
elementType.addUser(this);
}
+ @override
String toString() => 'List type $type';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitListTypeInformation(this);
}
+ @override
bool hasStableType(InferrerEngine inferrer) {
return elementType.isStable && super.hasStableType(inferrer);
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
AbstractValue mask = type;
@@ -1557,8 +1640,10 @@
return mask;
}
+ @override
AbstractValue safeType(InferrerEngine inferrer) => originalType;
+ @override
void cleanup() {
super.cleanup();
elementType.cleanup();
@@ -1573,8 +1658,10 @@
MemberTypeInformation context, elementType)
: super(abstractValueDomain, context, elementType);
+ @override
String toString() => 'Element in container $type';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitElementInContainerTypeInformation(this);
}
@@ -1592,12 +1679,15 @@
elementType.addUser(this);
}
+ @override
String toString() => 'Set type $type';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitSetTypeInformation(this);
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
AbstractValue mask = type;
@@ -1612,12 +1702,15 @@
return mask;
}
+ @override
AbstractValue safeType(InferrerEngine inferrer) => originalType;
+ @override
bool hasStableType(InferrerEngine inferrer) {
return elementType.isStable && super.hasStableType(inferrer);
}
+ @override
void cleanup() {
super.cleanup();
elementType.cleanup();
@@ -1632,8 +1725,10 @@
MemberTypeInformation context, elementType)
: super(abstractValueDomain, context, elementType);
+ @override
String toString() => 'Element in set $type';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitElementInSetTypeInformation(this);
}
@@ -1713,10 +1808,12 @@
typeInfoMap.values.forEach((v) => v.inferred = true);
}
+ @override
addAssignment(TypeInformation other) {
throw "not supported";
}
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitMapTypeInformation(this);
}
@@ -1745,6 +1842,7 @@
}
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
if (abstractValueDomain.isDictionary(type) != inDictionaryMode) {
@@ -1775,14 +1873,17 @@
return type;
}
+ @override
AbstractValue safeType(InferrerEngine inferrer) => originalType;
+ @override
bool hasStableType(InferrerEngine inferrer) {
return keyType.isStable &&
valueType.isStable &&
super.hasStableType(inferrer);
}
+ @override
void cleanup() {
super.cleanup();
keyType.cleanup();
@@ -1793,6 +1894,7 @@
_flowsInto = null;
}
+ @override
String toString() {
return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap';
}
@@ -1805,10 +1907,12 @@
MemberTypeInformation context, TypeInformation keyType)
: super(abstractValueDomain, context, keyType);
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitKeyInMapTypeInformation(this);
}
+ @override
String toString() => 'Key in Map $type';
}
@@ -1825,16 +1929,19 @@
[this.nonNull = false])
: super(abstractValueDomain, context, valueType);
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitValueInMapTypeInformation(this);
}
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
return nonNull
? super.computeType(inferrer)
: inferrer.abstractValueDomain.includeNull(super.computeType(inferrer));
}
+ @override
String toString() => 'Value in Map $type';
}
@@ -1850,12 +1957,15 @@
{this.isTry})
: super(abstractValueDomain.emptyType, context);
+ @override
AbstractValue computeType(InferrerEngine inferrer) {
return inferrer.types.computeTypeMask(assignments);
}
+ @override
String toString() => 'Phi($hashCode) $variable $type';
+ @override
void _toStructuredText(
StringBuffer sb, String indent, Set<TypeInformation> seen) {
if (seen.add(this)) {
@@ -1870,6 +1980,7 @@
}
}
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitPhiElementTypeInformation(this);
}
@@ -1885,20 +1996,25 @@
FunctionEntity get closure => _element;
+ @override
AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
+ @override
AbstractValue safeType(InferrerEngine inferrer) {
return inferrer.types.functionType.type;
}
String get debugName => '$closure';
+ @override
String toString() => 'Closure $_element';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitClosureTypeInformation(this);
}
+ @override
bool hasStableType(InferrerEngine inferrer) {
return false;
}
@@ -1945,12 +2061,15 @@
: super(abstractValueDomain.emptyType, context);
// TODO(22894): Compute a better type here.
+ @override
AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
String get debugName => '$_node';
+ @override
String toString() => 'Await';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitAwaitTypeInformation(this);
}
@@ -1963,12 +2082,15 @@
MemberTypeInformation context, this._node)
: super(abstractValueDomain.emptyType, context);
+ @override
AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
String get debugName => '$_node';
+ @override
String toString() => 'Yield';
+ @override
accept(TypeInformationVisitor visitor) {
return visitor.visitYieldTypeInformation(this);
}
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
index 4b27265..e920091 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
@@ -12,12 +12,15 @@
/// debugging data stream.
static const String tag = 'container-type-mask';
+ @override
final TypeMask forwardTo;
// The [Node] where this type mask was created.
+ @override
final ir.TreeNode allocationNode;
// The [Entity] where this type mask was created.
+ @override
final MemberEntity allocationElement;
// The element type of this container.
@@ -44,6 +47,7 @@
}
/// Serializes this [ContainerTypeMask] to [sink].
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(TypeMaskKind.container);
sink.begin(tag);
@@ -55,6 +59,7 @@
sink.end(tag);
}
+ @override
TypeMask nullable() {
return isNullable
? this
@@ -62,6 +67,7 @@
allocationElement, elementType, length);
}
+ @override
TypeMask nonNullable() {
return isNullable
? new ContainerTypeMask(forwardTo.nonNullable(), allocationNode,
@@ -69,9 +75,12 @@
: this;
}
+ @override
bool get isContainer => true;
+ @override
bool get isExact => true;
+ @override
bool equalsDisregardNull(other) {
if (other is! ContainerTypeMask) return false;
return super.equalsDisregardNull(other) &&
@@ -80,12 +89,14 @@
length == other.length;
}
+ @override
TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
return forwardIntersection.isNullable ? nullable() : nonNullable();
}
+ @override
TypeMask union(dynamic other, JClosedWorld closedWorld) {
if (this == other) {
return this;
@@ -113,13 +124,16 @@
}
}
+ @override
bool operator ==(other) => super == other;
+ @override
int get hashCode {
return computeHashCode(
allocationNode, isNullable, elementType, length, forwardTo);
}
+ @override
String toString() {
return 'Container($forwardTo, element: $elementType, length: $length)';
}
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
index 8463350..827840c 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
@@ -44,6 +44,7 @@
}
/// Serializes this [DictionaryTypeMask] to [sink].
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(TypeMaskKind.dictionary);
sink.begin(tag);
@@ -59,6 +60,7 @@
sink.end(tag);
}
+ @override
TypeMask nullable() {
return isNullable
? this
@@ -66,6 +68,7 @@
allocationElement, keyType, valueType, _typeMap);
}
+ @override
TypeMask nonNullable() {
return isNullable
? new DictionaryTypeMask(forwardTo.nonNullable(), allocationNode,
@@ -73,13 +76,16 @@
: this;
}
+ @override
bool get isDictionary => true;
+ @override
bool get isExact => true;
bool containsKey(String key) => _typeMap.containsKey(key);
TypeMask getValueForKey(String key) => _typeMap[key];
+ @override
bool equalsDisregardNull(other) {
if (other is! DictionaryTypeMask) return false;
return allocationNode == other.allocationNode &&
@@ -90,12 +96,14 @@
(k) => _typeMap.containsKey(k) && _typeMap[k] == other._typeMap[k]);
}
+ @override
TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
return forwardIntersection.isNullable ? nullable() : nonNullable();
}
+ @override
TypeMask union(dynamic other, JClosedWorld closedWorld) {
if (this == other) {
return this;
@@ -135,12 +143,15 @@
}
}
+ @override
bool operator ==(other) => super == other;
+ @override
int get hashCode {
return computeHashCode(allocationNode, isNullable, _typeMap, forwardTo);
}
+ @override
String toString() {
return 'Dictionary($forwardTo, key: $keyType, '
'value: $valueType, map: $_typeMap)';
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
index 8478b0f..d8ddc8a 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
@@ -78,6 +78,7 @@
}
/// Serializes this [FlatTypeMask] to [sink].
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(TypeMaskKind.flat);
sink.begin(tag);
@@ -90,18 +91,30 @@
? ClassQuery.EXACT
: (isSubclass ? ClassQuery.SUBCLASS : ClassQuery.SUBTYPE);
+ @override
bool get isEmpty => isEmptyOrNull && !isNullable;
+ @override
bool get isNull => isEmptyOrNull && isNullable;
+ @override
bool get isEmptyOrNull => (flags >> 1) == EMPTY;
+ @override
bool get isExact => (flags >> 1) == EXACT;
+ @override
bool get isNullable => (flags & 1) != 0;
+ @override
bool get isUnion => false;
+ @override
bool get isContainer => false;
+ @override
bool get isSet => false;
+ @override
bool get isMap => false;
+ @override
bool get isDictionary => false;
+ @override
bool get isForwarding => false;
+ @override
bool get isValue => false;
// TODO(kasperl): Get rid of these. They should not be a visible
@@ -110,14 +123,17 @@
bool get isSubclass => (flags >> 1) == SUBCLASS;
bool get isSubtype => (flags >> 1) == SUBTYPE;
+ @override
TypeMask nullable() {
return isNullable ? this : new FlatTypeMask.internal(base, flags | 1);
}
+ @override
TypeMask nonNullable() {
return isNullable ? new FlatTypeMask.internal(base, flags & ~1) : this;
}
+ @override
bool contains(ClassEntity other, JClosedWorld closedWorld) {
if (isEmptyOrNull) {
return false;
@@ -162,6 +178,7 @@
return false;
}
+ @override
bool isInMask(TypeMask other, JClosedWorld closedWorld) {
if (isEmptyOrNull) return isNullable ? other.isNullable : true;
// The empty type contains no classes.
@@ -195,10 +212,12 @@
return satisfies(otherBase, closedWorld);
}
+ @override
bool containsMask(TypeMask other, JClosedWorld closedWorld) {
return other.isInMask(this, closedWorld);
}
+ @override
bool containsOnlyInt(JClosedWorld closedWorld) {
CommonElements commonElements = closedWorld.commonElements;
return base == closedWorld.commonElements.intClass ||
@@ -208,11 +227,13 @@
base == commonElements.jsUInt32Class;
}
+ @override
bool containsOnlyDouble(JClosedWorld closedWorld) {
return base == closedWorld.commonElements.doubleClass ||
base == closedWorld.commonElements.jsDoubleClass;
}
+ @override
bool containsOnlyNum(JClosedWorld closedWorld) {
return containsOnlyInt(closedWorld) ||
containsOnlyDouble(closedWorld) ||
@@ -220,20 +241,24 @@
base == closedWorld.commonElements.jsNumberClass;
}
+ @override
bool containsOnlyBool(JClosedWorld closedWorld) {
return base == closedWorld.commonElements.boolClass ||
base == closedWorld.commonElements.jsBoolClass;
}
+ @override
bool containsOnlyString(JClosedWorld closedWorld) {
return base == closedWorld.commonElements.stringClass ||
base == closedWorld.commonElements.jsStringClass;
}
+ @override
bool containsOnly(ClassEntity cls) {
return base == cls;
}
+ @override
bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
if (isEmptyOrNull) return false;
if (closedWorld.classHierarchy.isSubtypeOf(base, cls)) return true;
@@ -242,6 +267,7 @@
/// Returns the [Entity] if this type represents a single class, otherwise
/// returns `null`. This method is conservative.
+ @override
ClassEntity singleClass(JClosedWorld closedWorld) {
if (isEmptyOrNull) return null;
if (isNullable) return null; // It is Null and some other class.
@@ -258,11 +284,13 @@
}
/// Returns whether or not this type mask contains all types.
+ @override
bool containsAll(JClosedWorld closedWorld) {
if (isEmptyOrNull || isExact) return false;
return identical(base, closedWorld.commonElements.objectClass);
}
+ @override
TypeMask union(TypeMask other, JClosedWorld closedWorld) {
assert(other != null);
assert(TypeMask.assertIsNormalized(this, closedWorld));
@@ -352,6 +380,7 @@
: this;
}
+ @override
TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
assert(other != null);
if (other is! FlatTypeMask) return other.intersection(this, closedWorld);
@@ -425,6 +454,7 @@
}
}
+ @override
bool isDisjoint(TypeMask other, JClosedWorld closedWorld) {
if (other is! FlatTypeMask) return other.isDisjoint(this, closedWorld);
FlatTypeMask flatOther = other;
@@ -517,6 +547,7 @@
/// Returns whether [element] is a potential target when being
/// invoked on this type mask. [selector] is used to ensure library
/// privacy is taken into account.
+ @override
bool canHit(MemberEntity element, Name name, JClosedWorld closedWorld) {
CommonElements commonElements = closedWorld.commonElements;
assert(element.name == name.text);
@@ -552,6 +583,7 @@
}
}
+ @override
bool needsNoSuchMethodHandling(
Selector selector, covariant JClosedWorld closedWorld) {
// A call on an empty type mask is either dead code, or a call on
@@ -566,6 +598,7 @@
return closedWorld.needsNoSuchMethod(base, selector, _classQuery);
}
+ @override
MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld) {
if (isEmptyOrNull) return null;
if (closedWorld.includesClosureCall(selector, this)) return null;
@@ -593,6 +626,7 @@
return null;
}
+ @override
bool operator ==(var other) {
if (identical(this, other)) return true;
if (other is! FlatTypeMask) return false;
@@ -600,10 +634,12 @@
return (flags == otherMask.flags) && (base == otherMask.base);
}
+ @override
int get hashCode {
return (base == null ? 0 : base.hashCode) + 31 * flags.hashCode;
}
+ @override
String toString() {
if (isEmptyOrNull) return isNullable ? '[null]' : '[empty]';
StringBuffer buffer = new StringBuffer();
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
index 6021460..39f850c 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
@@ -11,68 +11,93 @@
ForwardingTypeMask();
+ @override
bool get isEmptyOrNull => forwardTo.isEmptyOrNull;
+ @override
bool get isEmpty => forwardTo.isEmpty;
+ @override
bool get isNullable => forwardTo.isNullable;
+ @override
bool get isNull => forwardTo.isNull;
+ @override
bool get isExact => forwardTo.isExact;
+ @override
bool get isUnion => false;
+ @override
bool get isContainer => false;
+ @override
bool get isSet => false;
+ @override
bool get isMap => false;
+ @override
bool get isDictionary => false;
+ @override
bool get isValue => false;
+ @override
bool get isForwarding => true;
+ @override
bool isInMask(TypeMask other, JClosedWorld closedWorld) {
return forwardTo.isInMask(other, closedWorld);
}
+ @override
bool containsMask(TypeMask other, JClosedWorld closedWorld) {
return forwardTo.containsMask(other, closedWorld);
}
+ @override
bool containsOnlyInt(JClosedWorld closedWorld) {
return forwardTo.containsOnlyInt(closedWorld);
}
+ @override
bool containsOnlyDouble(JClosedWorld closedWorld) {
return forwardTo.containsOnlyDouble(closedWorld);
}
+ @override
bool containsOnlyNum(JClosedWorld closedWorld) {
return forwardTo.containsOnlyNum(closedWorld);
}
+ @override
bool containsOnlyBool(JClosedWorld closedWorld) {
return forwardTo.containsOnlyBool(closedWorld);
}
+ @override
bool containsOnlyString(JClosedWorld closedWorld) {
return forwardTo.containsOnlyString(closedWorld);
}
+ @override
bool containsOnly(ClassEntity cls) {
return forwardTo.containsOnly(cls);
}
+ @override
bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
return forwardTo.satisfies(cls, closedWorld);
}
+ @override
bool contains(ClassEntity cls, JClosedWorld closedWorld) {
return forwardTo.contains(cls, closedWorld);
}
+ @override
bool containsAll(JClosedWorld closedWorld) {
return forwardTo.containsAll(closedWorld);
}
+ @override
ClassEntity singleClass(JClosedWorld closedWorld) {
return forwardTo.singleClass(closedWorld);
}
+ @override
TypeMask union(other, JClosedWorld closedWorld) {
if (this == other) {
return this;
@@ -84,23 +109,28 @@
return forwardTo.union(other, closedWorld);
}
+ @override
bool isDisjoint(TypeMask other, JClosedWorld closedWorld) {
return forwardTo.isDisjoint(other, closedWorld);
}
+ @override
TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
return forwardTo.intersection(other, closedWorld);
}
+ @override
bool needsNoSuchMethodHandling(
Selector selector, covariant JClosedWorld closedWorld) {
return forwardTo.needsNoSuchMethodHandling(selector, closedWorld);
}
+ @override
bool canHit(MemberEntity element, Name name, JClosedWorld closedWorld) {
return forwardTo.canHit(element, name, closedWorld);
}
+ @override
MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld) {
return forwardTo.locateSingleMember(selector, closedWorld);
}
@@ -114,10 +144,12 @@
}
}
+ @override
bool operator ==(other) {
return equalsDisregardNull(other) && isNullable == other.isNullable;
}
+ @override
int get hashCode => throw "Subclass should implement hashCode getter";
}
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
index 2486256..7ba33af 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
@@ -12,12 +12,15 @@
/// debugging data stream.
static const String tag = 'map-type-mask';
+ @override
final TypeMask forwardTo;
// The [Node] where this type mask was created.
+ @override
final ir.TreeNode allocationNode;
// The [MemberEntity] where this type mask was created.
+ @override
final MemberEntity allocationElement;
// The value type of this map.
@@ -44,6 +47,7 @@
}
/// Serializes this [MapTypeMask] to [sink].
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(TypeMaskKind.map);
sink.begin(tag);
@@ -55,6 +59,7 @@
sink.end(tag);
}
+ @override
TypeMask nullable() {
return isNullable
? this
@@ -62,6 +67,7 @@
allocationElement, keyType, valueType);
}
+ @override
TypeMask nonNullable() {
return isNullable
? new MapTypeMask(forwardTo.nonNullable(), allocationNode,
@@ -69,10 +75,14 @@
: this;
}
+ @override
bool get isContainer => false;
+ @override
bool get isMap => true;
+ @override
bool get isExact => true;
+ @override
bool equalsDisregardNull(other) {
if (other is! MapTypeMask) return false;
return super.equalsDisregardNull(other) &&
@@ -81,12 +91,14 @@
valueType == other.valueType;
}
+ @override
TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
return forwardIntersection.isNullable ? nullable() : nonNullable();
}
+ @override
TypeMask union(dynamic other, JClosedWorld closedWorld) {
if (this == other) {
return this;
@@ -128,13 +140,16 @@
}
}
+ @override
bool operator ==(other) => super == other;
+ @override
int get hashCode {
return computeHashCode(
allocationNode, isNullable, keyType, valueType, forwardTo);
}
+ @override
String toString() {
return 'Map($forwardTo, key: $keyType, value: $valueType)';
}
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart
index fb0a7e2..966cbdf 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart
@@ -12,12 +12,15 @@
/// data stream.
static const String tag = 'set-type-mask';
+ @override
final TypeMask forwardTo;
// The [Node] where this type mask was created.
+ @override
final ir.TreeNode allocationNode;
// The [Entity] where this type mask was created.
+ @override
final MemberEntity allocationElement;
// The element type of this set.
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
index cb54ce7..cf6099d 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
@@ -48,6 +48,7 @@
return _masks.add(mask);
}
+ @override
String toString() {
if (isAll) {
return '<all>';
@@ -361,6 +362,7 @@
///
/// Note: This may differ from semantic equality in the set containment sense.
/// Use [containsMask] and [isInMask] for that, instead.
+ @override
bool operator ==(other);
/// If this returns `true`, [other] is guaranteed to be a supertype of this
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
index 98a5a87..1c3b7ec 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
@@ -34,6 +34,7 @@
}
/// Serializes this [UnionTypeMask] to [sink].
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(TypeMaskKind.union);
sink.begin(tag);
@@ -161,6 +162,7 @@
return new TypeMask(bestElement, bestKind, isNullable, closedWorld);
}
+ @override
TypeMask union(dynamic other, JClosedWorld closedWorld) {
other = TypeMask.nonForwardingMask(other);
if (!other.isUnion && disjointMasks.contains(other)) return this;
@@ -175,6 +177,7 @@
return new TypeMask.unionOf(newList, closedWorld);
}
+ @override
TypeMask intersection(dynamic other, JClosedWorld closedWorld) {
other = TypeMask.nonForwardingMask(other);
if (!other.isUnion && disjointMasks.contains(other)) return other;
@@ -197,6 +200,7 @@
return new TypeMask.unionOf(intersections, closedWorld);
}
+ @override
bool isDisjoint(TypeMask other, JClosedWorld closedWorld) {
for (var current in disjointMasks) {
if (!current.isDisjoint(other, closedWorld)) return false;
@@ -204,6 +208,7 @@
return true;
}
+ @override
TypeMask nullable() {
if (isNullable) return this;
List<FlatTypeMask> newList = new List<FlatTypeMask>.from(disjointMasks);
@@ -211,6 +216,7 @@
return new UnionTypeMask._internal(newList);
}
+ @override
TypeMask nonNullable() {
if (!isNullable) return this;
Iterable<FlatTypeMask> newIterable = disjointMasks.map((e) {
@@ -220,17 +226,29 @@
return new UnionTypeMask._internal(newIterable);
}
+ @override
bool get isEmptyOrNull => false;
+ @override
bool get isEmpty => false;
+ @override
bool get isNull => false;
+ @override
bool get isNullable => disjointMasks.any((e) => e.isNullable);
+ @override
bool get isExact => false;
+ @override
bool get isUnion => true;
+ @override
bool get isContainer => false;
+ @override
bool get isSet => false;
+ @override
bool get isMap => false;
+ @override
bool get isDictionary => false;
+ @override
bool get isForwarding => false;
+ @override
bool get isValue => false;
/// Checks whether [other] is contained in this union.
@@ -268,6 +286,7 @@
return members.every((ClassEntity cls) => this.contains(cls, closedWorld));
}
+ @override
bool isInMask(TypeMask other, JClosedWorld closedWorld) {
other = TypeMask.nonForwardingMask(other);
if (isNullable && !other.isNullable) return false;
@@ -296,6 +315,7 @@
return disjointMasks.every((mask) => mask.isInMask(other, closedWorld));
}
+ @override
bool containsMask(TypeMask other, JClosedWorld closedWorld) {
other = TypeMask.nonForwardingMask(other);
if (other.isNullable && !isNullable) return false;
@@ -311,55 +331,68 @@
return contained;
}
+ @override
bool containsOnlyInt(JClosedWorld closedWorld) {
return disjointMasks.every((mask) => mask.containsOnlyInt(closedWorld));
}
+ @override
bool containsOnlyDouble(JClosedWorld closedWorld) {
return disjointMasks.every((mask) => mask.containsOnlyDouble(closedWorld));
}
+ @override
bool containsOnlyNum(JClosedWorld closedWorld) {
return disjointMasks.every((mask) {
return mask.containsOnlyNum(closedWorld);
});
}
+ @override
bool containsOnlyBool(JClosedWorld closedWorld) {
return disjointMasks.every((mask) => mask.containsOnlyBool(closedWorld));
}
+ @override
bool containsOnlyString(JClosedWorld closedWorld) {
return disjointMasks.every((mask) => mask.containsOnlyString(closedWorld));
}
+ @override
bool containsOnly(ClassEntity element) {
return disjointMasks.every((mask) => mask.containsOnly(element));
}
+ @override
bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
return disjointMasks.every((mask) => mask.satisfies(cls, closedWorld));
}
+ @override
bool contains(ClassEntity cls, JClosedWorld closedWorld) {
return disjointMasks.any((e) => e.contains(cls, closedWorld));
}
+ @override
bool containsAll(JClosedWorld closedWorld) {
return disjointMasks.any((mask) => mask.containsAll(closedWorld));
}
+ @override
ClassEntity singleClass(JClosedWorld closedWorld) => null;
+ @override
bool needsNoSuchMethodHandling(Selector selector, JClosedWorld closedWorld) {
return disjointMasks
.any((e) => e.needsNoSuchMethodHandling(selector, closedWorld));
}
+ @override
bool canHit(MemberEntity element, Name name, JClosedWorld closedWorld) {
return disjointMasks.any((e) => e.canHit(element, name, closedWorld));
}
+ @override
MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld) {
MemberEntity candidate;
for (FlatTypeMask mask in disjointMasks) {
@@ -375,6 +408,7 @@
return candidate;
}
+ @override
String toString() {
String masksString =
(disjointMasks.map((TypeMask mask) => mask.toString()).toList()..sort())
@@ -382,6 +416,7 @@
return 'Union($masksString)';
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
@@ -398,6 +433,7 @@
containsAll();
}
+ @override
int get hashCode {
int hashCode = isNullable ? 86 : 43;
// The order of the masks in [disjointMasks] must not affect the
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart
index 45c1300..1c965dc 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart
@@ -9,6 +9,7 @@
/// debugging data stream.
static const String tag = 'value-type-mask';
+ @override
final TypeMask forwardTo;
final PrimitiveConstantValue value;
@@ -25,6 +26,7 @@
}
/// Serializes this [ValueTypeMask] to [sink].
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(TypeMaskKind.value);
sink.begin(tag);
@@ -33,35 +35,43 @@
sink.end(tag);
}
+ @override
TypeMask nullable() {
return isNullable ? this : new ValueTypeMask(forwardTo.nullable(), value);
}
+ @override
TypeMask nonNullable() {
return isNullable
? new ValueTypeMask(forwardTo.nonNullable(), value)
: this;
}
+ @override
bool get isValue => true;
+ @override
bool equalsDisregardNull(other) {
if (other is! ValueTypeMask) return false;
return super.equalsDisregardNull(other) && value == other.value;
}
+ @override
TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
return forwardIntersection.isNullable ? nullable() : nonNullable();
}
+ @override
bool operator ==(other) => super == other;
+ @override
int get hashCode {
return computeHashCode(value, isNullable, forwardTo);
}
+ @override
String toString() {
return 'Value($forwardTo, value: ${value.toDartText()})';
}
diff --git a/pkg/compiler/lib/src/inferrer/types.dart b/pkg/compiler/lib/src/inferrer/types.dart
index 6a1017b..265d76d 100644
--- a/pkg/compiler/lib/src/inferrer/types.dart
+++ b/pkg/compiler/lib/src/inferrer/types.dart
@@ -147,6 +147,7 @@
/// Global analysis that infers concrete types.
class GlobalTypeInferenceTask extends CompilerTask {
// TODO(sigmund): rename at the same time as our benchmarking tools.
+ @override
final String name = 'Type inference';
final Compiler compiler;
@@ -187,7 +188,9 @@
/// in a debugging data stream.
static const String tag = 'global-type-inference-results';
+ @override
final JClosedWorld closedWorld;
+ @override
final InferredData inferredData;
final GlobalTypeInferenceMemberResult _deadFieldResult;
final GlobalTypeInferenceMemberResult _deadMethodResult;
@@ -240,6 +243,7 @@
allocatedLists);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeBool(false); // Is _not_ trivial.
sink.begin(tag);
@@ -365,8 +369,10 @@
bool isFixedArrayCheckedForGrowable(ir.Node ctorCall) =>
checkedForGrowableLists.contains(ctorCall);
+ @override
AbstractValue typeOfNewList(ir.Node node) => _allocatedLists[node];
+ @override
AbstractValue typeOfListLiteral(ir.Node node) => _allocatedLists[node];
}
@@ -377,9 +383,13 @@
static const String tag = 'global-type-inference-member-result';
final GlobalTypeInferenceElementData _data;
+ @override
final AbstractValue returnType;
+ @override
final AbstractValue type;
+ @override
final bool throwsAlways;
+ @override
final bool isCalledOnce;
GlobalTypeInferenceMemberResultImpl(this._data, this.returnType, this.type,
@@ -403,6 +413,7 @@
throwsAlways: throwsAlways, isCalledOnce: isCalledOnce);
}
+ @override
void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
sink.begin(tag);
sink.writeValueOrNull(_data, (GlobalTypeInferenceElementData data) {
@@ -415,19 +426,26 @@
sink.end(tag);
}
+ @override
AbstractValue typeOfSend(ir.Node node) => _data?.typeOfSend(node);
+ @override
AbstractValue typeOfGetter(ir.Node node) => _data?.typeOfGetter(node);
+ @override
AbstractValue typeOfIterator(ir.Node node) => _data?.typeOfIterator(node);
+ @override
AbstractValue typeOfIteratorMoveNext(ir.Node node) =>
_data?.typeOfIteratorMoveNext(node);
+ @override
AbstractValue typeOfIteratorCurrent(ir.Node node) =>
_data?.typeOfIteratorCurrent(node);
}
class TrivialGlobalTypeInferenceResults implements GlobalTypeInferenceResults {
+ @override
final JClosedWorld closedWorld;
final TrivialGlobalTypeInferenceMemberResult _trivialMemberResult;
final AbstractValue _trivialParameterResult;
+ @override
final InferredData inferredData = new TrivialInferredData();
TrivialGlobalTypeInferenceResults(this.closedWorld)
@@ -435,6 +453,7 @@
closedWorld.abstractValueDomain.dynamicType),
_trivialParameterResult = closedWorld.abstractValueDomain.dynamicType;
+ @override
void writeToDataSink(DataSink sink) {
sink.writeBool(true); // Is trivial.
}
@@ -497,6 +516,7 @@
@override
bool get isCalledOnce => false;
+ @override
void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
throw new UnsupportedError(
"TrivialGlobalTypeInferenceMemberResult.writeToDataSink");
@@ -539,6 +559,7 @@
@override
bool get isCalledOnce => false;
+ @override
void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
throw new UnsupportedError(
"DeadFieldGlobalTypeInferenceResult.writeToDataSink");
@@ -581,6 +602,7 @@
@override
bool get isCalledOnce => false;
+ @override
void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
throw new UnsupportedError(
"DeadFieldGlobalTypeInferenceResult.writeToDataSink");
diff --git a/pkg/compiler/lib/src/io/code_output.dart b/pkg/compiler/lib/src/io/code_output.dart
index 9ccc4b3..d7342ef 100644
--- a/pkg/compiler/lib/src/io/code_output.dart
+++ b/pkg/compiler/lib/src/io/code_output.dart
@@ -50,9 +50,11 @@
}
class _SourceLocationsImpl implements SourceLocations {
+ @override
final String name;
final AbstractCodeOutput codeOutput;
Map<int, List<SourceLocation>> markers = <int, List<SourceLocation>>{};
+ @override
Map<int, List<FrameEntry>> frameMarkers = <int, List<FrameEntry>>{};
_SourceLocationsImpl(this.name, this.codeOutput);
@@ -143,6 +145,7 @@
abstract class AbstractCodeOutput extends CodeOutput {
Map<String, _SourceLocationsImpl> sourceLocationsMap =
<String, _SourceLocationsImpl>{};
+ @override
bool isClosed = false;
void _addInternal(String text);
@@ -199,10 +202,12 @@
@override
int get length => buffer.length;
+ @override
String getText() {
return buffer.toString();
}
+ @override
String toString() {
throw "Don't use CodeBuffer.toString() since it drops sourcemap data.";
}
@@ -210,6 +215,7 @@
/// [CodeOutput] using a [CompilationOutput] as backend.
class StreamCodeOutput extends AbstractCodeOutput {
+ @override
int length = 0;
final OutputSink output;
final List<CodeOutputListener> _listeners;
@@ -225,6 +231,7 @@
}
}
+ @override
void close() {
output.close();
super.close();
diff --git a/pkg/compiler/lib/src/io/kernel_source_information.dart b/pkg/compiler/lib/src/io/kernel_source_information.dart
index 3e63370..520fbb40 100644
--- a/pkg/compiler/lib/src/io/kernel_source_information.dart
+++ b/pkg/compiler/lib/src/io/kernel_source_information.dart
@@ -109,6 +109,8 @@
location = node.location;
offset = node.fileOffset;
}
+ assert(
+ location != null, "No location found for $node (${node.runtimeType})");
return new KernelSourceLocation(location, offset, name);
}
@@ -483,8 +485,11 @@
}
class KernelSourceLocation extends AbstractSourceLocation {
+ @override
final int offset;
+ @override
final String sourceName;
+ @override
final Uri sourceUri;
KernelSourceLocation(ir.Location location, this.offset, this.sourceName)
diff --git a/pkg/compiler/lib/src/io/location_provider.dart b/pkg/compiler/lib/src/io/location_provider.dart
index a015bab..3455e31 100644
--- a/pkg/compiler/lib/src/io/location_provider.dart
+++ b/pkg/compiler/lib/src/io/location_provider.dart
@@ -49,6 +49,7 @@
this.length = length;
}
+ @override
String toString() {
return 'lineStarts=$lineStarts,length=$length';
}
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 0d3b387..732b841 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -23,6 +23,7 @@
@override
final SourceLocation innerPosition;
+ @override
final List<FrameContext> inliningContext;
PositionSourceInformation(
@@ -49,11 +50,13 @@
return new SourceSpan(uri, offset, offset);
}
+ @override
int get hashCode {
return 0x7FFFFFFF &
(startPosition.hashCode * 17 + innerPosition.hashCode * 19);
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! PositionSourceInformation) return false;
@@ -78,6 +81,7 @@
return sb.toString();
}
+ @override
String get shortText {
if (startPosition != null) {
return _computeText(startPosition.sourceUri.pathSegments.last);
@@ -86,6 +90,7 @@
}
}
+ @override
String toString() {
if (startPosition != null) {
return _computeText('${startPosition.sourceUri}');
@@ -152,6 +157,7 @@
}
}
+ @override
String toString() {
return 'CodePosition(start=$startPosition,'
'end=$endPosition,closing=$closingPosition)';
@@ -178,6 +184,7 @@
_codePositionMap[node] = codePosition;
}
+ @override
CodePosition operator [](js.Node node) => _codePositionMap[node];
}
@@ -295,6 +302,7 @@
}
}
+ @override
void process(js.Node node, BufferedCodeOutput code) {
new JavaScriptTracer(codePositionMap, reader, traceListeners).apply(node);
inliningListener?.finish();
@@ -379,6 +387,7 @@
class InliningTraceListener extends TraceListener
with NodeToSourceInformationMixin {
final SourceMapper sourceMapper;
+ @override
final SourceInformationReader reader;
final Map<int, List<FrameContext>> _frames = {};
@@ -459,6 +468,7 @@
class PositionTraceListener extends TraceListener
with NodeToSourceInformationMixin {
final SourceMapper sourceMapper;
+ @override
final SourceInformationReader reader;
PositionTraceListener(this.sourceMapper, this.reader);
@@ -752,6 +762,7 @@
int get value => subexpressionOffset;
+ @override
String toString() {
return 'Offset[statementOffset=$statementOffset,'
'leftToRightOffset=$leftToRightOffset,'
@@ -1369,12 +1380,14 @@
return sb.toString();
}
+ @override
String toString() => getCoverageReport();
}
/// [TraceListener] that registers [onStep] callbacks with [coverage].
class CoverageListener extends TraceListener with NodeToSourceInformationMixin {
final Coverage coverage;
+ @override
final SourceInformationReader reader;
CoverageListener(this.coverage, this.reader);
diff --git a/pkg/compiler/lib/src/io/source_file.dart b/pkg/compiler/lib/src/io/source_file.dart
index ff227ae..ffdb8d0 100644
--- a/pkg/compiler/lib/src/io/source_file.dart
+++ b/pkg/compiler/lib/src/io/source_file.dart
@@ -17,8 +17,10 @@
/// a UTF-8 encoded [List<int>] of bytes.
abstract class SourceFile<T> implements Input<T>, LocationProvider {
/// The absolute URI of the source file.
+ @override
Uri get uri;
+ @override
InputKind get inputKind => InputKind.UTF8;
kernel.Source cachedKernelSource;
@@ -83,6 +85,7 @@
return starts;
}
+ @override
kernel.Location getLocation(int offset) {
return kernelSource.getLocation(null, offset);
}
@@ -172,6 +175,7 @@
}
class Utf8BytesSourceFile extends SourceFile<List<int>> {
+ @override
final Uri uri;
/// The UTF-8 encoded content of the source file.
@@ -184,22 +188,27 @@
Utf8BytesSourceFile(this.uri, List<int> content)
: this.zeroTerminatedContent = _zeroTerminateIfNecessary(content);
+ @override
List<int> get data => zeroTerminatedContent;
+ @override
String slowText() {
// Don't convert the trailing zero byte.
return utf8.decoder
.convert(zeroTerminatedContent, 0, zeroTerminatedContent.length - 1);
}
+ @override
List<int> slowUtf8ZeroTerminatedBytes() => zeroTerminatedContent;
+ @override
String slowSubstring(int start, int end) {
// TODO(lry): to make this faster, the scanner could record the UTF-8 slack
// for all positions of the source text. We could use [:content.sublist:].
return slowText().substring(start, end);
}
+ @override
int get length {
if (lengthCache == -1) {
// During scanning the length is not yet assigned, so we use a slow path.
@@ -208,17 +217,20 @@
return lengthCache;
}
+ @override
set length(int v) => lengthCache = v;
int lengthCache = -1;
}
class CachingUtf8BytesSourceFile extends Utf8BytesSourceFile {
String cachedText;
+ @override
final String filename;
CachingUtf8BytesSourceFile(Uri uri, this.filename, List<int> content)
: super(uri, content);
+ @override
String slowText() {
if (cachedText == null) {
cachedText = super.slowText();
@@ -228,7 +240,9 @@
}
class StringSourceFile extends SourceFile<List<int>> {
+ @override
final Uri uri;
+ @override
final String filename;
final String text;
@@ -240,26 +254,35 @@
StringSourceFile.fromName(String filename, String text)
: this(new Uri(path: filename), filename, text);
+ @override
List<int> get data => utf8.encode(text);
+ @override
int get length => text.length;
+ @override
set length(int v) {}
+ @override
String slowText() => text;
+ @override
List<int> slowUtf8ZeroTerminatedBytes() {
return _zeroTerminateIfNecessary(utf8.encode(text));
}
+ @override
String slowSubstring(int start, int end) => text.substring(start, end);
}
/// Binary input data.
class Binary implements Input<List<int>> {
+ @override
final Uri uri;
+ @override
final List<int> data;
Binary(this.uri, this.data);
+ @override
InputKind get inputKind => InputKind.binary;
}
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index 756340b..7709884 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -53,6 +53,7 @@
FrameContext(this.callInformation, this.inlinedMethodName);
+ @override
String toString() => "(FrameContext: $callInformation, $inlinedMethodName)";
}
@@ -225,12 +226,14 @@
/// `true` if the offset within the length of the source file.
bool get isValid;
+ @override
int get hashCode {
return sourceUri.hashCode * 17 +
offset.hashCode * 19 +
sourceName.hashCode * 23;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! SourceLocation) return false;
@@ -241,6 +244,7 @@
String get shortText => '${sourceUri?.pathSegments?.last}:[$line,$column]';
+ @override
String toString() => '${sourceUri}:[${line},${column}]';
}
@@ -264,37 +268,49 @@
: this.fromLocation(location._location);
/// The absolute URI of the source file of this source location.
+ @override
Uri get sourceUri => _sourceFile.uri;
/// The character offset of the this source location into the source file.
+ @override
int get offset;
/// The 1-based line number of the [offset].
+ @override
int get line => (_location ??= _sourceFile.getLocation(offset)).line;
/// The 1-based column number of the [offset] with its line.
+ @override
int get column => (_location ??= _sourceFile.getLocation(offset)).column;
/// The name associated with this source location, if any.
+ @override
String get sourceName;
/// `true` if the offset within the length of the source file.
+ @override
bool get isValid => offset < _sourceFile.length;
+ @override
String get shortText => '${sourceUri.pathSegments.last}:[$line,$column]';
+ @override
String toString() => '${sourceUri}:[$line,$column]';
}
class OffsetSourceLocation extends AbstractSourceLocation {
+ @override
final int offset;
+ @override
final String sourceName;
OffsetSourceLocation(SourceFile sourceFile, this.offset, this.sourceName)
: super(sourceFile);
+ @override
String get shortText => '${super.shortText}:$sourceName';
+ @override
String toString() => '${super.toString()}:$sourceName';
}
@@ -365,6 +381,7 @@
String get shortName => '<no-location>';
+ @override
String toString() => '<no-location>';
}
diff --git a/pkg/compiler/lib/src/ir/annotations.dart b/pkg/compiler/lib/src/ir/annotations.dart
index 485362e..1cd8bcf 100644
--- a/pkg/compiler/lib/src/ir/annotations.dart
+++ b/pkg/compiler/lib/src/ir/annotations.dart
@@ -7,33 +7,105 @@
class IrAnnotationData {
Map<ir.Class, String> _nativeClassNames = {};
+ Set<ir.Member> _nativeMembers = {};
+ Map<ir.Member, String> _nativeMemberNames = {};
+ Map<ir.Member, List<String>> _createsAnnotations = {};
+ Map<ir.Member, List<String>> _returnsAnnotations = {};
Map<ir.Library, String> _jsInteropLibraryNames = {};
Map<ir.Class, String> _jsInteropClassNames = {};
Set<ir.Class> _anonymousJsInteropClasses = {};
Map<ir.Member, String> _jsInteropMemberNames = {};
+ Map<ir.Member, List<PragmaAnnotationData>> _memberPragmaAnnotations = {};
+
+ // Returns the text from the `@Native(<text>)` annotation of [node], if any.
String getNativeClassName(ir.Class node) => _nativeClassNames[node];
+ // Returns `true` if [node] has a native body, as in `method() native;`.
+ bool hasNativeBody(ir.Member node) => _nativeMembers.contains(node);
+
+ // Returns the text from the `@JSName(<text>)` annotation of [node], if any.
+ String getNativeMemberName(ir.Member node) => _nativeMemberNames[node];
+
+ // Returns a list of the text from the `@Creates(<text>)` annotation of
+ // [node].
+ List<String> getCreatesAnnotations(ir.Member node) =>
+ _createsAnnotations[node] ?? const [];
+
+ // Returns a list of the text from the `@Returns(<text>)` annotation of
+ // [node].
+ List<String> getReturnsAnnotations(ir.Member node) =>
+ _returnsAnnotations[node] ?? const [];
+
+ // Returns the text from the `@JS(<text>)` annotation of [node], if any.
String getJsInteropLibraryName(ir.Library node) =>
_jsInteropLibraryNames[node];
+
+ // Returns the text from the `@JS(<text>)` annotation of [node], if any.
String getJsInteropClassName(ir.Class node) => _jsInteropClassNames[node];
+
+ // Returns `true` if [node] is annotated with `@anonymous`.
bool isAnonymousJsInteropClass(ir.Class node) =>
_anonymousJsInteropClasses.contains(node);
+
+ // Returns the text from the `@JS(<text>)` annotation of [node], if any.
String getJsInteropMemberName(ir.Member node) => _jsInteropMemberNames[node];
+
+ // Returns a list of the `@pragma('dart2js:<suffix>')` annotations on [node].
+ List<PragmaAnnotationData> getMemberPragmaAnnotationData(ir.Member node) =>
+ _memberPragmaAnnotations[node] ?? const [];
}
IrAnnotationData processAnnotations(ir.Component component) {
IrAnnotationData data = new IrAnnotationData();
void processMember(ir.Member member) {
+ List<PragmaAnnotationData> pragmaAnnotations;
+ List<String> createsAnnotations;
+ List<String> returnsAnnotations;
for (ir.Expression annotation in member.annotations) {
if (annotation is ir.ConstantExpression) {
ir.Constant constant = annotation.constant;
+
String jsName = _getJsInteropName(constant);
if (jsName != null) {
data._jsInteropMemberNames[member] = jsName;
}
+
+ bool isNativeMember = _isNativeMember(constant);
+ if (isNativeMember) {
+ data._nativeMembers.add(member);
+ }
+
+ String nativeName = _getNativeMemberName(constant);
+ if (nativeName != null) {
+ data._nativeMemberNames[member] = nativeName;
+ }
+
+ String creates = _getCreatesAnnotation(constant);
+ if (creates != null) {
+ if (createsAnnotations == null) {
+ data._createsAnnotations[member] = createsAnnotations = [];
+ }
+ createsAnnotations.add(creates);
+ }
+
+ String returns = _getReturnsAnnotation(constant);
+ if (returns != null) {
+ if (returnsAnnotations == null) {
+ data._returnsAnnotations[member] = returnsAnnotations = [];
+ }
+ returnsAnnotations.add(returns);
+ }
+
+ PragmaAnnotationData pragmaAnnotation = _getPragmaAnnotation(constant);
+ if (pragmaAnnotation != null) {
+ if (pragmaAnnotations == null) {
+ data._memberPragmaAnnotations[member] = pragmaAnnotations = [];
+ }
+ pragmaAnnotations.add(pragmaAnnotation);
+ }
}
}
}
@@ -83,6 +155,8 @@
String _getNativeClassName(ir.Constant constant) {
if (constant is ir.InstanceConstant) {
+ // TODO(johnniwinther): Add an IrCommonElements for these queries; i.e.
+ // `commonElements.isNativeAnnotationClass(constant.classNode)`.
if (constant.classNode.name == 'Native' &&
constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
if (constant.fieldValues.length == 1) {
@@ -100,31 +174,131 @@
return null;
}
+bool _isNativeMember(ir.Constant constant) {
+ return constant is ir.InstanceConstant &&
+ constant.classNode.name == 'ExternalName' &&
+ constant.classNode.enclosingLibrary.importUri == Uris.dart__internal;
+}
+
+String _getNativeMemberName(ir.Constant constant) {
+ if (constant is ir.InstanceConstant &&
+ constant.classNode.name == 'JSName' &&
+ constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
+ assert(constant.fieldValues.length == 1);
+ ir.Constant fieldValue = constant.fieldValues.values.single;
+ if (fieldValue is ir.StringConstant) {
+ return fieldValue.value;
+ }
+ }
+ return null;
+}
+
+String _getCreatesAnnotation(ir.Constant constant) {
+ if (constant is ir.InstanceConstant &&
+ constant.classNode.name == 'Creates' &&
+ constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
+ assert(constant.fieldValues.length == 1);
+ ir.Constant fieldValue = constant.fieldValues.values.single;
+ if (fieldValue is ir.StringConstant) {
+ return fieldValue.value;
+ }
+ }
+ return null;
+}
+
+String _getReturnsAnnotation(ir.Constant constant) {
+ if (constant is ir.InstanceConstant &&
+ constant.classNode.name == 'Returns' &&
+ constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
+ assert(constant.fieldValues.length == 1);
+ ir.Constant fieldValue = constant.fieldValues.values.single;
+ if (fieldValue is ir.StringConstant) {
+ return fieldValue.value;
+ }
+ }
+ return null;
+}
+
String _getJsInteropName(ir.Constant constant) {
- if (constant is ir.InstanceConstant) {
- if (constant.classNode.name == 'JS' &&
- constant.classNode.enclosingLibrary.importUri == Uris.package_js) {
- if (constant.fieldValues.length == 1) {
- ir.Constant fieldValue = constant.fieldValues.values.single;
- String name;
- if (fieldValue is ir.NullConstant) {
- name = '';
- } else if (fieldValue is ir.StringConstant) {
- name = fieldValue.value;
- }
- if (name != null) {
- return name;
- }
- }
+ if (constant is ir.InstanceConstant &&
+ constant.classNode.name == 'JS' &&
+ constant.classNode.enclosingLibrary.importUri == Uris.package_js) {
+ assert(constant.fieldValues.length == 1);
+ ir.Constant fieldValue = constant.fieldValues.values.single;
+ if (fieldValue is ir.NullConstant) {
+ return '';
+ } else if (fieldValue is ir.StringConstant) {
+ return fieldValue.value;
}
}
return null;
}
bool _isAnonymousJsInterop(ir.Constant constant) {
- if (constant is ir.InstanceConstant) {
- return constant.classNode.name == '_Anonymous' &&
- constant.classNode.enclosingLibrary.importUri == Uris.package_js;
+ return constant is ir.InstanceConstant &&
+ constant.classNode.name == '_Anonymous' &&
+ constant.classNode.enclosingLibrary.importUri == Uris.package_js;
+}
+
+class PragmaAnnotationData {
+ // TODO(johnniwinther): Support non 'dart2js:' pragma names if necessary.
+ final String suffix;
+
+ // TODO(johnniwinther): Support options objects when necessary.
+ final bool hasOptions;
+
+ const PragmaAnnotationData(this.suffix, {this.hasOptions: false});
+
+ String get name => 'dart2js:$suffix';
+
+ @override
+ String toString() => 'PragmaAnnotationData($name)';
+}
+
+PragmaAnnotationData _getPragmaAnnotation(ir.Constant constant) {
+ if (constant is! ir.InstanceConstant) return null;
+ ir.InstanceConstant value = constant;
+ ir.Class cls = value.classNode;
+ Uri uri = cls.enclosingLibrary.importUri;
+ if (uri == Uris.package_meta_dart2js) {
+ if (cls.name == '_NoInline') {
+ return const PragmaAnnotationData('noInline');
+ } else if (cls.name == '_TryInline') {
+ return const PragmaAnnotationData('tryInline');
+ }
+ } else if (uri == Uris.dart_core && cls.name == 'pragma') {
+ ir.Constant nameValue;
+ ir.Constant optionsValue;
+ value.fieldValues.forEach((ir.Reference reference, ir.Constant fieldValue) {
+ ir.Field field = reference.asField;
+ if (field.name.name == 'name') {
+ nameValue = fieldValue;
+ } else if (field.name.name == 'options') {
+ optionsValue = fieldValue;
+ }
+ });
+ if (nameValue is! ir.StringConstant) return null;
+ ir.StringConstant stringValue = nameValue;
+ String name = stringValue.value;
+ String prefix = 'dart2js:';
+ if (!name.startsWith(prefix)) return null;
+ String suffix = name.substring(prefix.length);
+ return new PragmaAnnotationData(suffix,
+ hasOptions: optionsValue is! ir.NullConstant);
}
- return false;
+ return null;
+}
+
+List<PragmaAnnotationData> computePragmaAnnotationDataFromIr(ir.Member member) {
+ List<PragmaAnnotationData> annotations = [];
+ for (ir.Expression metadata in member.annotations) {
+ if (metadata is! ir.ConstantExpression) continue;
+ ir.ConstantExpression constantExpression = metadata;
+ ir.Constant constant = constantExpression.constant;
+ PragmaAnnotationData data = _getPragmaAnnotation(constant);
+ if (data != null) {
+ annotations.add(data);
+ }
+ }
+ return annotations;
}
diff --git a/pkg/compiler/lib/src/ir/cached_static_type.dart b/pkg/compiler/lib/src/ir/cached_static_type.dart
index 5daea39..6067b5e 100644
--- a/pkg/compiler/lib/src/ir/cached_static_type.dart
+++ b/pkg/compiler/lib/src/ir/cached_static_type.dart
@@ -14,6 +14,7 @@
/// and a precomputed cache for complex expression type.
class CachedStaticType extends StaticTypeBase implements StaticTypeProvider {
final Map<ir.Expression, ir.DartType> _cache;
+ @override
final ThisInterfaceType thisType;
CachedStaticType(
diff --git a/pkg/compiler/lib/src/ir/closure.dart b/pkg/compiler/lib/src/ir/closure.dart
index 2bc573f..d237f3f 100644
--- a/pkg/compiler/lib/src/ir/closure.dart
+++ b/pkg/compiler/lib/src/ir/closure.dart
@@ -17,6 +17,7 @@
Map<ir.TreeNode, KernelScopeInfo> closuresToGenerate =
<ir.TreeNode, KernelScopeInfo>{};
+ @override
String toString() {
return '$scopeInfo\n$capturedScopesMap\n$closuresToGenerate';
}
@@ -76,6 +77,7 @@
this.thisUsedAsFreeVariableIfNeedsRti,
this.hasThisLocal);
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('KernelScopeInfo(this=$hasThisLocal,');
@@ -319,6 +321,7 @@
static const VariableUse fieldType =
const VariableUse._simple(VariableUseKind.fieldType);
+ @override
int get hashCode =>
kind.hashCode * 11 +
member.hashCode * 13 +
@@ -326,6 +329,7 @@
invocation.hashCode * 19 +
instantiation.hashCode * 23;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! VariableUse) return false;
@@ -336,6 +340,7 @@
instantiation == other.instantiation;
}
+ @override
String toString() => 'VariableUse(kind=$kind,member=$member,'
'localFunction=$localFunction,invocation=$invocation,'
'instantiation=$instantiation)';
@@ -398,21 +403,26 @@
TypeVariableTypeWithContext.internal(
this.type, this.context, this.kind, this.typeDeclaration);
+ @override
accept(ir.Visitor v) {
throw new UnsupportedError('TypeVariableTypeWithContext.accept');
}
+ @override
visitChildren(ir.Visitor v) {
throw new UnsupportedError('TypeVariableTypeWithContext.visitChildren');
}
+ @override
int get hashCode => type.hashCode;
+ @override
bool operator ==(other) {
if (other is! TypeVariableTypeWithContext) return false;
return type == other.type && context == other.context;
}
+ @override
String toString() =>
'TypeVariableTypeWithContext(type=$type,context=$context,'
'kind=$kind,typeDeclaration=$typeDeclaration)';
diff --git a/pkg/compiler/lib/src/ir/debug.dart b/pkg/compiler/lib/src/ir/debug.dart
index a61a77a..27fad8e 100644
--- a/pkg/compiler/lib/src/ir/debug.dart
+++ b/pkg/compiler/lib/src/ir/debug.dart
@@ -12,6 +12,7 @@
import '../util/util.dart' show Indentation, Tagging;
class DebugPrinter extends Visitor with Indentation, Tagging<Node> {
+ @override
StringBuffer sb = new StringBuffer();
void visitNodeWithChildren(Node node, String type, [Map params]) {
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index dd5802a..c548eae 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -188,6 +188,7 @@
abstract class ImpactBuilderBase extends StaticTypeVisitor
implements ImpactRegistry {
+ @override
final VariableScopeModel variableScopeModel;
ImpactBuilderBase(ir.TypeEnvironment typeEnvironment,
@@ -406,6 +407,7 @@
registerLoadLibrary();
}
+ @override
void handleRedirectingInitializer(
ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {
registerRedirectingInitializer(
@@ -643,6 +645,7 @@
return super.visitSwitchStatement(node);
}
+ @override
void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
ir.DartType receiverType, ir.DartType argumentType) {
registerRuntimeTypeUse(node, kind, receiverType, argumentType);
@@ -656,16 +659,36 @@
/// Visitor that builds an [ImpactData] object for the world impact.
class ImpactBuilder extends ImpactBuilderBase with ImpactRegistryMixin {
+ @override
final bool useAsserts;
+ @override
final inferEffectivelyFinalVariableTypes;
ImpactBuilder(ir.TypeEnvironment typeEnvironment,
ir.ClassHierarchy classHierarchy, VariableScopeModel variableScopeModel,
{this.useAsserts: false, this.inferEffectivelyFinalVariableTypes: true})
: super(typeEnvironment, classHierarchy, variableScopeModel);
+
+ ImpactBuilderData computeImpact(ir.Member node) {
+ if (retainDataForTesting) {
+ typeMapsForTesting = {};
+ }
+ node.accept(this);
+ return new ImpactBuilderData(
+ impactData, typeMapsForTesting, cachedStaticTypes);
+ }
}
/// Return the named arguments names as a list of strings.
List<String> _getNamedArguments(ir.Arguments arguments) =>
arguments.named.map((n) => n.name).toList();
+
+class ImpactBuilderData {
+ final ImpactData impactData;
+ final Map<ir.Expression, TypeMap> typeMapsForTesting;
+ final Map<ir.Expression, ir.DartType> cachedStaticTypes;
+
+ ImpactBuilderData(
+ this.impactData, this.typeMapsForTesting, this.cachedStaticTypes);
+}
diff --git a/pkg/compiler/lib/src/ir/modular.dart b/pkg/compiler/lib/src/ir/modular.dart
new file mode 100644
index 0000000..9d7ea73
--- /dev/null
+++ b/pkg/compiler/lib/src/ir/modular.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, 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:kernel/ast.dart' as ir;
+import 'package:kernel/class_hierarchy.dart' as ir;
+import 'package:kernel/core_types.dart' as ir;
+import 'package:kernel/type_algebra.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
+
+import '../js_backend/annotations.dart';
+import '../util/enumset.dart';
+import 'annotations.dart';
+import 'impact.dart';
+import 'scope.dart';
+
+class ModularMemberData {
+ final ScopeModel scopeModel;
+ final ImpactBuilderData impactBuilderData;
+
+ ModularMemberData(this.scopeModel, this.impactBuilderData);
+}
+
+abstract class ModularStrategy {
+ List<PragmaAnnotationData> getPragmaAnnotationData(ir.Member node);
+
+ // TODO(johnniwinther): Avoid the need for passing [pragmaAnnotations].
+ ModularMemberData getModularMemberData(
+ ir.Member node, EnumSet<PragmaAnnotation> pragmaAnnotations);
+}
diff --git a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
index cde8217..d7e1d75 100644
--- a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
+++ b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
@@ -63,6 +63,7 @@
throw new UnsupportedError("Unexpected RuntimeTypeUseKind $kind.");
}
+ @override
String toString() {
return "RuntimeTypeUseData(kind=$kind,"
"receiverGet=$leftRuntimeTypeExpression,receiver=$receiver,"
diff --git a/pkg/compiler/lib/src/ir/scope.dart b/pkg/compiler/lib/src/ir/scope.dart
index a323f6f..1d2a300 100644
--- a/pkg/compiler/lib/src/ir/scope.dart
+++ b/pkg/compiler/lib/src/ir/scope.dart
@@ -11,45 +11,17 @@
final VariableScopeModel variableScopeModel;
final InitializerComplexity initializerComplexity;
- ScopeModel(this.closureScopeModel, this.variableScopeModel,
- this.initializerComplexity);
+ const ScopeModel(
+ {this.closureScopeModel,
+ this.variableScopeModel,
+ this.initializerComplexity})
+ : assert(initializerComplexity != null);
/// Inspect members and mark if those members capture any state that needs to
/// be marked as free variables.
- static ScopeModel computeScopeModel(ir.Member node) {
- if (node.isAbstract && !node.isExternal) return null;
- if (node is ir.Field && !node.isInstanceMember) {
- ir.Field field = node;
- // Skip top-level/static fields without an initializer.
- if (field.initializer == null) return null;
- }
-
- bool hasThisLocal = false;
- if (node is ir.Constructor) {
- hasThisLocal = true;
- } else if (node is ir.Procedure && node.kind == ir.ProcedureKind.Factory) {
- hasThisLocal = false;
- } else if (node.isInstanceMember) {
- hasThisLocal = true;
- }
- ClosureScopeModel closureScopeModel = new ClosureScopeModel();
- ScopeModelBuilder builder =
- new ScopeModelBuilder(closureScopeModel, hasThisLocal: hasThisLocal);
- InitializerComplexity initializerComplexity =
- const InitializerComplexity.lazy();
- if (node is ir.Field) {
- if (node is ir.Field && node.initializer != null) {
- initializerComplexity = node.accept(builder);
- } else {
- assert(node.isInstanceMember);
- closureScopeModel.scopeInfo = new KernelScopeInfo(true);
- }
- } else {
- assert(node is ir.Procedure || node is ir.Constructor);
- node.accept(builder);
- }
- return new ScopeModel(
- closureScopeModel, builder.variableScopeModel, initializerComplexity);
+ factory ScopeModel.from(ir.Member node) {
+ ScopeModelBuilder builder = new ScopeModelBuilder();
+ return builder.computeModel(node);
}
}
@@ -100,6 +72,7 @@
class VariableScopeImpl implements VariableScope {
List<VariableScope> _subScopes;
Set<ir.VariableDeclaration> _assignedVariables;
+ @override
bool hasContinueSwitch = false;
void addSubScope(VariableScope scope) {
@@ -112,6 +85,7 @@
_assignedVariables.add(variable);
}
+ @override
Iterable<ir.VariableDeclaration> get assignedVariables sync* {
if (_assignedVariables != null) {
yield* _assignedVariables;
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 07ae385..7fcac8a 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -13,7 +13,7 @@
/// variable is being used at any point in the code.
class ScopeModelBuilder extends ir.Visitor<InitializerComplexity>
with VariableCollectorMixin {
- ClosureScopeModel _model;
+ final ClosureScopeModel _model = new ClosureScopeModel();
/// A map of each visited call node with the associated information about what
/// variables are captured/used. Each ir.Node key corresponds to a scope that
@@ -61,7 +61,7 @@
/// The current scope we are in.
KernelScopeInfo _currentScopeInfo;
- final bool _hasThisLocal;
+ bool _hasThisLocal;
/// Keeps track of the number of boxes that we've created so that they each
/// have unique names.
@@ -74,8 +74,40 @@
/// type variable usage, such as type argument in method invocations.
VariableUse _currentTypeUsage;
- ScopeModelBuilder(this._model, {bool hasThisLocal})
- : this._hasThisLocal = hasThisLocal;
+ ScopeModel computeModel(ir.Member node) {
+ if (node.isAbstract && !node.isExternal) {
+ return const ScopeModel(
+ initializerComplexity: const InitializerComplexity.lazy());
+ }
+
+ if (node is ir.Constructor) {
+ _hasThisLocal = true;
+ } else if (node is ir.Procedure && node.kind == ir.ProcedureKind.Factory) {
+ _hasThisLocal = false;
+ } else if (node.isInstanceMember) {
+ _hasThisLocal = true;
+ } else {
+ _hasThisLocal = false;
+ }
+
+ InitializerComplexity initializerComplexity =
+ const InitializerComplexity.lazy();
+ if (node is ir.Field) {
+ if (node.initializer != null) {
+ initializerComplexity = node.accept(this);
+ } else {
+ initializerComplexity = const InitializerComplexity.constant();
+ _model.scopeInfo = new KernelScopeInfo(_hasThisLocal);
+ }
+ } else {
+ assert(node is ir.Procedure || node is ir.Constructor);
+ node.accept(this);
+ }
+ return new ScopeModel(
+ closureScopeModel: _model,
+ variableScopeModel: variableScopeModel,
+ initializerComplexity: initializerComplexity);
+ }
@override
InitializerComplexity defaultNode(ir.Node node) =>
@@ -338,6 +370,7 @@
return const InitializerComplexity.lazy();
}
+ @override
InitializerComplexity visitWhileStatement(ir.WhileStatement node) {
enterNewScope(node, () {
visitInVariableScope(node, () {
@@ -348,6 +381,7 @@
return const InitializerComplexity.lazy();
}
+ @override
InitializerComplexity visitDoStatement(ir.DoStatement node) {
enterNewScope(node, () {
visitInVariableScope(node, () {
@@ -412,6 +446,7 @@
return const InitializerComplexity.lazy();
}
+ @override
InitializerComplexity visitSuperMethodInvocation(
ir.SuperMethodInvocation node) {
if (_hasThisLocal) {
@@ -426,6 +461,7 @@
return const InitializerComplexity.lazy();
}
+ @override
InitializerComplexity visitSuperPropertySet(ir.SuperPropertySet node) {
if (_hasThisLocal) {
_registerNeedsThis(VariableUse.explicit);
@@ -434,6 +470,7 @@
return const InitializerComplexity.lazy();
}
+ @override
InitializerComplexity visitSuperPropertyGet(ir.SuperPropertyGet node) {
if (_hasThisLocal) {
_registerNeedsThis(VariableUse.explicit);
@@ -683,30 +720,40 @@
@override
InitializerComplexity visitListLiteral(ir.ListLiteral node) {
- visitInContext(node.typeArgument, VariableUse.listLiteral);
- visitNodes(node.expressions);
- return node.isConst
- ? const InitializerComplexity.constant()
- : const InitializerComplexity.lazy();
+ InitializerComplexity complexity =
+ visitInContext(node.typeArgument, VariableUse.listLiteral);
+ complexity = complexity.combine(visitNodes(node.expressions));
+ if (node.isConst) {
+ return const InitializerComplexity.constant();
+ } else {
+ return complexity.makeEager();
+ }
}
@override
InitializerComplexity visitSetLiteral(ir.SetLiteral node) {
- visitInContext(node.typeArgument, VariableUse.setLiteral);
- visitNodes(node.expressions);
- return node.isConst
- ? const InitializerComplexity.constant()
- : const InitializerComplexity.lazy();
+ InitializerComplexity complexity =
+ visitInContext(node.typeArgument, VariableUse.setLiteral);
+ complexity = complexity.combine(visitNodes(node.expressions));
+ if (node.isConst) {
+ return const InitializerComplexity.constant();
+ } else {
+ return complexity.makeEager();
+ }
}
@override
InitializerComplexity visitMapLiteral(ir.MapLiteral node) {
- visitInContext(node.keyType, VariableUse.mapLiteral);
- visitInContext(node.valueType, VariableUse.mapLiteral);
- visitNodes(node.entries);
- return node.isConst
- ? const InitializerComplexity.constant()
- : const InitializerComplexity.lazy();
+ InitializerComplexity complexity =
+ visitInContext(node.keyType, VariableUse.mapLiteral);
+ complexity = complexity
+ .combine(visitInContext(node.valueType, VariableUse.mapLiteral));
+ complexity = complexity.combine(visitNodes(node.entries));
+ if (node.isConst) {
+ return const InitializerComplexity.constant();
+ } else {
+ return complexity.makeEager();
+ }
}
@override
@@ -747,9 +794,16 @@
@override
InitializerComplexity visitStaticGet(ir.StaticGet node) {
- return node.target.isConst
- ? const InitializerComplexity.constant()
- : const InitializerComplexity.lazy();
+ ir.Member target = node.target;
+ if (target is ir.Field) {
+ return target.isConst
+ ? const InitializerComplexity.constant()
+ : new InitializerComplexity.eager(fields: <ir.Field>{target});
+ } else if (target is ir.Procedure &&
+ target.kind == ir.ProcedureKind.Method) {
+ return const InitializerComplexity.constant();
+ }
+ return const InitializerComplexity.lazy();
}
@override
@@ -1065,43 +1119,90 @@
class InitializerComplexity {
final ComplexityLevel level;
+ final Set<ir.Field> fields;
// TODO(johnniwinther): This should hold the constant literal from CFE when
// provided.
- const InitializerComplexity.constant() : level = ComplexityLevel.constant;
+ const InitializerComplexity.constant()
+ : level = ComplexityLevel.constant,
+ fields = null;
// TODO(johnniwinther): Use this to collect data on the size of the
// initializer.
- const InitializerComplexity.eager()
+ InitializerComplexity.eager({this.fields})
: level = ComplexityLevel.potentiallyEager;
- const InitializerComplexity.lazy() : level = ComplexityLevel.definitelyLazy;
+ const InitializerComplexity.lazy()
+ : level = ComplexityLevel.definitelyLazy,
+ fields = null;
InitializerComplexity combine(InitializerComplexity other) {
- if (level == other.level) {
- // TODO(johnniwinther): Special case 'eager' when it contains data.
+ if (identical(this, other)) {
return this;
- } else if (level == ComplexityLevel.definitelyLazy ||
- other.level == ComplexityLevel.definitelyLazy) {
+ } else if (isLazy || other.isLazy) {
return const InitializerComplexity.lazy();
- } else if (level == ComplexityLevel.potentiallyEager) {
+ } else if (isEager || other.isEager) {
+ if (fields != null && other.fields != null) {
+ fields.addAll(other.fields);
+ return this;
+ } else if (fields != null) {
+ return this;
+ } else {
+ return other;
+ }
+ } else if (isConstant && other.isConstant) {
+ // TODO(johnniwinther): This is case doesn't work if InitializerComplexity
+ // objects of constant complexity hold the constant literal.
+ return this;
+ } else if (isEager) {
+ assert(other.isConstant);
return this;
} else {
- assert(other.level == ComplexityLevel.potentiallyEager);
+ assert(isConstant);
+ assert(other.isEager);
return other;
}
}
+ InitializerComplexity makeEager() {
+ if (isLazy || isEager) {
+ return this;
+ } else {
+ return new InitializerComplexity.eager();
+ }
+ }
+
+ bool get isConstant => level == ComplexityLevel.constant;
+
+ bool get isEager => level == ComplexityLevel.potentiallyEager;
+
+ bool get isLazy => level == ComplexityLevel.definitelyLazy;
+
/// Returns a short textual representation used for testing.
String get shortText {
+ StringBuffer sb = new StringBuffer();
switch (level) {
case ComplexityLevel.constant:
- return 'constant';
+ sb.write('constant');
+ break;
case ComplexityLevel.potentiallyEager:
- return 'eager';
+ sb.write('eager');
+ if (fields != null) {
+ sb.write('&fields=[');
+ List<String> names = fields.map((f) => f.name.name).toList()..sort();
+ sb.write(names.join(','));
+ sb.write(']');
+ }
+ break;
case ComplexityLevel.definitelyLazy:
- return 'lazy';
+ sb.write('lazy');
+ break;
+ default:
+ throw new UnsupportedError("Unexpected complexity level $level");
}
- throw new UnsupportedError("Unexpected complexity level $level");
+ return sb.toString();
}
+
+ @override
+ String toString() => 'InitializerComplexity($shortText)';
}
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index b8d423c..1300bd8 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -58,6 +58,7 @@
VariableScopeModel get variableScopeModel;
+ @override
ThisInterfaceType get thisType {
assert(_thisType != null);
return _thisType;
@@ -249,11 +250,35 @@
ir.DartType visitPropertySet(ir.PropertySet node) {
ir.DartType receiverType = visitNode(node.receiver);
ir.DartType valueType = super.visitPropertySet(node);
- if (node.interfaceTarget == null && receiverType is ir.InterfaceType) {
- node.interfaceTarget = hierarchy
+ ir.Member interfaceTarget = node.interfaceTarget;
+ if (interfaceTarget == null && receiverType is ir.InterfaceType) {
+ interfaceTarget = hierarchy
.getInterfaceMember(receiverType.classNode, node.name, setter: true);
+ if (interfaceTarget != null) {
+ ir.Class superclass = interfaceTarget.enclosingClass;
+ ir.Substitution receiverSubstitution =
+ ir.Substitution.fromInterfaceType(
+ getTypeAsInstanceOf(receiverType, superclass));
+ ir.DartType setterType =
+ receiverSubstitution.substituteType(interfaceTarget.setterType);
+ if (!typeEnvironment.isSubtypeOf(valueType, setterType)) {
+ // We need to insert an implicit cast to preserve the invariant that
+ // a property set with a known interface target is also statically
+ // checked.
+ ir.AsExpression implicitCast =
+ new ir.AsExpression(node.value, setterType)
+ ..isTypeError = true
+ ..parent = node;
+ node.value = implicitCast;
+ // Visit the newly created as expression; the original value has
+ // already been visited.
+ handleAsExpression(implicitCast, valueType);
+ valueType = setterType;
+ }
+ node.interfaceTarget = interfaceTarget;
+ }
}
- receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
+ receiverType = _narrowInstanceReceiver(interfaceTarget, receiverType);
handlePropertySet(node, receiverType, valueType);
return valueType;
}
@@ -415,6 +440,106 @@
return false;
}
+ /// Update the interface target on [node].
+ ///
+ /// This inserts any implicit cast of the arguments necessary to uphold the
+ /// invariant that a method invocation with an interface target handles
+ /// the static types at the call site.
+ void _updateMethodInvocationTarget(
+ ir.MethodInvocation node,
+ ArgumentTypes argumentTypes,
+ ir.DartType functionType,
+ ir.Member interfaceTarget) {
+ // TODO(johnniwinther): Handle incremental target improvement.
+ if (node.interfaceTarget != null) return;
+ node.interfaceTarget = interfaceTarget;
+ if (functionType is! ir.FunctionType) return;
+ ir.FunctionType parameterTypes = functionType;
+ Map<int, ir.DartType> neededPositionalChecks = {};
+ for (int i = 0; i < node.arguments.positional.length; i++) {
+ ir.DartType argumentType = argumentTypes.positional[i];
+ ir.DartType parameterType = parameterTypes.positionalParameters[i];
+ if (!typeEnvironment.isSubtypeOf(argumentType, parameterType)) {
+ neededPositionalChecks[i] = parameterType;
+ }
+ }
+ Map<int, ir.DartType> neededNamedChecks = {};
+ for (int argumentIndex = 0;
+ argumentIndex < node.arguments.named.length;
+ argumentIndex++) {
+ ir.NamedExpression namedArgument = node.arguments.named[argumentIndex];
+ ir.DartType argumentType = argumentTypes.named[argumentIndex];
+ ir.DartType parameterType = parameterTypes.namedParameters
+ .singleWhere((namedType) => namedType.name == namedArgument.name)
+ .type;
+ if (!typeEnvironment.isSubtypeOf(argumentType, parameterType)) {
+ neededNamedChecks[argumentIndex] = parameterType;
+ }
+ }
+ if (neededPositionalChecks.isEmpty && neededNamedChecks.isEmpty) {
+ // No implicit casts needed
+ return;
+ }
+
+ List<ir.VariableDeclaration> letVariables = [];
+
+ // Arguments need to be hoisted to an enclosing let expression in order
+ // to ensure that the arguments are evaluated before any implicit cast.
+
+ ir.Expression updateArgument(ir.Expression expression, ir.TreeNode parent,
+ ir.DartType argumentType, ir.DartType checkedParameterType) {
+ ir.VariableDeclaration variable =
+ new ir.VariableDeclaration.forValue(expression, type: argumentType);
+ // Visit the newly created variable declaration.
+ handleVariableDeclaration(variable);
+ letVariables.add(variable);
+ ir.VariableGet get = new ir.VariableGet(variable)..parent = parent;
+ // Visit the newly created variable get.
+ handleVariableGet(get, argumentType);
+ cachedStaticTypes[get] = argumentType;
+
+ if (checkedParameterType == null) {
+ return get;
+ }
+ // We need to insert an implicit cast to preserve the invariant that
+ // a method invocation with a known interface target is also
+ // statically checked.
+ ir.AsExpression implicitCast =
+ new ir.AsExpression(get, checkedParameterType)
+ ..isTypeError = true
+ ..parent = parent;
+ // Visit the newly created as expression; the original value has
+ // already been visited.
+ handleAsExpression(implicitCast, argumentType);
+ return implicitCast;
+ }
+
+ for (int index = 0; index < node.arguments.positional.length; index++) {
+ ir.DartType argumentType = argumentTypes.positional[index];
+ node.arguments.positional[index] = updateArgument(
+ node.arguments.positional[index],
+ node.arguments,
+ argumentType,
+ neededPositionalChecks[index]);
+ }
+ for (int argumentIndex = 0;
+ argumentIndex < node.arguments.named.length;
+ argumentIndex++) {
+ ir.NamedExpression namedArgument = node.arguments.named[argumentIndex];
+ ir.DartType argumentType = argumentTypes.named[argumentIndex];
+ namedArgument.value = updateArgument(namedArgument.value, namedArgument,
+ argumentType, neededNamedChecks[argumentIndex]);
+ }
+
+ ir.Expression dummy = new ir.NullLiteral();
+ node.replaceWith(dummy);
+ ir.Expression body = node;
+ for (ir.VariableDeclaration variable in letVariables.reversed) {
+ body = new ir.Let(variable, body);
+ }
+ dummy.replaceWith(body);
+ }
+
/// Computes the result type of the method invocation [node] on a receiver of
/// type [receiverType].
///
@@ -436,20 +561,17 @@
ir.Member member =
hierarchy.getInterfaceMember(receiverType.classNode, node.name);
if (_isApplicable(node.arguments, member)) {
- interfaceTarget = node.interfaceTarget = member;
+ interfaceTarget = member;
}
}
if (interfaceTarget != null) {
- if (isSpecialCasedBinaryOperator(interfaceTarget)) {
- ir.DartType argumentType = argumentTypes.positional[0];
- return typeEnvironment.getTypeOfOverloadedArithmetic(
- receiverType, argumentType);
- }
ir.Class superclass = interfaceTarget.enclosingClass;
- receiverType = getTypeAsInstanceOf(receiverType, superclass);
- ir.DartType getterType = ir.Substitution.fromInterfaceType(receiverType)
- .substituteType(interfaceTarget.getterType);
+ ir.Substitution receiverSubstitution = ir.Substitution.fromInterfaceType(
+ getTypeAsInstanceOf(receiverType, superclass));
+ ir.DartType getterType =
+ receiverSubstitution.substituteType(interfaceTarget.getterType);
if (getterType is ir.FunctionType) {
+ ir.FunctionType functionType = getterType;
List<ir.DartType> typeArguments = node.arguments.types;
if (interfaceTarget is ir.Procedure &&
interfaceTarget.function.typeParameters.isNotEmpty &&
@@ -457,15 +579,22 @@
// If this was a dynamic call the invocation does not have the
// inferred default type arguments so we need to create them here
// to perform a valid substitution.
- ir.Substitution substitution =
- ir.Substitution.fromInterfaceType(receiverType);
typeArguments = interfaceTarget.function.typeParameters
- .map((t) => substitution.substituteType(t.defaultType))
+ .map((t) => receiverSubstitution.substituteType(t.defaultType))
.toList();
}
- return ir.Substitution.fromPairs(
- getterType.typeParameters, typeArguments)
- .substituteType(getterType.returnType);
+ getterType = ir.Substitution.fromPairs(
+ functionType.typeParameters, typeArguments)
+ .substituteType(functionType.withoutTypeParameters);
+ }
+ _updateMethodInvocationTarget(
+ node, argumentTypes, getterType, interfaceTarget);
+ if (isSpecialCasedBinaryOperator(interfaceTarget)) {
+ ir.DartType argumentType = argumentTypes.positional[0];
+ return typeEnvironment.getTypeOfOverloadedArithmetic(
+ receiverType, argumentType);
+ } else if (getterType is ir.FunctionType) {
+ return getterType.returnType;
} else {
return const ir.DynamicType();
}
@@ -823,6 +952,7 @@
return type;
}
+ @override
ir.DartType visitExpressionStatement(ir.ExpressionStatement node) {
visitNode(node.expression);
return null;
@@ -1299,6 +1429,7 @@
return candidate;
}
+ @override
int get hashCode {
if (_hashCode == null) {
_hashCode = Hashing.setHash(falseTypes,
@@ -1307,6 +1438,7 @@
return _hashCode;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
return other is TypeHolder &&
@@ -1332,6 +1464,7 @@
sb.write('}');
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('TypeHolder(');
@@ -1569,6 +1702,7 @@
sb.write(']');
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('TargetInfo(');
@@ -1713,6 +1847,7 @@
return sb.toString();
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('TypeMap(');
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index 2ed1a24..272689a 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -14,6 +14,7 @@
class DoesNotCompleteType extends ir.BottomType {
const DoesNotCompleteType();
+ @override
String toString() => 'DoesNotCompleteType()';
}
@@ -27,6 +28,7 @@
? new ThisInterfaceType(type.classNode, type.typeArguments)
: null;
+ @override
String toString() => 'this:${super.toString()}';
}
@@ -40,6 +42,7 @@
? new ExactInterfaceType(type.classNode, type.typeArguments)
: null;
+ @override
String toString() => 'exact:${super.toString()}';
}
@@ -79,6 +82,7 @@
}
}
+ @override
ir.DartType defaultExpression(ir.Expression node) {
throw fail('Unhandled node $node (${node.runtimeType})');
}
diff --git a/pkg/compiler/lib/src/ir/types.dart b/pkg/compiler/lib/src/ir/types.dart
index 6d0f40d..ec95dff 100644
--- a/pkg/compiler/lib/src/ir/types.dart
+++ b/pkg/compiler/lib/src/ir/types.dart
@@ -99,18 +99,22 @@
KernelOrderedTypeSetBuilder(this.elementMap, ClassEntity cls) : super(cls);
+ @override
InterfaceType getThisType(ClassEntity cls) {
return elementMap.getThisType(cls);
}
+ @override
InterfaceType substByContext(InterfaceType type, InterfaceType context) {
return elementMap.substByContext(type, context);
}
+ @override
int getHierarchyDepth(ClassEntity cls) {
return elementMap.getHierarchyDepth(cls);
}
+ @override
OrderedTypeSet getOrderedTypeSet(ClassEntity cls) {
return elementMap.getOrderedTypeSet(cls);
}
@@ -141,6 +145,7 @@
class KernelSubtypeVisitor extends SubtypeVisitor<DartType>
with AbstractTypeRelationMixin {
+ @override
final IrToElementMap elementMap;
KernelSubtypeVisitor(this.elementMap);
@@ -148,6 +153,7 @@
class _KernelPotentialSubtypeVisitor extends PotentialSubtypeVisitor<DartType>
with AbstractTypeRelationMixin {
+ @override
final IrToElementMap elementMap;
_KernelPotentialSubtypeVisitor(this.elementMap);
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index 0a749db..2ce8d7d 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -91,6 +91,7 @@
ir.Let get let => syntheticVariable.parent;
+ @override
String toString() => let.toString();
}
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index fabd55d..0b7e8e4 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -63,6 +63,7 @@
return constant;
}
+ @override
ConstantExpression defaultExpression(ir.Expression node) {
if (requireConstant) {
failNode ??= node;
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index 523cd66..c62d6f3 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -134,6 +134,7 @@
final bool _protectForEval;
LiteralString _cachedLiteral;
+ @override
Iterable<Node> get containedNodes => [tree];
/// A [js.Literal] that represents the string result of unparsing [ast].
diff --git a/pkg/compiler/lib/src/js/js_debug.dart b/pkg/compiler/lib/src/js/js_debug.dart
index d191491..9eaca9f 100644
--- a/pkg/compiler/lib/src/js/js_debug.dart
+++ b/pkg/compiler/lib/src/js/js_debug.dart
@@ -24,6 +24,7 @@
/// Visitor that creates an XML-like representation of the structure of a
/// JavaScript [Node].
class DebugPrinter extends BaseVisitor with Indentation, Tagging<Node> {
+ @override
StringBuffer sb = new StringBuffer();
void visitNodeWithChildren(Node node, String type, [Map params]) {
diff --git a/pkg/compiler/lib/src/js/js_source_mapping.dart b/pkg/compiler/lib/src/js/js_source_mapping.dart
index 13735ca..ff8a155 100644
--- a/pkg/compiler/lib/src/js/js_source_mapping.dart
+++ b/pkg/compiler/lib/src/js/js_source_mapping.dart
@@ -63,6 +63,7 @@
SourceMapperProviderImpl(this.provider);
+ @override
SourceMapper createSourceMapper(String name) {
return new SourceLocationsMapper(provider.createSourceLocations(name));
}
diff --git a/pkg/compiler/lib/src/js/placeholder_safety.dart b/pkg/compiler/lib/src/js/placeholder_safety.dart
index 48b71cc..72d1e8d 100644
--- a/pkg/compiler/lib/src/js/placeholder_safety.dart
+++ b/pkg/compiler/lib/src/js/placeholder_safety.dart
@@ -60,16 +60,19 @@
return node.accept(this);
}
+ @override
int visitNode(js.Node node) {
safe = false;
super.visitNode(node);
return UNKNOWN_VALUE;
}
+ @override
int visitLiteralNull(js.LiteralNull node) {
return UNKNOWN_VALUE;
}
+ @override
int visitLiteral(js.Literal node) {
return NONNULL_VALUE;
}
@@ -81,26 +84,32 @@
return position;
}
+ @override
int visitInterpolatedExpression(js.InterpolatedExpression node) {
return handleInterpolatedNode(node);
}
+ @override
int visitInterpolatedLiteral(js.InterpolatedLiteral node) {
return handleInterpolatedNode(node);
}
+ @override
int visitInterpolatedSelector(js.InterpolatedSelector node) {
return handleInterpolatedNode(node);
}
+ @override
int visitInterpolatedStatement(js.InterpolatedStatement node) {
return handleInterpolatedNode(node);
}
+ @override
int visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
return handleInterpolatedNode(node);
}
+ @override
int visitObjectInitializer(js.ObjectInitializer node) {
for (js.Property property in node.properties) {
visit(property);
@@ -108,21 +117,25 @@
return NONNULL_VALUE;
}
+ @override
int visitProperty(js.Property node) {
visit(node.name);
visit(node.value);
return UNKNOWN_VALUE;
}
+ @override
int visitArrayInitializer(js.ArrayInitializer node) {
node.elements.forEach(visit);
return NONNULL_VALUE;
}
+ @override
int visitArrayHole(js.ArrayHole node) {
return UNKNOWN_VALUE;
}
+ @override
int visitAccess(js.PropertyAccess node) {
int first = visit(node.receiver);
visit(node.selector);
@@ -131,6 +144,7 @@
return UNKNOWN_VALUE;
}
+ @override
int visitAssignment(js.Assignment node) {
js.Expression left = node.leftHandSide;
js.Expression right = node.value;
@@ -172,6 +186,7 @@
return leftToRight();
}
+ @override
int visitCall(js.Call node) {
// TODO(sra): Recognize JavaScript built-ins like
// 'Object.prototype.hasOwnProperty.call'.
@@ -180,12 +195,14 @@
return unsafe(UNKNOWN_VALUE);
}
+ @override
int visitNew(js.New node) {
visit(node.target);
node.arguments.forEach(visit);
return unsafe(NONNULL_VALUE);
}
+ @override
int visitBinary(js.Binary node) {
switch (node.op) {
// We make the non-conservative assumption that these operations are not
@@ -238,6 +255,7 @@
}
}
+ @override
int visitConditional(js.Conditional node) {
visit(node.condition);
// TODO(sra): Might be safe, e.g. "# ? 1 : 2".
@@ -247,11 +265,13 @@
return UNKNOWN_VALUE;
}
+ @override
int visitThrow(js.Throw node) {
visit(node.expression);
return unsafe(UNKNOWN_VALUE);
}
+ @override
int visitPrefix(js.Prefix node) {
if (node.op == 'typeof') {
// "typeof a" first evaluates to a Reference. If the Reference is to a
@@ -287,12 +307,14 @@
}
}
+ @override
int visitPostfix(js.Postfix node) {
assert(node.op == '--' || node.op == '++');
visit(node.argument);
return NONNULL_VALUE; // Always a number, even for "(a=null, a++)".
}
+ @override
int visitVariableUse(js.VariableUse node) {
// We could get a ReferenceError unless the variable is in scope. For JS
// fragments, the only use of VariableUse outside a `function(){...}` should
@@ -315,6 +337,7 @@
}
}
+ @override
int visitFun(js.Fun node) {
bool oldSafe = safe;
int oldNextPosition = nextPosition;
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 68fffe8..b3768c4 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -1510,6 +1510,7 @@
}
/// See the comments of [rewriteFunction] for more explanation.
+ @override
void visitTry(js.Try node) {
if (!shouldTransform(node)) {
js.Block body = translateToBlock(node.body);
@@ -1721,6 +1722,7 @@
}
class AsyncRewriter extends AsyncRewriterBase {
+ @override
bool get isAsync => true;
/// The Completer that will finish an async function.
@@ -1787,6 +1789,7 @@
reporter.internalError(spannable, "Yield in non-generating async function");
}
+ @override
void addErrorExit(SourceInformation sourceInformation) {
if (!hasHandlerLabels) return; // rethrow handled in method boilerplate.
beginLabel(rethrowLabel);
@@ -1803,6 +1806,7 @@
/// Returning from an async method calls [asyncStarHelper] with the result.
/// (the result might have been stored in [returnValue] by some finally
/// block).
+ @override
void addSuccessExit(SourceInformation sourceInformation) {
if (analysis.hasExplicitReturns) {
beginLabel(exitLabel);
@@ -1929,6 +1933,7 @@
}
class SyncStarRewriter extends AsyncRewriterBase {
+ @override
bool get isSyncStar => true;
/// Constructor creating the Iterable for a sync* method. Called with
@@ -2068,6 +2073,7 @@
}).withSourceInformation(functionSourceInformation);
}
+ @override
void addErrorExit(SourceInformation sourceInformation) {
hasHandlerLabels = true; // TODO(sra): Add short form error handler.
beginLabel(rethrowLabel);
@@ -2080,6 +2086,7 @@
}
/// Returning from a sync* function returns an [endOfIteration] marker.
+ @override
void addSuccessExit(SourceInformation sourceInformation) {
if (analysis.hasExplicitReturns) {
beginLabel(exitLabel);
@@ -2114,6 +2121,7 @@
}
class AsyncStarRewriter extends AsyncRewriterBase {
+ @override
bool get isAsyncStar => true;
/// The stack of labels of finally blocks to assign to [next] if the
diff --git a/pkg/compiler/lib/src/js_backend/annotations.dart b/pkg/compiler/lib/src/js_backend/annotations.dart
index f0c48f7..1464c0b 100644
--- a/pkg/compiler/lib/src/js_backend/annotations.dart
+++ b/pkg/compiler/lib/src/js_backend/annotations.dart
@@ -4,11 +4,16 @@
library js_backend.backend.annotations;
+import 'package:kernel/ast.dart' as ir;
+
+import '../common.dart';
import '../common_elements.dart' show KCommonElements, KElementEnvironment;
import '../constants/values.dart';
import '../diagnostics/diagnostic_listener.dart';
import '../diagnostics/messages.dart';
import '../elements/entities.dart';
+import '../ir/annotations.dart';
+import '../ir/util.dart';
import '../kernel/dart2js_target.dart';
import '../options.dart';
import '../serialization/serialization.dart';
@@ -80,20 +85,11 @@
];
}
-Set<PragmaAnnotation> processMemberAnnotations(
- CompilerOptions options,
- DiagnosticReporter reporter,
+List<PragmaAnnotationData> computePragmaAnnotationData(
KCommonElements commonElements,
KElementEnvironment elementEnvironment,
- AnnotationsDataBuilder annotationsDataBuilder,
MemberEntity element) {
- EnumSet<PragmaAnnotation> values = new EnumSet<PragmaAnnotation>();
-
- LibraryEntity library = element.library;
- bool platformAnnotationsAllowed = options.testMode ||
- library.canonicalUri.scheme == 'dart' ||
- maybeEnableNative(library.canonicalUri);
-
+ List<PragmaAnnotationData> annotations = [];
for (ConstantValue constantValue
in elementEnvironment.getMemberMetadata(element)) {
if (!constantValue.isConstructedObject) continue;
@@ -102,21 +98,9 @@
assert(cls != null); // Unresolved classes null.
if (cls == commonElements.metaNoInlineClass) {
- values.add(PragmaAnnotation.noInline);
- if (element is! FunctionEntity) {
- reporter.internalError(
- element,
- "@pragma('dart2js:noInline') is only allowed in methods "
- "and constructors.");
- }
+ annotations.add(const PragmaAnnotationData('noInline'));
} else if (cls == commonElements.metaTryInlineClass) {
- values.add(PragmaAnnotation.tryInline);
- if (element is! FunctionEntity) {
- reporter.internalError(
- element,
- "@pragma('dart2js:tryInline') is only allowed in methods "
- "and constructors.");
- }
+ annotations.add(const PragmaAnnotationData('tryInline'));
} else if (cls == commonElements.pragmaClass) {
ConstantValue nameValue =
value.fields[commonElements.pragmaClassNameField];
@@ -128,49 +112,78 @@
ConstantValue optionsValue =
value.fields[commonElements.pragmaClassOptionsField];
- bool found = false;
- for (PragmaAnnotation annotation in PragmaAnnotation.values) {
- if (annotation.name == suffix) {
- found = true;
- values.add(annotation);
+ annotations.add(
+ new PragmaAnnotationData(suffix, hasOptions: !optionsValue.isNull));
+ }
+ }
+ return annotations;
+}
- if (!optionsValue.isNull) {
- reporter.reportErrorMessage(element, MessageKind.GENERIC,
- {'text': "@pragma('$name') annotation does not take options"});
- }
- if (annotation.forFunctionsOnly) {
- if (element is! FunctionEntity) {
- reporter.reportErrorMessage(element, MessageKind.GENERIC, {
- 'text': "@pragma('$name') annotation is only supported "
- "for methods and constructors."
- });
- }
- }
- if (annotation.forFieldsOnly) {
- if (element is! FieldEntity) {
- reporter.reportErrorMessage(element, MessageKind.GENERIC, {
- 'text': "@pragma('$name') annotation is only supported "
- "for fields."
- });
- }
- }
- if (annotation.internalOnly && !platformAnnotationsAllowed) {
- reporter.reportErrorMessage(element, MessageKind.GENERIC,
- {'text': "Unrecognized dart2js pragma @pragma('$name')"});
- }
- break;
+EnumSet<PragmaAnnotation> processMemberAnnotations(
+ CompilerOptions options,
+ DiagnosticReporter reporter,
+ ir.Member member,
+ List<PragmaAnnotationData> pragmaAnnotationData) {
+ EnumSet<PragmaAnnotation> values = new EnumSet<PragmaAnnotation>();
+
+ Uri uri = member.enclosingLibrary.importUri;
+ bool platformAnnotationsAllowed =
+ options.testMode || uri.scheme == 'dart' || maybeEnableNative(uri);
+
+ for (PragmaAnnotationData data in pragmaAnnotationData) {
+ String name = data.name;
+ String suffix = data.suffix;
+ bool found = false;
+ for (PragmaAnnotation annotation in PragmaAnnotation.values) {
+ if (annotation.name == suffix) {
+ found = true;
+ values.add(annotation);
+
+ if (data.hasOptions) {
+ reporter.reportErrorMessage(
+ computeSourceSpanFromTreeNode(member),
+ MessageKind.GENERIC,
+ {'text': "@pragma('$name') annotation does not take options"});
}
+ if (annotation.forFunctionsOnly) {
+ if (member is! ir.Procedure && member is! ir.Constructor) {
+ reporter.reportErrorMessage(
+ computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
+ 'text': "@pragma('$name') annotation is only supported "
+ "for methods and constructors."
+ });
+ }
+ }
+ if (annotation.forFieldsOnly) {
+ if (member is! ir.Field) {
+ reporter.reportErrorMessage(
+ computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
+ 'text': "@pragma('$name') annotation is only supported "
+ "for fields."
+ });
+ }
+ }
+ if (annotation.internalOnly && !platformAnnotationsAllowed) {
+ reporter.reportErrorMessage(
+ computeSourceSpanFromTreeNode(member),
+ MessageKind.GENERIC,
+ {'text': "Unrecognized dart2js pragma @pragma('$name')"});
+ }
+ break;
}
- if (!found) {
- reporter.reportErrorMessage(element, MessageKind.GENERIC,
- {'text': "Unknown dart2js pragma @pragma('$name')"});
- }
+ }
+ if (!found) {
+ reporter.reportErrorMessage(
+ computeSourceSpanFromTreeNode(member),
+ MessageKind.GENERIC,
+ {'text': "Unknown dart2js pragma @pragma('$name')"});
}
}
if (values.contains(PragmaAnnotation.tryInline) &&
values.contains(PragmaAnnotation.noInline)) {
- reporter.reportErrorMessage(element, MessageKind.GENERIC, {
+ reporter.reportErrorMessage(
+ computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
'text': "@pragma('dart2js:tryInline') must not be used with "
"@pragma('dart2js:noInline')."
});
@@ -179,20 +192,18 @@
if (values.contains(PragmaAnnotation.noThrows) &&
!values.contains(PragmaAnnotation.noInline)) {
reporter.internalError(
- element,
+ computeSourceSpanFromTreeNode(member),
"@pragma('dart2js:noThrows') should always be combined with "
"@pragma('dart2js:noInline').");
}
if (values.contains(PragmaAnnotation.noSideEffects) &&
!values.contains(PragmaAnnotation.noInline)) {
reporter.internalError(
- element,
+ computeSourceSpanFromTreeNode(member),
"@pragma('dart2js:noSideEffects') should always be combined with "
"@pragma('dart2js:noInline').");
}
- annotationsDataBuilder.registerPragmaAnnotations(element, values);
- return new Set<PragmaAnnotation>.from(
- values.iterable(PragmaAnnotation.values));
+ return values;
}
abstract class AnnotationsData {
@@ -262,6 +273,7 @@
return new AnnotationsDataImpl(pragmaAnnotations);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeMemberMap(pragmaAnnotations, (EnumSet<PragmaAnnotation> set) {
@@ -275,27 +287,35 @@
return set != null && set.contains(annotation);
}
+ @override
bool hasAssumeDynamic(MemberEntity member) =>
_hasPragma(member, PragmaAnnotation.assumeDynamic);
+ @override
bool hasNoInline(MemberEntity member) =>
_hasPragma(member, PragmaAnnotation.noInline);
+ @override
bool hasTryInline(MemberEntity member) =>
_hasPragma(member, PragmaAnnotation.tryInline);
+ @override
bool hasDisableFinal(MemberEntity member) =>
_hasPragma(member, PragmaAnnotation.disableFinal);
+ @override
bool hasNoElision(MemberEntity member) =>
_hasPragma(member, PragmaAnnotation.noElision);
+ @override
bool hasNoThrows(MemberEntity member) =>
_hasPragma(member, PragmaAnnotation.noThrows);
+ @override
bool hasNoSideEffects(MemberEntity member) =>
_hasPragma(member, PragmaAnnotation.noSideEffects);
+ @override
void forEachNoInline(void f(FunctionEntity function)) {
pragmaAnnotations
.forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
@@ -305,6 +325,7 @@
});
}
+ @override
void forEachTryInline(void f(FunctionEntity function)) {
pragmaAnnotations
.forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
@@ -314,6 +335,7 @@
});
}
+ @override
void forEachNoThrows(void f(FunctionEntity function)) {
pragmaAnnotations
.forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
@@ -323,6 +345,7 @@
});
}
+ @override
void forEachNoSideEffects(void f(FunctionEntity function)) {
pragmaAnnotations
.forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index ed86add..1dc5108 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -114,12 +114,14 @@
bool requiresPreamble = false;
/// `true` if `Function.apply` is used.
+ @override
bool isFunctionApplyUsed = false;
/// `true` if 'dart:mirrors' features are used.
bool isMirrorsUsed = false;
/// `true` if `noSuchMethod` is used.
+ @override
bool isNoSuchMethodUsed = false;
BackendUsageBuilderImpl(this._frontendStrategy);
@@ -190,6 +192,7 @@
}
}
+ @override
void processBackendImpact(BackendImpact backendImpact) {
for (FunctionEntity staticUse in backendImpact.staticUses) {
assert(staticUse != null);
@@ -223,6 +226,7 @@
}
}
+ @override
void registerUsedMember(MemberEntity member) {
if (member == _commonElements.getIsolateAffinityTagMarker) {
_needToInitializeIsolateAffinityTag = true;
@@ -235,6 +239,7 @@
}
}
+ @override
void registerGlobalFunctionDependency(FunctionEntity element) {
assert(element != null);
if (_globalFunctionDependencies == null) {
@@ -243,6 +248,7 @@
_globalFunctionDependencies.add(element);
}
+ @override
void registerGlobalClassDependency(ClassEntity element) {
assert(element != null);
if (_globalClassDependencies == null) {
@@ -256,6 +262,7 @@
_runtimeTypeUses.add(runtimeTypeUse);
}
+ @override
BackendUsage close() {
return new BackendUsageImpl(
globalFunctionDependencies: _globalFunctionDependencies,
@@ -289,19 +296,25 @@
final Set<RuntimeTypeUse> _runtimeTypeUses;
+ @override
bool needToInitializeIsolateAffinityTag;
+ @override
bool needToInitializeDispatchProperty;
/// `true` if a core-library function requires the preamble file to function.
+ @override
final bool requiresPreamble;
/// `true` if `Function.apply` is used.
+ @override
final bool isFunctionApplyUsed;
/// `true` if 'dart:mirrors' features are used.
+ @override
final bool isMirrorsUsed;
/// `true` if `noSuchMethod` is used.
+ @override
final bool isNoSuchMethodUsed;
BackendUsageImpl(
@@ -357,6 +370,7 @@
isNoSuchMethodUsed: isNoSuchMethodUsed);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeMembers(_globalFunctionDependencies);
diff --git a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
index 71bb262..9682f5b 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -37,8 +37,10 @@
class PropertyCheckedModeHelper extends CheckedModeHelper {
const PropertyCheckedModeHelper(String name) : super(name);
+ @override
CallStructure get callStructure => CallStructure.TWO_ARGS;
+ @override
void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
DartType type = node.typeExpression;
@@ -50,8 +52,10 @@
class TypeVariableCheckedModeHelper extends CheckedModeHelper {
const TypeVariableCheckedModeHelper(String name) : super(name);
+ @override
CallStructure get callStructure => CallStructure.TWO_ARGS;
+ @override
void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
assert(node.typeExpression.isTypeVariable);
@@ -63,8 +67,10 @@
class FunctionTypeRepresentationCheckedModeHelper extends CheckedModeHelper {
const FunctionTypeRepresentationCheckedModeHelper(String name) : super(name);
+ @override
CallStructure get callStructure => CallStructure.TWO_ARGS;
+ @override
void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
assert(node.typeExpression.isFunctionType);
@@ -76,8 +82,10 @@
class FutureOrRepresentationCheckedModeHelper extends CheckedModeHelper {
const FutureOrRepresentationCheckedModeHelper(String name) : super(name);
+ @override
CallStructure get callStructure => CallStructure.TWO_ARGS;
+ @override
void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
assert(node.typeExpression.isFutureOr);
@@ -89,8 +97,10 @@
class SubtypeCheckedModeHelper extends CheckedModeHelper {
const SubtypeCheckedModeHelper(String name) : super(name);
+ @override
CallStructure get callStructure => const CallStructure.unnamed(4);
+ @override
void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
// TODO(sra): Move these calls into the SSA graph so that the arguments can
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index 1335b2e..2b65955 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -20,6 +20,7 @@
: this.jsConstantCompiler = new JavaScriptConstantCompiler(),
super(compiler.measurer);
+ @override
String get name => 'ConstantHandler';
}
diff --git a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
index a3c61f7..16be5f2 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -81,6 +81,7 @@
}
class CustomElementsResolutionAnalysis extends CustomElementsAnalysisBase {
+ @override
final CustomElementsAnalysisJoin join;
CustomElementsResolutionAnalysis(
@@ -117,6 +118,7 @@
}
class CustomElementsCodegenAnalysis extends CustomElementsAnalysisBase {
+ @override
final CustomElementsAnalysisJoin join;
CustomElementsCodegenAnalysis(CommonElements commonElements,
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 72910ae..a0c3009 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -37,8 +37,11 @@
final CodegenWorldBuilderImpl _worldBuilder;
final WorkItemBuilder _workItemBuilder;
+ @override
bool queueIsClosed = false;
+ @override
final CompilerTask task;
+ @override
final EnqueuerListener listener;
final CompilerOptions _options;
@@ -62,8 +65,10 @@
_impactVisitor = new EnqueuerImplImpactVisitor(this);
}
+ @override
CodegenWorldBuilder get worldBuilder => _worldBuilder;
+ @override
bool get queueIsEmpty => _queue.isEmpty;
@override
@@ -74,6 +79,7 @@
}
/// Returns [:true:] if this enqueuer is the resolution enqueuer.
+ @override
bool get isResolutionQueue => false;
/// Create a [WorkItem] for [entity] and add it to the work list if it has not
@@ -92,6 +98,7 @@
_queue.add(workItem);
}
+ @override
void applyImpact(WorldImpact worldImpact, {var impactSource}) {
if (worldImpact.isEmpty) return;
impactStrategy.visitImpact(
@@ -106,11 +113,13 @@
});
}
+ @override
bool checkNoEnqueuedInvokedInstanceMethods(
ElementEnvironment elementEnvironment) {
return checkEnqueuerConsistency(elementEnvironment);
}
+ @override
void checkClass(ClassEntity cls) {
_worldBuilder.processClassMembers(cls, (MemberEntity member, useSet) {
if (useSet.isNotEmpty) {
@@ -148,12 +157,14 @@
}
}
+ @override
void processDynamicUse(DynamicUse dynamicUse) {
task.measure(() {
_worldBuilder.registerDynamicUse(dynamicUse, _applyMemberUse);
});
}
+ @override
void processStaticUse(StaticUse staticUse) {
_worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
switch (staticUse.kind) {
@@ -171,6 +182,7 @@
}
}
+ @override
void processTypeUse(TypeUse typeUse) {
DartType type = typeUse.type;
switch (typeUse.kind) {
@@ -213,6 +225,7 @@
}
}
+ @override
void processConstantUse(ConstantUse constantUse) {
task.measure(() {
if (_worldBuilder.registerConstantUse(constantUse)) {
@@ -252,6 +265,7 @@
_queue.isNotEmpty || _recentClasses.isNotEmpty || _recentConstants);
}
+ @override
void forEach(void f(WorkItem work)) {
_forEach(f);
if (onEmptyForTesting != null) {
@@ -276,8 +290,10 @@
listener.logSummary(log);
}
+ @override
String toString() => 'Enqueuer($name)';
+ @override
ImpactUseCase get impactUse => IMPACT_USE;
@override
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index 41477f0..915dd48 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -4,20 +4,20 @@
import 'package:kernel/ast.dart' as ir;
+import '../common.dart';
import '../constants/values.dart';
import '../elements/entities.dart';
+import '../elements/entity_utils.dart';
import '../ir/scope_visitor.dart';
import '../js_model/elements.dart' show JField;
import '../js_model/js_world_builder.dart';
import '../kernel/element_map.dart';
import '../kernel/kernel_strategy.dart';
import '../kernel/kelements.dart' show KClass, KField, KConstructor;
+import '../kernel/kernel_world.dart';
import '../options.dart';
import '../serialization/serialization.dart';
import '../universe/member_usage.dart';
-import '../world.dart';
-
-abstract class FieldAnalysis {}
/// AllocatorAnalysis
///
@@ -35,7 +35,7 @@
//
// this.x = this.z = null;
//
-class KFieldAnalysis implements FieldAnalysis {
+class KFieldAnalysis {
final KernelToElementMap _elementMap;
final Map<KClass, ClassData> _classData = {};
@@ -154,6 +154,8 @@
final InitializerComplexity complexity;
StaticFieldData(this.initialValue, this.complexity);
+
+ bool get hasDependencies => complexity != null && complexity.fields != null;
}
class AllocatorData {
@@ -209,13 +211,14 @@
throw new UnsupportedError('Unexpected kind $kind');
}
+ @override
String toString() => shortText;
}
-class JFieldAnalysis implements FieldAnalysis {
+class JFieldAnalysis {
/// Tag used for identifying serialized [JFieldAnalysis] objects in a
/// debugging data stream.
- static const String tag = 'allocator-analysis';
+ static const String tag = 'field-analysis';
// --csp and --fast-startup have different constraints to the generated code.
@@ -241,8 +244,8 @@
sink.end(tag);
}
- factory JFieldAnalysis.from(
- KClosedWorld closedWorld, JsToFrontendMap map, CompilerOptions options) {
+ factory JFieldAnalysis.from(KClosedWorldImpl closedWorld, JsToFrontendMap map,
+ CompilerOptions options) {
Map<FieldEntity, FieldAnalysisData> fieldData = {};
bool canBeElided(FieldEntity field) {
@@ -355,33 +358,178 @@
});
});
+ List<KField> independentFields = [];
+ List<KField> dependentFields = [];
+
closedWorld.liveMemberUsage
.forEach((MemberEntity member, MemberUsage memberUsage) {
if (member.isField && !member.isInstanceMember) {
- JField jField = map.toBackendMember(member);
- if (jField == null) return;
-
- if (!memberUsage.hasRead && canBeElided(member)) {
- fieldData[jField] = const FieldAnalysisData(isElided: true);
+ StaticFieldData staticFieldData =
+ closedWorld.fieldAnalysis._staticFieldData[member];
+ if (staticFieldData.hasDependencies) {
+ dependentFields.add(member);
} else {
- bool isEffectivelyFinal = !memberUsage.hasWrite;
- StaticFieldData staticFieldData =
- closedWorld.fieldAnalysis._staticFieldData[member];
- ConstantValue value = map
- .toBackendConstant(staticFieldData.initialValue, allowNull: true);
- bool isElided =
- isEffectivelyFinal && value != null && canBeElided(member);
- // TODO(johnniwinther): Compute effective initializer complexity.
- if (value != null || isEffectivelyFinal) {
- fieldData[jField] = new FieldAnalysisData(
- initialValue: value,
- isEffectivelyFinal: isEffectivelyFinal,
- isElided: isElided);
- }
+ independentFields.add(member);
}
}
});
+ // Fields already processed.
+ Set<KField> processedFields = {};
+
+ // Fields currently being processed. Use for detecting cyclic dependencies.
+ Set<KField> currentFields = {};
+
+ // Index ascribed to eager fields that depend on other fields. This is
+ // used to sort the field in emission to ensure that used fields have been
+ // initialized when read.
+ int eagerCreationIndex = 0;
+
+ /// Computes the [FieldAnalysisData] for the JField corresponding to
+ /// [kField].
+ ///
+ /// If the data is currently been computed, that is, [kField] has a
+ /// cyclic dependency, `null` is returned.
+ FieldAnalysisData processField(KField kField) {
+ JField jField = map.toBackendMember(kField);
+ // TODO(johnniwinther): Can we assert that [jField] exists?
+ if (jField == null) return null;
+
+ FieldAnalysisData data = fieldData[jField];
+ if (processedFields.contains(kField)) {
+ // We only store data for non-trivial [FieldAnalysisData].
+ return data ?? const FieldAnalysisData();
+ }
+ if (currentFields.contains(kField)) {
+ // Cyclic dependency.
+ return null;
+ }
+ currentFields.add(kField);
+ MemberUsage memberUsage = closedWorld.liveMemberUsage[kField];
+ if (!memberUsage.hasRead && canBeElided(kField)) {
+ data = fieldData[jField] = const FieldAnalysisData(isElided: true);
+ } else {
+ bool isEffectivelyFinal = !memberUsage.hasWrite;
+ StaticFieldData staticFieldData =
+ closedWorld.fieldAnalysis._staticFieldData[kField];
+ ConstantValue value = map
+ .toBackendConstant(staticFieldData.initialValue, allowNull: true);
+
+ // If the field is effectively final with a constant initializer we
+ // elide the field, if allowed, because it is effectively constant.
+ bool isElided =
+ isEffectivelyFinal && value != null && canBeElided(kField);
+
+ bool isEager;
+
+ // If the field is eager and dependent on other eager fields,
+ // [eagerFieldDependencies] holds these fields and [creationIndex] is
+ // given the creation order index used to ensure that all dependencies
+ // have been assigned their values before this field is initialized.
+ //
+ // Since we only need the values of [eagerFieldDependencies] for testing
+ // and only the non-emptiness for determining the need for creation
+ // order indices, [eagerFieldDependencies] is non-null if the field has
+ // dependencies but only hold these when [retainDataForTesting] is
+ // `true`.
+ List<FieldEntity> eagerFieldDependencies;
+ int creationIndex = null;
+
+ if (isElided) {
+ // If the field is elided it needs no initializer and is therefore
+ // not eager.
+ isEager = false;
+ } else {
+ // If the field has a constant initializer we know it can be
+ // initialized eagerly.
+ //
+ // Ideally this should be the same as
+ // `staticFieldData.complexity.isConstant` but currently the constant
+ // evaluator handles cases that the analysis doesn't, so we use the
+ // better result.
+ isEager = value != null;
+ if (!isEager) {
+ // The field might be eager depending on the initializer complexity
+ // and its dependencies.
+ InitializerComplexity complexity = staticFieldData.complexity;
+ isEager = complexity?.isEager ?? false;
+ if (isEager && complexity.fields != null) {
+ for (ir.Field node in complexity.fields) {
+ KField otherField = closedWorld.elementMap.getField(node);
+ FieldAnalysisData otherData = processField(otherField);
+ if (otherData == null) {
+ // Cyclic dependency on [otherField].
+ isEager = false;
+ break;
+ }
+ if (otherData.isLazy) {
+ // [otherField] needs lazy initialization.
+ isEager = false;
+ break;
+ }
+ if (!otherData.isEffectivelyFinal) {
+ // [otherField] might not hold its initial value when this field
+ // is accessed the first time, so we need to initialize this
+ // field lazily.
+ isEager = false;
+ break;
+ }
+ if (!otherData.isEffectivelyConstant) {
+ eagerFieldDependencies ??= [];
+ if (retainDataForTesting) {
+ eagerFieldDependencies.add(map.toBackendMember(otherField));
+ }
+ }
+ }
+ }
+ }
+
+ if (isEager && eagerFieldDependencies != null) {
+ creationIndex = eagerCreationIndex++;
+ if (!retainDataForTesting) {
+ eagerFieldDependencies = null;
+ }
+ } else {
+ eagerFieldDependencies = null;
+ }
+ }
+
+ data = fieldData[jField] = new FieldAnalysisData(
+ initialValue: value,
+ isEffectivelyFinal: isEffectivelyFinal,
+ isElided: isElided,
+ isEager: isEager,
+ eagerCreationIndex: creationIndex,
+ eagerFieldDependenciesForTesting: eagerFieldDependencies);
+ }
+
+ currentFields.remove(kField);
+ processedFields.add(kField);
+ return data;
+ }
+
+ // Process independent fields in no particular order. The emitter sorts
+ // these later.
+ independentFields.forEach(processField);
+
+ // Process dependent fields in declaration order to make ascribed creation
+ // indices stable. The emitter uses the creation indices for sorting
+ // dependent fields.
+ dependentFields.sort((KField a, KField b) {
+ int result =
+ compareLibrariesUris(a.library.canonicalUri, b.library.canonicalUri);
+ if (result != 0) return result;
+ ir.Location aLocation = closedWorld.elementMap.getMemberNode(a).location;
+ ir.Location bLocation = closedWorld.elementMap.getMemberNode(b).location;
+ result = compareSourceUris(aLocation.file, bLocation.file);
+ if (result != 0) return result;
+ result = aLocation.line.compareTo(bLocation.line);
+ if (result != 0) return result;
+ return aLocation.column.compareTo(bLocation.column);
+ });
+
+ dependentFields.forEach(processField);
+
return new JFieldAnalysis._(fieldData);
}
@@ -402,11 +550,25 @@
final bool isEffectivelyFinal;
final bool isElided;
+ /// If `true` the field is not effectively constant but the initializer can be
+ /// generated eagerly without the need for lazy initialization wrapper.
+ final bool isEager;
+
+ /// Index ascribed to eager fields that depend on other fields. This is
+ /// used to sort the field in emission to ensure that used fields have been
+ /// initialized when read.
+ final int eagerCreationIndex;
+
+ final List<FieldEntity> eagerFieldDependenciesForTesting;
+
const FieldAnalysisData(
{this.initialValue,
this.isInitializedInAllocator: false,
this.isEffectivelyFinal: false,
- this.isElided: false});
+ this.isElided: false,
+ this.isEager: false,
+ this.eagerCreationIndex: null,
+ this.eagerFieldDependenciesForTesting: null});
factory FieldAnalysisData.fromDataSource(DataSource source) {
source.begin(tag);
@@ -415,12 +577,19 @@
bool isInitializedInAllocator = source.readBool();
bool isEffectivelyFinal = source.readBool();
bool isElided = source.readBool();
+ bool isEager = source.readBool();
+ int eagerCreationIndex = source.readIntOrNull();
+ List<FieldEntity> eagerFieldDependencies =
+ source.readMembers<FieldEntity>(emptyAsNull: true);
source.end(tag);
return new FieldAnalysisData(
initialValue: initialValue,
isInitializedInAllocator: isInitializedInAllocator,
isEffectivelyFinal: isEffectivelyFinal,
- isElided: isElided);
+ isElided: isElided,
+ isEager: isEager,
+ eagerCreationIndex: eagerCreationIndex,
+ eagerFieldDependenciesForTesting: eagerFieldDependencies);
}
void writeToDataSink(DataSink sink) {
@@ -429,16 +598,26 @@
sink.writeBool(isInitializedInAllocator);
sink.writeBool(isEffectivelyFinal);
sink.writeBool(isElided);
+ sink.writeBool(isEager);
+ sink.writeIntOrNull(eagerCreationIndex);
+ sink.writeMembers(eagerFieldDependenciesForTesting, allowNull: true);
sink.end(tag);
}
+ /// If `true` the initializer for this field requires a lazy initialization
+ /// wrapper.
+ bool get isLazy => initialValue == null && !isEager;
+
bool get isEffectivelyConstant =>
isEffectivelyFinal && isElided && initialValue != null;
ConstantValue get constantValue => isEffectivelyFinal ? initialValue : null;
+ @override
String toString() =>
'FieldAnalysisData(initialValue=${initialValue?.toStructuredText()},'
'isInitializedInAllocator=$isInitializedInAllocator,'
- 'isEffectivelyFinal=$isEffectivelyFinal,isElided=$isElided)';
+ 'isEffectivelyFinal=$isEffectivelyFinal,isElided=$isElided,'
+ 'isEager=$isEager,eagerCreationIndex=$eagerCreationIndex,'
+ 'eagerFieldDependencies=$eagerFieldDependenciesForTesting)';
}
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index 828dd25..a0fb0b3 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -189,7 +189,9 @@
/// as a separator between method names and argument counts and does not appear
/// in generated names themselves.
class _MixinFieldNamingScope extends _FieldNamingScope {
+ @override
int get _localFieldNameCounter => registry.globalCount;
+ @override
void set _localFieldNameCounter(int val) {
registry.globalCount = val;
}
@@ -204,6 +206,7 @@
_FieldNamingScope superScope, _FieldNamingRegistry registry)
: super.inherit(container, superScope, registry);
+ @override
jsAst.Name _nextName() {
jsAst.Name proposed = super._nextName();
return new CompoundName([proposed, Namer._literalDollar]);
@@ -221,6 +224,7 @@
@override
bool containsField(_) => true;
+ @override
jsAst.Name operator [](Entity field) {
if (!names.containsKey(field)) add(field);
return names[field];
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 781d1ef..36ff852 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -7,6 +7,7 @@
class FrequencyBasedNamer extends Namer
with _MinifiedFieldNamer, _MinifiedOneShotInterceptorNamer
implements jsAst.TokenFinalizer {
+ @override
_FieldNamingRegistry fieldRegistry;
List<TokenName> tokens = new List<TokenName>();
@@ -14,21 +15,35 @@
new Maplet<NamingScope, TokenScope>();
// Some basic settings for smaller names
+ @override
String get isolateName => 'I';
+ @override
String get isolatePropertiesName => 'p';
+ @override
bool get shouldMinify => true;
+ @override
final String getterPrefix = 'g';
+ @override
final String setterPrefix = 's';
+ @override
final String callPrefix = ''; // this will create function names $<n>
+ @override
String get operatorIsPrefix => r'$i';
+ @override
String get operatorAsPrefix => r'$a';
+ @override
String get callCatchAllName => r'$C';
+ @override
String get requiredParameterField => r'$R';
+ @override
String get defaultValuesField => r'$D';
+ @override
String get operatorSignature => r'$S';
+ @override
String get genericInstantiationPrefix => r'$I';
+ @override
jsAst.Name get staticsPropertyName =>
_staticsPropertyName ??= getFreshName(instanceScope, 'static');
diff --git a/pkg/compiler/lib/src/js_backend/inferred_data.dart b/pkg/compiler/lib/src/js_backend/inferred_data.dart
index ad5be30..be9b3dc 100644
--- a/pkg/compiler/lib/src/js_backend/inferred_data.dart
+++ b/pkg/compiler/lib/src/js_backend/inferred_data.dart
@@ -121,6 +121,7 @@
functionsThatMightBePassedToApply);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeBool(false); // Is _not_ trivial.
sink.begin(tag);
@@ -235,6 +236,7 @@
}
/// Compute [SideEffects] for all registered [SideEffectBuilder]s.
+ @override
InferredData close(JClosedWorld closedWorld) {
assert(_sideEffectsBuilders != null,
"Inferred data has already been computed.");
diff --git a/pkg/compiler/lib/src/js_backend/interceptor_data.dart b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
index 06c66ae..0a206a5 100644
--- a/pkg/compiler/lib/src/js_backend/interceptor_data.dart
+++ b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
@@ -72,6 +72,7 @@
final Map<String, Set<MemberEntity>> interceptedMembers;
/// Set of classes whose methods are intercepted.
+ @override
final Set<ClassEntity> interceptedClasses;
/// Set of classes used as mixins on intercepted (native and primitive)
@@ -125,6 +126,7 @@
classesMixedIntoInterceptedClasses);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeInt(interceptedMembers.length);
@@ -137,6 +139,7 @@
sink.end(tag);
}
+ @override
bool isInterceptedMethod(MemberEntity element) {
if (!element.isInstanceMember) return false;
// TODO(johnniwinther): Avoid this hack.
@@ -146,18 +149,22 @@
return interceptedMembers[element.name] != null;
}
+ @override
bool fieldHasInterceptedGetter(FieldEntity element) {
return interceptedMembers[element.name] != null;
}
+ @override
bool fieldHasInterceptedSetter(FieldEntity element) {
return interceptedMembers[element.name] != null;
}
+ @override
bool isInterceptedName(String name) {
return interceptedMembers[name] != null;
}
+ @override
bool isInterceptedSelector(Selector selector) {
return interceptedMembers[selector.name] != null;
}
@@ -165,6 +172,7 @@
/// Returns `true` iff [selector] matches an element defined in a class mixed
/// into an intercepted class. These selectors are not eligible for the
/// 'dummy explicit receiver' optimization.
+ @override
bool isInterceptedMixinSelector(
Selector selector, AbstractValue mask, JClosedWorld closedWorld) {
Set<MemberEntity> elements =
@@ -203,6 +211,7 @@
/// Returns a set of interceptor classes that contain a member named [name]
///
/// Returns an empty set if there is no class. Do not modify the returned set.
+ @override
Set<ClassEntity> getInterceptedClassesOn(
String name, JClosedWorld closedWorld) {
Set<MemberEntity> intercepted = interceptedMembers[name];
@@ -244,6 +253,7 @@
return result;
}
+ @override
bool isInterceptedClass(ClassEntity element) {
if (element == null) return false;
if (_nativeData.isNativeOrExtendsNative(element)) return true;
@@ -252,9 +262,11 @@
return false;
}
+ @override
bool isMixedIntoInterceptedClass(ClassEntity element) =>
classesMixedIntoInterceptedClasses.contains(element);
+ @override
bool mayGenerateInstanceofCheck(DartType type, JClosedWorld closedWorld) {
// We can use an instanceof check for raw types that have no subclass that
// is mixed-in or in an implements clause.
@@ -291,6 +303,7 @@
InterceptorDataBuilderImpl(
this._nativeData, this._elementEnvironment, this._commonElements);
+ @override
InterceptorData close() {
return new InterceptorDataImpl(
_nativeData,
@@ -300,6 +313,7 @@
_classesMixedIntoInterceptedClasses);
}
+ @override
void addInterceptorsForNativeClassMembers(ClassEntity cls) {
_elementEnvironment.forEachClassMember(cls,
(ClassEntity cls, MemberEntity member) {
@@ -317,6 +331,7 @@
});
}
+ @override
void addInterceptors(ClassEntity cls) {
if (_interceptedClasses.add(cls)) {
_elementEnvironment.forEachClassMember(cls,
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 2d772ff..3179a2f 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -16,21 +16,35 @@
fieldRegistry = new _FieldNamingRegistry(this);
}
+ @override
_FieldNamingRegistry fieldRegistry;
+ @override
String get isolateName => 'I';
+ @override
String get isolatePropertiesName => 'p';
+ @override
bool get shouldMinify => true;
+ @override
final String getterPrefix = 'g';
+ @override
final String setterPrefix = 's';
+ @override
final String callPrefix = ''; // this will create function names $<n>
+ @override
String get operatorIsPrefix => r'$i';
+ @override
String get operatorAsPrefix => r'$a';
+ @override
String get callCatchAllName => r'$C';
+ @override
String get requiredParameterField => r'$R';
+ @override
String get defaultValuesField => r'$D';
+ @override
String get operatorSignature => r'$S';
+ @override
String get genericInstantiationPrefix => r'$I';
final ALPHABET_CHARACTERS = 52; // a-zA-Z.
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 3222b70..0648b9c 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -2291,24 +2291,30 @@
return sb.toString();
}
+ @override
visit(DartType type, [_]) {
type.accept(this, null);
}
+ @override
visitType(DartType type, _) {}
+ @override
visitInterfaceType(InterfaceType type, _) {
sb.write(type.element.name);
}
+ @override
visitTypedefType(TypedefType type, _) {
sb.write(type.element.name);
}
+ @override
visitTypeVariableType(TypeVariableType type, _) {
sb.write(type.element.name);
}
+ @override
visitFunctionType(FunctionType type, _) {
if (rtiEncoder.isSimpleFunctionType(type)) {
sb.write('args${type.parameterTypes.length}');
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index 9f351e3..db0819d 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -9,6 +9,7 @@
int get _kind;
_NamerName get _target => this;
+ @override
String toString() {
if (DEBUG_MODE) {
return 'Name($key)';
@@ -21,21 +22,27 @@
// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class StringBackedName extends _NamerName {
+ @override
final String name;
+ @override
int get _kind => _NamerNameKinds.StringBacked.index;
StringBackedName(this.name);
+ @override
String get key => name;
+ @override
operator ==(other) {
if (other is _NameReference) other = other._target;
if (identical(this, other)) return true;
return (other is StringBackedName) && other.name == name;
}
+ @override
int get hashCode => name.hashCode;
+ @override
int compareTo(covariant _NamerName other) {
other = other._target;
if (other._kind != _kind) return other._kind - _kind;
@@ -47,16 +54,21 @@
abstract class _PrefixedName extends _NamerName implements jsAst.AstContainer {
final jsAst.Name prefix;
final jsAst.Name base;
+ @override
int get _kind;
+ @override
Iterable<jsAst.Node> get containedNodes => [prefix, base];
_PrefixedName(this.prefix, this.base);
+ @override
String get name => prefix.name + base.name;
+ @override
String get key => prefix.key + base.key;
+ @override
bool operator ==(other) {
if (other is _NameReference) other = other._target;
if (identical(this, other)) return true;
@@ -64,8 +76,10 @@
return other.base == base && other.prefix == prefix;
}
+ @override
int get hashCode => base.hashCode * 13 + prefix.hashCode;
+ @override
int compareTo(covariant _NamerName other) {
other = other._target;
if (other._kind != _kind) return other._kind - _kind;
@@ -83,6 +97,7 @@
// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class GetterName extends _PrefixedName {
+ @override
int get _kind => _NamerNameKinds.Getter.index;
GetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
@@ -90,6 +105,7 @@
// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class SetterName extends _PrefixedName {
+ @override
int get _kind => _NamerNameKinds.Setter.index;
SetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
@@ -97,6 +113,7 @@
// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class _AsyncName extends _PrefixedName {
+ @override
int get _kind => _NamerNameKinds.Async.index;
_AsyncName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
@@ -108,14 +125,17 @@
// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class CompoundName extends _NamerName implements jsAst.AstContainer {
final List<_NamerName> _parts;
+ @override
int get _kind => _NamerNameKinds.Compound.index;
String _cachedName;
int _cachedHashCode = -1;
+ @override
Iterable<jsAst.Node> get containedNodes => _parts;
CompoundName(this._parts);
+ @override
String get name {
if (_cachedName == null) {
_cachedName = _parts.map((jsAst.Name name) => name.name).join();
@@ -123,8 +143,10 @@
return _cachedName;
}
+ @override
String get key => _parts.map((_NamerName name) => name.key).join();
+ @override
bool operator ==(other) {
if (other is _NameReference) other = other._target;
if (identical(this, other)) return true;
@@ -136,6 +158,7 @@
return true;
}
+ @override
int get hashCode {
if (_cachedHashCode < 0) {
_cachedHashCode = 0;
@@ -146,6 +169,7 @@
return _cachedHashCode;
}
+ @override
int compareTo(covariant _NamerName other) {
other = other._target;
if (other._kind != _kind) return other._kind - _kind;
@@ -163,8 +187,10 @@
// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class TokenName extends _NamerName implements jsAst.ReferenceCountedAstNode {
+ @override
int get _kind => _NamerNameKinds.Token.index;
String _name;
+ @override
final String key;
final TokenScope _scope;
int _rc = 0;
@@ -173,6 +199,7 @@
bool get isFinalized => _name != null;
+ @override
String get name {
assert(isFinalized);
return _name;
@@ -186,6 +213,7 @@
return key.compareTo(otherToken.key);
}
+ @override
markSeen(jsAst.TokenCounter counter) => _rc++;
@override
@@ -209,15 +237,20 @@
// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class _NameReference extends _NamerName implements jsAst.AstContainer {
+ @override
_NamerName _target;
+ @override
int get _kind => _target._kind;
+ @override
String get key => _target.key;
+ @override
Iterable<jsAst.Node> get containedNodes => [_target];
_NameReference(this._target);
+ @override
String get name => _target.name;
@override
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
index a491286..7b31ddc 100644
--- a/pkg/compiler/lib/src/js_backend/native_data.dart
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -63,6 +63,7 @@
NativeDataImpl.readFromDataSource;
/// Serializes this [NativeData] to [sink].
+ @override
void writeToDataSink(DataSink sink);
/// Returns `true` if [element] corresponds to a native JavaScript member.
@@ -97,6 +98,7 @@
String getFixedBackendMethodPath(FunctionEntity element);
/// Returns `true` if [element] is a JsInterop method.
+ @override
bool isJsInteropMember(MemberEntity element);
/// Returns the explicit js interop name for library [element].
@@ -158,26 +160,10 @@
/// Registers the [behavior] for writing to the native [field].
void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior);
- /// Marks [element] as an explicit part of JsInterop. The js interop name is
- /// expected to be computed later.
- void markAsJsInteropMember(MemberEntity element);
-
/// Sets the native [name] for the member [element]. This name is used for
/// [element] in the generated JavaScript.
void setNativeMemberName(MemberEntity element, String name);
- /// Sets the explicit js interop [name] for the library [element].
- void setJsInteropLibraryName(LibraryEntity element, String name);
-
- /// Marks [element] as having an `@Anonymous` annotation.
- void markJsInteropClassAsAnonymous(ClassEntity element);
-
- /// Sets the explicit js interop [name] for the class [element].
- void setJsInteropClassName(ClassEntity element, String name);
-
- /// Sets the explicit js interop [name] for the member [element].
- void setJsInteropMemberName(MemberEntity element, String name);
-
/// Closes this builder and creates the resulting [NativeData] object.
NativeData close();
}
@@ -207,6 +193,7 @@
/// The tag info string contains comma-separated 'words' which are either
/// dispatch tags (having JavaScript identifier syntax) and directives that
/// begin with `!`.
+ @override
void setNativeClassTagInfo(ClassEntity cls, String tagText) {
assert(
!_closed,
@@ -267,6 +254,7 @@
jsInteropMembers[element] = name;
}
+ @override
NativeBasicData close(ElementEnvironment environment) {
_closed = true;
return new NativeBasicDataImpl(
@@ -340,6 +328,7 @@
jsInteropMembers);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeClassMap(nativeClassTagInfo, (NativeClassTag tag) {
@@ -438,29 +427,11 @@
Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior =
<FieldEntity, NativeBehavior>{};
- /// The JavaScript names for libraries implemented via typed JavaScript
- /// interop.
- final Map<LibraryEntity, String> jsInteropLibraries;
-
- /// JavaScript interop classes annotated with `@anonymous`
- final Set<ClassEntity> anonymousJsInteropClasses;
-
- /// The JavaScript names for classes implemented via typed JavaScript
- /// interop.
- final Map<ClassEntity, String> jsInteropClasses;
-
- /// The JavaScript names for members implemented via typed JavaScript
- /// interop.
- final Map<MemberEntity, String> jsInteropMembers;
-
- NativeDataBuilderImpl(this._nativeBasicData)
- : jsInteropLibraries = _nativeBasicData.jsInteropLibraries,
- jsInteropClasses = _nativeBasicData.jsInteropClasses,
- anonymousJsInteropClasses = _nativeBasicData.anonymousJsInteropClasses,
- jsInteropMembers = _nativeBasicData.jsInteropMembers;
+ NativeDataBuilderImpl(this._nativeBasicData);
/// Sets the native [name] for the member [element]. This name is used for
/// [element] in the generated JavaScript.
+ @override
void setNativeMemberName(MemberEntity element, String name) {
// TODO(johnniwinther): Avoid setting this more than once. The enqueuer
// might enqueue [element] several times (before processing it) and computes
@@ -476,68 +447,26 @@
}
/// Registers the [behavior] for calling the native [method].
+ @override
void setNativeMethodBehavior(FunctionEntity method, NativeBehavior behavior) {
nativeMethodBehavior[method] = behavior;
}
/// Registers the [behavior] for reading from the native [field].
+ @override
void setNativeFieldLoadBehavior(FieldEntity field, NativeBehavior behavior) {
nativeFieldLoadBehavior[field] = behavior;
}
/// Registers the [behavior] for writing to the native [field].
+ @override
void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) {
nativeFieldStoreBehavior[field] = behavior;
}
- /// Sets the explicit js interop [name] for the library [element].
- void setJsInteropLibraryName(LibraryEntity element, String name) {
- assert(
- _nativeBasicData.isJsInteropLibrary(element),
- failedAt(element,
- 'Library $element is not js interop but given a js interop name.'));
- jsInteropLibraries[element] = name;
- }
-
@override
- void markJsInteropClassAsAnonymous(ClassEntity element) {
- anonymousJsInteropClasses.add(element);
- }
-
- /// Sets the explicit js interop [name] for the class [element].
- void setJsInteropClassName(ClassEntity element, String name) {
- assert(
- _nativeBasicData.isJsInteropClass(element),
- failedAt(element,
- 'Class $element is not js interop but given a js interop name.'));
- jsInteropClasses[element] = name;
- }
-
- @override
- void markAsJsInteropMember(MemberEntity element) {
- jsInteropMembers[element] = null;
- }
-
- /// Sets the explicit js interop [name] for the member [element].
- void setJsInteropMemberName(MemberEntity element, String name) {
- assert(
- jsInteropMembers.containsKey(element),
- failedAt(element,
- 'Member $element is not js interop but given a js interop name.'));
- jsInteropMembers[element] = name;
- }
-
- @override
- NativeData close() => new NativeDataImpl(
- _nativeBasicData,
- nativeMemberName,
- nativeMethodBehavior,
- nativeFieldLoadBehavior,
- nativeFieldStoreBehavior,
- jsInteropLibraries,
- anonymousJsInteropClasses,
- jsInteropClasses,
- jsInteropMembers);
+ NativeData close() => new NativeDataImpl(_nativeBasicData, nativeMemberName,
+ nativeMethodBehavior, nativeFieldLoadBehavior, nativeFieldStoreBehavior);
}
// TODO(johnniwinther): Remove fields that overlap with [NativeBasicData], like
@@ -565,31 +494,12 @@
/// Cache for [NativeBehavior]s for writing to native fields.
final Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior;
- /// The JavaScript names for libraries implemented via typed JavaScript
- /// interop.
- final Map<LibraryEntity, String> jsInteropLibraries;
-
- /// JavaScript interop classes annotated with `@anonymous`
- final Set<ClassEntity> anonymousJsInteropClasses;
-
- /// The JavaScript names for classes implemented via typed JavaScript
- /// interop.
- final Map<ClassEntity, String> jsInteropClasses;
-
- /// The JavaScript names for members implemented via typed JavaScript
- /// interop.
- final Map<MemberEntity, String> jsInteropMembers;
-
NativeDataImpl(
this._nativeBasicData,
this.nativeMemberName,
this.nativeMethodBehavior,
this.nativeFieldLoadBehavior,
- this.nativeFieldStoreBehavior,
- this.jsInteropLibraries,
- this.anonymousJsInteropClasses,
- this.jsInteropClasses,
- this.jsInteropMembers);
+ this.nativeFieldStoreBehavior);
factory NativeDataImpl.readFromDataSource(
DataSource source, ElementEnvironment elementEnvironment) {
@@ -604,26 +514,16 @@
.readMemberMap(() => new NativeBehavior.readFromDataSource(source));
Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior = source
.readMemberMap(() => new NativeBehavior.readFromDataSource(source));
- Map<LibraryEntity, String> jsInteropLibraries =
- source.readLibraryMap(source.readString);
- Set<ClassEntity> anonymousJsInteropClasses = source.readClasses().toSet();
- Map<ClassEntity, String> jsInteropClasses =
- source.readClassMap(source.readString);
- Map<MemberEntity, String> jsInteropMembers =
- source.readMemberMap(source.readString);
source.end(tag);
return new NativeDataImpl(
nativeBasicData,
nativeMemberName,
nativeMethodBehavior,
nativeFieldLoadBehavior,
- nativeFieldStoreBehavior,
- jsInteropLibraries,
- anonymousJsInteropClasses,
- jsInteropClasses,
- jsInteropMembers);
+ nativeFieldStoreBehavior);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
_nativeBasicData.writeToDataSink(sink);
@@ -641,65 +541,96 @@
behavior.writeToDataSink(sink);
});
- sink.writeLibraryMap(jsInteropLibraries, sink.writeString);
- sink.writeClasses(anonymousJsInteropClasses);
- sink.writeClassMap(jsInteropClasses, sink.writeString);
- sink.writeMemberMap(jsInteropMembers, sink.writeString);
sink.end(tag);
}
+ /// The JavaScript names for libraries implemented via typed JavaScript
+ /// interop.
+ @override
+ Map<LibraryEntity, String> get jsInteropLibraries =>
+ _nativeBasicData.jsInteropLibraries;
+
+ /// JavaScript interop classes annotated with `@anonymous`
+ @override
+ Set<ClassEntity> get anonymousJsInteropClasses =>
+ _nativeBasicData.anonymousJsInteropClasses;
+
+ /// The JavaScript names for classes implemented via typed JavaScript
+ /// interop.
+ @override
+ Map<ClassEntity, String> get jsInteropClasses =>
+ _nativeBasicData.jsInteropClasses;
+
+ /// The JavaScript names for members implemented via typed JavaScript
+ /// interop.
+ @override
+ Map<MemberEntity, String> get jsInteropMembers =>
+ _nativeBasicData.jsInteropMembers;
+
@override
bool isAnonymousJsInteropClass(ClassEntity element) {
return anonymousJsInteropClasses.contains(element);
}
/// Returns `true` if [cls] is a native class.
+ @override
bool isNativeClass(ClassEntity element) =>
_nativeBasicData.isNativeClass(element);
/// Returns the list of non-directive native tag words for [cls].
+ @override
List<String> getNativeTagsOfClass(ClassEntity cls) =>
_nativeBasicData.getNativeTagsOfClass(cls);
/// Returns `true` if [cls] has a `!nonleaf` tag word.
+ @override
bool hasNativeTagsForcedNonLeaf(ClassEntity cls) =>
_nativeBasicData.hasNativeTagsForcedNonLeaf(cls);
+ @override
bool get isJsInteropUsed => _nativeBasicData.isJsInteropUsed;
/// Returns `true` if [element] is a JsInterop library.
+ @override
bool isJsInteropLibrary(LibraryEntity element) =>
_nativeBasicData.isJsInteropLibrary(element);
/// Returns `true` if [element] is a JsInterop class.
+ @override
bool isJsInteropClass(ClassEntity element) =>
_nativeBasicData.isJsInteropClass(element);
/// Returns `true` if [element] or any of its superclasses is native.
+ @override
bool isNativeOrExtendsNative(ClassEntity element) =>
_nativeBasicData.isNativeOrExtendsNative(element);
/// Returns the explicit js interop name for library [element].
+ @override
String getJsInteropLibraryName(LibraryEntity element) {
return jsInteropLibraries[element];
}
/// Returns the explicit js interop name for class [element].
+ @override
String getJsInteropClassName(ClassEntity element) {
return jsInteropClasses[element];
}
/// Returns the explicit js interop name for member [element].
+ @override
String getJsInteropMemberName(MemberEntity element) {
return jsInteropMembers[element];
}
/// Returns `true` if [element] is explicitly marked as part of JsInterop.
+ @override
bool _isJsInteropMember(MemberEntity element) {
return jsInteropMembers.containsKey(element);
}
/// Returns `true` if [element] is a JsInterop method.
+ @override
bool isJsInteropMember(MemberEntity element) {
if (element.isFunction ||
element.isConstructor ||
@@ -723,12 +654,14 @@
/// Returns `true` if the name of [element] is fixed for the generated
/// JavaScript.
+ @override
bool hasFixedBackendName(MemberEntity element) {
return isJsInteropMember(element) || nativeMemberName.containsKey(element);
}
/// Computes the name for [element] to use in the generated JavaScript. This
/// is either given through a native annotation or a js interop annotation.
+ @override
String getFixedBackendName(MemberEntity element) {
String name = nativeMemberName[element];
if (name == null && isJsInteropMember(element)) {
@@ -774,6 +707,7 @@
/// For example: fixedBackendPath for the static method createMap in the
/// Map class of the goog.map JavaScript library would have path
/// "goog.maps.Map".
+ @override
String getFixedBackendMethodPath(FunctionEntity element) {
if (!isJsInteropMember(element)) return null;
if (element.isInstanceMember) return 'this';
@@ -794,12 +728,14 @@
}
/// Returns `true` if [element] is a native member of a native class.
+ @override
bool isNativeMember(MemberEntity element) {
if (isJsInteropMember(element)) return true;
return nativeMemberName.containsKey(element);
}
/// Returns the [NativeBehavior] for calling the native [method].
+ @override
NativeBehavior getNativeMethodBehavior(FunctionEntity method) {
assert(
nativeMethodBehavior.containsKey(method),
@@ -809,6 +745,7 @@
}
/// Returns the [NativeBehavior] for reading from the native [field].
+ @override
NativeBehavior getNativeFieldLoadBehavior(FieldEntity field) {
assert(
nativeFieldLoadBehavior.containsKey(field),
@@ -820,6 +757,7 @@
}
/// Returns the [NativeBehavior] for writing to the native [field].
+ @override
NativeBehavior getNativeFieldStoreBehavior(FieldEntity field) {
assert(
nativeFieldStoreBehavior.containsKey(field),
@@ -830,6 +768,7 @@
/// Apply JS$ escaping scheme to convert possible escaped Dart names into
/// JS names.
+ @override
String computeUnescapedJSInteropName(String name) {
return name.startsWith(_jsInteropEscapePrefix)
? name.substring(_jsInteropEscapePrefix.length)
@@ -869,13 +808,16 @@
return sb.toString();
}
+ @override
int get hashCode => Hashing.listHash(names, isNonLeaf.hashCode);
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! NativeClassTag) return false;
return equalElements(names, other.names) && isNonLeaf == other.isNonLeaf;
}
+ @override
String toString() => text;
}
diff --git a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
index 3dc3075..b579c07 100644
--- a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
+++ b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
@@ -94,13 +94,17 @@
NoSuchMethodResolver get internalResolverForTesting => _resolver;
+ @override
bool get hasThrowingNoSuchMethod => throwingImpls.isNotEmpty;
+ @override
bool get hasComplexNoSuchMethod => otherImpls.isNotEmpty;
+ @override
void registerNoSuchMethod(FunctionEntity noSuchMethodElement) {
_uncategorizedImpls.add(noSuchMethodElement);
}
+ @override
void onQueueEmpty() {
_uncategorizedImpls.forEach(_categorizeImpl);
_uncategorizedImpls.clear();
@@ -161,6 +165,7 @@
}
}
+ @override
NoSuchMethodData close() {
return new NoSuchMethodDataImpl(
throwingImpls, otherImpls, forwardingSyntaxImpls);
@@ -234,6 +239,7 @@
..complexReturningImpls.addAll(complexReturningImpls);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeMembers(throwingImpls);
@@ -247,6 +253,7 @@
/// Now that type inference is complete, split category D into two
/// subcategories: D1, those that have no return type, and D2, those
/// that have a return type.
+ @override
void categorizeComplexImplementations(GlobalTypeInferenceResults results) {
otherImpls.forEach((FunctionEntity element) {
if (results.resultOfMember(element).throwsAlways) {
@@ -258,6 +265,7 @@
}
/// Emits a diagnostic
+ @override
void emitDiagnostic(DiagnosticReporter reporter) {
throwingImpls.forEach((e) {
if (!forwardingSyntaxImpls.contains(e)) {
@@ -279,6 +287,7 @@
/// Returns [true] if the given element is a complex [noSuchMethod]
/// implementation. An implementation is complex if it falls into
/// category D, as described above.
+ @override
bool isComplex(FunctionEntity element) {
assert(element.name == Identifiers.noSuchMethod_);
return otherImpls.contains(element);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 382475a..e5132c6 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -124,6 +124,7 @@
class TrivialRuntimeTypesNeed implements RuntimeTypesNeed {
const TrivialRuntimeTypesNeed();
+ @override
void writeToDataSink(DataSink sink) {
sink.writeBool(true); // Is trivial.
}
@@ -244,6 +245,7 @@
class TrivialRuntimeTypesChecksBuilder implements RuntimeTypesChecksBuilder {
final JClosedWorld _closedWorld;
final TrivialRuntimeTypesSubstitutions _substitutions;
+ @override
bool rtiChecksBuilderClosed = false;
TrivialRuntimeTypesChecksBuilder(this._closedWorld, this._substitutions);
@@ -299,6 +301,7 @@
ClassCollector(this._elementEnvironment);
+ @override
void addClass(ClassEntity cls) {
if (classes.add(cls)) {
_elementEnvironment.forEachSupertype(cls, (InterfaceType type) {
@@ -633,7 +636,9 @@
}
class TrivialRuntimeTypesSubstitutions extends RuntimeTypesSubstitutionsMixin {
+ @override
final JClosedWorld _closedWorld;
+ @override
TypeChecks _requiredChecks;
TrivialRuntimeTypesSubstitutions(this._closedWorld);
@@ -786,6 +791,7 @@
instantiationsNeedingTypeArguments);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeBool(false); // Is _not_ trivial.
sink.begin(tag);
@@ -802,16 +808,19 @@
bool checkClass(covariant ClassEntity cls) => true;
+ @override
bool classNeedsTypeArguments(ClassEntity cls) {
assert(checkClass(cls));
if (!_elementEnvironment.isGenericClass(cls)) return false;
return classesNeedingTypeArguments.contains(cls);
}
+ @override
bool methodNeedsSignature(FunctionEntity function) {
return methodsNeedingSignature.contains(function);
}
+ @override
bool methodNeedsTypeArguments(FunctionEntity function) {
return methodsNeedingTypeArguments.contains(function);
}
@@ -1398,6 +1407,7 @@
String get kind;
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write(kind);
@@ -1412,8 +1422,10 @@
ClassNode(this.cls);
+ @override
Entity get entity => cls;
+ @override
String get kind => 'class';
}
@@ -1427,6 +1439,7 @@
MethodNode(this.function, this.parameterStructure,
{this.isCallTarget, this.instanceName, this.isNoSuchMethod: false});
+ @override
Entity get entity => function;
bool selectorApplies(Selector selector) {
@@ -1436,8 +1449,10 @@
selector.callStructure.signatureApplies(parameterStructure);
}
+ @override
String get kind => 'method';
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('MethodNode(');
@@ -1892,6 +1907,7 @@
class _RuntimeTypesChecks implements RuntimeTypesChecks {
final RuntimeTypesSubstitutions _substitutions;
+ @override
final TypeChecks requiredChecks;
final Iterable<ClassEntity> _typeLiterals;
final Iterable<ClassEntity> _typeArguments;
@@ -1920,6 +1936,7 @@
class RuntimeTypesImpl extends _RuntimeTypesBase
with RuntimeTypesSubstitutionsMixin
implements RuntimeTypesChecksBuilder {
+ @override
final JClosedWorld _closedWorld;
// The set of type arguments tested against type variable bounds.
@@ -1929,13 +1946,16 @@
TypeChecks cachedRequiredChecks;
+ @override
bool rtiChecksBuilderClosed = false;
RuntimeTypesImpl(this._closedWorld) : super(_closedWorld.dartTypes);
JCommonElements get _commonElements => _closedWorld.commonElements;
+ @override
JElementEnvironment get _elementEnvironment =>
_closedWorld.elementEnvironment;
+ @override
RuntimeTypesNeed get _rtiNeed => _closedWorld.rtiNeed;
@override
@@ -1958,6 +1978,7 @@
_genericInstantiations.add(instantiation);
}
+ @override
RuntimeTypesChecks computeRequiredChecks(
CodegenWorldBuilder codegenWorldBuilder, CompilerOptions options) {
TypeVariableTests typeVariableTests = new TypeVariableTests(
@@ -1979,14 +2000,32 @@
Set<ClassEntity> typeLiterals = new Set<ClassEntity>();
Set<ClassEntity> typeArguments = new Set<ClassEntity>();
+ // The [liveTypeVisitor] is used to register class use in the type of
+ // instantiated objects like `new T` and the function types of
+ // tear offs and closures.
+ //
+ // A type found in a covariant position of such types is considered live
+ // whereas a type found in a contravariant position of such types is
+ // considered tested.
+ //
+ // For instance
+ //
+ // new A<B Function(C)>();
+ //
+ // makes A and B live but C tested.
TypeVisitor liveTypeVisitor =
new TypeVisitor(onClass: (ClassEntity cls, {TypeVisitorState state}) {
ClassUse classUse = classUseMap.putIfAbsent(cls, () => new ClassUse());
switch (state) {
- case TypeVisitorState.typeArgument:
+ case TypeVisitorState.covariantTypeArgument:
classUse.typeArgument = true;
typeArguments.add(cls);
break;
+ case TypeVisitorState.contravariantTypeArgument:
+ classUse.typeArgument = true;
+ classUse.checkedTypeArgument = true;
+ typeArguments.add(cls);
+ break;
case TypeVisitorState.typeLiteral:
classUse.typeLiteral = true;
typeLiterals.add(cls);
@@ -1996,15 +2035,31 @@
}
});
+ // The [testedTypeVisitor] is used to register class use in type tests like
+ // `o is T` and `o as T` (both implicit and explicit).
+ //
+ // A type found in a covariant position of such types is considered tested
+ // whereas a type found in a contravariant position of such types is
+ // considered live.
+ //
+ // For instance
+ //
+ // o is A<B Function(C)>;
+ //
+ // makes A and B tested but C live.
TypeVisitor testedTypeVisitor =
new TypeVisitor(onClass: (ClassEntity cls, {TypeVisitorState state}) {
ClassUse classUse = classUseMap.putIfAbsent(cls, () => new ClassUse());
switch (state) {
- case TypeVisitorState.typeArgument:
+ case TypeVisitorState.covariantTypeArgument:
classUse.typeArgument = true;
classUse.checkedTypeArgument = true;
typeArguments.add(cls);
break;
+ case TypeVisitorState.contravariantTypeArgument:
+ classUse.typeArgument = true;
+ typeArguments.add(cls);
+ break;
case TypeVisitorState.typeLiteral:
break;
case TypeVisitorState.direct:
@@ -2025,31 +2080,32 @@
classUse.directInstance = true;
FunctionType callType = _types.getCallType(type);
if (callType != null) {
- testedTypeVisitor.visitType(callType, TypeVisitorState.direct);
+ liveTypeVisitor.visitType(callType, TypeVisitorState.direct);
}
});
for (FunctionEntity element
in codegenWorldBuilder.staticFunctionsNeedingGetter) {
FunctionType functionType = _elementEnvironment.getFunctionType(element);
- testedTypeVisitor.visitType(functionType, TypeVisitorState.direct);
+ liveTypeVisitor.visitType(functionType, TypeVisitorState.direct);
}
for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) {
FunctionType functionType = _elementEnvironment.getFunctionType(element);
- testedTypeVisitor.visitType(functionType, TypeVisitorState.direct);
+ liveTypeVisitor.visitType(functionType, TypeVisitorState.direct);
}
void processMethodTypeArguments(_, Set<DartType> typeArguments) {
for (DartType typeArgument in typeArguments) {
- liveTypeVisitor.visit(typeArgument, TypeVisitorState.typeArgument);
+ liveTypeVisitor.visit(
+ typeArgument, TypeVisitorState.covariantTypeArgument);
}
}
codegenWorldBuilder.forEachStaticTypeArgument(processMethodTypeArguments);
codegenWorldBuilder.forEachDynamicTypeArgument(processMethodTypeArguments);
codegenWorldBuilder.liveTypeArguments.forEach((DartType type) {
- liveTypeVisitor.visitType(type, TypeVisitorState.typeArgument);
+ liveTypeVisitor.visitType(type, TypeVisitorState.covariantTypeArgument);
});
codegenWorldBuilder.constTypeLiterals.forEach((DartType type) {
liveTypeVisitor.visitType(type, TypeVisitorState.typeLiteral);
@@ -2102,7 +2158,8 @@
DartType bound =
_elementEnvironment.getTypeVariableBound(typeVariable.element);
processCheckedType(bound);
- liveTypeVisitor.visit(bound, TypeVisitorState.typeArgument);
+ liveTypeVisitor.visit(
+ bound, TypeVisitorState.covariantTypeArgument);
}
}
}
@@ -2412,6 +2469,7 @@
jsAst.Expression visit(DartType type, Emitter emitter) =>
type.accept(this, emitter);
+ @override
jsAst.Expression visitTypeVariableType(
TypeVariableType type, Emitter emitter) {
if (typedefBindings != null) {
@@ -2421,6 +2479,7 @@
return onVariable(type);
}
+ @override
jsAst.Expression visitFunctionTypeVariable(
FunctionTypeVariable type, Emitter emitter) {
int position = functionTypeVariables.indexOf(type);
@@ -2428,6 +2487,7 @@
return js.number(functionTypeVariables.length - position - 1);
}
+ @override
jsAst.Expression visitDynamicType(DynamicType type, Emitter emitter) {
return getDynamicValue();
}
@@ -2444,6 +2504,7 @@
return new jsAst.ArrayInitializer(elements);
}
+ @override
jsAst.Expression visitInterfaceType(InterfaceType type, Emitter emitter) {
jsAst.Expression name = getJavaScriptClassName(type.element, emitter);
jsAst.Expression result;
@@ -2508,6 +2569,7 @@
return jsAst.js.expressionTemplateFor("# === -2");
}
+ @override
jsAst.Expression visitFunctionType(FunctionType type, Emitter emitter) {
List<jsAst.Property> properties = <jsAst.Property>[];
@@ -2566,10 +2628,12 @@
return new jsAst.ObjectInitializer(properties);
}
+ @override
jsAst.Expression visitVoidType(VoidType type, Emitter emitter) {
return getVoidValue();
}
+ @override
jsAst.Expression visitTypedefType(TypedefType type, Emitter emitter) {
bool shouldEncode = shouldEncodeTypedef(type);
DartType unaliasedType = type.unaliased;
@@ -2646,6 +2710,7 @@
class TypeCheckMapping implements TypeChecks {
final Map<ClassEntity, ClassChecks> map = new Map<ClassEntity, ClassChecks>();
+ @override
ClassChecks operator [](ClassEntity element) {
ClassChecks result = map[element];
return result != null ? result : const ClassChecks.empty();
@@ -2655,8 +2720,10 @@
map[element] = checks;
}
+ @override
Iterable<ClassEntity> get classes => map.keys;
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
for (ClassEntity holder in classes) {
@@ -2687,15 +2754,18 @@
}
}
+ @override
visitTypedefType(TypedefType type, bool isTypeArgument) {
collect(type.unaliased, isTypeArgument: isTypeArgument);
}
+ @override
visitInterfaceType(InterfaceType type, bool isTypeArgument) {
if (isTypeArgument) addClass(type.element);
collectAll(type.typeArguments, isTypeArgument: true);
}
+ @override
visitFunctionType(FunctionType type, _) {
collect(type.returnType, isTypeArgument: true);
collectAll(type.parameterTypes, isTypeArgument: true);
@@ -2719,10 +2789,12 @@
}
}
+ @override
visitTypedefType(TypedefType type, bool inFunctionType) {
collect(type.unaliased, inFunctionType: inFunctionType);
}
+ @override
visitInterfaceType(InterfaceType type, bool inFunctionType) {
if (inFunctionType) {
classes.add(type.element);
@@ -2730,6 +2802,7 @@
collectAll(type.typeArguments, inFunctionType: inFunctionType);
}
+ @override
visitFunctionType(FunctionType type, _) {
collect(type.returnType, inFunctionType: true);
collectAll(type.parameterTypes, inFunctionType: true);
@@ -2780,6 +2853,7 @@
bool get isJsInterop => length != null;
+ @override
String toString() => 'Substitution(isTrivial=$isTrivial,'
'isFunction=$isFunction,isJsInterop=$isJsInterop,arguments=$arguments,'
'parameters=$parameters,length=$length)';
@@ -2791,16 +2865,23 @@
final ClassEntity cls;
final bool needsIs;
final Substitution substitution;
+ @override
final int hashCode = _nextHash = (_nextHash + 100003).toUnsigned(30);
static int _nextHash = 0;
TypeCheck(this.cls, this.substitution, {this.needsIs: true});
+ @override
String toString() =>
'TypeCheck(cls=$cls,needsIs=$needsIs,substitution=$substitution)';
}
-enum TypeVisitorState { direct, typeArgument, typeLiteral }
+enum TypeVisitorState {
+ direct,
+ covariantTypeArgument,
+ contravariantTypeArgument,
+ typeLiteral,
+}
class TypeVisitor extends DartTypeVisitor<void, TypeVisitorState> {
Set<FunctionTypeVariable> _visitedFunctionTypeVariables =
@@ -2816,6 +2897,34 @@
visitType(DartType type, TypeVisitorState state) => type.accept(this, state);
+ TypeVisitorState covariantArgument(TypeVisitorState state) {
+ switch (state) {
+ case TypeVisitorState.direct:
+ return TypeVisitorState.covariantTypeArgument;
+ case TypeVisitorState.covariantTypeArgument:
+ return TypeVisitorState.covariantTypeArgument;
+ case TypeVisitorState.contravariantTypeArgument:
+ return TypeVisitorState.contravariantTypeArgument;
+ case TypeVisitorState.typeLiteral:
+ return TypeVisitorState.typeLiteral;
+ }
+ throw new UnsupportedError("Unexpected TypeVisitorState $state");
+ }
+
+ TypeVisitorState contravariantArgument(TypeVisitorState state) {
+ switch (state) {
+ case TypeVisitorState.direct:
+ return TypeVisitorState.contravariantTypeArgument;
+ case TypeVisitorState.covariantTypeArgument:
+ return TypeVisitorState.contravariantTypeArgument;
+ case TypeVisitorState.contravariantTypeArgument:
+ return TypeVisitorState.covariantTypeArgument;
+ case TypeVisitorState.typeLiteral:
+ return TypeVisitorState.typeLiteral;
+ }
+ throw new UnsupportedError("Unexpected TypeVisitorState $state");
+ }
+
visitTypes(List<DartType> types, TypeVisitorState state) {
for (DartType type in types) {
visitType(type, state);
@@ -2834,11 +2943,7 @@
if (onClass != null) {
onClass(type.element, state: state);
}
- visitTypes(
- type.typeArguments,
- state == TypeVisitorState.typeLiteral
- ? state
- : TypeVisitorState.typeArgument);
+ visitTypes(type.typeArguments, covariantArgument(state));
}
@override
@@ -2848,13 +2953,10 @@
}
// Visit all nested types as type arguments; these types are not runtime
// instances but runtime type representations.
- state = state == TypeVisitorState.typeLiteral
- ? state
- : TypeVisitorState.typeArgument;
- visitType(type.returnType, state);
- visitTypes(type.parameterTypes, state);
- visitTypes(type.optionalParameterTypes, state);
- visitTypes(type.namedParameterTypes, state);
+ visitType(type.returnType, covariantArgument(state));
+ visitTypes(type.parameterTypes, contravariantArgument(state));
+ visitTypes(type.optionalParameterTypes, contravariantArgument(state));
+ visitTypes(type.namedParameterTypes, contravariantArgument(state));
_visitedFunctionTypeVariables.removeAll(type.typeVariables);
}
@@ -2891,6 +2993,7 @@
Iterable<TypeCheck> get checks => _map.values;
+ @override
String toString() {
return 'ClassChecks($checks)';
}
@@ -2985,6 +3088,7 @@
/// type arguments.
bool get isLive => directInstance || typeArgument;
+ @override
String toString() {
List<String> properties = <String>[];
if (instance) {
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index fb31e92..81b9f9e 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -9,6 +9,7 @@
import '../elements/entities.dart';
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
+import '../js_backend/field_analysis.dart';
import '../js_backend/namer.dart' show Namer;
import '../js_backend/interceptor_data.dart' show InterceptorData;
import '../options.dart';
@@ -108,8 +109,14 @@
}
return js('#.#()', [receiver, getterName]);
} else {
- jsAst.Name fieldName = _namer.instanceFieldPropertyName(member);
- return js('#.#', [receiver, fieldName]);
+ FieldAnalysisData fieldData =
+ _closedWorld.fieldAnalysis.getFieldData(member);
+ if (fieldData.isEffectivelyConstant) {
+ return _emitter.constantReference(fieldData.constantValue);
+ } else {
+ jsAst.Name fieldName = _namer.instanceFieldPropertyName(member);
+ return js('#.#', [receiver, fieldName]);
+ }
}
}
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 987d957..0320701 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -67,6 +67,7 @@
return _emitter;
}
+ @override
String get name => 'Code emitter';
/// Returns true, if the emitter supports reflection.
@@ -268,6 +269,7 @@
}
abstract class EmitterBase implements Emitter {
+ @override
Program programForTesting;
Namer get namer;
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index 9b4aed2..9306361 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -27,6 +27,7 @@
_dartTypeOrdering = new _DartTypeOrdering(this);
}
+ @override
int compare(ConstantValue a, ConstantValue b) => compareValues(a, b);
int compareValues(ConstantValue a, ConstantValue b) {
@@ -75,38 +76,46 @@
return _dartTypeOrdering.compare(a, b);
}
+ @override
int visitFunction(FunctionConstantValue a, FunctionConstantValue b) {
return compareMembers(a.element, b.element);
}
+ @override
int visitNull(NullConstantValue a, NullConstantValue b) {
return 0;
}
+ @override
int visitNonConstant(NonConstantValue a, NonConstantValue b) {
return 0;
}
+ @override
int visitInt(IntConstantValue a, IntConstantValue b) {
return a.intValue.compareTo(b.intValue);
}
+ @override
int visitDouble(DoubleConstantValue a, DoubleConstantValue b) {
return a.doubleValue.compareTo(b.doubleValue);
}
+ @override
int visitBool(BoolConstantValue a, BoolConstantValue b) {
int aInt = a.boolValue ? 1 : 0;
int bInt = b.boolValue ? 1 : 0;
return aInt.compareTo(bInt);
}
+ @override
int visitString(StringConstantValue a, StringConstantValue b) {
String aString = a.stringValue;
String bString = b.stringValue;
return aString.compareTo(bString);
}
+ @override
int visitList(ListConstantValue a, ListConstantValue b) {
int r = compareLists(compareValues, a.entries, b.entries);
if (r != 0) return r;
@@ -120,6 +129,7 @@
return compareDartTypes(a.type, b.type);
}
+ @override
int visitMap(MapConstantValue a, MapConstantValue b) {
int r = compareLists(compareValues, a.keys, b.keys);
if (r != 0) return r;
@@ -128,6 +138,7 @@
return compareDartTypes(a.type, b.type);
}
+ @override
int visitConstructed(ConstructedConstantValue a, ConstructedConstantValue b) {
int r = compareDartTypes(a.type, b.type);
if (r != 0) return r;
@@ -145,16 +156,19 @@
aFields.map((field) => b.fields[field]).toList());
}
+ @override
int visitType(TypeConstantValue a, TypeConstantValue b) {
int r = compareDartTypes(a.representedType, b.representedType);
if (r != 0) return r;
return compareDartTypes(a.type, b.type);
}
+ @override
int visitInterceptor(InterceptorConstantValue a, InterceptorConstantValue b) {
return compareClasses(a.cls, b.cls);
}
+ @override
int visitSynthetic(SyntheticConstantValue a, SyntheticConstantValue b) {
// [SyntheticConstantValue]s have abstract fields that are set only by
// convention. Lucky for us, they do not occur as top level constant, only
@@ -183,6 +197,7 @@
}
}
+ @override
int visitDeferredGlobal(
DeferredGlobalConstantValue a, DeferredGlobalConstantValue b) {
int r = compareValues(a.referenced, b.referenced);
@@ -190,6 +205,7 @@
return a.unit.compareTo(b.unit);
}
+ @override
int visitInstantiation(
InstantiationConstantValue a, InstantiationConstantValue b) {
int r = compareValues(a.function, b.function);
@@ -221,21 +237,37 @@
static int kind(ConstantValue constant) =>
constant.accept(const _KindVisitor(), null);
+ @override
int visitFunction(FunctionConstantValue a, _) => FUNCTION;
+ @override
int visitNull(NullConstantValue a, _) => NULL;
+ @override
int visitNonConstant(NonConstantValue a, _) => NONCONSTANT;
+ @override
int visitInt(IntConstantValue a, _) => INT;
+ @override
int visitDouble(DoubleConstantValue a, _) => DOUBLE;
+ @override
int visitBool(BoolConstantValue a, _) => BOOL;
+ @override
int visitString(StringConstantValue a, _) => STRING;
+ @override
int visitList(ListConstantValue a, _) => LIST;
+ @override
int visitSet(SetConstantValue a, _) => SET;
+ @override
int visitMap(MapConstantValue a, _) => MAP;
+ @override
int visitConstructed(ConstructedConstantValue a, _) => CONSTRUCTED;
+ @override
int visitType(TypeConstantValue a, _) => TYPE;
+ @override
int visitInterceptor(InterceptorConstantValue a, _) => INTERCEPTOR;
+ @override
int visitSynthetic(SyntheticConstantValue a, _) => SYNTHETIC;
+ @override
int visitDeferredGlobal(DeferredGlobalConstantValue a, _) => DEFERRED_GLOBAL;
+ @override
int visitInstantiation(InstantiationConstantValue a, _) => INSTANTIATION;
}
@@ -247,11 +279,17 @@
return type.accept(const _DartTypeKindVisitor(), null);
}
+ @override
int visitVoidType(covariant VoidType type, _) => 6;
+ @override
int visitTypeVariableType(covariant TypeVariableType type, _) => 3;
+ @override
int visitFunctionType(covariant FunctionType type, _) => 0;
+ @override
int visitInterfaceType(covariant InterfaceType type, _) => 1;
+ @override
int visitTypedefType(covariant TypedefType type, _) => 2;
+ @override
int visitDynamicType(covariant DynamicType type, _) => 5;
}
@@ -271,16 +309,19 @@
return r;
}
+ @override
int visitVoidType(covariant VoidType type, covariant VoidType other) {
throw new UnsupportedError('Unreachable');
}
+ @override
int visitTypeVariableType(
covariant TypeVariableType type, covariant TypeVariableType other) {
throw new UnsupportedError(
"Type variables are not expected in constants: '$type' in '$_root'");
}
+ @override
int visitFunctionType(
covariant FunctionType type, covariant FunctionType other) {
int r = _compareTypeArguments(type.parameterTypes, other.parameterTypes);
@@ -297,6 +338,7 @@
return compare(type.returnType, other.returnType);
}
+ @override
int visitInterfaceType(
covariant InterfaceType type, covariant InterfaceType other) {
int r = _constantOrdering.compareClasses(type.element, other.element);
@@ -304,6 +346,7 @@
return _compareTypeArguments(type.typeArguments, other.typeArguments);
}
+ @override
int visitTypedefType(
covariant TypedefType type, covariant TypedefType other) {
int r = _constantOrdering.compareTypedefs(type.element, other.element);
@@ -311,6 +354,7 @@
return _compareTypeArguments(type.typeArguments, other.typeArguments);
}
+ @override
int visitDynamicType(
covariant DynamicType type, covariant DynamicType other) {
throw new UnsupportedError('Unreachable');
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index db2d3c0..39b2574 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -29,18 +29,22 @@
abstract class _MetadataEntry extends jsAst.DeferredNumber
implements Comparable, jsAst.ReferenceCountedAstNode {
jsAst.Expression get entry;
+ @override
int get value;
int get _rc;
// Mark this entry as seen. On the first time this is seen, the visitor
// will be applied to the [entry] to also mark potential [_MetadataEntry]
// instances in the [entry] as seen.
+ @override
markSeen(jsAst.TokenCounter visitor);
}
class _BoundMetadataEntry extends _MetadataEntry {
int _value = -1;
+ @override
int _rc = 0;
+ @override
final jsAst.Expression entry;
_BoundMetadataEntry(this.entry);
@@ -52,6 +56,7 @@
_value = value;
}
+ @override
int get value {
assert(isFinalized);
return _value;
@@ -59,13 +64,16 @@
bool get isUsed => _rc > 0;
+ @override
markSeen(jsAst.BaseVisitor visitor) {
_rc++;
if (_rc == 1) entry.accept(visitor);
}
+ @override
int compareTo(covariant _MetadataEntry other) => other._rc - this._rc;
+ @override
String toString() => '_BoundMetadataEntry($hashCode,rc=$_rc,_value=$_value)';
}
@@ -78,11 +86,13 @@
_value = value;
}
+ @override
jsAst.Expression get value {
assert(_value != null);
return _value;
}
+ @override
int get precedenceLevel => js_precedence.PRIMARY;
}
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 6f7b580..247a1ef 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -83,6 +83,7 @@
Holder(this.name, this.index,
{this.isStaticStateHolder: false, this.isConstantsHolder: false});
+ @override
String toString() {
return 'Holder(name=${name})';
}
@@ -136,8 +137,10 @@
: super(outputUnit, outputFileName, libraries, staticNonFinalFields,
staticLazilyInitializedFields, constants);
+ @override
bool get isMainFragment => true;
+ @override
String toString() {
return 'MainFragment()';
}
@@ -158,8 +161,10 @@
: super(outputUnit, outputFileName, libraries, staticNonFinalFields,
staticLazilyInitializedFields, constants);
+ @override
bool get isMainFragment => false;
+ @override
String toString() {
return 'DeferredFragment(name=${name})';
}
@@ -172,6 +177,7 @@
Constant(this.name, this.holder, this.value);
+ @override
String toString() {
return 'Constant(name=${name.key},value=${value.toStructuredText()})';
}
@@ -190,11 +196,13 @@
final List<StaticMethod> statics;
final List<Class> classes;
+ @override
final List<Field> staticFieldsForReflection;
Library(this.element, this.uri, this.statics, this.classes,
this.staticFieldsForReflection);
+ @override
String toString() {
return 'Library(uri=${uri},element=${element})';
}
@@ -213,10 +221,12 @@
final js.Expression code;
final bool isFinal;
final bool isLazy;
+ final bool isInitializedByConstant;
StaticField(this.element, this.name, this.getterName, this.holder, this.code,
- this.isFinal, this.isLazy);
+ {this.isFinal, this.isLazy, this.isInitializedByConstant: false});
+ @override
String toString() {
return 'StaticField(name=${name.key},element=${element})';
}
@@ -241,6 +251,7 @@
/// noSuchMethod stubs in the special case that the class is Object.
final List<StubMethod> noSuchMethodStubs;
+ @override
final List<Field> staticFieldsForReflection;
final bool hasRtiField; // Per-instance runtime type information pseudo-field.
final bool onlyForRti;
@@ -315,6 +326,7 @@
int get superclassHolderIndex =>
(superclass == null) ? 0 : superclass.holder.index;
+ @override
String toString() => 'Class(name=${name.key},element=$element)';
}
@@ -351,8 +363,10 @@
isClosureBaseClass: false,
isSuperMixinApplication: false);
+ @override
bool get isSimpleMixinApplication => true;
+ @override
String toString() => 'Mixin(name=${name.key},element=$element)';
}
@@ -412,6 +426,7 @@
bool get needsInterceptedGetterOnThis => getterFlags == 3;
bool get needsInterceptedSetterOnThis => setterFlags == 3;
+ @override
String toString() {
return 'Field(name=${name.key},element=${element})';
}
@@ -519,8 +534,10 @@
assert(isClosureCallMethod != null);
}
+ @override
bool get isStatic => false;
+ @override
String toString() {
return 'InstanceMethod(name=${name.key},element=${element}'
',code=${js.nodeToString(code)})';
@@ -534,6 +551,7 @@
StubMethod(js.Name name, js.Expression code, {MemberEntity element})
: super(element, name, code);
+ @override
String toString() {
return 'StubMethod(name=${name.key},element=${element}'
',code=${js.nodeToString(code)})';
@@ -561,6 +579,7 @@
{MemberEntity element})
: super(name, code, element: element);
+ @override
String toString() {
return 'ParameterStubMethod(name=${name.key}, callName=${callName?.key}'
', element=${element}'
@@ -573,6 +592,7 @@
}
class StaticDartMethod extends DartMethod implements StaticMethod {
+ @override
final Holder holder;
StaticDartMethod(
@@ -598,8 +618,10 @@
functionType: functionType,
applyIndex: applyIndex);
+ @override
bool get isStatic => true;
+ @override
String toString() {
return 'StaticDartMethod(name=${name.key},element=${element}'
',code=${js.nodeToString(code)})';
@@ -607,10 +629,12 @@
}
class StaticStubMethod extends StubMethod implements StaticMethod {
+ @override
Holder holder;
StaticStubMethod(js.Name name, this.holder, js.Expression code)
: super(name, code);
+ @override
String toString() {
return 'StaticStubMethod(name=${name.key},element=${element}}'
',code=${js.nodeToString(code)})';
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index d74d9c7..d0e09c8 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -263,22 +263,36 @@
void computeNeededStaticNonFinalFields() {
addToOutputUnit(FieldEntity element) {
List<FieldEntity> list = outputStaticNonFinalFieldLists.putIfAbsent(
- // ignore: UNNECESSARY_CAST
- _outputUnitData.outputUnitForMember(element as MemberEntity),
+ _outputUnitData.outputUnitForMember(element),
() => new List<FieldEntity>());
list.add(element);
}
- Iterable<FieldEntity> fields =
+ List<FieldEntity> fields =
// TODO(johnniwinther): This should be accessed from a codegen closed
// world.
_worldBuilder.allReferencedStaticFields.where((FieldEntity field) {
- FieldAnalysisData fieldData =
- _closedWorld.fieldAnalysis.getFieldData(field);
- return !fieldData.isEffectivelyFinal && fieldData.initialValue != null;
- });
+ return _closedWorld.fieldAnalysis.getFieldData(field).isEager;
+ }).toList();
- _sorter.sortMembers(fields).forEach((MemberEntity e) => addToOutputUnit(e));
+ fields.sort((FieldEntity a, FieldEntity b) {
+ FieldAnalysisData aFieldData = _closedWorld.fieldAnalysis.getFieldData(a);
+ FieldAnalysisData bFieldData = _closedWorld.fieldAnalysis.getFieldData(b);
+ int aIndex = aFieldData.eagerCreationIndex;
+ int bIndex = bFieldData.eagerCreationIndex;
+ if (aIndex != null && bIndex != null) {
+ return aIndex.compareTo(bIndex);
+ } else if (aIndex != null) {
+ // Sort [b] before [a].
+ return 1;
+ } else if (bIndex != null) {
+ // Sort [a] before [b].
+ return -1;
+ } else {
+ return _sorter.compareMembersByLocation(a, b);
+ }
+ });
+ fields.forEach(addToOutputUnit);
}
void computeNeededLibraries() {
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index efd77cd..bbf43e4 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -409,21 +409,28 @@
StaticField _buildStaticField(FieldEntity element) {
FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(element);
ConstantValue initialValue = fieldData.initialValue;
- // TODO(zarah): The holder should not be registered during building of
- // a static field.
- _registry.registerHolder(_namer.globalObjectForConstant(initialValue),
- isConstantsHolder: true);
- js.Expression code = _task.emitter.constantReference(initialValue);
+ js.Expression code;
+ if (initialValue != null) {
+ // TODO(zarah): The holder should not be registered during building of
+ // a static field.
+ _registry.registerHolder(_namer.globalObjectForConstant(initialValue),
+ isConstantsHolder: true);
+ code = _task.emitter.constantReference(initialValue);
+ } else {
+ assert(fieldData.isEager);
+ code = _generatedCode[element];
+ }
js.Name name = _namer.globalPropertyNameForMember(element);
- bool isFinal = false;
- bool isLazy = false;
// TODO(floitsch): we shouldn't update the registry in the middle of
// building a static field. (Note that the static-state holder was
// already registered earlier, and that we just call the register to get
// the holder-instance.
- return new StaticField(element, name, null, _registerStaticStateHolder(),
- code, isFinal, isLazy);
+ return new StaticField(
+ element, name, null, _registerStaticStateHolder(), code,
+ isFinal: false,
+ isLazy: false,
+ isInitializedByConstant: initialValue != null);
}
List<StaticField> _buildStaticLazilyInitializedFields(
@@ -449,14 +456,13 @@
js.Name name = _namer.globalPropertyNameForMember(element);
js.Name getterName = _namer.lazyInitializerName(element);
- bool isFinal = !element.isAssignable;
- bool isLazy = true;
// TODO(floitsch): we shouldn't update the registry in the middle of
// building a static field. (Note that the static-state holder was
// already registered earlier, and that we just call the register to get
// the holder-instance.
- return new StaticField(element, name, getterName,
- _registerStaticStateHolder(), code, isFinal, isLazy);
+ return new StaticField(
+ element, name, getterName, _registerStaticStateHolder(), code,
+ isFinal: !element.isAssignable, isLazy: true);
}
List<Library> _buildLibraries(LibrariesMap librariesMap) {
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index f6be1c1..75acab7 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -41,6 +41,7 @@
class Emitter extends emitterTask.EmitterBase {
final Compiler _compiler;
final JClosedWorld _closedWorld;
+ @override
final Namer namer;
final ModelEmitter _emitter;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index e47c77a..a1ba755 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -434,14 +434,16 @@
// Instantiates all constants.
#constants;
+
+// Emits the embedded globals. Due to type checks in eager initializers this is
+// needed before static non-final fields initializers.
+#embeddedGlobals;
+
// Initializes the static non-final fields (with their constant values).
#staticNonFinalFields;
// Creates lazy getters for statics that must run initializers on first access.
#lazyStatics;
-// Emits the embedded globals.
-#embeddedGlobals;
-
// Sets up the native support.
// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
#nativeSupport;
@@ -1605,8 +1607,43 @@
//
Iterable<js.Statement> statements = fields.map((StaticField field) {
assert(field.holder.isStaticStateHolder);
- js.Statement statement = js.js
- .statement("#.# = #;", [field.holder.name, field.name, field.code]);
+ js.Statement statement;
+ if (field.isInitializedByConstant) {
+ statement = js.js
+ .statement("#.# = #;", [field.holder.name, field.name, field.code]);
+ } else {
+ // This is a bit of a hack. Field initializers are generated as a
+ // function ending with a return statement. We replace the function
+ // with the body block and replace the return statement with an
+ // assignment to the field.
+ //
+ // Since unneeded blocks are not generated in the output,
+ // the statement(s) of the initializes are inlined in the emitted code.
+ //
+ // This is a cheap way of supporting eager fields (as opposed to
+ // generating one SSA graph for all eager fields) though it does not
+ // avoid redundant declaration of local variable, for instance for
+ // type arguments.
+ js.Fun code = field.code;
+ if (code.params.isEmpty &&
+ code.body.statements.length == 1 &&
+ code.body.statements.last is js.Return) {
+ // For now we only support initializers of the form
+ //
+ // function() { return e; }
+ //
+ // To avoid unforeseen consequences of having parameters and locals
+ // in the initializer code.
+ js.Return last = code.body.statements.last;
+ statement = js.js.statement(
+ "#.# = #;", [field.holder.name, field.name, last.value]);
+ } else {
+ // Safe fallback in the event of a field initializer with no return
+ // statement as the last statement.
+ statement = js.js
+ .statement("#.# = #();", [field.holder.name, field.name, code]);
+ }
+ }
registerEntityAst(field.element, statement,
library: field.element.library);
return statement;
@@ -1957,10 +1994,12 @@
_value = value;
}
+ @override
js.Expression get value {
assert(_value != null);
return _value;
}
+ @override
int get precedenceLevel => js_precedence.PRIMARY;
}
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 5582d45..d3295fe 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -64,6 +64,7 @@
}
/// Serializes this [ClosureData] to [sink].
+ @override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeMemberMap(
@@ -430,6 +431,7 @@
static const String tag = 'scope-info';
final Iterable<Local> localsUsedInTryOrSync;
+ @override
final Local thisLocal;
final Map<Local, JRecordField> boxedVariables;
@@ -455,15 +457,18 @@
}
}
+ @override
void forEachBoxedVariable(f(Local local, FieldEntity field)) {
boxedVariables.forEach((Local l, JRecordField box) {
f(l, box);
});
}
+ @override
bool localIsUsedInTryOrSync(Local variable) =>
localsUsedInTryOrSync.contains(variable);
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('this=$thisLocal,');
@@ -471,6 +476,7 @@
return sb.toString();
}
+ @override
bool isBoxedVariable(Local variable) => boxedVariables.containsKey(variable);
factory JsScopeInfo.readFromDataSource(DataSource source) {
@@ -502,6 +508,7 @@
/// debugging data stream.
static const String tag = 'captured-scope';
+ @override
final Local context;
JsCapturedScope.internal(
@@ -522,6 +529,7 @@
boxedVariables.isNotEmpty ? boxedVariables.values.first.box : null,
super.from(boxedVariables, capturedScope, localsMap, elementMap);
+ @override
bool get requiresContextBox => boxedVariables.isNotEmpty;
factory JsCapturedScope.readFromDataSource(DataSource source) {
@@ -555,6 +563,7 @@
/// debugging data stream.
static const String tag = 'captured-loop-scope';
+ @override
final List<Local> boxedLoopVariables;
JsCapturedLoopScope.internal(
@@ -577,6 +586,7 @@
.toList(),
super.from(boxedVariables, capturedScope, localsMap, elementMap);
+ @override
bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
factory JsCapturedLoopScope.readFromDataSource(DataSource source) {
@@ -615,10 +625,14 @@
/// debugging data stream.
static const String tag = 'closure-representation-info';
+ @override
JFunction callMethod;
JSignatureMethod signatureMethod;
+ @override
final Local closureEntity;
+ @override
final Local thisLocal;
+ @override
final JClass closureClassEntity;
final Map<Local, JField> localToFieldMap;
@@ -674,6 +688,7 @@
localToFieldMap);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(ScopeInfoKind.closureRepresentationInfo);
sink.begin(tag);
@@ -689,6 +704,7 @@
sink.end(tag);
}
+ @override
List<Local> get createdFieldEntities => localToFieldMap.keys.toList();
@override
@@ -702,13 +718,16 @@
return null;
}
+ @override
FieldEntity get thisFieldEntity => localToFieldMap[thisLocal];
+ @override
void forEachFreeVariable(f(Local variable, JField field)) {
localToFieldMap.forEach(f);
boxedVariables.forEach(f);
}
+ @override
bool get isClosure => true;
}
@@ -728,6 +747,7 @@
return new JClosureClass(library, name);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JClassKind.closure);
sink.begin(tag);
@@ -739,6 +759,7 @@
@override
bool get isClosure => true;
+ @override
String toString() => '${jsElementPrefix}closure_class($name)';
}
@@ -747,16 +768,20 @@
AnonymousClosureLocal(this.closureClass);
+ @override
String get name => '';
+ @override
int get hashCode => closureClass.hashCode * 13;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! AnonymousClosureLocal) return false;
return closureClass == other.closureClass;
}
+ @override
String toString() =>
'${jsElementPrefix}anonymous_closure_local(${closureClass.name})';
}
@@ -766,6 +791,7 @@
/// debugging data stream.
static const String tag = 'closure-field';
+ @override
final String declaredName;
JClosureField(
@@ -894,6 +920,7 @@
return new JRecord(library, name);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JClassKind.record);
sink.begin(tag);
@@ -902,8 +929,10 @@
sink.end(tag);
}
+ @override
bool get isClosure => false;
+ @override
String toString() => '${jsElementPrefix}record_container($name)';
}
@@ -991,6 +1020,7 @@
/// debugging data stream.
static const String tag = 'closure-class-definition';
+ @override
final SourceSpan location;
ClosureClassDefinition(this.location);
@@ -1010,20 +1040,25 @@
sink.end(tag);
}
+ @override
ClassKind get kind => ClassKind.closure;
+ @override
ir.Node get node =>
throw new UnsupportedError('ClosureClassDefinition.node for $location');
+ @override
String toString() => 'ClosureClassDefinition(kind:$kind,location:$location)';
}
abstract class ClosureMemberData implements JMemberData {
+ @override
final MemberDefinition definition;
final InterfaceType memberThisType;
ClosureMemberData(this.definition, this.memberThisType);
+ @override
Map<ir.Expression, ir.DartType> get staticTypes {
// The cached types are stored in the data for enclosing member.
throw new UnsupportedError("ClosureMemberData.staticTypes");
@@ -1043,7 +1078,9 @@
static const String tag = 'closure-function-data';
final FunctionType functionType;
+ @override
final ir.FunctionNode functionNode;
+ @override
final ClassTypeVariableAccess classTypeVariableAccess;
ClosureFunctionData(
@@ -1068,6 +1105,7 @@
functionNode, classTypeVariableAccess);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JMemberDataKind.closureFunction);
sink.begin(tag);
@@ -1104,6 +1142,7 @@
return new ClosureFieldData(definition, memberThisType);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JMemberDataKind.closureField);
sink.begin(tag);
@@ -1157,8 +1196,11 @@
/// debugging data stream.
static const String tag = 'closure-member-definition';
+ @override
final SourceSpan location;
+ @override
final MemberKind kind;
+ @override
final ir.TreeNode node;
ClosureMemberDefinition(this.location, this.kind, this.node)
@@ -1174,6 +1216,7 @@
return new ClosureMemberDefinition(location, kind, node);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(kind);
sink.begin(tag);
@@ -1182,6 +1225,7 @@
sink.end(tag);
}
+ @override
String toString() => 'ClosureMemberDefinition(kind:$kind,location:$location)';
}
@@ -1190,6 +1234,7 @@
/// a debugging data stream.
static const String tag = 'record-definition';
+ @override
final SourceSpan location;
RecordContainerDefinition(this.location);
@@ -1209,11 +1254,14 @@
sink.end(tag);
}
+ @override
ClassKind get kind => ClassKind.record;
+ @override
ir.Node get node => throw new UnsupportedError(
'RecordContainerDefinition.node for $location');
+ @override
String toString() =>
'RecordContainerDefinition(kind:$kind,location:$location)';
}
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 9371d5c..2afbce4 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -384,6 +384,7 @@
/// debugging data stream.
static const String tag = 'regular-member-definition';
+ @override
final ir.Member node;
RegularMemberDefinition(this.node);
@@ -403,10 +404,13 @@
sink.end(tag);
}
+ @override
SourceSpan get location => computeSourceSpanFromTreeNode(node);
+ @override
MemberKind get kind => MemberKind.regular;
+ @override
String toString() => 'RegularMemberDefinition(kind:$kind,'
'node:$node,location:$location)';
}
@@ -417,7 +421,9 @@
/// debugging data stream.
static const String tag = 'special-member-definition';
+ @override
final ir.TreeNode node;
+ @override
final MemberKind kind;
SpecialMemberDefinition(this.node, this.kind);
@@ -438,8 +444,10 @@
sink.end(tag);
}
+ @override
SourceSpan get location => computeSourceSpanFromTreeNode(node);
+ @override
String toString() => 'SpecialMemberDefinition(kind:$kind,'
'node:$node,location:$location)';
}
@@ -480,6 +488,7 @@
/// debugging data stream.
static const String tag = 'regular-class-definition';
+ @override
final ir.Class node;
RegularClassDefinition(this.node);
@@ -491,6 +500,7 @@
return new RegularClassDefinition(node);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(kind);
sink.begin(tag);
@@ -498,10 +508,13 @@
sink.end(tag);
}
+ @override
SourceSpan get location => computeSourceSpanFromTreeNode(node);
+ @override
ClassKind get kind => ClassKind.regular;
+ @override
String toString() => 'RegularClassDefinition(kind:$kind,'
'node:$node,location:$location)';
}
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 31e729e..10db057 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -88,6 +88,7 @@
static const String nestedClosuresTag = 'nested-closures';
final CompilerOptions options;
+ @override
final DiagnosticReporter reporter;
CommonElementsImpl _commonElements;
JsElementEnvironment _elementEnvironment;
@@ -483,8 +484,10 @@
sink.end(tag);
}
+ @override
DartTypes get types => _types;
+ @override
JsElementEnvironment get elementEnvironment => _elementEnvironment;
@override
@@ -597,11 +600,13 @@
return new InterfaceType(getClass(cls), getDartTypes(typeArguments));
}
+ @override
LibraryEntity getLibrary(ir.Library node) => getLibraryInternal(node);
@override
ClassEntity getClass(ir.Class node) => getClassInternal(node);
+ @override
InterfaceType getSuperType(IndexedClass cls) {
assert(checkFamily(cls));
JClassData data = classes.getData(cls);
@@ -632,6 +637,7 @@
}
}
+ @override
TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
getTypeVariableInternal(node);
@@ -732,6 +738,7 @@
throw new UnsupportedError("Unexpected member: $node");
}
+ @override
MemberEntity getSuperMember(MemberEntity context, ir.Name name,
{bool setter: false}) {
// We can no longer trust the interface target of the super access since it
@@ -788,9 +795,11 @@
@override
DartType getDartType(ir.DartType type) => _typeConverter.convert(type);
+ @override
TypeVariableType getTypeVariableType(ir.TypeParameterType type) =>
getDartType(type);
+ @override
List<DartType> getDartTypes(List<ir.DartType> types) {
List<DartType> list = <DartType>[];
types.forEach((ir.DartType type) {
@@ -799,6 +808,7 @@
return list;
}
+ @override
InterfaceType getInterfaceType(ir.InterfaceType type) =>
_typeConverter.convert(type);
@@ -876,6 +886,7 @@
constantRequired: requireConstant);
}
+ @override
DartType substByContext(DartType type, InterfaceType context) {
return type.subst(
context.typeArguments, getThisType(context.element).typeArguments);
@@ -886,6 +897,7 @@
/// If [type] doesn't have a `call` member `null` is returned. If [type] has
/// an invalid `call` member (non-method or a synthesized method with both
/// optional and named parameters) a [DynamicType] is returned.
+ @override
DartType getCallType(InterfaceType type) {
IndexedClass cls = type.element;
assert(checkFamily(cls));
@@ -896,6 +908,7 @@
return null;
}
+ @override
InterfaceType getThisType(IndexedClass cls) {
assert(checkFamily(cls));
JClassData data = classes.getData(cls);
@@ -928,6 +941,7 @@
return data.getFieldType(this);
}
+ @override
DartType getTypeVariableBound(IndexedTypeVariable typeVariable) {
assert(checkFamily(typeVariable));
JTypeVariableData data = typeVariables.getData(typeVariable);
@@ -1013,6 +1027,7 @@
return data.getFieldConstantExpression(this);
}
+ @override
InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls) {
assert(checkFamily(cls));
OrderedTypeSet orderedTypeSet = getOrderedTypeSet(type.element);
@@ -1024,6 +1039,7 @@
return supertype;
}
+ @override
OrderedTypeSet getOrderedTypeSet(IndexedClass cls) {
assert(checkFamily(cls));
JClassData data = classes.getData(cls);
@@ -1031,6 +1047,7 @@
return data.orderedTypeSet;
}
+ @override
int getHierarchyDepth(IndexedClass cls) {
assert(checkFamily(cls));
JClassData data = classes.getData(cls);
@@ -1038,6 +1055,7 @@
return data.orderedTypeSet.maxDepth;
}
+ @override
Iterable<InterfaceType> getInterfaces(IndexedClass cls) {
assert(checkFamily(cls));
JClassData data = classes.getData(cls);
@@ -1055,6 +1073,7 @@
return classes.getData(cls).definition;
}
+ @override
ImportEntity getImport(ir.LibraryDependency node) {
ir.Library library = node.parent;
JLibraryData data = libraries.getData(getLibraryInternal(library));
@@ -1076,6 +1095,7 @@
return _classHierarchy;
}
+ @override
StaticTypeProvider getStaticTypeProvider(MemberEntity member) {
MemberDefinition memberDefinition = members.getData(member).definition;
Map<ir.Expression, ir.DartType> cachedStaticTypes;
@@ -1112,11 +1132,13 @@
new ThisInterfaceType.from(thisType));
}
+ @override
Name getName(ir.Name name) {
return new Name(
name.name, name.isPrivate ? getLibrary(name.library) : null);
}
+ @override
CallStructure getCallStructure(ir.Arguments arguments) {
int argumentCount = arguments.positional.length + arguments.named.length;
List<String> namedArguments = arguments.named.map((e) => e.name).toList();
@@ -1124,6 +1146,7 @@
argumentCount, namedArguments, arguments.types.length);
}
+ @override
Selector getSelector(ir.Expression node) {
// TODO(efortuna): This is screaming for a common interface between
// PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
@@ -1258,6 +1281,7 @@
/// Computes the [native.NativeBehavior] for a call to the [JS] function.
// TODO(johnniwinther): Cache this for later use.
+ @override
NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
if (node.arguments.positional.length < 2 ||
node.arguments.named.isNotEmpty) {
@@ -1291,6 +1315,7 @@
/// Computes the [NativeBehavior] for a call to the [JS_BUILTIN]
/// function.
// TODO(johnniwinther): Cache this for later use.
+ @override
NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) {
if (node.arguments.positional.length < 1) {
reporter.internalError(
@@ -1319,6 +1344,7 @@
/// Computes the [NativeBehavior] for a call to the
/// [JS_EMBEDDED_GLOBAL] function.
// TODO(johnniwinther): Cache this for later use.
+ @override
NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
ir.StaticInvocation node) {
if (node.arguments.positional.length < 1) {
@@ -1351,6 +1377,7 @@
commonElements);
}
+ @override
js.Name getNameForJsGetName(ConstantValue constant, Namer namer) {
int index = extractEnumIndexFromConstantValue(
constant, commonElements.jsGetNameEnum);
@@ -1373,6 +1400,7 @@
return null;
}
+ @override
ConstantValue getConstantValue(ir.Expression node,
{bool requireConstant: true, bool implicitNull: false}) {
if (node is ir.ConstantExpression) {
@@ -1416,6 +1444,7 @@
return metadata;
}
+ @override
FunctionEntity getSuperNoSuchMethod(ClassEntity cls) {
while (cls != null) {
cls = elementEnvironment.getSuperClass(cls);
@@ -2454,9 +2483,13 @@
/// [BehaviorBuilder] for kernel based elements.
class JsBehaviorBuilder extends BehaviorBuilder {
+ @override
final ElementEnvironment elementEnvironment;
+ @override
final CommonElements commonElements;
+ @override
final DiagnosticReporter reporter;
+ @override
final NativeBasicData nativeBasicData;
final CompilerOptions _options;
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index 4afe45a..2818e69 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -20,7 +20,9 @@
/// debugging data stream.
static const String tag = 'library';
+ @override
final String name;
+ @override
final Uri canonicalUri;
JLibrary(this.name, this.canonicalUri);
@@ -42,6 +44,7 @@
sink.end(tag);
}
+ @override
String toString() => '${jsElementPrefix}library($name)';
}
@@ -53,9 +56,12 @@
/// debugging data stream.
static const String tag = 'class';
+ @override
final JLibrary library;
+ @override
final String name;
+ @override
final bool isAbstract;
JClass(this.library, this.name, {this.isAbstract});
@@ -92,6 +98,7 @@
@override
bool get isClosure => false;
+ @override
String toString() => '${jsElementPrefix}class($name)';
}
@@ -100,8 +107,10 @@
/// debugging data stream.
static const String tag = 'typedef';
+ @override
final JLibrary library;
+ @override
final String name;
JTypedef(this.library, this.name);
@@ -123,6 +132,7 @@
sink.end(tag);
}
+ @override
String toString() => '${jsElementPrefix}typedef($name)';
}
@@ -143,7 +153,9 @@
}
abstract class JMember extends IndexedMember {
+ @override
final JLibrary library;
+ @override
final JClass enclosingClass;
final Name _name;
final bool _isStatic;
@@ -186,8 +198,10 @@
/// Serializes this [JMember] to [sink].
void writeToDataSink(DataSink sink);
+ @override
String get name => _name.text;
+ @override
Name get memberName => _name;
@override
@@ -225,14 +239,18 @@
String get _kind;
+ @override
String toString() => '${jsElementPrefix}$_kind'
'(${enclosingClass != null ? '${enclosingClass.name}.' : ''}$name)';
}
abstract class JFunction extends JMember
implements FunctionEntity, IndexedFunction {
+ @override
final ParameterStructure parameterStructure;
+ @override
final bool isExternal;
+ @override
final AsyncMarker asyncMarker;
JFunction(JLibrary library, JClass enclosingClass, Name name,
@@ -243,6 +261,7 @@
abstract class JConstructor extends JFunction
implements ConstructorEntity, IndexedConstructor {
+ @override
final bool isConst;
JConstructor(
@@ -267,6 +286,7 @@
@override
bool get isFromEnvironmentConstructor => false;
+ @override
String get _kind => 'constructor';
}
@@ -370,6 +390,7 @@
/// debugging data stream.
static const String tag = 'constructor-body';
+ @override
final JConstructor constructor;
JConstructorBody(this.constructor, ParameterStructure parameterStructure)
@@ -395,6 +416,7 @@
sink.end(tag);
}
+ @override
String get _kind => 'constructor_body';
}
@@ -403,6 +425,7 @@
/// debugging data stream.
static const String tag = 'method';
+ @override
final bool isAbstract;
JMethod(JLibrary library, JClass enclosingClass, Name name,
@@ -461,6 +484,7 @@
@override
bool get isFunction => true;
+ @override
String get _kind => 'method';
}
@@ -471,6 +495,7 @@
final JFunction function;
final DartType elementType;
+ @override
final int hashCode;
JGeneratorBody(this.function, this.elementType)
@@ -496,6 +521,7 @@
sink.end(tag);
}
+ @override
String get _kind => 'generator_body';
}
@@ -504,6 +530,7 @@
/// debugging data stream.
static const String tag = 'getter';
+ @override
final bool isAbstract;
JGetter(JLibrary library, JClass enclosingClass, Name name,
@@ -560,6 +587,7 @@
@override
bool get isGetter => true;
+ @override
String get _kind => 'getter';
}
@@ -568,6 +596,7 @@
/// debugging data stream.
static const String tag = 'setter';
+ @override
final bool isAbstract;
JSetter(JLibrary library, JClass enclosingClass, Name name,
@@ -624,6 +653,7 @@
@override
bool get isSetter => true;
+ @override
String get _kind => 'setter';
}
@@ -632,7 +662,9 @@
/// debugging data stream.
static const String tag = 'field';
+ @override
final bool isAssignable;
+ @override
final bool isConst;
JField(JLibrary library, JClass enclosingClass, Name name,
@@ -683,6 +715,7 @@
@override
bool get isField => true;
+ @override
String get _kind => 'field';
}
@@ -718,6 +751,7 @@
sink.end(tag);
}
+ @override
String get _kind => 'closure_call';
}
@@ -740,6 +774,7 @@
return new JSignatureMethod(cls);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JMemberKind.signatureMethod);
sink.begin(tag);
@@ -747,6 +782,7 @@
sink.end(tag);
}
+ @override
String get _kind => 'signature';
}
@@ -758,8 +794,11 @@
/// debugging data stream.
static const String tag = 'type-variable';
+ @override
final Entity typeDeclaration;
+ @override
final String name;
+ @override
final int index;
JTypeVariable(this.typeDeclaration, this.name, this.index);
@@ -818,6 +857,7 @@
sink.end(tag);
}
+ @override
String toString() =>
'${jsElementPrefix}type_variable(${typeDeclaration.name}.$name)';
}
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index 1e72ff3..9fb97dc 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -230,11 +230,13 @@
/// debugging data stream.
static const String tag = 'class-env';
+ @override
final ir.Class cls;
final Map<String, ir.Member> _constructorMap;
final Map<String, ir.Member> _memberMap;
final Map<String, ir.Member> _setterMap;
final List<ir.Member> _members; // in declaration order.
+ @override
final bool isSuperMixinApplication;
/// Constructor bodies created for this class.
@@ -272,11 +274,13 @@
sink.end(tag);
}
+ @override
bool get isUnnamedMixinApplication => cls.isAnonymousMixin;
/// Return the [MemberEntity] for the member [name] in [cls]. If [setter] is
/// `true`, the setter or assignable field corresponding to [name] is
/// returned.
+ @override
MemberEntity lookupMember(IrToElementMap elementMap, String name,
{bool setter: false}) {
ir.Member member = setter ? _setterMap[name] : _memberMap[name];
@@ -284,6 +288,7 @@
}
/// Calls [f] for each member of [cls].
+ @override
void forEachMember(IrToElementMap elementMap, void f(MemberEntity member)) {
_members.forEach((ir.Member member) {
f(elementMap.getMember(member));
@@ -291,12 +296,14 @@
}
/// Return the [ConstructorEntity] for the constructor [name] in [cls].
+ @override
ConstructorEntity lookupConstructor(IrToElementMap elementMap, String name) {
ir.Member constructor = _constructorMap[name];
return constructor != null ? elementMap.getConstructor(constructor) : null;
}
/// Calls [f] for each constructor of [cls].
+ @override
void forEachConstructor(
IrToElementMap elementMap, void f(ConstructorEntity constructor)) {
_constructorMap.values.forEach((ir.Member constructor) {
@@ -309,6 +316,7 @@
_constructorBodyList.add(constructorBody);
}
+ @override
void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
_constructorBodyList?.forEach(f);
}
@@ -454,15 +462,23 @@
static const String tag = 'class-data';
final ir.Class cls;
+ @override
final ClassDefinition definition;
+ @override
bool isMixinApplication;
bool isCallTypeComputed = false;
+ @override
InterfaceType thisType;
+ @override
InterfaceType rawType;
+ @override
InterfaceType supertype;
+ @override
InterfaceType mixedInType;
+ @override
List<InterfaceType> interfaces;
+ @override
OrderedTypeSet orderedTypeSet;
JClassDataImpl(this.cls, this.definition);
@@ -484,8 +500,10 @@
sink.end(tag);
}
+ @override
bool get isEnumClass => cls != null && cls.isEnum;
+ @override
DartType get callType => null;
}
@@ -543,12 +561,15 @@
abstract class JMemberDataImpl implements JMemberData {
final ir.Member node;
+ @override
final MemberDefinition definition;
+ @override
final Map<ir.Expression, ir.DartType> staticTypes;
JMemberDataImpl(this.node, this.definition, this.staticTypes);
+ @override
InterfaceType getMemberThisType(JsToElementMap elementMap) {
MemberEntity member = elementMap.getMember(node);
ClassEntity cls = member.enclosingClass;
@@ -575,6 +596,7 @@
ir.FunctionNode get functionNode;
List<TypeVariableType> _typeVariables;
+ @override
List<TypeVariableType> getFunctionTypeVariables(
covariant JsKernelToElementMap elementMap) {
if (_typeVariables == null) {
@@ -602,6 +624,7 @@
abstract class FunctionDataForEachParameterMixin implements FunctionData {
ir.FunctionNode get functionNode;
+ @override
void forEachParameter(
JsToElementMap elementMap,
ParameterStructure parameterStructure,
@@ -637,6 +660,7 @@
/// debugging data stream.
static const String tag = 'function-data';
+ @override
final ir.FunctionNode functionNode;
FunctionType _type;
@@ -664,6 +688,7 @@
return new FunctionDataImpl(node, functionNode, definition, staticTypes);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JMemberDataKind.function);
sink.begin(tag);
@@ -673,6 +698,7 @@
sink.end(tag);
}
+ @override
FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
return _type ??= elementMap.getFunctionType(functionNode);
}
@@ -689,8 +715,10 @@
/// debugging data stream.
static const String tag = 'signature-function-data';
+ @override
final MemberDefinition definition;
final InterfaceType memberThisType;
+ @override
final ClassTypeVariableAccess classTypeVariableAccess;
final List<ir.TypeParameter> typeParameters;
@@ -710,6 +738,7 @@
definition, memberThisType, typeParameters, classTypeVariableAccess);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JMemberDataKind.signature);
sink.begin(tag);
@@ -723,10 +752,12 @@
@override
Map<ir.Expression, ir.DartType> get staticTypes => const {};
+ @override
FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
throw new UnsupportedError("SignatureFunctionData.getFunctionType");
}
+ @override
List<TypeVariableType> getFunctionTypeVariables(IrToElementMap elementMap) {
return typeParameters
.map<TypeVariableType>((ir.TypeParameter typeParameter) {
@@ -734,6 +765,7 @@
}).toList();
}
+ @override
void forEachParameter(
JsToElementMap elementMap,
ParameterStructure parameterStructure,
@@ -742,6 +774,7 @@
throw new UnimplementedError('SignatureData.forEachParameter');
}
+ @override
InterfaceType getMemberThisType(JsToElementMap elementMap) {
return memberThisType;
}
@@ -752,14 +785,17 @@
DelegatedFunctionData(this.baseData);
+ @override
FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
return baseData.getFunctionType(elementMap);
}
+ @override
List<TypeVariableType> getFunctionTypeVariables(IrToElementMap elementMap) {
return baseData.getFunctionTypeVariables(elementMap);
}
+ @override
void forEachParameter(
JsToElementMap elementMap,
ParameterStructure parameterStructure,
@@ -769,10 +805,12 @@
isNative: isNative);
}
+ @override
InterfaceType getMemberThisType(JsToElementMap elementMap) {
return baseData.getMemberThisType(elementMap);
}
+ @override
ClassTypeVariableAccess get classTypeVariableAccess =>
baseData.classTypeVariableAccess;
}
@@ -782,6 +820,7 @@
/// a debugging data stream.
static const String tag = 'generator-body-data';
+ @override
final MemberDefinition definition;
GeneratorBodyFunctionData(FunctionData baseData, this.definition)
@@ -797,6 +836,7 @@
return new GeneratorBodyFunctionData(baseData, definition);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JMemberDataKind.generatorBody);
sink.begin(tag);
@@ -848,6 +888,7 @@
node, functionNode, definition, staticTypes);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JMemberDataKind.constructor);
sink.begin(tag);
@@ -858,6 +899,7 @@
sink.end(tag);
}
+ @override
ConstantConstructor getConstructorConstant(
JsKernelToElementMap elementMap, ConstructorEntity constructor) {
if (_constantConstructor == null) {
@@ -909,6 +951,7 @@
node, functionNode, definition, staticTypes);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JMemberDataKind.constructorBody);
sink.begin(tag);
@@ -955,6 +998,7 @@
return new JFieldDataImpl(node, definition, staticTypes);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.writeEnum(JMemberDataKind.field);
sink.begin(tag);
@@ -964,12 +1008,15 @@
sink.end(tag);
}
+ @override
ir.Field get node => super.node;
+ @override
DartType getFieldType(covariant JsKernelToElementMap elementMap) {
return _type ??= elementMap.getDartType(node.type);
}
+ @override
ConstantExpression getFieldConstantExpression(
JsKernelToElementMap elementMap) {
if (_constantExpression == null) {
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index e605804..2090143 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -26,7 +26,6 @@
import '../js_backend/native_data.dart';
import '../kernel/kernel_strategy.dart';
import '../native/behavior.dart';
-import '../options.dart';
import '../ssa/builder_kernel.dart';
import '../ssa/nodes.dart';
import '../ssa/ssa.dart';
@@ -138,21 +137,9 @@
KernelCodegenWorkItemBuilder(
this._backend, this._closedWorld, this._globalInferenceResults);
- CompilerOptions get _options => _backend.compiler.options;
-
@override
CodegenWorkItem createWorkItem(MemberEntity entity) {
if (entity.isAbstract) return null;
-
- // Codegen inlines field initializers. It only needs to generate
- // code for checked setters.
- if (entity.isField && entity.isInstanceMember) {
- if (!_options.parameterCheckPolicy.isEmitted ||
- entity.enclosingClass.isClosure) {
- return null;
- }
- }
-
return new KernelCodegenWorkItem(
_backend, _closedWorld, _globalInferenceResults, entity);
}
@@ -161,7 +148,9 @@
class KernelCodegenWorkItem extends CodegenWorkItem {
final JavaScriptBackend _backend;
final JClosedWorld _closedWorld;
+ @override
final MemberEntity element;
+ @override
final CodegenRegistry registry;
final GlobalTypeInferenceResults _globalInferenceResults;
@@ -220,73 +209,88 @@
_globalInferenceResults
.resultOfMember(e is ConstructorBodyEntity ? e.constructor : e);
+ @override
AbstractValue getReturnTypeOf(FunctionEntity function) {
return AbstractValueFactory.inferredReturnTypeForElement(
function, _globalInferenceResults);
}
+ @override
AbstractValue receiverTypeOfInvocation(
ir.MethodInvocation node, AbstractValueDomain abstractValueDomain) {
return _targetResults.typeOfSend(node);
}
+ @override
AbstractValue receiverTypeOfGet(ir.PropertyGet node) {
return _targetResults.typeOfSend(node);
}
+ @override
AbstractValue receiverTypeOfDirectGet(ir.DirectPropertyGet node) {
return _targetResults.typeOfSend(node);
}
+ @override
AbstractValue receiverTypeOfSet(
ir.PropertySet node, AbstractValueDomain abstractValueDomain) {
return _targetResults.typeOfSend(node);
}
+ @override
AbstractValue typeOfListLiteral(
ir.ListLiteral listLiteral, AbstractValueDomain abstractValueDomain) {
return _globalInferenceResults.typeOfListLiteral(listLiteral) ??
abstractValueDomain.dynamicType;
}
+ @override
AbstractValue typeOfIterator(ir.ForInStatement node) {
return _targetResults.typeOfIterator(node);
}
+ @override
AbstractValue typeOfIteratorCurrent(ir.ForInStatement node) {
return _targetResults.typeOfIteratorCurrent(node);
}
+ @override
AbstractValue typeOfIteratorMoveNext(ir.ForInStatement node) {
return _targetResults.typeOfIteratorMoveNext(node);
}
+ @override
bool isJsIndexableIterator(
ir.ForInStatement node, AbstractValueDomain abstractValueDomain) {
AbstractValue mask = typeOfIterator(node);
return abstractValueDomain.isJsIndexableAndIterable(mask).isDefinitelyTrue;
}
+ @override
AbstractValue inferredIndexType(ir.ForInStatement node) {
return AbstractValueFactory.inferredTypeForSelector(
new Selector.index(), typeOfIterator(node), _globalInferenceResults);
}
+ @override
AbstractValue getInferredTypeOf(MemberEntity member) {
return AbstractValueFactory.inferredTypeForMember(
member, _globalInferenceResults);
}
+ @override
AbstractValue getInferredTypeOfParameter(Local parameter) {
return AbstractValueFactory.inferredTypeForParameter(
parameter, _globalInferenceResults);
}
+ @override
AbstractValue selectorTypeOf(Selector selector, AbstractValue mask) {
return AbstractValueFactory.inferredTypeForSelector(
selector, mask, _globalInferenceResults);
}
+ @override
AbstractValue typeFromNativeBehavior(
NativeBehavior nativeBehavior, JClosedWorld closedWorld) {
return AbstractValueFactory.fromNativeBehavior(nativeBehavior, closedWorld);
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 024408f..fdf9a69 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -41,9 +41,13 @@
class JsClosedWorld implements JClosedWorld {
static const String tag = 'closed-world';
+ @override
final NativeData nativeData;
+ @override
final InterceptorData interceptorData;
+ @override
final BackendUsage backendUsage;
+ @override
final NoSuchMethodData noSuchMethodData;
FunctionSet _allFunctions;
@@ -64,19 +68,28 @@
/// Members that are written either directly or through a setter selector.
final Set<MemberEntity> assignedInstanceMembers;
+ @override
final Set<ClassEntity> liveNativeClasses;
+ @override
final Set<MemberEntity> processedMembers;
+ @override
final ClassHierarchy classHierarchy;
final JsKernelToElementMap elementMap;
+ @override
final RuntimeTypesNeed rtiNeed;
AbstractValueDomain _abstractValueDomain;
+ @override
final JFieldAnalysis fieldAnalysis;
+ @override
final AnnotationsData annotationsData;
+ @override
final GlobalLocalsMap globalLocalsMap;
+ @override
final ClosureData closureDataLookup;
+ @override
final OutputUnitData outputUnitData;
Sorter _sorter;
@@ -207,13 +220,17 @@
sink.end(tag);
}
+ @override
JElementEnvironment get elementEnvironment => elementMap.elementEnvironment;
+ @override
JCommonElements get commonElements => elementMap.commonElements;
+ @override
DartTypes get dartTypes => elementMap.types;
/// Returns `true` if [cls] is implemented by an instantiated class.
+ @override
bool isImplemented(ClassEntity cls) {
return implementedClasses.contains(cls);
}
@@ -239,11 +256,13 @@
}
/// Returns `true` if [cls] is mixed into a live class.
+ @override
bool isUsedAsMixin(ClassEntity cls) {
return !mixinUsesOf(cls).isEmpty;
}
/// Returns `true` if any live class that mixes in [cls] implements [type].
+ @override
bool hasAnySubclassOfMixinUseThatImplements(
ClassEntity cls, ClassEntity type) {
return mixinUsesOf(cls)
@@ -252,6 +271,7 @@
/// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass
/// of a mixin application of [y].
+ @override
bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) {
Map<ClassEntity, bool> secondMap =
_subtypeCoveredByCache[x] ??= <ClassEntity, bool>{};
@@ -262,6 +282,7 @@
}
/// Returns `true` if any subclass of [superclass] implements [type].
+ @override
bool hasAnySubclassThatImplements(ClassEntity superclass, ClassEntity type) {
Set<ClassEntity> subclasses = typesImplementedBySubclasses[superclass];
if (subclasses == null) return false;
@@ -320,6 +341,7 @@
}
/// Returns an iterable over the common supertypes of the [classes].
+ @override
Iterable<ClassEntity> commonSupertypesOf(Iterable<ClassEntity> classes) {
Iterator<ClassEntity> iterator = classes.iterator;
if (!iterator.moveNext()) return const <ClassEntity>[];
@@ -360,6 +382,7 @@
}
/// Returns an iterable over the live mixin applications that mixin [cls].
+ @override
Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) {
if (_liveMixinUses == null) {
_liveMixinUses = new Map<ClassEntity, List<ClassEntity>>();
@@ -389,6 +412,7 @@
/// Returns `true` if any live class that mixes in [mixin] is also a subclass
/// of [superclass].
+ @override
bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) {
return mixinUsesOf(mixin).any((ClassEntity each) {
return classHierarchy.isSubclassOf(each, superclass);
@@ -396,6 +420,7 @@
}
/// Returns `true` if [cls] or any superclass mixes in [mixin].
+ @override
bool isSubclassOfMixinUseOf(ClassEntity cls, ClassEntity mixin) {
if (isUsedAsMixin(mixin)) {
ClassEntity current = cls;
@@ -422,6 +447,7 @@
/// Every implementation of `Closure` has a 'call' method with its own
/// signature so it cannot be modelled by a [FunctionEntity]. Also,
/// call-methods for tear-off are not part of the element model.
+ @override
bool includesClosureCall(Selector selector, AbstractValue receiver) {
return selector.name == Identifiers.call &&
(receiver == null ||
@@ -431,6 +457,7 @@
.isPotentiallyTrue);
}
+ @override
AbstractValue computeReceiverType(Selector selector, AbstractValue receiver) {
_ensureFunctionSet();
if (includesClosureCall(selector, receiver)) {
@@ -439,6 +466,7 @@
return _allFunctions.receiverType(selector, receiver, abstractValueDomain);
}
+ @override
Iterable<MemberEntity> locateMembers(
Selector selector, AbstractValue receiver) {
_ensureFunctionSet();
@@ -452,6 +480,7 @@
.any((each) => each.isGetter);
}
+ @override
MemberEntity locateSingleMember(Selector selector, AbstractValue receiver) {
if (includesClosureCall(selector, receiver)) {
return null;
@@ -460,6 +489,7 @@
return abstractValueDomain.locateSingleMember(receiver, selector);
}
+ @override
bool fieldNeverChanges(MemberEntity element) {
if (!element.isField) return false;
if (nativeData.isNativeMember(element)) {
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index baff70c..c8210a9 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -340,25 +340,12 @@
Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior =
map.toBackendMemberMap(
nativeData.nativeFieldStoreBehavior, convertNativeBehavior);
- Map<LibraryEntity, String> jsInteropLibraryNames =
- map.toBackendLibraryMap(nativeData.jsInteropLibraries, identity);
- Set<ClassEntity> anonymousJsInteropClasses =
- map.toBackendClassSet(nativeData.anonymousJsInteropClasses);
- Map<ClassEntity, String> jsInteropClassNames =
- map.toBackendClassMap(nativeData.jsInteropClasses, identity);
- Map<MemberEntity, String> jsInteropMemberNames =
- map.toBackendMemberMap(nativeData.jsInteropMembers, identity);
-
return new NativeDataImpl(
nativeBasicData,
nativeMemberName,
nativeMethodBehavior,
nativeFieldLoadBehavior,
- nativeFieldStoreBehavior,
- jsInteropLibraryNames,
- anonymousJsInteropClasses,
- jsInteropClassNames,
- jsInteropMemberNames);
+ nativeFieldStoreBehavior);
}
InterceptorData _convertInterceptorData(JsToFrontendMap map,
@@ -673,6 +660,7 @@
JsToFrontendMapImpl(this._backend);
+ @override
DartType toBackendType(DartType type, {bool allowFreeVariables: false}) =>
type == null
? null
@@ -690,14 +678,17 @@
return toBackendLibrary(entity);
}
+ @override
LibraryEntity toBackendLibrary(covariant IndexedLibrary library) {
return _backend.libraries.getEntity(library.libraryIndex);
}
+ @override
ClassEntity toBackendClass(covariant IndexedClass cls) {
return _backend.classes.getEntity(cls.classIndex);
}
+ @override
MemberEntity toBackendMember(covariant IndexedMember member) {
return _backend.members.getEntity(member.memberIndex);
}
@@ -716,6 +707,7 @@
.getEntity(indexedTypeVariable.typeVariableIndex);
}
+ @override
ConstantValue toBackendConstant(ConstantValue constant,
{bool allowNull: false}) {
if (constant == null) {
@@ -835,19 +827,28 @@
_ConstantConverter(this.toBackendEntity)
: typeConverter = new _TypeConverter();
+ @override
ConstantValue visitNull(NullConstantValue constant, _) => constant;
+ @override
ConstantValue visitInt(IntConstantValue constant, _) => constant;
+ @override
ConstantValue visitDouble(DoubleConstantValue constant, _) => constant;
+ @override
ConstantValue visitBool(BoolConstantValue constant, _) => constant;
+ @override
ConstantValue visitString(StringConstantValue constant, _) => constant;
+ @override
ConstantValue visitSynthetic(SyntheticConstantValue constant, _) => constant;
+ @override
ConstantValue visitNonConstant(NonConstantValue constant, _) => constant;
+ @override
ConstantValue visitFunction(FunctionConstantValue constant, _) {
return new FunctionConstantValue(toBackendEntity(constant.element),
typeConverter.visit(constant.type, toBackendEntity));
}
+ @override
ConstantValue visitList(ListConstantValue constant, _) {
DartType type = typeConverter.visit(constant.type, toBackendEntity);
List<ConstantValue> entries = _handleValues(constant.entries);
@@ -868,6 +869,7 @@
return new constant_system.JavaScriptSetConstant(type, entries);
}
+ @override
ConstantValue visitMap(
covariant constant_system.JavaScriptMapConstant constant, _) {
DartType type = typeConverter.visit(constant.type, toBackendEntity);
@@ -884,6 +886,7 @@
type, keys, values, protoValue, constant.onlyStringKeys);
}
+ @override
ConstantValue visitConstructed(ConstructedConstantValue constant, _) {
DartType type = typeConverter.visit(constant.type, toBackendEntity);
Map<FieldEntity, ConstantValue> fields = {};
@@ -895,6 +898,7 @@
return new ConstructedConstantValue(type, fields);
}
+ @override
ConstantValue visitType(TypeConstantValue constant, _) {
DartType type = typeConverter.visit(constant.type, toBackendEntity);
DartType representedType =
@@ -905,18 +909,21 @@
return new TypeConstantValue(representedType, type);
}
+ @override
ConstantValue visitInterceptor(InterceptorConstantValue constant, _) {
// Interceptor constants are only created in the SSA graph builder.
throw new UnsupportedError(
"Unexpected visitInterceptor ${constant.toStructuredText()}");
}
+ @override
ConstantValue visitDeferredGlobal(DeferredGlobalConstantValue constant, _) {
// Deferred global constants are only created in the SSA graph builder.
throw new UnsupportedError(
"Unexpected DeferredGlobalConstantValue ${constant.toStructuredText()}");
}
+ @override
ConstantValue visitInstantiation(InstantiationConstantValue constant, _) {
ConstantValue function = constant.function.accept(this, null);
List<DartType> typeArguments =
diff --git a/pkg/compiler/lib/src/js_model/locals.dart b/pkg/compiler/lib/src/js_model/locals.dart
index 2281cd9..d6666c0 100644
--- a/pkg/compiler/lib/src/js_model/locals.dart
+++ b/pkg/compiler/lib/src/js_model/locals.dart
@@ -138,6 +138,7 @@
}
/// Serializes this [KernelToLocalsMapImpl] to [sink].
+ @override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeMember(currentMember);
@@ -187,6 +188,7 @@
}
}
+ @override
MemberEntity get currentMember => _currentMember;
Local getLocalByIndex(int index) {
@@ -451,11 +453,16 @@
static const String tag = 'jump-target';
final MemberEntity memberContext;
+ @override
final int nestingLevel;
List<LabelDefinition> _labels;
+ @override
final bool isSwitch;
+ @override
final bool isSwitchCase;
+ @override
bool isBreakTarget;
+ @override
bool isContinueTarget;
JJumpTarget(this.memberContext, this.nestingLevel,
@@ -527,6 +534,7 @@
return _labels ?? const <LabelDefinition>[];
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('JJumpTarget(');
@@ -548,9 +556,13 @@
}
class JLabelDefinition extends LabelDefinition {
+ @override
final JumpTarget target;
+ @override
final String labelName;
+ @override
bool isBreakTarget;
+ @override
bool isContinueTarget;
JLabelDefinition(this.target, this.labelName,
@@ -558,6 +570,7 @@
@override
String get name => labelName;
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('JLabelDefinition(');
@@ -573,6 +586,7 @@
}
class JLocal extends IndexedLocal {
+ @override
final String name;
final MemberEntity memberContext;
@@ -585,6 +599,7 @@
String get _kind => 'local';
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('$_kind(');
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 38c496d..cc810d1 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -45,14 +45,18 @@
/// A kernel [Target] to configure the Dart Front End for dart2js.
class Dart2jsTarget extends Target {
final TargetFlags flags;
+ @override
final String name;
Dart2jsTarget(this.name, this.flags);
+ @override
bool get legacyMode => flags.legacyMode;
+ @override
bool get enableNoSuchMethodForwarders => !flags.legacyMode;
+ @override
List<String> get extraRequiredLibraries => _requiredLibraries[name];
@override
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index 3a22be9..d69ff52 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -147,6 +147,7 @@
/// Computes the native behavior for reading the native [field].
NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field,
+ Iterable<String> createsAnnotations, Iterable<String> returnsAnnotations,
{bool isJsInterop});
/// Computes the native behavior for writing to the native [field].
@@ -155,6 +156,7 @@
/// Computes the native behavior for calling the function or constructor
/// [member].
NativeBehavior getNativeBehaviorForMethod(ir.Member member,
+ Iterable<String> createsAnnotations, Iterable<String> returnsAnnotations,
{bool isJsInterop});
/// Compute the kind of foreign helper function called by [node], if any.
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index db56ed7..6f2491d 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -61,15 +61,11 @@
part 'native_basic_data.dart';
part 'no_such_method_resolver.dart';
-/// If `true` kernel impacts are computed as [ImpactData] directly on kernel
-/// and converted to the K model afterwards. This is a pre-step to modularizing
-/// the world impact computation.
-bool useImpactDataForTesting = false;
-
/// Implementation of [KernelToElementMap] that only supports world
/// impact computation.
class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
final CompilerOptions options;
+ @override
final DiagnosticReporter reporter;
CommonElementsImpl _commonElements;
KernelElementEnvironment _elementEnvironment;
@@ -128,8 +124,10 @@
_types = new KernelDartTypes(this);
}
+ @override
DartTypes get types => _types;
+ @override
KernelElementEnvironment get elementEnvironment => _elementEnvironment;
@override
@@ -251,6 +249,7 @@
@override
ClassEntity getClass(ir.Class node) => getClassInternal(node);
+ @override
InterfaceType getSuperType(IndexedClass cls) {
assert(checkFamily(cls));
KClassData data = classes.getData(cls);
@@ -281,6 +280,7 @@
}
}
+ @override
TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
getTypeVariableInternal(node);
@@ -381,6 +381,7 @@
throw new UnsupportedError("Unexpected member: $node");
}
+ @override
MemberEntity getSuperMember(MemberEntity context, ir.Name name,
{bool setter: false}) {
// We can no longer trust the interface target of the super access since it
@@ -410,6 +411,7 @@
ConstructorEntity getConstructor(ir.Member node) =>
getConstructorInternal(node);
+ @override
ConstructorEntity getSuperConstructor(
ir.Constructor sourceNode, ir.Member targetNode) {
ConstructorEntity source = getConstructor(sourceNode);
@@ -440,6 +442,7 @@
@override
DartType getDartType(ir.DartType type) => _typeConverter.convert(type);
+ @override
TypeVariableType getTypeVariableType(ir.TypeParameterType type) =>
getDartType(type);
@@ -451,6 +454,7 @@
return list;
}
+ @override
InterfaceType getInterfaceType(ir.InterfaceType type) =>
_typeConverter.convert(type);
@@ -528,6 +532,7 @@
constantRequired: requireConstant, checkCasts: checkCasts);
}
+ @override
DartType substByContext(DartType type, InterfaceType context) {
return type.subst(
context.typeArguments, getThisType(context.element).typeArguments);
@@ -538,6 +543,7 @@
/// If [type] doesn't have a `call` member `null` is returned. If [type] has
/// an invalid `call` member (non-method or a synthesized method with both
/// optional and named parameters) a [DynamicType] is returned.
+ @override
DartType getCallType(InterfaceType type) {
IndexedClass cls = type.element;
assert(checkFamily(cls));
@@ -548,6 +554,7 @@
return null;
}
+ @override
InterfaceType getThisType(IndexedClass cls) {
assert(checkFamily(cls));
KClassData data = classes.getData(cls);
@@ -580,6 +587,7 @@
return data.getFunctionTypeVariables(this);
}
+ @override
DartType getTypeVariableBound(IndexedTypeVariable typeVariable) {
assert(checkFamily(typeVariable));
KTypeVariableData data = typeVariables.getData(typeVariable);
@@ -672,6 +680,7 @@
return data.getFieldConstantExpression(this);
}
+ @override
InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls) {
assert(checkFamily(cls));
OrderedTypeSet orderedTypeSet = getOrderedTypeSet(type.element);
@@ -683,6 +692,7 @@
return supertype;
}
+ @override
OrderedTypeSet getOrderedTypeSet(IndexedClass cls) {
assert(checkFamily(cls));
KClassData data = classes.getData(cls);
@@ -690,6 +700,7 @@
return data.orderedTypeSet;
}
+ @override
int getHierarchyDepth(IndexedClass cls) {
assert(checkFamily(cls));
KClassData data = classes.getData(cls);
@@ -697,6 +708,7 @@
return data.orderedTypeSet.maxDepth;
}
+ @override
Iterable<InterfaceType> getInterfaces(IndexedClass cls) {
assert(checkFamily(cls));
KClassData data = classes.getData(cls);
@@ -704,11 +716,13 @@
return data.interfaces;
}
+ @override
ir.Member getMemberNode(covariant IndexedMember member) {
assert(checkFamily(member));
return members.getData(member).node;
}
+ @override
ir.Class getClassNode(covariant IndexedClass cls) {
assert(checkFamily(cls));
return classes.getData(cls).node;
@@ -718,6 +732,7 @@
return typedefs.getData(typedef).node;
}
+ @override
ImportEntity getImport(ir.LibraryDependency node) {
if (node == null) return null;
ir.Library library = node.parent;
@@ -725,6 +740,7 @@
return data.imports[node];
}
+ @override
ir.TypeEnvironment get typeEnvironment {
if (_typeEnvironment == null) {
_typeEnvironment ??= new ir.TypeEnvironment(
@@ -733,6 +749,7 @@
return _typeEnvironment;
}
+ @override
ir.ClassHierarchy get classHierarchy {
if (_classHierarchy == null) {
_classHierarchy ??= new ir.ClassHierarchy(env.mainComponent);
@@ -740,11 +757,13 @@
return _classHierarchy;
}
+ @override
Name getName(ir.Name name) {
return new Name(
name.name, name.isPrivate ? getLibrary(name.library) : null);
}
+ @override
CallStructure getCallStructure(ir.Arguments arguments) {
int argumentCount = arguments.positional.length + arguments.named.length;
List<String> namedArguments = arguments.named.map((e) => e.name).toList();
@@ -766,6 +785,7 @@
namedParameters, includeTypeParameters ? typeParameters : 0);
}
+ @override
Selector getInvocationSelector(ir.Name irName, int positionalArguments,
List<String> namedArguments, int typeArguments) {
Name name = getName(irName);
@@ -876,6 +896,7 @@
/// Computes the [NativeBehavior] for a call to the [JS] function.
// TODO(johnniwinther): Cache this for later use.
+ @override
NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
if (node.arguments.positional.length < 2 ||
node.arguments.named.isNotEmpty) {
@@ -909,6 +930,7 @@
/// Computes the [NativeBehavior] for a call to the [JS_BUILTIN]
/// function.
// TODO(johnniwinther): Cache this for later use.
+ @override
NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) {
if (node.arguments.positional.length < 1) {
reporter.internalError(
@@ -937,6 +959,7 @@
/// Computes the [NativeBehavior] for a call to the
/// [JS_EMBEDDED_GLOBAL] function.
// TODO(johnniwinther): Cache this for later use.
+ @override
NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
ir.StaticInvocation node) {
if (node.arguments.positional.length < 1) {
@@ -969,6 +992,7 @@
commonElements);
}
+ @override
js.Name getNameForJsGetName(ConstantValue constant, Namer namer) {
int index = extractEnumIndexFromConstantValue(
constant, commonElements.jsGetNameEnum);
@@ -991,6 +1015,7 @@
return null;
}
+ @override
ConstantValue getConstantValue(ir.Expression node,
{bool requireConstant: true,
bool implicitNull: false,
@@ -1038,6 +1063,7 @@
return metadata;
}
+ @override
FunctionEntity getSuperNoSuchMethod(ClassEntity cls) {
while (cls != null) {
cls = elementEnvironment.getSuperClass(cls);
@@ -1308,12 +1334,14 @@
}
/// NativeBasicData is need for computation of the default super class.
+ @override
NativeBasicData get nativeBasicData => _frontendStrategy.nativeBasicData;
/// Adds libraries in [component] to the set of libraries.
///
/// The main method of the first component is used as the main method for the
/// compilation.
+ @override
void addComponent(ir.Component component) {
env.addComponent(component);
}
@@ -1322,26 +1350,19 @@
_nativeBehaviorBuilder ??= new KernelBehaviorBuilder(elementEnvironment,
commonElements, nativeBasicData, reporter, options);
- ResolutionImpact computeWorldImpact(
- KMember member,
- VariableScopeModel variableScopeModel,
- Set<PragmaAnnotation> annotations) {
+ ResolutionImpact computeWorldImpact(KMember member,
+ VariableScopeModel variableScopeModel, Set<PragmaAnnotation> annotations,
+ {ImpactBuilderData impactBuilderData}) {
KMemberData memberData = members.getData(member);
ir.Member node = memberData.node;
- if (useImpactDataForTesting) {
- ImpactBuilder builder = new ImpactBuilder(
- typeEnvironment, classHierarchy, variableScopeModel,
- useAsserts: options.enableUserAssertions,
- inferEffectivelyFinalVariableTypes:
- !annotations.contains(PragmaAnnotation.disableFinal));
- if (retainDataForTesting) {
+ if (impactBuilderData != null) {
+ if (impactBuilderData.typeMapsForTesting != null) {
typeMapsForTesting ??= {};
- typeMapsForTesting[member] = builder.typeMapsForTesting = {};
+ typeMapsForTesting[member] = impactBuilderData.typeMapsForTesting;
}
- node.accept(builder);
- ImpactData impactData = builder.impactData;
- memberData.staticTypes = builder.cachedStaticTypes;
+ ImpactData impactData = impactBuilderData.impactData;
+ memberData.staticTypes = impactBuilderData.cachedStaticTypes;
KernelImpactConverter converter =
new KernelImpactConverter(this, member, reporter, options);
return converter.convert(impactData);
@@ -1358,11 +1379,6 @@
}
}
- ScopeModel computeScopeModel(KMember member) {
- ir.Member node = members.getData(member).node;
- return ScopeModel.computeScopeModel(node);
- }
-
Map<ir.Expression, ir.DartType> getCachedStaticTypes(KMember member) {
Map<ir.Expression, ir.DartType> staticTypes =
members.getData(member).staticTypes;
@@ -1458,6 +1474,7 @@
/// Returns `true` is [node] has a `@Native(...)` annotation.
// TODO(johnniwinther): Cache this for later use.
+ @override
bool isNativeClass(ir.Class node) {
for (ir.Expression annotation in node.annotations) {
if (annotation is ir.ConstructorInvocation) {
@@ -1471,6 +1488,7 @@
}
/// Compute the kind of foreign helper function called by [node], if any.
+ @override
ForeignKind getForeignKind(ir.StaticInvocation node) {
if (commonElements.isForeignHelper(getMember(node.target))) {
switch (node.target.name.name) {
@@ -1489,6 +1507,7 @@
/// Computes the [InterfaceType] referenced by a call to the
/// [JS_INTERCEPTOR_CONSTANT] function, if any.
+ @override
InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node) {
if (node.arguments.positional.length != 1 ||
node.arguments.named.isNotEmpty) {
@@ -1504,17 +1523,19 @@
/// Computes the native behavior for reading the native [field].
// TODO(johnniwinther): Cache this for later use.
+ @override
NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field,
+ Iterable<String> createsAnnotations, Iterable<String> returnsAnnotations,
{bool isJsInterop}) {
DartType type = getDartType(field.type);
- List<ConstantValue> metadata = getMetadata(field.annotations);
- return nativeBehaviorBuilder.buildFieldLoadBehavior(
- type, metadata, typeLookup(resolveAsRaw: false),
+ return nativeBehaviorBuilder.buildFieldLoadBehavior(type,
+ createsAnnotations, returnsAnnotations, typeLookup(resolveAsRaw: false),
isJsInterop: isJsInterop);
}
/// Computes the native behavior for writing to the native [field].
// TODO(johnniwinther): Cache this for later use.
+ @override
NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) {
DartType type = getDartType(field.type);
return nativeBehaviorBuilder.buildFieldStoreBehavior(type);
@@ -1522,7 +1543,9 @@
/// Computes the native behavior for calling [member].
// TODO(johnniwinther): Cache this for later use.
+ @override
NativeBehavior getNativeBehaviorForMethod(ir.Member member,
+ Iterable<String> createsAnnotations, Iterable<String> returnsAnnotations,
{bool isJsInterop}) {
DartType type;
if (member is ir.Procedure) {
@@ -1532,9 +1555,8 @@
} else {
failedAt(CURRENT_ELEMENT_SPANNABLE, "Unexpected method node $member.");
}
- List<ConstantValue> metadata = getMetadata(member.annotations);
- return nativeBehaviorBuilder.buildMethodBehavior(
- type, metadata, typeLookup(resolveAsRaw: false),
+ return nativeBehaviorBuilder.buildMethodBehavior(type, createsAnnotations,
+ returnsAnnotations, typeLookup(resolveAsRaw: false),
isJsInterop: isJsInterop);
}
@@ -1852,9 +1874,13 @@
/// [BehaviorBuilder] for kernel based elements.
class KernelBehaviorBuilder extends BehaviorBuilder {
+ @override
final ElementEnvironment elementEnvironment;
+ @override
final CommonElements commonElements;
+ @override
final DiagnosticReporter reporter;
+ @override
final NativeBasicData nativeBasicData;
final CompilerOptions _options;
@@ -1893,6 +1919,7 @@
class KernelEvaluationEnvironment extends EvaluationEnvironmentBase {
final KernelToElementMapImpl _elementMap;
final Environment _environment;
+ @override
final bool checkCasts;
KernelEvaluationEnvironment(
@@ -1941,7 +1968,7 @@
class KernelNativeMemberResolver implements NativeMemberResolver {
static final RegExp _identifier = new RegExp(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$');
- final KernelToElementMap _elementMap;
+ final KernelToElementMapImpl _elementMap;
final NativeBasicData _nativeBasicData;
final NativeDataBuilder _nativeDataBuilder;
@@ -1953,25 +1980,28 @@
CommonElements get _commonElements => _elementMap.commonElements;
@override
- void resolveNativeMember(MemberEntity element) {
+ void resolveNativeMember(
+ MemberEntity element, IrAnnotationData annotationData) {
bool isJsInterop = _isJsInteropMember(element);
if (element.isFunction ||
element.isConstructor ||
element.isGetter ||
element.isSetter) {
FunctionEntity method = element;
- bool isNative = _processMethodAnnotations(method);
+ bool isNative = _processMethodAnnotations(method, annotationData);
if (isNative || isJsInterop) {
- NativeBehavior behavior =
- _computeNativeMethodBehavior(method, isJsInterop: isJsInterop);
+ NativeBehavior behavior = _computeNativeMethodBehavior(
+ method, annotationData,
+ isJsInterop: isJsInterop);
_nativeDataBuilder.setNativeMethodBehavior(method, behavior);
}
} else if (element.isField) {
FieldEntity field = element;
- bool isNative = _processFieldAnnotations(field);
+ bool isNative = _processFieldAnnotations(field, annotationData);
if (isNative || isJsInterop) {
- NativeBehavior fieldLoadBehavior =
- _computeNativeFieldLoadBehavior(field, isJsInterop: isJsInterop);
+ NativeBehavior fieldLoadBehavior = _computeNativeFieldLoadBehavior(
+ field, annotationData,
+ isJsInterop: isJsInterop);
NativeBehavior fieldStoreBehavior =
_computeNativeFieldStoreBehavior(field);
_nativeDataBuilder.setNativeFieldLoadBehavior(field, fieldLoadBehavior);
@@ -1983,17 +2013,18 @@
/// Process the potentially native [field]. Adds information from metadata
/// attributes. Returns `true` of [method] is native.
- bool _processFieldAnnotations(covariant FieldEntity element) {
+ bool _processFieldAnnotations(
+ FieldEntity element, IrAnnotationData annotationData) {
if (element.isInstanceMember &&
_nativeBasicData.isNativeClass(element.enclosingClass)) {
// Exclude non-instance (static) fields - they are not really native and
// are compiled as isolate globals. Access of a property of a constructor
// function or a non-method property in the prototype chain, must be coded
// using a JS-call.
- _setNativeName(element);
+ _setNativeName(element, annotationData);
return true;
} else {
- String name = _findJsNameFromAnnotation(element);
+ String name = _findJsNameFromAnnotation(element, annotationData);
if (name != null) {
failedAt(
element,
@@ -2006,12 +2037,13 @@
/// Process the potentially native [method]. Adds information from metadata
/// attributes. Returns `true` of [method] is native.
- bool _processMethodAnnotations(covariant FunctionEntity method) {
- if (_isNativeMethod(method)) {
+ bool _processMethodAnnotations(
+ FunctionEntity method, IrAnnotationData annotationData) {
+ if (_isNativeMethod(method, annotationData)) {
if (method.isStatic) {
- _setNativeNameForStaticMethod(method);
+ _setNativeNameForStaticMethod(method, annotationData);
} else {
- _setNativeName(method);
+ _setNativeName(method, annotationData);
}
return true;
}
@@ -2020,9 +2052,9 @@
/// Sets the native name of [element], either from an annotation, or
/// defaulting to the Dart name.
- void _setNativeName(MemberEntity element) {
- String name = _findJsNameFromAnnotation(element);
- if (name == null) name = element.name;
+ void _setNativeName(MemberEntity element, IrAnnotationData annotationData) {
+ String name = _findJsNameFromAnnotation(element, annotationData);
+ name ??= element.name;
_nativeDataBuilder.setNativeMemberName(element, name);
}
@@ -2034,9 +2066,10 @@
/// use the declared @JSName as the expression
/// 3. If [element] does not have a @JSName annotation, qualify the name of
/// the method with the @Native name of the enclosing class.
- void _setNativeNameForStaticMethod(FunctionEntity element) {
- String name = _findJsNameFromAnnotation(element);
- if (name == null) name = element.name;
+ void _setNativeNameForStaticMethod(
+ FunctionEntity element, IrAnnotationData annotationData) {
+ String name = _findJsNameFromAnnotation(element, annotationData);
+ name ??= element.name;
if (_isIdentifier(name)) {
List<String> nativeNames =
_nativeBasicData.getNativeTagsOfClass(element.enclosingClass);
@@ -2057,16 +2090,23 @@
/// Returns the JSName annotation string or `null` if no JSName annotation is
/// present.
- String _findJsNameFromAnnotation(MemberEntity element) {
- String jsName = null;
- for (ConstantValue value
- in _elementEnvironment.getMemberMetadata(element)) {
- String name = readAnnotationName(
- element, value, _commonElements.annotationJSNameClass);
- if (jsName == null) {
- jsName = name;
- } else if (name != null) {
- failedAt(element, 'Too many JSName annotations: ${value.toDartText()}');
+ String _findJsNameFromAnnotation(
+ MemberEntity element, IrAnnotationData annotationData) {
+ String jsName;
+ if (annotationData != null) {
+ jsName = annotationData
+ .getNativeMemberName(_elementMap.getMemberNode(element));
+ } else {
+ for (ConstantValue value
+ in _elementEnvironment.getMemberMetadata(element)) {
+ String name = readAnnotationName(
+ element, value, _commonElements.annotationJSNameClass);
+ if (jsName == null) {
+ jsName = name;
+ } else if (name != null) {
+ failedAt(
+ element, 'Too many JSName annotations: ${value.toDartText()}');
+ }
}
}
return jsName;
@@ -2077,28 +2117,63 @@
return _elementMap.getNativeBehaviorForFieldStore(node);
}
- NativeBehavior _computeNativeFieldLoadBehavior(covariant KField field,
+ NativeBehavior _computeNativeFieldLoadBehavior(
+ KField field, IrAnnotationData annotationData,
{bool isJsInterop}) {
ir.Field node = _elementMap.getMemberNode(field);
- return _elementMap.getNativeBehaviorForFieldLoad(node,
+ Iterable<String> createsAnnotations;
+ Iterable<String> returnsAnnotations;
+ if (annotationData != null) {
+ createsAnnotations = annotationData.getCreatesAnnotations(node);
+ returnsAnnotations = annotationData.getReturnsAnnotations(node);
+ } else {
+ List<ConstantValue> metadata =
+ _elementEnvironment.getMemberMetadata(field);
+ createsAnnotations = getCreatesAnnotations(
+ _elementMap.reporter, _elementMap.commonElements, metadata);
+ returnsAnnotations = getReturnsAnnotations(
+ _elementMap.reporter, _elementMap.commonElements, metadata);
+ }
+ return _elementMap.getNativeBehaviorForFieldLoad(
+ node, createsAnnotations, returnsAnnotations,
isJsInterop: isJsInterop);
}
- NativeBehavior _computeNativeMethodBehavior(covariant KFunction function,
+ NativeBehavior _computeNativeMethodBehavior(
+ KFunction function, IrAnnotationData annotationData,
{bool isJsInterop}) {
ir.Member node = _elementMap.getMemberNode(function);
- return _elementMap.getNativeBehaviorForMethod(node,
+ Iterable<String> createsAnnotations;
+ Iterable<String> returnsAnnotations;
+ if (annotationData != null) {
+ createsAnnotations = annotationData.getCreatesAnnotations(node);
+ returnsAnnotations = annotationData.getReturnsAnnotations(node);
+ } else {
+ List<ConstantValue> metadata =
+ _elementEnvironment.getMemberMetadata(function);
+ createsAnnotations = getCreatesAnnotations(
+ _elementMap.reporter, _elementMap.commonElements, metadata);
+ returnsAnnotations = getReturnsAnnotations(
+ _elementMap.reporter, _elementMap.commonElements, metadata);
+ }
+ return _elementMap.getNativeBehaviorForMethod(
+ node, createsAnnotations, returnsAnnotations,
isJsInterop: isJsInterop);
}
- bool _isNativeMethod(covariant KFunction function) {
+ bool _isNativeMethod(
+ covariant KFunction function, IrAnnotationData annotationData) {
if (!maybeEnableNative(function.library.canonicalUri)) return false;
ir.Member node = _elementMap.getMemberNode(function);
- return node.annotations.any((ir.Expression expression) {
- return expression is ir.ConstructorInvocation &&
- _elementMap.getInterfaceType(expression.constructedType) ==
- _commonElements.externalNameType;
- });
+ if (annotationData != null) {
+ return annotationData.hasNativeBody(node);
+ } else {
+ return node.annotations.any((ir.Expression expression) {
+ return expression is ir.ConstructorInvocation &&
+ _elementMap.getInterfaceType(expression.constructedType) ==
+ _commonElements.externalNameType;
+ });
+ }
}
bool _isJsInteropMember(MemberEntity element) {
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index a721968..b7c9246 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -285,6 +285,7 @@
/// Environment for fast lookup of class members.
class KClassEnvImpl implements KClassEnv {
+ @override
final ir.Class cls;
Map<String, ir.Member> _constructorMap;
@@ -301,8 +302,10 @@
KClassEnvImpl.internal(this.cls, this._constructorMap, this._memberMap,
this._setterMap, this._members, this._isSuperMixinApplication);
+ @override
bool get isUnnamedMixinApplication => cls.isAnonymousMixin;
+ @override
bool get isSuperMixinApplication {
assert(_isSuperMixinApplication != null);
return _isSuperMixinApplication;
@@ -354,6 +357,7 @@
initializers: <ir.Initializer>[superInitializer]);
}
+ @override
void ensureMembers(KernelToElementMapImpl elementMap) {
_ensureMaps(elementMap);
}
@@ -505,6 +509,7 @@
/// Return the [MemberEntity] for the member [name] in [cls]. If [setter] is
/// `true`, the setter or assignable field corresponding to [name] is
/// returned.
+ @override
MemberEntity lookupMember(IrToElementMap elementMap, String name,
{bool setter: false}) {
_ensureMaps(elementMap);
@@ -513,6 +518,7 @@
}
/// Calls [f] for each member of [cls].
+ @override
void forEachMember(IrToElementMap elementMap, void f(MemberEntity member)) {
_ensureMaps(elementMap);
_members.forEach((ir.Member member) {
@@ -521,6 +527,7 @@
}
/// Return the [ConstructorEntity] for the constructor [name] in [cls].
+ @override
ConstructorEntity lookupConstructor(IrToElementMap elementMap, String name) {
_ensureMaps(elementMap);
ir.Member constructor = _constructorMap[name];
@@ -528,6 +535,7 @@
}
/// Calls [f] for each constructor of [cls].
+ @override
void forEachConstructor(
IrToElementMap elementMap, void f(ConstructorEntity constructor)) {
_ensureMaps(elementMap);
@@ -541,10 +549,12 @@
_constructorBodyList.add(constructorBody);
}
+ @override
void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
_constructorBodyList?.forEach(f);
}
+ @override
JClassEnv convert(IrToElementMap elementMap,
Map<MemberEntity, MemberUsage> liveMemberUsage) {
Map<String, ir.Member> constructorMap;
@@ -621,30 +631,42 @@
}
class KClassDataImpl implements KClassData {
+ @override
final ir.Class node;
+ @override
bool isMixinApplication;
bool isCallTypeComputed = false;
+ @override
InterfaceType thisType;
+ @override
InterfaceType rawType;
+ @override
InterfaceType supertype;
+ @override
InterfaceType mixedInType;
+ @override
List<InterfaceType> interfaces;
+ @override
OrderedTypeSet orderedTypeSet;
Iterable<ConstantValue> _metadata;
KClassDataImpl(this.node);
+ @override
bool get isEnumClass => node.isEnum;
+ @override
DartType get callType => null;
+ @override
Iterable<ConstantValue> getMetadata(
covariant KernelToElementMapImpl elementMap) {
return _metadata ??= elementMap.getMetadata(node.annotations);
}
+ @override
JClassData convert() {
return new JClassDataImpl(node, new RegularClassDefinition(node));
}
@@ -666,19 +688,23 @@
}
abstract class KMemberDataImpl implements KMemberData {
+ @override
final ir.Member node;
Iterable<ConstantValue> _metadata;
+ @override
Map<ir.Expression, ir.DartType> staticTypes;
KMemberDataImpl(this.node);
+ @override
Iterable<ConstantValue> getMetadata(
covariant KernelToElementMapImpl elementMap) {
return _metadata ??= elementMap.getMetadata(node.annotations);
}
+ @override
InterfaceType getMemberThisType(JsToElementMap elementMap) {
MemberEntity member = elementMap.getMember(node);
ClassEntity cls = member.enclosingClass;
@@ -702,6 +728,7 @@
ir.FunctionNode get functionNode;
List<TypeVariableType> _typeVariables;
+ @override
List<TypeVariableType> getFunctionTypeVariables(
covariant KernelToElementMapImpl elementMap) {
if (_typeVariables == null) {
@@ -729,15 +756,18 @@
class KFunctionDataImpl extends KMemberDataImpl
with KFunctionDataMixin
implements KFunctionData {
+ @override
final ir.FunctionNode functionNode;
FunctionType _type;
KFunctionDataImpl(ir.Member node, this.functionNode) : super(node);
+ @override
FunctionType getFunctionType(covariant KernelToElementMapImpl elementMap) {
return _type ??= elementMap.getFunctionType(functionNode);
}
+ @override
void forEachParameter(JsToElementMap elementMap,
void f(DartType type, String name, ConstantValue defaultValue)) {
void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) {
@@ -789,6 +819,7 @@
KConstructorDataImpl(ir.Member node, ir.FunctionNode functionNode)
: super(node, functionNode);
+ @override
ConstantConstructor getConstructorConstant(
KernelToElementMapImpl elementMap, ConstructorEntity constructor) {
if (_constantConstructor == null) {
@@ -835,12 +866,15 @@
KFieldDataImpl(ir.Field node) : super(node);
+ @override
ir.Field get node => super.node;
+ @override
DartType getFieldType(covariant KernelToElementMapImpl elementMap) {
return _type ??= elementMap.getDartType(node.type);
}
+ @override
ConstantExpression getFieldConstantExpression(
KernelToElementMapImpl elementMap) {
if (_constantExpression == null) {
diff --git a/pkg/compiler/lib/src/kernel/front_end_adapter.dart b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
index 169237d..571f11f 100644
--- a/pkg/compiler/lib/src/kernel/front_end_adapter.dart
+++ b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
@@ -32,6 +32,7 @@
}
class _CompilerFileSystemEntity implements fe.FileSystemEntity {
+ @override
final Uri uri;
final CompilerFileSystem fs;
diff --git a/pkg/compiler/lib/src/kernel/kelements.dart b/pkg/compiler/lib/src/kernel/kelements.dart
index 2f1a8f5..1ac70af 100644
--- a/pkg/compiler/lib/src/kernel/kelements.dart
+++ b/pkg/compiler/lib/src/kernel/kelements.dart
@@ -13,18 +13,24 @@
const String kElementPrefix = 'k:';
class KLibrary extends IndexedLibrary {
+ @override
final String name;
+ @override
final Uri canonicalUri;
KLibrary(this.name, this.canonicalUri);
+ @override
String toString() => '${kElementPrefix}library($name)';
}
class KClass extends IndexedClass {
+ @override
final KLibrary library;
+ @override
final String name;
+ @override
final bool isAbstract;
KClass(this.library, this.name, {this.isAbstract});
@@ -32,21 +38,27 @@
@override
bool get isClosure => false;
+ @override
String toString() => '${kElementPrefix}class($name)';
}
class KTypedef extends IndexedTypedef {
+ @override
final KLibrary library;
+ @override
final String name;
KTypedef(this.library, this.name);
+ @override
String toString() => '${kElementPrefix}typedef($name)';
}
abstract class KMember extends IndexedMember {
+ @override
final KLibrary library;
+ @override
final KClass enclosingClass;
final Name _name;
final bool _isStatic;
@@ -54,8 +66,10 @@
KMember(this.library, this.enclosingClass, this._name, {bool isStatic: false})
: _isStatic = isStatic;
+ @override
String get name => _name.text;
+ @override
Name get memberName => _name;
@override
@@ -93,14 +107,18 @@
String get _kind;
+ @override
String toString() => '${kElementPrefix}$_kind'
'(${enclosingClass != null ? '${enclosingClass.name}.' : ''}$name)';
}
abstract class KFunction extends KMember
implements FunctionEntity, IndexedFunction {
+ @override
final ParameterStructure parameterStructure;
+ @override
final bool isExternal;
+ @override
final AsyncMarker asyncMarker;
KFunction(KLibrary library, KClass enclosingClass, Name name,
@@ -111,6 +129,7 @@
abstract class KConstructor extends KFunction
implements ConstructorEntity, IndexedConstructor {
+ @override
final bool isConst;
KConstructor(
@@ -135,6 +154,7 @@
@override
bool get isFromEnvironmentConstructor => false;
+ @override
String get _kind => 'constructor';
}
@@ -170,6 +190,7 @@
}
class KMethod extends KFunction {
+ @override
final bool isAbstract;
KMethod(KLibrary library, KClass enclosingClass, Name name,
@@ -181,10 +202,12 @@
@override
bool get isFunction => true;
+ @override
String get _kind => 'method';
}
class KGetter extends KFunction {
+ @override
final bool isAbstract;
KGetter(KLibrary library, KClass enclosingClass, Name name,
@@ -197,10 +220,12 @@
@override
bool get isGetter => true;
+ @override
String get _kind => 'getter';
}
class KSetter extends KFunction {
+ @override
final bool isAbstract;
KSetter(KLibrary library, KClass enclosingClass, Name name,
@@ -215,11 +240,14 @@
@override
bool get isSetter => true;
+ @override
String get _kind => 'setter';
}
class KField extends KMember implements FieldEntity, IndexedField {
+ @override
final bool isAssignable;
+ @override
final bool isConst;
KField(KLibrary library, KClass enclosingClass, Name name,
@@ -229,21 +257,27 @@
@override
bool get isField => true;
+ @override
String get _kind => 'field';
}
class KTypeVariable extends IndexedTypeVariable {
+ @override
final Entity typeDeclaration;
+ @override
final String name;
+ @override
final int index;
KTypeVariable(this.typeDeclaration, this.name, this.index);
+ @override
String toString() =>
'${kElementPrefix}type_variable(${typeDeclaration.name}.$name)';
}
class KLocalFunction implements Local {
+ @override
final String name;
final MemberEntity memberContext;
final Entity executableContext;
@@ -253,19 +287,24 @@
KLocalFunction(
this.name, this.memberContext, this.executableContext, this.node);
+ @override
String toString() => '${kElementPrefix}local_function'
'(${memberContext.name}.${name ?? '<anonymous>'})';
}
class KLocalTypeVariable implements TypeVariableEntity {
+ @override
final Entity typeDeclaration;
+ @override
final String name;
+ @override
final int index;
DartType bound;
DartType defaultType;
KLocalTypeVariable(this.typeDeclaration, this.name, this.index);
+ @override
String toString() =>
'${kElementPrefix}local_type_variable(${typeDeclaration.name}.$name)';
}
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index f65c5d6..2b2499e 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -21,6 +21,7 @@
import '../ir/util.dart';
import '../js_backend/annotations.dart';
import '../js_backend/native_data.dart';
+import '../native/behavior.dart';
import '../options.dart';
import '../resolution/registry.dart' show ResolutionWorldImpactBuilder;
import '../universe/call_structure.dart';
@@ -33,10 +34,15 @@
/// Visitor that computes the world impact of a member.
class KernelImpactBuilder extends ImpactBuilderBase
with KernelImpactRegistryMixin {
+ @override
final ResolutionWorldImpactBuilder impactBuilder;
+ @override
final KernelToElementMap elementMap;
+ @override
final DiagnosticReporter reporter;
+ @override
final CompilerOptions _options;
+ @override
final MemberEntity currentMember;
final Set<PragmaAnnotation> _annotations;
@@ -47,12 +53,16 @@
super(elementMap.typeEnvironment, elementMap.classHierarchy,
variableScopeModel);
+ @override
CommonElements get commonElements => elementMap.commonElements;
+ @override
NativeBasicData get _nativeBasicData => elementMap.nativeBasicData;
+ @override
bool get useAsserts => _options.enableUserAssertions;
+ @override
bool get inferEffectivelyFinalVariableTypes =>
!_annotations.contains(PragmaAnnotation.disableFinal);
}
@@ -60,10 +70,15 @@
/// Converts a [ImpactData] object based on kernel to the corresponding
/// [ResolutionImpact] based on the K model.
class KernelImpactConverter extends KernelImpactRegistryMixin {
+ @override
final ResolutionWorldImpactBuilder impactBuilder;
+ @override
final KernelToElementMap elementMap;
+ @override
final DiagnosticReporter reporter;
+ @override
final CompilerOptions _options;
+ @override
final MemberEntity currentMember;
KernelImpactConverter(
@@ -71,10 +86,13 @@
: this.impactBuilder =
new ResolutionWorldImpactBuilder('${currentMember}');
+ @override
ir.TypeEnvironment get typeEnvironment => elementMap.typeEnvironment;
+ @override
CommonElements get commonElements => elementMap.commonElements;
+ @override
NativeBasicData get _nativeBasicData => elementMap.nativeBasicData;
/// Converts a [ImpactData] object based on kernel to the corresponding
@@ -133,9 +151,18 @@
if (field.isInstanceMember &&
elementMap.isNativeClass(field.enclosingClass)) {
MemberEntity member = elementMap.getMember(field);
+ // TODO(johnniwinther): NativeDataBuilder already has the native behavior
+ // at this point. Use that instead.
bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
- impactBuilder.registerNativeData(elementMap
- .getNativeBehaviorForFieldLoad(field, isJsInterop: isJsInterop));
+ List<ConstantValue> metadata =
+ elementMap.elementEnvironment.getMemberMetadata(member);
+ Iterable<String> createsAnnotations =
+ getCreatesAnnotations(reporter, commonElements, metadata);
+ Iterable<String> returnsAnnotations =
+ getReturnsAnnotations(reporter, commonElements, metadata);
+ impactBuilder.registerNativeData(elementMap.getNativeBehaviorForFieldLoad(
+ field, createsAnnotations, returnsAnnotations,
+ isJsInterop: isJsInterop));
impactBuilder
.registerNativeData(elementMap.getNativeBehaviorForFieldStore(field));
}
@@ -145,9 +172,18 @@
void registerConstructorNode(ir.Constructor constructor) {
MemberEntity member = elementMap.getMember(constructor);
if (constructor.isExternal && !commonElements.isForeignHelper(member)) {
+ // TODO(johnniwinther): NativeDataBuilder already has the native behavior
+ // at this point. Use that instead.
bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
- impactBuilder.registerNativeData(elementMap
- .getNativeBehaviorForMethod(constructor, isJsInterop: isJsInterop));
+ List<ConstantValue> metadata =
+ elementMap.elementEnvironment.getMemberMetadata(member);
+ Iterable<String> createsAnnotations =
+ getCreatesAnnotations(reporter, commonElements, metadata);
+ Iterable<String> returnsAnnotations =
+ getReturnsAnnotations(reporter, commonElements, metadata);
+ impactBuilder.registerNativeData(elementMap.getNativeBehaviorForMethod(
+ constructor, createsAnnotations, returnsAnnotations,
+ isJsInterop: isJsInterop));
}
}
@@ -182,9 +218,18 @@
void registerProcedureNode(ir.Procedure procedure) {
MemberEntity member = elementMap.getMember(procedure);
if (procedure.isExternal && !commonElements.isForeignHelper(member)) {
+ // TODO(johnniwinther): NativeDataBuilder already has the native behavior
+ // at this point. Use that instead.
bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
- impactBuilder.registerNativeData(elementMap
- .getNativeBehaviorForMethod(procedure, isJsInterop: isJsInterop));
+ List<ConstantValue> metadata =
+ elementMap.elementEnvironment.getMemberMetadata(member);
+ Iterable<String> createsAnnotations =
+ getCreatesAnnotations(reporter, commonElements, metadata);
+ Iterable<String> returnsAnnotations =
+ getReturnsAnnotations(reporter, commonElements, metadata);
+ impactBuilder.registerNativeData(elementMap.getNativeBehaviorForMethod(
+ procedure, createsAnnotations, returnsAnnotations,
+ isJsInterop: isJsInterop));
}
}
@@ -284,6 +329,7 @@
}
}
+ @override
void registerConstConstructorInvocationNode(ir.ConstructorInvocation node) {
assert(node.isConst);
ConstructorEntity constructor = elementMap.getConstructor(node.target);
@@ -669,6 +715,7 @@
impactBuilder.registerFeature(Feature.THROW_EXPRESSION);
}
+ @override
void registerSyncForIn(ir.DartType iterableType) {
// TODO(johnniwinther): Use receiver constraints for the dynamic uses in
// strong mode.
@@ -678,6 +725,7 @@
impactBuilder.registerDynamicUse(new DynamicUse(Selectors.moveNext));
}
+ @override
void registerAsyncForIn(ir.DartType iterableType) {
// TODO(johnniwinther): Use receiver constraints for the dynamic uses in
// strong mode.
@@ -687,14 +735,17 @@
impactBuilder.registerDynamicUse(new DynamicUse(Selectors.moveNext));
}
+ @override
void registerCatch() {
impactBuilder.registerFeature(Feature.CATCH_STATEMENT);
}
+ @override
void registerStackTrace() {
impactBuilder.registerFeature(Feature.STACK_TRACE_IN_CATCH);
}
+ @override
void registerCatchType(ir.DartType type) {
impactBuilder
.registerTypeUse(new TypeUse.catchType(elementMap.getDartType(type)));
@@ -734,9 +785,8 @@
@override
void registerConstant(ir.ConstantExpression node) {
- // ignore: unused_local_variable
ConstantValue value = elementMap.getConstantValue(node);
- // TODO(johnniwinther,fishythefish): Register the constant.
+ impactBuilder.registerConstantUse(new ConstantUse.literal(value));
}
@override
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 7feda83..46f5293 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -4,6 +4,8 @@
library dart2js.kernel.frontend_strategy;
+import 'package:kernel/ast.dart' as ir;
+
import '../common.dart';
import '../common/backend_api.dart';
import '../common/resolution.dart';
@@ -19,6 +21,8 @@
import '../frontend_strategy.dart';
import '../ir/annotations.dart';
import '../ir/closure.dart' show ClosureScopeModel;
+import '../ir/impact.dart';
+import '../ir/modular.dart';
import '../ir/scope.dart' show ScopeModel;
import '../js_backend/annotations.dart';
import '../js_backend/field_analysis.dart' show KFieldAnalysis;
@@ -34,6 +38,7 @@
import '../universe/resolution_world_builder.dart';
import '../universe/world_builder.dart';
import '../universe/world_impact.dart';
+import '../util/enumset.dart';
import 'deferred_load.dart';
import 'element_map.dart';
import 'element_map_impl.dart';
@@ -51,26 +56,38 @@
final Map<MemberEntity, ClosureScopeModel> closureModels = {};
+ ModularStrategy _modularStrategy;
+ IrAnnotationData _irAnnotationData;
+
KernelFrontEndStrategy(this._compilerTask, this._options,
DiagnosticReporter reporter, env.Environment environment) {
assert(_compilerTask != null);
_elementMap =
new KernelToElementMapImpl(reporter, environment, this, _options);
+ _modularStrategy = new KernelModularStrategy(_compilerTask, _elementMap);
}
@override
void registerLoadedLibraries(KernelResult kernelResult) {
_elementMap.addComponent(kernelResult.component);
- _annotationProcessor = new KernelAnnotationProcessor(elementMap,
- nativeBasicDataBuilder, processAnnotations(kernelResult.component));
+ if (useIrAnnotationsDataForTesting) {
+ _irAnnotationData = processAnnotations(kernelResult.component);
+ }
+ _annotationProcessor = new KernelAnnotationProcessor(
+ elementMap, nativeBasicDataBuilder, _irAnnotationData);
}
+ IrAnnotationData get irAnnotationDataForTesting => _irAnnotationData;
+
+ ModularStrategy get modularStrategyForTesting => _modularStrategy;
+
@override
ElementEnvironment get elementEnvironment => _elementMap.elementEnvironment;
@override
CommonElements get commonElements => _elementMap.commonElements;
+ @override
DartTypes get dartTypes => _elementMap.types;
KernelToElementMap get elementMap => _elementMap;
@@ -92,16 +109,19 @@
_elementMap.elementEnvironment, nativeBasicData);
}
+ @override
NoSuchMethodResolver createNoSuchMethodResolver() {
return new KernelNoSuchMethodResolver(elementMap);
}
/// Computes the main function from [mainLibrary] adding additional world
/// impact to [impactBuilder].
+ @override
FunctionEntity computeMain(WorldImpactBuilder impactBuilder) {
return elementEnvironment.mainFunction;
}
+ @override
RuntimeTypesNeedBuilder createRuntimeTypesNeedBuilder() {
return _runtimeTypesNeedBuilder ??= _options.disableRtiOptimization
? const TrivialRuntimeTypesNeedBuilder()
@@ -109,9 +129,11 @@
elementEnvironment, _elementMap.types);
}
+ @override
RuntimeTypesNeedBuilder get runtimeTypesNeedBuilderForTesting =>
_runtimeTypesNeedBuilder;
+ @override
ResolutionWorldBuilder createResolutionWorldBuilder(
NativeBasicData nativeBasicData,
NativeDataBuilder nativeDataBuilder,
@@ -162,9 +184,12 @@
impactTransformer,
closureModels,
impactCache,
- fieldAnalysis);
+ fieldAnalysis,
+ _modularStrategy,
+ _irAnnotationData);
}
+ @override
ClassQueries createClassQueries() {
return new KernelClassQueries(elementMap);
}
@@ -184,6 +209,8 @@
final Map<MemberEntity, ClosureScopeModel> _closureModels;
final Map<Entity, WorldImpact> _impactCache;
final KFieldAnalysis _fieldAnalysis;
+ final ModularStrategy _modularStrategy;
+ final IrAnnotationData _irAnnotationData;
KernelWorkItemBuilder(
this._compilerTask,
@@ -194,7 +221,9 @@
this._impactTransformer,
this._closureModels,
this._impactCache,
- this._fieldAnalysis)
+ this._fieldAnalysis,
+ this._modularStrategy,
+ this._irAnnotationData)
: _nativeMemberResolver = new KernelNativeMemberResolver(
_elementMap, nativeBasicData, nativeDataBuilder);
@@ -209,7 +238,9 @@
entity,
_closureModels,
_impactCache,
- _fieldAnalysis);
+ _fieldAnalysis,
+ _modularStrategy,
+ _irAnnotationData);
}
}
@@ -219,10 +250,13 @@
final ImpactTransformer _impactTransformer;
final NativeMemberResolver _nativeMemberResolver;
final AnnotationsDataBuilder _annotationsDataBuilder;
+ @override
final MemberEntity element;
final Map<MemberEntity, ClosureScopeModel> _closureModels;
final Map<Entity, WorldImpact> _impactCache;
final KFieldAnalysis _fieldAnalysis;
+ final ModularStrategy _modularStrategy;
+ final IrAnnotationData _irAnnotationData;
KernelWorkItem(
this._compilerTask,
@@ -233,33 +267,44 @@
this.element,
this._closureModels,
this._impactCache,
- this._fieldAnalysis);
+ this._fieldAnalysis,
+ this._modularStrategy,
+ this._irAnnotationData);
@override
WorldImpact run() {
return _compilerTask.measure(() {
- _nativeMemberResolver.resolveNativeMember(element);
- Set<PragmaAnnotation> annotations = processMemberAnnotations(
+ _nativeMemberResolver.resolveNativeMember(element, _irAnnotationData);
+ ir.Member node = _elementMap.getMemberNode(element);
+
+ List<PragmaAnnotationData> pragmaAnnotationData =
+ _modularStrategy.getPragmaAnnotationData(node);
+
+ EnumSet<PragmaAnnotation> annotations = processMemberAnnotations(
_elementMap.options,
_elementMap.reporter,
- _elementMap.commonElements,
- _elementMap.elementEnvironment,
- _annotationsDataBuilder,
- element);
- ScopeModel scopeModel = _compilerTask.measureSubtask('closures', () {
- ScopeModel scopeModel = _elementMap.computeScopeModel(element);
- if (scopeModel?.closureScopeModel != null) {
- _closureModels[element] = scopeModel.closureScopeModel;
- }
- if (element.isField && !element.isInstanceMember) {
- _fieldAnalysis.registerStaticField(
- element, scopeModel?.initializerComplexity);
- }
- return scopeModel;
- });
+ _elementMap.getMemberNode(element),
+ pragmaAnnotationData);
+ _annotationsDataBuilder.registerPragmaAnnotations(element, annotations);
+
+ ModularMemberData modularMemberData =
+ _modularStrategy.getModularMemberData(node, annotations);
+ ScopeModel scopeModel = modularMemberData.scopeModel;
+ if (scopeModel.closureScopeModel != null) {
+ _closureModels[element] = scopeModel.closureScopeModel;
+ }
+ if (element.isField && !element.isInstanceMember) {
+ _fieldAnalysis.registerStaticField(
+ element, scopeModel.initializerComplexity);
+ }
+ ImpactBuilderData impactBuilderData = modularMemberData.impactBuilderData;
return _compilerTask.measureSubtask('worldImpact', () {
ResolutionImpact impact = _elementMap.computeWorldImpact(
- element, scopeModel?.variableScopeModel, annotations);
+ element,
+ scopeModel.variableScopeModel,
+ new Set<PragmaAnnotation>.from(
+ annotations.iterable(PragmaAnnotation.values)),
+ impactBuilderData: impactBuilderData);
WorldImpact worldImpact =
_impactTransformer.transformResolutionImpact(impact);
if (_impactCache != null) {
@@ -270,3 +315,52 @@
});
}
}
+
+/// If `true` kernel impacts are computed as [ImpactData] directly on kernel
+/// and converted to the K model afterwards. This is a pre-step to modularizing
+/// the world impact computation.
+bool useImpactDataForTesting = false;
+
+/// If `true` pragma annotations are computed directly on kernel. This is a
+/// pre-step to modularizing the world impact computation.
+bool useIrAnnotationsDataForTesting = false;
+
+class KernelModularStrategy extends ModularStrategy {
+ final CompilerTask _compilerTask;
+ final KernelToElementMapImpl _elementMap;
+
+ KernelModularStrategy(this._compilerTask, this._elementMap);
+
+ @override
+ List<PragmaAnnotationData> getPragmaAnnotationData(ir.Member node) {
+ if (useIrAnnotationsDataForTesting) {
+ return computePragmaAnnotationDataFromIr(node);
+ } else {
+ return computePragmaAnnotationData(_elementMap.commonElements,
+ _elementMap.elementEnvironment, _elementMap.getMember(node));
+ }
+ }
+
+ @override
+ ModularMemberData getModularMemberData(
+ ir.Member node, EnumSet<PragmaAnnotation> annotations) {
+ ScopeModel scopeModel = _compilerTask.measureSubtask(
+ 'closures', () => new ScopeModel.from(node));
+ ImpactBuilderData impactBuilderData;
+ if (useImpactDataForTesting) {
+ // TODO(johnniwinther): Always create and use the [ImpactBuilderData].
+ // Currently it is a bit half-baked since we cannot compute data that
+ // depend on metadata, so these parts of the impact data need to be
+ // computed during conversion to [ResolutionImpact].
+ impactBuilderData = _compilerTask.measureSubtask('worldImpact', () {
+ ImpactBuilder builder = new ImpactBuilder(_elementMap.typeEnvironment,
+ _elementMap.classHierarchy, scopeModel.variableScopeModel,
+ useAsserts: _elementMap.options.enableUserAssertions,
+ inferEffectivelyFinalVariableTypes:
+ !annotations.contains(PragmaAnnotation.disableFinal));
+ return builder.computeImpact(node);
+ });
+ }
+ return new ModularMemberData(scopeModel, impactBuilderData);
+ }
+}
diff --git a/pkg/compiler/lib/src/kernel/kernel_world.dart b/pkg/compiler/lib/src/kernel/kernel_world.dart
index 673ba75..053c528 100644
--- a/pkg/compiler/lib/src/kernel/kernel_world.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_world.dart
@@ -24,33 +24,49 @@
class KClosedWorldImpl implements KClosedWorld {
final KernelToElementMapImpl elementMap;
+ @override
final KElementEnvironment elementEnvironment;
+ @override
final DartTypes dartTypes;
+ @override
final KCommonElements commonElements;
+ @override
final NativeData nativeData;
+ @override
final InterceptorData interceptorData;
+ @override
final BackendUsage backendUsage;
+ @override
final NoSuchMethodData noSuchMethodData;
+ @override
final Map<ClassEntity, Set<ClassEntity>> mixinUses;
+ @override
final Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses;
// TODO(johnniwinther): Can this be derived from [ClassSet]s?
final Set<ClassEntity> _implementedClasses;
+ @override
final Iterable<MemberEntity> liveInstanceMembers;
/// Members that are written either directly or through a setter selector.
+ @override
final Iterable<MemberEntity> assignedInstanceMembers;
+ @override
final KFieldAnalysis fieldAnalysis;
+ @override
final Iterable<ClassEntity> liveNativeClasses;
+ @override
final Map<MemberEntity, MemberUsage> liveMemberUsage;
+ @override
final ClassHierarchy classHierarchy;
+ @override
final AnnotationsData annotationsData;
RuntimeTypesNeed _rtiNeed;
@@ -81,9 +97,11 @@
resolutionWorldBuilder, this, options);
}
+ @override
RuntimeTypesNeed get rtiNeed => _rtiNeed;
/// Returns `true` if [cls] is implemented by an instantiated class.
+ @override
bool isImplemented(ClassEntity cls) {
return _implementedClasses.contains(cls);
}
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index 7b56f28..b972976 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -51,6 +51,7 @@
: initializedCompilerState = _options.kernelInitializedCompilerState,
super(measurer);
+ @override
String get name => 'kernel loader';
/// Loads an entire Kernel [Component] from a file on disk.
@@ -157,5 +158,6 @@
assert(rootLibraryUri != null);
}
+ @override
String toString() => 'root=$rootLibraryUri,libraries=${libraries}';
}
diff --git a/pkg/compiler/lib/src/kernel/native_basic_data.dart b/pkg/compiler/lib/src/kernel/native_basic_data.dart
index 8bcc052..745afa5 100644
--- a/pkg/compiler/lib/src/kernel/native_basic_data.dart
+++ b/pkg/compiler/lib/src/kernel/native_basic_data.dart
@@ -13,14 +13,17 @@
KernelAnnotationProcessor(
this.elementMap, this._nativeBasicDataBuilder, this.annotationData);
+ @override
void extractNativeAnnotations(LibraryEntity library) {
KElementEnvironment elementEnvironment = elementMap.elementEnvironment;
KCommonElements commonElements = elementMap.commonElements;
elementEnvironment.forEachClass(library, (ClassEntity cls) {
ir.Class node = elementMap.getClassNode(cls);
- String annotationName = annotationData.getNativeClassName(node);
- if (annotationName == null) {
+ String annotationName;
+ if (annotationData != null) {
+ annotationName = annotationData.getNativeClassName(node);
+ } else {
// TODO(johnniwinther): Remove this branch when we use constants from
// CFE.
for (ConstantValue value in elementEnvironment.getClassMetadata(cls)) {
@@ -66,25 +69,34 @@
}
}
+ @override
void extractJsInteropAnnotations(LibraryEntity library) {
DiagnosticReporter reporter = elementMap.reporter;
KElementEnvironment elementEnvironment = elementMap.elementEnvironment;
KCommonElements commonElements = elementMap.commonElements;
ir.Library libraryNode = elementMap.getLibraryNode(library);
- String libraryName = annotationData.getJsInteropLibraryName(libraryNode);
- // TODO(johnniwinther): Remove this when we use constants from CFE.
- libraryName ??= getJsInteropName(
- library, elementEnvironment.getLibraryMetadata(library));
+ String libraryName;
+ if (annotationData != null) {
+ libraryName = annotationData.getJsInteropLibraryName(libraryNode);
+ } else {
+ // TODO(johnniwinther): Remove this when we use constants from CFE.
+ libraryName = getJsInteropName(
+ library, elementEnvironment.getLibraryMetadata(library));
+ }
final bool isExplicitlylyJsLibrary = libraryName != null;
bool isJsLibrary = isExplicitlylyJsLibrary;
elementEnvironment.forEachLibraryMember(library, (MemberEntity member) {
ir.Member memberNode = elementMap.getMemberNode(member);
- String memberName = annotationData.getJsInteropMemberName(memberNode);
- // TODO(johnniwinther): Remove this when we use constants from CFE.
- memberName ??= getJsInteropName(
- library, elementEnvironment.getMemberMetadata(member));
+ String memberName;
+ if (annotationData != null) {
+ memberName = annotationData.getJsInteropMemberName(memberNode);
+ } else {
+ // TODO(johnniwinther): Remove this when we use constants from CFE.
+ memberName = getJsInteropName(
+ library, elementEnvironment.getMemberMetadata(member));
+ }
if (member.isField) {
if (memberName != null) {
// TODO(34174): Disallow js-interop fields.
@@ -119,15 +131,22 @@
});
elementEnvironment.forEachClass(library, (ClassEntity cls) {
+ Iterable<ConstantValue> metadata;
ir.Class classNode = elementMap.getClassNode(cls);
- String className = annotationData.getJsInteropClassName(classNode);
- Iterable<ConstantValue> metadata =
- elementEnvironment.getClassMetadata(cls);
- // TODO(johnniwinther): Remove this when we use constants from CFE.
- className ??= getJsInteropName(cls, metadata);
+ String className;
+ if (annotationData != null) {
+ className = annotationData.getJsInteropClassName(classNode);
+ } else {
+ metadata = elementEnvironment.getClassMetadata(cls);
+ // TODO(johnniwinther): Remove this when we use constants from CFE.
+ className = getJsInteropName(cls, metadata);
+ }
if (className != null) {
- bool isAnonymous = annotationData.isAnonymousJsInteropClass(classNode);
- if (!isAnonymous) {
+ bool isAnonymous;
+ if (annotationData != null) {
+ isAnonymous = annotationData.isAnonymousJsInteropClass(classNode);
+ } else {
+ isAnonymous = false;
// TODO(johnniwinther): Remove this branch when we use constants from
// CFE.
for (ConstantValue value in metadata) {
@@ -153,12 +172,14 @@
} else {
FunctionEntity function = member;
ir.Member memberNode = elementMap.getMemberNode(member);
- String memberName =
- annotationData.getJsInteropMemberName(memberNode);
- // TODO(johnniwinther): Remove this when we use constants from CFE.
- memberName ??= getJsInteropName(
- library, elementEnvironment.getMemberMetadata(function));
-
+ String memberName;
+ if (annotationData != null) {
+ memberName = annotationData.getJsInteropMemberName(memberNode);
+ } else {
+ // TODO(johnniwinther): Remove this when we use constants from CFE.
+ memberName = getJsInteropName(
+ library, elementEnvironment.getMemberMetadata(function));
+ }
if (function.isExternal) {
memberName ??= function.name;
}
@@ -278,10 +299,14 @@
// it.
elementEnvironment.forEachClass(library, (ClassEntity cls) {
ir.Class classNode = elementMap.getClassNode(cls);
- String className = annotationData.getJsInteropClassName(classNode);
- // TODO(johnniwinther): Remove this when we use constants from CFE.
- className ??=
- getJsInteropName(cls, elementEnvironment.getClassMetadata(cls));
+ String className;
+ if (annotationData != null) {
+ className = annotationData.getJsInteropClassName(classNode);
+ } else {
+ // TODO(johnniwinther): Remove this when we use constants from CFE.
+ className ??=
+ getJsInteropName(cls, elementEnvironment.getClassMetadata(cls));
+ }
if (className != null) {
bool implementsJsJavaScriptObjectClass = false;
elementEnvironment.forEachSupertype(cls, (InterfaceType supertype) {
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 07e03da..5bb7e12 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -24,8 +24,10 @@
/// The type Object, but no subtypes:
static const JsObject = const SpecialType._('=Object');
+ @override
int get hashCode => name.hashCode;
+ @override
String toString() => name;
static SpecialType fromName(String name) {
@@ -68,6 +70,7 @@
return this;
}
+ @override
String toString() {
if (this == NEVER) return 'never';
if (this == MAY) return 'may';
@@ -258,6 +261,7 @@
sink.end(tag);
}
+ @override
String toString() {
return 'NativeBehavior('
'returns: ${typesReturned}'
@@ -736,14 +740,12 @@
NativeBehavior _behavior;
- void _overrideWithAnnotations(
- Iterable<ConstantValue> metadata, TypeLookup lookupType) {
- if (metadata.isEmpty) return;
+ void _overrideWithAnnotations(Iterable<String> createsAnnotations,
+ Iterable<String> returnsAnnotations, TypeLookup lookupType) {
+ if (createsAnnotations.isEmpty && returnsAnnotations.isEmpty) return;
- List creates =
- _collect(metadata, commonElements.annotationCreatesClass, lookupType);
- List returns =
- _collect(metadata, commonElements.annotationReturnsClass, lookupType);
+ List creates = _collect(createsAnnotations, lookupType);
+ List returns = _collect(returnsAnnotations, lookupType);
if (creates != null) {
_behavior.typesInstantiated
@@ -760,22 +762,9 @@
/// Returns a list of type constraints from the annotations of
/// [annotationClass].
/// Returns `null` if no constraints.
- List _collect(Iterable<ConstantValue> metadata, ClassEntity annotationClass,
- TypeLookup lookupType) {
+ List _collect(Iterable<String> annotations, TypeLookup lookupType) {
var types = null;
- for (ConstantValue value in metadata) {
- if (!value.isConstructedObject) continue;
- ConstructedConstantValue constructedObject = value;
- if (constructedObject.type.element != annotationClass) continue;
-
- Iterable<ConstantValue> fields = constructedObject.fields.values;
- // TODO(sra): Better validation of the constant.
- if (fields.length != 1 || !fields.single.isString) {
- reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
- 'Annotations needs one string: ${value.toStructuredText()}');
- }
- StringConstantValue specStringConstant = fields.single;
- String specString = specStringConstant.stringValue;
+ for (String specString in annotations) {
for (final typeString in specString.split('|')) {
var type = NativeBehavior._parseType(typeString, lookupType);
if (types == null) types = [];
@@ -847,7 +836,10 @@
}
NativeBehavior buildFieldLoadBehavior(
- DartType type, Iterable<ConstantValue> metadata, TypeLookup lookupType,
+ DartType type,
+ Iterable<String> createsAnnotations,
+ Iterable<String> returnsAnnotations,
+ TypeLookup lookupType,
{bool isJsInterop}) {
_behavior = new NativeBehavior();
// TODO(sigmund,sra): consider doing something better for numeric types.
@@ -857,7 +849,8 @@
// Declared types are nullable.
_behavior.typesReturned.add(commonElements.nullType);
_capture(type, isJsInterop);
- _overrideWithAnnotations(metadata, lookupType);
+ _overrideWithAnnotations(
+ createsAnnotations, returnsAnnotations, lookupType);
return _behavior;
}
@@ -869,8 +862,11 @@
return _behavior;
}
- NativeBehavior buildMethodBehavior(FunctionType type,
- Iterable<ConstantValue> metadata, TypeLookup lookupType,
+ NativeBehavior buildMethodBehavior(
+ FunctionType type,
+ Iterable<String> createAnnotations,
+ Iterable<String> returnsAnnotations,
+ TypeLookup lookupType,
{bool isJsInterop}) {
_behavior = new NativeBehavior();
DartType returnType = type.returnType;
@@ -899,7 +895,40 @@
_escape(type, isJsInterop);
}
- _overrideWithAnnotations(metadata, lookupType);
+ _overrideWithAnnotations(createAnnotations, returnsAnnotations, lookupType);
return _behavior;
}
}
+
+List<String> _getAnnotations(DiagnosticReporter reporter,
+ Iterable<ConstantValue> metadata, ClassEntity cls) {
+ List<String> annotations = [];
+ for (ConstantValue value in metadata) {
+ if (!value.isConstructedObject) continue;
+ ConstructedConstantValue constructedObject = value;
+ if (constructedObject.type.element != cls) continue;
+
+ Iterable<ConstantValue> fields = constructedObject.fields.values;
+ // TODO(sra): Better validation of the constant.
+ if (fields.length != 1 || !fields.single.isString) {
+ reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
+ 'Annotations needs one string: ${value.toStructuredText()}');
+ }
+ StringConstantValue specStringConstant = fields.single;
+ String specString = specStringConstant.stringValue;
+ annotations.add(specString);
+ }
+ return annotations;
+}
+
+List<String> getCreatesAnnotations(DiagnosticReporter reporter,
+ CommonElements commonElements, Iterable<ConstantValue> metadata) {
+ return _getAnnotations(
+ reporter, metadata, commonElements.annotationCreatesClass);
+}
+
+List<String> getReturnsAnnotations(DiagnosticReporter reporter,
+ CommonElements commonElements, Iterable<ConstantValue> metadata) {
+ return _getAnnotations(
+ reporter, metadata, commonElements.annotationReturnsClass);
+}
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index dfd4b8f..4552d00 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -40,6 +40,7 @@
final Set<ClassEntity> _registeredClasses = new Set<ClassEntity>();
final Set<ClassEntity> _unusedClasses = new Set<ClassEntity>();
+ @override
bool get hasInstantiatedNativeClasses => !_registeredClasses.isEmpty;
/// Log message reported if all native types are used.
@@ -56,6 +57,7 @@
bool get enableLiveTypeAnalysis => _options.enableNativeLiveTypeAnalysis;
+ @override
void onInstantiatedType(InterfaceType type) {
if (_unusedClasses.remove(type.element)) {
_registeredClasses.add(type.element);
@@ -77,6 +79,7 @@
}
}
+ @override
void registerNativeBehavior(
WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {
_processNativeBehavior(impactBuilder, nativeBehavior, cause);
@@ -161,6 +164,7 @@
});
}
+ @override
void logSummary(void log(String message)) {
if (_allUsedMessage != null) {
log(_allUsedMessage);
@@ -189,6 +193,7 @@
Iterable<ClassEntity> get liveNativeClasses => _registeredClasses;
+ @override
WorldImpact processNativeClasses(Iterable<Uri> libraries) {
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
Iterable<ClassEntity> nativeClasses =
@@ -201,6 +206,7 @@
return impactBuilder;
}
+ @override
void logSummary(void log(String message)) {
super.logSummary(log);
log('Resolved ${_registeredClasses.length} native elements used, '
@@ -225,6 +231,7 @@
this._nativeData)
: super(options, elementEnvironment, commonElements, dartTypes);
+ @override
WorldImpact processNativeClasses(Iterable<Uri> libraries) {
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
_unusedClasses.addAll(_nativeClasses);
@@ -247,6 +254,7 @@
return impactBuilder;
}
+ @override
void _registerTypeUses(
WorldImpactBuilder impactBuilder, Set<ClassEntity> classes, cause) {
super._registerTypeUses(impactBuilder, classes, cause);
@@ -288,6 +296,7 @@
directSubtypes.add(cls);
}
+ @override
void logSummary(void log(String message)) {
super.logSummary(log);
log('Compiled ${_registeredClasses.length} native classes, '
diff --git a/pkg/compiler/lib/src/native/js.dart b/pkg/compiler/lib/src/native/js.dart
index 0c83197..bbc8bd0 100644
--- a/pkg/compiler/lib/src/native/js.dart
+++ b/pkg/compiler/lib/src/native/js.dart
@@ -41,18 +41,21 @@
node.accept(this);
}
+ @override
void visitLiteralExpression(js.LiteralExpression node) {
sideEffects.setAllSideEffects();
sideEffects.setDependsOnSomething();
node.visitChildren(this);
}
+ @override
void visitLiteralStatement(js.LiteralStatement node) {
sideEffects.setAllSideEffects();
sideEffects.setDependsOnSomething();
node.visitChildren(this);
}
+ @override
void visitAssignment(js.Assignment node) {
sideEffects.setChangesStaticProperty();
sideEffects.setChangesInstanceProperty();
@@ -60,32 +63,38 @@
node.visitChildren(this);
}
+ @override
void visitVariableInitialization(js.VariableInitialization node) {
node.visitChildren(this);
}
+ @override
void visitCall(js.Call node) {
sideEffects.setAllSideEffects();
sideEffects.setDependsOnSomething();
node.visitChildren(this);
}
+ @override
void visitBinary(js.Binary node) {
node.visitChildren(this);
}
+ @override
void visitThrow(js.Throw node) {
// TODO(ngeoffray): Incorporate a mayThrow flag in the
// [SideEffects] class.
sideEffects.setAllSideEffects();
}
+ @override
void visitNew(js.New node) {
sideEffects.setAllSideEffects();
sideEffects.setDependsOnSomething();
node.visitChildren(this);
}
+ @override
void visitPrefix(js.Prefix node) {
if (node.op == 'delete') {
sideEffects.setChangesStaticProperty();
@@ -95,14 +104,17 @@
node.visitChildren(this);
}
+ @override
void visitVariableUse(js.VariableUse node) {
sideEffects.setDependsOnStaticPropertyStore();
}
+ @override
void visitPostfix(js.Postfix node) {
node.visitChildren(this);
}
+ @override
void visitAccess(js.PropertyAccess node) {
sideEffects.setDependsOnIndexStore();
sideEffects.setDependsOnInstancePropertyStore();
@@ -149,43 +161,53 @@
return node.accept(this);
}
+ @override
NativeThrowBehavior visitNode(js.Node node) {
return NativeThrowBehavior.MAY;
}
+ @override
NativeThrowBehavior visitLiteral(js.Literal node) {
return NativeThrowBehavior.NEVER;
}
+ @override
NativeThrowBehavior visitInterpolatedExpression(js.InterpolatedNode node) {
return NativeThrowBehavior.NEVER;
}
+ @override
NativeThrowBehavior visitInterpolatedSelector(js.InterpolatedNode node) {
return NativeThrowBehavior.NEVER;
}
+ @override
NativeThrowBehavior visitArrayInitializer(js.ArrayInitializer node) {
return node.elements.map(visit).fold(NativeThrowBehavior.NEVER, sequence);
}
+ @override
NativeThrowBehavior visitArrayHole(js.ArrayHole node) {
return NativeThrowBehavior.NEVER;
}
+ @override
NativeThrowBehavior visitObjectInitializer(js.ObjectInitializer node) {
return node.properties.map(visit).fold(NativeThrowBehavior.NEVER, sequence);
}
+ @override
NativeThrowBehavior visitProperty(js.Property node) {
return sequence(visit(node.name), visit(node.value));
}
+ @override
NativeThrowBehavior visitAssignment(js.Assignment node) {
// TODO(sra): Can we make "#.p = #" be null(1)?
return NativeThrowBehavior.MAY;
}
+ @override
NativeThrowBehavior visitCall(js.Call node) {
js.Expression target = node.target;
if (target is js.PropertyAccess && _isFirstInterpolatedProperty(target)) {
@@ -201,11 +223,13 @@
return NativeThrowBehavior.MAY;
}
+ @override
NativeThrowBehavior visitNew(js.New node) {
// TODO(sra): `new Array(x)` where `x` is a small number.
return NativeThrowBehavior.MAY;
}
+ @override
NativeThrowBehavior visitBinary(js.Binary node) {
NativeThrowBehavior left = visit(node.left);
NativeThrowBehavior right = visit(node.right);
@@ -248,10 +272,12 @@
}
}
+ @override
NativeThrowBehavior visitThrow(js.Throw node) {
return sequence(visit(node.expression), NativeThrowBehavior.MAY);
}
+ @override
NativeThrowBehavior visitPrefix(js.Prefix node) {
if (node.op == 'typeof' && node.argument is js.VariableUse)
return NativeThrowBehavior.NEVER;
@@ -269,6 +295,7 @@
}
}
+ @override
NativeThrowBehavior visitVariableUse(js.VariableUse node) {
// We could get a ReferenceError unless the variable is in scope. The AST
// could distinguish in-scope and out-of scope references. For JS fragments,
@@ -284,6 +311,7 @@
}
}
+ @override
NativeThrowBehavior visitAccess(js.PropertyAccess node) {
js.Node receiver = node.receiver;
NativeThrowBehavior first = visit(receiver);
diff --git a/pkg/compiler/lib/src/native/resolver.dart b/pkg/compiler/lib/src/native/resolver.dart
index 2b4ad8a..8a9ed11 100644
--- a/pkg/compiler/lib/src/native/resolver.dart
+++ b/pkg/compiler/lib/src/native/resolver.dart
@@ -6,12 +6,14 @@
import '../common_elements.dart' show KElementEnvironment;
import '../constants/values.dart';
import '../elements/entities.dart';
+import '../ir/annotations.dart';
import '../js_backend/native_data.dart';
/// Interface for computing native members.
abstract class NativeMemberResolver {
/// Computes whether [element] is native or JsInterop.
- void resolveNativeMember(MemberEntity element);
+ void resolveNativeMember(
+ MemberEntity element, IrAnnotationData annotationData);
}
/// Determines all native classes in a set of libraries.
@@ -28,6 +30,7 @@
BaseNativeClassFinder(this._elementEnvironment, this._nativeBasicData);
+ @override
Iterable<ClassEntity> computeNativeClasses(Iterable<Uri> libraries) {
Set<ClassEntity> nativeClasses = new Set<ClassEntity>();
libraries.forEach((uri) => _processNativeClassesInLibrary(
diff --git a/pkg/compiler/lib/src/null_compiler_output.dart b/pkg/compiler/lib/src/null_compiler_output.dart
index 95206bb..b01e544 100644
--- a/pkg/compiler/lib/src/null_compiler_output.dart
+++ b/pkg/compiler/lib/src/null_compiler_output.dart
@@ -29,10 +29,13 @@
NullSink(this.name);
+ @override
void add(String value) {}
+ @override
void close() {}
+ @override
String toString() => name;
/// Convenience method for getting an [api.CompilerOutputProvider].
@@ -53,5 +56,6 @@
@override
void close() {}
+ @override
String toString() => 'NullBinarySink($uri)';
}
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index c9c8862..9ee2539 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -136,15 +136,19 @@
bool disableProgramSplit = false;
/// Diagnostic option: If `true`, warnings cause the compilation to fail.
+ @override
bool fatalWarnings = false;
/// Diagnostic option: Emit terse diagnostics without howToFix.
+ @override
bool terseDiagnostics = false;
/// Diagnostic option: If `true`, warnings are not reported.
+ @override
bool suppressWarnings = false;
/// Diagnostic option: If `true`, hints are not reported.
+ @override
bool suppressHints = false;
/// Diagnostic option: List of packages for which warnings and hints are
@@ -449,14 +453,17 @@
}
/// Returns `true` if warnings and hints are shown for all packages.
+ @override
bool get showAllPackageWarnings {
return shownPackageWarnings != null && shownPackageWarnings.isEmpty;
}
/// Returns `true` if warnings and hints are hidden for all packages.
+ @override
bool get hidePackageWarnings => shownPackageWarnings == null;
/// Returns `true` if warnings should be should for [uri].
+ @override
bool showPackageWarningsFor(Uri uri) {
if (showAllPackageWarnings) {
return true;
@@ -485,6 +492,7 @@
static const trusted = const CheckPolicy(isTrusted: true);
static const checked = const CheckPolicy(isEmitted: true);
+ @override
String toString() => 'CheckPolicy(isTrusted=$isTrusted,'
'isEmitted=$isEmitted)';
}
diff --git a/pkg/compiler/lib/src/ordered_typeset.dart b/pkg/compiler/lib/src/ordered_typeset.dart
index efec511..ce4ff17 100644
--- a/pkg/compiler/lib/src/ordered_typeset.dart
+++ b/pkg/compiler/lib/src/ordered_typeset.dart
@@ -175,6 +175,7 @@
return null;
}
+ @override
String toString() => types.toString();
}
@@ -213,6 +214,7 @@
int getHierarchyDepth(covariant ClassEntity cls);
OrderedTypeSet getOrderedTypeSet(covariant ClassEntity cls);
+ @override
OrderedTypeSet createOrderedTypeSet(
InterfaceType supertype, Link<DartType> interfaces) {
// TODO(15296): Collapse these iterations to one when the order is not
@@ -305,6 +307,7 @@
return new OrderedTypeSet.internal(levels, levels.last);
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
for (int depth = 0; depth <= maxDepth; depth++) {
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 853beb3..9fdb9bb 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -103,6 +103,7 @@
_constantLiterals.add(constant);
}
+ @override
Iterable<ConstantExpression> get constantLiterals {
return _constantLiterals != null
? _constantLiterals
@@ -140,6 +141,7 @@
return _genericInstantiations ?? const <GenericInstantiation>[];
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('ResolutionWorldImpactBuilder($name)');
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index 0c95e75..737c314 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -43,6 +43,7 @@
_importIndex = new IndexedSink<ImportEntity>(this);
}
+ @override
void begin(String tag) {
if (useDataKinds) {
_tags ??= <String>[];
@@ -51,6 +52,7 @@
}
}
+ @override
void end(Object tag) {
if (useDataKinds) {
_end(tag);
@@ -207,6 +209,7 @@
_writeIntInternal(value);
}
+ @override
void writeTreeNode(ir.TreeNode value) {
_writeDataKind(DataKind.treeNode);
_writeTreeNode(value);
@@ -294,22 +297,27 @@
if (useDataKinds) _writeEnumInternal(kind);
}
+ @override
void writeLibrary(IndexedLibrary value) {
writeInt(value.libraryIndex);
}
+ @override
void writeClass(IndexedClass value) {
writeInt(value.classIndex);
}
+ @override
void writeTypedef(IndexedTypedef value) {
writeInt(value.typedefIndex);
}
+ @override
void writeMember(IndexedMember value) {
writeInt(value.memberIndex);
}
+ @override
void writeLocal(Local local) {
if (local is JLocal) {
writeEnum(LocalKind.jLocal);
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index a78fbea..b9660bd 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -27,14 +27,17 @@
_importIndex = new IndexedSource<ImportEntity>(this);
}
+ @override
void begin(String tag) {
if (useDataKinds) _begin(tag);
}
+ @override
void end(String tag) {
if (useDataKinds) _end(tag);
}
+ @override
void registerComponentLookup(ComponentLookup componentLookup) {
assert(_componentLookup == null);
_componentLookup = componentLookup;
@@ -45,6 +48,7 @@
return _componentLookup;
}
+ @override
void registerEntityLookup(EntityLookup entityLookup) {
assert(_entityLookup == null);
_entityLookup = entityLookup;
@@ -55,6 +59,7 @@
return _entityLookup;
}
+ @override
void registerLocalLookup(LocalLookup localLookup) {
assert(_localLookup == null);
_localLookup = localLookup;
@@ -71,18 +76,22 @@
return source.read(f);
}
+ @override
IndexedLibrary readLibrary() {
return getIndexedLibrary(readInt());
}
+ @override
IndexedClass readClass() {
return getIndexedClass(readInt());
}
+ @override
IndexedTypedef readTypedef() {
return getIndexedTypedef(readInt());
}
+ @override
IndexedMember readMember() {
return getIndexedMember(readInt());
}
@@ -409,6 +418,7 @@
return _readConstant();
}
+ @override
double readDoubleValue() {
_checkDataKind(DataKind.double);
return _readDoubleValue();
@@ -423,6 +433,7 @@
return data.getFloat64(0);
}
+ @override
int readIntegerValue() {
_checkDataKind(DataKind.int);
return _readBigInt().toInt();
diff --git a/pkg/compiler/lib/src/serialization/binary_sink.dart b/pkg/compiler/lib/src/serialization/binary_sink.dart
index ae11f9b..3f771b4 100644
--- a/pkg/compiler/lib/src/serialization/binary_sink.dart
+++ b/pkg/compiler/lib/src/serialization/binary_sink.dart
@@ -16,9 +16,11 @@
: _bufferedSink = new BufferedSink(sink),
super(useDataKinds: useDataKinds);
+ @override
void _begin(String tag) {
// TODO(johnniwinther): Support tags in binary serialization?
}
+ @override
void _end(String tag) {
// TODO(johnniwinther): Support tags in binary serialization?
}
@@ -57,6 +59,7 @@
_writeIntInternal(value.index);
}
+ @override
void close() {
_bufferedSink.flushAndDestroy();
_bufferedSink = null;
@@ -64,5 +67,6 @@
}
/// Returns the number of bytes written to this data sink.
+ @override
int get length => _length;
}
diff --git a/pkg/compiler/lib/src/serialization/binary_source.dart b/pkg/compiler/lib/src/serialization/binary_source.dart
index c68e4c9..11132b9 100644
--- a/pkg/compiler/lib/src/serialization/binary_source.dart
+++ b/pkg/compiler/lib/src/serialization/binary_source.dart
@@ -14,7 +14,9 @@
BinarySourceImpl(this._bytes, {bool useDataKinds: false})
: super(useDataKinds: useDataKinds);
+ @override
void _begin(String tag) {}
+ @override
void _end(String tag) {}
int _readByte() => _bytes[_byteOffset++];
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index d6db5f2..4bb57a4 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -71,14 +71,17 @@
Tag(this.value);
+ @override
int get hashCode => value.hashCode * 13;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! Tag) return false;
return value == other.value;
}
+ @override
String toString() => 'Tag($value)';
}
@@ -102,6 +105,7 @@
DartTypeWriter(this._sink);
+ @override
void visit(covariant DartType type,
List<FunctionTypeVariable> functionTypeVariables) =>
type.accept(this, functionTypeVariables);
@@ -114,11 +118,13 @@
}
}
+ @override
void visitVoidType(covariant VoidType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.voidType);
}
+ @override
void visitTypeVariableType(covariant TypeVariableType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.typeVariable);
@@ -126,6 +132,7 @@
_sink.writeInt(typeVariable.typeVariableIndex);
}
+ @override
void visitFunctionTypeVariable(covariant FunctionTypeVariable type,
List<FunctionTypeVariable> functionTypeVariables) {
int index = functionTypeVariables.indexOf(type);
@@ -138,6 +145,7 @@
}
}
+ @override
void visitFunctionType(covariant FunctionType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.functionType);
@@ -157,6 +165,7 @@
}
}
+ @override
void visitInterfaceType(covariant InterfaceType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.interfaceType);
@@ -164,6 +173,7 @@
visitTypes(type.typeArguments, functionTypeVariables);
}
+ @override
void visitTypedefType(covariant TypedefType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.typedef);
@@ -172,11 +182,13 @@
_sink._writeDartType(type.unaliased, functionTypeVariables);
}
+ @override
void visitDynamicType(covariant DynamicType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.dynamicType);
}
+ @override
void visitFutureOrType(covariant FutureOrType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.futureOr);
@@ -217,27 +229,32 @@
}
}
+ @override
void defaultDartType(
ir.DartType node, List<ir.TypeParameter> functionTypeVariables) {
throw new UnsupportedError(
"Unexpected ir.DartType $node (${node.runtimeType}).");
}
+ @override
void visitInvalidType(
ir.InvalidType node, List<ir.TypeParameter> functionTypeVariables) {
_sink.writeEnum(DartTypeNodeKind.invalidType);
}
+ @override
void visitDynamicType(
ir.DynamicType node, List<ir.TypeParameter> functionTypeVariables) {
_sink.writeEnum(DartTypeNodeKind.dynamicType);
}
+ @override
void visitVoidType(
ir.VoidType node, List<ir.TypeParameter> functionTypeVariables) {
_sink.writeEnum(DartTypeNodeKind.voidType);
}
+ @override
void visitBottomType(
ir.BottomType node, List<ir.TypeParameter> functionTypeVariables) {
if (node == const DoesNotCompleteType()) {
@@ -247,6 +264,7 @@
}
}
+ @override
void visitInterfaceType(
ir.InterfaceType node, List<ir.TypeParameter> functionTypeVariables) {
if (node is ThisInterfaceType) {
@@ -260,6 +278,7 @@
visitTypes(node.typeArguments, functionTypeVariables);
}
+ @override
void visitFunctionType(
ir.FunctionType node, List<ir.TypeParameter> functionTypeVariables) {
_sink.writeEnum(DartTypeNodeKind.functionType);
@@ -286,6 +305,7 @@
_sink.end(functionTypeNodeTag);
}
+ @override
void visitTypeParameterType(
ir.TypeParameterType node, List<ir.TypeParameter> functionTypeVariables) {
int index = functionTypeVariables.indexOf(node.parameter);
@@ -302,6 +322,7 @@
}
}
+ @override
void visitTypedefType(
ir.TypedefType node, List<ir.TypeParameter> functionTypeVariables) {
_sink.writeEnum(DartTypeNodeKind.typedef);
diff --git a/pkg/compiler/lib/src/serialization/member_data.dart b/pkg/compiler/lib/src/serialization/member_data.dart
index b4aeee12..f088210 100644
--- a/pkg/compiler/lib/src/serialization/member_data.dart
+++ b/pkg/compiler/lib/src/serialization/member_data.dart
@@ -108,6 +108,7 @@
return _members[name];
}
+ @override
String toString() => '_LibraryData($node(${identityHashCode(node)}))';
}
@@ -137,6 +138,7 @@
return _members[name];
}
+ @override
String toString() => '_ClassData($node(${identityHashCode(node)}))';
}
@@ -180,5 +182,6 @@
return index;
}
+ @override
String toString() => '_MemberData($node(${identityHashCode(node)}))';
}
diff --git a/pkg/compiler/lib/src/serialization/object_sink.dart b/pkg/compiler/lib/src/serialization/object_sink.dart
index 3246b9f..31376e3 100644
--- a/pkg/compiler/lib/src/serialization/object_sink.dart
+++ b/pkg/compiler/lib/src/serialization/object_sink.dart
@@ -14,10 +14,12 @@
ObjectSink(this._data, {bool useDataKinds})
: super(useDataKinds: useDataKinds);
+ @override
void _begin(String tag) {
_data.add(new Tag('begin:$tag'));
}
+ @override
void _end(String tag) {
_data.add(new Tag('end:$tag'));
}
diff --git a/pkg/compiler/lib/src/serialization/object_source.dart b/pkg/compiler/lib/src/serialization/object_source.dart
index 4ce571e..54207a2 100644
--- a/pkg/compiler/lib/src/serialization/object_source.dart
+++ b/pkg/compiler/lib/src/serialization/object_source.dart
@@ -21,6 +21,7 @@
return value;
}
+ @override
void _begin(String tag) {
Tag expectedTag = new Tag('begin:$tag');
Tag actualTag = _read();
@@ -30,6 +31,7 @@
"Expected $expectedTag, found $actualTag.$_errorContext");
}
+ @override
void _end(String tag) {
Tag expectedTag = new Tag('end:$tag');
Tag actualTag = _read();
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 3aac9f3..56ab4bd 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -49,6 +49,7 @@
SerializationTask(this.compiler, Measurer measurer) : super(measurer);
+ @override
String get name => 'Serialization';
void serialize(GlobalTypeInferenceResults results) {
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index f6551af..3a6f81a 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -176,6 +176,7 @@
class CompilerSourceFileProvider extends SourceFileProvider {
// TODO(johnniwinther): Remove this when no longer needed for the old compiler
// API.
+ @override
Future<List<int>> call(Uri resourceUri) =>
readFromUri(resourceUri).then((input) => input.data);
@@ -372,6 +373,7 @@
return uri;
}
+ @override
OutputSink createOutputSink(String name, String extension, OutputType type) {
Uri uri = createUri(name, extension, type);
bool isPrimaryOutput = uri == out;
@@ -474,8 +476,10 @@
_OutputSinkWrapper(this.onAdd, this.onClose);
+ @override
void add(String data) => onAdd(data);
+ @override
void close() => onClose();
}
@@ -485,9 +489,11 @@
_BinaryOutputSinkWrapper(this.onWrite, this.onClose);
+ @override
void write(List<int> data, [int start = 0, int end]) =>
onWrite(data, start, end);
+ @override
void close() => onClose();
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 242f060..8047624 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -83,11 +83,14 @@
class KernelSsaGraphBuilder extends ir.Visitor
with GraphBuilder, SsaBuilderFieldMixin {
+ @override
final MemberEntity targetElement;
final MemberEntity initialTargetElement;
+ @override
final JClosedWorld closedWorld;
final CodegenWorldBuilder _worldBuilder;
+ @override
final CodegenRegistry registry;
final ClosureData closureDataLookup;
@@ -105,6 +108,7 @@
HInstruction rethrowableException;
+ @override
final Compiler compiler;
@override
@@ -112,8 +116,10 @@
final SourceInformationStrategy _sourceInformationStrategy;
final JsToElementMap _elementMap;
+ @override
final GlobalTypeInferenceResults globalInferenceResults;
LoopHandler loopHandler;
+ @override
TypeBuilder typeBuilder;
final NativeEmitter nativeEmitter;
@@ -233,7 +239,20 @@
// the constant value.
return null;
} else if (targetElement.isStatic || targetElement.isTopLevel) {
- backend.constants.registerLazyStatic(targetElement);
+ if (_fieldAnalysis.getFieldData(targetElement).isLazy) {
+ // TODO(johnniwinther): Lazy fields should be collected like
+ // eager and non-final fields.
+ backend.constants.registerLazyStatic(targetElement);
+ }
+ } else {
+ assert(targetElement.isInstanceMember);
+ if (_fieldAnalysis
+ .getFieldData(targetElement)
+ .isEffectivelyFinal ||
+ !options.parameterCheckPolicy.isEmitted) {
+ // No need for a checked setter.
+ return null;
+ }
}
buildField(target);
} else if (target is ir.FunctionExpression) {
@@ -258,8 +277,8 @@
buildConstructorBody(constructor);
break;
case MemberKind.closureField:
- failedAt(targetElement, "Unexpected closure field: $targetElement");
- break;
+ // Closure fields have no setter and therefore never require any code.
+ return null;
case MemberKind.signature:
ir.Node target = definition.node;
ir.FunctionNode originalClosureNode;
@@ -1417,29 +1436,8 @@
}
@override
- void defaultExpression(ir.Expression expression) {
- // TODO(johnniwinther): We should make this an internal error.
- _trap('Unhandled ir.${expression.runtimeType} $expression');
- }
-
- @override
- void defaultStatement(ir.Statement statement) {
- // TODO(johnniwinther): We should make this an internal error.
- _trap('Unhandled ir.${statement.runtimeType} $statement');
- pop();
- }
-
- void _trap(String message) {
- HInstruction nullValue = graph.addConstantNull(closedWorld);
- HInstruction errorMessage = graph.addConstantString(message, closedWorld);
- HInstruction trap = new HForeignCode(
- js.js.parseForeignJS("#.#"),
- abstractValueDomain.dynamicType,
- <HInstruction>[nullValue, errorMessage]);
- trap.sideEffects
- ..setAllSideEffects()
- ..setDependsOnSomething();
- push(trap);
+ void defaultNode(ir.Node node) {
+ throw new UnsupportedError("Unhandled node $node (${node.runtimeType})");
}
/// Returns the current source element. This is used by the type builder.
@@ -1526,6 +1524,12 @@
}
}
+ @override
+ void visitConstantExpression(ir.ConstantExpression node) {
+ stack.add(
+ graph.addConstant(_elementMap.getConstantValue(node), closedWorld));
+ }
+
/// Returns true if the [type] is a valid return type for an asynchronous
/// function.
///
@@ -1944,6 +1948,7 @@
..cleanUp();
}
+ @override
HInstruction callSetRuntimeTypeInfo(HInstruction typeInfo,
HInstruction newObject, SourceInformation sourceInformation) {
// Set the runtime type information on the object.
@@ -3078,26 +3083,26 @@
} else if (staticTarget is ir.Field) {
FieldEntity field = _elementMap.getField(staticTarget);
FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(field);
- if (fieldData.initialValue != null) {
- if (fieldData.isEffectivelyFinal) {
- var unit = closedWorld.outputUnitData.outputUnitForMember(field);
- // TODO(sigmund): this is not equivalent to what the old FE does: if
- // there is no prefix the old FE wouldn't treat this in any special
- // way. Also, if the prefix points to a constant in the main output
- // unit, the old FE would still generate a deferred wrapper here.
- if (!closedWorld.outputUnitData
- .hasOnlyNonDeferredImportPaths(targetElement, field)) {
- stack.add(graph.addDeferredConstant(fieldData.initialValue, unit,
- sourceInformation, compiler, closedWorld));
- } else {
- stack.add(graph.addConstant(fieldData.initialValue, closedWorld,
- sourceInformation: sourceInformation));
- }
+ if (fieldData.isEager) {
+ push(new HStatic(field, _typeInferenceMap.getInferredTypeOf(field),
+ sourceInformation));
+ } else if (fieldData.isEffectivelyConstant) {
+ var unit = closedWorld.outputUnitData.outputUnitForMember(field);
+ // TODO(sigmund): this is not equivalent to what the old FE does: if
+ // there is no prefix the old FE wouldn't treat this in any special
+ // way. Also, if the prefix points to a constant in the main output
+ // unit, the old FE would still generate a deferred wrapper here.
+ if (!closedWorld.outputUnitData
+ .hasOnlyNonDeferredImportPaths(targetElement, field)) {
+ stack.add(graph.addDeferredConstant(fieldData.initialValue, unit,
+ sourceInformation, compiler, closedWorld));
} else {
- push(new HStatic(field, _typeInferenceMap.getInferredTypeOf(field),
- sourceInformation));
+ stack.add(graph.addConstant(fieldData.initialValue, closedWorld,
+ sourceInformation: sourceInformation));
}
} else {
+ assert(
+ fieldData.isLazy, "Unexpected field data for $field: $fieldData");
push(new HLazyStatic(field, _typeInferenceMap.getInferredTypeOf(field),
sourceInformation));
}
@@ -5043,6 +5048,7 @@
}
}
+ @override
void visitYieldStatement(ir.YieldStatement node) {
node.expression.accept(this);
add(new HYield(abstractValueDomain, pop(), node.isYieldStar,
@@ -6598,8 +6604,10 @@
KernelTypeBuilder(KernelSsaGraphBuilder builder, this._elementMap)
: super(builder);
+ @override
KernelSsaGraphBuilder get builder => super.builder;
+ @override
ClassTypeVariableAccess computeTypeVariableAccess(MemberEntity member) {
return _elementMap.getClassTypeVariableAccessForMember(member);
}
@@ -6612,17 +6620,22 @@
static bool check(ir.Initializer initializer) =>
initializer.accept(new _ErroneousInitializerVisitor());
+ @override
bool defaultInitializer(ir.Node node) => false;
+ @override
bool visitInvalidInitializer(ir.InvalidInitializer node) => true;
+ @override
bool visitLocalInitializer(ir.LocalInitializer node) {
return node.variable.initializer?.accept(this) ?? false;
}
// Expressions: Does the expression always throw?
+ @override
bool defaultExpression(ir.Expression node) => false;
+ @override
bool visitThrow(ir.Throw node) => true;
// TODO(sra): We might need to match other expressions that always throw but
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index ffccada..6c5852a 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -54,6 +54,7 @@
: this.backend = backend,
super(backend.compiler.measurer);
+ @override
String get name => 'SSA code generator';
js.Fun buildJavaScriptFunction(bool needsAsyncRewrite, FunctionEntity element,
@@ -772,8 +773,10 @@
}
// The regular [visitIf] method implements the needed logic.
+ @override
bool visitIfInfo(HIfBlockInformation info) => false;
+ @override
bool visitSwitchInfo(HSwitchBlockInformation info) {
bool isExpression = isJSExpression(info.expression);
if (!isExpression) {
@@ -845,23 +848,28 @@
return true;
}
+ @override
bool visitSequenceInfo(HStatementSequenceInformation info) {
return false;
}
+ @override
bool visitSubGraphInfo(HSubGraphBlockInformation info) {
visitSubGraph(info.subGraph);
return true;
}
+ @override
bool visitSubExpressionInfo(HSubExpressionBlockInformation info) {
return false;
}
+ @override
bool visitAndOrInfo(HAndOrBlockInformation info) {
return false;
}
+ @override
bool visitTryInfo(HTryBlockInformation info) {
js.Block body = generateStatementsInNewBlock(info.body);
js.Catch catchPart = null;
@@ -902,6 +910,7 @@
}
}
+ @override
bool visitLoopInfo(HLoopBlockInformation info) {
HExpressionInformation condition = info.condition;
bool isConditionExpression = isJSCondition(condition);
@@ -1122,6 +1131,7 @@
return true;
}
+ @override
bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) {
Link<Entity> continueOverrides = const Link<Entity>();
@@ -1408,6 +1418,7 @@
.withSourceInformation(sourceInformation));
}
+ @override
visitLateValue(HLateValue node) {
use(node.target);
}
@@ -1476,21 +1487,33 @@
}
}
+ @override
visitIdentity(HIdentity node) {
emitIdentityComparison(node, node.sourceInformation, inverse: false);
}
+ @override
visitAdd(HAdd node) => visitInvokeBinary(node, '+');
+ @override
visitDivide(HDivide node) => visitInvokeBinary(node, '/');
+ @override
visitMultiply(HMultiply node) => visitInvokeBinary(node, '*');
+ @override
visitSubtract(HSubtract node) => visitInvokeBinary(node, '-');
+ @override
visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&');
+ @override
visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~');
+ @override
visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|');
+ @override
visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^');
+ @override
visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<');
+ @override
visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>');
+ @override
visitTruncatingDivide(HTruncatingDivide node) {
assert(node.isUInt31(_abstractValueDomain).isDefinitelyTrue);
// TODO(karlklose): Enable this assertion again when type propagation is
@@ -1506,12 +1529,15 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
visitRemainder(HRemainder node) {
return visitInvokeBinary(node, '%');
}
+ @override
visitNegate(HNegate node) => visitInvokeUnary(node, '-');
+ @override
visitAbs(HAbs node) {
use(node.operand);
push(js
@@ -1519,11 +1545,16 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
visitLess(HLess node) => visitRelational(node, '<');
+ @override
visitLessEqual(HLessEqual node) => visitRelational(node, '<=');
+ @override
visitGreater(HGreater node) => visitRelational(node, '>');
+ @override
visitGreaterEqual(HGreaterEqual node) => visitRelational(node, '>=');
+ @override
visitBoolify(HBoolify node) {
assert(node.inputs.length == 1);
use(node.inputs[0]);
@@ -1532,10 +1563,12 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
visitExit(HExit node) {
// Don't do anything.
}
+ @override
visitGoto(HGoto node) {
HBasicBlock block = node.block;
assert(block.successors.length == 1);
@@ -1556,6 +1589,7 @@
continueSubGraph(dominated.first);
}
+ @override
visitLoopBranch(HLoopBranch node) {
assert(node.block == subGraph.end);
// We are generating code for a loop condition.
@@ -1568,6 +1602,7 @@
}
}
+ @override
visitBreak(HBreak node) {
assert(node.block.successors.length == 1);
if (node.label != null) {
@@ -1594,6 +1629,7 @@
}
}
+ @override
visitContinue(HContinue node) {
assert(node.block.successors.length == 1);
if (node.label != null) {
@@ -1622,6 +1658,7 @@
}
}
+ @override
visitExitTry(HExitTry node) {
// An [HExitTry] is used to represent the control flow graph of a
// try/catch block, ie the try body is always a predecessor
@@ -1631,6 +1668,7 @@
continueSubGraph(node.bodyTrySuccessor);
}
+ @override
visitTry(HTry node) {
// We should never get here. Try/catch/finally is always handled using block
// information in [visitTryInfo].
@@ -1729,6 +1767,7 @@
return js.If(test, thenPart, elsePart);
}
+ @override
visitIf(HIf node) {
if (tryControlFlowOperation(node)) return;
@@ -1764,6 +1803,7 @@
}
}
+ @override
void visitInterceptor(HInterceptor node) {
if (node.isConditionalConstantInterceptor) {
assert(node.inputs.length == 2);
@@ -1787,6 +1827,7 @@
}
}
+ @override
visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
use(node.receiver);
js.Expression object = pop();
@@ -1829,6 +1870,7 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
void visitInvokeConstructorBody(HInvokeConstructorBody node) {
use(node.inputs[0]);
js.Expression object = pop();
@@ -1841,6 +1883,7 @@
node.element, new CallStructure.unnamed(arguments.length)));
}
+ @override
void visitInvokeGeneratorBody(HInvokeGeneratorBody node) {
JGeneratorBody element = node.element;
if (element.isInstanceMember) {
@@ -1862,6 +1905,7 @@
.registerStaticUse(new StaticUse.generatorBodyInvoke(node.element));
}
+ @override
void visitOneShotInterceptor(HOneShotInterceptor node) {
List<js.Expression> arguments = visitArguments(node.inputs);
var isolate = new js.VariableUse(
@@ -1976,6 +2020,7 @@
}
}
+ @override
visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
use(node.receiver);
js.Name name = _namer.invocationName(node.selector);
@@ -1985,6 +2030,7 @@
registerSetter(node, needsCheck: node.needsCheck);
}
+ @override
visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
use(node.receiver);
js.Name name = _namer.invocationName(node.selector);
@@ -1994,6 +2040,7 @@
registerGetter(node);
}
+ @override
visitInvokeClosure(HInvokeClosure node) {
Selector call = new Selector.callClosureFrom(node.selector);
use(node.receiver);
@@ -2008,6 +2055,7 @@
new ConstrainedDynamicUse(call, null, node.typeArguments));
}
+ @override
visitInvokeStatic(HInvokeStatic node) {
MemberEntity element = node.element;
node.instantiatedTypes?.forEach(_registry.registerInstantiation);
@@ -2056,6 +2104,7 @@
}
}
+ @override
visitInvokeSuper(HInvokeSuper node) {
MemberEntity superElement = node.element;
ClassEntity superClass = superElement.enclosingClass;
@@ -2116,6 +2165,7 @@
}
}
+ @override
visitFieldGet(HFieldGet node) {
use(node.receiver);
if (node.isNullCheck) {
@@ -2133,6 +2183,7 @@
}
}
+ @override
visitFieldSet(HFieldSet node) {
FieldEntity element = node.element;
_registry.registerStaticUse(new StaticUse.fieldSet(element));
@@ -2147,12 +2198,14 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
visitGetLength(HGetLength node) {
use(node.receiver);
push(new js.PropertyAccess.field(pop(), 'length')
.withSourceInformation(node.sourceInformation));
}
+ @override
visitReadModifyWrite(HReadModifyWrite node) {
FieldEntity element = node.element;
_registry.registerStaticUse(new StaticUse.fieldGet(element));
@@ -2173,10 +2226,12 @@
}
}
+ @override
visitLocalGet(HLocalGet node) {
use(node.receiver);
}
+ @override
visitLocalSet(HLocalSet node) {
use(node.value);
assignVariable(
@@ -2190,6 +2245,7 @@
_registry.worldImpact, nativeBehavior, node);
}
+ @override
visitForeignCode(HForeignCode node) {
List<HInstruction> inputs = node.inputs;
if (node.isJsStatement()) {
@@ -2221,6 +2277,7 @@
}
}
+ @override
visitCreate(HCreate node) {
js.Expression jsClassReference = _emitter.constructorAccess(node.element);
List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
@@ -2242,6 +2299,7 @@
}
}
+ @override
visitCreateBox(HCreateBox node) {
push(new js.ObjectInitializer(<js.Property>[]));
}
@@ -2267,6 +2325,7 @@
push(expression);
}
+ @override
visitConstant(HConstant node) {
assert(isGenerateAtUseSite(node));
generateConstant(node.constant, node.sourceInformation);
@@ -2279,6 +2338,7 @@
}
}
+ @override
visitNot(HNot node) {
assert(node.inputs.length == 1);
generateNot(node.inputs[0], node.sourceInformation);
@@ -2348,6 +2408,7 @@
}
}
+ @override
visitParameterValue(HParameterValue node) {
assert(!isGenerateAtUseSite(node));
String name = variableNames.getName(node);
@@ -2355,12 +2416,14 @@
declaredLocals.add(name);
}
+ @override
visitLocalValue(HLocalValue node) {
assert(!isGenerateAtUseSite(node));
String name = variableNames.getName(node);
collectedVariableDeclarations.add(name);
}
+ @override
visitPhi(HPhi node) {
// This method is only called for phis that are generated at use
// site. A phi can be generated at use site only if it is the
@@ -2392,6 +2455,7 @@
}
}
+ @override
visitReturn(HReturn node) {
assert(node.inputs.length == 1);
HInstruction input = node.inputs[0];
@@ -2405,10 +2469,12 @@
}
}
+ @override
visitThis(HThis node) {
push(new js.This());
}
+ @override
visitThrow(HThrow node) {
if (node.isRethrow) {
use(node.inputs[0]);
@@ -2421,23 +2487,27 @@
}
}
+ @override
visitAwait(HAwait node) {
use(node.inputs[0]);
push(new js.Await(pop()).withSourceInformation(node.sourceInformation));
}
+ @override
visitYield(HYield node) {
use(node.inputs[0]);
pushStatement(new js.DartYield(pop(), node.hasStar)
.withSourceInformation(node.sourceInformation));
}
+ @override
visitRangeConversion(HRangeConversion node) {
// Range conversion instructions are removed by the value range
// analyzer.
assert(false);
}
+ @override
visitBoundsCheck(HBoundsCheck node) {
// TODO(ngeoffray): Separate the two checks of the bounds check, so,
// e.g., the zero checks can be shared if possible.
@@ -2518,6 +2588,7 @@
}
}
+ @override
visitThrowExpression(HThrowExpression node) {
HInstruction argument = node.inputs[0];
use(argument);
@@ -2532,10 +2603,12 @@
push(value);
}
+ @override
void visitSwitch(HSwitch node) {
// Switches are handled using [visitSwitchInfo].
}
+ @override
void visitStatic(HStatic node) {
MemberEntity element = node.element;
assert(element.isFunction || element.isField);
@@ -2552,6 +2625,7 @@
}
}
+ @override
void visitLazyStatic(HLazyStatic node) {
FieldEntity element = node.element;
_registry.registerStaticUse(new StaticUse.staticInit(element));
@@ -2561,6 +2635,7 @@
push(call);
}
+ @override
void visitStaticStore(HStaticStore node) {
_registry.registerStaticUse(new StaticUse.staticSet(node.element));
js.Node variable = _emitter.staticFieldAccess(node.element);
@@ -2569,6 +2644,7 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
void visitStringConcat(HStringConcat node) {
use(node.left);
js.Expression jsLeft = pop();
@@ -2577,6 +2653,7 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
void visitStringify(HStringify node) {
HInstruction input = node.inputs.first;
if (input.isString(_abstractValueDomain).isDefinitelyTrue) {
@@ -2607,6 +2684,7 @@
}
}
+ @override
void visitLiteralList(HLiteralList node) {
_registry
// ignore:deprecated_member_use_from_same_package
@@ -2623,6 +2701,7 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
void visitIndex(HIndex node) {
use(node.receiver);
js.Expression receiver = pop();
@@ -2631,6 +2710,7 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
void visitIndexAssign(HIndexAssign node) {
use(node.receiver);
js.Expression receiver = pop();
@@ -2902,10 +2982,12 @@
.withSourceInformation(sourceInformation));
}
+ @override
void visitIs(HIs node) {
emitIs(node, "===", node.sourceInformation);
}
+ @override
void visitIsViaInterceptor(HIsViaInterceptor node) {
emitIsViaInterceptor(node, node.sourceInformation, negative: false);
}
@@ -3019,6 +3101,7 @@
throw failedAt(input, 'Unexpected check: $type.');
}
+ @override
void visitTypeConversion(HTypeConversion node) {
if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
js.Expression test = generateReceiverOrArgumentTypeTest(node);
@@ -3078,17 +3161,20 @@
.withSourceInformation(node.sourceInformation));
}
+ @override
void visitTypeKnown(HTypeKnown node) {
// [HTypeKnown] instructions are removed before generating code.
assert(false);
}
+ @override
void visitTypeInfoReadRaw(HTypeInfoReadRaw node) {
use(node.inputs[0]);
js.Expression receiver = pop();
push(js.js(r'#.#', [receiver, _namer.rtiFieldJsName]));
}
+ @override
void visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
TypeVariableEntity element = node.variable.element;
int index = element.index;
@@ -3143,6 +3229,7 @@
}
}
+ @override
void visitTypeInfoExpression(HTypeInfoExpression node) {
DartType type = node.dartType;
if (node.isTypeVariableReplacement) {
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 6c28b79..4ad0571 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -27,11 +27,13 @@
AbstractValueDomain get _abstractValueDomain =>
_closedWorld.abstractValueDomain;
+ @override
void visitGraph(HGraph graph) {
this.graph = graph;
visitDominatorTree(graph);
}
+ @override
visitBasicBlock(HBasicBlock block) {
HInstruction instruction = block.first;
while (instruction != null) {
@@ -63,10 +65,12 @@
}
}
+ @override
HInstruction visitInstruction(HInstruction node) {
return node;
}
+ @override
HInstruction visitIs(HIs node) {
if (node.kind == HIs.RAW_CHECK) {
HInstruction interceptor = node.interceptor;
@@ -78,6 +82,7 @@
return node;
}
+ @override
HInstruction visitIdentity(HIdentity node) {
node.singleComparisonOp = simpleOp(node.left, node.right);
return node;
@@ -128,6 +133,7 @@
.isInterceptor(_abstractValueDomain.excludeNull(type))
.isPotentiallyTrue;
+ @override
HInstruction visitInvokeDynamic(HInvokeDynamic node) {
if (node.isInterceptedCall) {
tryReplaceInterceptorWithDummy(node, node.selector, node.mask);
@@ -135,6 +141,7 @@
return node;
}
+ @override
HInstruction visitInvokeSuper(HInvokeSuper node) {
if (node.isInterceptedCall) {
AbstractValue mask = node.getDartReceiver(_closedWorld).instructionType;
@@ -143,6 +150,7 @@
return node;
}
+ @override
HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
// The receiver parameter should never be replaced with a dummy constant.
return node;
@@ -195,6 +203,7 @@
return false;
}
+ @override
HInstruction visitFieldSet(HFieldSet setter) {
// Pattern match
// t1 = x.f; t2 = t1 + 1; x.f = t2; use(t2) --> ++x.f
@@ -305,6 +314,7 @@
return noMatchingRead();
}
+ @override
visitIf(HIf node) {
if (!_options.experimentToBoolean) return node;
HInstruction condition = node.inputs.single;
@@ -343,10 +353,12 @@
/// Remove [HTypeKnown] instructions from the graph, to make codegen
/// analysis easier.
class SsaTypeKnownRemover extends HBaseVisitor with CodegenPhase {
+ @override
void visitGraph(HGraph graph) {
visitDominatorTree(graph);
}
+ @override
void visitBasicBlock(HBasicBlock block) {
HInstruction instruction = block.first;
while (instruction != null) {
@@ -356,6 +368,7 @@
}
}
+ @override
void visitTypeKnown(HTypeKnown instruction) {
for (HInstruction user in instruction.usedBy) {
if (user is HTypeConversion) {
@@ -374,11 +387,13 @@
SsaTrustedCheckRemover(this._options);
+ @override
void visitGraph(HGraph graph) {
if (!_options.trustPrimitives) return;
visitDominatorTree(graph);
}
+ @override
void visitBasicBlock(HBasicBlock block) {
HInstruction instruction = block.first;
while (instruction != null) {
@@ -388,6 +403,7 @@
}
}
+ @override
void visitTypeConversion(HTypeConversion instruction) {
if (instruction.isReceiverTypeCheck || instruction.isArgumentTypeCheck) {
instruction.block.rewrite(instruction, instruction.checkedInput);
@@ -413,11 +429,13 @@
AbstractValueDomain get _abstractValueDomain =>
_closedWorld.abstractValueDomain;
+ @override
void visitGraph(HGraph graph) {
//this.graph = graph;
visitDominatorTree(graph);
}
+ @override
void visitBasicBlock(HBasicBlock block) {
HInstruction instruction = block.first;
while (instruction != null) {
@@ -426,14 +444,17 @@
}
/// Returns the next instruction.
+ @override
HInstruction visitInstruction(HInstruction node) {
return node.next;
}
+ @override
HInstruction visitFieldSet(HFieldSet setter) {
return tryChainAssignment(setter, setter.value);
}
+ @override
HInstruction visitStaticStore(HStaticStore store) {
return tryChainAssignment(store, store.inputs.single);
}
@@ -589,6 +610,7 @@
SsaInstructionMerger(
this._abstractValueDomain, this.generateAtUseSite, this._superMemberData);
+ @override
void visitGraph(HGraph graph) {
visitDominatorTree(graph);
}
@@ -651,12 +673,14 @@
.isNotEmpty;
}
+ @override
void visitInstruction(HInstruction instruction) {
// A code motion invariant instruction is dealt before visiting it.
assert(!instruction.isCodeMotionInvariant());
analyzeInputs(instruction, 0);
}
+ @override
void visitInvokeSuper(HInvokeSuper instruction) {
MemberEntity superMethod = instruction.element;
Selector selector = instruction.selector;
@@ -677,6 +701,7 @@
}
}
+ @override
void visitIs(HIs instruction) {
// In the general case the input might be used multple multiple times, so it
// must not be set generate at use site.
@@ -695,6 +720,7 @@
// A bounds check method must not have its first input generated at use site,
// because it's using it twice.
+ @override
void visitBoundsCheck(HBoundsCheck instruction) {
analyzeInputs(instruction, 1);
}
@@ -702,6 +728,7 @@
// An identity operation must only have its inputs generated at use site if
// does not require an expression with multiple uses (because of null /
// undefined).
+ @override
void visitIdentity(HIdentity instruction) {
if (instruction.singleComparisonOp != null) {
super.visitIdentity(instruction);
@@ -709,6 +736,7 @@
// Do nothing.
}
+ @override
void visitTypeConversion(HTypeConversion instruction) {
if (!instruction.isArgumentTypeCheck && !instruction.isReceiverTypeCheck) {
assert(instruction.isCheckedModeCheck || instruction.isCastTypeCheck);
@@ -719,6 +747,7 @@
}
}
+ @override
void visitTypeKnown(HTypeKnown instruction) {
// [HTypeKnown] instructions are removed before code generation.
assert(false);
@@ -734,6 +763,7 @@
block.successors[0].predecessors.length == 1;
}
+ @override
void visitBasicBlock(HBasicBlock block) {
// Compensate from not merging blocks: if the block is the
// single predecessor of its single successor, let the successor
@@ -878,6 +908,7 @@
SsaConditionMerger(this.generateAtUseSite, this.controlFlowOperators);
+ @override
void visitGraph(HGraph graph) {
visitPostDominatorTree(graph);
}
@@ -927,6 +958,7 @@
return user.hasSameLoopHeaderAs(input);
}
+ @override
void visitBasicBlock(HBasicBlock block) {
if (block.last is! HIf) return;
HIf startIf = block.last;
@@ -1046,6 +1078,7 @@
SsaShareRegionConstants(this._options);
+ @override
visitGraph(HGraph graph) {
// We need the async rewrite to be smarter about hoisting region constants
// before it is worth-while.
@@ -1056,6 +1089,7 @@
visitBasicBlock(graph.entry);
}
+ @override
visitBasicBlock(HBasicBlock block) {
HInstruction instruction = block.first;
while (instruction != null) {
@@ -1089,6 +1123,7 @@
}
}
+ @override
void visitThis(HThis node) {
int size = 4;
// Compare the size of the unchanged minified with the size of the minified
@@ -1110,6 +1145,7 @@
_cache(node, (_) => true, '_this');
}
+ @override
void visitConstant(HConstant node) {
if (node.usedBy.length <= 1) return;
ConstantValue constant = node.constant;
@@ -1218,6 +1254,7 @@
/// A simple Entity to give intermediate values nice names when not generating
/// minified code.
class _ExpressionName implements Entity {
+ @override
final String name;
_ExpressionName(this.name);
}
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index 3f5d89b..098809b 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -32,6 +32,7 @@
///
class SsaSimplifyInterceptors extends HBaseVisitor
implements OptimizationPhase {
+ @override
final String name = "SsaSimplifyInterceptors";
final JClosedWorld _closedWorld;
final ClassEntity _enclosingClass;
@@ -46,11 +47,13 @@
AbstractValueDomain get _abstractValueDomain =>
_closedWorld.abstractValueDomain;
+ @override
void visitGraph(HGraph graph) {
this._graph = graph;
visitDominatorTree(graph);
}
+ @override
void visitBasicBlock(HBasicBlock node) {
currentBlock = node;
@@ -65,8 +68,10 @@
}
}
+ @override
bool visitInstruction(HInstruction instruction) => false;
+ @override
bool visitInvoke(HInvoke invoke) {
if (!invoke.isInterceptedCall) return false;
dynamic interceptor = invoke.inputs[0];
@@ -187,6 +192,7 @@
static int useCount(HInstruction user, HInstruction used) =>
user.inputs.where((input) => input == used).length;
+ @override
bool visitInterceptor(HInterceptor node) {
if (node.receiver.nonCheck() == _graph.explicitReceiverParameter) {
// If `explicitReceiverParameter` is set it means the current method is an
@@ -431,6 +437,7 @@
}
}
+ @override
bool visitOneShotInterceptor(HOneShotInterceptor node) {
// 'Undo' the one-shot transformation if the receiver has a constant
// interceptor.
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index 7e6e84c..42e3113 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -116,6 +116,7 @@
class IndexAssignSpecializer extends InvokeDynamicSpecializer {
const IndexAssignSpecializer();
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -187,6 +188,7 @@
class IndexSpecializer extends InvokeDynamicSpecializer {
const IndexSpecializer();
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -221,10 +223,12 @@
class BitNotSpecializer extends InvokeDynamicSpecializer {
const BitNotSpecializer();
+ @override
constant_system.UnaryOperation operation() {
return constant_system.bitNot;
}
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -241,6 +245,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -266,10 +271,12 @@
class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
const UnaryNegateSpecializer();
+ @override
constant_system.UnaryOperation operation() {
return constant_system.negate;
}
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -297,6 +304,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -322,10 +330,12 @@
class AbsSpecializer extends InvokeDynamicSpecializer {
const AbsSpecializer();
+ @override
constant_system.UnaryOperation operation() {
return constant_system.abs;
}
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -341,6 +351,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -369,6 +380,7 @@
abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
const BinaryArithmeticSpecializer();
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -408,6 +420,7 @@
.isDefinitelyTrue;
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -465,6 +478,7 @@
class AddSpecializer extends BinaryArithmeticSpecializer {
const AddSpecializer();
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -480,10 +494,12 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
constant_system.BinaryOperation operation() {
return constant_system.add;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -506,10 +522,12 @@
class DivideSpecializer extends BinaryArithmeticSpecializer {
const DivideSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.divide;
}
+ @override
AbstractValue computeTypeFromInputTypes(
HInstruction instruction,
GlobalTypeInferenceResults results,
@@ -523,6 +541,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -542,6 +561,7 @@
class ModuloSpecializer extends BinaryArithmeticSpecializer {
const ModuloSpecializer();
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -554,10 +574,12 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
constant_system.BinaryOperation operation() {
return constant_system.modulo;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -634,6 +656,7 @@
class RemainderSpecializer extends BinaryArithmeticSpecializer {
const RemainderSpecializer();
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -646,10 +669,12 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
constant_system.BinaryOperation operation() {
return constant_system.remainder;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -672,10 +697,12 @@
class MultiplySpecializer extends BinaryArithmeticSpecializer {
const MultiplySpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.multiply;
}
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -688,6 +715,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -710,10 +738,12 @@
class SubtractSpecializer extends BinaryArithmeticSpecializer {
const SubtractSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.subtract;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -736,10 +766,12 @@
class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
const TruncatingDivideSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.truncatingDivide;
}
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -789,6 +821,7 @@
return false;
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -824,6 +857,7 @@
return null;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -846,6 +880,7 @@
abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
const BinaryBitOpSpecializer();
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -895,10 +930,12 @@
class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
const ShiftLeftSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.shiftLeft;
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -933,6 +970,7 @@
return null;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -955,6 +993,7 @@
class ShiftRightSpecializer extends BinaryBitOpSpecializer {
const ShiftRightSpecializer();
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -968,6 +1007,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -1015,6 +1055,7 @@
return null;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -1027,6 +1068,7 @@
computeTypeFromInputTypes(instruction, results, options, closedWorld));
}
+ @override
constant_system.BinaryOperation operation() {
return constant_system.shiftRight;
}
@@ -1041,10 +1083,12 @@
class BitOrSpecializer extends BinaryBitOpSpecializer {
const BitOrSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.bitOr;
}
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -1060,6 +1104,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -1072,6 +1117,7 @@
computeTypeFromInputTypes(instruction, results, options, closedWorld));
}
+ @override
void registerOptimization(
OptimizationTestLog log, HInstruction original, HInstruction converted) {
log.registerBitOr(original, converted);
@@ -1081,10 +1127,12 @@
class BitAndSpecializer extends BinaryBitOpSpecializer {
const BitAndSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.bitAnd;
}
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -1103,6 +1151,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -1115,6 +1164,7 @@
computeTypeFromInputTypes(instruction, results, options, closedWorld));
}
+ @override
void registerOptimization(
OptimizationTestLog log, HInstruction original, HInstruction converted) {
log.registerBitAnd(original, converted);
@@ -1124,10 +1174,12 @@
class BitXorSpecializer extends BinaryBitOpSpecializer {
const BitXorSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.bitXor;
}
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -1143,6 +1195,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -1155,6 +1208,7 @@
computeTypeFromInputTypes(instruction, results, options, closedWorld));
}
+ @override
void registerOptimization(
OptimizationTestLog log, HInstruction original, HInstruction converted) {
log.registerBitXor(original, converted);
@@ -1164,6 +1218,7 @@
abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
const RelationalSpecializer();
+ @override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
@@ -1178,6 +1233,7 @@
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -1209,6 +1265,7 @@
class EqualsSpecializer extends RelationalSpecializer {
const EqualsSpecializer();
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -1250,10 +1307,12 @@
return null;
}
+ @override
constant_system.BinaryOperation operation() {
return constant_system.equal;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction, JClosedWorld closedWorld) {
return new HIdentity(instruction.inputs[1], instruction.inputs[2],
@@ -1270,10 +1329,12 @@
class LessSpecializer extends RelationalSpecializer {
const LessSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.less;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction, JClosedWorld closedWorld) {
return new HLess(instruction.inputs[1], instruction.inputs[2],
@@ -1290,10 +1351,12 @@
class GreaterSpecializer extends RelationalSpecializer {
const GreaterSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.greater;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction, JClosedWorld closedWorld) {
return new HGreater(instruction.inputs[1], instruction.inputs[2],
@@ -1310,10 +1373,12 @@
class GreaterEqualSpecializer extends RelationalSpecializer {
const GreaterEqualSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.greaterEqual;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction, JClosedWorld closedWorld) {
return new HGreaterEqual(instruction.inputs[1], instruction.inputs[2],
@@ -1330,10 +1395,12 @@
class LessEqualSpecializer extends RelationalSpecializer {
const LessEqualSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.lessEqual;
}
+ @override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction, JClosedWorld closedWorld) {
return new HLessEqual(instruction.inputs[1], instruction.inputs[2],
@@ -1350,10 +1417,12 @@
class CodeUnitAtSpecializer extends InvokeDynamicSpecializer {
const CodeUnitAtSpecializer();
+ @override
constant_system.BinaryOperation operation() {
return constant_system.codeUnitAt;
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -1387,6 +1456,7 @@
class CompareToSpecializer extends InvokeDynamicSpecializer {
const CompareToSpecializer();
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -1436,6 +1506,7 @@
extends InvokeDynamicSpecializer {
const IdempotentStringOperationSpecializer();
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -1482,6 +1553,7 @@
class PatternMatchSpecializer extends InvokeDynamicSpecializer {
const PatternMatchSpecializer();
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
@@ -1510,10 +1582,12 @@
class RoundSpecializer extends InvokeDynamicSpecializer {
const RoundSpecializer();
+ @override
constant_system.UnaryOperation operation() {
return constant_system.round;
}
+ @override
HInstruction tryConvertToBuiltin(
HInvokeDynamic instruction,
HGraph graph,
diff --git a/pkg/compiler/lib/src/ssa/jump_handler.dart b/pkg/compiler/lib/src/ssa/jump_handler.dart
index 20d604b0..df6a83e 100644
--- a/pkg/compiler/lib/src/ssa/jump_handler.dart
+++ b/pkg/compiler/lib/src/ssa/jump_handler.dart
@@ -45,25 +45,34 @@
NullJumpHandler(this.reporter);
+ @override
void generateBreak(SourceInformation sourceInformation,
[LabelDefinition label]) {
reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
'NullJumpHandler.generateBreak should not be called.');
}
+ @override
void generateContinue(SourceInformation sourceInformation,
[LabelDefinition label]) {
reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
'NullJumpHandler.generateContinue should not be called.');
}
+ @override
void forEachBreak(Function ignored) {}
+ @override
void forEachContinue(Function ignored) {}
+ @override
void close() {}
+ @override
bool hasAnyContinue() => false;
+ @override
bool hasAnyBreak() => false;
+ @override
List<LabelDefinition> get labels => const <LabelDefinition>[];
+ @override
JumpTarget get target => null;
}
@@ -73,6 +82,7 @@
/// breaks of the body. Continues in switches is currently not handled.
class TargetJumpHandler implements JumpHandler {
final GraphBuilder builder;
+ @override
final JumpTarget target;
final List<_JumpHandlerEntry> jumps;
@@ -83,6 +93,7 @@
builder.jumpTargets[target] = this;
}
+ @override
void generateBreak(SourceInformation sourceInformation,
[LabelDefinition label]) {
HInstruction breakInstruction;
@@ -98,6 +109,7 @@
jumps.add(new _JumpHandlerEntry(breakInstruction, locals));
}
+ @override
void generateContinue(SourceInformation sourceInformation,
[LabelDefinition label]) {
HInstruction continueInstruction;
@@ -116,18 +128,21 @@
jumps.add(new _JumpHandlerEntry(continueInstruction, locals));
}
+ @override
void forEachBreak(Function action) {
for (_JumpHandlerEntry entry in jumps) {
if (entry.isBreak()) action(entry.jumpInstruction, entry.locals);
}
}
+ @override
void forEachContinue(Function action) {
for (_JumpHandlerEntry entry in jumps) {
if (entry.isContinue()) action(entry.jumpInstruction, entry.locals);
}
}
+ @override
bool hasAnyContinue() {
for (_JumpHandlerEntry entry in jumps) {
if (entry.isContinue()) return true;
@@ -135,6 +150,7 @@
return false;
}
+ @override
bool hasAnyBreak() {
for (_JumpHandlerEntry entry in jumps) {
if (entry.isBreak()) return true;
@@ -142,11 +158,13 @@
return false;
}
+ @override
void close() {
// The mapping from TargetElement to JumpHandler is no longer needed.
builder.jumpTargets.remove(target);
}
+ @override
List<LabelDefinition> get labels {
List<LabelDefinition> result = null;
for (LabelDefinition element in target.labels) {
@@ -167,6 +185,7 @@
SwitchCaseJumpHandler(GraphBuilder builder, JumpTarget target)
: super(builder, target);
+ @override
void generateBreak(SourceInformation sourceInformation,
[LabelDefinition label]) {
if (label == null) {
@@ -189,6 +208,7 @@
return label != null && targetIndexMap.containsKey(label.target);
}
+ @override
void generateContinue(SourceInformation sourceInformation,
[LabelDefinition label]) {
if (isContinueToSwitchCase(label)) {
@@ -212,6 +232,7 @@
}
}
+ @override
void close() {
// The mapping from TargetElement to JumpHandler is no longer needed.
for (JumpTarget target in targetIndexMap.keys) {
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index b74bb8c..9c08d57 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -692,15 +692,18 @@
/// For instance used for holding return value of function or the exception of a
/// try-catch statement.
class SyntheticLocal extends Local {
+ @override
final String name;
final Entity executableContext;
final MemberEntity memberContext;
// Avoid slow Object.hashCode.
+ @override
final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
static int _nextHashCode = 0;
SyntheticLocal(this.name, this.executableContext, this.memberContext);
+ @override
toString() => 'SyntheticLocal($name)';
}
diff --git a/pkg/compiler/lib/src/ssa/logging.dart b/pkg/compiler/lib/src/ssa/logging.dart
index cdaef90..0a99d31 100644
--- a/pkg/compiler/lib/src/ssa/logging.dart
+++ b/pkg/compiler/lib/src/ssa/logging.dart
@@ -244,6 +244,7 @@
return entries.join(',\n');
}
+ @override
String toString() => 'OptimizationLog(${getText()})';
}
@@ -257,5 +258,6 @@
OptimizationLogEntry(this.tag, this.features);
+ @override
String toString() => '$tag(${features.getText()})';
}
diff --git a/pkg/compiler/lib/src/ssa/loop_handler.dart b/pkg/compiler/lib/src/ssa/loop_handler.dart
index be4fb554..f9fda03 100644
--- a/pkg/compiler/lib/src/ssa/loop_handler.dart
+++ b/pkg/compiler/lib/src/ssa/loop_handler.dart
@@ -313,6 +313,7 @@
// TODO(het): Since kernel simplifies loop breaks and continues, we should
// rewrite the loop handler from scratch to account for the simplified structure
class KernelLoopHandler extends LoopHandler {
+ @override
final KernelSsaGraphBuilder builder;
KernelLoopHandler(KernelSsaGraphBuilder builder)
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 3b46935..0ec907d 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -188,6 +188,7 @@
visitInstruction(HInstruction node);
+ @override
visitBasicBlock(HBasicBlock node) {
void visitInstructionList(HInstructionList list) {
HInstruction instruction = list.first;
@@ -398,12 +399,14 @@
return validator.isValid;
}
+ @override
toString() => 'HGraph($element)';
}
class HBaseVisitor extends HGraphVisitor implements HVisitor {
HBasicBlock currentBlock;
+ @override
visitBasicBlock(HBasicBlock node) {
currentBlock = node;
@@ -428,93 +431,171 @@
visitFieldAccess(HFieldAccess node) => visitInstruction(node);
visitRelational(HRelational node) => visitInvokeBinary(node);
+ @override
visitAbs(HAbs node) => visitInvokeUnary(node);
+ @override
visitAdd(HAdd node) => visitBinaryArithmetic(node);
+ @override
visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
+ @override
visitBitNot(HBitNot node) => visitInvokeUnary(node);
+ @override
visitBitOr(HBitOr node) => visitBinaryBitOp(node);
+ @override
visitBitXor(HBitXor node) => visitBinaryBitOp(node);
+ @override
visitBoolify(HBoolify node) => visitInstruction(node);
+ @override
visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
+ @override
visitBreak(HBreak node) => visitJump(node);
+ @override
visitContinue(HContinue node) => visitJump(node);
visitCheck(HCheck node) => visitInstruction(node);
+ @override
visitConstant(HConstant node) => visitInstruction(node);
+ @override
visitCreate(HCreate node) => visitInstruction(node);
+ @override
visitCreateBox(HCreateBox node) => visitInstruction(node);
+ @override
visitDivide(HDivide node) => visitBinaryArithmetic(node);
+ @override
visitExit(HExit node) => visitControlFlow(node);
+ @override
visitExitTry(HExitTry node) => visitControlFlow(node);
+ @override
visitFieldGet(HFieldGet node) => visitFieldAccess(node);
+ @override
visitFieldSet(HFieldSet node) => visitFieldAccess(node);
+ @override
visitForeignCode(HForeignCode node) => visitInstruction(node);
+ @override
visitGetLength(HGetLength node) => visitInstruction(node);
+ @override
visitGoto(HGoto node) => visitControlFlow(node);
+ @override
visitGreater(HGreater node) => visitRelational(node);
+ @override
visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
+ @override
visitIdentity(HIdentity node) => visitRelational(node);
+ @override
visitIf(HIf node) => visitConditionalBranch(node);
+ @override
visitIndex(HIndex node) => visitInstruction(node);
+ @override
visitIndexAssign(HIndexAssign node) => visitInstruction(node);
+ @override
visitInterceptor(HInterceptor node) => visitInstruction(node);
+ @override
visitInvokeClosure(HInvokeClosure node) => visitInvokeDynamic(node);
+ @override
visitInvokeConstructorBody(HInvokeConstructorBody node) =>
visitInvokeStatic(node);
+ @override
visitInvokeGeneratorBody(HInvokeGeneratorBody node) =>
visitInvokeStatic(node);
+ @override
visitInvokeDynamicMethod(HInvokeDynamicMethod node) =>
visitInvokeDynamic(node);
+ @override
visitInvokeDynamicGetter(HInvokeDynamicGetter node) =>
visitInvokeDynamicField(node);
+ @override
visitInvokeDynamicSetter(HInvokeDynamicSetter node) =>
visitInvokeDynamicField(node);
+ @override
visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
+ @override
visitInvokeSuper(HInvokeSuper node) => visitInvokeStatic(node);
visitJump(HJump node) => visitControlFlow(node);
+ @override
visitLazyStatic(HLazyStatic node) => visitInstruction(node);
+ @override
visitLess(HLess node) => visitRelational(node);
+ @override
visitLessEqual(HLessEqual node) => visitRelational(node);
+ @override
visitLiteralList(HLiteralList node) => visitInstruction(node);
visitLocalAccess(HLocalAccess node) => visitInstruction(node);
+ @override
visitLocalGet(HLocalGet node) => visitLocalAccess(node);
+ @override
visitLocalSet(HLocalSet node) => visitLocalAccess(node);
+ @override
visitLocalValue(HLocalValue node) => visitInstruction(node);
+ @override
visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
+ @override
visitNegate(HNegate node) => visitInvokeUnary(node);
+ @override
visitNot(HNot node) => visitInstruction(node);
+ @override
visitOneShotInterceptor(HOneShotInterceptor node) => visitInvokeDynamic(node);
+ @override
visitPhi(HPhi node) => visitInstruction(node);
+ @override
visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
+ @override
visitParameterValue(HParameterValue node) => visitLocalValue(node);
+ @override
visitRangeConversion(HRangeConversion node) => visitCheck(node);
+ @override
visitReadModifyWrite(HReadModifyWrite node) => visitInstruction(node);
+ @override
visitRef(HRef node) => node.value.accept(this);
+ @override
visitRemainder(HRemainder node) => visitBinaryArithmetic(node);
+ @override
visitReturn(HReturn node) => visitControlFlow(node);
+ @override
visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
+ @override
visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
+ @override
visitSubtract(HSubtract node) => visitBinaryArithmetic(node);
+ @override
visitSwitch(HSwitch node) => visitControlFlow(node);
+ @override
visitStatic(HStatic node) => visitInstruction(node);
+ @override
visitStaticStore(HStaticStore node) => visitInstruction(node);
+ @override
visitStringConcat(HStringConcat node) => visitInstruction(node);
+ @override
visitStringify(HStringify node) => visitInstruction(node);
+ @override
visitThis(HThis node) => visitParameterValue(node);
+ @override
visitThrow(HThrow node) => visitControlFlow(node);
+ @override
visitThrowExpression(HThrowExpression node) => visitInstruction(node);
+ @override
visitTruncatingDivide(HTruncatingDivide node) => visitBinaryArithmetic(node);
+ @override
visitTry(HTry node) => visitControlFlow(node);
+ @override
visitIs(HIs node) => visitInstruction(node);
+ @override
visitLateValue(HLateValue node) => visitInstruction(node);
+ @override
visitIsViaInterceptor(HIsViaInterceptor node) => visitInstruction(node);
+ @override
visitTypeConversion(HTypeConversion node) => visitCheck(node);
+ @override
visitTypeKnown(HTypeKnown node) => visitCheck(node);
+ @override
visitAwait(HAwait node) => visitInstruction(node);
+ @override
visitYield(HYield node) => visitInstruction(node);
+ @override
visitTypeInfoReadRaw(HTypeInfoReadRaw node) => visitInstruction(node);
+ @override
visitTypeInfoReadVariable(HTypeInfoReadVariable node) =>
visitInstruction(node);
+ @override
visitTypeInfoExpression(HTypeInfoExpression node) => visitInstruction(node);
}
@@ -669,6 +750,7 @@
successors = const <HBasicBlock>[],
dominatedBlocks = <HBasicBlock>[];
+ @override
int get hashCode => id;
bool isNew() => status == STATUS_NEW;
@@ -762,6 +844,7 @@
instruction.notifyAddedToBlock(this);
}
+ @override
void remove(HInstruction instruction) {
assert(isOpen() || isClosed());
assert(instruction is! HPhi);
@@ -924,6 +1007,7 @@
other.dominatorDfsOut <= this.dominatorDfsOut;
}
+ @override
toString() => 'HBasicBlock($id)';
}
@@ -996,6 +1080,7 @@
assert(inputs.every((e) => e != null), "inputs: $inputs");
}
+ @override
int get hashCode => id;
bool useGvn() => _useGvn;
@@ -1473,6 +1558,7 @@
@override
accept(HVisitor visitor) => visitor.visitRef(this);
+ @override
String toString() => 'HRef(${value})';
}
@@ -1490,9 +1576,13 @@
sourceInformation = value.sourceInformation;
}
+ @override
accept(HVisitor visitor) => visitor.visitBoolify(this);
+ @override
int typeCode() => HInstruction.BOOLIFY_TYPECODE;
+ @override
bool typeEquals(other) => other is HBoolify;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -1506,9 +1596,12 @@
setUseGvn();
}
HInstruction get checkedInput => inputs[0];
+ @override
bool isJsStatement() => true;
+ @override
bool canThrow(AbstractValueDomain domain) => true;
+ @override
HInstruction nonCheck() => checkedInput.nonCheck();
}
@@ -1532,11 +1625,16 @@
// There can be an additional fourth input which is the index to report to
// [ioore]. This is used by the expansion of [JSArray.removeLast].
HInstruction get reportedIndex => inputs.length > 3 ? inputs[3] : index;
+ @override
bool isControlFlow() => true;
+ @override
accept(HVisitor visitor) => visitor.visitBoundsCheck(this);
+ @override
int typeCode() => HInstruction.BOUNDS_CHECK_TYPECODE;
+ @override
bool typeEquals(other) => other is HBoundsCheck;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -1554,7 +1652,9 @@
// have an `instructionType`, or statement-like [HInstruction]s should
// have a throwing getter.
: super(inputs, domain.emptyType);
+ @override
bool isControlFlow() => true;
+ @override
bool isJsStatement() => true;
}
@@ -1582,6 +1682,7 @@
this.sourceInformation = sourceInformation;
}
+ @override
bool isAllocation(AbstractValueDomain domain) => true;
HInstruction get rtiInput {
@@ -1589,8 +1690,10 @@
return inputs.last;
}
+ @override
accept(HVisitor visitor) => visitor.visitCreate(this);
+ @override
String toString() => 'HCreate($element, ${instantiatedTypes})';
}
@@ -1598,10 +1701,13 @@
class HCreateBox extends HInstruction {
HCreateBox(AbstractValue type) : super(<HInstruction>[], type);
+ @override
bool isAllocation(AbstractValueDomain domain) => true;
+ @override
accept(HVisitor visitor) => visitor.visitCreateBox(this);
+ @override
String toString() => 'HCreateBox()';
}
@@ -1617,7 +1723,9 @@
sideEffects.setDependsOnSomething();
}
static const int ARGUMENTS_OFFSET = 1;
+ @override
bool canThrow(AbstractValueDomain domain) => true;
+ @override
bool isAllocation(AbstractValueDomain domain) => _isAllocation;
void setAllocation(bool value) {
_isAllocation = value;
@@ -1626,6 +1734,7 @@
abstract class HInvokeDynamic extends HInvoke {
final InvokeDynamicSpecializer specializer;
+ @override
Selector selector;
AbstractValue mask;
MemberEntity element;
@@ -1640,8 +1749,10 @@
assert(isIntercepted != null);
isInterceptedCall = isIntercepted;
}
+ @override
toString() => 'invoke dynamic: selector=$selector, mask=$mask';
HInstruction get receiver => inputs[0];
+ @override
HInstruction getDartReceiver(JClosedWorld closedWorld) {
return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
}
@@ -1654,8 +1765,11 @@
return isInterceptedCall && receiver.isInterceptor(closedWorld);
}
+ @override
int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
+ @override
bool typeEquals(other) => other is HInvokeDynamic;
+ @override
bool dataEquals(HInvokeDynamic other) {
// Use the name and the kind instead of [Selector.operator==]
// because we don't need to check the arity (already checked in
@@ -1666,6 +1780,7 @@
}
class HInvokeClosure extends HInvokeDynamic {
+ @override
final List<DartType> typeArguments;
HInvokeClosure(Selector selector, List<HInstruction> inputs,
@@ -1675,10 +1790,12 @@
assert(selector.callStructure.typeArgumentCount == typeArguments.length);
assert(!isInterceptedCall);
}
+ @override
accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
}
class HInvokeDynamicMethod extends HInvokeDynamic {
+ @override
final List<DartType> typeArguments;
HInvokeDynamicMethod(
@@ -1694,7 +1811,9 @@
assert(selector.callStructure.typeArgumentCount == typeArguments.length);
}
+ @override
String toString() => 'invoke dynamic method: selector=$selector, mask=$mask';
+ @override
accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
}
@@ -1708,6 +1827,7 @@
AbstractValue type)
: super(selector, mask, element, inputs, isIntercepted, type);
+ @override
String toString() => 'invoke dynamic field: selector=$selector, mask=$mask';
}
@@ -1724,17 +1844,21 @@
this.sourceInformation = sourceInformation;
}
+ @override
accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
bool get isTearOff => element != null && element.isFunction;
+ @override
List<DartType> get typeArguments => const <DartType>[];
// There might be an interceptor input, so `inputs.last` is the dart receiver.
+ @override
bool canThrow(AbstractValueDomain domain) => isTearOff
? inputs.last.isNull(domain).isPotentiallyTrue
: super.canThrow(domain);
+ @override
String toString() => 'invoke dynamic getter: selector=$selector, mask=$mask';
}
@@ -1755,10 +1879,13 @@
this.sourceInformation = sourceInformation;
}
+ @override
accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
+ @override
List<DartType> get typeArguments => const <DartType>[];
+ @override
String toString() =>
'invoke dynamic setter: selector=$selector, mask=$mask, element=$element';
}
@@ -1771,6 +1898,7 @@
final bool targetCanThrow;
+ @override
bool canThrow(AbstractValueDomain domain) => targetCanThrow;
/// If this instruction is a call to a constructor, [instantiatedTypes]
@@ -1786,10 +1914,13 @@
isInterceptedCall = isIntercepted;
}
+ @override
accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
+ @override
int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE;
+ @override
String toString() => 'invoke static: $element';
}
@@ -1797,6 +1928,7 @@
/// The class where the call to super is being done.
final ClassEntity caller;
final bool isSetter;
+ @override
final Selector selector;
HInvokeSuper(
@@ -1815,6 +1947,7 @@
}
HInstruction get receiver => inputs[0];
+ @override
HInstruction getDartReceiver(JClosedWorld closedWorld) {
return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
}
@@ -1824,7 +1957,9 @@
return isInterceptedCall && receiver.isInterceptor(closedWorld);
}
+ @override
toString() => 'invoke super: $element';
+ @override
accept(HVisitor visitor) => visitor.visitInvokeSuper(this);
HInstruction get value {
@@ -1847,7 +1982,9 @@
this.sourceInformation = sourceInformation;
}
+ @override
String toString() => 'invoke constructor body: ${element.name}';
+ @override
accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this);
}
@@ -1866,7 +2003,9 @@
this.sourceInformation = sourceInformation;
}
+ @override
String toString() => 'HInvokeGeneratorBody(${element.name})';
+ @override
accept(HVisitor visitor) => visitor.visitInvokeGeneratorBody(this);
}
@@ -1897,6 +2036,7 @@
}
}
+ @override
bool isInterceptor(JClosedWorld closedWorld) {
if (sourceElement == null) return false;
// In case of a closure inside an interceptor class, [:this:] is
@@ -1910,18 +2050,26 @@
return false;
}
+ @override
bool canThrow(AbstractValueDomain domain) =>
receiver.isNull(domain).isPotentiallyTrue;
+ @override
HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+ @override
bool onlyThrowsNSM() => true;
bool get isNullCheck => element == null;
+ @override
accept(HVisitor visitor) => visitor.visitFieldGet(this);
+ @override
int typeCode() => HInstruction.FIELD_GET_TYPECODE;
+ @override
bool typeEquals(other) => other is HFieldGet;
+ @override
bool dataEquals(HFieldGet other) => element == other.element;
+ @override
String toString() => "FieldGet(element=$element,type=$instructionType)";
}
@@ -1934,18 +2082,24 @@
sideEffects.setChangesInstanceProperty();
}
+ @override
bool canThrow(AbstractValueDomain domain) =>
receiver.isNull(domain).isPotentiallyTrue;
+ @override
HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+ @override
bool onlyThrowsNSM() => true;
HInstruction get value => inputs[1];
+ @override
accept(HVisitor visitor) => visitor.visitFieldSet(this);
// HFieldSet is an expression if it has a user.
+ @override
bool isJsStatement() => usedBy.isEmpty;
+ @override
String toString() => "FieldSet(element=$element,type=$instructionType)";
}
@@ -1965,17 +2119,25 @@
HInstruction get receiver => inputs.single;
+ @override
bool canThrow(AbstractValueDomain domain) =>
receiver.isNull(domain).isPotentiallyTrue;
+ @override
HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+ @override
bool onlyThrowsNSM() => true;
+ @override
accept(HVisitor visitor) => visitor.visitGetLength(this);
+ @override
int typeCode() => HInstruction.GET_LENGTH_TYPECODE;
+ @override
bool typeEquals(other) => other is HGetLength;
+ @override
bool dataEquals(HGetLength other) => true;
+ @override
String toString() => "GetLength()";
}
@@ -2017,16 +2179,22 @@
bool get isPostOp => opKind == POST_OP;
bool get isAssignOp => opKind == ASSIGN_OP;
+ @override
bool canThrow(AbstractValueDomain domain) =>
receiver.isNull(domain).isPotentiallyTrue;
+ @override
HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+ @override
bool onlyThrowsNSM() => true;
HInstruction get value => inputs[1];
+ @override
accept(HVisitor visitor) => visitor.visitReadModifyWrite(this);
+ @override
bool isJsStatement() => isAssignOp;
+ @override
String toString() => "ReadModifyWrite $jsOp $opKind $element";
}
@@ -2048,6 +2216,7 @@
this.sourceInformation = sourceInformation;
}
+ @override
accept(HVisitor visitor) => visitor.visitLocalGet(this);
HLocalValue get local => inputs[0];
@@ -2058,10 +2227,12 @@
HInstruction value)
: super(variable, <HInstruction>[local, value], domain.emptyType);
+ @override
accept(HVisitor visitor) => visitor.visitLocalSet(this);
HLocalValue get local => inputs[0];
HInstruction get value => inputs[1];
+ @override
bool isJsStatement() => true;
}
@@ -2071,6 +2242,7 @@
bool get isStatement => false;
NativeBehavior get nativeBehavior => null;
+ @override
bool canThrow(AbstractValueDomain domain) {
return sideEffects.hasSideEffects() || sideEffects.dependsOnSomething();
}
@@ -2078,7 +2250,9 @@
class HForeignCode extends HForeign {
final js.Template codeTemplate;
+ @override
final bool isStatement;
+ @override
final NativeBehavior nativeBehavior;
NativeThrowBehavior throwBehavior;
final FunctionEntity foreignFunction;
@@ -2116,9 +2290,12 @@
effects: effects,
nativeBehavior: nativeBehavior);
+ @override
accept(HVisitor visitor) => visitor.visitForeignCode(this);
+ @override
bool isJsStatement() => isStatement;
+ @override
bool canThrow(AbstractValueDomain domain) {
if (inputs.length > 0) {
return inputs.first.isNull(domain).isPotentiallyTrue
@@ -2128,24 +2305,31 @@
return throwBehavior.canThrow;
}
+ @override
bool onlyThrowsNSM() => throwBehavior.isOnlyNullNSMGuard;
+ @override
bool isAllocation(AbstractValueDomain domain) =>
nativeBehavior != null &&
nativeBehavior.isAllocation &&
isNull(domain).isDefinitelyFalse;
+ @override
int typeCode() => HInstruction.FOREIGN_CODE_TYPECODE;
+ @override
bool typeEquals(other) => other is HForeignCode;
+ @override
bool dataEquals(HForeignCode other) {
return codeTemplate.source != null &&
codeTemplate.source == other.codeTemplate.source;
}
+ @override
String toString() => 'HForeignCode("${codeTemplate.source}")';
}
abstract class HInvokeBinary extends HInstruction {
+ @override
final Selector selector;
HInvokeBinary(
HInstruction left, HInstruction right, this.selector, AbstractValue type)
@@ -2165,6 +2349,7 @@
HBinaryArithmetic(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
constant_system.BinaryOperation operation();
}
@@ -2172,11 +2357,16 @@
HAdd(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitAdd(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.add;
+ @override
int typeCode() => HInstruction.ADD_TYPECODE;
+ @override
bool typeEquals(other) => other is HAdd;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2184,11 +2374,16 @@
HDivide(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitDivide(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.divide;
+ @override
int typeCode() => HInstruction.DIVIDE_TYPECODE;
+ @override
bool typeEquals(other) => other is HDivide;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2196,11 +2391,16 @@
HMultiply(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitMultiply(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.multiply;
+ @override
int typeCode() => HInstruction.MULTIPLY_TYPECODE;
+ @override
bool typeEquals(other) => other is HMultiply;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2208,11 +2408,16 @@
HSubtract(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitSubtract(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.subtract;
+ @override
int typeCode() => HInstruction.SUBTRACT_TYPECODE;
+ @override
bool typeEquals(other) => other is HSubtract;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2220,12 +2425,17 @@
HTruncatingDivide(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);
+ @override
constant_system.BinaryOperation operation() =>
constant_system.truncatingDivide;
+ @override
int typeCode() => HInstruction.TRUNCATING_DIVIDE_TYPECODE;
+ @override
bool typeEquals(other) => other is HTruncatingDivide;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2233,11 +2443,16 @@
HRemainder(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitRemainder(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.remainder;
+ @override
int typeCode() => HInstruction.REMAINDER_TYPECODE;
+ @override
bool typeEquals(other) => other is HRemainder;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2256,8 +2471,10 @@
/// following join-block.
HBasicBlock get defaultTarget => block.successors.last;
+ @override
accept(HVisitor visitor) => visitor.visitSwitch(this);
+ @override
String toString() => "HSwitch cases = $inputs";
}
@@ -2271,11 +2488,16 @@
HShiftLeft(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitShiftLeft(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.shiftLeft;
+ @override
int typeCode() => HInstruction.SHIFT_LEFT_TYPECODE;
+ @override
bool typeEquals(other) => other is HShiftLeft;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2283,11 +2505,16 @@
HShiftRight(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitShiftRight(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.shiftRight;
+ @override
int typeCode() => HInstruction.SHIFT_RIGHT_TYPECODE;
+ @override
bool typeEquals(other) => other is HShiftRight;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2295,11 +2522,16 @@
HBitOr(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitBitOr(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.bitOr;
+ @override
int typeCode() => HInstruction.BIT_OR_TYPECODE;
+ @override
bool typeEquals(other) => other is HBitOr;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2307,11 +2539,16 @@
HBitAnd(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitBitAnd(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.bitAnd;
+ @override
int typeCode() => HInstruction.BIT_AND_TYPECODE;
+ @override
bool typeEquals(other) => other is HBitAnd;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2319,15 +2556,21 @@
HBitXor(HInstruction left, HInstruction right, Selector selector,
AbstractValue type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitBitXor(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.bitXor;
+ @override
int typeCode() => HInstruction.BIT_XOR_TYPECODE;
+ @override
bool typeEquals(other) => other is HBitXor;
+ @override
bool dataEquals(HInstruction other) => true;
}
abstract class HInvokeUnary extends HInstruction {
+ @override
final Selector selector;
HInvokeUnary(HInstruction input, this.selector, type)
: super(<HInstruction>[input], type) {
@@ -2344,45 +2587,64 @@
class HNegate extends HInvokeUnary {
HNegate(HInstruction input, Selector selector, AbstractValue type)
: super(input, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitNegate(this);
+ @override
constant_system.UnaryOperation operation() => constant_system.negate;
+ @override
int typeCode() => HInstruction.NEGATE_TYPECODE;
+ @override
bool typeEquals(other) => other is HNegate;
+ @override
bool dataEquals(HInstruction other) => true;
}
class HAbs extends HInvokeUnary {
HAbs(HInstruction input, Selector selector, AbstractValue type)
: super(input, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitAbs(this);
+ @override
constant_system.UnaryOperation operation() => constant_system.abs;
+ @override
int typeCode() => HInstruction.ABS_TYPECODE;
+ @override
bool typeEquals(other) => other is HAbs;
+ @override
bool dataEquals(HInstruction other) => true;
}
class HBitNot extends HInvokeUnary {
HBitNot(HInstruction input, Selector selector, AbstractValue type)
: super(input, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitBitNot(this);
+ @override
constant_system.UnaryOperation operation() => constant_system.bitNot;
+ @override
int typeCode() => HInstruction.BIT_NOT_TYPECODE;
+ @override
bool typeEquals(other) => other is HBitNot;
+ @override
bool dataEquals(HInstruction other) => true;
}
class HExit extends HControlFlow {
HExit(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
+ @override
toString() => 'exit';
+ @override
accept(HVisitor visitor) => visitor.visitExit(this);
}
class HGoto extends HControlFlow {
HGoto(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
+ @override
toString() => 'goto';
+ @override
accept(HVisitor visitor) => visitor.visitGoto(this);
}
@@ -2420,8 +2682,10 @@
: breakSwitchContinueLoop = false,
super.toLabel(domain, label, sourceInformation);
+ @override
String toString() => (label != null) ? 'break ${label.labelName}' : 'break';
+ @override
accept(HVisitor visitor) => visitor.visitBreak(this);
}
@@ -2434,9 +2698,11 @@
SourceInformation sourceInformation)
: super.toLabel(domain, label, sourceInformation);
+ @override
String toString() =>
(label != null) ? 'continue ${label.labelName}' : 'continue';
+ @override
accept(HVisitor visitor) => visitor.visitContinue(this);
}
@@ -2445,7 +2711,9 @@
HBasicBlock catchBlock;
HBasicBlock finallyBlock;
HTry(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
+ @override
toString() => 'try';
+ @override
accept(HVisitor visitor) => visitor.visitTry(this);
HBasicBlock get joinBlock => this.block.successors.last;
}
@@ -2457,7 +2725,9 @@
// finally.
class HExitTry extends HControlFlow {
HExitTry(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
+ @override
toString() => 'exit try';
+ @override
accept(HVisitor visitor) => visitor.visitExitTry(this);
HBasicBlock get bodyTrySuccessor => block.successors[0];
}
@@ -2466,7 +2736,9 @@
HBlockFlow blockInformation = null;
HIf(AbstractValueDomain domain, HInstruction condition)
: super(domain, <HInstruction>[condition]);
+ @override
toString() => 'if';
+ @override
accept(HVisitor visitor) => visitor.visitIf(this);
HBasicBlock get thenBlock {
@@ -2490,7 +2762,9 @@
HLoopBranch(AbstractValueDomain domain, HInstruction condition,
[this.kind = CONDITION_FIRST_LOOP])
: super(domain, <HInstruction>[condition]);
+ @override
toString() => 'loop-branch';
+ @override
accept(HVisitor visitor) => visitor.visitLoopBranch(this);
}
@@ -2499,25 +2773,40 @@
HConstant.internal(this.constant, AbstractValue constantType)
: super(<HInstruction>[], constantType);
+ @override
toString() => 'literal: ${constant.toStructuredText()}';
+ @override
accept(HVisitor visitor) => visitor.visitConstant(this);
+ @override
bool isConstant() => true;
+ @override
bool isConstantBoolean() => constant.isBool;
+ @override
bool isConstantNull() => constant.isNull;
+ @override
bool isConstantNumber() => constant.isNum;
+ @override
bool isConstantInteger() => constant.isInt;
+ @override
bool isConstantString() => constant.isString;
+ @override
bool isConstantList() => constant.isList;
+ @override
bool isConstantMap() => constant.isMap;
+ @override
bool isConstantFalse() => constant.isFalse;
+ @override
bool isConstantTrue() => constant.isTrue;
+ @override
bool isInterceptor(JClosedWorld closedWorld) => constant.isInterceptor;
// Maybe avoid this if the literal is big?
+ @override
bool isCodeMotionInvariant() => true;
+ @override
set instructionType(type) {
// Only lists can be specialized. The SSA builder uses the
// inferrer for finding the type of a constant list. We should
@@ -2533,9 +2822,13 @@
setUseGvn();
}
+ @override
accept(HVisitor visitor) => visitor.visitNot(this);
+ @override
int typeCode() => HInstruction.NOT_TYPECODE;
+ @override
bool typeEquals(other) => other is HNot;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2548,7 +2841,9 @@
sourceElement = variable;
}
+ @override
toString() => 'local ${sourceElement.name}';
+ @override
accept(HVisitor visitor) => visitor.visitLocalValue(this);
}
@@ -2566,27 +2861,35 @@
return false;
}
+ @override
toString() => 'parameter ${sourceElement.name}';
+ @override
accept(HVisitor visitor) => visitor.visitParameterValue(this);
}
class HThis extends HParameterValue {
HThis(ThisLocal element, AbstractValue type) : super(element, type);
+ @override
ThisLocal get sourceElement => super.sourceElement;
+ @override
void set sourceElement(covariant ThisLocal local) {
super.sourceElement = local;
}
+ @override
accept(HVisitor visitor) => visitor.visitThis(this);
+ @override
bool isCodeMotionInvariant() => true;
+ @override
bool isInterceptor(JClosedWorld closedWorld) {
return closedWorld.interceptorData
.isInterceptedClass(sourceElement.enclosingClass);
}
+ @override
String toString() => 'this';
}
@@ -2618,7 +2921,9 @@
input.usedBy.add(this);
}
+ @override
toString() => 'phi $id';
+ @override
accept(HVisitor visitor) => visitor.visitPhi(this);
}
@@ -2632,52 +2937,77 @@
String singleComparisonOp; // null, '===', '=='
HIdentity(left, right, selector, type) : super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitIdentity(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.identity;
+ @override
int typeCode() => HInstruction.IDENTITY_TYPECODE;
+ @override
bool typeEquals(other) => other is HIdentity;
+ @override
bool dataEquals(HInstruction other) => true;
}
class HGreater extends HRelational {
HGreater(left, right, selector, type) : super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitGreater(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.greater;
+ @override
int typeCode() => HInstruction.GREATER_TYPECODE;
+ @override
bool typeEquals(other) => other is HGreater;
+ @override
bool dataEquals(HInstruction other) => true;
}
class HGreaterEqual extends HRelational {
HGreaterEqual(left, right, selector, type)
: super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitGreaterEqual(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.greaterEqual;
+ @override
int typeCode() => HInstruction.GREATER_EQUAL_TYPECODE;
+ @override
bool typeEquals(other) => other is HGreaterEqual;
+ @override
bool dataEquals(HInstruction other) => true;
}
class HLess extends HRelational {
HLess(left, right, selector, type) : super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitLess(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.less;
+ @override
int typeCode() => HInstruction.LESS_TYPECODE;
+ @override
bool typeEquals(other) => other is HLess;
+ @override
bool dataEquals(HInstruction other) => true;
}
class HLessEqual extends HRelational {
HLessEqual(left, right, selector, type) : super(left, right, selector, type);
+ @override
accept(HVisitor visitor) => visitor.visitLessEqual(this);
+ @override
constant_system.BinaryOperation operation() => constant_system.lessEqual;
+ @override
int typeCode() => HInstruction.LESS_EQUAL_TYPECODE;
+ @override
bool typeEquals(other) => other is HLessEqual;
+ @override
bool dataEquals(HInstruction other) => true;
}
@@ -2687,7 +3017,9 @@
: super(domain, <HInstruction>[value]) {
this.sourceInformation = sourceInformation;
}
+ @override
toString() => 'return';
+ @override
accept(HVisitor visitor) => visitor.visitReturn(this);
}
@@ -2697,18 +3029,25 @@
: super(<HInstruction>[value], domain.emptyType) {
this.sourceInformation = sourceInformation;
}
+ @override
toString() => 'throw expression';
+ @override
accept(HVisitor visitor) => visitor.visitThrowExpression(this);
+ @override
bool canThrow(AbstractValueDomain domain) => true;
}
class HAwait extends HInstruction {
HAwait(HInstruction value, AbstractValue type)
: super(<HInstruction>[value], type);
+ @override
toString() => 'await';
+ @override
accept(HVisitor visitor) => visitor.visitAwait(this);
// An await will throw if its argument is not a real future.
+ @override
bool canThrow(AbstractValueDomain domain) => true;
+ @override
SideEffects sideEffects = new SideEffects();
}
@@ -2719,9 +3058,13 @@
this.sourceInformation = sourceInformation;
}
bool hasStar;
+ @override
toString() => 'yield';
+ @override
accept(HVisitor visitor) => visitor.visitYield(this);
+ @override
bool canThrow(AbstractValueDomain domain) => false;
+ @override
SideEffects sideEffects = new SideEffects();
}
@@ -2733,7 +3076,9 @@
: super(domain, <HInstruction>[value]) {
this.sourceInformation = sourceInformation;
}
+ @override
toString() => 'throw';
+ @override
accept(HVisitor visitor) => visitor.visitThrow(this);
}
@@ -2750,13 +3095,20 @@
setUseGvn();
this.sourceInformation = sourceInformation;
}
+ @override
toString() => 'static ${element.name}';
+ @override
accept(HVisitor visitor) => visitor.visitStatic(this);
+ @override
int gvnHashCode() => super.gvnHashCode() ^ element.hashCode;
+ @override
int typeCode() => HInstruction.STATIC_TYPECODE;
+ @override
bool typeEquals(other) => other is HStatic;
+ @override
bool dataEquals(HStatic other) => element == other.element;
+ @override
bool isCodeMotionInvariant() => !element.isAssignable;
}
@@ -2782,7 +3134,9 @@
setUseGvn();
}
+ @override
String toString() => 'interceptor on $interceptedClasses';
+ @override
accept(HVisitor visitor) => visitor.visitInterceptor(this);
HInstruction get receiver => inputs[0];
@@ -2793,10 +3147,14 @@
inputs.add(constant);
}
+ @override
bool isInterceptor(JClosedWorld closedWorld) => true;
+ @override
int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
+ @override
bool typeEquals(other) => other is HInterceptor;
+ @override
bool dataEquals(HInterceptor other) {
return interceptedClasses == other.interceptedClasses ||
(interceptedClasses.length == other.interceptedClasses.length &&
@@ -2812,6 +3170,7 @@
/// calls, this class extends [HInvokeDynamic] and also has the null
/// constant as the first input.
class HOneShotInterceptor extends HInvokeDynamic {
+ @override
List<DartType> typeArguments;
Set<ClassEntity> interceptedClasses;
@@ -2828,9 +3187,12 @@
assert(inputs[0].instructionType == domain.nullType);
assert(selector.callStructure.typeArgumentCount == typeArguments.length);
}
+ @override
bool isCallOnInterceptor(JClosedWorld closedWorld) => true;
+ @override
String toString() => 'one shot interceptor: selector=$selector, mask=$mask';
+ @override
accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
}
@@ -2848,12 +3210,17 @@
this.sourceInformation = sourceInformation;
}
+ @override
toString() => 'lazy static ${element.name}';
+ @override
accept(HVisitor visitor) => visitor.visitLazyStatic(this);
+ @override
int typeCode() => 30;
// TODO(4931): can we do better here?
+ @override
bool isCodeMotionInvariant() => false;
+ @override
bool canThrow(AbstractValueDomain domain) => true;
}
@@ -2865,29 +3232,39 @@
sideEffects.clearAllDependencies();
sideEffects.setChangesStaticProperty();
}
+ @override
toString() => 'static store ${element.name}';
+ @override
accept(HVisitor visitor) => visitor.visitStaticStore(this);
HInstruction get value => inputs.single;
+ @override
int typeCode() => HInstruction.STATIC_STORE_TYPECODE;
+ @override
bool typeEquals(other) => other is HStaticStore;
+ @override
bool dataEquals(HStaticStore other) => element == other.element;
+ @override
bool isJsStatement() => usedBy.isEmpty;
}
class HLiteralList extends HInstruction {
HLiteralList(List<HInstruction> inputs, AbstractValue type)
: super(inputs, type);
+ @override
toString() => 'literal list';
+ @override
accept(HVisitor visitor) => visitor.visitLiteralList(this);
+ @override
bool isAllocation(AbstractValueDomain domain) => true;
}
/// The primitive array indexing operation. Note that this instruction
/// does not throw because we generate the checks explicitly.
class HIndex extends HInstruction {
+ @override
final Selector selector;
HIndex(HInstruction receiver, HInstruction index, this.selector,
AbstractValue type)
@@ -2898,7 +3275,9 @@
setUseGvn();
}
+ @override
String toString() => 'index operator';
+ @override
accept(HVisitor visitor) => visitor.visitIndex(this);
HInstruction get receiver => inputs[0];
@@ -2906,21 +3285,29 @@
// Implicit dependency on HBoundsCheck or constraints on index.
// TODO(27272): Make HIndex dependent on bounds checking.
+ @override
bool get isMovable => false;
+ @override
HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+ @override
bool onlyThrowsNSM() => true;
+ @override
bool canThrow(AbstractValueDomain domain) =>
receiver.isNull(domain).isPotentiallyTrue;
+ @override
int typeCode() => HInstruction.INDEX_TYPECODE;
+ @override
bool typeEquals(HInstruction other) => other is HIndex;
+ @override
bool dataEquals(HIndex other) => true;
}
/// The primitive array assignment operation. Note that this instruction
/// does not throw because we generate the checks explicitly.
class HIndexAssign extends HInstruction {
+ @override
final Selector selector;
HIndexAssign(AbstractValueDomain domain, HInstruction receiver,
HInstruction index, HInstruction value, this.selector)
@@ -2929,7 +3316,9 @@
sideEffects.clearAllDependencies();
sideEffects.setChangesIndex();
}
+ @override
String toString() => 'index assign operator';
+ @override
accept(HVisitor visitor) => visitor.visitIndexAssign(this);
HInstruction get receiver => inputs[0];
@@ -2938,10 +3327,14 @@
// Implicit dependency on HBoundsCheck or constraints on index.
// TODO(27272): Make HIndex dependent on bounds checking.
+ @override
bool get isMovable => false;
+ @override
HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+ @override
bool onlyThrowsNSM() => true;
+ @override
bool canThrow(AbstractValueDomain domain) =>
receiver.isNull(domain).isPotentiallyTrue;
}
@@ -3030,14 +3423,19 @@
bool get isVariableCheck => kind == VARIABLE_CHECK;
bool get isCompoundCheck => kind == COMPOUND_CHECK;
+ @override
accept(HVisitor visitor) => visitor.visitIs(this);
+ @override
toString() => "$expression is $typeExpression";
+ @override
int typeCode() => HInstruction.IS_TYPECODE;
+ @override
bool typeEquals(HInstruction other) => other is HIs;
+ @override
bool dataEquals(HIs other) {
return typeExpression == other.typeExpression && kind == other.kind;
}
@@ -3056,10 +3454,15 @@
HInstruction get interceptor => inputs[0];
+ @override
accept(HVisitor visitor) => visitor.visitIsViaInterceptor(this);
+ @override
toString() => "$interceptor is $typeExpression";
+ @override
int typeCode() => HInstruction.IS_VIA_INTERCEPTOR_TYPECODE;
+ @override
bool typeEquals(HInstruction other) => other is HIsViaInterceptor;
+ @override
bool dataEquals(HIs other) {
return typeExpression == other.typeExpression;
}
@@ -3077,7 +3480,9 @@
HInstruction get target => inputs.single;
+ @override
accept(HVisitor visitor) => visitor.visitLateValue(this);
+ @override
toString() => 'HLateValue($target)';
}
@@ -3143,8 +3548,10 @@
HInstruction get typeRepresentation => inputs[1];
+ @override
HInstruction get checkedInput => super.checkedInput;
+ @override
HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
if (typeExpression == type) {
// Don't omit a boolean conversion (which doesn't allow `null`) unless
@@ -3165,15 +3572,22 @@
bool get isCastTypeCheck => kind == CAST_TYPE_CHECK;
bool get isBooleanConversionCheck => kind == BOOLEAN_CONVERSION_CHECK;
+ @override
accept(HVisitor visitor) => visitor.visitTypeConversion(this);
+ @override
bool isJsStatement() => isControlFlow();
+ @override
bool isControlFlow() => isArgumentTypeCheck || isReceiverTypeCheck;
+ @override
int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE;
+ @override
bool typeEquals(HInstruction other) => other is HTypeConversion;
+ @override
bool isCodeMotionInvariant() => false;
+ @override
bool dataEquals(HTypeConversion other) {
return kind == other.kind &&
typeExpression == other.typeExpression &&
@@ -3220,6 +3634,7 @@
return abstractValueDomain.isIn(inputType, checkedType).isDefinitelyTrue;
}
+ @override
String toString() => 'HTypeConversion(type=$typeExpression, kind=$kind, '
'${hasTypeRepresentation ? 'representation=$typeRepresentation, ' : ''}'
'checkedInput=$checkedInput)';
@@ -3241,22 +3656,32 @@
this._isMovable = true,
super(<HInstruction>[input, witness], knownType);
+ @override
toString() => 'TypeKnown $knownType';
+ @override
accept(HVisitor visitor) => visitor.visitTypeKnown(this);
+ @override
bool isJsStatement() => false;
+ @override
bool isControlFlow() => false;
+ @override
bool canThrow(AbstractValueDomain domain) => false;
bool get isPinned => inputs.length == 1;
HInstruction get witness => inputs.length == 2 ? inputs[1] : null;
+ @override
int typeCode() => HInstruction.TYPE_KNOWN_TYPECODE;
+ @override
bool typeEquals(HInstruction other) => other is HTypeKnown;
+ @override
bool isCodeMotionInvariant() => true;
+ @override
bool get isMovable => _isMovable && useGvn();
+ @override
bool dataEquals(HTypeKnown other) {
return knownType == other.knownType &&
instructionType == other.instructionType;
@@ -3278,8 +3703,10 @@
sourceElement = input.sourceElement;
}
+ @override
bool get isMovable => false;
+ @override
accept(HVisitor visitor) => visitor.visitRangeConversion(this);
}
@@ -3295,7 +3722,9 @@
HInstruction get left => inputs[0];
HInstruction get right => inputs[1];
+ @override
accept(HVisitor visitor) => visitor.visitStringConcat(this);
+ @override
toString() => "string concat";
}
@@ -3308,7 +3737,9 @@
sideEffects.setDependsOnSomething();
}
+ @override
accept(HVisitor visitor) => visitor.visitStringify(this);
+ @override
toString() => "stringify";
}
@@ -3372,11 +3803,13 @@
/// Information about a statement-like structure.
abstract class HStatementInformation extends HBlockInformation {
+ @override
bool accept(HStatementInformationVisitor visitor);
}
/// Information about an expression-like structure.
abstract class HExpressionInformation extends HBlockInformation {
+ @override
bool accept(HExpressionInformationVisitor visitor);
HInstruction get conditionExpression;
}
@@ -3407,9 +3840,12 @@
final SubGraph subGraph;
HSubGraphBlockInformation(this.subGraph);
+ @override
HBasicBlock get start => subGraph.start;
+ @override
HBasicBlock get end => subGraph.end;
+ @override
bool accept(HStatementInformationVisitor visitor) =>
visitor.visitSubGraphInfo(this);
}
@@ -3420,11 +3856,15 @@
final SubExpression subExpression;
HSubExpressionBlockInformation(this.subExpression);
+ @override
HBasicBlock get start => subExpression.start;
+ @override
HBasicBlock get end => subExpression.end;
+ @override
HInstruction get conditionExpression => subExpression.conditionExpression;
+ @override
bool accept(HExpressionInformationVisitor visitor) =>
visitor.visitSubExpressionInfo(this);
}
@@ -3434,9 +3874,12 @@
final List<HStatementInformation> statements;
HStatementSequenceInformation(this.statements);
+ @override
HBasicBlock get start => statements[0].start;
+ @override
HBasicBlock get end => statements.last.end;
+ @override
bool accept(HStatementInformationVisitor visitor) =>
visitor.visitSequenceInfo(this);
}
@@ -3456,9 +3899,12 @@
{this.isContinue: false})
: this.labels = const <LabelDefinition>[];
+ @override
HBasicBlock get start => body.start;
+ @override
HBasicBlock get end => body.end;
+ @override
bool accept(HStatementInformationVisitor visitor) =>
visitor.visitLabeledBlockInfo(this);
}
@@ -3486,6 +3932,7 @@
(kind == DO_WHILE_LOOP ? body.start : condition.start).isLoopHeader());
}
+ @override
HBasicBlock get start {
if (initializer != null) return initializer.start;
if (kind == DO_WHILE_LOOP) {
@@ -3498,6 +3945,7 @@
return kind == DO_WHILE_LOOP ? body.start : condition.start;
}
+ @override
HBasicBlock get end {
if (updates != null) return updates.end;
if (kind == DO_WHILE_LOOP && condition != null) {
@@ -3506,6 +3954,7 @@
return body.end;
}
+ @override
bool accept(HStatementInformationVisitor visitor) =>
visitor.visitLoopInfo(this);
}
@@ -3516,9 +3965,12 @@
final HStatementInformation elseGraph;
HIfBlockInformation(this.condition, this.thenGraph, this.elseGraph);
+ @override
HBasicBlock get start => condition.start;
+ @override
HBasicBlock get end => elseGraph == null ? thenGraph.end : elseGraph.end;
+ @override
bool accept(HStatementInformationVisitor visitor) =>
visitor.visitIfInfo(this);
}
@@ -3529,14 +3981,18 @@
final HExpressionInformation right;
HAndOrBlockInformation(this.isAnd, this.left, this.right);
+ @override
HBasicBlock get start => left.start;
+ @override
HBasicBlock get end => right.end;
// We don't currently use HAndOrBlockInformation.
+ @override
HInstruction get conditionExpression {
return null;
}
+ @override
bool accept(HExpressionInformationVisitor visitor) =>
visitor.visitAndOrInfo(this);
}
@@ -3549,10 +4005,13 @@
HTryBlockInformation(
this.body, this.catchVariable, this.catchBlock, this.finallyBlock);
+ @override
HBasicBlock get start => body.start;
+ @override
HBasicBlock get end =>
finallyBlock == null ? catchBlock.end : finallyBlock.end;
+ @override
bool accept(HStatementInformationVisitor visitor) =>
visitor.visitTryInfo(this);
}
@@ -3567,13 +4026,16 @@
HSwitchBlockInformation(this.expression, this.statements, this.target,
this.labels, this.sourceInformation);
+ @override
HBasicBlock get start => expression.start;
+ @override
HBasicBlock get end {
// We don't create a switch block if there are no cases.
assert(!statements.isEmpty);
return statements.last.end;
}
+ @override
bool accept(HStatementInformationVisitor visitor) =>
visitor.visitSwitchInfo(this);
}
@@ -3585,13 +4047,18 @@
setUseGvn();
}
+ @override
accept(HVisitor visitor) => visitor.visitTypeInfoReadRaw(this);
+ @override
bool canThrow(AbstractValueDomain domain) => false;
+ @override
int typeCode() => HInstruction.TYPE_INFO_READ_RAW_TYPECODE;
+ @override
bool typeEquals(HInstruction other) => other is HTypeInfoReadRaw;
+ @override
bool dataEquals(HTypeInfoReadRaw other) {
return true;
}
@@ -3626,17 +4093,23 @@
HInstruction get object => inputs.last;
+ @override
accept(HVisitor visitor) => visitor.visitTypeInfoReadVariable(this);
+ @override
bool canThrow(AbstractValueDomain domain) => false;
+ @override
int typeCode() => HInstruction.TYPE_INFO_READ_VARIABLE_TYPECODE;
+ @override
bool typeEquals(HInstruction other) => other is HTypeInfoReadVariable;
+ @override
bool dataEquals(HTypeInfoReadVariable other) {
return variable == other.variable;
}
+ @override
String toString() => 'HTypeInfoReadVariable($variable)';
}
@@ -3706,17 +4179,23 @@
setUseGvn();
}
+ @override
accept(HVisitor visitor) => visitor.visitTypeInfoExpression(this);
+ @override
bool canThrow(AbstractValueDomain domain) => false;
+ @override
int typeCode() => HInstruction.TYPE_INFO_EXPRESSION_TYPECODE;
+ @override
bool typeEquals(HInstruction other) => other is HTypeInfoExpression;
+ @override
bool dataEquals(HTypeInfoExpression other) {
return kind == other.kind && dartType == other.dartType;
}
+ @override
String toString() => 'HTypeInfoExpression($kindAsString, $dartType)';
// ignore: MISSING_RETURN
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index e40719b..e584210 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -48,6 +48,7 @@
SsaOptimizerTask(this._backend) : super(_backend.compiler.measurer);
+ @override
String get name => 'SSA optimizer';
Compiler get _compiler => _backend.compiler;
@@ -191,6 +192,7 @@
// strings.
static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512;
+ @override
final String name = "SsaInstructionSimplifier";
final GlobalTypeInferenceResults _globalInferenceResults;
final CompilerOptions _options;
@@ -210,11 +212,13 @@
NativeData get _nativeData => _closedWorld.nativeData;
+ @override
void visitGraph(HGraph visitee) {
_graph = visitee;
visitDominatorTree(visitee);
}
+ @override
visitBasicBlock(HBasicBlock block) {
simplifyPhis(block);
HInstruction instruction = block.first;
@@ -383,6 +387,7 @@
return true;
}
+ @override
HInstruction visitInstruction(HInstruction node) {
return node;
}
@@ -411,6 +416,7 @@
}
}
+ @override
HInstruction visitParameterValue(HParameterValue node) {
// [HParameterValue]s are either the value of the parameter (in fully SSA
// converted code), or the mutable variable containing the value (in
@@ -436,6 +442,7 @@
return node;
}
+ @override
HInstruction visitBoolify(HBoolify node) {
List<HInstruction> inputs = node.inputs;
assert(inputs.length == 1);
@@ -462,6 +469,7 @@
return node;
}
+ @override
HInstruction visitNot(HNot node) {
List<HInstruction> inputs = node.inputs;
assert(inputs.length == 1);
@@ -476,6 +484,7 @@
return node;
}
+ @override
HInstruction visitInvokeUnary(HInvokeUnary node) {
HInstruction folded = foldUnary(node.operation(), node.operand);
return folded != null ? folded : node;
@@ -688,6 +697,7 @@
return tagInstruction;
}
+ @override
HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
propagateConstantValueToUses(node);
if (node.isInterceptedCall) {
@@ -849,6 +859,7 @@
return result;
}
+ @override
HInstruction visitBoundsCheck(HBoundsCheck node) {
HInstruction index = node.index;
if (index.isInteger(_abstractValueDomain).isDefinitelyTrue) {
@@ -876,6 +887,7 @@
return null;
}
+ @override
HInstruction visitAdd(HAdd node) {
HInstruction left = node.left;
HInstruction right = node.right;
@@ -889,6 +901,7 @@
return super.visitAdd(node);
}
+ @override
HInstruction visitMultiply(HMultiply node) {
HInstruction left = node.left;
HInstruction right = node.right;
@@ -900,6 +913,7 @@
return super.visitMultiply(node);
}
+ @override
HInstruction visitInvokeBinary(HInvokeBinary node) {
HInstruction left = node.left;
HInstruction right = node.right;
@@ -918,6 +932,7 @@
return true;
}
+ @override
HInstruction visitRelational(HRelational node) {
if (allUsersAreBoolifies(node)) {
// TODO(ngeoffray): Call a boolified selector.
@@ -987,6 +1002,7 @@
return null;
}
+ @override
HInstruction visitIdentity(HIdentity node) {
HInstruction newInstruction = handleIdentityCheck(node);
return newInstruction == null ? super.visitIdentity(node) : newInstruction;
@@ -1019,6 +1035,7 @@
uses.replaceWith(_graph.addConstantBool(value, _closedWorld));
}
+ @override
HInstruction visitIf(HIf node) {
HInstruction condition = node.condition;
if (condition.isConstant()) return node;
@@ -1044,6 +1061,7 @@
return node;
}
+ @override
HInstruction visitIs(HIs node) {
DartType type = node.typeExpression;
@@ -1118,6 +1136,7 @@
return node;
}
+ @override
HInstruction visitTypeConversion(HTypeConversion node) {
if (node.isRedundant(_closedWorld)) return node.checkedInput;
@@ -1139,6 +1158,7 @@
return node;
}
+ @override
HInstruction visitTypeKnown(HTypeKnown node) {
return node.isRedundant(_closedWorld) ? node.checkedInput : node;
}
@@ -1152,6 +1172,7 @@
return member is FieldEntity ? member : null;
}
+ @override
HInstruction visitFieldGet(HFieldGet node) {
if (node.isNullCheck) return node;
var receiver = node.receiver;
@@ -1173,6 +1194,7 @@
return node;
}
+ @override
HInstruction visitGetLength(HGetLength node) {
HInstruction receiver = node.receiver;
if (_graph.allocatedFixedLists.contains(receiver)) {
@@ -1219,6 +1241,7 @@
return node;
}
+ @override
HInstruction visitIndex(HIndex node) {
if (node.receiver.isConstantList() && node.index.isConstantInteger()) {
HConstant instruction = node.receiver;
@@ -1234,6 +1257,7 @@
return node;
}
+ @override
HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
propagateConstantValueToUses(node);
if (node.isInterceptedCall) {
@@ -1312,6 +1336,7 @@
isAssignable: isAssignable);
}
+ @override
HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
if (node.isInterceptedCall) {
HInstruction folded = handleInterceptedCall(node);
@@ -1356,6 +1381,7 @@
}
}
+ @override
HInstruction visitInvokeClosure(HInvokeClosure node) {
HInstruction closure = node.getDartReceiver(_closedWorld);
@@ -1378,6 +1404,7 @@
return node;
}
+ @override
HInstruction visitInvokeStatic(HInvokeStatic node) {
propagateConstantValueToUses(node);
MemberEntity element = node.element;
@@ -1478,6 +1505,7 @@
return source;
}
+ @override
HInstruction visitStringConcat(HStringConcat node) {
// Simplify string concat:
//
@@ -1525,6 +1553,7 @@
return new HStringConcat(prefix, folded, _abstractValueDomain.stringType);
}
+ @override
HInstruction visitStringify(HStringify node) {
HInstruction input = node.inputs[0];
if (input.isString(_abstractValueDomain).isDefinitelyTrue) {
@@ -1602,6 +1631,7 @@
return tryConstant() ?? tryToString() ?? node;
}
+ @override
HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
return handleInterceptedCall(node);
}
@@ -1615,6 +1645,7 @@
});
}
+ @override
HInstruction visitTypeInfoExpression(HTypeInfoExpression node) {
// Identify the case where the type info expression would be of the form:
//
@@ -1673,6 +1704,7 @@
return tryCopyInfo() ?? node;
}
+ @override
HInstruction visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
TypeVariableType variable = node.variable;
ClassEntity contextClass = variable.element.typeDeclaration;
@@ -1810,6 +1842,7 @@
final Set<HInstruction> boundsChecked;
final bool trustPrimitives;
final JClosedWorld closedWorld;
+ @override
final String name = "SsaCheckInserter";
HGraph graph;
@@ -1818,6 +1851,7 @@
AbstractValueDomain get _abstractValueDomain =>
closedWorld.abstractValueDomain;
+ @override
void visitGraph(HGraph graph) {
this.graph = graph;
@@ -1829,6 +1863,7 @@
visitDominatorTree(graph);
}
+ @override
void visitBasicBlock(HBasicBlock block) {
HInstruction instruction = block.first;
while (instruction != null) {
@@ -1866,18 +1901,21 @@
return check;
}
+ @override
void visitIndex(HIndex node) {
if (boundsChecked.contains(node)) return;
HInstruction index = node.index;
index = insertBoundsCheck(node, node.receiver, index);
}
+ @override
void visitIndexAssign(HIndexAssign node) {
if (boundsChecked.contains(node)) return;
HInstruction index = node.index;
index = insertBoundsCheck(node, node.receiver, index);
}
+ @override
void visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
MemberEntity element = node.element;
if (node.isInterceptedCall) return;
@@ -1894,6 +1932,7 @@
}
class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
+ @override
final String name = "SsaDeadCodeEliminator";
final JClosedWorld closedWorld;
@@ -2018,6 +2057,7 @@
return true;
}
+ @override
void visitGraph(HGraph graph) {
_graph = graph;
analyzer = new SsaLiveBlockAnalyzer(graph, closedWorld, optimizer);
@@ -2026,6 +2066,7 @@
cleanPhis();
}
+ @override
void visitBasicBlock(HBasicBlock block) {
bool isDeadBlock = analyzer.isDeadBlock(block);
block.isLive = !isDeadBlock;
@@ -2247,10 +2288,12 @@
}
}
+ @override
void visitControlFlow(HControlFlow instruction) {
instruction.block.successors.forEach(markBlockLive);
}
+ @override
void visitIf(HIf instruction) {
HInstruction condition = instruction.condition;
if (condition.isConstant()) {
@@ -2264,6 +2307,7 @@
}
}
+ @override
void visitSwitch(HSwitch node) {
if (node.expression.isInteger(_abstractValueDomain).isDefinitelyTrue) {
Range switchRange = ranges[node.expression];
@@ -2296,8 +2340,10 @@
}
class SsaDeadPhiEliminator implements OptimizationPhase {
+ @override
final String name = "SsaDeadPhiEliminator";
+ @override
void visitGraph(HGraph graph) {
final List<HPhi> worklist = <HPhi>[];
// A set to keep track of the live phis that we found.
@@ -2353,8 +2399,10 @@
}
class SsaRedundantPhiEliminator implements OptimizationPhase {
+ @override
final String name = "SsaRedundantPhiEliminator";
+ @override
void visitGraph(HGraph graph) {
final List<HPhi> worklist = <HPhi>[];
@@ -2412,6 +2460,7 @@
class SsaGlobalValueNumberer implements OptimizationPhase {
final AbstractValueDomain _abstractValueDomain;
+ @override
final String name = "SsaGlobalValueNumberer";
final Set<int> visited;
@@ -2420,6 +2469,7 @@
SsaGlobalValueNumberer(this._abstractValueDomain) : visited = new Set<int>();
+ @override
void visitGraph(HGraph graph) {
computeChangesFlags(graph);
moveLoopInvariantCode(graph);
@@ -2635,6 +2685,7 @@
class SsaCodeMotion extends HBaseVisitor implements OptimizationPhase {
final AbstractValueDomain _abstractValueDomain;
+ @override
final String name = "SsaCodeMotion";
bool movedCode = false;
@@ -2642,6 +2693,7 @@
SsaCodeMotion(this._abstractValueDomain);
+ @override
void visitGraph(HGraph graph) {
values = new List<ValueSet>(graph.blocks.length);
for (int i = 0; i < graph.blocks.length; i++) {
@@ -2650,6 +2702,7 @@
visitPostDominatorTree(graph);
}
+ @override
void visitBasicBlock(HBasicBlock block) {
List<HBasicBlock> successors = block.successors;
@@ -2739,6 +2792,7 @@
class SsaTypeConversionInserter extends HBaseVisitor
implements OptimizationPhase {
+ @override
final String name = "SsaTypeconversionInserter";
final JClosedWorld closedWorld;
@@ -2747,6 +2801,7 @@
AbstractValueDomain get _abstractValueDomain =>
closedWorld.abstractValueDomain;
+ @override
void visitGraph(HGraph graph) {
visitDominatorTree(graph);
}
@@ -2776,6 +2831,7 @@
dominatedUses.replaceWith(newInput);
}
+ @override
void visitIs(HIs instruction) {
DartType type = instruction.typeExpression;
if (!instruction.isRawCheck) {
@@ -2806,6 +2862,7 @@
// false. Avoid strengthening to `null`.
}
+ @override
void visitIdentity(HIdentity instruction) {
// At HIf(HIdentity(x, null)) strengthens x to non-null on else branch.
HInstruction left = instruction.left;
@@ -2885,6 +2942,7 @@
final Compiler compiler;
final JClosedWorld closedWorld;
final JFieldAnalysis _fieldAnalysis;
+ @override
final String name = "SsaLoadElimination";
MemorySet memorySet;
List<MemorySet> memories;
@@ -2897,6 +2955,7 @@
AbstractValueDomain get _abstractValueDomain =>
closedWorld.abstractValueDomain;
+ @override
void visitGraph(HGraph graph) {
_graph = graph;
memories = new List<MemorySet>(graph.blocks.length);
@@ -2915,6 +2974,7 @@
}
}
+ @override
void visitBasicBlock(HBasicBlock block) {
if (block.predecessors.length == 0) {
// Entry block.
@@ -2957,6 +3017,7 @@
}
}
+ @override
void visitFieldGet(HFieldGet instruction) {
if (instruction.isNullCheck) return;
FieldEntity element = instruction.element;
@@ -2964,6 +3025,7 @@
_visitFieldGet(element, receiver, instruction);
}
+ @override
void visitGetLength(HGetLength instruction) {
HInstruction receiver = instruction.receiver.nonCheck();
HInstruction existing =
@@ -2989,6 +3051,7 @@
}
}
+ @override
void visitFieldSet(HFieldSet instruction) {
FieldEntity element = instruction.element;
HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck();
@@ -2998,6 +3061,7 @@
}
}
+ @override
void visitCreate(HCreate instruction) {
memorySet.registerAllocation(instruction);
if (shouldTrackInitialValues(instruction)) {
@@ -3063,6 +3127,7 @@
return interestingUse(instruction, 0);
}
+ @override
void visitInstruction(HInstruction instruction) {
if (instruction.isAllocation(_abstractValueDomain)) {
memorySet.registerAllocation(instruction);
@@ -3070,6 +3135,7 @@
memorySet.killAffectedBy(instruction);
}
+ @override
void visitLazyStatic(HLazyStatic instruction) {
FieldEntity field = instruction.element;
handleStaticLoad(field, instruction);
@@ -3086,10 +3152,12 @@
}
}
+ @override
void visitStatic(HStatic instruction) {
handleStaticLoad(instruction.element, instruction);
}
+ @override
void visitStaticStore(HStaticStore instruction) {
if (memorySet.registerFieldValueUpdate(
instruction.element, null, instruction.inputs.last)) {
@@ -3097,6 +3165,7 @@
}
}
+ @override
void visitLiteralList(HLiteralList instruction) {
memorySet.registerAllocation(instruction);
memorySet.killAffectedBy(instruction);
@@ -3104,6 +3173,7 @@
// TODO(sra): Set initial length.
}
+ @override
void visitIndex(HIndex instruction) {
HInstruction receiver = instruction.receiver.nonCheck();
HInstruction existing =
@@ -3117,6 +3187,7 @@
}
}
+ @override
void visitIndexAssign(HIndexAssign instruction) {
HInstruction receiver = instruction.receiver.nonCheck();
memorySet.registerKeyedValueUpdate(
@@ -3124,20 +3195,35 @@
}
// Pure operations that do not escape their inputs.
+ @override
void visitBinaryArithmetic(HBinaryArithmetic instruction) {}
+ @override
void visitBoundsCheck(HBoundsCheck instruction) {}
+ @override
void visitConstant(HConstant instruction) {}
+ @override
void visitIf(HIf instruction) {}
+ @override
void visitInterceptor(HInterceptor instruction) {}
+ @override
void visitIs(HIs instruction) {}
+ @override
void visitIsViaInterceptor(HIsViaInterceptor instruction) {}
+ @override
void visitNot(HNot instruction) {}
+ @override
void visitParameterValue(HParameterValue instruction) {}
+ @override
void visitRelational(HRelational instruction) {}
+ @override
void visitStringConcat(HStringConcat instruction) {}
+ @override
void visitTypeKnown(HTypeKnown instruction) {}
+ @override
void visitTypeInfoReadRaw(HTypeInfoReadRaw instruction) {}
+ @override
void visitTypeInfoReadVariable(HTypeInfoReadVariable instruction) {}
+ @override
void visitTypeInfoExpression(HTypeInfoExpression instruction) {}
}
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index 41360b05..cdcc910 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -33,12 +33,14 @@
optimizer = new SsaOptimizerTask(backend),
backend = backend;
+ @override
void onCodegenStart() {
_builder.onCodegenStart();
}
/// Generates JavaScript code for `work.element`.
/// Using the ssa builder, optimizer and code generator.
+ @override
js.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld,
GlobalTypeInferenceResults globalInferenceResults) {
HGraph graph = _builder.build(work, closedWorld, globalInferenceResults);
@@ -62,6 +64,7 @@
return result;
}
+ @override
Iterable<CompilerTask> get tasks {
return <CompilerTask>[_builder, optimizer, generator];
}
@@ -82,6 +85,7 @@
SsaBuilderTask(this._backend, this._sourceInformationFactory)
: super(_backend.compiler.measurer);
+ @override
String get name => 'SSA builder';
void onCodegenStart() {
@@ -123,11 +127,9 @@
/// constant value.
return true;
}
- } else {
- // If the constant-handler was not able to produce a result we have to
- // go through the builder (below) to generate the lazy initializer for
- // the static variable.
- // We also need to register the use of the cyclic-error helper.
+ } else if (fieldData.isLazy) {
+ // The generated initializer needs be wrapped in the cyclic-error
+ // helper.
registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke(
closedWorld.commonElements.cyclicThrowHelper,
CallStructure.ONE_ARG));
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index ee7bc98..40770be 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -18,6 +18,7 @@
class HTracer extends HGraphVisitor with TracerUtil {
final JClosedWorld closedWorld;
final Namer namer;
+ @override
final OutputSink output;
HTracer(this.output, this.closedWorld, this.namer);
@@ -72,6 +73,7 @@
}
}
+ @override
void visitBasicBlock(HBasicBlock block) {
HInstructionStringifier stringifier =
new HInstructionStringifier(block, closedWorld, namer);
@@ -168,10 +170,12 @@
return "$prefix${instruction.id}";
}
+ @override
String visitLateValue(HLateValue node) {
return "LateValue: ${temporaryId(node.inputs[0])}";
}
+ @override
String visitBoolify(HBoolify node) {
return "Boolify: ${temporaryId(node.inputs[0])}";
}
@@ -182,30 +186,38 @@
return '$opcode: $left $right';
}
+ @override
String visitAbs(HAbs node) {
String operand = temporaryId(node.operand);
return "Abs: $operand";
}
+ @override
String visitAdd(HAdd node) => handleInvokeBinary(node, 'Add');
+ @override
String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, 'BitAnd');
+ @override
String visitBitNot(HBitNot node) {
String operand = temporaryId(node.operand);
return "BitNot: $operand";
}
+ @override
String visitBitOr(HBitOr node) => handleInvokeBinary(node, 'BitOr');
+ @override
String visitBitXor(HBitXor node) => handleInvokeBinary(node, 'BitXor');
+ @override
String visitBoundsCheck(HBoundsCheck node) {
String lengthId = temporaryId(node.length);
String indexId = temporaryId(node.index);
return "BoundsCheck: length = $lengthId, index = $indexId";
}
+ @override
String visitBreak(HBreak node) {
HBasicBlock target = currentBlock.successors[0];
if (node.label != null) {
@@ -214,8 +226,10 @@
return "Break: (B${target.id})";
}
+ @override
String visitConstant(HConstant constant) => "Constant: ${constant.constant}";
+ @override
String visitContinue(HContinue node) {
HBasicBlock target = currentBlock.successors[0];
if (node.label != null) {
@@ -224,18 +238,23 @@
return "Continue: (B${target.id})";
}
+ @override
String visitCreate(HCreate node) {
return handleGenericInvoke("Create", "${node.element.name}", node.inputs);
}
+ @override
String visitCreateBox(HCreateBox node) {
return handleGenericInvoke("CreateBox", "", node.inputs);
}
+ @override
String visitDivide(HDivide node) => handleInvokeBinary(node, 'Divide');
+ @override
String visitExit(HExit node) => "Exit";
+ @override
String visitFieldGet(HFieldGet node) {
if (node.isNullCheck) {
return 'FieldGet: NullCheck ${temporaryId(node.receiver)}';
@@ -244,12 +263,14 @@
return 'FieldGet: ${temporaryId(node.receiver)}.$fieldName';
}
+ @override
String visitFieldSet(HFieldSet node) {
String valueId = temporaryId(node.value);
String fieldName = node.element.name;
return 'FieldSet: ${temporaryId(node.receiver)}.$fieldName to $valueId';
}
+ @override
String visitReadModifyWrite(HReadModifyWrite node) {
String fieldName = node.element.name;
String receiverId = temporaryId(node.receiver);
@@ -264,33 +285,41 @@
}
}
+ @override
String visitGetLength(HGetLength node) {
return 'GetLength: ${temporaryId(node.receiver)}';
}
+ @override
String visitLocalGet(HLocalGet node) {
String localName = node.variable.name;
return 'LocalGet: ${temporaryId(node.local)}.$localName';
}
+ @override
String visitLocalSet(HLocalSet node) {
String valueId = temporaryId(node.value);
String localName = node.variable.name;
return 'LocalSet: ${temporaryId(node.local)}.$localName to $valueId';
}
+ @override
String visitGoto(HGoto node) {
HBasicBlock target = currentBlock.successors[0];
return "Goto: (B${target.id})";
}
+ @override
String visitGreater(HGreater node) => handleInvokeBinary(node, 'Greater');
+ @override
String visitGreaterEqual(HGreaterEqual node) {
return handleInvokeBinary(node, 'GreaterEqual');
}
+ @override
String visitIdentity(HIdentity node) => handleInvokeBinary(node, 'Identity');
+ @override
String visitIf(HIf node) {
HBasicBlock thenBlock = currentBlock.successors[0];
HBasicBlock elseBlock = currentBlock.successors[1];
@@ -308,12 +337,14 @@
return "$invokeType: $functionName($argumentsString)";
}
+ @override
String visitIndex(HIndex node) {
String receiver = temporaryId(node.receiver);
String index = temporaryId(node.index);
return "Index: $receiver[$index]";
}
+ @override
String visitIndexAssign(HIndexAssign node) {
String receiver = temporaryId(node.receiver);
String index = temporaryId(node.index);
@@ -321,6 +352,7 @@
return "IndexAssign: $receiver[$index] = $value";
}
+ @override
String visitInterceptor(HInterceptor node) {
String value = temporaryId(node.inputs[0]);
if (node.interceptedClasses != null) {
@@ -330,6 +362,7 @@
return "Interceptor: $value";
}
+ @override
String visitInvokeClosure(HInvokeClosure node) =>
handleInvokeDynamic(node, "InvokeClosure");
@@ -342,33 +375,41 @@
return handleGenericInvoke(kind, target, arguments) + "(${invoke.mask})";
}
+ @override
String visitInvokeDynamicMethod(HInvokeDynamicMethod node) =>
handleInvokeDynamic(node, "InvokeDynamicMethod");
+ @override
String visitInvokeDynamicGetter(HInvokeDynamicGetter node) =>
handleInvokeDynamic(node, "InvokeDynamicGetter");
+ @override
String visitInvokeDynamicSetter(HInvokeDynamicSetter node) =>
handleInvokeDynamic(node, "InvokeDynamicSetter");
+ @override
String visitInvokeStatic(HInvokeStatic invoke) {
String target = invoke.element.name;
return handleGenericInvoke("InvokeStatic", target, invoke.inputs);
}
+ @override
String visitInvokeSuper(HInvokeSuper invoke) {
String target = invoke.element.name;
return handleGenericInvoke("InvokeSuper", target, invoke.inputs);
}
+ @override
String visitInvokeConstructorBody(HInvokeConstructorBody invoke) {
String target = invoke.element.name;
return handleGenericInvoke("InvokeConstructorBody", target, invoke.inputs);
}
+ @override
String visitInvokeGeneratorBody(HInvokeGeneratorBody invoke) {
String target = invoke.element.name;
return handleGenericInvoke("InvokeGeneratorBody", target, invoke.inputs);
}
+ @override
String visitForeignCode(HForeignCode node) {
var template = node.codeTemplate;
String code = '${template.ast}';
@@ -376,10 +417,13 @@
return "ForeignCode: $code ($inputs)";
}
+ @override
String visitLess(HLess node) => handleInvokeBinary(node, 'Less');
+ @override
String visitLessEqual(HLessEqual node) =>
handleInvokeBinary(node, 'LessEqual');
+ @override
String visitLiteralList(HLiteralList node) {
StringBuffer elementsString = new StringBuffer();
for (int i = 0; i < node.inputs.length; i++) {
@@ -389,6 +433,7 @@
return "LiteralList: [$elementsString]";
}
+ @override
String visitLoopBranch(HLoopBranch branch) {
HBasicBlock bodyBlock = currentBlock.successors[0];
HBasicBlock exitBlock = currentBlock.successors[1];
@@ -396,23 +441,29 @@
return "LoopBranch ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})";
}
+ @override
String visitMultiply(HMultiply node) => handleInvokeBinary(node, 'Multiply');
+ @override
String visitNegate(HNegate node) {
String operand = temporaryId(node.operand);
return "Negate: $operand";
}
+ @override
String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}";
+ @override
String visitParameterValue(HParameterValue node) {
return "ParameterValue: ${node.sourceElement.name}";
}
+ @override
String visitLocalValue(HLocalValue node) {
return "LocalValue: ${node.sourceElement.name}";
}
+ @override
String visitPhi(HPhi phi) {
StringBuffer buffer = new StringBuffer();
buffer.write("Phi: ");
@@ -423,42 +474,54 @@
return buffer.toString();
}
+ @override
String visitRef(HRef node) {
return 'Ref: ${temporaryId(node.value)}';
}
+ @override
String visitReturn(HReturn node) => "Return: ${temporaryId(node.inputs[0])}";
+ @override
String visitShiftLeft(HShiftLeft node) =>
handleInvokeBinary(node, 'ShiftLeft');
+ @override
String visitShiftRight(HShiftRight node) =>
handleInvokeBinary(node, 'ShiftRight');
+ @override
String visitStatic(HStatic node) => "Static: ${node.element.name}";
+ @override
String visitLazyStatic(HLazyStatic node) =>
"LazyStatic: ${node.element.name}";
+ @override
String visitOneShotInterceptor(HOneShotInterceptor node) =>
handleInvokeDynamic(node, "OneShotInterceptor");
+ @override
String visitStaticStore(HStaticStore node) {
String lhs = node.element.name;
return "StaticStore: $lhs = ${temporaryId(node.inputs[0])}";
}
+ @override
String visitStringConcat(HStringConcat node) {
var leftId = temporaryId(node.left);
var rightId = temporaryId(node.right);
return "StringConcat: $leftId + $rightId";
}
+ @override
String visitStringify(HStringify node) {
return "Stringify: ${temporaryId(node.inputs[0])}";
}
+ @override
String visitSubtract(HSubtract node) => handleInvokeBinary(node, 'Subtract');
+ @override
String visitSwitch(HSwitch node) {
StringBuffer buf = new StringBuffer();
buf.write("Switch: (");
@@ -475,26 +538,33 @@
return buf.toString();
}
+ @override
String visitThis(HThis node) => "This";
+ @override
String visitThrow(HThrow node) => "Throw: ${temporaryId(node.inputs[0])}";
+ @override
String visitThrowExpression(HThrowExpression node) {
return "ThrowExpression: ${temporaryId(node.inputs[0])}";
}
+ @override
String visitTruncatingDivide(HTruncatingDivide node) {
return handleInvokeBinary(node, 'TruncatingDivide');
}
+ @override
String visitRemainder(HRemainder node) {
return handleInvokeBinary(node, 'Remainder');
}
+ @override
String visitExitTry(HExitTry node) {
return "ExitTry";
}
+ @override
String visitTry(HTry node) {
List<HBasicBlock> successors = currentBlock.successors;
String tryBlock = 'B${successors[0].id}';
@@ -512,16 +582,19 @@
"Join: B${successors.last.id}";
}
+ @override
String visitIs(HIs node) {
String type = node.typeExpression.toString();
return "Is: ${temporaryId(node.expression)} is $type";
}
+ @override
String visitIsViaInterceptor(HIsViaInterceptor node) {
String type = node.typeExpression.toString();
return "IsViaInterceptor: ${temporaryId(node.inputs[0])} is $type";
}
+ @override
String visitTypeConversion(HTypeConversion node) {
String checkedInput = temporaryId(node.checkedInput);
String rest;
@@ -551,6 +624,7 @@
return '?';
}
+ @override
String visitTypeKnown(HTypeKnown node) {
assert(node.inputs.length <= 2);
String result =
@@ -561,30 +635,36 @@
return result;
}
+ @override
String visitRangeConversion(HRangeConversion node) {
return "RangeConversion: ${node.checkedInput}";
}
+ @override
String visitTypeInfoReadRaw(HTypeInfoReadRaw node) {
var inputs = node.inputs.map(temporaryId).join(', ');
return "TypeInfoReadRaw: $inputs";
}
+ @override
String visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
var inputs = node.inputs.map(temporaryId).join(', ');
return "TypeInfoReadVariable: ${node.variable} $inputs";
}
+ @override
String visitTypeInfoExpression(HTypeInfoExpression node) {
var inputs = node.inputs.map(temporaryId).join(', ');
return "TypeInfoExpression: ${node.kindAsString} ${node.dartType}"
" ($inputs)";
}
+ @override
String visitAwait(HAwait node) {
return "Await: ${temporaryId(node.inputs[0])}";
}
+ @override
String visitYield(HYield node) {
return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}";
}
diff --git a/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
index 1efc255..bebc7e6 100644
--- a/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
+++ b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
@@ -10,6 +10,7 @@
return switchCaseBody.accept(new SwitchContinueAnalysis._());
}
+ @override
bool visitContinueSwitchStatement(ir.ContinueSwitchStatement continueStmt) {
// TODO(efortuna): Check what the target of this continue statement actually
// IS, because depending on where the label points if we have a nested
@@ -18,6 +19,7 @@
return true;
}
+ @override
bool visitBlock(ir.Block block) {
for (ir.Statement statement in block.statements) {
if (statement.accept(this)) {
@@ -27,22 +29,27 @@
return false;
}
+ @override
bool visitLabeledStatement(ir.LabeledStatement statement) {
return statement.body.accept(this);
}
+ @override
bool visitDoStatement(ir.DoStatement doStatement) {
return doStatement.body.accept(this);
}
+ @override
bool visitForStatement(ir.ForStatement forStatement) {
return forStatement.body.accept(this);
}
+ @override
bool visitForInStatement(ir.ForInStatement forInStatement) {
return forInStatement.body.accept(this);
}
+ @override
bool visitSwitchStatement(ir.SwitchStatement switchStatement) {
for (var switchCase in switchStatement.cases) {
if (switchCase.accept(this)) {
@@ -52,15 +59,18 @@
return false;
}
+ @override
bool visitSwitchCase(ir.SwitchCase switchCase) {
return switchCase.body.accept(this);
}
+ @override
bool visitIfStatement(ir.IfStatement ifStatement) {
return ifStatement.then.accept(this) ||
(ifStatement.otherwise != null && ifStatement.otherwise.accept(this));
}
+ @override
bool visitTryCatch(ir.TryCatch tryCatch) {
if (tryCatch.body.accept(this)) {
for (var catchStatement in tryCatch.catches) {
@@ -72,26 +82,32 @@
return false;
}
+ @override
bool visitWhileStatement(ir.WhileStatement statement) {
return statement.body.accept(this);
}
+ @override
bool visitCatch(ir.Catch catchStatement) {
return catchStatement.body.accept(this);
}
+ @override
bool visitTryFinally(ir.TryFinally tryFinally) {
return tryFinally.body.accept(this) && tryFinally.finalizer.accept(this);
}
+ @override
bool visitFunctionDeclaration(ir.FunctionDeclaration declaration) {
return declaration.function.accept(this);
}
+ @override
bool visitFunctionNode(ir.FunctionNode node) {
return node.body.accept(this);
}
+ @override
bool defaultStatement(ir.Statement node) {
if (node is ir.ExpressionStatement ||
node is ir.EmptyStatement ||
@@ -106,5 +122,6 @@
'SwitchContinueAnalysis';
}
+ @override
bool defaultNode(ir.Node node) => false;
}
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 0c7b575..e716108 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -41,6 +41,7 @@
final CommonElements commonElements;
final JClosedWorld closedWorld;
final OptimizationTestLog _log;
+ @override
String get name => 'SsaTypePropagator';
SsaTypePropagator(this.results, this.options, this.commonElements,
@@ -66,11 +67,13 @@
return oldType != newType;
}
+ @override
void visitGraph(HGraph graph) {
visitDominatorTree(graph);
processWorklist();
}
+ @override
visitBasicBlock(HBasicBlock block) {
if (block.isLoopHeader()) {
block.forEachPhi((HPhi phi) {
@@ -129,6 +132,7 @@
}
}
+ @override
AbstractValue visitBinaryArithmetic(HBinaryArithmetic instruction) {
HInstruction left = instruction.left;
HInstruction right = instruction.right;
@@ -152,29 +156,35 @@
return visitBinaryArithmetic(instruction);
}
+ @override
AbstractValue visitMultiply(HMultiply instruction) {
return checkPositiveInteger(instruction);
}
+ @override
AbstractValue visitAdd(HAdd instruction) {
return checkPositiveInteger(instruction);
}
+ @override
AbstractValue visitDivide(HDivide instruction) {
// Always double, as initialized.
return instruction.instructionType;
}
+ @override
AbstractValue visitTruncatingDivide(HTruncatingDivide instruction) {
// Always as initialized.
return instruction.instructionType;
}
+ @override
AbstractValue visitRemainder(HRemainder instruction) {
// Always as initialized.
return instruction.instructionType;
}
+ @override
AbstractValue visitNegate(HNegate instruction) {
HInstruction operand = instruction.operand;
// We have integer subclasses that represent ranges, so widen any int
@@ -185,16 +195,19 @@
return instruction.operand.instructionType;
}
+ @override
AbstractValue visitAbs(HAbs instruction) {
// TODO(sra): Can narrow to non-negative type for integers.
return instruction.operand.instructionType;
}
+ @override
AbstractValue visitInstruction(HInstruction instruction) {
assert(instruction.instructionType != null);
return instruction.instructionType;
}
+ @override
AbstractValue visitPhi(HPhi phi) {
AbstractValue candidateType = abstractValueDomain.emptyType;
for (int i = 0, length = phi.inputs.length; i < length; i++) {
@@ -204,6 +217,7 @@
return candidateType;
}
+ @override
AbstractValue visitTypeConversion(HTypeConversion instruction) {
HInstruction input = instruction.checkedInput;
AbstractValue inputType = input.instructionType;
@@ -261,6 +275,7 @@
return outputType;
}
+ @override
AbstractValue visitTypeKnown(HTypeKnown instruction) {
HInstruction input = instruction.checkedInput;
AbstractValue inputType = input.instructionType;
@@ -392,6 +407,7 @@
});
}
+ @override
AbstractValue visitInvokeDynamic(HInvokeDynamic instruction) {
if (instruction.isInterceptedCall) {
// We cannot do the following optimization now, because we have to wait
diff --git a/pkg/compiler/lib/src/ssa/validate.dart b/pkg/compiler/lib/src/ssa/validate.dart
index 1f93b4e..74a852a 100644
--- a/pkg/compiler/lib/src/ssa/validate.dart
+++ b/pkg/compiler/lib/src/ssa/validate.dart
@@ -20,6 +20,7 @@
// Note that during construction of the Ssa graph the basic blocks are
// not required to be valid yet.
+ @override
void visitBasicBlock(HBasicBlock block) {
currentBlock = block;
if (!isValid) return; // Don't need to continue if we are already invalid.
@@ -164,6 +165,7 @@
return true;
}
+ @override
void visitInstruction(HInstruction instruction) {
// Verifies that we are in the use list of our inputs.
bool hasCorrectInputs() {
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index 639c727..a0af6be 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -102,6 +102,7 @@
const MarkerValue(this.positive, info) : super(info);
+ @override
Value operator +(Value other) {
if (other.isPositive && positive) return const MaxIntValue();
if (other.isNegative && !positive) return const MinIntValue();
@@ -109,6 +110,7 @@
return const UnknownValue();
}
+ @override
Value operator -(Value other) {
if (other.isPositive && !positive) return const MinIntValue();
if (other.isNegative && positive) return const MaxIntValue();
@@ -123,6 +125,7 @@
const IntValue(this.value, info) : super(info);
+ @override
Value operator +(dynamic other) {
if (other.isZero) return this;
if (other is! IntValue) return other + this;
@@ -133,6 +136,7 @@
return info.newIntValue(constant.intValue);
}
+ @override
Value operator -(dynamic other) {
if (other.isZero) return this;
if (other is! IntValue) return -other + this;
@@ -143,6 +147,7 @@
return info.newIntValue(constant.intValue);
}
+ @override
Value operator -() {
if (isZero) return this;
dynamic constant =
@@ -151,6 +156,7 @@
return info.newIntValue(constant.intValue);
}
+ @override
Value operator &(dynamic other) {
if (other is! IntValue) return const UnknownValue();
dynamic constant = constant_system.bitAnd.fold(
@@ -159,26 +165,34 @@
return info.newIntValue(constant.intValue);
}
+ @override
Value min(dynamic other) {
if (other is! IntValue) return other.min(this);
return this.value < other.value ? this : other;
}
+ @override
Value max(dynamic other) {
if (other is! IntValue) return other.max(this);
return this.value < other.value ? other : this;
}
+ @override
bool operator ==(other) {
if (other is! IntValue) return false;
return this.value == other.value;
}
+ @override
int get hashCode => throw new UnsupportedError('IntValue.hashCode');
+ @override
String toString() => 'IntValue $value';
+ @override
bool get isNegative => value < BigInt.zero;
+ @override
bool get isPositive => value >= BigInt.zero;
+ @override
bool get isZero => value == BigInt.zero;
}
@@ -186,13 +200,21 @@
/// which is currently +infinity.
class MaxIntValue extends Value {
const MaxIntValue() : super(null);
+ @override
Value operator +(Value other) => this;
+ @override
Value operator -(Value other) => this;
+ @override
Value operator -() => const MinIntValue();
+ @override
Value min(Value other) => other;
+ @override
Value max(Value other) => this;
+ @override
String toString() => 'Max';
+ @override
bool get isNegative => false;
+ @override
bool get isPositive => true;
}
@@ -200,13 +222,21 @@
/// which is currently -infinity.
class MinIntValue extends Value {
const MinIntValue() : super(null);
+ @override
Value operator +(Value other) => this;
+ @override
Value operator -(Value other) => this;
+ @override
Value operator -() => const MaxIntValue();
+ @override
Value min(Value other) => this;
+ @override
Value max(Value other) => other;
+ @override
String toString() => 'Min';
+ @override
bool get isNegative => true;
+ @override
bool get isPositive => false;
}
@@ -214,13 +244,21 @@
/// operation that could not be done because of too much complexity.
class UnknownValue extends Value {
const UnknownValue() : super(null);
+ @override
Value operator +(Value other) => const UnknownValue();
+ @override
Value operator -(Value other) => const UnknownValue();
+ @override
Value operator -() => const UnknownValue();
+ @override
Value min(Value other) => const UnknownValue();
+ @override
Value max(Value other) => const UnknownValue();
+ @override
bool get isNegative => false;
+ @override
bool get isPositive => false;
+ @override
String toString() => 'Unknown';
}
@@ -229,13 +267,16 @@
final HInstruction instruction;
InstructionValue(this.instruction, info) : super(info);
+ @override
bool operator ==(other) {
if (other is! InstructionValue) return false;
return this.instruction == other.instruction;
}
+ @override
int get hashCode => throw new UnsupportedError('InstructionValue.hashCode');
+ @override
Value operator +(Value other) {
if (other.isZero) return this;
if (other is IntValue) {
@@ -250,6 +291,7 @@
return other + this;
}
+ @override
Value operator -(Value other) {
if (other.isZero) return this;
if (this == other) return info.intZero;
@@ -265,19 +307,24 @@
return -other + this;
}
+ @override
Value operator -() {
return info.newNegateValue(this);
}
+ @override
bool get isNegative => false;
+ @override
bool get isPositive => false;
+ @override
String toString() => 'Instruction: $instruction';
}
/// Special value for instructions whose type is a positive integer.
class PositiveValue extends InstructionValue {
PositiveValue(HInstruction instruction, info) : super(instruction, info);
+ @override
bool get isPositive => true;
}
@@ -292,16 +339,20 @@
class AddValue extends BinaryOperationValue {
AddValue(left, right, info) : super(left, right, info);
+ @override
bool operator ==(other) {
if (other is! AddValue) return false;
return (left == other.left && right == other.right) ||
(left == other.right && right == other.left);
}
+ @override
int get hashCode => throw new UnsupportedError('AddValue.hashCode');
+ @override
Value operator -() => -left - right;
+ @override
Value operator +(Value other) {
if (other.isZero) return this;
Value value = left + other;
@@ -317,6 +368,7 @@
return const UnknownValue();
}
+ @override
Value operator -(Value other) {
if (other.isZero) return this;
Value value = left - other;
@@ -332,23 +384,30 @@
return const UnknownValue();
}
+ @override
bool get isNegative => left.isNegative && right.isNegative;
+ @override
bool get isPositive => left.isPositive && right.isPositive;
+ @override
String toString() => '$left + $right';
}
class SubtractValue extends BinaryOperationValue {
SubtractValue(left, right, info) : super(left, right, info);
+ @override
bool operator ==(other) {
if (other is! SubtractValue) return false;
return left == other.left && right == other.right;
}
+ @override
int get hashCode => throw new UnsupportedError('SubtractValue.hashCode');
+ @override
Value operator -() => right - left;
+ @override
Value operator +(Value other) {
if (other.isZero) return this;
Value value = left + other;
@@ -364,6 +423,7 @@
return const UnknownValue();
}
+ @override
Value operator -(Value other) {
if (other.isZero) return this;
Value value = left - other;
@@ -379,8 +439,11 @@
return const UnknownValue();
}
+ @override
bool get isNegative => left.isNegative && right.isPositive;
+ @override
bool get isPositive => left.isPositive && right.isNegative;
+ @override
String toString() => '$left - $right';
}
@@ -388,13 +451,16 @@
final Value value;
NegateValue(this.value, info) : super(info);
+ @override
bool operator ==(other) {
if (other is! NegateValue) return false;
return value == other.value;
}
+ @override
int get hashCode => throw new UnsupportedError('Negate.hashCode');
+ @override
Value operator +(other) {
if (other.isZero) return this;
if (other == value) return info.intZero;
@@ -411,8 +477,10 @@
return other - value;
}
+ @override
Value operator &(Value other) => const UnknownValue();
+ @override
Value operator -(other) {
if (other.isZero) return this;
if (other is IntValue) {
@@ -428,10 +496,14 @@
return -other - value;
}
+ @override
Value operator -() => value;
+ @override
bool get isNegative => value.isPositive;
+ @override
bool get isPositive => value.isNegative;
+ @override
String toString() => '-$value';
}
@@ -523,11 +595,13 @@
}
}
+ @override
bool operator ==(other) {
if (other is! Range) return false;
return other.lower == lower && other.upper == upper;
}
+ @override
int get hashCode => throw new UnsupportedError('Range.hashCode');
bool operator <(Range other) {
@@ -550,6 +624,7 @@
bool get isPositive => lower.isPositive;
bool get isSingleValue => lower == upper;
+ @override
String toString() => '[$lower, $upper]';
}
@@ -558,6 +633,7 @@
/// removes unnecessary bounds checks, and comparisons that are proven
/// to be true or false.
class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase {
+ @override
String get name => 'SSA value range builder';
/// List of [HRangeConversion] instructions created by the phase. We
@@ -578,6 +654,7 @@
: info = new ValueRangeInfo(),
this.closedWorld = closedWorld;
+ @override
void visitGraph(HGraph graph) {
this.graph = graph;
visitDominatorTree(graph);
@@ -596,6 +673,7 @@
});
}
+ @override
void visitBasicBlock(HBasicBlock block) {
void visit(HInstruction instruction) {
Range range = instruction.accept(this);
@@ -611,6 +689,7 @@
block.forEachInstruction(visit);
}
+ @override
Range visitInstruction(HInstruction instruction) {
if (instruction
.isPositiveInteger(closedWorld.abstractValueDomain)
@@ -627,6 +706,7 @@
}
}
+ @override
Range visitPhi(HPhi phi) {
if (phi.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse)
return info.newUnboundRange();
@@ -652,6 +732,7 @@
return range;
}
+ @override
Range visitConstant(HConstant hConstant) {
if (hConstant
.isInteger(closedWorld.abstractValueDomain)
@@ -679,10 +760,12 @@
return info.newNormalizedRange(value, value);
}
+ @override
Range visitFieldGet(HFieldGet fieldGet) {
return visitInstruction(fieldGet);
}
+ @override
Range visitGetLength(HGetLength node) {
PositiveValue value = info.newPositiveValue(node);
// We know this range is above zero. To simplify the analysis, we
@@ -692,6 +775,7 @@
return info.newNormalizedRange(info.intZero, value);
}
+ @override
Range visitBoundsCheck(HBoundsCheck check) {
// Save the next instruction, in case the check gets removed.
HInstruction next = check.next;
@@ -761,6 +845,7 @@
return newIndexRange;
}
+ @override
Range visitRelational(HRelational relational) {
HInstruction right = relational.right;
HInstruction left = relational.left;
@@ -828,6 +913,7 @@
return info.newUnboundRange();
}
+ @override
Range visitRemainder(HRemainder instruction) {
HInstruction left = instruction.inputs[0];
HInstruction right = instruction.inputs[1];
@@ -862,6 +948,7 @@
return info.newUnboundRange();
}
+ @override
Range visitInvokeDynamicMethod(HInvokeDynamicMethod invoke) {
if ((invoke.inputs.length == 3) && (invoke.selector.name == "%"))
return handleInvokeModulo(invoke);
@@ -879,14 +966,17 @@
.apply(ranges[instruction.left], ranges[instruction.right]);
}
+ @override
Range visitAdd(HAdd add) {
return handleBinaryOperation(add);
}
+ @override
Range visitSubtract(HSubtract sub) {
return handleBinaryOperation(sub);
}
+ @override
Range visitBitAnd(HBitAnd node) {
if (node.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
return info.newUnboundRange();
@@ -918,6 +1008,7 @@
return info.newUnboundRange();
}
+ @override
Range visitCheck(HCheck instruction) {
if (ranges[instruction.checkedInput] == null) {
return visitInstruction(instruction);
@@ -986,6 +1077,7 @@
return range.intersection(leftRange);
}
+ @override
Range visitConditionalBranch(HConditionalBranch branch) {
dynamic condition = branch.condition;
// TODO(ngeoffray): Handle complex conditions.
@@ -1051,6 +1143,7 @@
return info.newUnboundRange();
}
+ @override
Range visitRangeConversion(HRangeConversion conversion) {
return ranges[conversion];
}
@@ -1095,6 +1188,7 @@
return instruction.accept(this);
}
+ @override
Range visitPhi(HPhi phi) {
// If the update of a loop phi involves another loop phi, we give
// up.
@@ -1112,14 +1206,17 @@
return phiRange;
}
+ @override
Range visitCheck(HCheck instruction) {
return visit(instruction.checkedInput);
}
+ @override
Range visitAdd(HAdd operation) {
return handleBinaryOperation(operation);
}
+ @override
Range visitSubtract(HSubtract operation) {
return handleBinaryOperation(operation);
}
diff --git a/pkg/compiler/lib/src/ssa/value_set.dart b/pkg/compiler/lib/src/ssa/value_set.dart
index 89dbeca..b24a560 100644
--- a/pkg/compiler/lib/src/ssa/value_set.dart
+++ b/pkg/compiler/lib/src/ssa/value_set.dart
@@ -152,6 +152,7 @@
class ValueSetNode {
final HInstruction value;
final int hash;
+ @override
int get hashCode => hash;
ValueSetNode next;
ValueSetNode(this.value, this.hash, this.next);
diff --git a/pkg/compiler/lib/src/ssa/variable_allocator.dart b/pkg/compiler/lib/src/ssa/variable_allocator.dart
index aca7c88..a9f6e39 100644
--- a/pkg/compiler/lib/src/ssa/variable_allocator.dart
+++ b/pkg/compiler/lib/src/ssa/variable_allocator.dart
@@ -16,6 +16,7 @@
assert(start <= end);
}
+ @override
String toString() => '[$start $end[';
}
@@ -56,6 +57,7 @@
return false;
}
+ @override
String toString() {
List<String> res = new List<String>();
for (final interval in ranges) res.add(interval.toString());
@@ -148,6 +150,7 @@
bool get isEmpty => liveInstructions.isEmpty && loopMarkers.isEmpty;
bool contains(HInstruction instruction) =>
liveInstructions.containsKey(instruction);
+ @override
String toString() => liveInstructions.toString();
}
@@ -174,6 +177,7 @@
: liveInstructions = new Map<HBasicBlock, LiveEnvironment>(),
liveIntervals = new Map<HInstruction, LiveInterval>();
+ @override
void visitGraph(HGraph graph) {
visitPostDominatorTree(graph);
if (!liveInstructions[graph.entry].isEmpty) {
@@ -251,6 +255,7 @@
}
}
+ @override
void visitBasicBlock(HBasicBlock block) {
LiveEnvironment environment =
new LiveEnvironment(liveIntervals, instructionId);
@@ -356,6 +361,7 @@
Copy(this.source, this.destination);
+ @override
String toString() => '$destination <- $source';
}
@@ -381,6 +387,7 @@
assignments.add(new Copy<HInstruction>(source, destination));
}
+ @override
String toString() => 'Copies: $copies, assignments: $assignments';
bool get isEmpty => copies.isEmpty && assignments.isEmpty;
@@ -574,10 +581,12 @@
this.generateAtUseSite)
: this.names = new VariableNames();
+ @override
void visitGraph(HGraph graph) {
visitDominatorTree(graph);
}
+ @override
void visitBasicBlock(HBasicBlock block) {
VariableNamer variableNamer =
new VariableNamer(liveInstructions[block], names, _namer);
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index f4e7870..2c687bf 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -26,6 +26,7 @@
final JClosedWorld closedWorld;
final Namer namer;
bool traceActive = false;
+ @override
final api.OutputSink output;
final RegExp traceFilter;
diff --git a/pkg/compiler/lib/src/universe/call_structure.dart b/pkg/compiler/lib/src/universe/call_structure.dart
index d40a26e..8c148c8 100644
--- a/pkg/compiler/lib/src/universe/call_structure.dart
+++ b/pkg/compiler/lib/src/universe/call_structure.dart
@@ -109,6 +109,7 @@
return sb.toString();
}
+ @override
String toString() => 'CallStructure(${structureToString()})';
Selector get callSelector => new Selector.call(Names.call, this);
@@ -122,6 +123,7 @@
}
// TODO(johnniwinther): Cache hash code?
+ @override
int get hashCode {
return Hashing.listHash(
namedArguments,
@@ -129,6 +131,7 @@
Hashing.objectHash(typeArgumentCount, namedArguments.length)));
}
+ @override
bool operator ==(other) {
if (other is! CallStructure) return false;
return match(other);
@@ -184,6 +187,7 @@
///
class NamedCallStructure extends CallStructure {
+ @override
final List<String> namedArguments;
final List<String> _orderedNamedArguments = <String>[];
diff --git a/pkg/compiler/lib/src/universe/class_hierarchy.dart b/pkg/compiler/lib/src/universe/class_hierarchy.dart
index e5707ad..940d180 100644
--- a/pkg/compiler/lib/src/universe/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/universe/class_hierarchy.dart
@@ -184,6 +184,7 @@
commonElements, classHierarchyNodes, classSets);
}
+ @override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeInt(_classSets.length);
@@ -231,6 +232,7 @@
/// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
/// instance of [y].
+ @override
bool isSubtypeOf(ClassEntity x, ClassEntity y) {
ClassSet classSet = _classSets[y];
assert(
@@ -246,12 +248,14 @@
}
/// Return `true` if [x] is a (non-strict) subclass of [y].
+ @override
bool isSubclassOf(ClassEntity x, ClassEntity y) {
return _classHierarchyNodes[y].hasSubclass(_classHierarchyNodes[x]);
}
/// Returns an iterable over the directly instantiated classes that extend
/// [cls] possibly including [cls] itself, if it is live.
+ @override
Iterable<ClassEntity> subclassesOf(ClassEntity cls) {
ClassHierarchyNode hierarchy = _classHierarchyNodes[cls];
if (hierarchy == null) return const <ClassEntity>[];
@@ -261,6 +265,7 @@
/// Returns an iterable over the directly instantiated classes that extend
/// [cls] _not_ including [cls] itself.
+ @override
Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls) {
ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
if (subclasses == null) return const <ClassEntity>[];
@@ -271,6 +276,7 @@
/// Returns the number of live classes that extend [cls] _not_
/// including [cls] itself.
+ @override
int strictSubclassCount(ClassEntity cls) {
ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
if (subclasses == null) return 0;
@@ -279,6 +285,7 @@
/// Applies [f] to each live class that extend [cls] _not_ including [cls]
/// itself.
+ @override
void forEachStrictSubclassOf(
ClassEntity cls, IterationStep f(ClassEntity cls)) {
ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
@@ -289,6 +296,7 @@
/// Returns `true` if [predicate] applies to any live class that extend [cls]
/// _not_ including [cls] itself.
+ @override
bool anyStrictSubclassOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
if (subclasses == null) return false;
@@ -299,6 +307,7 @@
/// Returns an iterable over the directly instantiated that implement [cls]
/// possibly including [cls] itself, if it is live.
+ @override
Iterable<ClassEntity> subtypesOf(ClassEntity cls) {
ClassSet classSet = _classSets[cls];
if (classSet == null) {
@@ -311,6 +320,7 @@
/// Returns an iterable over the directly instantiated that implement [cls]
/// _not_ including [cls].
+ @override
Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls) {
ClassSet classSet = _classSets[cls];
if (classSet == null) {
@@ -323,6 +333,7 @@
/// Returns the number of live classes that implement [cls] _not_
/// including [cls] itself.
+ @override
int strictSubtypeCount(ClassEntity cls) {
ClassSet classSet = _classSets[cls];
if (classSet == null) return 0;
@@ -331,6 +342,7 @@
/// Applies [f] to each live class that implements [cls] _not_ including [cls]
/// itself.
+ @override
void forEachStrictSubtypeOf(
ClassEntity cls, IterationStep f(ClassEntity cls)) {
ClassSet classSet = _classSets[cls];
@@ -341,6 +353,7 @@
/// Returns `true` if [predicate] applies to any live class that extend [cls]
/// _not_ including [cls] itself.
+ @override
bool anyStrictSubtypeOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
ClassSet classSet = _classSets[cls];
if (classSet == null) return false;
@@ -350,6 +363,7 @@
}
/// Returns `true` if [a] and [b] have any known common subtypes.
+ @override
bool haveAnyCommonSubtypes(ClassEntity a, ClassEntity b) {
ClassSet classSetA = _classSets[a];
ClassSet classSetB = _classSets[b];
@@ -366,6 +380,7 @@
/// Returns `true` if any directly instantiated class other than [cls] extends
/// [cls].
+ @override
bool hasAnyStrictSubclass(ClassEntity cls) {
ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
if (subclasses == null) return false;
@@ -374,12 +389,14 @@
/// Returns `true` if any directly instantiated class other than [cls]
/// implements [cls].
+ @override
bool hasAnyStrictSubtype(ClassEntity cls) {
return strictSubtypeCount(cls) > 0;
}
/// Returns `true` if all directly instantiated classes that implement [cls]
/// extend it.
+ @override
bool hasOnlySubclasses(ClassEntity cls) {
// TODO(johnniwinther): move this to ClassSet?
if (cls == _commonElements.objectClass) return true;
@@ -391,6 +408,7 @@
return classSet.hasOnlyInstantiatedSubclasses;
}
+ @override
SubclassResult commonSubclasses(ClassEntity cls1, ClassQuery query1,
ClassEntity cls2, ClassQuery query2) {
if (query1 == ClassQuery.EXACT && query2 == ClassQuery.EXACT) {
@@ -541,6 +559,7 @@
///
/// This method is only provided for testing. For queries on classes, use the
/// methods defined in [JClosedWorld].
+ @override
ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) {
return _classHierarchyNodes[cls];
}
@@ -550,6 +569,7 @@
///
/// This method is only provided for testing. For queries on classes, use the
/// methods defined in [JClosedWorld].
+ @override
ClassSet getClassSet(ClassEntity cls) {
return _classSets[cls];
}
@@ -1004,5 +1024,6 @@
static const SubclassResult SUBTYPE2 =
const SubclassResult.internal(SubclassResultKind.SUBTYPE2);
+ @override
String toString() => 'SubclassResult($kind,classes=$classes)';
}
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index fa29bf7..a2eaee0 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -448,6 +448,7 @@
return sb.toString();
}
+ @override
String toString() => cls.toString();
}
@@ -841,6 +842,7 @@
return null;
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('[\n');
@@ -1040,6 +1042,7 @@
/// Singleton map implemented as a field on the key.
class ClassHierarchyNodesMap extends MapBase<ClassEntity, ClassHierarchyNode> {
+ @override
ClassHierarchyNode operator [](Object cls) {
// TODO(sra): Change the key type to `covariant ClassHierarchyNodesMapKey`.
if (cls is ClassHierarchyNodesMapKey) {
@@ -1048,6 +1051,7 @@
throw new UnimplementedError('ClassHierarchyNodesMap for $cls');
}
+ @override
operator []=(Object cls, ClassHierarchyNode node) {
// TODO(sra): Change the key type to `covariant ClassHierarchyNodesMapKey`.
if (cls is ClassHierarchyNodesMapKey) {
@@ -1057,19 +1061,23 @@
throw new UnimplementedError('ClassHierarchyNodesMap for $cls');
}
+ @override
ClassHierarchyNode putIfAbsent(
ClassEntity cls, ClassHierarchyNode ifAbsent()) {
return this[cls] ??= ifAbsent();
}
+ @override
Iterable<ClassEntity> get keys {
throw new UnimplementedError('ClassHierarchyNodesMap.keys');
}
+ @override
ClassHierarchyNode remove(Object key) {
throw new UnimplementedError('ClassHierarchyNodesMap.remove');
}
+ @override
void clear() {
throw new UnimplementedError('ClassHierarchyNodesMap.clear');
}
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 4bf8ac1..4ece571 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -90,6 +90,7 @@
Iterable<FieldEntity> get allReferencedStaticFields;
/// Set of methods in instantiated classes that are potentially closurized.
+ @override
Iterable<FunctionEntity> get closurizedMembers;
/// Register [constant] as needed for emission.
@@ -136,13 +137,16 @@
/// The set of all referenced static fields.
///
/// Invariant: Elements are declaration elements.
+ @override
final Set<FieldEntity> allReferencedStaticFields = new Set<FieldEntity>();
/// Documentation wanted -- johnniwinther
///
/// Invariant: Elements are declaration elements.
+ @override
final Set<FunctionEntity> staticFunctionsNeedingGetter =
new Set<FunctionEntity>();
+ @override
final Set<FunctionEntity> methodsNeedingSuperGetter =
new Set<FunctionEntity>();
final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
@@ -181,6 +185,7 @@
final Map<String, Set<MemberUsage>> _instanceFunctionsByName =
<String, Set<MemberUsage>>{};
+ @override
final Set<DartType> isChecks = new Set<DartType>();
final SelectorConstraintsStrategy selectorConstraintsStrategy;
@@ -201,6 +206,7 @@
GlobalLocalsMap get _globalLocalsMap => _world.globalLocalsMap;
+ @override
Iterable<ClassEntity> get instantiatedClasses => _processedClasses.keys
.where((cls) => _processedClasses[cls].isInstantiated);
@@ -208,6 +214,7 @@
/// constructor that has been called directly and not only through a
/// super-call.
// TODO(johnniwinther): Improve semantic precision.
+ @override
Iterable<ClassEntity> get directlyInstantiatedClasses {
return _directlyInstantiatedClasses;
}
@@ -217,6 +224,7 @@
///
/// See [directlyInstantiatedClasses].
// TODO(johnniwinther): Improve semantic precision.
+ @override
Iterable<InterfaceType> get instantiatedTypes => _instantiatedTypes;
/// Register [type] as (directly) instantiated.
@@ -270,11 +278,13 @@
return _hasMatchingSelector(_invokedNames[member.name], member, _world);
}
+ @override
bool hasInvokedGetter(MemberEntity member) {
return _hasMatchingSelector(_invokedGetters[member.name], member, _world) ||
member.isFunction && methodsNeedingSuperGetter.contains(member);
}
+ @override
bool hasInvokedSetter(MemberEntity member) {
return _hasMatchingSelector(_invokedSetters[member.name], member, _world);
}
@@ -347,28 +357,34 @@
return new UnmodifiableMapView(map);
}
+ @override
Map<Selector, SelectorConstraints> invocationsByName(String name) {
return _asUnmodifiable(_invokedNames[name]);
}
+ @override
Map<Selector, SelectorConstraints> getterInvocationsByName(String name) {
return _asUnmodifiable(_invokedGetters[name]);
}
+ @override
Map<Selector, SelectorConstraints> setterInvocationsByName(String name) {
return _asUnmodifiable(_invokedSetters[name]);
}
+ @override
void forEachInvokedName(
f(String name, Map<Selector, SelectorConstraints> selectors)) {
_invokedNames.forEach(f);
}
+ @override
void forEachInvokedGetter(
f(String name, Map<Selector, SelectorConstraints> selectors)) {
_invokedGetters.forEach(f);
}
+ @override
void forEachInvokedSetter(
f(String name, Map<Selector, SelectorConstraints> selectors)) {
_invokedSetters.forEach(f);
@@ -723,11 +739,13 @@
_constTypeLiterals.add(type);
}
+ @override
Iterable<DartType> get constTypeLiterals => _constTypeLiterals;
void registerTypeArgument(DartType type) {
_liveTypeArguments.add(type);
}
+ @override
Iterable<DartType> get liveTypeArguments => _liveTypeArguments;
}
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index f0c29bc..484ce10 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -103,12 +103,14 @@
MapLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false});
+ @override
int get hashCode {
return type.hashCode * 13 +
isConstant.hashCode * 17 +
isEmpty.hashCode * 19;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! MapLiteralUse) return false;
@@ -117,6 +119,7 @@
isEmpty == other.isEmpty;
}
+ @override
String toString() {
return 'MapLiteralUse($type,isConstant:$isConstant,isEmpty:$isEmpty)';
}
@@ -130,9 +133,11 @@
SetLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false});
+ @override
int get hashCode =>
type.hashCode * 13 + isConstant.hashCode * 17 + isEmpty.hashCode * 19;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! SetLiteralUse) return false;
@@ -141,6 +146,7 @@
isEmpty == other.isEmpty;
}
+ @override
String toString() =>
'SetLiteralUse($type,isConstant:$isConstant,isEmpty:$isEmpty)';
}
@@ -153,12 +159,14 @@
ListLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false});
+ @override
int get hashCode {
return type.hashCode * 13 +
isConstant.hashCode * 17 +
isEmpty.hashCode * 19;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! ListLiteralUse) return false;
@@ -167,6 +175,7 @@
isEmpty == other.isEmpty;
}
+ @override
String toString() {
return 'ListLiteralUse($type,isConstant:$isConstant,isEmpty:$isEmpty)';
}
@@ -185,11 +194,13 @@
RuntimeTypeUse(this.kind, this.receiverType, this.argumentType);
+ @override
int get hashCode =>
kind.hashCode * 13 +
receiverType.hashCode * 17 +
argumentType.hashCode * 19;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! RuntimeTypeUse) return false;
@@ -220,6 +231,7 @@
return sb.toString();
}
+ @override
String toString() => 'RuntimeTypeUse(kind=$kind,receiver=$receiverType'
',argument=$argumentType)';
}
@@ -238,9 +250,11 @@
/// Short textual representation use for testing.
String get shortText => '<${typeArguments.join(',')}>';
+ @override
int get hashCode =>
Hashing.listHash(typeArguments, Hashing.objectHash(functionType));
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! GenericInstantiation) return false;
@@ -248,6 +262,7 @@
equalElements(typeArguments, other.typeArguments);
}
+ @override
String toString() {
return 'GenericInstantiation(functionType:$functionType,'
'typeArguments:$typeArguments)';
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index e8edd4b..d12781c 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -96,6 +96,7 @@
class SelectorMask {
final Selector selector;
final AbstractValue receiver;
+ @override
final int hashCode;
SelectorMask(this.selector, this.receiver)
@@ -119,11 +120,13 @@
.isPotentiallyTrue;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
return selector == other.selector && receiver == other.receiver;
}
+ @override
String toString() => '($selector,$receiver)';
}
@@ -238,6 +241,7 @@
return result;
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('FunctionSetNode(');
@@ -273,6 +277,7 @@
@override
Iterable<MemberEntity> get functions => const <MemberEntity>[];
+ @override
String toString() => '<empty>';
}
@@ -289,5 +294,6 @@
return _receiver ??= domain.computeReceiver(functions);
}
+ @override
String toString() => '$_receiver:$functions';
}
diff --git a/pkg/compiler/lib/src/universe/member_usage.dart b/pkg/compiler/lib/src/universe/member_usage.dart
index b0898df..50fc2dc 100644
--- a/pkg/compiler/lib/src/universe/member_usage.dart
+++ b/pkg/compiler/lib/src/universe/member_usage.dart
@@ -140,20 +140,26 @@
@override
EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
+ @override
int get hashCode => entity.hashCode;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! MemberUsage) return false;
return entity == other.entity;
}
+ @override
String toString() => '$entity:${appliedUse.iterable(MemberUse.values)}';
}
class FieldUsage extends MemberUsage {
+ @override
bool hasInit = false;
+ @override
bool hasRead = false;
+ @override
bool hasWrite = false;
FieldUsage(FieldEntity field, {bool isNative: false})
@@ -221,12 +227,15 @@
return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
}
+ @override
String toString() => 'FieldUsage($entity,hasInit=$hasInit,hasRead=$hasRead,'
'hasWrite=$hasWrite,pendingUse=${_pendingUse.iterable(MemberUse.values)}';
}
class FinalFieldUsage extends MemberUsage {
+ @override
bool hasInit = false;
+ @override
bool hasRead = false;
FinalFieldUsage(FieldEntity field, {bool isNative: false})
@@ -280,12 +289,15 @@
return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
}
+ @override
String toString() => 'FinalFieldUsage($entity,hasInit=$hasInit,'
'hasRead=$hasRead,pendingUse=${_pendingUse.iterable(MemberUse.values)}';
}
class FunctionUsage extends MemberUsage {
+ @override
bool hasInvoke = false;
+ @override
bool hasRead = false;
FunctionUsage(FunctionEntity function) : super.internal(function) {
@@ -297,11 +309,14 @@
}
}
+ @override
FunctionEntity get entity => super.entity;
+ @override
EnumSet<MemberUse> get _originalUse =>
entity.isInstanceMember ? MemberUses.ALL_INSTANCE : MemberUses.ALL_STATIC;
+ @override
bool get hasPendingClosurizationUse => entity.isInstanceMember
? _pendingUse.contains(MemberUse.CLOSURIZE_INSTANCE)
: _pendingUse.contains(MemberUse.CLOSURIZE_STATIC);
@@ -349,6 +364,7 @@
}
class ParameterTrackingFunctionUsage extends MemberUsage {
+ @override
bool hasRead = false;
final ParameterUsage _parameterUsage;
@@ -364,12 +380,15 @@
}
}
+ @override
bool get hasInvoke => _parameterUsage.hasInvoke;
+ @override
bool get hasPendingClosurizationUse => entity.isInstanceMember
? _pendingUse.contains(MemberUse.CLOSURIZE_INSTANCE)
: _pendingUse.contains(MemberUse.CLOSURIZE_STATIC);
+ @override
EnumSet<MemberUse> get _originalUse =>
entity.isInstanceMember ? MemberUses.ALL_INSTANCE : MemberUses.ALL_STATIC;
@@ -420,6 +439,7 @@
@override
bool get hasPendingNormalUse => !isFullyInvoked;
+ @override
bool get isFullyInvoked => _parameterUsage.isFullyUsed;
@override
@@ -430,6 +450,7 @@
}
class GetterUsage extends MemberUsage {
+ @override
bool hasRead = false;
GetterUsage(FunctionEntity getter) : super.internal(getter);
@@ -454,6 +475,7 @@
}
class SetterUsage extends MemberUsage {
+ @override
bool hasWrite = false;
SetterUsage(FunctionEntity setter) : super.internal(setter);
@@ -475,12 +497,15 @@
}
class ConstructorUsage extends MemberUsage {
+ @override
bool hasInvoke = false;
ConstructorUsage(ConstructorEntity constructor) : super.internal(constructor);
+ @override
ConstructorEntity get entity => super.entity;
+ @override
EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
@override
@@ -512,8 +537,10 @@
: _parameterUsage = new ParameterUsage(constructor.parameterStructure),
super.internal(constructor);
+ @override
ConstructorEntity get entity => super.entity;
+ @override
EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
@override
@@ -548,6 +575,7 @@
@override
bool get hasPendingNormalUse => !isFullyInvoked;
+ @override
bool get isFullyInvoked => _parameterUsage.isFullyUsed;
@override
@@ -620,6 +648,7 @@
@override
EnumSet<ClassUse> get _originalUse => ClassUses.ALL;
+ @override
String toString() => '$cls:${appliedUse.iterable(ClassUse.values)}';
}
@@ -641,6 +670,7 @@
// TODO(johnniwinther): Merge this with [MemberUsage].
abstract class StaticMemberUsage extends AbstractUsage<MemberUse>
implements MemberUsage {
+ @override
final MemberEntity entity;
bool hasNormalUse = false;
@@ -658,14 +688,19 @@
EnumSet<MemberUse> tearOff();
+ @override
EnumSet<MemberUse> init() => normalUse();
+ @override
EnumSet<MemberUse> read() => tearOff();
+ @override
EnumSet<MemberUse> write() => normalUse();
+ @override
EnumSet<MemberUse> invoke(CallStructure callStructure) => normalUse();
+ @override
EnumSet<MemberUse> fullyUse() => normalUse();
@override
@@ -677,12 +712,14 @@
@override
EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
+ @override
String toString() => '$entity:${appliedUse.iterable(MemberUse.values)}';
}
class GeneralStaticMemberUsage extends StaticMemberUsage {
GeneralStaticMemberUsage(MemberEntity entity) : super.internal(entity);
+ @override
EnumSet<MemberUse> tearOff() => normalUse();
@override
@@ -708,15 +745,18 @@
}
class StaticFunctionUsage extends StaticMemberUsage {
+ @override
bool hasClosurization = false;
StaticFunctionUsage(FunctionEntity entity) : super.internal(entity);
+ @override
FunctionEntity get entity => super.entity;
@override
bool get hasInit => true;
+ @override
EnumSet<MemberUse> tearOff() {
if (hasClosurization) {
return MemberUses.NONE;
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 9835da3..0111c4d 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -144,11 +144,13 @@
Instance(this.type, this.kind, {this.isRedirection: false});
+ @override
int get hashCode {
return Hashing.objectHash(
type, Hashing.objectHash(kind, Hashing.objectHash(isRedirection)));
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! Instance) return false;
@@ -157,6 +159,7 @@
isRedirection == other.isRedirection;
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write(type);
@@ -270,6 +273,7 @@
/// `true` if the class is abstractly instantiated.
bool isAbstractlyInstantiated = false;
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('InstantiationInfo[');
@@ -366,11 +370,14 @@
<String, Set<MemberUsage>>{};
/// Fields set.
+ @override
final Set<FieldEntity> fieldSetters = new Set<FieldEntity>();
+ @override
final Set<DartType> isChecks = new Set<DartType>();
/// Set of all closures in the program. Used by the mirror tracking system
/// to find all live closure instances.
+ @override
final Set<Local> localFunctions = new Set<Local>();
/// Set of live local functions (closures) whose signatures reference type
@@ -378,12 +385,14 @@
///
/// A local function is considered live if the enclosing member function is
/// live.
+ @override
final Set<Local> localFunctionsWithFreeTypeVariables = new Set<Local>();
/// Set of live closurized members whose signatures reference type variables.
///
/// A closurized method is considered live if the enclosing class has been
/// instantiated.
+ @override
final Set<FunctionEntity> closurizedMembersWithFreeTypeVariables =
new Set<FunctionEntity>();
@@ -415,6 +424,7 @@
final Set<ConstantValue> _constantValues = new Set<ConstantValue>();
+ @override
final Set<Local> genericLocalFunctions = new Set<Local>();
Set<MemberEntity> _processedMembers = new Set<MemberEntity>();
@@ -442,16 +452,20 @@
this._classHierarchyBuilder,
this._classQueries);
+ @override
Iterable<ClassEntity> get processedClasses => _processedClasses.keys
.where((cls) => _processedClasses[cls].isInstantiated);
+ @override
bool isMemberProcessed(MemberEntity member) =>
_processedMembers.contains(member);
+ @override
void registerProcessedMember(MemberEntity member) {
_processedMembers.add(member);
}
+ @override
Iterable<FunctionEntity> get genericInstanceMethods {
List<FunctionEntity> functions = <FunctionEntity>[];
for (MemberEntity member in processedMembers) {
@@ -464,6 +478,7 @@
return functions;
}
+ @override
Iterable<FunctionEntity> get userNoSuchMethods {
List<FunctionEntity> functions = <FunctionEntity>[];
for (MemberEntity member in processedMembers) {
@@ -477,8 +492,10 @@
return functions;
}
+ @override
Iterable<MemberEntity> get processedMembers => _processedMembers;
+ @override
KClosedWorld get closedWorldForTesting {
if (!_closed) {
failedAt(
@@ -491,6 +508,7 @@
/// constructor that has been called directly and not only through a
/// super-call.
// TODO(johnniwinther): Improve semantic precision.
+ @override
Iterable<ClassEntity> get directlyInstantiatedClasses {
Set<ClassEntity> classes = new Set<ClassEntity>();
getInstantiationMap().forEach((ClassEntity cls, InstantiationInfo info) {
@@ -506,6 +524,7 @@
///
/// See [directlyInstantiatedClasses].
// TODO(johnniwinther): Improve semantic precision.
+ @override
Iterable<InterfaceType> get instantiatedTypes {
Set<InterfaceType> types = new Set<InterfaceType>();
getInstantiationMap().forEach((_, InstantiationInfo info) {
@@ -520,10 +539,12 @@
return types;
}
+ @override
bool isImplemented(ClassEntity cls) {
return _implementedClasses.contains(cls);
}
+ @override
void registerClosurizedMember(MemberEntity element) {
closurizedMembers.add(element);
FunctionType type = _elementEnvironment.getFunctionType(element);
@@ -538,6 +559,7 @@
// TODO(johnniwinther): Fully enforce the separation between exact, through
// subclass and through subtype instantiated types/classes.
// TODO(johnniwinther): Support unknown type arguments for generic types.
+ @override
void registerTypeInstantiation(
InterfaceType type, ClassUsedCallback classUsed,
{ConstructorEntity constructor, bool isRedirection: false}) {
@@ -628,10 +650,12 @@
member.isFunction && methodsNeedingSuperGetter.contains(member);
}
+ @override
bool hasInvokedSetter(MemberEntity member) {
return _hasMatchingSelector(_invokedSetters[member.name], member);
}
+ @override
void registerDynamicUse(
DynamicUse dynamicUse, MemberUsedCallback memberUsed) {
Selector selector = dynamicUse.selector;
@@ -696,14 +720,17 @@
return constraints.addReceiverConstraint(constraint);
}
+ @override
void registerIsCheck(covariant DartType type) {
isChecks.add(type);
}
+ @override
bool registerConstantUse(ConstantUse use) {
return _constantValues.add(use.value);
}
+ @override
void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
if (staticUse.kind == StaticUseKind.CLOSURE) {
Local localFunction = staticUse.element;
@@ -828,6 +855,7 @@
/// Computes usage for all members declared by [cls]. Calls [membersUsed] with
/// the usage changes for each member.
+ @override
void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed) {
_elementEnvironment.forEachClassMember(cls,
(ClassEntity cls, MemberEntity member) {
@@ -946,11 +974,13 @@
}
/// Returns an iterable over all mixin applications that mixin [cls].
+ @override
Iterable<ClassEntity> allMixinUsesOf(ClassEntity cls) {
Iterable<ClassEntity> uses = _classHierarchyBuilder.mixinUses[cls];
return uses != null ? uses : const <ClassEntity>[];
}
+ @override
void registerUsedElement(MemberEntity element) {
if (element.isInstanceMember && !element.isAbstract) {
_liveInstanceMembers.add(element);
@@ -1011,6 +1041,7 @@
return assignedInstanceMembers;
}
+ @override
void registerClass(ClassEntity cls) {
_classHierarchyBuilder.registerClass(cls);
}
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index f8a1dc4..2f70e16 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -17,6 +17,7 @@
class SelectorKind {
final String name;
+ @override
final int hashCode;
const SelectorKind(this.name, this.hashCode);
@@ -29,6 +30,7 @@
int get index => hashCode;
+ @override
String toString() => name;
static List<SelectorKind> values = const <SelectorKind>[
@@ -50,6 +52,7 @@
final Name memberName;
final CallStructure callStructure;
+ @override
final int hashCode;
int get argumentCount => callStructure.argumentCount;
@@ -307,6 +310,7 @@
return Hashing.mixHashCodeBits(hash, callStructure.hashCode);
}
+ @override
String toString() {
return 'Selector($kind, $name, ${callStructure.structureToString()})';
}
diff --git a/pkg/compiler/lib/src/universe/side_effects.dart b/pkg/compiler/lib/src/universe/side_effects.dart
index aac589a..2a63070 100644
--- a/pkg/compiler/lib/src/universe/side_effects.dart
+++ b/pkg/compiler/lib/src/universe/side_effects.dart
@@ -57,8 +57,10 @@
sink.end(tag);
}
+ @override
bool operator ==(other) => _flags == other._flags;
+ @override
int get hashCode => throw new UnsupportedError('SideEffects.hashCode');
bool _getFlag(int position) {
@@ -200,6 +202,7 @@
int get flags => _flags;
+ @override
String toString() {
StringBuffer buffer = new StringBuffer();
buffer.write('SideEffects(reads');
@@ -307,6 +310,7 @@
MemberEntity get member => _member;
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('SideEffectsBuilder(member=$member,');
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index ab3ffbb..6e19b31 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -85,9 +85,11 @@
List<DartType> get typeArguments => const <DartType>[];
+ @override
int get hashCode => Hashing.listHash(
typeArguments, Hashing.objectsHash(selector, receiverConstraint));
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! DynamicUse) return false;
@@ -96,6 +98,7 @@
equalElements(typeArguments, other.typeArguments);
}
+ @override
String toString() => '$selector,$receiverConstraint';
}
@@ -112,6 +115,7 @@
"${typeArguments?.length ?? 0} were passed.");
}
+ @override
List<DartType> get typeArguments => _typeArguments ?? const <DartType>[];
}
@@ -120,6 +124,7 @@
/// This is used in the codegen phase where receivers are constrained to a
/// type mask or similar.
class ConstrainedDynamicUse extends DynamicUse {
+ @override
final Object receiverConstraint;
final List<DartType> _typeArguments;
@@ -134,6 +139,7 @@
"${_typeArguments?.length ?? 0} were passed.");
}
+ @override
List<DartType> get typeArguments => _typeArguments ?? const <DartType>[];
}
@@ -163,6 +169,7 @@
class StaticUse {
final Entity element;
final StaticUseKind kind;
+ @override
final int hashCode;
final InterfaceType type;
final CallStructure callStructure;
@@ -588,6 +595,7 @@
return new GenericStaticUse.methodInlining(element, typeArguments);
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! StaticUse) return false;
@@ -598,11 +606,13 @@
equalElements(typeArguments, other.typeArguments);
}
+ @override
String toString() =>
'StaticUse($element,$kind,$type,$typeArguments,$callStructure)';
}
class GenericStaticUse extends StaticUse {
+ @override
final List<DartType> typeArguments;
GenericStaticUse(Entity entity, StaticUseKind kind,
@@ -643,6 +653,7 @@
class TypeUse {
final DartType type;
final TypeUseKind kind;
+ @override
final int hashCode;
final ImportEntity deferredImport;
@@ -758,12 +769,14 @@
return new TypeUse.internal(type, TypeUseKind.TYPE_ARGUMENT);
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! TypeUse) return false;
return type == other.type && kind == other.kind;
}
+ @override
String toString() => 'TypeUse($type,$kind)';
}
@@ -778,6 +791,7 @@
class ConstantUse {
final ConstantValue value;
final ConstantUseKind kind;
+ @override
final int hashCode;
ConstantUse._(this.value, this.kind)
@@ -809,11 +823,13 @@
ConstantUse.literal(ConstantValue value)
: this._(value, ConstantUseKind.DIRECT);
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! ConstantUse) return false;
return value == other.value;
}
+ @override
String toString() => 'ConstantUse(${value.toStructuredText()},$kind)';
}
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index e80c180..49d452d 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -91,6 +91,7 @@
class StrongModeWorldStrategy implements SelectorConstraintsStrategy {
const StrongModeWorldStrategy();
+ @override
StrongModeWorldConstraints createSelectorConstraints(
Selector selector, Object initialConstraint) {
return new StrongModeWorldConstraints()
@@ -151,6 +152,7 @@
return _constraints.add(constraint);
}
+ @override
String toString() {
if (isAll) {
return '<all>';
@@ -190,6 +192,7 @@
bool get isThis => relation == ClassRelation.thisExpression;
+ @override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is StrongModeConstraint &&
@@ -197,8 +200,10 @@
relation == other.relation;
}
+ @override
int get hashCode => cls.hashCode * 13;
+ @override
String toString() => 'StrongModeConstraint($cls,$relation)';
}
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index af5eaae..cc9a92c 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -43,6 +43,7 @@
constantUses.forEach(visitor.visitConstantUse);
}
+ @override
String toString() => dump(this);
static String dump(WorldImpact worldImpact) {
@@ -97,42 +98,50 @@
impact.constantUses.forEach(registerConstantUse);
}
+ @override
void registerDynamicUse(DynamicUse dynamicUse) {
assert(dynamicUse != null);
_dynamicUses ??= new Setlet<DynamicUse>();
_dynamicUses.add(dynamicUse);
}
+ @override
Iterable<DynamicUse> get dynamicUses {
return _dynamicUses != null ? _dynamicUses : const <DynamicUse>[];
}
+ @override
void registerTypeUse(TypeUse typeUse) {
assert(typeUse != null);
_typeUses ??= new Setlet<TypeUse>();
_typeUses.add(typeUse);
}
+ @override
Iterable<TypeUse> get typeUses {
return _typeUses != null ? _typeUses : const <TypeUse>[];
}
+ @override
void registerStaticUse(StaticUse staticUse) {
assert(staticUse != null);
_staticUses ??= new Setlet<StaticUse>();
_staticUses.add(staticUse);
}
+ @override
Iterable<StaticUse> get staticUses {
return _staticUses != null ? _staticUses : const <StaticUse>[];
}
+ @override
void registerConstantUse(ConstantUse constantUse) {
assert(constantUse != null);
_constantUses ??= new Setlet<ConstantUse>();
_constantUses.add(constantUse);
}
+ @override
Iterable<ConstantUse> get constantUses {
return _constantUses != null ? _constantUses : const <ConstantUse>[];
}
@@ -221,6 +230,7 @@
return _dynamicUses != null ? _dynamicUses : worldImpact.dynamicUses;
}
+ @override
void registerDynamicUse(DynamicUse dynamicUse) {
if (_dynamicUses == null) {
_dynamicUses = new Setlet<DynamicUse>();
@@ -229,6 +239,7 @@
_dynamicUses.add(dynamicUse);
}
+ @override
void registerTypeUse(TypeUse typeUse) {
if (_typeUses == null) {
_typeUses = new Setlet<TypeUse>();
@@ -242,6 +253,7 @@
return _typeUses != null ? _typeUses : worldImpact.typeUses;
}
+ @override
void registerStaticUse(StaticUse staticUse) {
if (_staticUses == null) {
_staticUses = new Setlet<StaticUse>();
@@ -260,6 +272,7 @@
return _constantUses != null ? _constantUses : worldImpact.constantUses;
}
+ @override
void registerConstantUse(ConstantUse constantUse) {
if (_constantUses == null) {
_constantUses = new Setlet<ConstantUse>();
@@ -268,6 +281,7 @@
_constantUses.add(constantUse);
}
+ @override
void apply(WorldImpactVisitor visitor) {
staticUses.forEach(visitor.visitStaticUse);
dynamicUses.forEach(visitor.visitDynamicUse);
@@ -275,6 +289,7 @@
constantUses.forEach(visitor.visitConstantUse);
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('TransformedWorldImpact($worldImpact)');
@@ -289,6 +304,7 @@
const ImpactUseCase(this.name);
+ @override
String toString() => 'ImpactUseCase($name)';
}
diff --git a/pkg/compiler/lib/src/util/emptyset.dart b/pkg/compiler/lib/src/util/emptyset.dart
index 796498b..6fe644c 100644
--- a/pkg/compiler/lib/src/util/emptyset.dart
+++ b/pkg/compiler/lib/src/util/emptyset.dart
@@ -9,37 +9,59 @@
class ImmutableEmptySet<E> extends IterableBase<E> implements Set<E> {
const ImmutableEmptySet();
+ @override
Set<R> cast<R>() => new ImmutableEmptySet<R>();
+ @override
get iterator => const _EmptySetIterator();
+ @override
int get length => 0;
+ @override
bool get isEmpty => true;
get _immutableError => throw new UnsupportedError("EmptySet is immutable");
+ @override
bool add(E element) => _immutableError;
+ @override
void addAll(Iterable<E> elements) => _immutableError;
+ @override
E lookup(Object element) => null;
+ @override
bool remove(Object element) => false;
+ @override
void removeAll(Iterable<Object> elements) {}
+ @override
void removeWhere(bool test(E element)) {}
+ @override
void retainAll(Iterable<Object> elements) {}
+ @override
void retainWhere(bool test(E element)) {}
+ @override
void forEach(void action(E element)) {}
+ @override
void clear() {}
+ @override
bool contains(Object element) => false;
+ @override
bool containsAll(Iterable<Object> other) => other.isEmpty;
+ @override
Set<E> union(Set<E> other) => new Set.from(other);
+ @override
Set<E> intersection(Set<Object> other) => this;
+ @override
Set<E> difference(Set<Object> other) => this;
+ @override
Set<E> toSet() => new Set<E>();
}
class _EmptySetIterator implements Iterator<Null> {
const _EmptySetIterator();
+ @override
Null get current => null;
+ @override
bool moveNext() => false;
}
diff --git a/pkg/compiler/lib/src/util/enumset.dart b/pkg/compiler/lib/src/util/enumset.dart
index e292aa6..587b00064 100644
--- a/pkg/compiler/lib/src/util/enumset.dart
+++ b/pkg/compiler/lib/src/util/enumset.dart
@@ -98,14 +98,17 @@
/// Returns `true` if this set is not empty.
bool get isNotEmpty => value != 0;
+ @override
int get hashCode => value.hashCode * 19;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! EnumSet<E>) return false;
return value == other.value;
}
+ @override
String toString() {
if (value == 0) return '0';
int index = value.bitLength - 1;
@@ -172,6 +175,7 @@
/// Immutable implementation of [EnumSet].
class _ConstEnumSet<E> extends EnumSet<E> {
+ @override
final int value;
const _ConstEnumSet(this.value) : super._();
@@ -188,6 +192,7 @@
return new _ConstEnumSet(value);
}
+ @override
void set value(int mask) {
throw new UnsupportedError('EnumSet.value=');
}
diff --git a/pkg/compiler/lib/src/util/features.dart b/pkg/compiler/lib/src/util/features.dart
index d0547d3..bf98932 100644
--- a/pkg/compiler/lib/src/util/features.dart
+++ b/pkg/compiler/lib/src/util/features.dart
@@ -62,6 +62,7 @@
return sb.toString();
}
+ @override
String toString() => 'Features(${getText()})';
/// Creates a [Features] object by parse the [text] encoding.
diff --git a/pkg/compiler/lib/src/util/maplet.dart b/pkg/compiler/lib/src/util/maplet.dart
index b9dc6744..329853c 100644
--- a/pkg/compiler/lib/src/util/maplet.dart
+++ b/pkg/compiler/lib/src/util/maplet.dart
@@ -34,6 +34,7 @@
});
}
+ @override
bool get isEmpty {
if (_extra == null) {
return _MARKER == _key;
@@ -44,6 +45,7 @@
}
}
+ @override
int get length {
if (_extra == null) {
return (_MARKER == _key) ? 0 : 1;
@@ -54,6 +56,7 @@
}
}
+ @override
bool containsKey(Object key) {
if (_extra == null) {
return _key == key;
@@ -70,6 +73,7 @@
}
}
+ @override
V operator [](Object key) {
if (_extra == null) {
return (_key == key) ? _value : null;
@@ -86,6 +90,7 @@
}
}
+ @override
void operator []=(K key, V value) {
if (_extra == null) {
if (_MARKER == _key) {
@@ -166,6 +171,7 @@
}
}
+ @override
V remove(Object key) {
if (_extra == null) {
if (_key != key) return null;
@@ -193,6 +199,7 @@
}
}
+ @override
void forEach(void action(K key, V value)) {
if (_extra == null) {
if (_MARKER != _key) action(_key, _value);
@@ -208,11 +215,13 @@
}
}
+ @override
void clear() {
_key = _MARKER;
_value = _extra = null;
}
+ @override
Iterable<K> get keys => new _MapletKeyIterable<K>(this);
}
@@ -225,6 +234,7 @@
_MapletKeyIterable(this.maplet);
+ @override
Iterator<K> get iterator {
if (maplet._extra == null) {
return new _MapletSingleIterator<K>(maplet._key);
@@ -242,8 +252,10 @@
_MapletSingleIterator(this._element);
+ @override
K get current => _current;
+ @override
bool moveNext() {
if (Maplet._MARKER == _element) {
_current = null;
@@ -263,8 +275,10 @@
_MapletListIterator(this._list, this._remaining);
+ @override
K get current => _current;
+ @override
bool moveNext() {
while (_remaining > 0) {
var candidate = _list[_index++];
diff --git a/pkg/compiler/lib/src/util/setlet.dart b/pkg/compiler/lib/src/util/setlet.dart
index ab1911b..e35c12b 100644
--- a/pkg/compiler/lib/src/util/setlet.dart
+++ b/pkg/compiler/lib/src/util/setlet.dart
@@ -29,7 +29,9 @@
static Set<R> _newSet<R>() => new Setlet<R>();
+ @override
Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newSet);
+ @override
Iterator<E> get iterator {
if (_extra == null) {
return new _SetletSingleIterator<E>(_contents);
@@ -40,6 +42,7 @@
}
}
+ @override
int get length {
if (_extra == null) {
return (_MARKER == _contents) ? 0 : 1;
@@ -50,6 +53,7 @@
}
}
+ @override
bool get isEmpty {
if (_extra == null) {
return _MARKER == _contents;
@@ -60,6 +64,7 @@
}
}
+ @override
bool contains(Object element) {
if (_extra == null) {
return _contents == element;
@@ -76,6 +81,7 @@
}
}
+ @override
bool add(E element) {
if (_extra == null) {
if (_MARKER == _contents) {
@@ -142,10 +148,12 @@
}
}
+ @override
void addAll(Iterable<E> elements) {
elements.forEach((each) => add(each));
}
+ @override
E lookup(Object element) {
if (_extra == null) {
return _contents == element ? _contents : null;
@@ -162,6 +170,7 @@
}
}
+ @override
bool remove(Object element) {
if (_extra == null) {
if (_contents == element) {
@@ -187,10 +196,12 @@
}
}
+ @override
void removeAll(Iterable<Object> other) {
other.forEach(remove);
}
+ @override
void removeWhere(bool test(E element)) {
if (_extra == null) {
if (test(_contents)) {
@@ -211,15 +222,18 @@
}
}
+ @override
void retainWhere(bool test(E element)) {
removeWhere((E element) => !test(element));
}
+ @override
void retainAll(Iterable<Object> elements) {
Set set = elements is Set ? elements : elements.toSet();
removeWhere((E element) => !set.contains(element));
}
+ @override
void forEach(void action(E element)) {
if (_extra == null) {
if (_MARKER != _contents) action(_contents);
@@ -235,6 +249,7 @@
}
}
+ @override
bool containsAll(Iterable<Object> other) {
for (E e in other) {
if (!this.contains(e)) return false;
@@ -242,19 +257,24 @@
return true;
}
+ @override
clear() {
_contents = _MARKER;
_extra = null;
}
+ @override
Set<E> union(Set<E> other) => new Set<E>.from(this)..addAll(other);
+ @override
Setlet<E> intersection(Set<Object> other) =>
new Setlet<E>.from(this.where((e) => other.contains(e)));
+ @override
Setlet<E> difference(Set<Object> other) =>
new Setlet<E>.from(this.where((e) => !other.contains(e)));
+ @override
Setlet<E> toSet() {
Setlet<E> result = new Setlet<E>();
if (_extra == null) {
@@ -272,6 +292,7 @@
class _SetletMarker {
const _SetletMarker();
+ @override
toString() => "-";
}
@@ -280,8 +301,10 @@
E _current;
_SetletSingleIterator(this._element);
+ @override
E get current => _current;
+ @override
bool moveNext() {
if (Setlet._MARKER == _element) {
_current = null;
@@ -300,8 +323,10 @@
E _current;
_SetletListIterator(this._list, this._remaining);
+ @override
E get current => _current;
+ @override
bool moveNext() {
while (_remaining > 0) {
var candidate = _list[_index++];
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index 785253d..3dfee4b 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -234,14 +234,17 @@
Pair(this.a, this.b);
+ @override
int get hashCode => 13 * a.hashCode + 17 * b.hashCode;
+ @override
bool operator ==(var other) {
if (identical(this, other)) return true;
if (other is! Pair) return false;
return a == other.a && b == other.b;
}
+ @override
String toString() => '($a,$b)';
}
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index fed2fe2..b34280b 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -3,7 +3,7 @@
name: compiler
publish_to: none
environment:
- sdk: '>=2.1.0 <3.0.0'
+ sdk: '>=2.2.0 <3.0.0'
# NOTE: `pub get / pub upgrade` are generally not needed when working on this
# package. The `.packages` file in the repository root will be used by default.
diff --git a/pkg/compiler/testing.json b/pkg/compiler/testing.json
index d5fb717..498a45c 100644
--- a/pkg/compiler/testing.json
+++ b/pkg/compiler/testing.json
@@ -14,7 +14,9 @@
],
"exclude": [
- "^tests/compiler/dart2js/inference/data/super_invoke\\.dart"
+ "^tests/compiler/dart2js/.*/data/.*",
+ "^tests/compiler/dart2js/.*/model_data/.*",
+ "^tests/compiler/dart2js/deferred_loading/libs/.*"
]
}
}
diff --git a/pkg/compiler/tool/status_files/log_parser.dart b/pkg/compiler/tool/status_files/log_parser.dart
deleted file mode 100644
index 43df6f4..0000000
--- a/pkg/compiler/tool/status_files/log_parser.dart
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2017, 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 status_files.log_parser;
-
-import 'record.dart';
-
-final RegExp _stackRE = new RegExp('#[0-9]* ');
-final RegExp _assertionFileRE = new RegExp(r"'file:[^']*/sdk/pkg/");
-final String _assertionFileReplacement = r"'file:*/pkg/";
-
-/// Extracts test records from a test.py [log].
-List<Record> parse(String log) {
- var records = <Record>[];
- var suite;
- var test;
- var config;
- var expected;
- var actual;
- var reason;
- var fullReason; // lines before stack, usually multiline reason.
- var stack = <String>[];
- var paragraph = []; // collector of lines for fullReason.
- bool reproIsNext = false;
- for (var line in log.split('\n')) {
- if (line.startsWith("FAILED: ")) {
- int lastSlash = line.lastIndexOf('/');
- // Some tests (particularly the html tests) have "group names" with spaces
- // in them. So we find the test name by the space just before the last
- // slash.
- int space = line.substring(0, lastSlash).lastIndexOf(' ');
- test = line.substring(space + 1).trim();
- suite = '';
- var slash = test.indexOf('/');
- if (slash > 0) {
- suite = test.substring(0, slash).trim();
- test = test.substring(slash + 1).trim();
- }
- config = line
- .substring("FAILED: ".length, space)
- .replaceAll('release_ia32', '')
- .replaceAll('release_x64', '');
- }
- if (line.startsWith("Expected: ")) {
- expected = line.substring("Expected: ".length).trim();
- }
- if (line.startsWith("Actual: ")) {
- actual = line.substring("Actual: ".length).trim();
- }
- if (line.startsWith("The compiler crashed:")) {
- reason = line.substring("The compiler crashed:".length).trim();
- reason = reason.replaceFirst(_assertionFileRE, _assertionFileReplacement);
- paragraph.clear();
- }
-
- if (line.startsWith(_stackRE)) {
- stack.add(line);
- fullReason ??= paragraph.take(5).join('\n');
- paragraph.clear();
- } else {
- paragraph.add(line);
- }
-
- if (reproIsNext) {
- records.add(new Record(suite, test, config, expected, actual, reason,
- line.trim(), fullReason, stack));
- suite = test = config = expected = actual = reason = null;
- stack = [];
- fullReason = null;
- paragraph.clear();
- reproIsNext = false;
- }
- if (line.startsWith("--- Re-run this test:")) {
- reproIsNext = true;
- }
- }
- return records;
-}
diff --git a/pkg/compiler/tool/status_files/rank_stacks.dart b/pkg/compiler/tool/status_files/rank_stacks.dart
deleted file mode 100644
index 27cf37b..0000000
--- a/pkg/compiler/tool/status_files/rank_stacks.dart
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/*
-Usage:
-
- $ tools/test.py -m release \
- -c dart2js -r d8 --dart2js-batch --report \
- --host-checked \
- --dart2js_options="--library-root=out/ReleaseX64/dart-sdk/ --use-kernel" \
- language language_2 corelib corelib_2 \
- dart2js_native dart2js_extra \
- 2>&1 > LOG
-
- $ sdk/bin/dart pkg/compiler/tool/status_files/rank_stacks.dart LOG > STACKS.txt
-*/
-
-import 'dart:io';
-
-import 'package:args/args.dart';
-
-import 'log_parser.dart';
-import 'record.dart';
-
-int stackPrintLength;
-int howManyStacks;
-
-void die(String why) {
- print(why);
- print('Usage:\n'
- 'dart rank_stacks.dart [options] test-logs\n\n'
- '${argParser.usage}');
- exit(1);
-}
-
-ArgParser argParser = new ArgParser()
- ..addOption('stacks',
- abbr: 's',
- defaultsTo: '0',
- help: 'Number of highest ranking stacks to print (0 for all).')
- ..addOption('length',
- abbr: 'l', defaultsTo: '12', help: 'Number of stack frames printed.');
-
-int intOption(ArgResults args, String name) {
- onError(String text) {
- die("Value '$text' is not an integer. "
- "Option '$name' requires an integer value.");
- }
-
- return int.parse(args[name], onError: onError);
-}
-
-main(args) {
- List<String> rest;
- try {
- var argResults = argParser.parse(args);
- howManyStacks = intOption(argResults, 'stacks');
- stackPrintLength = intOption(argResults, 'length');
- rest = argResults.rest;
- } catch (e) {
- die('$e');
- }
-
- if (rest.isEmpty) die('No input file.');
- var records = <Record>[];
- for (String input in rest) {
- var uri = Uri.base.resolve(input);
- var file = new File.fromUri(uri);
- if (!file.existsSync()) {
- die("File not found: '$input'.");
- }
- String text = file.readAsStringSync();
- records.addAll(parse(text));
- }
-
- var trie = new TrieNode(null, 0);
- for (var record in records) {
- enter(record, 0, trie);
- }
-
- var leaves = trieLeaves(trie).toList();
- leaves.sort(compareNodesByCountAndStack);
- for (var leaf in howManyStacks == 0 ? leaves : leaves.take(howManyStacks)) {
- print('');
- var examples = leaf.members.map(fullReasonOf).toSet().toList();
- examples.sort();
- print('${leaf.length} of:');
- for (var example in examples) {
- var count = leaf.members.where((r) => fullReasonOf(r) == example).length;
- var countAligned = '$count'.padLeft(6);
- if (examples.length == 1) countAligned = ' .';
- var indentedExample = '\t' + example.replaceAll('\n', '\n\t');
- print('${countAligned}${indentedExample}');
- }
-
- for (var line in leaf.members.first.stack.take(stackPrintLength)) {
- print(' $line');
- }
- }
-}
-
-String fullReasonOf(Record r) {
- // Some records have no matched reason, so default to test status.
- return r.fullReason ?? r.actual;
-}
-
-int compareNodesByCountAndStack(TrieNode a, TrieNode b) {
- int r = b.length.compareTo(a.length);
- if (r != 0) return r;
- List<String> stackA = a.members.first.stack;
- List<String> stackB = b.members.first.stack;
- int lengthA = stackA.length;
- int lengthB = stackB.length;
- for (int i = 0; i < lengthA && i < lengthB; i++) {
- r = stackA[i].compareTo(stackB[i]);
- if (r != 0) return r;
- }
- return lengthA.compareTo(lengthB);
-}
-
-class TrieNode {
- final int depth;
- final String key;
- final Map<String, TrieNode> map = <String, TrieNode>{};
- final List<Record> members = <Record>[];
-
- int get length => members.length;
-
- TrieNode(this.key, this.depth);
-
- String toString() => 'TrieNode(#$length)';
-}
-
-void enter(Record record, int depth, TrieNode root) {
- // Cluster on printed stack.
- if (depth >= stackPrintLength || depth >= record.stack.length) {
- root.members.add(record);
- return;
- }
- var key = record.stack[depth];
- var node = root.map[key] ??= new TrieNode(key, depth + 1);
- enter(record, depth + 1, node);
-}
-
-void printTrie(TrieNode node) {
- var indent = ' ' * node.depth;
- print('${indent} ${node.length} ${node.key}');
- for (var key in node.map.keys) {
- printTrie(node.map[key]);
- }
-}
-
-trieLeaves(node) sync* {
- if (node.members.isNotEmpty) {
- yield node;
- }
- for (var v in node.map.values) {
- yield* trieLeaves(v);
- }
-}
diff --git a/pkg/compiler/tool/status_files/record.dart b/pkg/compiler/tool/status_files/record.dart
deleted file mode 100644
index f2a6e97..0000000
--- a/pkg/compiler/tool/status_files/record.dart
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/// An entry found in the test.py logs corresponding to a test failure.
-///
-/// It stores what suite, test, and configuration was the failure seen at.
-library status_files.record;
-
-class Record implements Comparable<Record> {
- final String suite;
- final String test;
- final String config;
- final String expected;
- final String actual;
- final String repro;
- final String reason;
- final String fullReason;
- final List<String> stack;
-
- // TODO(sigmund): extract also a failure reason if any (e.g. a stack trace or
- // error message for crashes).
-
- bool get isPassing => actual == 'Pass';
-
- Record(this.suite, this.test, this.config, this.expected, this.actual,
- this.reason, this.repro, this.fullReason, this.stack);
-
- int compareTo(Record other) {
- if (suite == null && other.suite != null) return -1;
- if (suite != null && other.suite == null) return 1;
- if (test == null && other.test != null) return -1;
- if (test != null && other.test == null) return 1;
-
- var suiteDiff = suite.compareTo(other.suite);
- if (suiteDiff != 0) return suiteDiff;
-
- if (isPassing && !other.isPassing) return -1;
- if (!isPassing && other.isPassing) return 1;
-
- var testDiff = test.compareTo(other.test);
- if (testDiff != 0) return testDiff;
- return repro.compareTo(other.repro);
- }
-
- bool operator ==(covariant Record other) =>
- suite == other.suite &&
- test == other.test &&
- config == other.config &&
- expected == other.expected &&
- actual == other.actual &&
- repro == other.repro;
-}
diff --git a/pkg/compiler/tool/status_files/update_all.dart b/pkg/compiler/tool/status_files/update_all.dart
deleted file mode 100644
index bf09b28..0000000
--- a/pkg/compiler/tool/status_files/update_all.dart
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2018, 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.
-
-// Script to update the dart2js status lines for all tests running with the
-// $dart2js_with_kernel test configuration.
-
-import 'dart:io';
-import 'package:args/args.dart';
-import 'update_from_log.dart' as update_script;
-
-const List<String> strongSuites = const <String>[
- 'language_2',
- 'corelib_2',
-];
-
-const List<String> nonStrongSuites = const <String>[
- 'dart2js_native',
- 'dart2js_extra',
-];
-
-main(List<String> args) {
- ArgParser argParser = new ArgParser(allowTrailingOptions: true)
- ..addFlag('with-fast-startup')
- ..addFlag('fast-startup')
- ..addFlag('strong')
- ..addFlag('with-checked-mode')
- ..addFlag('checked-mode')
- ..addFlag('checked');
- ArgResults argResults = argParser.parse(args);
- bool fastStartup =
- argResults['with-fast-startup'] || argResults['fast-startup'];
- bool strong = argResults['strong'];
- bool checkedMode = argResults['with-checked-mode'] ||
- argResults['checked-mode'] ||
- argResults['checked'];
- List<String> suites = argResults.rest;
- if (suites.isEmpty) {
- if (strong) {
- suites = strongSuites;
- } else {
- suites = nonStrongSuites;
- }
- if (Platform.isWindows) {
- // TODO(johnniwinther): Running drt seems to be broken on Windows.
- suites = new List<String>.from(suites)..remove('html');
- }
- } else {
- bool failure = false;
- for (String suite in suites) {
- if (strongSuites.contains(suite) && nonStrongSuites.contains(suite)) {
- print("Unknown suite '$suite'");
- failure = true;
- }
- }
- if (failure) {
- exit(1);
- }
- }
-
- Directory tmp = Directory.systemTemp.createTempSync('update_all');
-
- String python = Platform.isWindows ? 'python.exe' : 'python';
-
- updateSuiteWithFlags(
- String name, String suite, String runtime, List<String> args) {
- if (strong) {
- name = "$name-strong";
- args.add('--strong');
- }
-
- print(" - $name tests");
- List<String> testArgs = [
- './tools/test.py',
- '-m',
- 'release',
- '-c',
- 'dart2js',
- '-r',
- runtime,
- '--dart2js-batch',
- '--dart2js-with-kernel'
- ];
- testArgs.addAll(args);
- testArgs.add(suite);
- String temp = '${tmp.path}/$suite-$name.txt';
- ProcessResult result = Process.runSync(python, testArgs);
- String stdout = result.stdout.toString();
- new File(temp).writeAsStringSync(stdout);
- print(temp);
- update_script.main([name, temp]);
- }
-
- updateSuite(String suite) {
- String runtime = "d8";
- if (suite == "html") {
- runtime = "drt";
- }
- print("update suite: \u001b[32m$suite\u001b[0m");
-
- updateSuiteWithFlags(
- 'minified', suite, runtime, ["--minified", "--use-sdk"]);
- updateSuiteWithFlags('host-checked', suite, runtime, ["--host-checked"]);
- if (fastStartup) {
- updateSuiteWithFlags('fast-startup', suite, runtime, ["--fast-startup"]);
- }
- if (checkedMode) {
- updateSuiteWithFlags('checked-mode', suite, runtime, ["--checked"]);
- }
- }
-
- print('build create_sdk');
- ProcessResult result = Process.runSync(
- python, ['./tools/build.py', '-m', 'release', 'create_sdk']);
- if (result.exitCode != 0) {
- print(result.stdout);
- print(result.stderr);
- exit(1);
- }
-
- suites.forEach(updateSuite);
-
- tmp.deleteSync(recursive: true);
-}
diff --git a/pkg/compiler/tool/status_files/update_from_log.dart b/pkg/compiler/tool/status_files/update_from_log.dart
deleted file mode 100644
index 26a6dd0..0000000
--- a/pkg/compiler/tool/status_files/update_from_log.dart
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/// Script that updates dart2js status lines automatically for tests under the
-/// '$fasta' configuration.
-///
-/// This script is hardcoded to only support this configuration and relies on
-/// a convention for how the status files are structured, In particular,
-/// every status file for dart2js should have 3 sections:
-///
-/// [ $compiler == dart2js && $fasta && $host_checked ]
-///
-/// and:
-///
-/// [ $compiler == dart2js && $fasta && $minified ]
-///
-/// and:
-///
-/// [ $compiler == dart2js && $fasta && $fast_startup ]
-///
-/// and:
-///
-/// [ $compiler == dart2js && $checked && $fasta ]
-library compiler.status_files.update_from_log;
-
-import 'dart:io';
-
-import 'record.dart';
-import 'log_parser.dart';
-
-final dart2jsConfigurations = {
- 'host-checked': r'[ $compiler == dart2js && $fasta && $host_checked ]',
- 'minified': r'[ $compiler == dart2js && $fasta && $minified ]',
- 'host-checked-strong':
- r'[ $compiler == dart2js && $fasta && $host_checked && $strong ]',
- 'minified-strong':
- r'[ $compiler == dart2js && $fasta && $minified && $strong ]',
- 'fast-startup': r'[ $compiler == dart2js && $fast_startup && $fasta ]',
- 'fast-startup-strong':
- r'[ $compiler == dart2js && $fast_startup && $fasta && $strong ]',
- 'checked-mode': r'[ $compiler == dart2js && $checked && $fasta ]',
- 'checked-mode-strong':
- r'[ $compiler == dart2js && $checked && $fasta && $strong ]',
-};
-
-final dart2jsStatusFiles = {
- 'language_2': 'tests/language_2/language_2_dart2js.status',
- // TODO(sigmund,rnystrom): update when corelib_2 gets split into multiple
- // status files.
- 'corelib_2': 'tests/corelib_2/corelib_2.status',
- 'dart2js_extra': 'tests/compiler/dart2js_extra/dart2js_extra.status',
- 'dart2js_native': 'tests/compiler/dart2js_native/dart2js_native.status',
-};
-
-main(args) {
- mainInternal(args, dart2jsConfigurations, dart2jsStatusFiles);
-}
-
-/// Note: this is called above and also from
-/// pkg/front_end/tool/status_files/update_from_log.dart
-mainInternal(List<String> args, Map<String, String> configurations,
- Map<String, String> statusFiles) {
- if (args.length < 2) {
- print('usage: update_from_log.dart <mode> log.txt [message-in-quotes]');
- print(' where mode is one of these values: ${configurations.keys}');
- exit(1);
- }
- var mode = args[0];
- if (!configurations.containsKey(mode)) {
- print('invalid mode: $mode, expected one in ${configurations.keys}');
- exit(1);
- }
-
- var uri =
- Uri.base.resolveUri(new Uri.file(args[1], windows: Platform.isWindows));
- var file = new File.fromUri(uri);
- if (!file.existsSync()) {
- print('file not found: $file');
- exit(1);
- }
-
- var globalReason = args.length > 2 ? args[2] : null;
- updateLogs(
- mode, file.readAsStringSync(), configurations, statusFiles, globalReason);
-}
-
-/// Update all status files based on the [log] records when running the compiler
-/// in [mode]. If provided [globalReason] is added as a comment to new test
-/// failures. If not, an automated reason might be extracted from the test
-/// failure message.
-void updateLogs(String mode, String log, Map<String, String> configurations,
- Map<String, String> statusFiles, String globalReason) {
- List<Record> records = parse(log);
- records.sort();
- var last;
- ConfigurationInSuiteSection section;
- for (var record in records) {
- if (last == record) continue; // ignore duplicates
- if (section?.suite != record.suite) {
- section?.update(globalReason);
- var statusFile = statusFiles[record.suite];
- if (statusFile == null) {
- print("No status file for suite '${record.suite}'.");
- continue;
- }
- var condition = configurations[mode];
- section = ConfigurationInSuiteSection.create(
- record.suite, mode, statusFile, condition);
- }
- section.add(record);
- last = record;
- }
- section?.update(globalReason);
-}
-
-/// Represents an existing entry in the logs.
-class ExistingEntry {
- final String test;
- final String status;
- final bool hasComment;
-
- ExistingEntry(this.test, this.status, this.hasComment);
-
- static parse(String line) {
- var colonIndex = line.indexOf(':');
- var test = line.substring(0, colonIndex);
- var status = line.substring(colonIndex + 1).trim();
- var commentIndex = status.indexOf("#");
- if (commentIndex != -1) {
- status = status.substring(0, commentIndex);
- }
- return new ExistingEntry(test, status, commentIndex != -1);
- }
-}
-
-/// Represents a section in a .status file that corresponds to a specific suite
-/// and configuration.
-class ConfigurationInSuiteSection {
- final String suite;
- final String _statusFile;
- final String _contents;
- final int _begin;
- final int _end;
- final List<Record> _records = [];
-
- ConfigurationInSuiteSection(
- this.suite, this._statusFile, this._contents, this._begin, this._end);
-
- /// Add a new test record, indicating that the test status should be updated.
- void add(Record record) => _records.add(record);
-
- /// Update the section in the file.
- ///
- /// This will reflect the new status lines as recorded in [_records].
- void update(String providedReason) {
- int changes = 0;
- int ignored = 0;
- var originalEntries = _contents.substring(_begin, _end).split('\n');
-
- // The algorithm below walks entries in the file and from the log in the
- // same order: preserving entries that didn't change, and updating entries
- // where the logs show that the test status changed.
-
- // Sort the file contents in case the file has been tampered with.
- originalEntries.sort();
-
- /// Re-sort records by name (they came sorted by suite and status first, so
- /// it may be wrong for the merging below).
- _records.sort((a, b) => a.test.compareTo(b.test));
-
- var newContents = new StringBuffer();
- newContents.write(_contents.substring(0, _begin));
- addFromRecord(Record record) {
- var reason = providedReason ?? record.reason;
- var comment = reason != null && reason.isNotEmpty ? ' # ${reason}' : '';
- newContents.writeln('${record.test}: ${record.actual}$comment');
- }
-
- int i = 0, j = 0;
- while (i < originalEntries.length && j < _records.length) {
- var existingLine = originalEntries[i];
- if (existingLine.trim().isEmpty) {
- i++;
- continue;
- }
- var existing = ExistingEntry.parse(existingLine);
- var record = _records[j];
- var compare = existing.test.compareTo(record.test);
- if (compare < 0) {
- // Existing test was unaffected, copy the status line.
- newContents.writeln(existingLine);
- i++;
- } else if (compare > 0) {
- // New entry, if it's a failure, we haven't seen this before and must
- // add it. If the status says it is passing, we ignore it. We do this
- // to support making this script idempotent if the patching has already
- // been done.
- if (!record.isPassing) {
- // New failure never seen before
- addFromRecord(record);
- changes++;
- }
- j++;
- } else if (existing.status == record.actual) {
- if (!existing.hasComment && record.reason != null) {
- addFromRecord(record);
- changes++;
- } else {
- // This also should only happen if the patching has already been done.
- // We don't complain to make this script idempotent.
- newContents.writeln(existingLine);
- }
- ignored++;
- i++;
- j++;
- } else {
- changes++;
- // The status changed, if it is now passing, we omit the entry entirely,
- // otherwise we use the status from the logs.
- if (!record.isPassing) {
- addFromRecord(record);
- }
- i++;
- j++;
- }
- }
-
- for (; i < originalEntries.length; i++) {
- newContents.writeln(originalEntries[i]);
- }
-
- for (; j < _records.length; j++) {
- changes++;
- addFromRecord(_records[j]);
- }
-
- newContents.write('\n');
- newContents.write(_contents.substring(_end));
- new File(_statusFile).writeAsStringSync('$newContents');
- print("updated '$_statusFile' with $changes changes");
- if (ignored > 0) {
- print(' $ignored changes were already applied in the status file.');
- }
- }
-
- static ConfigurationInSuiteSection create(
- String suite, String mode, String statusFile, String condition) {
- var contents = new File(statusFile).readAsStringSync();
- int sectionDeclaration = contents.indexOf(condition);
- if (sectionDeclaration == -1) {
- print('error: unable to find condition $condition in $statusFile');
- exit(1);
- }
- int begin = contents.indexOf('\n', sectionDeclaration) + 1;
- assert(begin != 0);
- int newlinePos = contents.indexOf('\n', begin + 1);
- int end = newlinePos;
- while (true) {
- if (newlinePos == -1) break;
- if (newlinePos + 1 < contents.length) {
- if (contents[newlinePos + 1] == '[') {
- // We've found the end of the section
- break;
- } else if (contents[newlinePos + 1] == '#') {
- // We've found a commented out line. This line might belong to the
- // next section.
- newlinePos = contents.indexOf('\n', newlinePos + 1);
- continue;
- }
- }
- // We've found an ordinary line. It's part of this section, so update
- // end.
- newlinePos = contents.indexOf('\n', newlinePos + 1);
- end = newlinePos;
- }
- end = end == -1 ? contents.length : end + 1;
- return new ConfigurationInSuiteSection(
- suite, statusFile, contents, begin, end);
- }
-}
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index cbb7d34..6e08dfb 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -200,6 +200,11 @@
final DeclaredVariables declaredVariables;
+ /// Tracks the temporary variable used to build collections containing
+ /// control flow [IfElement] and [ForElement] nodes. Should be saved when
+ /// visiting a new control flow tree and restored after.
+ JS.Expression _currentCollectionVariable;
+
CodeGenerator(LinkedAnalysisDriver driver, this.types, this.summaryData,
this.options, this._extensionTypes, this.errors)
: rules = Dart2TypeSystem(types),
@@ -5432,8 +5437,11 @@
return JS.Do(_visitScope(node.body), _visitTest(node.condition));
}
- JS.Statement _emitAwaitFor(SimpleIdentifier identifier,
- DeclaredIdentifier loopVariable, Expression iterable, Statement body) {
+ JS.Statement _emitAwaitFor(
+ SimpleIdentifier identifier,
+ DeclaredIdentifier loopVariable,
+ Expression iterable,
+ JS.Statement jsBody) {
// Emits `await for (var value in stream) ...`, which desugars as:
//
// let iter = new StreamIterator(stream);
@@ -5478,7 +5486,7 @@
JS.Yield(js.call('#.moveNext()', iter))
..sourceInformation = _nodeStart(variable),
init,
- _visitStatement(body),
+ jsBody,
JS.Yield(js.call('#.cancel()', iter))
..sourceInformation = _nodeStart(variable)
]);
@@ -5716,29 +5724,29 @@
@override
JS.Expression visitListLiteral(ListLiteral node) {
var elementType = (node.staticType as InterfaceType).typeArguments[0];
+ var elements = _visitCollectionElementList(node.elements2, elementType);
if (!node.isConst) {
- return _emitList(elementType, _visitExpressionList(node.elements2));
+ return _emitList(elementType, elements);
}
- return _cacheConst(() =>
- _emitConstList(elementType, _visitExpressionList(node.elements2)));
+
+ return _cacheConst(() => _emitConstList(elementType, elements));
}
// TODO(nshahan) Cleanup after control flow collections experiments are removed.
JS.Expression _emitSetLiteral(
Iterable<CollectionElement> elements, SetOrMapLiteral node) {
var type = node.staticType as InterfaceType;
+ var elementType = type.typeArguments[0];
+ var jsElements = _visitCollectionElementList(elements, elementType);
if (!node.isConst) {
var setType = _emitType(type);
if (elements.isEmpty) {
return js.call('#.new()', [setType]);
}
- return js.call(
- '#.from([#])', [setType, _visitCollectionElementList(elements)]);
+ return js.call('#.from([#])', [setType, jsElements]);
}
- return _cacheConst(() => runtimeCall('constSet(#, [#])', [
- _emitType((node.staticType as InterfaceType).typeArguments[0]),
- _visitCollectionElementList(elements)
- ]));
+ return _cacheConst(() =>
+ runtimeCall('constSet(#, [#])', [_emitType(elementType), jsElements]));
}
JS.Expression _emitConstList(
@@ -5764,16 +5772,16 @@
JS.Expression _emitMapLiteral(
Iterable<CollectionElement> elements, SetOrMapLiteral node) {
var type = node.staticType as InterfaceType;
+ var elementType = type.typeArguments[0];
+ var jsElements = _visitCollectionElementList(elements, elementType);
if (!node.isConst) {
var mapType = _emitMapImplType(type);
if (elements.isEmpty) {
return js.call('new #.new()', [mapType]);
}
- return js.call(
- 'new #.from([#])', [mapType, _visitCollectionElementList(elements)]);
+ return js.call('new #.from([#])', [mapType, jsElements]);
}
- return _cacheConst(
- () => _emitConstMap(type, _visitCollectionElementList(elements)));
+ return _cacheConst(() => _emitConstMap(type, jsElements));
}
JS.Expression _emitConstMap(InterfaceType type, List<JS.Expression> entries) {
@@ -5864,13 +5872,50 @@
return nodes?.map(_visitStatement)?.toList();
}
- /// Visits [nodes] with [_visitColelctionElement].
+ /// Returns a [JS.Expression] for each [CollectionElement] in [nodes].
+ ///
+ /// Visits all [nodes] in order and nested [CollectionElement]s depth first
+ /// to produce [JS.Expresison]s intended to be used when outputing a
+ /// collection literal.
+ ///
+ /// [IfElement]s and [ForElement]s will be transformed into a spread of a
+ /// self invoking function that reutrns a list.
+ ///
+ /// Example Dart:
+ /// [1, if(true) for (var i=2; i<10; i++) i, 10]
+ ///
+ /// JS:
+ /// [1, ...(() => {
+ /// let temp = JSArrayOfint().of([]);
+ /// if (true) for (let i = 2; i < 10; i++) temp.push(i);
+ /// return temp;
+ /// })(), 10]
List<JS.Expression> _visitCollectionElementList(
- Iterable<CollectionElement> nodes) {
+ Iterable<CollectionElement> nodes, DartType elementType) {
var expressions = <JS.Expression>[];
for (var node in nodes) {
- //TODO(nshahan) Handle [IfElement] and [ForElement].
- if (node is MapLiteralEntry) {
+ if (_isUiAsCodeElement(node)) {
+ // Create a temporary variable to build a new collection from.
+ var previousCollectionVariable = _currentCollectionVariable;
+ var temporaryIdentifier =
+ _createTemporary('items', _jsArray.type.instantiate([elementType]));
+ _currentCollectionVariable = _emitSimpleIdentifier(temporaryIdentifier);
+ var items = js.statement('let # = #',
+ [_currentCollectionVariable, _emitList(elementType, [])]);
+
+ // Build up a list for the control-flow-collections element and wrap in
+ // a function call that returns the list.
+ var functionBody = JS.Block([
+ items,
+ node.accept<JS.Node>(this),
+ JS.Return(_currentCollectionVariable)
+ ]);
+ var functionCall = JS.Call(JS.ArrowFun([], functionBody), []);
+
+ // Finally, spread the temporary control-flow-collections list.
+ expressions.add(JS.Spread(functionCall));
+ _currentCollectionVariable = previousCollectionVariable;
+ } else if (node is MapLiteralEntry) {
expressions.add(_visitExpression(node.key));
expressions.add(_visitExpression(node.value));
} else {
@@ -5880,6 +5925,26 @@
return expressions;
}
+ /// Visits [node] with [_visitExpression] and wraps the result in a call to
+ /// append it to the list tracked by [_currentCollectionVariable].
+ JS.Statement _visitNestedCollectionElement(CollectionElement node) {
+ JS.Statement pushToCurrentCollection(Expression value) => js.statement(
+ '#.push(#)', [_currentCollectionVariable, _visitExpression(value)]);
+
+ if (node is MapLiteralEntry) {
+ return JS.Block([
+ pushToCurrentCollection(node.key),
+ pushToCurrentCollection(node.value)
+ ]);
+ }
+
+ return pushToCurrentCollection(node);
+ }
+
+ /// Returns `true` if [node] is a UI-as-Code [CollectionElement].
+ bool _isUiAsCodeElement(node) =>
+ node is IfElement || node is ForElement || node is SpreadElement;
+
/// Gets the start position of [node] for use in source mapping.
///
/// This is the most common kind of marking, and is used for most expressions
@@ -6430,7 +6495,7 @@
// TODO(nshahan) Simplify when control-flow-collections experiments are removed.
// Should just accept a ForParts as an arg with fewer casts.
JS.For _emitFor(Expression initialization, VariableDeclarationList variables,
- Expression condition, Iterable<Expression> updaters, Statement body) {
+ Expression condition, Iterable<Expression> updaters, JS.Statement body) {
var init = _visitExpression(initialization) ??
visitVariableDeclarationList(variables);
JS.Expression update;
@@ -6440,17 +6505,18 @@
.toVoidExpression();
}
- return JS.For(init, _visitTest(condition), update, _visitScope(body));
+ return JS.For(init, _visitTest(condition), update, body);
}
// TODO(nshahan) Simplify when control-flow-collections experiments are removed.
// Should just accept a ForEachParts as an arg with fewer casts.
- JS.Statement _emitForEach(SimpleIdentifier identifier,
- DeclaredIdentifier loopVariable, Expression iterable, Statement body) {
+ JS.Statement _emitForEach(
+ SimpleIdentifier identifier,
+ DeclaredIdentifier loopVariable,
+ Expression iterable,
+ JS.Statement jsBody) {
var jsLeftExpression = _visitExpression(identifier);
var jsIterable = _visitExpression(iterable);
-
- var jsBody = _visitScope(body);
if (jsLeftExpression == null) {
var id = _emitVariableDef(loopVariable.identifier);
jsLeftExpression = js.call('let #', id);
@@ -6470,10 +6536,33 @@
}
@override
- visitForElement(ForElement node) => _unreachable(node);
+ JS.Statement visitForElement(ForElement node) {
+ // TODO(nshahan) Need to support await for in collections.
+ if (node.awaitKeyword != null) return _unreachable(node);
+ var jsBody = _isUiAsCodeElement(node.body)
+ ? node.body.accept(this)
+ : _visitNestedCollectionElement(node.body);
+
+ return _forAdaptor(node.forLoopParts, node.awaitKeyword, jsBody);
+ }
@override
- visitIfElement(IfElement node) => _unreachable(node);
+ JS.Statement visitIfElement(IfElement node) {
+ var thenElement = _isUiAsCodeElement(node.thenElement)
+ ? node.thenElement.accept(this)
+ : _visitNestedCollectionElement(node.thenElement);
+
+ JS.Statement elseElement;
+ if (node.elseElement != null) {
+ if (_isUiAsCodeElement(node.elseElement)) {
+ elseElement = node.elseElement.accept<JS.Node>(this);
+ } else {
+ elseElement = _visitNestedCollectionElement(node.elseElement);
+ }
+ }
+
+ return JS.If(_visitTest(node.condition), thenElement, elseElement);
+ }
@override
visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) =>
@@ -6484,31 +6573,34 @@
_unreachable(node);
@override
- JS.Statement visitForStatement2(ForStatement2 node) {
- // TODO(nshahan) Simplify when control-flow-collections experiments are removed.
- var forParts = node.forLoopParts;
+ JS.Statement visitForStatement2(ForStatement2 node) =>
+ _forAdaptor(node.forLoopParts, node.awaitKeyword, _visitScope(node.body));
+
+ // TODO(nshahan) Simplify when control-flow-collections experiment is removed.
+ JS.Statement _forAdaptor(
+ ForLoopParts forParts, Token awaitKeyword, JS.Statement jsBody) {
if (forParts is ForPartsWithExpression) {
return _emitFor(forParts.initialization, null, forParts.condition,
- forParts.updaters, node.body);
+ forParts.updaters, jsBody);
} else if (forParts is ForPartsWithDeclarations) {
return _emitFor(null, forParts.variables, forParts.condition,
- forParts.updaters, node.body);
- } else if (node.awaitKeyword == null) {
+ forParts.updaters, jsBody);
+ } else if (awaitKeyword == null) {
if (forParts is ForEachPartsWithIdentifier) {
return _emitForEach(
- forParts.identifier, null, forParts.iterable, node.body);
+ forParts.identifier, null, forParts.iterable, jsBody);
} else if (forParts is ForEachPartsWithDeclaration) {
return _emitForEach(
- null, forParts.loopVariable, forParts.iterable, node.body);
+ null, forParts.loopVariable, forParts.iterable, jsBody);
}
} else if (forParts is ForEachPartsWithIdentifier) {
return _emitAwaitFor(
- forParts.identifier, null, forParts.iterable, node.body);
+ forParts.identifier, null, forParts.iterable, jsBody);
} else if (forParts is ForEachPartsWithDeclaration) {
return _emitAwaitFor(
- null, forParts.loopVariable, forParts.iterable, node.body);
+ null, forParts.loopVariable, forParts.iterable, jsBody);
}
- return _unreachable(node);
+ return _unreachable(forParts);
}
@deprecated
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index cec419b..a4fd216 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -77,8 +77,6 @@
{SummaryDataStore summaryData,
List<String> summaryPaths = const [],
Map<String, bool> experiments = const {}}) {
- AnalysisEngine.instance.processRequiredPlugins();
-
var resourceProvider = options.resourceProvider;
var contextBuilder = options.createContextBuilder();
@@ -235,7 +233,8 @@
libraryUris.toSet(),
(uri) => summaryData.linkedMap[uri],
(uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
- declaredVariables.get);
+ declaredVariables,
+ analysisOptions);
linkResult.forEach(assembler.addLinkedLibrary);
var summaryBytes = assembler.assemble().toBuffer();
diff --git a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
index 65cfe52..e911dca 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
@@ -4,7 +4,7 @@
// TODO(jmesserly): import from its own package
import '../js_ast/js_ast.dart';
-
+import 'shared_compiler.dart' show YieldFinder;
import 'js_names.dart' show TemporaryId;
/// A synthetic `let*` node, similar to that found in Scheme.
@@ -181,7 +181,7 @@
}
Expression _toInvokedFunction(Block block) {
- var finder = _YieldFinder();
+ var finder = YieldFinder();
block.accept(finder);
if (!finder.hasYield) {
return Call(ArrowFun([], block), []);
@@ -353,34 +353,3 @@
if (!found) super.visitNode(node);
}
}
-
-class _YieldFinder extends BaseVisitor {
- bool hasYield = false;
- bool hasThis = false;
- bool _nestedFunction = false;
-
- @override
- visitThis(This node) {
- hasThis = true;
- }
-
- @override
- visitFunctionExpression(FunctionExpression node) {
- var savedNested = _nestedFunction;
- _nestedFunction = true;
- super.visitFunctionExpression(node);
- _nestedFunction = savedNested;
- }
-
- @override
- visitYield(Yield node) {
- if (!_nestedFunction) hasYield = true;
- super.visitYield(node);
- }
-
- @override
- visitNode(Node node) {
- if (hasYield && hasThis) return; // found both, nothing more to do.
- super.visitNode(node);
- }
-}
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 66e0628..be9b13f 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -192,3 +192,34 @@
if (!found) super.visitNode(node);
}
}
+
+class YieldFinder extends JS.BaseVisitor {
+ bool hasYield = false;
+ bool hasThis = false;
+ bool _nestedFunction = false;
+
+ @override
+ visitThis(JS.This node) {
+ hasThis = true;
+ }
+
+ @override
+ visitFunctionExpression(JS.FunctionExpression node) {
+ var savedNested = _nestedFunction;
+ _nestedFunction = true;
+ super.visitFunctionExpression(node);
+ _nestedFunction = savedNested;
+ }
+
+ @override
+ visitYield(JS.Yield node) {
+ if (!_nestedFunction) hasYield = true;
+ super.visitYield(node);
+ }
+
+ @override
+ visitNode(JS.Node node) {
+ if (hasYield && hasThis) return; // found both, nothing more to do.
+ super.visitNode(node);
+ }
+}
diff --git a/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart b/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart
new file mode 100644
index 0000000..e44eb59
--- /dev/null
+++ b/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart
@@ -0,0 +1,573 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(jmesserly): this file was copied from:
+// https://github.com/flutter/engine/blob/4b01d795feec3ba8231a397a4ec2759954d8216e/flutter_kernel_transformers/lib/track_widget_constructor_locations.dart
+//
+// Longer term, this transform should be injected by Flutter when they building
+// the Flutter-specific `dartdevc` script.
+//
+// The following modifications were made:
+// - remove "package:vm" dependency (only used for one interface)
+// - pass in the class hierarchy that DDC already has available.
+library track_widget_constructor_locations;
+
+// The kernel/src import below that requires lint `ignore_for_file`
+// is a temporary state of things until kernel team builds better api that would
+// replace api used below. This api was made private in an effort to discourage
+// further use.
+// ignore_for_file: implementation_imports
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:meta/meta.dart';
+
+// Parameter name used to track were widget constructor calls were made from.
+//
+// The parameter name contains a randomly generate hex string to avoid collision
+// with user generated parameters.
+const String _creationLocationParameterName =
+ r'$creationLocationd_0dea112b090073317d4';
+
+/// Name of private field added to the Widget class and any other classes that
+/// implement Widget.
+///
+/// Regardless of what library a class implementing Widget is defined in, the
+/// private field will always be defined in the context of the widget_inspector
+/// library ensuring no name conflicts with regular fields.
+const String _locationFieldName = r'_location';
+
+bool _hasNamedParameter(FunctionNode function, String name) {
+ return function.namedParameters
+ .any((VariableDeclaration parameter) => parameter.name == name);
+}
+
+bool _hasNamedArgument(Arguments arguments, String argumentName) {
+ return arguments.named
+ .any((NamedExpression argument) => argument.name == argumentName);
+}
+
+VariableDeclaration _getNamedParameter(
+ FunctionNode function,
+ String parameterName,
+) {
+ for (VariableDeclaration parameter in function.namedParameters) {
+ if (parameter.name == parameterName) {
+ return parameter;
+ }
+ }
+ return null;
+}
+
+// TODO(jacobr): find a solution that supports optional positional parameters.
+/// Add the creation location to the arguments list if possible.
+///
+/// Returns whether the creation location argument could be added. We cannot
+/// currently add the named argument for functions with optional positional
+/// parameters as the current scheme requires adding the creation location as a
+/// named parameter. Fortunately that is not a significant issue in practice as
+/// no Widget classes in package:flutter have optional positional parameters.
+/// This code degrades gracefully for constructors with optional positional
+/// parameters by skipping adding the creation location argument rather than
+/// failing.
+void _maybeAddCreationLocationArgument(
+ Arguments arguments,
+ FunctionNode function,
+ Expression creationLocation,
+ Class locationClass,
+) {
+ if (_hasNamedArgument(arguments, _creationLocationParameterName)) {
+ return;
+ }
+ if (!_hasNamedParameter(function, _creationLocationParameterName)) {
+ return;
+ }
+
+ final NamedExpression namedArgument =
+ new NamedExpression(_creationLocationParameterName, creationLocation);
+ namedArgument.parent = arguments;
+ arguments.named.add(namedArgument);
+}
+
+/// Adds a named parameter to a function if the function does not already have
+/// a named parameter with the name or optional positional parameters.
+bool _maybeAddNamedParameter(
+ FunctionNode function,
+ VariableDeclaration variable,
+) {
+ if (_hasNamedParameter(function, _creationLocationParameterName)) {
+ // Gracefully handle if this method is called on a function that has already
+ // been transformed.
+ return false;
+ }
+ // Function has optional positional parameters so cannot have optional named
+ // parameters.
+ if (function.requiredParameterCount != function.positionalParameters.length) {
+ return false;
+ }
+ variable.parent = function;
+ function.namedParameters.add(variable);
+ return true;
+}
+
+/// Transformer that modifies all calls to Widget constructors to include
+/// a [DebugLocation] parameter specifying the location where the constructor
+/// call was made.
+///
+/// This transformer requires that all Widget constructors have already been
+/// transformed to have a named parameter with the name specified by
+/// `_locationParameterName`.
+class _WidgetCallSiteTransformer extends Transformer {
+ final ClassHierarchy _hierarchy;
+
+ /// The [Widget] class defined in the `package:flutter` library.
+ ///
+ /// Used to perform instanceof checks to determine whether Dart constructor
+ /// calls are creating [Widget] objects.
+ Class _widgetClass;
+
+ /// The [DebugLocation] class defined in the `package:flutter` library.
+ Class _locationClass;
+
+ /// Current factory constructor that node being transformed is inside.
+ ///
+ /// Used to flow the location passed in as an argument to the factory to the
+ /// actual constructor call within the factory.
+ Procedure _currentFactory;
+
+ _WidgetCallSiteTransformer(
+ this._hierarchy, {
+ @required Class widgetClass,
+ @required Class locationClass,
+ }) : _widgetClass = widgetClass,
+ _locationClass = locationClass;
+
+ /// Builds a call to the const constructor of the [DebugLocation]
+ /// object specifying the location where a constructor call was made and
+ /// optionally the locations for all parameters passed in.
+ ///
+ /// Specifying the parameters passed in is an experimental feature. With
+ /// access to the source code of an application you could determine the
+ /// locations of the parameters passed in from the source location of the
+ /// constructor call but it is convenient to bundle the location and names
+ /// of the parameters passed in so that tools can show parameter locations
+ /// without re-parsing the source code.
+ ConstructorInvocation _constructLocation(
+ Location location, {
+ String name,
+ ListLiteral parameterLocations,
+ bool showFile: true,
+ }) {
+ final List<NamedExpression> arguments = <NamedExpression>[
+ new NamedExpression('line', new IntLiteral(location.line)),
+ new NamedExpression('column', new IntLiteral(location.column)),
+ ];
+ if (showFile) {
+ arguments.add(new NamedExpression(
+ 'file', new StringLiteral(location.file.toString())));
+ }
+ if (name != null) {
+ arguments.add(new NamedExpression('name', new StringLiteral(name)));
+ }
+ if (parameterLocations != null) {
+ arguments
+ .add(new NamedExpression('parameterLocations', parameterLocations));
+ }
+ return new ConstructorInvocation(
+ _locationClass.constructors.first,
+ new Arguments(<Expression>[], named: arguments),
+ isConst: true,
+ );
+ }
+
+ @override
+ Procedure visitProcedure(Procedure node) {
+ if (node.isFactory) {
+ _currentFactory = node;
+ node.transformChildren(this);
+ _currentFactory = null;
+ return node;
+ }
+ return defaultTreeNode(node);
+ }
+
+ bool _isSubclassOfWidget(Class clazz) {
+ // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
+ // non-deprecated ClassHierarchy constructor.
+ return _hierarchy.isSubclassOf(clazz, _widgetClass);
+ }
+
+ @override
+ StaticInvocation visitStaticInvocation(StaticInvocation node) {
+ node.transformChildren(this);
+ final Procedure target = node.target;
+ if (!target.isFactory) {
+ return node;
+ }
+ final Class constructedClass = target.enclosingClass;
+ if (!_isSubclassOfWidget(constructedClass)) {
+ return node;
+ }
+
+ _addLocationArgument(node, target.function, constructedClass);
+ return node;
+ }
+
+ void _addLocationArgument(InvocationExpression node, FunctionNode function,
+ Class constructedClass) {
+ _maybeAddCreationLocationArgument(
+ node.arguments,
+ function,
+ _computeLocation(node, function, constructedClass),
+ _locationClass,
+ );
+ }
+
+ @override
+ ConstructorInvocation visitConstructorInvocation(ConstructorInvocation node) {
+ node.transformChildren(this);
+
+ final Constructor constructor = node.target;
+ final Class constructedClass = constructor.enclosingClass;
+ if (!_isSubclassOfWidget(constructedClass)) {
+ return node;
+ }
+
+ _addLocationArgument(node, constructor.function, constructedClass);
+ return node;
+ }
+
+ Expression _computeLocation(InvocationExpression node, FunctionNode function,
+ Class constructedClass) {
+ // For factory constructors we need to use the location specified as an
+ // argument to the factory constructor rather than the location
+ // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
+ // non-deprecated ClassHierarchy constructor.
+ if (_currentFactory != null &&
+ _hierarchy.isSubclassOf(
+ constructedClass, _currentFactory.enclosingClass)) {
+ final VariableDeclaration creationLocationParameter = _getNamedParameter(
+ _currentFactory.function,
+ _creationLocationParameterName,
+ );
+ if (creationLocationParameter != null) {
+ return new VariableGet(creationLocationParameter);
+ }
+ }
+
+ final Arguments arguments = node.arguments;
+ final Location location = node.location;
+ final List<ConstructorInvocation> parameterLocations =
+ <ConstructorInvocation>[];
+ final List<VariableDeclaration> parameters = function.positionalParameters;
+ for (int i = 0; i < arguments.positional.length; ++i) {
+ final Expression expression = arguments.positional[i];
+ final VariableDeclaration parameter = parameters[i];
+ parameterLocations.add(_constructLocation(
+ expression.location,
+ name: parameter.name,
+ showFile: false,
+ ));
+ }
+ for (NamedExpression expression in arguments.named) {
+ parameterLocations.add(_constructLocation(
+ expression.location,
+ name: expression.name,
+ showFile: false,
+ ));
+ }
+ return _constructLocation(
+ location,
+ parameterLocations: new ListLiteral(
+ parameterLocations,
+ typeArgument: _locationClass.thisType,
+ isConst: true,
+ ),
+ );
+ }
+}
+
+/// Rewrites all widget constructors and constructor invocations to add a
+/// parameter specifying the location the constructor was called from.
+///
+/// The creation location is stored as a private field named `_location`
+/// on the base widget class and flowed through the constructors using a named
+/// parameter.
+class WidgetCreatorTracker {
+ Class _widgetClass;
+ Class _locationClass;
+
+ /// Marker interface indicating that a private _location field is
+ /// available.
+ Class _hasCreationLocationClass;
+
+ /// The [ClassHierarchy] that should be used after applying this transformer.
+ /// If any class was updated, in general we need to create a new
+ /// [ClassHierarchy] instance, with new dispatch targets; or at least let
+ /// the existing instance know that some of its dispatch tables are not
+ /// valid anymore.
+ final ClassHierarchy hierarchy;
+
+ WidgetCreatorTracker(this.hierarchy);
+
+ void _resolveFlutterClasses(Iterable<Library> libraries) {
+ // If the Widget or Debug location classes have been updated we need to get
+ // the latest version
+ for (Library library in libraries) {
+ final Uri importUri = library.importUri;
+ if (!library.isExternal &&
+ importUri != null &&
+ importUri.scheme == 'package') {
+ if (importUri.path == 'flutter/src/widgets/framework.dart') {
+ for (Class class_ in library.classes) {
+ if (class_.name == 'Widget') {
+ _widgetClass = class_;
+ }
+ }
+ } else {
+ if (importUri.path == 'flutter/src/widgets/widget_inspector.dart') {
+ for (Class class_ in library.classes) {
+ if (class_.name == '_HasCreationLocation') {
+ _hasCreationLocationClass = class_;
+ } else if (class_.name == '_Location') {
+ _locationClass = class_;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// Modify [clazz] to add a field named [_locationFieldName] that is the
+ /// first parameter of all constructors of the class.
+ ///
+ /// This method should only be called for classes that implement but do not
+ /// extend [Widget].
+ void _transformClassImplementingWidget(Class clazz) {
+ if (clazz.fields
+ .any((Field field) => field.name.name == _locationFieldName)) {
+ // This class has already been transformed. Skip
+ return;
+ }
+ clazz.implementedTypes
+ .add(new Supertype(_hasCreationLocationClass, <DartType>[]));
+ // We intentionally use the library context of the _HasCreationLocation
+ // class for the private field even if [clazz] is in a different library
+ // so that all classes implementing Widget behave consistently.
+ final Field locationField = new Field(
+ new Name(
+ _locationFieldName,
+ _hasCreationLocationClass.enclosingLibrary,
+ ),
+ isFinal: true,
+ );
+ clazz.addMember(locationField);
+
+ final Set<Constructor> _handledConstructors =
+ new Set<Constructor>.identity();
+
+ void handleConstructor(Constructor constructor) {
+ if (!_handledConstructors.add(constructor)) {
+ return;
+ }
+ assert(!_hasNamedParameter(
+ constructor.function,
+ _creationLocationParameterName,
+ ));
+ final VariableDeclaration variable = new VariableDeclaration(
+ _creationLocationParameterName,
+ type: _locationClass.thisType,
+ );
+ if (!_maybeAddNamedParameter(constructor.function, variable)) {
+ return;
+ }
+
+ bool hasRedirectingInitializer = false;
+ for (Initializer initializer in constructor.initializers) {
+ if (initializer is RedirectingInitializer) {
+ if (initializer.target.enclosingClass == clazz) {
+ // We need to handle this constructor first or the call to
+ // addDebugLocationArgument bellow will fail due to the named
+ // parameter not yet existing on the constructor.
+ handleConstructor(initializer.target);
+ }
+ _maybeAddCreationLocationArgument(
+ initializer.arguments,
+ initializer.target.function,
+ new VariableGet(variable),
+ _locationClass,
+ );
+ hasRedirectingInitializer = true;
+ break;
+ }
+ }
+ if (!hasRedirectingInitializer) {
+ constructor.initializers.add(new FieldInitializer(
+ locationField,
+ new VariableGet(variable),
+ ));
+ // TODO(jacobr): add an assert verifying the locationField is not
+ // null. Currently, we cannot safely add this assert because we do not
+ // handle Widget classes with optional positional arguments. There are
+ // no Widget classes in the flutter repo with optional positional
+ // arguments but it is possible users could add classes with optional
+ // positional arguments.
+ //
+ // constructor.initializers.add(new AssertInitializer(new AssertStatement(
+ // new IsExpression(
+ // new VariableGet(variable), _locationClass.thisType),
+ // conditionStartOffset: constructor.fileOffset,
+ // conditionEndOffset: constructor.fileOffset,
+ // )));
+ }
+ }
+
+ // Add named parameters to all constructors.
+ clazz.constructors.forEach(handleConstructor);
+ }
+
+ /// Transform the given [module].
+ void transform(Component module) {
+ final List<Library> libraries = module.libraries;
+
+ if (libraries.isEmpty) {
+ return;
+ }
+
+ _resolveFlutterClasses(libraries);
+
+ if (_widgetClass == null) {
+ // This application doesn't actually use the package:flutter library.
+ return;
+ }
+
+ final Set<Class> transformedClasses = new Set<Class>.identity();
+ final Set<Library> librariesToTransform = new Set<Library>.identity()
+ ..addAll(module.libraries);
+
+ for (Library library in module.libraries) {
+ if (library.isExternal) {
+ continue;
+ }
+ for (Class class_ in library.classes) {
+ _transformWidgetConstructors(
+ librariesToTransform,
+ transformedClasses,
+ class_,
+ );
+ }
+ }
+
+ // Transform call sites to pass the location parameter.
+ final _WidgetCallSiteTransformer callsiteTransformer =
+ new _WidgetCallSiteTransformer(
+ hierarchy,
+ widgetClass: _widgetClass,
+ locationClass: _locationClass,
+ );
+
+ for (Library library in module.libraries) {
+ if (library.isExternal) {
+ continue;
+ }
+ library.transformChildren(callsiteTransformer);
+ }
+ }
+
+ bool _isSubclassOfWidget(Class clazz) {
+ if (clazz == null) {
+ return false;
+ }
+ // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
+ // non-deprecated ClassHierarchy constructor.
+ return hierarchy.isSubclassOf(clazz, _widgetClass);
+ }
+
+ void _transformWidgetConstructors(Set<Library> librariesToBeTransformed,
+ Set<Class> transformedClasses, Class clazz) {
+ if (!_isSubclassOfWidget(clazz) ||
+ !librariesToBeTransformed.contains(clazz.enclosingLibrary) ||
+ !transformedClasses.add(clazz)) {
+ return;
+ }
+
+ // Ensure super classes have been transformed before this class.
+ if (clazz.superclass != null &&
+ !transformedClasses.contains(clazz.superclass)) {
+ _transformWidgetConstructors(
+ librariesToBeTransformed,
+ transformedClasses,
+ clazz.superclass,
+ );
+ }
+
+ for (Procedure procedure in clazz.procedures) {
+ if (procedure.isFactory) {
+ _maybeAddNamedParameter(
+ procedure.function,
+ new VariableDeclaration(
+ _creationLocationParameterName,
+ type: _locationClass.thisType,
+ ),
+ );
+ }
+ }
+
+ // Handle the widget class and classes that implement but do not extend the
+ // widget class.
+ if (!_isSubclassOfWidget(clazz.superclass)) {
+ _transformClassImplementingWidget(clazz);
+ return;
+ }
+
+ final Set<Constructor> _handledConstructors =
+ new Set<Constructor>.identity();
+
+ void handleConstructor(Constructor constructor) {
+ if (!_handledConstructors.add(constructor)) {
+ return;
+ }
+
+ final VariableDeclaration variable = new VariableDeclaration(
+ _creationLocationParameterName,
+ type: _locationClass.thisType,
+ );
+ if (_hasNamedParameter(
+ constructor.function, _creationLocationParameterName)) {
+ // Constructor was already rewritten. TODO(jacobr): is this case actually hit?
+ return;
+ }
+ if (!_maybeAddNamedParameter(constructor.function, variable)) {
+ return;
+ }
+ for (Initializer initializer in constructor.initializers) {
+ if (initializer is RedirectingInitializer) {
+ if (initializer.target.enclosingClass == clazz) {
+ // We need to handle this constructor first or the call to
+ // addDebugLocationArgument could fail due to the named parameter
+ // not existing.
+ handleConstructor(initializer.target);
+ }
+
+ _maybeAddCreationLocationArgument(
+ initializer.arguments,
+ initializer.target.function,
+ new VariableGet(variable),
+ _locationClass,
+ );
+ } else if (initializer is SuperInitializer &&
+ _isSubclassOfWidget(initializer.target.enclosingClass)) {
+ _maybeAddCreationLocationArgument(
+ initializer.arguments,
+ initializer.target.function,
+ new VariableGet(variable),
+ _locationClass,
+ );
+ }
+ }
+ }
+
+ clazz.constructors.forEach(handleConstructor);
+ }
+}
diff --git a/pkg/dev_compiler/lib/src/js_ast/nodes.dart b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
index 6b78736..4b39d7e 100644
--- a/pkg/dev_compiler/lib/src/js_ast/nodes.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
@@ -1124,7 +1124,6 @@
// it is for simplicity's sake.
class Spread extends Prefix {
Spread(Expression operand) : super('...', operand);
- int get precedenceLevel => SPREAD;
T accept<T>(NodeVisitor<T> visitor) => visitor.visitSpread(this);
Spread _clone() => Spread(argument);
diff --git a/pkg/dev_compiler/lib/src/js_ast/precedence.dart b/pkg/dev_compiler/lib/src/js_ast/precedence.dart
index b10bac6..f149dc2 100644
--- a/pkg/dev_compiler/lib/src/js_ast/precedence.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/precedence.dart
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
const EXPRESSION = 0;
+// TODO(nshahan) No longer used for the spread operator.
+// All precedence levels need to be updated to be more accurate.
const SPREAD = EXPRESSION + 1;
const YIELD = SPREAD + 1;
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index b3852c9..e7a764c 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -9,6 +9,7 @@
import 'package:args/args.dart';
import 'package:build_integration/file_system/multi_root.dart';
import 'package:cli_util/cli_util.dart' show getSdkPath;
+import 'package:dev_compiler/src/flutter/track_widget_constructor_locations.dart';
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
import 'package:kernel/kernel.dart' hide MapEntry;
import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
@@ -72,6 +73,8 @@
help: 'emit API summary in a .js.txt file',
defaultsTo: false,
hide: true)
+ ..addFlag('track-widget-creation',
+ help: 'enable inspecting of Flutter widgets', hide: true)
// TODO(jmesserly): add verbose help to show hidden options
..addOption('dart-sdk-summary',
help: 'The path to the Dart SDK summary file.', hide: true)
@@ -252,8 +255,16 @@
outFiles.add(File(output + '.txt').writeAsString(sb.toString()));
}
var target = compilerState.options.target as DevCompilerTarget;
+ var hierarchy = target.hierarchy;
+
+ // TODO(jmesserly): remove this hack once Flutter SDK has a `dartdevc` with
+ // support for the widget inspector.
+ if (argResults['track-widget-creation'] as bool) {
+ WidgetCreatorTracker(hierarchy).transform(component);
+ }
+
var compiler =
- ProgramCompiler(component, target.hierarchy, options, declaredVariables);
+ ProgramCompiler(component, hierarchy, options, declaredVariables);
var jsModule = compiler.emitModule(component, result.inputSummaries,
compilerState.options.inputSummaries, summaryModules);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 6c5ccc6..a2cba73 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -4775,6 +4775,24 @@
}
@override
+ visitListConcatenation(ListConcatenation node) {
+ // Only occurs inside unevaluated constants.
+ throw new UnsupportedError("List concatenation");
+ }
+
+ @override
+ visitSetConcatenation(SetConcatenation node) {
+ // Only occurs inside unevaluated constants.
+ throw new UnsupportedError("Set concatenation");
+ }
+
+ @override
+ visitMapConcatenation(MapConcatenation node) {
+ // Only occurs inside unevaluated constants.
+ throw new UnsupportedError("Map concatenation");
+ }
+
+ @override
visitIsExpression(IsExpression node) {
return _emitIsExpression(node.operand, node.type);
}
@@ -5038,7 +5056,25 @@
@override
visitBlockExpression(BlockExpression node) {
- throw UnimplementedError('ProgramCompiler.visitBlockExpression');
+ var jsExpr = _visitExpression(node.value);
+ List<JS.Statement> jsStmts = node.body.statements
+ .map(_visitStatement)
+ .toList()
+ ..add(JS.Return(jsExpr));
+ var jsBlock = JS.Block(jsStmts);
+ // BlockExpressions with async operations must be constructed
+ // with a generator instead of a lambda.
+ var finder = YieldFinder();
+ jsBlock.accept(finder);
+ if (finder.hasYield) {
+ var genFn = JS.Fun([], jsBlock, isGenerator: true);
+ var asyncLibrary = emitLibraryName(coreTypes.asyncLibrary);
+ var returnType = _emitType(node.getStaticType(types));
+ var asyncCall =
+ js.call('#.async(#, #)', [asyncLibrary, returnType, genFn]);
+ return JS.Yield(asyncCall);
+ }
+ return JS.Call(JS.ArrowFun([], jsBlock), []);
}
@override
@@ -5144,9 +5180,12 @@
}
@override
- visitListConstant(node) {
- return _cacheConst(() => _emitConstList(
- node.typeArgument, node.entries.map(visitConstant).toList()));
+ visitListConstant(node) => visitConstantList(node.typeArgument, node.entries);
+
+ /// Visits [Constant] with [_visitConstant].
+ visitConstantList(DartType typeArgument, List<Constant> entries) {
+ return _cacheConst(() =>
+ _emitConstList(typeArgument, entries.map(visitConstant).toList()));
}
@override
@@ -5154,7 +5193,10 @@
// Set literals are currently desugared in the frontend.
// Implement this method before flipping the supportsSetLiterals flag
// in DevCompilerTarget to true.
- throw "Set literal constants not supported.";
+ return _cacheConst(() => runtimeCall('constSet(#, #)', [
+ _emitType(node.typeArgument),
+ visitConstantList(node.typeArgument, node.entries)
+ ]));
}
@override
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 1227ed7..db69224 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -69,6 +69,9 @@
bool get errorOnUnexactWebIntLiterals => true;
@override
+ bool get supportsSetLiterals => true;
+
+ @override
bool get enableNoSuchMethodForwarders => true;
@override
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
index 9027893..368d5e7 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
@@ -2634,7 +2634,9 @@
var resultBits = Uint8List(8);
var length = _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
- if (length - 53 > maxDoubleExponent) return double.infinity;
+ if (length > maxDoubleExponent + 53) {
+ return _isNegative ? double.negativeInfinity : double.infinity;
+ }
// The most significant bit is for the sign.
if (_isNegative) resultBits[7] = 0x80;
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart
index 1e2c7dd..869c705 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart
@@ -67,14 +67,14 @@
@patch
class Random {
- static final _secureRandom = _JSSecureRandom();
+ static Random _secureRandom;
@patch
factory Random([int seed]) =>
(seed == null) ? const _JSRandom() : _Random(seed);
@patch
- factory Random.secure() => _secureRandom;
+ factory Random.secure() => _secureRandom ??= _JSSecureRandom();
}
class _JSRandom implements Random {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart
index 41a51d6..aeb4e2f 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart
@@ -162,9 +162,7 @@
return result.toString();
}
} else {
- var quoted = quoteStringForRegExp(pattern);
- var replacer = JS('', "new RegExp(#, 'g')", quoted);
- return stringReplaceJS(receiver, replacer, replacement);
+ return JS('String', '#.split(#).join(#)', receiver, pattern, replacement);
}
} else if (pattern is JSSyntaxRegExp) {
var re = regExpGetGlobalNative(pattern);
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index 9ff093c..ce04a71 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -19,11 +19,12 @@
abstract class IncrementalKernelGenerator {
factory IncrementalKernelGenerator(CompilerOptions options, Uri entryPoint,
- [Uri initializeFromDillUri]) {
+ [Uri initializeFromDillUri, bool outlineOnly]) {
return new IncrementalCompiler(
new CompilerContext(
new ProcessedOptions(options: options, inputs: [entryPoint])),
- initializeFromDillUri);
+ initializeFromDillUri,
+ outlineOnly);
}
/// Initialize the incremental compiler from a component.
@@ -31,11 +32,13 @@
/// Notice that the component has to include the platform, and that no other
/// platform will be loaded.
factory IncrementalKernelGenerator.fromComponent(
- CompilerOptions options, Uri entryPoint, Component component) {
+ CompilerOptions options, Uri entryPoint, Component component,
+ [bool outlineOnly]) {
return new IncrementalCompiler.fromComponent(
new CompilerContext(
new ProcessedOptions(options: options, inputs: [entryPoint])),
- component);
+ component,
+ outlineOnly);
}
/// Returns a component whose libraries are the recompiled libraries,
@@ -47,6 +50,26 @@
/// next call to [computeDelta]).
void invalidate(Uri uri);
+ /// Invalidate all libraries that were build from source.
+ ///
+ /// This is equivalent to a number of calls to [invalidate]: One for each URI
+ /// that happens to have been read from source.
+ /// Said another way, this invalidates everything not loaded from dill
+ /// (at startup) or via [setModulesToLoadOnNextComputeDelta].
+ void invalidateAllSources();
+
+ /// Set the given [components] as components to load on the next iteration
+ /// of [computeDelta].
+ ///
+ /// If specified, all libraries not compiled from source and not included in
+ /// these components will be invalidated and the libraries inside these
+ /// components will be loaded instead.
+ ///
+ /// Useful for, for instance, modular compilation, where modules
+ /// (created externally) via this functionality can be added, changed or
+ /// removed.
+ void setModulesToLoadOnNextComputeDelta(List<Component> components);
+
/// Compile [expression] as an [Expression]. A function returning that
/// expression is compiled.
///
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 6196ba7..5555840 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -37,6 +37,7 @@
Future<InitializedCompilerState> initializeCompiler(
InitializedCompilerState oldState,
Uri sdkSummary,
+ Uri librariesSpecificationUri,
Uri packagesFile,
List<Uri> summaryInputs,
List<Uri> linkedInputs,
@@ -50,6 +51,7 @@
CompilerOptions options = new CompilerOptions()
..sdkSummary = sdkSummary
..packagesFileUri = packagesFile
+ ..librariesSpecificationUri = librariesSpecificationUri
..inputSummaries = summaryInputs
..linkedDependencies = linkedInputs
..target = target
diff --git a/pkg/front_end/lib/src/fasta/builder/declaration.dart b/pkg/front_end/lib/src/fasta/builder/declaration.dart
index 1584102..392b3e6 100644
--- a/pkg/front_end/lib/src/fasta/builder/declaration.dart
+++ b/pkg/front_end/lib/src/fasta/builder/declaration.dart
@@ -64,6 +64,10 @@
bool get isNamedMixinApplication => false;
+ bool get isAnonymousMixinApplication {
+ return isMixinApplication && !isNamedMixinApplication;
+ }
+
/// Applies [patch] to this declaration.
void applyPatch(Declaration patch) {
unsupported("${runtimeType}.applyPatch", charOffset, fileUri);
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 37cff6c..574152c 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -520,6 +520,28 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantDisambiguateAmbiguousInformation =
+ messageCantDisambiguateAmbiguousInformation;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantDisambiguateAmbiguousInformation = const MessageCode(
+ "CantDisambiguateAmbiguousInformation",
+ message:
+ r"""Both Iterable and Map spread elements encountered in ambiguous literal.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantDisambiguateNotEnoughInformation =
+ messageCantDisambiguateNotEnoughInformation;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantDisambiguateNotEnoughInformation = const MessageCode(
+ "CantDisambiguateNotEnoughInformation",
+ message:
+ r"""Not enough type information to disambiguate between literal set and literal map.""",
+ tip:
+ r"""Try providing type arguments for the literal explicitly to disambiguate it.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeCantInferPackagesFromManyInputs =
messageCantInferPackagesFromManyInputs;
@@ -568,30 +590,31 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
+const Template<Message Function(String name)>
templateCantInferTypeDueToInconsistentOverrides =
- const Template<Message Function(String string)>(
+ const Template<Message Function(String name)>(
messageTemplate:
- r"""Can't infer the type of '#string': overridden members must all have the same type.""",
- tipTemplate: r"""Specify the type explicitly.""",
+ r"""Can't infer a type for '#name' as some of the inherited members have different types.""",
+ tipTemplate: r"""Try adding an explicit type.""",
withArguments: _withArgumentsCantInferTypeDueToInconsistentOverrides);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
+const Code<Message Function(String name)>
codeCantInferTypeDueToInconsistentOverrides =
- const Code<Message Function(String string)>(
+ const Code<Message Function(String name)>(
"CantInferTypeDueToInconsistentOverrides",
templateCantInferTypeDueToInconsistentOverrides,
analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCantInferTypeDueToInconsistentOverrides(String string) {
- if (string.isEmpty) throw 'No string provided';
+Message _withArgumentsCantInferTypeDueToInconsistentOverrides(String name) {
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
return new Message(codeCantInferTypeDueToInconsistentOverrides,
message:
- """Can't infer the type of '${string}': overridden members must all have the same type.""",
- tip: """Specify the type explicitly.""",
- arguments: {'string': string});
+ """Can't infer a type for '${name}' as some of the inherited members have different types.""",
+ tip: """Try adding an explicit type.""",
+ arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2781,6 +2804,15 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedElseOrComma = messageExpectedElseOrComma;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedElseOrComma = const MessageCode(
+ "ExpectedElseOrComma",
+ index: 94,
+ message: r"""Expected 'else' or comma.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(Token token)> templateExpectedEnumBody = const Template<
Message Function(Token token)>(
@@ -3297,7 +3329,10 @@
-Dname
-Dname=value
- Ignored for now.
+ Define an environment variable in the compile-time environment.
+
+ --no-defines
+ Ignore all -D options and leave environment constants unevaluated.
--
Stop option parsing, the rest of the command line is assumed to be
@@ -6890,6 +6925,14 @@
message: r"""Can only use type variables in instance methods.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNonNullAwareSpreadIsNull = messageNonNullAwareSpreadIsNull;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNonNullAwareSpreadIsNull = const MessageCode(
+ "NonNullAwareSpreadIsNull",
+ message: r"""Can't spread a value with static type Null.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeNonPartOfDirectiveInPart = messageNonPartOfDirectiveInPart;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7342,29 +7385,35 @@
String name,
String name2,
DartType _type,
- DartType
- _type2)> templateOverrideTypeMismatchParameter = const Template<
- Message Function(String name, String name2, DartType _type,
- DartType _type2)>(
+ DartType _type2,
+ String
+ name3)> templateOverrideTypeMismatchParameter = const Template<
+ Message Function(
+ String name,
+ String name2,
+ DartType _type,
+ DartType _type2,
+ String
+ name3)>(
messageTemplate:
- r"""The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type in the overridden method, '#type2'.""",
+ r"""The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type, '#type2', in the overridden method, '#name3'.""",
tipTemplate:
r"""Change to a supertype of '#type2', or, for a covariant parameter, a subtype.""",
withArguments: _withArgumentsOverrideTypeMismatchParameter);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<
- Message Function(
- String name, String name2, DartType _type, DartType _type2)>
- codeOverrideTypeMismatchParameter = const Code<
- Message Function(
- String name, String name2, DartType _type, DartType _type2)>(
+ Message Function(String name, String name2, DartType _type,
+ DartType _type2, String name3)> codeOverrideTypeMismatchParameter =
+ const Code<
+ Message Function(String name, String name2, DartType _type,
+ DartType _type2, String name3)>(
"OverrideTypeMismatchParameter", templateOverrideTypeMismatchParameter,
analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsOverrideTypeMismatchParameter(
- String name, String name2, DartType _type, DartType _type2) {
+ String name, String name2, DartType _type, DartType _type2, String name3) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
if (name2.isEmpty) throw 'No name provided';
@@ -7372,18 +7421,21 @@
TypeLabeler labeler = new TypeLabeler();
List<Object> typeParts = labeler.labelType(_type);
List<Object> type2Parts = labeler.labelType(_type2);
+ if (name3.isEmpty) throw 'No name provided';
+ name3 = demangleMixinApplicationName(name3);
String type = typeParts.join();
String type2 = type2Parts.join();
return new Message(codeOverrideTypeMismatchParameter,
message:
- """The parameter '${name}' of the method '${name2}' has type '${type}', which does not match the corresponding type in the overridden method, '${type2}'.""" +
+ """The parameter '${name}' of the method '${name2}' has type '${type}', which does not match the corresponding type, '${type2}', in the overridden method, '${name3}'.""" +
labeler.originMessages,
tip: """Change to a supertype of '${type2}', or, for a covariant parameter, a subtype.""",
arguments: {
'name': name,
'name2': name2,
'type': _type,
- 'type2': _type2
+ 'type2': _type2,
+ 'name3': name3
});
}
@@ -7392,38 +7444,50 @@
Message Function(
String name,
DartType _type,
- DartType
- _type2)> templateOverrideTypeMismatchReturnType = const Template<
- Message Function(String name, DartType _type, DartType _type2)>(
+ DartType _type2,
+ String
+ name2)> templateOverrideTypeMismatchReturnType = const Template<
+ Message Function(
+ String name, DartType _type, DartType _type2, String name2)>(
messageTemplate:
- r"""The return type of the method '#name' is '#type', which does not match the return type of the overridden method, '#type2'.""",
+ r"""The return type of the method '#name' is '#type', which does not match the return type, '#type2', of the overridden method, '#name2'.""",
tipTemplate: r"""Change to a subtype of '#type2'.""",
withArguments: _withArgumentsOverrideTypeMismatchReturnType);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type, DartType _type2)>
- codeOverrideTypeMismatchReturnType =
- const Code<Message Function(String name, DartType _type, DartType _type2)>(
+const Code<
+ Message Function(
+ String name, DartType _type, DartType _type2, String name2)>
+ codeOverrideTypeMismatchReturnType = const Code<
+ Message Function(
+ String name, DartType _type, DartType _type2, String name2)>(
"OverrideTypeMismatchReturnType",
templateOverrideTypeMismatchReturnType,
analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsOverrideTypeMismatchReturnType(
- String name, DartType _type, DartType _type2) {
+ String name, DartType _type, DartType _type2, String name2) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
TypeLabeler labeler = new TypeLabeler();
List<Object> typeParts = labeler.labelType(_type);
List<Object> type2Parts = labeler.labelType(_type2);
+ if (name2.isEmpty) throw 'No name provided';
+ name2 = demangleMixinApplicationName(name2);
String type = typeParts.join();
String type2 = type2Parts.join();
return new Message(codeOverrideTypeMismatchReturnType,
message:
- """The return type of the method '${name}' is '${type}', which does not match the return type of the overridden method, '${type2}'.""" +
+ """The return type of the method '${name}' is '${type}', which does not match the return type, '${type2}', of the overridden method, '${name2}'.""" +
labeler.originMessages,
tip: """Change to a subtype of '${type2}'.""",
- arguments: {'name': name, 'type': _type, 'type2': _type2});
+ arguments: {
+ 'name': name,
+ 'type': _type,
+ 'type2': _type2,
+ 'name2': name2
+ });
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8225,6 +8289,13 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSpreadElement = messageSpreadElement;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSpreadElement = const MessageCode("SpreadElement",
+ severity: Severity.context, message: r"""Iterable spread.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
DartType _type,
@@ -8258,6 +8329,109 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSpreadMapElement = messageSpreadMapElement;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSpreadMapElement = const MessageCode(
+ "SpreadMapElement",
+ severity: Severity.context,
+ message: r"""Map spread.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ DartType _type,
+ DartType
+ _type2)> templateSpreadMapEntryElementKeyTypeMismatch = const Template<
+ Message Function(DartType _type, DartType _type2)>(
+ messageTemplate:
+ r"""Can't assign spread entry keys of type '#type' to map entry keys of type '#type2'.""",
+ withArguments: _withArgumentsSpreadMapEntryElementKeyTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+ codeSpreadMapEntryElementKeyTypeMismatch =
+ const Code<Message Function(DartType _type, DartType _type2)>(
+ "SpreadMapEntryElementKeyTypeMismatch",
+ templateSpreadMapEntryElementKeyTypeMismatch,
+ analyzerCodes: <String>["MAP_KEY_TYPE_NOT_ASSIGNABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadMapEntryElementKeyTypeMismatch(
+ DartType _type, DartType _type2) {
+ TypeLabeler labeler = new TypeLabeler();
+ List<Object> typeParts = labeler.labelType(_type);
+ List<Object> type2Parts = labeler.labelType(_type2);
+ String type = typeParts.join();
+ String type2 = type2Parts.join();
+ return new Message(codeSpreadMapEntryElementKeyTypeMismatch,
+ message:
+ """Can't assign spread entry keys of type '${type}' to map entry keys of type '${type2}'.""" +
+ labeler.originMessages,
+ arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(DartType _type, DartType _type2)>
+ templateSpreadMapEntryElementValueTypeMismatch =
+ const Template<Message Function(DartType _type, DartType _type2)>(
+ messageTemplate:
+ r"""Can't assign spread entry values of type '#type' to map entry values of type '#type2'.""",
+ withArguments: _withArgumentsSpreadMapEntryElementValueTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+ codeSpreadMapEntryElementValueTypeMismatch =
+ const Code<Message Function(DartType _type, DartType _type2)>(
+ "SpreadMapEntryElementValueTypeMismatch",
+ templateSpreadMapEntryElementValueTypeMismatch,
+ analyzerCodes: <String>["MAP_VALUE_TYPE_NOT_ASSIGNABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadMapEntryElementValueTypeMismatch(
+ DartType _type, DartType _type2) {
+ TypeLabeler labeler = new TypeLabeler();
+ List<Object> typeParts = labeler.labelType(_type);
+ List<Object> type2Parts = labeler.labelType(_type2);
+ String type = typeParts.join();
+ String type2 = type2Parts.join();
+ return new Message(codeSpreadMapEntryElementValueTypeMismatch,
+ message:
+ """Can't assign spread entry values of type '${type}' to map entry values of type '${type2}'.""" +
+ labeler.originMessages,
+ arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ DartType
+ _type)> templateSpreadMapEntryTypeMismatch = const Template<
+ Message Function(DartType _type)>(
+ messageTemplate:
+ r"""Unexpected type '#type' of a map spread entry. Expected 'dynamic' or a Map.""",
+ withArguments: _withArgumentsSpreadMapEntryTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeSpreadMapEntryTypeMismatch =
+ const Code<Message Function(DartType _type)>(
+ "SpreadMapEntryTypeMismatch",
+ templateSpreadMapEntryTypeMismatch,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadMapEntryTypeMismatch(DartType _type) {
+ TypeLabeler labeler = new TypeLabeler();
+ List<Object> typeParts = labeler.labelType(_type);
+ String type = typeParts.join();
+ return new Message(codeSpreadMapEntryTypeMismatch,
+ message:
+ """Unexpected type '${type}' of a map spread entry. Expected 'dynamic' or a Map.""" +
+ labeler.originMessages,
+ arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
DartType
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index a8245b2..e938d69 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -84,6 +84,8 @@
final Ticker ticker;
+ final bool outlineOnly;
+
Set<Uri> invalidatedUris = new Set<Uri>();
DillTarget dillLoadedData;
@@ -96,17 +98,25 @@
bool hasToCheckPackageUris = false;
Map<Uri, List<DiagnosticMessageFromJson>> remainingComponentProblems =
new Map<Uri, List<DiagnosticMessageFromJson>>();
+ List<Component> modulesToLoad;
+
+ static final Uri debugExprUri =
+ new Uri(scheme: "org-dartlang-debug", path: "synthetic_debug_expression");
KernelTarget userCode;
IncrementalCompiler.fromComponent(
- this.context, Component this.componentToInitializeFrom)
+ this.context, Component this.componentToInitializeFrom,
+ [bool outlineOnly])
: ticker = context.options.ticker,
- initializeFromDillUri = null;
+ initializeFromDillUri = null,
+ this.outlineOnly = outlineOnly ?? false;
- IncrementalCompiler(this.context, [this.initializeFromDillUri])
+ IncrementalCompiler(this.context,
+ [this.initializeFromDillUri, bool outlineOnly])
: ticker = context.options.ticker,
- componentToInitializeFrom = null;
+ componentToInitializeFrom = null,
+ this.outlineOnly = outlineOnly ?? false;
@override
Future<Component> computeDelta(
@@ -315,22 +325,39 @@
});
}
+ /// Internal method.
+ void invalidateNotKeptUserBuilders(Set<Uri> invalidatedUris) {
+ throw UnimplementedError("Not implemented yet.");
+ }
+
+ /// Internal method.
+ Future loadEnsureLoadedComponents(
+ Set<Uri> reusedLibraryUris, List<LibraryBuilder> reusedLibraries) async {
+ throw UnimplementedError("Not implemented yet.");
+ }
+
+ /// Internal method.
void reissueLibraryProblems(
Set<Library> allLibraries, List<Library> compiledLibraries) {
// The newly-compiled libraries have issued problems already. Re-issue
- // problems for the libraries that weren't re-compiled.
+ // problems for the libraries that weren't re-compiled (ignore compile
+ // expression problems)
allLibraries.removeAll(compiledLibraries);
for (Library library in allLibraries) {
if (library.problemsAsJson?.isNotEmpty == true) {
for (String jsonString in library.problemsAsJson) {
DiagnosticMessageFromJson message =
new DiagnosticMessageFromJson.fromJson(jsonString);
+ if (message.uri == debugExprUri) {
+ continue;
+ }
context.options.reportDiagnosticMessage(message);
}
}
}
}
+ /// Internal method.
/// Re-issue problems on the component and return the filtered list.
List<String> reissueComponentProblems(Component componentWithDill) {
// These problems have already been reported.
@@ -364,6 +391,7 @@
return new List<String>.from(issuedProblems);
}
+ /// Internal method.
Uri getPartFileUri(
Uri parentFileUri, LibraryPart part, UriTranslator uriTranslator) {
Uri fileUri = parentFileUri.resolve(part.partUri);
@@ -376,6 +404,7 @@
return fileUri;
}
+ /// Internal method.
/// Compute the transitive closure.
///
/// As a side-effect, this also cleans-up now-unreferenced builders as well as
@@ -448,6 +477,7 @@
return result;
}
+ /// Internal method.
void removeLibraryFromRemainingComponentProblems(
Library lib, UriTranslator uriTranslator) {
remainingComponentProblems.remove(lib.fileUri);
@@ -458,6 +488,7 @@
}
}
+ /// Internal method.
int prepareSummary(List<int> summaryBytes, UriTranslator uriTranslator,
CompilerContext c, IncrementalCompilerData data) {
dillLoadedData = new DillTarget(ticker, uriTranslator, c.options.target);
@@ -475,6 +506,7 @@
return bytesLength;
}
+ /// Internal method.
// This procedure will try to load the dill file and will crash if it cannot.
Future<int> initializeFromDill(UriTranslator uriTranslator, CompilerContext c,
IncrementalCompilerData data) async {
@@ -515,6 +547,7 @@
return bytesLength;
}
+ /// Internal method.
void saveComponentProblems(IncrementalCompilerData data) {
if (data.component.problemsAsJson != null) {
for (String jsonString in data.component.problemsAsJson) {
@@ -528,6 +561,7 @@
}
}
+ /// Internal method.
// This procedure will set up compiler from [componentToInitializeFrom].
void initializeFromComponent(UriTranslator uriTranslator, CompilerContext c,
IncrementalCompilerData data) {
@@ -559,6 +593,7 @@
ticker.logMs("Ran initializeFromComponent");
}
+ /// Internal method.
void appendLibraries(IncrementalCompilerData data, int bytesLength) {
if (data.component != null) {
dillLoadedData.loader
@@ -597,9 +632,6 @@
if (!isLegalIdentifier(name)) return null;
}
- Uri debugExprUri = new Uri(
- scheme: "org-dartlang-debug", path: "synthetic_debug_expression");
-
KernelLibraryBuilder debugLibrary = new KernelLibraryBuilder(
libraryUri,
debugExprUri,
@@ -673,6 +705,7 @@
});
}
+ /// Internal method.
List<LibraryBuilder> computeReusedLibraries(
Set<Uri> invalidatedUris, UriTranslator uriTranslator,
{Set<LibraryBuilder> notReused}) {
@@ -796,7 +829,20 @@
invalidatedUris.add(uri);
}
+ @override
+ void invalidateAllSources() {
+ throw UnimplementedError("Not implemented yet.");
+ }
+
+ @override
+ void setModulesToLoadOnNextComputeDelta(List<Component> components) {
+ throw UnimplementedError("Not implemented yet.");
+ }
+
+ /// Internal method.
void recordInvalidatedImportUrisForTesting(List<Uri> uris) {}
+
+ /// Internal method.
void recordTemporaryFileForTesting(Uri uri) {}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 123e9f2..7655108 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -2554,7 +2554,7 @@
if (entry is MapEntry) {
entries.add(entry);
} else if (entry is SpreadElement) {
- entries.add(new SpreadMapEntry(entry.expression));
+ entries.add(new SpreadMapEntry(entry.expression, entry.isNullAware));
} else {
addProblem(
fasta.templateExpectedAfterButGot.withArguments(':'),
@@ -3655,13 +3655,10 @@
@override
void endIfControlFlow(Token token) {
debugEvent("endIfControlFlow");
- // TODO(danrubel) implement control flow support
-
var entry = pop();
- pop(); // parenthesized expression
+ var condition = pop(); // parenthesized expression
Token ifToken = pop();
- if (entry != invalidCollectionElement) {
- // TODO(danrubel): Replace this with control flow structure
+ if (!library.loader.target.enableControlFlowCollections) {
// TODO(danrubel): Report a more user friendly error message
// when an experiment is not enabled
handleRecoverableError(
@@ -3669,24 +3666,28 @@
ifToken,
ifToken);
push(invalidCollectionElement);
- } else {
- // TODO(danrubel): Remove this when unified collections enabled
+ return;
+ }
+ if (entry == invalidCollectionElement) {
push(invalidCollectionElement);
+ return;
+ }
+ transformCollections = true;
+ if (entry is MapEntry) {
+ push(forest.ifMapEntry(toValue(condition), entry, null, ifToken));
+ } else {
+ push(forest.ifElement(toValue(condition), toValue(entry), null, ifToken));
}
}
@override
void endIfElseControlFlow(Token token) {
debugEvent("endIfElseControlFlow");
- // TODO(danrubel) implement control flow support
-
var elseEntry = pop(); // else entry
var thenEntry = pop(); // then entry
- pop(); // parenthesized expression
+ var condition = pop(); // parenthesized expression
Token ifToken = pop();
- if (thenEntry != invalidCollectionElement &&
- elseEntry != invalidCollectionElement) {
- // TODO(danrubel): Replace this with control flow support
+ if (!library.loader.target.enableControlFlowCollections) {
// TODO(danrubel): Report a more user friendly error message
// when an experiment is not enabled
handleRecoverableError(
@@ -3694,23 +3695,57 @@
ifToken,
ifToken);
push(invalidCollectionElement);
- } else {
- // TODO(danrubel): Remove when unified collections enabled
+ return;
+ }
+ if (thenEntry == invalidCollectionElement ||
+ elseEntry == invalidCollectionElement) {
push(invalidCollectionElement);
+ return;
+ }
+ transformCollections = true;
+ if (thenEntry is MapEntry) {
+ if (elseEntry is MapEntry) {
+ push(forest.ifMapEntry(
+ toValue(condition), thenEntry, elseEntry, ifToken));
+ } else if (elseEntry is SpreadElement) {
+ push(forest.ifMapEntry(
+ toValue(condition),
+ thenEntry,
+ new SpreadMapEntry(elseEntry.expression, elseEntry.isNullAware),
+ ifToken));
+ } else {
+ push(invalidCollectionElement);
+ }
+ } else if (elseEntry is MapEntry) {
+ if (thenEntry is SpreadElement) {
+ push(forest.ifMapEntry(
+ toValue(condition),
+ new SpreadMapEntry(thenEntry.expression, thenEntry.isNullAware),
+ elseEntry,
+ ifToken));
+ } else {
+ push(invalidCollectionElement);
+ }
+ } else {
+ push(forest.ifElement(
+ toValue(condition), toValue(thenEntry), toValue(elseEntry), ifToken));
}
}
@override
void handleSpreadExpression(Token spreadToken) {
debugEvent("SpreadExpression");
+ var expression = pop();
if (!library.loader.target.enableSpreadCollections) {
- return handleRecoverableError(
+ handleRecoverableError(
fasta.templateUnexpectedToken.withArguments(spreadToken),
spreadToken,
spreadToken);
+ push(invalidCollectionElement);
+ return;
}
transformCollections = true;
- push(forest.spreadElement(popForValue(), spreadToken));
+ push(forest.spreadElement(toValue(expression), spreadToken));
}
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/collections.dart b/pkg/front_end/lib/src/fasta/kernel/collections.dart
index b830d4b..74f6789 100644
--- a/pkg/front_end/lib/src/fasta/kernel/collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/collections.dart
@@ -204,11 +204,14 @@
/// A spread element in a map literal.
class SpreadMapEntry extends TreeNode with _FakeMapEntryMixin {
Expression expression;
+ bool isNullAware;
- SpreadMapEntry(this.expression) {
+ SpreadMapEntry(this.expression, this.isNullAware) {
expression?.parent = this;
}
+ accept(TreeVisitor<Object> v) => v.defaultTreeNode(this);
+
@override
visitChildren(Visitor<Object> v) {
expression?.accept(v);
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index eee9401..005376d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -53,7 +53,7 @@
import 'body_builder.dart' show LabelTarget;
-import 'collections.dart' show SpreadElement;
+import 'collections.dart' show IfElement, IfMapEntry, SpreadElement;
import 'kernel_expression_generator.dart'
show
@@ -283,6 +283,20 @@
}
@override
+ Expression ifElement(Expression condition, Expression then,
+ Expression otherwise, Token token) {
+ return new IfElement(condition, then, otherwise)
+ ..fileOffset = offsetForToken(token);
+ }
+
+ @override
+ MapEntry ifMapEntry(
+ Expression condition, MapEntry then, MapEntry otherwise, Token token) {
+ return new IfMapEntry(condition, then, otherwise)
+ ..fileOffset = offsetForToken(token);
+ }
+
+ @override
AssertInitializer assertInitializer(
Token assertKeyword,
Token leftParenthesis,
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index e024458..8cf916f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -190,6 +190,12 @@
Expression spreadElement(Expression expression, Token token);
+ Expression ifElement(
+ Expression condition, Expression then, Expression otherwise, Token token);
+
+ MapEntry ifMapEntry(
+ Expression condition, MapEntry then, MapEntry otherwise, Token token);
+
/// Return a representation of an assert that appears in a constructor's
/// initializer list.
Object assertInitializer(Token assertKeyword, Token leftParenthesis,
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index d108638..a678e10 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -11,6 +11,10 @@
@override
void defaultExpression(Expression node, DartType typeContext) {
+ if (node is IfElement) {
+ visitIfElement(node, typeContext);
+ return;
+ }
unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
inferrer.helper.uri);
}
@@ -21,6 +25,11 @@
inferrer.helper.uri);
}
+ visitIfElement(IfElement node, DartType typeContext) {
+ node.parent.replaceChild(node,
+ new InvalidExpression('unhandled if element in collection literal'));
+ }
+
@override
void visitInvalidExpression(InvalidExpression node, DartType typeContext) {}
@@ -165,11 +174,13 @@
node.arguments,
isConst: node.isConst);
inferrer.storeInferredType(node, inferenceResult.type);
- KernelLibraryBuilder inferrerLibrary = inferrer.library;
- if (!hasExplicitTypeArguments && inferrerLibrary is KernelLibraryBuilder) {
- inferrerLibrary.checkBoundsInConstructorInvocation(
- node, inferrer.typeSchemaEnvironment,
- inferred: true);
+ if (!inferrer.isTopLevel) {
+ KernelLibraryBuilder library = inferrer.library;
+ if (!hasExplicitTypeArguments) {
+ library.checkBoundsInConstructorInvocation(
+ node, inferrer.typeSchemaEnvironment,
+ inferred: true);
+ }
}
}
@@ -224,11 +235,13 @@
node.argumentJudgments,
isConst: node.isConst);
node.inferredType = inferenceResult.type;
- KernelLibraryBuilder inferrerLibrary = inferrer.library;
- if (!hadExplicitTypeArguments && inferrerLibrary is KernelLibraryBuilder) {
- inferrerLibrary.checkBoundsInFactoryInvocation(
- node, inferrer.typeSchemaEnvironment,
- inferred: true);
+ if (!inferrer.isTopLevel) {
+ KernelLibraryBuilder library = inferrer.library;
+ if (!hadExplicitTypeArguments) {
+ library.checkBoundsInFactoryInvocation(
+ node, inferrer.typeSchemaEnvironment,
+ inferred: true);
+ }
}
return null;
}
@@ -638,12 +651,15 @@
inferrer.inferStatement(node.body);
}
- DartType getSpreadElementType(DartType spreadType) {
+ DartType getSpreadElementType(DartType spreadType, bool isNullAware) {
if (spreadType is InterfaceType) {
InterfaceType supertype = inferrer.typeSchemaEnvironment
.getTypeAsInstanceOf(spreadType, inferrer.coreTypes.iterableClass);
- if (supertype == null) return null;
- return supertype.typeArguments[0];
+ if (supertype != null) return supertype.typeArguments[0];
+ if (spreadType.classNode == inferrer.coreTypes.nullClass && isNullAware) {
+ return spreadType;
+ }
+ return null;
}
if (spreadType is DynamicType) return const DynamicType();
return null;
@@ -691,8 +707,9 @@
spreadTypes[i] = spreadType;
}
// Use 'dynamic' for error recovery.
- actualTypes
- .add(getSpreadElementType(spreadType) ?? const DynamicType());
+ actualTypes.add(
+ getSpreadElementType(spreadType, judgment.isNullAware) ??
+ const DynamicType());
} else {
inferrer.inferExpression(judgment, inferredTypeArgument,
inferenceNeeded || typeChecksNeeded,
@@ -725,34 +742,39 @@
Expression item = node.expressions[i];
if (item is SpreadElement) {
DartType spreadType = spreadTypes[i];
- DartType spreadElementType = getSpreadElementType(spreadType);
+ DartType spreadElementType =
+ getSpreadElementType(spreadType, item.isNullAware);
if (spreadElementType == null) {
- node.replaceChild(
- node.expressions[i],
- inferrer.helper.desugarSyntheticExpression(inferrer.helper
- .buildProblem(
- templateSpreadTypeMismatch.withArguments(spreadType),
- item.expression.fileOffset,
- 1)));
+ if (spreadType is InterfaceType &&
+ spreadType.classNode == inferrer.coreTypes.nullClass &&
+ !item.isNullAware) {
+ node.replaceChild(
+ node.expressions[i],
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(messageNonNullAwareSpreadIsNull,
+ item.expression.fileOffset, 1)));
+ } else {
+ node.replaceChild(
+ node.expressions[i],
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(
+ templateSpreadTypeMismatch.withArguments(spreadType),
+ item.expression.fileOffset,
+ 1)));
+ }
} else if (spreadType is DynamicType) {
inferrer.ensureAssignable(inferrer.coreTypes.iterableClass.rawType,
spreadType, item.expression, item.expression.fileOffset);
} else if (spreadType is InterfaceType) {
- if (spreadType.classNode == inferrer.coreTypes.nullClass) {
- // TODO(dmitryas): Handle this case when null-aware spreads are
- // supported by the parser.
- } else {
- if (!inferrer.isAssignable(
- node.typeArgument, spreadElementType)) {
- node.replaceChild(
- node.expressions[i],
- inferrer.helper.desugarSyntheticExpression(inferrer.helper
- .buildProblem(
- templateSpreadElementTypeMismatch.withArguments(
- spreadElementType, node.typeArgument),
- item.expression.fileOffset,
- 1)));
- }
+ if (!inferrer.isAssignable(node.typeArgument, spreadElementType)) {
+ node.replaceChild(
+ node.expressions[i],
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(
+ templateSpreadElementTypeMismatch.withArguments(
+ spreadElementType, node.typeArgument),
+ item.expression.fileOffset,
+ 1)));
}
}
} else {
@@ -763,11 +785,12 @@
}
}
node.inferredType = new InterfaceType(listClass, [inferredTypeArgument]);
- KernelLibraryBuilder inferrerLibrary = inferrer.library;
- if (inferenceNeeded && inferrerLibrary is KernelLibraryBuilder) {
- inferrerLibrary.checkBoundsInListLiteral(
- node, inferrer.typeSchemaEnvironment,
- inferred: true);
+ if (!inferrer.isTopLevel) {
+ KernelLibraryBuilder library = inferrer.library;
+ if (inferenceNeeded) {
+ library.checkBoundsInListLiteral(node, inferrer.typeSchemaEnvironment,
+ inferred: true);
+ }
}
return null;
@@ -787,6 +810,28 @@
return null;
}
+ // Calculates the key and the value type of a spread map entry of type
+ // spreadMapEntryType and stores them in output in positions offset and offset
+ // + 1. If the types can't be calculated, for example, if spreadMapEntryType
+ // is a function type, the original values in output are preserved.
+ void storeSpreadMapEntryElementTypes(DartType spreadMapEntryType,
+ bool isNullAware, List<DartType> output, int offset) {
+ if (spreadMapEntryType is InterfaceType) {
+ InterfaceType supertype = inferrer.typeSchemaEnvironment
+ .getTypeAsInstanceOf(spreadMapEntryType, inferrer.coreTypes.mapClass);
+ if (supertype != null) {
+ output[offset] = supertype.typeArguments[0];
+ output[offset + 1] = supertype.typeArguments[1];
+ } else if (spreadMapEntryType.classNode == inferrer.coreTypes.nullClass &&
+ isNullAware) {
+ output[offset] = output[offset + 1] = spreadMapEntryType;
+ }
+ }
+ if (spreadMapEntryType is DynamicType) {
+ output[offset] = output[offset + 1] = const DynamicType();
+ }
+ }
+
void visitMapLiteralJudgment(MapLiteralJudgment node, DartType typeContext) {
var mapClass = inferrer.coreTypes.mapClass;
var mapType = mapClass.thisType;
@@ -799,26 +844,31 @@
(node.valueType is ImplicitTypeArgument));
bool inferenceNeeded = node.keyType is ImplicitTypeArgument;
KernelLibraryBuilder library = inferrer.library;
- if (library != null &&
- library.loader.target.enableSetLiterals &&
- inferenceNeeded &&
- node.entries.isEmpty) {
- // Ambiguous set/map literal
- DartType context =
- inferrer.typeSchemaEnvironment.unfutureType(typeContext);
- if (context is InterfaceType) {
- if (inferrer.classHierarchy.isSubtypeOf(
- context.classNode, inferrer.coreTypes.iterableClass) &&
- !inferrer.classHierarchy
- .isSubtypeOf(context.classNode, inferrer.coreTypes.mapClass)) {
- // Set literal
- SetLiteralJudgment setLiteral = new SetLiteralJudgment([],
- typeArgument: const ImplicitTypeArgument(), isConst: node.isConst)
- ..fileOffset = node.fileOffset;
- node.parent.replaceChild(node, setLiteral);
- visitSetLiteralJudgment(setLiteral, typeContext);
- node.inferredType = setLiteral.inferredType;
- return;
+ bool typeContextIsMap = false;
+ bool typeContextIsIterable = false;
+ if (!inferrer.isTopLevel) {
+ if (library.loader.target.enableSetLiterals && inferenceNeeded) {
+ // Ambiguous set/map literal
+ DartType context =
+ inferrer.typeSchemaEnvironment.unfutureType(typeContext);
+ if (context is InterfaceType) {
+ typeContextIsMap = inferrer.classHierarchy
+ .isSubtypeOf(context.classNode, inferrer.coreTypes.mapClass);
+ typeContextIsIterable = inferrer.classHierarchy
+ .isSubtypeOf(context.classNode, inferrer.coreTypes.iterableClass);
+ if (node.entries.isEmpty &&
+ typeContextIsIterable &&
+ !typeContextIsMap) {
+ // Set literal
+ SetLiteralJudgment setLiteral = new SetLiteralJudgment([],
+ typeArgument: const ImplicitTypeArgument(),
+ isConst: node.isConst)
+ ..fileOffset = node.fileOffset;
+ node.parent.replaceChild(node, setLiteral);
+ visitSetLiteralJudgment(setLiteral, typeContext);
+ node.inferredType = setLiteral.inferredType;
+ return;
+ }
}
}
}
@@ -840,34 +890,137 @@
}
List<Expression> cachedKeys = new List(node.entries.length);
List<Expression> cachedValues = new List(node.entries.length);
+ List<DartType> spreadMapEntryTypes =
+ typeChecksNeeded ? new List<DartType>(node.entries.length) : null;
for (int i = 0; i < node.entries.length; i++) {
MapEntry entry = node.entries[i];
- if (entry is! SpreadMapEntry) {
+ if (entry is! SpreadMapEntry && entry is! IfMapEntry) {
cachedKeys[i] = node.entries[i].key;
cachedValues[i] = node.entries[i].value;
}
}
+ int iterableSpreadOffset = -1;
+ int mapSpreadOffset = -1;
+ int mapEntryOffset = -1;
if (inferenceNeeded || typeChecksNeeded) {
- for (MapEntry entry in node.entries) {
+ DartType spreadTypeContext = const UnknownType();
+ if (typeContextIsIterable && !typeContextIsMap) {
+ spreadTypeContext = inferrer.typeSchemaEnvironment
+ .getTypeAsInstanceOf(typeContext, inferrer.coreTypes.iterableClass);
+ } else if (!typeContextIsIterable && typeContextIsMap) {
+ spreadTypeContext =
+ new InterfaceType(inferrer.coreTypes.mapClass, inferredTypes);
+ }
+ for (int i = 0; i < node.entries.length; ++i) {
+ MapEntry entry = node.entries[i];
if (entry is SpreadMapEntry) {
- actualTypes.add(const BottomType());
- actualTypes.add(inferrer.coreTypes.nullClass.rawType);
- continue;
- }
- Expression key = entry.key;
- inferrer.inferExpression(key, inferredKeyType, true,
- isVoidAllowed: true);
- actualTypes.add(getInferredType(key, inferrer));
- Expression value = entry.value;
- inferrer.inferExpression(value, inferredValueType, true,
- isVoidAllowed: true);
- actualTypes.add(getInferredType(value, inferrer));
- if (inferenceNeeded) {
- formalTypes.addAll(mapType.typeArguments);
+ DartType spreadMapEntryType = inferrer.inferExpression(
+ entry.expression,
+ spreadTypeContext,
+ inferenceNeeded || typeChecksNeeded,
+ isVoidAllowed: true);
+ if (inferenceNeeded) {
+ formalTypes.add(mapType.typeArguments[0]);
+ formalTypes.add(mapType.typeArguments[1]);
+ }
+ if (typeChecksNeeded) {
+ spreadMapEntryTypes[i] = spreadMapEntryType;
+ }
+
+ bool isMap = inferrer.typeSchemaEnvironment.isSubtypeOf(
+ spreadMapEntryType, inferrer.coreTypes.mapClass.rawType);
+ bool isSet = inferrer.typeSchemaEnvironment.isSubtypeOf(
+ spreadMapEntryType, inferrer.coreTypes.iterableClass.rawType);
+
+ if (isMap && !isSet) {
+ mapSpreadOffset = entry.expression.fileOffset;
+ }
+ if (!isMap && isSet) {
+ iterableSpreadOffset = entry.expression.fileOffset;
+ }
+
+ // Use 'dynamic' for error recovery.
+ int length = actualTypes.length;
+ actualTypes.add(const DynamicType());
+ actualTypes.add(const DynamicType());
+ storeSpreadMapEntryElementTypes(
+ spreadMapEntryType, entry.isNullAware, actualTypes, length);
+ } else if (entry is IfMapEntry) {
+ node.entries[i] = new MapEntry(
+ new InvalidExpression('unimplemented spread entry')
+ ..fileOffset = node.fileOffset,
+ new NullLiteral());
+ actualTypes.add(const DynamicType());
+ actualTypes.add(const DynamicType());
+ } else {
+ Expression key = entry.key;
+ inferrer.inferExpression(key, inferredKeyType, true,
+ isVoidAllowed: true);
+ actualTypes.add(getInferredType(key, inferrer));
+ Expression value = entry.value;
+ inferrer.inferExpression(value, inferredValueType, true,
+ isVoidAllowed: true);
+ actualTypes.add(getInferredType(value, inferrer));
+ if (inferenceNeeded) {
+ formalTypes.addAll(mapType.typeArguments);
+ }
+
+ mapEntryOffset = entry.fileOffset;
}
}
}
if (inferenceNeeded) {
+ bool canBeSet =
+ mapSpreadOffset == -1 && mapEntryOffset == -1 && !typeContextIsMap;
+ bool canBeMap = iterableSpreadOffset == -1 && !typeContextIsIterable;
+ if (canBeSet && !canBeMap) {
+ List<Expression> setElements = <Expression>[];
+ for (int i = 0; i < node.entries.length; ++i) {
+ SpreadMapEntry entry = node.entries[i];
+ setElements
+ .add(new SpreadElement(entry.expression, entry.isNullAware));
+ }
+ SetLiteralJudgment setLiteral = new SetLiteralJudgment(setElements,
+ typeArgument: const ImplicitTypeArgument(), isConst: node.isConst)
+ ..fileOffset = node.fileOffset;
+ node.parent.replaceChild(node, setLiteral);
+ visitSetLiteralJudgment(setLiteral, typeContext);
+ node.inferredType = setLiteral.inferredType;
+ return;
+ }
+ if (canBeSet && canBeMap && node.entries.isNotEmpty) {
+ node.parent.replaceChild(
+ node,
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(messageCantDisambiguateNotEnoughInformation,
+ node.fileOffset, 1)));
+ node.inferredType = const BottomType();
+ return;
+ }
+ if (!canBeSet && !canBeMap) {
+ if (!inferrer.isTopLevel) {
+ LocatedMessage iterableContextMessage = messageSpreadElement
+ .withLocation(library.uri, iterableSpreadOffset, 1);
+ LocatedMessage mapContextMessage = messageSpreadMapElement
+ .withLocation(library.uri, mapSpreadOffset, 1);
+ List<LocatedMessage> context = <LocatedMessage>[];
+ if (iterableSpreadOffset < mapSpreadOffset) {
+ context.add(iterableContextMessage);
+ context.add(mapContextMessage);
+ } else {
+ context.add(mapContextMessage);
+ context.add(iterableContextMessage);
+ }
+ node.parent.replaceChild(
+ node,
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(messageCantDisambiguateAmbiguousInformation,
+ node.fileOffset, 1,
+ context: context)));
+ }
+ node.inferredType = const BottomType();
+ return;
+ }
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
mapType,
mapClass.typeParameters,
@@ -888,33 +1041,97 @@
}
if (typeChecksNeeded) {
for (int i = 0; i < node.entries.length; ++i) {
- Expression keyJudgment = cachedKeys[i];
- if (keyJudgment == null) {
- node.entries[i] = new MapEntry(
- new InvalidExpression('unimplemented spread entry')
- ..fileOffset = node.fileOffset,
- new NullLiteral()..parent = node);
- continue;
- }
- inferrer.ensureAssignable(node.keyType, actualTypes[2 * i], keyJudgment,
- keyJudgment.fileOffset,
- isVoidAllowed: node.keyType is VoidType);
+ MapEntry entry = node.entries[i];
+ List<DartType> spreadMapEntryElementTypes = new List<DartType>(2);
+ if (entry is SpreadMapEntry) {
+ DartType spreadMapEntryType = spreadMapEntryTypes[i];
+ spreadMapEntryElementTypes[0] = spreadMapEntryElementTypes[1] = null;
+ storeSpreadMapEntryElementTypes(spreadMapEntryType, entry.isNullAware,
+ spreadMapEntryElementTypes, 0);
+ if (spreadMapEntryElementTypes[0] == null) {
+ if (spreadMapEntryType is InterfaceType &&
+ spreadMapEntryType.classNode == inferrer.coreTypes.nullClass &&
+ !entry.isNullAware) {
+ node.replaceChild(
+ node.entries[i],
+ new MapEntry(
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(messageNonNullAwareSpreadIsNull,
+ entry.expression.fileOffset, 1)),
+ new NullLiteral()));
+ } else {
+ node.replaceChild(
+ node.entries[i],
+ new MapEntry(
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(
+ templateSpreadMapEntryTypeMismatch
+ .withArguments(spreadMapEntryType),
+ entry.expression.fileOffset,
+ 1)),
+ new NullLiteral()));
+ }
+ } else if (spreadMapEntryType is DynamicType) {
+ inferrer.ensureAssignable(
+ inferrer.coreTypes.mapClass.rawType,
+ spreadMapEntryType,
+ entry.expression,
+ entry.expression.fileOffset);
+ } else if (spreadMapEntryType is InterfaceType) {
+ Expression keyError;
+ Expression valueError;
+ if (!inferrer.isAssignable(
+ node.keyType, spreadMapEntryElementTypes[0])) {
+ keyError = inferrer.helper.desugarSyntheticExpression(
+ inferrer.helper.buildProblem(
+ templateSpreadMapEntryElementKeyTypeMismatch
+ .withArguments(
+ spreadMapEntryElementTypes[0], node.keyType),
+ entry.expression.fileOffset,
+ 1));
+ }
+ if (!inferrer.isAssignable(
+ node.valueType, spreadMapEntryElementTypes[1])) {
+ valueError = inferrer.helper.desugarSyntheticExpression(
+ inferrer.helper.buildProblem(
+ templateSpreadMapEntryElementValueTypeMismatch
+ .withArguments(
+ spreadMapEntryElementTypes[1], node.valueType),
+ entry.expression.fileOffset,
+ 1));
+ }
+ if (keyError != null || valueError != null) {
+ keyError ??= new NullLiteral();
+ valueError ??= new NullLiteral();
+ node.replaceChild(
+ node.entries[i], new MapEntry(keyError, valueError));
+ }
+ }
+ } else {
+ Expression keyJudgment = cachedKeys[i];
+ if (keyJudgment != null) {
+ inferrer.ensureAssignable(node.keyType, actualTypes[2 * i],
+ keyJudgment, keyJudgment.fileOffset,
+ isVoidAllowed: node.keyType is VoidType);
- Expression valueJudgment = cachedValues[i];
- inferrer.ensureAssignable(node.valueType, actualTypes[2 * i + 1],
- valueJudgment, valueJudgment.fileOffset,
- isVoidAllowed: node.valueType is VoidType);
+ Expression valueJudgment = cachedValues[i];
+ inferrer.ensureAssignable(node.valueType, actualTypes[2 * i + 1],
+ valueJudgment, valueJudgment.fileOffset,
+ isVoidAllowed: node.valueType is VoidType);
+ }
+ }
}
}
node.inferredType =
new InterfaceType(mapClass, [inferredKeyType, inferredValueType]);
- KernelLibraryBuilder inferrerLibrary = inferrer.library;
- // Either both [_declaredKeyType] and [_declaredValueType] are omitted or
- // none of them, so we may just check one.
- if (inferenceNeeded && inferrerLibrary is KernelLibraryBuilder) {
- inferrerLibrary.checkBoundsInMapLiteral(
- node, inferrer.typeSchemaEnvironment,
- inferred: true);
+ if (!inferrer.isTopLevel) {
+ KernelLibraryBuilder library = inferrer.library;
+ // Either both [_declaredKeyType] and [_declaredValueType] are omitted or
+ // none of them, so we may just check one.
+ if (inferenceNeeded) {
+ library.checkBoundsInMapLiteral(node, inferrer.typeSchemaEnvironment,
+ inferred: true);
+ }
}
}
@@ -1173,8 +1390,9 @@
spreadTypes[i] = spreadType;
}
// Use 'dynamic' for error recovery.
- actualTypes
- .add(getSpreadElementType(spreadType) ?? const DynamicType());
+ actualTypes.add(
+ getSpreadElementType(spreadType, judgment.isNullAware) ??
+ const DynamicType());
} else {
inferrer.inferExpression(judgment, inferredTypeArgument,
inferenceNeeded || typeChecksNeeded,
@@ -1207,34 +1425,39 @@
Expression item = node.expressions[i];
if (item is SpreadElement) {
DartType spreadType = spreadTypes[i];
- DartType spreadElementType = getSpreadElementType(spreadType);
+ DartType spreadElementType =
+ getSpreadElementType(spreadType, item.isNullAware);
if (spreadElementType == null) {
- node.replaceChild(
- node.expressions[i],
- inferrer.helper.desugarSyntheticExpression(inferrer.helper
- .buildProblem(
- templateSpreadTypeMismatch.withArguments(spreadType),
- item.expression.fileOffset,
- 1)));
+ if (spreadType is InterfaceType &&
+ spreadType.classNode == inferrer.coreTypes.nullClass &&
+ !item.isNullAware) {
+ node.replaceChild(
+ node.expressions[i],
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(messageNonNullAwareSpreadIsNull,
+ item.expression.fileOffset, 1)));
+ } else {
+ node.replaceChild(
+ node.expressions[i],
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(
+ templateSpreadTypeMismatch.withArguments(spreadType),
+ item.expression.fileOffset,
+ 1)));
+ }
} else if (spreadType is DynamicType) {
inferrer.ensureAssignable(inferrer.coreTypes.iterableClass.rawType,
spreadType, item.expression, item.expression.fileOffset);
} else if (spreadType is InterfaceType) {
- if (spreadType.classNode == inferrer.coreTypes.nullClass) {
- // TODO(dmitryas): Handle this case when null-aware spreads are
- // supported by the parser.
- } else {
- if (!inferrer.isAssignable(
- node.typeArgument, spreadElementType)) {
- node.replaceChild(
- node.expressions[i],
- inferrer.helper.desugarSyntheticExpression(inferrer.helper
- .buildProblem(
- templateSpreadElementTypeMismatch.withArguments(
- spreadElementType, node.typeArgument),
- item.expression.fileOffset,
- 1)));
- }
+ if (!inferrer.isAssignable(node.typeArgument, spreadElementType)) {
+ node.replaceChild(
+ node.expressions[i],
+ inferrer.helper.desugarSyntheticExpression(inferrer.helper
+ .buildProblem(
+ templateSpreadElementTypeMismatch.withArguments(
+ spreadElementType, node.typeArgument),
+ item.expression.fileOffset,
+ 1)));
}
}
} else {
@@ -1245,17 +1468,16 @@
}
}
node.inferredType = new InterfaceType(setClass, [inferredTypeArgument]);
- KernelLibraryBuilder inferrerLibrary = inferrer.library;
- if (inferenceNeeded && inferrerLibrary is KernelLibraryBuilder) {
- inferrerLibrary.checkBoundsInSetLiteral(
- node, inferrer.typeSchemaEnvironment,
- inferred: true);
- }
+ if (!inferrer.isTopLevel) {
+ KernelLibraryBuilder library = inferrer.library;
+ if (inferenceNeeded) {
+ library.checkBoundsInSetLiteral(node, inferrer.typeSchemaEnvironment,
+ inferred: true);
+ }
- KernelLibraryBuilder library = inferrer.library;
- if (library != null &&
- !library.loader.target.backendTarget.supportsSetLiterals) {
- inferrer.helper.transformSetLiterals = true;
+ if (!library.loader.target.backendTarget.supportsSetLiterals) {
+ inferrer.helper.transformSetLiterals = true;
+ }
}
}
@@ -1273,10 +1495,7 @@
if (write is StaticSet) {
writeContext = write.target.setterType;
writeMember = write.target;
- if (writeMember is ShadowField && writeMember.inferenceNode != null) {
- writeMember.inferenceNode.resolve();
- writeMember.inferenceNode = null;
- }
+ TypeInferenceEngine.resolveInferenceNode(writeMember);
}
node._inferRhs(inferrer, readType, writeContext);
node._replaceWithDesugared();
@@ -1286,10 +1505,7 @@
@override
void visitStaticGet(StaticGet node, DartType typeContext) {
var target = node.target;
- if (target is ShadowField && target.inferenceNode != null) {
- target.inferenceNode.resolve();
- target.inferenceNode = null;
- }
+ TypeInferenceEngine.resolveInferenceNode(target);
var type = target.getterType;
if (target is Procedure && target.kind == ProcedureKind.Method) {
type = inferrer.instantiateTearOff(type, typeContext, node);
@@ -1516,11 +1732,13 @@
node.initializer = replacedInitializer;
}
}
- KernelLibraryBuilder inferrerLibrary = inferrer.library;
- if (node._implicitlyTyped && inferrerLibrary is KernelLibraryBuilder) {
- inferrerLibrary.checkBoundsInVariableDeclaration(
- node, inferrer.typeSchemaEnvironment,
- inferred: true);
+ if (!inferrer.isTopLevel) {
+ KernelLibraryBuilder library = inferrer.library;
+ if (node._implicitlyTyped) {
+ library.checkBoundsInVariableDeclaration(
+ node, inferrer.typeSchemaEnvironment,
+ inferred: true);
+ }
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
index 05513ad..91ae51b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
@@ -28,11 +28,18 @@
@override
DartType defaultExpression(Expression node, TypeInferrerImpl inferrer) {
+ if (node is IfElement) {
+ return visitIfElement(node, inferrer);
+ }
unhandled("${node.runtimeType}", "getInferredType", node.fileOffset,
inferrer.uri);
return const InvalidType();
}
+ DartType visitIfElement(IfElement node, TypeInferrerImpl inferrer) {
+ return const BottomType();
+ }
+
@override
DartType visitIntLiteral(IntLiteral node, TypeInferrerImpl inferrer) {
return inferrer.coreTypes.intClass.rawType;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index e43378a..80b38e4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -1025,18 +1025,24 @@
// Report an error.
String declaredMemberName =
'${declaredMember.enclosingClass.name}.${declaredMember.name.name}';
+ String interfaceMemberName =
+ '${interfaceMember.enclosingClass.name}.${interfaceMember.name.name}';
Message message;
int fileOffset;
if (declaredParameter == null) {
message = templateOverrideTypeMismatchReturnType.withArguments(
- declaredMemberName, declaredType, interfaceType);
+ declaredMemberName,
+ declaredType,
+ interfaceType,
+ interfaceMemberName);
fileOffset = declaredMember.fileOffset;
} else {
message = templateOverrideTypeMismatchParameter.withArguments(
declaredParameter.name,
declaredMemberName,
declaredType,
- interfaceType);
+ interfaceType,
+ interfaceMemberName);
fileOffset = declaredParameter.fileOffset;
}
library.addProblem(message, fileOffset, noLength, declaredMember.fileUri,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index b85bee7..56c6840 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -35,6 +35,12 @@
import '../fasta_codes.dart'
show
+ LocatedMessage,
+ messageCantDisambiguateAmbiguousInformation,
+ messageCantDisambiguateNotEnoughInformation,
+ messageNonNullAwareSpreadIsNull,
+ messageSpreadElement,
+ messageSpreadMapElement,
messageSwitchExpressionNotAssignableCause,
messageVoidExpression,
noLength,
@@ -43,6 +49,9 @@
templateForInLoopTypeNotIterable,
templateIntegerLiteralIsOutOfRange,
templateSpreadElementTypeMismatch,
+ templateSpreadMapEntryElementKeyTypeMismatch,
+ templateSpreadMapEntryElementValueTypeMismatch,
+ templateSpreadMapEntryTypeMismatch,
templateSpreadTypeMismatch,
templateSwitchExpressionNotAssignable,
templateWebLiteralCannotBeRepresentedExactly;
@@ -73,7 +82,8 @@
import 'body_builder.dart' show combineStatements;
-import 'collections.dart' show SpreadElement, SpreadMapEntry;
+import 'collections.dart'
+ show IfElement, SpreadElement, IfMapEntry, SpreadMapEntry;
import 'implicit_type_argument.dart' show ImplicitTypeArgument;
@@ -994,15 +1004,6 @@
void setInferredType(
TypeInferenceEngine engine, Uri uri, DartType inferredType);
-
- static void resolveInferenceNode(Member member) {
- if (member is ShadowMember) {
- if (member.inferenceNode != null) {
- member.inferenceNode.resolve();
- member.inferenceNode = null;
- }
- }
- }
}
/// Shadow object for [MethodInvocation].
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
index 27244cd..1afd831 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -4,25 +4,32 @@
library fasta.transform_collections;
+import 'dart:core' hide MapEntry;
+
import 'package:kernel/ast.dart'
show
Arguments,
Block,
BlockExpression,
+ Class,
DartType,
DynamicType,
Expression,
ExpressionStatement,
+ Field,
ForInStatement,
IfStatement,
InterfaceType,
InvalidExpression,
ListLiteral,
+ MapEntry,
+ MapLiteral,
MethodInvocation,
Name,
Not,
NullLiteral,
Procedure,
+ PropertyGet,
SetLiteral,
Statement,
StaticInvocation,
@@ -34,7 +41,7 @@
import 'package:kernel/visitor.dart' show Transformer;
-import 'collections.dart' show SpreadElement;
+import 'collections.dart' show SpreadElement, SpreadMapEntry;
import '../source/source_loader.dart' show SourceLoader;
@@ -46,6 +53,11 @@
final Procedure setFactory;
final Procedure setAdd;
final Procedure objectEquals;
+ final Procedure mapEntries;
+ final Procedure mapPut;
+ final Class mapEntryClass;
+ final Field mapEntryKey;
+ final Field mapEntryValue;
static Procedure _findSetFactory(CoreTypes coreTypes) {
Procedure factory = coreTypes.index.getMember('dart:core', 'Set', '');
@@ -59,7 +71,16 @@
setFactory = _findSetFactory(loader.coreTypes),
setAdd = loader.coreTypes.index.getMember('dart:core', 'Set', 'add'),
objectEquals =
- loader.coreTypes.index.getMember('dart:core', 'Object', '==');
+ loader.coreTypes.index.getMember('dart:core', 'Object', '=='),
+ mapEntries =
+ loader.coreTypes.index.getMember('dart:core', 'Map', 'get:entries'),
+ mapPut = loader.coreTypes.index.getMember('dart:core', 'Map', '[]='),
+ mapEntryClass =
+ loader.coreTypes.index.getClass('dart:core', 'MapEntry'),
+ mapEntryKey =
+ loader.coreTypes.index.getMember('dart:core', 'MapEntry', 'key'),
+ mapEntryValue =
+ loader.coreTypes.index.getMember('dart:core', 'MapEntry', 'value');
TreeNode _translateListOrSet(
Expression node, DartType elementType, List<Expression> elements,
@@ -174,4 +195,98 @@
return _translateListOrSet(node, node.typeArgument, node.expressions,
isConst: node.isConst, isSet: true);
}
+
+ @override
+ TreeNode visitMapLiteral(MapLiteral node) {
+ int i = 0;
+ for (; i < node.entries.length; ++i) {
+ if (node.entries[i] is SpreadMapEntry) break;
+ node.entries[i] = node.entries[i].accept(this)..parent = node;
+ }
+
+ if (i == node.entries.length) return node;
+
+ if (node.isConst) {
+ // We don't desugar const maps here. REmove spread for now so that they
+ // don't leak out.
+ for (; i < node.entries.length; ++i) {
+ MapEntry entry = node.entries[i];
+ if (entry is SpreadMapEntry) {
+ entry.parent.replaceChild(
+ entry,
+ new MapEntry(
+ InvalidExpression('unimplemented spread element')
+ ..fileOffset = entry.fileOffset,
+ new NullLiteral()));
+ }
+ }
+ }
+
+ VariableDeclaration map = new VariableDeclaration.forValue(
+ new MapLiteral([], keyType: node.keyType, valueType: node.valueType),
+ type: new InterfaceType(
+ coreTypes.mapClass, [node.keyType, node.valueType]),
+ isFinal: true);
+ List<Statement> body = [map];
+ for (int j = 0; j < i; ++j) {
+ body.add(new ExpressionStatement(new MethodInvocation(
+ new VariableGet(map),
+ new Name('[]='),
+ new Arguments([node.entries[j].key, node.entries[j].value]),
+ mapPut)));
+ }
+ DartType mapEntryType =
+ new InterfaceType(mapEntryClass, [node.keyType, node.valueType]);
+ for (; i < node.entries.length; ++i) {
+ MapEntry entry = node.entries[i];
+ if (entry is SpreadMapEntry) {
+ Expression value = entry.expression.accept(this);
+ // Null-aware spreads require testing the subexpression's value.
+ VariableDeclaration temp;
+ if (entry.isNullAware) {
+ temp = new VariableDeclaration.forValue(value,
+ type: coreTypes.mapClass.rawType);
+ body.add(temp);
+ value = new VariableGet(temp);
+ }
+
+ VariableDeclaration elt =
+ new VariableDeclaration(null, type: mapEntryType, isFinal: true);
+ Statement statement = new ForInStatement(
+ elt,
+ new PropertyGet(value, new Name('entries'), mapEntries),
+ new ExpressionStatement(new MethodInvocation(
+ new VariableGet(map),
+ new Name('[]='),
+ new Arguments([
+ new PropertyGet(
+ new VariableGet(elt), new Name('key'), mapEntryKey),
+ new PropertyGet(
+ new VariableGet(elt), new Name('value'), mapEntryValue)
+ ]),
+ mapPut)));
+
+ if (entry.isNullAware) {
+ statement = new IfStatement(
+ new Not(new MethodInvocation(
+ new VariableGet(temp),
+ new Name('=='),
+ new Arguments([new NullLiteral()]),
+ objectEquals)),
+ statement,
+ null);
+ }
+ body.add(statement);
+ } else {
+ entry = entry.accept(this);
+ body.add(new ExpressionStatement(new MethodInvocation(
+ new VariableGet(map),
+ new Name('[]='),
+ new Arguments([entry.key, entry.value]),
+ mapPut)));
+ }
+ }
+
+ return new BlockExpression(new Block(body), new VariableGet(map));
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart b/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart
index cb85853..c29fb9a 100644
--- a/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart
@@ -10,7 +10,7 @@
/// [simpleEntry] is the first step for parsing a literal entry
/// without any control flow or spread collection operator.
-const LiteralEntryInfo simpleEntry = const LiteralEntryInfo(true);
+const LiteralEntryInfo simpleEntry = const LiteralEntryInfo(true, 0);
/// [LiteralEntryInfo] represents steps for processing an entry
/// in a literal list, map, or set. These steps will handle parsing
@@ -35,7 +35,11 @@
/// or `false` if this object's [parse] method should be called.
final bool hasEntry;
- const LiteralEntryInfo(this.hasEntry);
+ /// Used for recovery, this indicates
+ /// +1 for an `if` condition and -1 for `else`.
+ final int ifConditionDelta;
+
+ const LiteralEntryInfo(this.hasEntry, this.ifConditionDelta);
/// Parse the control flow and spread collection aspects of this entry.
Token parse(Token token, Parser parser) {
diff --git a/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
index f62ba96..1ea0bf7 100644
--- a/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
@@ -19,7 +19,7 @@
class ForCondition extends LiteralEntryInfo {
bool inStyle;
- ForCondition() : super(false);
+ ForCondition() : super(false, 0);
@override
Token parse(Token token, Parser parser) {
@@ -96,7 +96,7 @@
/// A step for parsing a literal list, set, or map entry
/// as the "for" control flow's expression.
class ForEntry extends LiteralEntryInfo {
- const ForEntry() : super(true);
+ const ForEntry() : super(true, 0);
@override
LiteralEntryInfo computeNext(Token token) {
@@ -107,7 +107,7 @@
/// A step for parsing a literal list, set, or map entry
/// as the "for-in" control flow's expression.
class ForInEntry extends LiteralEntryInfo {
- const ForInEntry() : super(true);
+ const ForInEntry() : super(true, 0);
@override
LiteralEntryInfo computeNext(Token token) {
@@ -116,7 +116,7 @@
}
class ForComplete extends LiteralEntryInfo {
- const ForComplete() : super(false);
+ const ForComplete() : super(false, 0);
@override
Token parse(Token token, Parser parser) {
@@ -126,7 +126,7 @@
}
class ForInComplete extends LiteralEntryInfo {
- const ForInComplete() : super(false);
+ const ForInComplete() : super(false, 0);
@override
Token parse(Token token, Parser parser) {
@@ -137,7 +137,7 @@
/// The first step when processing an `if` control flow collection entry.
class IfCondition extends LiteralEntryInfo {
- const IfCondition() : super(false);
+ const IfCondition() : super(false, 1);
@override
Token parse(Token token, Parser parser) {
@@ -174,14 +174,14 @@
/// A step for parsing a literal list, set, or map entry
/// as the `if` control flow's then-expression.
class IfEntry extends LiteralEntryInfo {
- const IfEntry() : super(true);
+ const IfEntry() : super(true, 0);
@override
LiteralEntryInfo computeNext(Token token) => const IfComplete();
}
class IfComplete extends LiteralEntryInfo {
- const IfComplete() : super(false);
+ const IfComplete() : super(false, 0);
@override
Token parse(Token token, Parser parser) {
@@ -199,7 +199,7 @@
/// A step for parsing the `else` portion of an `if` control flow.
class IfElse extends LiteralEntryInfo {
- const IfElse() : super(false);
+ const IfElse() : super(false, -1);
@override
Token parse(Token token, Parser parser) {
@@ -235,7 +235,7 @@
}
class ElseEntry extends LiteralEntryInfo {
- const ElseEntry() : super(true);
+ const ElseEntry() : super(true, 0);
@override
LiteralEntryInfo computeNext(Token token) {
@@ -244,7 +244,7 @@
}
class IfElseComplete extends LiteralEntryInfo {
- const IfElseComplete() : super(false);
+ const IfElseComplete() : super(false, 0);
@override
Token parse(Token token, Parser parser) {
@@ -255,7 +255,7 @@
/// The first step when processing a spread entry.
class SpreadOperator extends LiteralEntryInfo {
- const SpreadOperator() : super(false);
+ const SpreadOperator() : super(false, 0);
@override
Token parse(Token token, Parser parser) {
@@ -271,7 +271,7 @@
LiteralEntryInfo nestedStep;
final LiteralEntryInfo lastStep;
- Nested(this.nestedStep, this.lastStep) : super(false);
+ Nested(this.nestedStep, this.lastStep) : super(false, 0);
@override
bool get hasEntry => nestedStep.hasEntry;
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 260fe3e..774daef 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -2416,10 +2416,50 @@
int count = 0;
bool old = mayParseFunctionExpressions;
mayParseFunctionExpressions = false;
- do {
- token = parseInitializer(token.next);
+ Token next = begin;
+ while (true) {
+ token = parseInitializer(next);
++count;
- } while (optional(',', token.next));
+ next = token.next;
+ if (!optional(',', next)) {
+ if (!next.isKeywordOrIdentifier) {
+ break;
+ }
+ // Recovery: Found an identifier which could be
+ // 1) missing preceding `,` thus it's another initializer, or
+ // 2) missing preceding `;` thus it's a class member, or
+ // 3) missing preceding '{' thus it's a statement
+ if (optional('assert', next)) {
+ next = next.next;
+ if (!optional('(', next)) {
+ break;
+ }
+ // Looks like assert expression ... fall through to insert comma
+ } else {
+ if (optional('this', next)) {
+ next = next.next;
+ if (!optional('.', next)) {
+ break;
+ }
+ next = next.next;
+ if (!next.isKeywordOrIdentifier) {
+ break;
+ }
+ }
+ next = next.next;
+ if (!optional('=', next)) {
+ break;
+ }
+ // Looks like field assignment... fall through to insert comma
+ }
+ // TODO(danrubel): Consider enhancing this to indicate that we are
+ // expecting one of `,` or `;` or `{`
+ reportRecoverableError(
+ token, fasta.templateExpectedAfterButGot.withArguments(','));
+ next = rewriter.insertToken(
+ token, new SyntheticToken(TokenType.COMMA, token.next.charOffset));
+ }
+ }
mayParseFunctionExpressions = old;
listener.endInitializers(count, begin, token.next);
return token;
@@ -4211,7 +4251,17 @@
token = next;
break;
}
- token = parseListOrSetLiteralEntry(token);
+ int ifCount = 0;
+ LiteralEntryInfo info = computeLiteralEntry(token);
+ while (info != null) {
+ if (info.hasEntry) {
+ token = parseExpression(token);
+ } else {
+ token = info.parse(token, this);
+ }
+ ifCount += info.ifConditionDelta;
+ info = info.computeNext(token);
+ }
next = token.next;
++count;
if (!optional(',', next)) {
@@ -4236,10 +4286,11 @@
}
// This looks like the start of an expression.
// Report an error, insert the comma, and continue parsing.
- next = rewriteAndRecover(
- token,
- fasta.templateExpectedButGot.withArguments(','),
- new SyntheticToken(TokenType.COMMA, next.offset));
+ var comma = new SyntheticToken(TokenType.COMMA, next.offset);
+ var message = ifCount > 0
+ ? fasta.messageExpectedElseOrComma
+ : fasta.templateExpectedButGot.withArguments(',');
+ next = rewriteAndRecover(token, message, comma);
}
token = next;
}
@@ -4248,19 +4299,6 @@
return token;
}
- Token parseListOrSetLiteralEntry(Token token) {
- LiteralEntryInfo info = computeLiteralEntry(token);
- while (info != null) {
- if (info.hasEntry) {
- token = parseExpression(token);
- } else {
- token = info.parse(token, this);
- }
- info = info.computeNext(token);
- }
- return token;
- }
-
/// This method parses the portion of a set or map literal that starts with
/// the left curly brace when there are no leading type arguments.
Token parseLiteralSetOrMapSuffix(Token token, Token constKeyword) {
@@ -4280,6 +4318,7 @@
bool hasSetEntry;
while (true) {
+ int ifCount = 0;
LiteralEntryInfo info = computeLiteralEntry(token);
if (info == simpleEntry) {
// TODO(danrubel): Remove this section and use the while loop below
@@ -4304,6 +4343,7 @@
} else {
token = info.parse(token, this);
}
+ ifCount += info.ifConditionDelta;
info = info.computeNext(token);
}
}
@@ -4327,10 +4367,12 @@
if (looksLikeLiteralEntry(next)) {
// If this looks like the start of an expression,
// then report an error, insert the comma, and continue parsing.
- token = rewriteAndRecover(
- token,
- fasta.templateExpectedButGot.withArguments(','),
- new SyntheticToken(TokenType.COMMA, next.offset));
+ // TODO(danrubel): Consider better error message
+ var comma = new SyntheticToken(TokenType.COMMA, next.offset);
+ var message = ifCount > 0
+ ? fasta.messageExpectedElseOrComma
+ : fasta.templateExpectedButGot.withArguments(',');
+ token = rewriteAndRecover(token, message, comma);
} else {
reportRecoverableError(
next, fasta.templateExpectedButGot.withArguments('}'));
diff --git a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
index 96b90c3..65db7c3 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
@@ -47,12 +47,7 @@
import '../kernel/kernel_library_builder.dart' show KernelLibraryBuilder;
import '../kernel/kernel_shadow_ast.dart'
- show
- ShadowClass,
- ShadowField,
- ShadowMember,
- ShadowProcedure,
- VariableDeclarationJudgment;
+ show ShadowClass, ShadowField, ShadowProcedure, VariableDeclarationJudgment;
import '../messages.dart'
show
@@ -160,7 +155,7 @@
DartType overriddenType;
if (resolvedCandidate is SyntheticAccessor) {
var field = resolvedCandidate._field;
- ShadowMember.resolveInferenceNode(field);
+ TypeInferenceEngine.resolveInferenceNode(field);
overriddenType = field.type;
} else if (resolvedCandidate.function != null) {
switch (resolvedCandidate.kind) {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 94cff43..a3251d6 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -11,6 +11,7 @@
Field,
FunctionType,
InterfaceType,
+ Member,
TypeParameter,
TypeParameterType,
TypedefType,
@@ -25,7 +26,7 @@
import '../kernel/kernel_builder.dart'
show LibraryBuilder, KernelLibraryBuilder;
-import '../kernel/kernel_shadow_ast.dart' show ShadowField;
+import '../kernel/kernel_shadow_ast.dart' show ShadowField, ShadowMember;
import '../messages.dart' show noLength, templateCantInferTypeDueToCircularity;
@@ -272,9 +273,7 @@
if (formal.type == null) {
for (Field field in parent.enclosingClass.fields) {
if (field.name.name == formal.name) {
- if (field is ShadowField && field.inferenceNode != null) {
- field.inferenceNode.resolve();
- }
+ TypeInferenceEngine.resolveInferenceNode(field);
formal.type = field.type;
return;
}
@@ -302,4 +301,13 @@
ShadowField.setInferenceNode(field, node);
staticInferenceNodes.add(node);
}
+
+ static void resolveInferenceNode(Member member) {
+ if (member is ShadowMember) {
+ if (member.inferenceNode != null) {
+ member.inferenceNode.resolve();
+ member.inferenceNode = null;
+ }
+ }
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 3de6c94..98cbf73 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -104,7 +104,6 @@
ExpressionJudgment,
ShadowClass,
ShadowField,
- ShadowMember,
ShadowTypeInferenceEngine,
ShadowTypeInferrer,
VariableDeclarationJudgment,
@@ -545,7 +544,8 @@
TypeInferrerImpl.private(
this.engine, this.uri, bool topLevel, this.thisType, this.library)
- : classHierarchy = engine.classHierarchy,
+ : assert((topLevel && library == null) || (!topLevel && library != null)),
+ classHierarchy = engine.classHierarchy,
instrumentation = topLevel ? null : engine.instrumentation,
typeSchemaEnvironment = engine.typeSchemaEnvironment,
isTopLevel = topLevel,
@@ -1840,7 +1840,7 @@
member = member is SyntheticAccessor
? SyntheticAccessor.getField(member)
: member;
- ShadowMember.resolveInferenceNode(member);
+ TypeInferenceEngine.resolveInferenceNode(member);
return member;
}
}
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index e1f1b74..cfa04f1 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -30,6 +30,10 @@
CannotReadSdkSpecification/analyzerCode: Fail
CannotReadSdkSpecification/example: Fail
CantDetermineConstness/analyzerCode: Fail
+CantDisambiguateAmbiguousInformation/analyzerCode: Fail # There's no analyzer code for that error yet.
+CantDisambiguateAmbiguousInformation/script: Fail # Can't be tested until 'spread-collections' flag is on.
+CantDisambiguateNotEnoughInformation/analyzerCode: Fail # There's no analyzer code for that error yet.
+CantDisambiguateNotEnoughInformation/script: Fail # Can't be tested until 'spread-collections' flag is on.
CantInferPackagesFromManyInputs/analyzerCode: Fail
CantInferPackagesFromManyInputs/example: Fail
CantInferPackagesFromPackageUri/analyzerCode: Fail
@@ -128,6 +132,7 @@
ExpectedClassMember/example: Fail
ExpectedClassOrMixinBody/example: Fail
ExpectedDeclaration/example: Fail
+ExpectedElseOrComma/example: Fail
ExpectedFunctionBody/example: Fail
ExpectedNamedArgument/example: Fail
ExpectedOneExpression/analyzerCode: Fail
@@ -271,6 +276,8 @@
NonConstConstructor/example: Fail
NonConstFactory/example: Fail
NonInstanceTypeVariableUse/example: Fail
+NonNullAwareSpreadIsNull/analyzerCode: Fail # There's no analyzer code for that error yet.
+NonNullAwareSpreadIsNull/script: Fail # Can't be tested until 'spread-collections' flag is on.
NonPartOfDirectiveInPart/script1: Fail
NotAConstantExpression/example: Fail
NotAType/example: Fail
@@ -337,7 +344,12 @@
SourceOutlineSummary/analyzerCode: Fail
SourceOutlineSummary/example: Fail
SpreadElementTypeMismatch/script: Fail # Can't be tested until 'spread-collections' flag is on.
-SpreadTypeMismatch/analyzerCode: Fail # There's not analyzer code for that error yet.
+SpreadMapEntryElementKeyTypeMismatch/script: Fail # Can't be tested until 'spread-collections' flag is on.
+SpreadMapEntryElementValueTypeMismatch/script: Fail # Can't be tested until 'spread-collections' flag is on.
+SpreadMapEntryTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
+SpreadMapEntryTypeMismatch/script1: Fail # Can't be tested until 'spread-collections' flag is on.
+SpreadMapEntryTypeMismatch/script2: Fail # Can't be tested until 'spread-collections' flag is on.
+SpreadTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
SpreadTypeMismatch/script1: Fail # Can't be tested until 'spread-collections' flag is on.
SpreadTypeMismatch/script2: Fail # Can't be tested until 'spread-collections' flag is on.
StackOverflow/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 8b18378..195f967 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -201,6 +201,11 @@
foo();
}
+ExpectedElseOrComma:
+ index: 94
+ template: "Expected 'else' or comma."
+ analyzerCode: ParserErrorCode.EXPECTED_ELSE_OR_COMMA
+
ExpectedBlock:
template: "Expected a block."
tip: "Try adding {}."
@@ -1533,7 +1538,10 @@
-Dname
-Dname=value
- Ignored for now.
+ Define an environment variable in the compile-time environment.
+
+ --no-defines
+ Ignore all -D options and leave environment constants unevaluated.
--
Stop option parsing, the rest of the command line is assumed to be
@@ -2028,12 +2036,12 @@
analyzerCode: INVALID_OVERRIDE_REQUIRED
OverrideTypeMismatchParameter:
- template: "The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type in the overridden method, '#type2'."
+ template: "The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type, '#type2', in the overridden method, '#name3'."
tip: "Change to a supertype of '#type2', or, for a covariant parameter, a subtype."
analyzerCode: INVALID_METHOD_OVERRIDE
OverrideTypeMismatchReturnType:
- template: "The return type of the method '#name' is '#type', which does not match the return type of the overridden method, '#type2'."
+ template: "The return type of the method '#name' is '#type', which does not match the return type, '#type2', of the overridden method, '#name2'."
tip: "Change to a subtype of '#type2'."
analyzerCode: INVALID_METHOD_OVERRIDE
@@ -2928,8 +2936,8 @@
#num3%12.3 ms/libraries.
CantInferTypeDueToInconsistentOverrides:
- template: "Can't infer the type of '#string': overridden members must all have the same type."
- tip: "Specify the type explicitly."
+ template: "Can't infer a type for '#name' as some of the inherited members have different types."
+ tip: "Try adding an explicit type."
analyzerCode: INVALID_METHOD_OVERRIDE
CantInferTypeDueToCircularity:
@@ -3493,3 +3501,65 @@
List<String> a = <String>["foo"];
List<int> b = <int>[...a];
}
+
+SpreadMapEntryTypeMismatch:
+ template: "Unexpected type '#type' of a map spread entry. Expected 'dynamic' or a Map."
+ script:
+ - |
+ main() {
+ int a = 42;
+ var b = <dynamic, dynamic>{...a};
+ }
+ - |
+ main() {
+ int Function() a = null;
+ var b = <dynamic, dynamic>{...a};
+ }
+
+SpreadMapEntryElementKeyTypeMismatch:
+ template: "Can't assign spread entry keys of type '#type' to map entry keys of type '#type2'."
+ analyzerCode: MAP_KEY_TYPE_NOT_ASSIGNABLE
+ script: >
+ main() {
+ Map<String, int> a = <String, int>{"foo": 42};
+ Map<int, int> b = <int, int>{...a};
+ }
+
+SpreadMapEntryElementValueTypeMismatch:
+ template: "Can't assign spread entry values of type '#type' to map entry values of type '#type2'."
+ analyzerCode: MAP_VALUE_TYPE_NOT_ASSIGNABLE
+ script: >
+ main() {
+ Map<String, int> a = <String, int>{"foo": 42};
+ Map<String, String> b = <String, String>{...a};
+ }
+
+CantDisambiguateNotEnoughInformation:
+ template: "Not enough type information to disambiguate between literal set and literal map."
+ tip: "Try providing type arguments for the literal explicitly to disambiguate it."
+ script: >
+ foo(dynamic spread) {
+ var a = {...spread};
+ }
+
+CantDisambiguateAmbiguousInformation:
+ template: "Both Iterable and Map spread elements encountered in ambiguous literal."
+ script: >
+ foo(Iterable<int> iterableSpread, Map<int, int> mapSpread) {
+ var c = {...iterableSpread, ...mapSpread};
+ }
+
+SpreadElement:
+ template: "Iterable spread."
+ severity: CONTEXT
+
+SpreadMapElement:
+ template: "Map spread."
+ severity: CONTEXT
+
+NonNullAwareSpreadIsNull:
+ template: "Can't spread a value with static type Null."
+ script: >
+ main() {
+ <int>[...null];
+ }
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 5ca71fb..b3f5034 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,7 +1,7 @@
name: front_end
# Currently, front_end API is not stable and users should not
# depend on semver semantics when depending on this package.
-version: 0.1.13
+version: 0.1.14
author: Dart Team <misc@dartlang.org>
description: Front end for compilation of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/front_end
@@ -11,14 +11,14 @@
charcode: '^1.1.1'
convert: '^2.0.1'
crypto: '^2.0.2'
- kernel: 0.3.13
+ kernel: 0.3.14
meta: '^1.1.1'
package_config: '^1.0.1'
path: '^1.3.9'
source_span: '^1.2.3'
yaml: '^2.1.12'
dev_dependencies:
- analyzer: 0.35.3
+ analyzer: 0.35.4
args: '>=0.13.0 <2.0.0'
build_integration:
path: ../build_integration
diff --git a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart b/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
index 31ca046..3051815 100644
--- a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
@@ -21,47 +21,49 @@
class CollectionElementTest {
test_closingBrace() {
parseEntry(
- 'before }',
+ '[ }',
[
'handleIdentifier expression',
'handleNoTypeArguments }',
'handleNoArguments }',
'handleSend }',
+ 'handleLiteralList 1, [, null, ]',
],
- errors: [error(codeExpectedIdentifier, 7, 1)],
+ errors: [error(codeExpectedIdentifier, 2, 1)],
expectAfter: '}',
);
}
test_comma() {
parseEntry(
- 'before ,',
+ '[ ,',
[
'handleIdentifier expression',
'handleNoTypeArguments ,',
'handleNoArguments ,',
'handleSend ,',
+ 'handleLiteralList 1, [, null, ]',
],
- errors: [error(codeExpectedIdentifier, 7, 1)],
- expectAfter: ',',
+ errors: [error(codeExpectedIdentifier, 2, 1)],
);
}
test_expression() {
parseEntry(
- 'before x',
+ '[ x',
[
'handleIdentifier x expression',
- 'handleNoTypeArguments ',
- 'handleNoArguments ',
- 'handleSend x ',
+ 'handleNoTypeArguments ]',
+ 'handleNoArguments ]',
+ 'handleSend x ]',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_for() {
parseEntry(
- 'before for (var i = 0; i < 10; ++i) 2',
+ '[ for (var i = 0; i < 10; ++i) 2',
[
'beginForControlFlow null for',
'beginMetadataStar var',
@@ -92,13 +94,14 @@
'handleForInitializerExpressionStatement for ( ; 1',
'handleLiteralInt 2',
'endForControlFlow 2',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_forForFor() {
parseEntry(
- 'before for (var i = 0; i < 10; ++i) for (x in y) for (var a in [6]) 2',
+ '[ for (var i = 0; i < 10; ++i) for (x in y) for (var a in [6]) 2',
[
// for (var i = 0; i < 10; ++i)
'beginForControlFlow null for',
@@ -168,13 +171,14 @@
'endForInControlFlow 2',
// end for
'endForControlFlow 2',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_forIfForElse() {
parseEntry(
- 'before await for (var x in y) if (a) for (b in c) 2 else 7',
+ '[ await for (var x in y) if (a) for (b in c) 2 else 7',
[
// await for (var x in y)
'beginForControlFlow await for',
@@ -228,6 +232,7 @@
'endIfElseControlFlow 7',
// end for
'endForInControlFlow 7',
+ 'handleLiteralList 1, [, null, ]',
],
inAsync: true,
);
@@ -235,7 +240,7 @@
test_forIn() {
parseEntry(
- 'before await for (var x in y) 2',
+ '[ await for (var x in y) 2',
[
'beginForControlFlow await for',
'beginMetadataStar var',
@@ -257,6 +262,7 @@
'handleForInLoopParts await for ( in',
'handleLiteralInt 2',
'endForInControlFlow 2',
+ 'handleLiteralList 1, [, null, ]',
],
inAsync: true,
);
@@ -264,7 +270,7 @@
test_forInSpread() {
parseEntry(
- 'before for (var x in y) ...[2]',
+ '[ for (var x in y) ...[2]',
[
'beginForControlFlow null for',
'beginMetadataStar var',
@@ -289,13 +295,14 @@
'handleLiteralList 1, [, null, ]',
'handleSpreadExpression ...',
'endForInControlFlow ]',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_forSpreadQ() {
parseEntry(
- 'before for (i = 0; i < 10; ++i) ...[2]',
+ '[ for (i = 0; i < 10; ++i) ...[2]',
[
'beginForControlFlow null for',
'handleIdentifier i expression',
@@ -324,26 +331,28 @@
'handleLiteralList 1, [, null, ]',
'handleSpreadExpression ...',
'endForControlFlow ]',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_if() {
parseEntry(
- 'before if (true) 2',
+ '[ if (true) 2',
[
'beginIfControlFlow if',
'handleLiteralBool true',
'handleParenthesizedCondition (',
'handleLiteralInt 2',
'endIfControlFlow 2',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_ifElse() {
parseEntry(
- 'before if (true) 2 else 5',
+ '[ if (true) 2 else 5',
[
'beginIfControlFlow if',
'handleLiteralBool true',
@@ -352,13 +361,14 @@
'handleElseControlFlow else',
'handleLiteralInt 5',
'endIfElseControlFlow 5',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_ifFor() {
parseEntry(
- 'before if (true) for (x in y) 2',
+ '[ if (true) for (x in y) 2',
[
// if (true)
'beginIfControlFlow if',
@@ -384,13 +394,14 @@
'endForInControlFlow 2',
// end if
'endIfControlFlow 2',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_ifForElseIfFor() {
parseEntry(
- 'before if (true) for (a in b) 2 else if (c) for (d in e) 5',
+ '[ if (true) for (a in b) 2 else if (c) for (d in e) 5',
[
// if (true)
'beginIfControlFlow if',
@@ -445,13 +456,14 @@
'endIfControlFlow 5',
// end else
'endIfElseControlFlow 5',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_ifSpreadQ() {
parseEntry(
- 'before if (true) ...?[2]',
+ '[ if (true) ...?[2]',
[
'beginIfControlFlow if',
'handleLiteralBool true',
@@ -461,13 +473,14 @@
'handleLiteralList 1, [, null, ]',
'handleSpreadExpression ...?',
'endIfControlFlow ]',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_ifElseSpreadQ() {
parseEntry(
- 'before if (true) ...?[2] else ... const {5}',
+ '[ if (true) ...?[2] else ... const {5}',
[
'beginIfControlFlow if',
'handleLiteralBool true',
@@ -481,34 +494,38 @@
'handleNoTypeArguments {',
'handleLiteralInt 5',
'handleLiteralSetOrMap 1, {, const, }',
- 'endConstLiteral ',
+ 'endConstLiteral ]',
'handleSpreadExpression ...',
'endIfElseControlFlow }',
+ 'handleLiteralList 1, [, null, ]',
],
);
}
test_intLiteral() {
- parseEntry('before 1', [
+ parseEntry('[ 1', [
'handleLiteralInt 1',
+ 'handleLiteralList 1, [, null, ]',
]);
}
test_spread() {
- parseEntry('before ...[1]', [
+ parseEntry('[ ...[1]', [
'handleNoTypeArguments [',
'handleLiteralInt 1',
'handleLiteralList 1, [, null, ]',
'handleSpreadExpression ...',
+ 'handleLiteralList 1, [, null, ]',
]);
}
test_spreadQ() {
- parseEntry('before ...?[1]', [
+ parseEntry('[ ...?[1]', [
'handleNoTypeArguments [',
'handleLiteralInt 1',
'handleLiteralList 1, [, null, ]',
'handleSpreadExpression ...?',
+ 'handleLiteralList 1, [, null, ]',
]);
}
@@ -518,7 +535,7 @@
final listener = new TestInfoListener();
final parser = new Parser(listener);
if (inAsync != null) parser.asyncState = AsyncModifier.Async;
- final lastConsumed = parser.parseListOrSetLiteralEntry(start);
+ final lastConsumed = parser.parseLiteralListSuffix(start, null);
expect(listener.errors, errors);
try {
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart b/pkg/front_end/testcases/inference/conflicting_fields.dart
new file mode 100644
index 0000000..0c53592
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, 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.
+
+/*@testedFeatures=inference*/
+
+class A {
+ dynamic field1;
+ int field2;
+}
+
+class I {
+ int field1;
+ dynamic field2;
+}
+
+class B extends A implements I {
+ get /*@topType=dynamic*/field1 => null;
+ get /*@topType=dynamic*/field2 => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.hierarchy.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.hierarchy.expect
new file mode 100644
index 0000000..058c190
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.hierarchy.expect
@@ -0,0 +1,99 @@
+Object:
+ superclasses:
+ interfaces:
+ classMembers:
+ Object._haveSameRuntimeType
+ Object.toString
+ Object.runtimeType
+ Object._toString
+ Object._simpleInstanceOf
+ Object._hashCodeRnd
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._objectHashCode
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+A:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ A.field1
+ Object.toString
+ A.field2
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ A.field1
+ A.field2
+
+I:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ I.field1
+ Object.toString
+ I.field2
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ I.field1
+ I.field2
+
+B:
+ superclasses:
+ Object
+ -> A
+ interfaces: I
+ classMembers:
+ B.field1
+ Object.toString
+ B.field2
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ A.field1
+ A.field2
+ interfaceMembers:
+ B.field1
+ Object.toString
+ B.field2
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+ A.field1
+ A.field2
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.expect
new file mode 100644
index 0000000..67e1ae7
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ field dynamic field1 = null;
+ field core::int field2 = null;
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class I extends core::Object {
+ field core::int field1 = null;
+ field dynamic field2 = null;
+ synthetic constructor •() → self::I
+ : super core::Object::•()
+ ;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+ get field1() → dynamic
+ return null;
+ get field2() → dynamic
+ return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.transformed.expect
new file mode 100644
index 0000000..67e1ae7
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.transformed.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ field dynamic field1 = null;
+ field core::int field2 = null;
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class I extends core::Object {
+ field core::int field1 = null;
+ field dynamic field2 = null;
+ synthetic constructor •() → self::I
+ : super core::Object::•()
+ ;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+ get field1() → dynamic
+ return null;
+ get field2() → dynamic
+ return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
new file mode 100644
index 0000000..6963ff2
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ field dynamic field1;
+ field core::int field2;
+ synthetic constructor •() → self::A
+ ;
+}
+class I extends core::Object {
+ field core::int field1;
+ field dynamic field2;
+ synthetic constructor •() → self::I
+ ;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → self::B
+ ;
+ get field1() → dynamic
+ ;
+ get field2() → dynamic
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
new file mode 100644
index 0000000..be7339f
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
@@ -0,0 +1,69 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:18:27: Error: Can't infer a type for 'field1' as some of the inherited members have different types.
+// Try adding an explicit type.
+// get /*@topType=dynamic*/field1 => null;
+// ^
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:27: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+// get /*@topType=dynamic*/field2 => null;
+// ^
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:27: Error: The return type of the method 'B.field2' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.field2'.
+// Change to a subtype of 'int'.
+// get /*@topType=dynamic*/field2 => null;
+// ^
+// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is the overridden method ('field2').
+// int field2;
+// ^
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:18:27: Error: The return type of the method 'B.field1' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'I.field1'.
+// Change to a subtype of 'int'.
+// get /*@topType=dynamic*/field1 => null;
+// ^
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is the overridden method ('field1').
+// int field1;
+// ^
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Error: The return type of the method 'A.field1' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'I.field1'.
+// Change to a subtype of 'int'.
+// dynamic field1;
+// ^
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is the overridden method ('field1').
+// int field1;
+// ^
+// pkg/front_end/testcases/inference/conflicting_fields.dart:17:7: Context: Both members are inherited by the non-abstract class 'B'.
+// class B extends A implements I {
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ field dynamic field1 = null;
+ field core::int field2 = null;
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class I extends core::Object {
+ field core::int field1 = null;
+ field dynamic field2 = null;
+ synthetic constructor •() → self::I
+ : super core::Object::•()
+ ;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → self::B
+ : super self::A::•()
+ ;
+ get field1() → dynamic
+ return null;
+ get field2() → dynamic
+ return null;
+ abstract forwarding-stub set field2(dynamic _) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
index 1812788..fd0caa9 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
@@ -2,17 +2,17 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: Can't infer the type of 'a': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: Can't infer a type for 'a' as some of the inherited members have different types.
+// Try adding an explicit type.
// get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
// ^
//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: Can't infer the type of 'a': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: Can't infer a type for 'a' as some of the inherited members have different types.
+// Try adding an explicit type.
// get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
// ^
//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1.a' is 'dynamic', which does not match the return type of the overridden method, 'I1'.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1.a' is 'dynamic', which does not match the return type, 'I1', of the overridden method, 'A.a'.
// - 'I1' is from 'pkg/front_end/testcases/inference/conflicts_can_happen.dart'.
// Change to a subtype of 'I1'.
// get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
@@ -21,7 +21,7 @@
// final I1 a = null;
// ^
//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1.a' is 'dynamic', which does not match the return type of the overridden method, 'I2'.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1.a' is 'dynamic', which does not match the return type, 'I2', of the overridden method, 'B.a'.
// - 'I2' is from 'pkg/front_end/testcases/inference/conflicts_can_happen.dart'.
// Change to a subtype of 'I2'.
// get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
@@ -30,7 +30,7 @@
// final I2 a = null;
// ^
//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type of the overridden method, 'I2'.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type, 'I2', of the overridden method, 'B.a'.
// - 'I2' is from 'pkg/front_end/testcases/inference/conflicts_can_happen.dart'.
// Change to a subtype of 'I2'.
// get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
@@ -39,7 +39,7 @@
// final I2 a = null;
// ^
//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type of the overridden method, 'I1'.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type, 'I1', of the overridden method, 'A.a'.
// - 'I1' is from 'pkg/front_end/testcases/inference/conflicts_can_happen.dart'.
// Change to a subtype of 'I1'.
// get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
index 9b5a480..292f0b7 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
@@ -2,12 +2,12 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: Can't infer the type of 'a': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: Can't infer a type for 'a' as some of the inherited members have different types.
+// Try adding an explicit type.
// get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
// ^
//
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type of the overridden method, 'I1'.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type, 'I1', of the overridden method, 'A.a'.
// - 'I1' is from 'pkg/front_end/testcases/inference/conflicts_can_happen2.dart'.
// Change to a subtype of 'I1'.
// get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
@@ -16,7 +16,7 @@
// final I1 a = null;
// ^
//
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type of the overridden method, 'I2'.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type, 'I2', of the overridden method, 'B.a'.
// - 'I2' is from 'pkg/front_end/testcases/inference/conflicts_can_happen2.dart'.
// Change to a subtype of 'I2'.
// get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
diff --git a/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect b/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect
index a20bdce..278c138 100644
--- a/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart:13:49: Error: The return type of the method 'B.x' is 'dynamic', which does not match the return type of the overridden method, 'int'.
+// pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart:13:49: Error: The return type of the method 'B.x' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.x'.
// Change to a subtype of 'int'.
// /*error:INVALID_METHOD_OVERRIDE*/ dynamic get x => 3;
// ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
index 9b3d956..6e70f39 100644
--- a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
@@ -9,7 +9,7 @@
// T m<T>(T x) => x;
// ^
//
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:14:64: Error: The return type of the method 'D.m' is 'dynamic', which does not match the return type of the overridden method, 'T'.
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:14:64: Error: The return type of the method 'D.m' is 'dynamic', which does not match the return type, 'T', of the overridden method, 'C.m'.
// Change to a subtype of 'T'.
// /*@error=OverrideTypeMismatchReturnType*/ /*@topType=dynamic*/ m(
// ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect
index 5d175fa..04d3c2c 100644
--- a/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect
@@ -9,7 +9,7 @@
// /*@topType=dynamic*/ m(/*@topType=dynamic*/ x) => x;
// ^
//
-// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:15:54: Error: The parameter 'x' of the method 'D.m' has type 'T', which does not match the corresponding type in the overridden method, 'dynamic'.
+// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:15:54: Error: The parameter 'x' of the method 'D.m' has type 'T', which does not match the corresponding type, 'dynamic', in the overridden method, 'C.m'.
// Change to a supertype of 'dynamic', or, for a covariant parameter, a subtype.
// T /*@error=OverrideTypeMismatchParameter*/ x) =>
// ^
@@ -24,7 +24,7 @@
// dynamic g(int x) => x;
// ^
//
-// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:18:54: Error: The parameter 'x' of the method 'D.g' has type 'T', which does not match the corresponding type in the overridden method, 'int'.
+// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:18:54: Error: The parameter 'x' of the method 'D.g' has type 'T', which does not match the corresponding type, 'int', in the overridden method, 'C.g'.
// Change to a supertype of 'int', or, for a covariant parameter, a subtype.
// T /*@error=OverrideTypeMismatchParameter*/ x) =>
// ^
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
index a48dc1a..01203f7 100644
--- a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
@@ -2,22 +2,22 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: Can't infer the type of 'x': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
// var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
// ^
//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: Can't infer the type of 'x': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
// var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
// ^
//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: Can't infer the type of 'x': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
// var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
// ^
//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F.x' is 'dynamic', which does not match the return type of the overridden method, 'int'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F.x' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.x'.
// Change to a subtype of 'int'.
// var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
// ^
@@ -25,7 +25,7 @@
// int get x;
// ^
//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F.x' is 'dynamic', which does not match the return type of the overridden method, 'num'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F.x' is 'dynamic', which does not match the return type, 'num', of the overridden method, 'C.x'.
// Change to a subtype of 'num'.
// var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
// ^
@@ -33,7 +33,7 @@
// num get x;
// ^
//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G.x' is 'dynamic', which does not match the return type of the overridden method, 'int'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G.x' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.x'.
// Change to a subtype of 'int'.
// var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
// ^
@@ -41,7 +41,7 @@
// int get x;
// ^
//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G.x' is 'dynamic', which does not match the return type of the overridden method, 'double'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G.x' is 'dynamic', which does not match the return type, 'double', of the overridden method, 'D.x'.
// Change to a subtype of 'double'.
// var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
// ^
@@ -49,7 +49,7 @@
// double get x;
// ^
//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H.x' is 'dynamic', which does not match the return type of the overridden method, 'num'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H.x' is 'dynamic', which does not match the return type, 'num', of the overridden method, 'C.x'.
// Change to a subtype of 'num'.
// var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
// ^
@@ -57,7 +57,7 @@
// num get x;
// ^
//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H.x' is 'dynamic', which does not match the return type of the overridden method, 'double'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H.x' is 'dynamic', which does not match the return type, 'double', of the overridden method, 'D.x'.
// Change to a subtype of 'double'.
// var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
// ^
diff --git a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect
index c73b3ed..e47b23c 100644
--- a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect
@@ -2,18 +2,18 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:25:79: Error: Can't infer the type of 'y': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:25:79: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
// /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ y);
// ^
//
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:29:80: Error: Can't infer the type of 'y': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:29:80: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
// {/*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ y});
// ^
//
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:27:80: Error: Can't infer the type of 'y': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:27:80: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
// [/*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ y]);
// ^
//
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect
index a901909..e21b9d9 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart:13:49: Error: The return type of the method 'B.x' is 'dynamic', which does not match the return type of the overridden method, 'int'.
+// pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart:13:49: Error: The return type of the method 'B.x' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.x'.
// Change to a subtype of 'int'.
// /*error:INVALID_METHOD_OVERRIDE*/ dynamic get x => 3;
// ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
index fe82b93..d33cc4c 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:24: Error: The return type of the method 'B.x' is 'int', which does not match the return type of the overridden method, 'double'.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:24: Error: The return type of the method 'B.x' is 'int', which does not match the return type, 'double', of the overridden method, 'A.x'.
// Change to a subtype of 'double'.
// var /*@topType=int*/ x;
// ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
index 57b6ceb..9e226c5 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:24: Error: The return type of the method 'C.x' is 'int', which does not match the return type of the overridden method, 'num'.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:24: Error: The return type of the method 'C.x' is 'int', which does not match the return type, 'num', of the overridden method, 'A.x'.
// Change to a subtype of 'num'.
// var /*@topType=int*/ x;
// ^
diff --git a/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect b/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect
index e11b390..1f70d42 100644
--- a/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/override_check_accessor_after_inference.dart:28:51: Error: The return type of the method 'F.y' is 'A', which does not match the return type of the overridden method, 'B'.
+// pkg/front_end/testcases/override_check_accessor_after_inference.dart:28:51: Error: The return type of the method 'F.y' is 'A', which does not match the return type, 'B', of the overridden method, 'D.y'.
// - 'A' is from 'pkg/front_end/testcases/override_check_accessor_after_inference.dart'.
// - 'B' is from 'pkg/front_end/testcases/override_check_accessor_after_inference.dart'.
// Change to a subtype of 'B'.
@@ -12,7 +12,7 @@
// get y => null; // Inferred type: B
// ^
//
-// pkg/front_end/testcases/override_check_accessor_after_inference.dart:27:57: Error: The parameter 'value' of the method 'F.x' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_after_inference.dart:27:57: Error: The parameter 'value' of the method 'F.x' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'D.x'.
// - 'B' is from 'pkg/front_end/testcases/override_check_accessor_after_inference.dart'.
// - 'A' is from 'pkg/front_end/testcases/override_check_accessor_after_inference.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect b/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect
index 055f4f6..3407e98 100644
--- a/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/override_check_accessor_basic.dart:23:56: Error: The return type of the method 'E.y' is 'Object', which does not match the return type of the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_basic.dart:23:56: Error: The return type of the method 'E.y' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.y'.
// - 'Object' is from 'dart:core'.
// - 'A' is from 'pkg/front_end/testcases/override_check_accessor_basic.dart'.
// Change to a subtype of 'A'.
@@ -12,7 +12,7 @@
// A get y => null;
// ^
//
-// pkg/front_end/testcases/override_check_accessor_basic.dart:22:57: Error: The parameter 'value' of the method 'E.x' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_basic.dart:22:57: Error: The parameter 'value' of the method 'E.x' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.x'.
// - 'B' is from 'pkg/front_end/testcases/override_check_accessor_basic.dart'.
// - 'A' is from 'pkg/front_end/testcases/override_check_accessor_basic.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect b/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect
index 5fa7ead..2b08b5a 100644
--- a/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:25:50: Error: The parameter 'value' of the method 'D.x4' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:25:50: Error: The parameter 'value' of the method 'D.x4' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.x4'.
// - 'B' is from 'pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart'.
// - 'A' is from 'pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
@@ -12,7 +12,7 @@
// void set x4(A value) {}
// ^
//
-// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:27:65: Error: The parameter 'value' of the method 'D.x5' has type 'String', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:27:65: Error: The parameter 'value' of the method 'D.x5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.x5'.
// - 'A' is from 'pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
// covariant String /*@error=OverrideTypeMismatchParameter*/ value) {}
diff --git a/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect b/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect
index 5e5e5ac..0cfd406 100644
--- a/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/override_check_after_inference.dart:24:53: Error: The parameter 'x' of the method 'F.f' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_after_inference.dart:24:53: Error: The parameter 'x' of the method 'F.f' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'D.f'.
// - 'B' is from 'pkg/front_end/testcases/override_check_after_inference.dart'.
// - 'A' is from 'pkg/front_end/testcases/override_check_after_inference.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/override_check_basic.dart.strong.expect b/pkg/front_end/testcases/override_check_basic.dart.strong.expect
index 7810d9b..b7a5ddb 100644
--- a/pkg/front_end/testcases/override_check_basic.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_basic.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/override_check_basic.dart:29:52: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type of the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_basic.dart:29:52: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
// - 'Object' is from 'dart:core'.
// - 'A' is from 'pkg/front_end/testcases/override_check_basic.dart'.
// Change to a subtype of 'A'.
@@ -12,7 +12,7 @@
// A f4() {}
// ^
//
-// pkg/front_end/testcases/override_check_basic.dart:28:55: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_basic.dart:28:55: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
// - 'B' is from 'pkg/front_end/testcases/override_check_basic.dart'.
// - 'A' is from 'pkg/front_end/testcases/override_check_basic.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
@@ -22,7 +22,7 @@
// void f3({A x}) {}
// ^
//
-// pkg/front_end/testcases/override_check_basic.dart:26:54: Error: The parameter 'x' of the method 'E.f1' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_basic.dart:26:54: Error: The parameter 'x' of the method 'E.f1' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f1'.
// - 'B' is from 'pkg/front_end/testcases/override_check_basic.dart'.
// - 'A' is from 'pkg/front_end/testcases/override_check_basic.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
@@ -32,7 +32,7 @@
// void f1(A x) {}
// ^
//
-// pkg/front_end/testcases/override_check_basic.dart:27:55: Error: The parameter 'x' of the method 'E.f2' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_basic.dart:27:55: Error: The parameter 'x' of the method 'E.f2' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f2'.
// - 'B' is from 'pkg/front_end/testcases/override_check_basic.dart'.
// - 'A' is from 'pkg/front_end/testcases/override_check_basic.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect b/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect
index 96fcfd3..d008fb9 100644
--- a/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:25:69: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:25:69: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
// - 'A' is from 'pkg/front_end/testcases/override_check_with_covariant_modifier.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
// void f5(covariant String /*@error=OverrideTypeMismatchParameter*/ x) {}
@@ -11,7 +11,7 @@
// void f5(covariant A x) {}
// ^
//
-// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:24:54: Error: The parameter 'x' of the method 'D.f4' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:24:54: Error: The parameter 'x' of the method 'D.f4' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f4'.
// - 'B' is from 'pkg/front_end/testcases/override_check_with_covariant_modifier.dart'.
// - 'A' is from 'pkg/front_end/testcases/override_check_with_covariant_modifier.dart'.
// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
index 61b9f49..5fceebe 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The return type of the method 'M.y' is 'int', which does not match the return type of the overridden method, 'Object'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The return type of the method 'M.y' is 'int', which does not match the return type, 'Object', of the overridden method, 'I.y'.
// - 'Object' is from 'dart:core'.
// Change to a subtype of 'Object'.
// int y;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
index b92f411..450603a 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M.x' is 'void Function(T)', which does not match the return type of the overridden method, 'void Function(int)'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M.x' is 'void Function(T)', which does not match the return type, 'void Function(int)', of the overridden method, 'B.x'.
// Change to a subtype of 'void Function(int)'.
// T get x => f();
// ^
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
index 47119ca..5a1fc12 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
@@ -2,7 +2,7 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M.y' has type 'int', which does not match the corresponding type in the overridden method, 'Object'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden method, 'I.y'.
// - 'Object' is from 'dart:core'.
// Change to a supertype of 'Object', or, for a covariant parameter, a subtype.
// void set y(int value) {
diff --git a/pkg/front_end/testcases/spread_collection.dart.legacy.expect b/pkg/front_end/testcases/spread_collection.dart.legacy.expect
index 4872fd1..ce54701 100644
--- a/pkg/front_end/testcases/spread_collection.dart.legacy.expect
+++ b/pkg/front_end/testcases/spread_collection.dart.legacy.expect
@@ -18,14 +18,6 @@
// final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
// ^^^^
//
-// pkg/front_end/testcases/spread_collection.dart:7:36: Error: Expected ':' after this.
-// final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
-// ^
-//
-// pkg/front_end/testcases/spread_collection.dart:7:48: Error: Expected ':' after this.
-// final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
-// ^
-//
// pkg/front_end/testcases/spread_collection.dart:8:25: Error: Unexpected token '...'.
// final aSet = <int>{1, ...[2], ...?[3]};
// ^^^
@@ -38,17 +30,13 @@
// final aSetOrMap = {...foo()};
// ^^^
//
-// pkg/front_end/testcases/spread_collection.dart:9:25: Error: Expected ':' after this.
-// final aSetOrMap = {...foo()};
-// ^
-//
import self as self;
import "dart:core" as core;
static method main() → dynamic {
- final dynamic aList = <core::int>[1, <dynamic>[2], <dynamic>[3]];
+ final dynamic aList = <core::int>[1];
final dynamic aMap = <core::int, core::int>{1: 1};
- final dynamic aSet = <core::int>{1, <dynamic>[2], <dynamic>[3]};
+ final dynamic aSet = <core::int>{1};
final dynamic aSetOrMap = <dynamic, dynamic>{};
core::print(aList);
core::print(aSet);
diff --git a/pkg/front_end/testcases/spread_collection.dart.legacy.transformed.expect b/pkg/front_end/testcases/spread_collection.dart.legacy.transformed.expect
index 4872fd1..ce54701 100644
--- a/pkg/front_end/testcases/spread_collection.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/spread_collection.dart.legacy.transformed.expect
@@ -18,14 +18,6 @@
// final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
// ^^^^
//
-// pkg/front_end/testcases/spread_collection.dart:7:36: Error: Expected ':' after this.
-// final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
-// ^
-//
-// pkg/front_end/testcases/spread_collection.dart:7:48: Error: Expected ':' after this.
-// final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
-// ^
-//
// pkg/front_end/testcases/spread_collection.dart:8:25: Error: Unexpected token '...'.
// final aSet = <int>{1, ...[2], ...?[3]};
// ^^^
@@ -38,17 +30,13 @@
// final aSetOrMap = {...foo()};
// ^^^
//
-// pkg/front_end/testcases/spread_collection.dart:9:25: Error: Expected ':' after this.
-// final aSetOrMap = {...foo()};
-// ^
-//
import self as self;
import "dart:core" as core;
static method main() → dynamic {
- final dynamic aList = <core::int>[1, <dynamic>[2], <dynamic>[3]];
+ final dynamic aList = <core::int>[1];
final dynamic aMap = <core::int, core::int>{1: 1};
- final dynamic aSet = <core::int>{1, <dynamic>[2], <dynamic>[3]};
+ final dynamic aSet = <core::int>{1};
final dynamic aSetOrMap = <dynamic, dynamic>{};
core::print(aList);
core::print(aSet);
diff --git a/pkg/front_end/testcases/spread_collection.dart.strong.expect b/pkg/front_end/testcases/spread_collection.dart.strong.expect
index 4b1c6d9..dbfd7b4 100644
--- a/pkg/front_end/testcases/spread_collection.dart.strong.expect
+++ b/pkg/front_end/testcases/spread_collection.dart.strong.expect
@@ -1,4 +1,12 @@
library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/spread_collection.dart:9:21: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+// final aSetOrMap = {...foo()};
+// ^
+//
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
@@ -14,18 +22,30 @@
for (final core::int #t4 in #t3)
#t1.{core::List::add}(#t4);
} =>#t1;
- final core::Map<core::int, core::int> aMap = <core::int, core::int>{1: 1, invalid-expression "unimplemented spread entry": null, invalid-expression "unimplemented spread entry": null};
- final core::Set<core::int> aSet = block {
- final core::Set<core::int> #t5 = col::LinkedHashSet::•<core::int>();
- #t5.{core::Set::add}(1);
- for (final core::int #t6 in <core::int>[2])
- #t5.{core::Set::add}(#t6);
- final dynamic #t7 = <core::int>[3];
+ final core::Map<core::int, core::int> aMap = block {
+ final core::Map<core::int, core::int> #t5 = <core::int, core::int>{};
+ #t5.{core::Map::[]=}(1, 1);
+ for (final core::MapEntry<core::int, core::int> #t6 in <core::int, core::int>{2: 2}.{core::Map::entries})
+ #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
+ final core::Map<dynamic, dynamic> #t7 = <core::int, core::int>{3: 3};
if(!#t7.{core::Object::==}(null))
- for (final core::int #t8 in #t7)
- #t5.{core::Set::add}(#t8);
+ for (final core::MapEntry<core::int, core::int> #t8 in #t7.{core::Map::entries})
+ #t5.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
} =>#t5;
- final core::Map<dynamic, dynamic> aSetOrMap = <dynamic, dynamic>{invalid-expression "unimplemented spread entry": null};
+ final core::Set<core::int> aSet = block {
+ final core::Set<core::int> #t9 = col::LinkedHashSet::•<core::int>();
+ #t9.{core::Set::add}(1);
+ for (final core::int #t10 in <core::int>[2])
+ #t9.{core::Set::add}(#t10);
+ final dynamic #t11 = <core::int>[3];
+ if(!#t11.{core::Object::==}(null))
+ for (final core::int #t12 in #t11)
+ #t9.{core::Set::add}(#t12);
+ } =>#t9;
+ final dynamic aSetOrMap = invalid-expression "pkg/front_end/testcases/spread_collection.dart:9:21: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+ final aSetOrMap = {...foo()};
+ ^";
core::print(aList);
core::print(aSet);
core::print(aMap);
diff --git a/pkg/front_end/testcases/spread_collection.dart.strong.transformed.expect b/pkg/front_end/testcases/spread_collection.dart.strong.transformed.expect
index 4b1c6d9..dbfd7b4 100644
--- a/pkg/front_end/testcases/spread_collection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/spread_collection.dart.strong.transformed.expect
@@ -1,4 +1,12 @@
library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/spread_collection.dart:9:21: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+// final aSetOrMap = {...foo()};
+// ^
+//
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
@@ -14,18 +22,30 @@
for (final core::int #t4 in #t3)
#t1.{core::List::add}(#t4);
} =>#t1;
- final core::Map<core::int, core::int> aMap = <core::int, core::int>{1: 1, invalid-expression "unimplemented spread entry": null, invalid-expression "unimplemented spread entry": null};
- final core::Set<core::int> aSet = block {
- final core::Set<core::int> #t5 = col::LinkedHashSet::•<core::int>();
- #t5.{core::Set::add}(1);
- for (final core::int #t6 in <core::int>[2])
- #t5.{core::Set::add}(#t6);
- final dynamic #t7 = <core::int>[3];
+ final core::Map<core::int, core::int> aMap = block {
+ final core::Map<core::int, core::int> #t5 = <core::int, core::int>{};
+ #t5.{core::Map::[]=}(1, 1);
+ for (final core::MapEntry<core::int, core::int> #t6 in <core::int, core::int>{2: 2}.{core::Map::entries})
+ #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
+ final core::Map<dynamic, dynamic> #t7 = <core::int, core::int>{3: 3};
if(!#t7.{core::Object::==}(null))
- for (final core::int #t8 in #t7)
- #t5.{core::Set::add}(#t8);
+ for (final core::MapEntry<core::int, core::int> #t8 in #t7.{core::Map::entries})
+ #t5.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
} =>#t5;
- final core::Map<dynamic, dynamic> aSetOrMap = <dynamic, dynamic>{invalid-expression "unimplemented spread entry": null};
+ final core::Set<core::int> aSet = block {
+ final core::Set<core::int> #t9 = col::LinkedHashSet::•<core::int>();
+ #t9.{core::Set::add}(1);
+ for (final core::int #t10 in <core::int>[2])
+ #t9.{core::Set::add}(#t10);
+ final dynamic #t11 = <core::int>[3];
+ if(!#t11.{core::Object::==}(null))
+ for (final core::int #t12 in #t11)
+ #t9.{core::Set::add}(#t12);
+ } =>#t9;
+ final dynamic aSetOrMap = invalid-expression "pkg/front_end/testcases/spread_collection.dart:9:21: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+ final aSetOrMap = {...foo()};
+ ^";
core::print(aList);
core::print(aSet);
core::print(aMap);
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart b/pkg/front_end/testcases/spread_collection_inference.dart
index c1cfb85..6225eca 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart
+++ b/pkg/front_end/testcases/spread_collection_inference.dart
@@ -9,6 +9,7 @@
foo() {
List<int> spread = <int>[1, 2, 3];
+ Map<String, int> mapSpread = <String, int>{"foo": 4, "bar": 2};
int notSpreadInt = 42;
int Function() notSpreadFunction = null;
@@ -17,46 +18,121 @@
var /*@type=Set<dynamic>*/ set10 = <dynamic>{... /*@typeArgs=dynamic*/ []};
+ var /*@type=Map<dynamic, dynamic>*/ map10 = <dynamic, dynamic>{...
+ /*@typeArgs=dynamic, dynamic*/ {}};
+
+ var /*@type=Map<dynamic, dynamic>*/ map10ambiguous =
+ /*@typeArgs=dynamic, dynamic*/ {... /*@typeArgs=dynamic, dynamic*/ {}};
+
var /*@type=List<int>*/ lhs20 = /*@typeArgs=int*/ [...spread];
var /*@type=Set<int>*/ set20 = /*@typeArgs=int*/ {...spread, 42};
+ var /*@type=Set<int>*/ set20ambiguous = /*@typeArgs=int*/ {...spread};
+
+ var /*@type=Map<String, int>*/ map20 = /*@typeArgs=String, int*/
+ {...mapSpread, "baz": 42};
+
+ var /*@type=Map<String, int>*/ map20ambiguous = /*@typeArgs=String, int*/
+ {...mapSpread};
+
var /*@type=List<dynamic>*/ lhs21 = /*@typeArgs=dynamic*/ [...(spread as
dynamic)];
var /*@type=Set<dynamic>*/ set21 = /*@typeArgs=dynamic*/ {...(spread as
dynamic), 42};
+ var /*@type=Map<dynamic, dynamic>*/ map21 = /*@typeArgs=dynamic, dynamic*/
+ {...(mapSpread as dynamic), "baz": 42};
+
+ dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+ (mapSpread as dynamic)};
+
List<int> lhs22 = /*@typeArgs=int*/ [... /*@typeArgs=int*/ []];
Set<int> set22 = /*@typeArgs=int*/ {... /*@typeArgs=int*/ [], 42};
+ Set<int> set22ambiguous = /*@typeArgs=int*/ {... /*@typeArgs=int*/ []};
+
+ Map<String, int> map22 = /*@typeArgs=String, int*/
+ {... /*@typeArgs=String, int*/ {}};
+
List<List<int>> lhs23 = /*@typeArgs=List<int>*/ [... /*@typeArgs=List<int>*/
[/*@typeArgs=int*/ []]];
Set<List<int>> set23 = /*@typeArgs=List<int>*/ {... /*@typeArgs=List<int>*/
[/*@typeArgs=int*/ []], <int>[42]};
+ Set<List<int>> set23ambiguous = /*@typeArgs=List<int>*/
+ {... /*@typeArgs=List<int>*/ [/*@typeArgs=int*/ []]};
+
+ Map<String, List<int>> map23 = /*@typeArgs=String, List<int>*/
+ {... /*@typeArgs=String, List<int>*/ {"baz": /*@typeArgs=int*/ []}};
+
+ dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+ spread, ...mapSpread};
+
int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
+ int set30ambiguous = /*@error=InvalidAssignment*/ /*@typeArgs=int*/
+ {...spread};
+
+ int map30 = /*@error=InvalidAssignment*/ /*@typeArgs=String, int*/
+ {...mapSpread, "baz": 42};
+
+ int map30ambiguous = /*@error=InvalidAssignment*/ /*@typeArgs=String, int*/
+ {...mapSpread};
+
List<dynamic> lhs40 = <dynamic>[... /*@error=SpreadTypeMismatch*/
notSpreadInt];
Set<dynamic> set40 = <dynamic>{... /*@error=SpreadTypeMismatch*/
notSpreadInt};
+ Map<dynamic, dynamic> map40 = <dynamic, dynamic>{...
+ /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+
List<dynamic> lhs50 = <dynamic> [... /*@error=SpreadTypeMismatch*/
notSpreadFunction];
Set<dynamic> set50 = <dynamic> {... /*@error=SpreadTypeMismatch*/
notSpreadFunction};
+ Map<dynamic, dynamic> map50 = <dynamic, dynamic>{...
+ /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+
List<String> lhs60 = <String>[... /*@error=SpreadElementTypeMismatch*/
spread];
Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
+
+ Map<int, int> map60 = <int, int>{...
+ /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+
+ Map<String, String> map61 = <String, String>{...
+ /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+
+ List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+
+ Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+
+ var /*@type=Set<dynamic>*/ set71ambiguous = /*@typeArgs=dynamic*/
+ {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+ []};
+
+ Map<String, int> map70 = <String, int>{... /*@error=NonNullAwareSpreadIsNull*/
+ null};
+
+ List<int> lhs80 = <int>[...?null];
+
+ Set<int> set80 = <int>{...?null};
+
+ var /*@type=Set<dynamic>*/ set81ambiguous = /*@typeArgs=dynamic*/
+ {...?null, ... /*@typeArgs=dynamic*/ []};
+
+ Map<String, int> map80 = <String, int>{...?null};
}
main() {}
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart.legacy.expect b/pkg/front_end/testcases/spread_collection_inference.dart.legacy.expect
index 8af1aa9..b419aeb 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart.legacy.expect
+++ b/pkg/front_end/testcases/spread_collection_inference.dart.legacy.expect
@@ -2,102 +2,250 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/spread_collection_inference.dart:15:62: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:16:62: Error: Unexpected token '...'.
// var /*@type=List<dynamic>*/ lhs10 = /*@typeArgs=dynamic*/ [...
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:18:48: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:19:48: Error: Unexpected token '...'.
// var /*@type=Set<dynamic>*/ set10 = <dynamic>{... /*@typeArgs=dynamic*/ []};
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:20:54: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:21:66: Error: Unexpected token '...'.
+// var /*@type=Map<dynamic, dynamic>*/ map10 = <dynamic, dynamic>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:25:37: Error: Unexpected token '...'.
+// /*@typeArgs=dynamic, dynamic*/ {... /*@typeArgs=dynamic, dynamic*/ {}};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:27:54: Error: Unexpected token '...'.
// var /*@type=List<int>*/ lhs20 = /*@typeArgs=int*/ [...spread];
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:22:53: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:29:53: Error: Unexpected token '...'.
// var /*@type=Set<int>*/ set20 = /*@typeArgs=int*/ {...spread, 42};
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:24:62: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:31:62: Error: Unexpected token '...'.
+// var /*@type=Set<int>*/ set20ambiguous = /*@typeArgs=int*/ {...spread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:34:6: Error: Unexpected token '...'.
+// {...mapSpread, "baz": 42};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:37:6: Error: Unexpected token '...'.
+// {...mapSpread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:39:62: Error: Unexpected token '...'.
// var /*@type=List<dynamic>*/ lhs21 = /*@typeArgs=dynamic*/ [...(spread as
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:27:61: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:42:61: Error: Unexpected token '...'.
// var /*@type=Set<dynamic>*/ set21 = /*@typeArgs=dynamic*/ {...(spread as
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:30:40: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:46:6: Error: Unexpected token '...'.
+// {...(mapSpread as dynamic), "baz": 42};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:48:77: Error: Unexpected token '...'.
+// dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:51:40: Error: Unexpected token '...'.
// List<int> lhs22 = /*@typeArgs=int*/ [... /*@typeArgs=int*/ []];
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:32:39: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:53:39: Error: Unexpected token '...'.
// Set<int> set22 = /*@typeArgs=int*/ {... /*@typeArgs=int*/ [], 42};
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:34:52: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:55:48: Error: Unexpected token '...'.
+// Set<int> set22ambiguous = /*@typeArgs=int*/ {... /*@typeArgs=int*/ []};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:58:6: Error: Unexpected token '...'.
+// {... /*@typeArgs=String, int*/ {}};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:60:52: Error: Unexpected token '...'.
// List<List<int>> lhs23 = /*@typeArgs=List<int>*/ [... /*@typeArgs=List<int>*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:37:51: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:63:51: Error: Unexpected token '...'.
// Set<List<int>> set23 = /*@typeArgs=List<int>*/ {... /*@typeArgs=List<int>*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:40:63: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:67:6: Error: Unexpected token '...'.
+// {... /*@typeArgs=List<int>*/ [/*@typeArgs=int*/ []]};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:70:6: Error: Unexpected token '...'.
+// {... /*@typeArgs=String, List<int>*/ {"baz": /*@typeArgs=int*/ []}};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:72:77: Error: Unexpected token '...'.
+// dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:73:13: Error: Unexpected token '...'.
+// spread, ...mapSpread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:75:63: Error: Unexpected token '...'.
// int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:42:63: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:77:63: Error: Unexpected token '...'.
// int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:44:35: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:80:6: Error: Unexpected token '...'.
+// {...spread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:83:6: Error: Unexpected token '...'.
+// {...mapSpread, "baz": 42};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:86:6: Error: Unexpected token '...'.
+// {...mapSpread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:88:35: Error: Unexpected token '...'.
// List<dynamic> lhs40 = <dynamic>[... /*@error=SpreadTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:47:34: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:91:34: Error: Unexpected token '...'.
// Set<dynamic> set40 = <dynamic>{... /*@error=SpreadTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:50:36: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:94:52: Error: Unexpected token '...'.
+// Map<dynamic, dynamic> map40 = <dynamic, dynamic>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:97:36: Error: Unexpected token '...'.
// List<dynamic> lhs50 = <dynamic> [... /*@error=SpreadTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:53:35: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:100:35: Error: Unexpected token '...'.
// Set<dynamic> set50 = <dynamic> {... /*@error=SpreadTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:56:33: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:103:52: Error: Unexpected token '...'.
+// Map<dynamic, dynamic> map50 = <dynamic, dynamic>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:106:33: Error: Unexpected token '...'.
// List<String> lhs60 = <String>[... /*@error=SpreadElementTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:59:32: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:109:32: Error: Unexpected token '...'.
// Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
// ^^^
//
+// pkg/front_end/testcases/spread_collection_inference.dart:111:36: Error: Unexpected token '...'.
+// Map<int, int> map60 = <int, int>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:114:48: Error: Unexpected token '...'.
+// Map<String, String> map61 = <String, String>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:117:27: Error: Unexpected token '...'.
+// List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:119:26: Error: Unexpected token '...'.
+// Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:6: Error: Unexpected token '...'.
+// {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:52: Error: Unexpected token '...'.
+// {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:125:42: Error: Unexpected token '...'.
+// Map<String, int> map70 = <String, int>{... /*@error=NonNullAwareSpreadIsNull*/
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:128:27: Error: Unexpected token '...?'.
+// List<int> lhs80 = <int>[...?null];
+// ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:130:26: Error: Unexpected token '...?'.
+// Set<int> set80 = <int>{...?null};
+// ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:133:6: Error: Unexpected token '...?'.
+// {...?null, ... /*@typeArgs=dynamic*/ []};
+// ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:133:16: Error: Unexpected token '...'.
+// {...?null, ... /*@typeArgs=dynamic*/ []};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:135:42: Error: Unexpected token '...?'.
+// Map<String, int> map80 = <String, int>{...?null};
+// ^^^^
+//
import self as self;
import "dart:core" as core;
static method foo() → dynamic {
core::List<core::int> spread = <core::int>[1, 2, 3];
+ core::Map<core::String, core::int> mapSpread = <core::String, core::int>{"foo": 4, "bar": 2};
core::int notSpreadInt = 42;
() → core::int notSpreadFunction = null;
- dynamic lhs10 = <dynamic>[<dynamic>[]];
- dynamic set10 = <dynamic>{<dynamic>[]};
- dynamic lhs20 = <dynamic>[spread];
- dynamic set20 = <dynamic>{spread, 42};
- dynamic lhs21 = <dynamic>[spread as dynamic];
- dynamic set21 = <dynamic>{spread as dynamic, 42};
- core::List<core::int> lhs22 = <dynamic>[<dynamic>[]];
- core::Set<core::int> set22 = <dynamic>{<dynamic>[], 42};
- core::List<core::List<core::int>> lhs23 = <dynamic>[<dynamic>[<dynamic>[]]];
- core::Set<core::List<core::int>> set23 = <dynamic>{<dynamic>[<dynamic>[]], <core::int>[42]};
- core::int lhs30 = <dynamic>[spread];
- core::int set30 = <dynamic>{spread, 42};
- core::List<dynamic> lhs40 = <dynamic>[notSpreadInt];
- core::Set<dynamic> set40 = <dynamic>{notSpreadInt};
- core::List<dynamic> lhs50 = <dynamic>[notSpreadFunction];
- core::Set<dynamic> set50 = <dynamic>{notSpreadFunction};
- core::List<core::String> lhs60 = <core::String>[spread];
- core::Set<core::String> set60 = <core::String>{spread};
+ dynamic lhs10 = <dynamic>[];
+ dynamic set10 = <dynamic>{};
+ dynamic map10 = <dynamic, dynamic>{};
+ dynamic map10ambiguous = <dynamic, dynamic>{};
+ dynamic lhs20 = <dynamic>[];
+ dynamic set20 = <dynamic>{42};
+ dynamic set20ambiguous = <dynamic, dynamic>{};
+ dynamic map20 = <dynamic, dynamic>{"baz": 42};
+ dynamic map20ambiguous = <dynamic, dynamic>{};
+ dynamic lhs21 = <dynamic>[];
+ dynamic set21 = <dynamic>{42};
+ dynamic map21 = <dynamic, dynamic>{"baz": 42};
+ dynamic map21ambiguous = <dynamic, dynamic>{};
+ core::List<core::int> lhs22 = <dynamic>[];
+ core::Set<core::int> set22 = <dynamic>{42};
+ core::Set<core::int> set22ambiguous = <dynamic, dynamic>{};
+ core::Map<core::String, core::int> map22 = <dynamic, dynamic>{};
+ core::List<core::List<core::int>> lhs23 = <dynamic>[];
+ core::Set<core::List<core::int>> set23 = <dynamic>{<core::int>[42]};
+ core::Set<core::List<core::int>> set23ambiguous = <dynamic, dynamic>{};
+ core::Map<core::String, core::List<core::int>> map23 = <dynamic, dynamic>{};
+ dynamic map24ambiguous = <dynamic, dynamic>{};
+ core::int lhs30 = <dynamic>[];
+ core::int set30 = <dynamic>{42};
+ core::int set30ambiguous = <dynamic, dynamic>{};
+ core::int map30 = <dynamic, dynamic>{"baz": 42};
+ core::int map30ambiguous = <dynamic, dynamic>{};
+ core::List<dynamic> lhs40 = <dynamic>[];
+ core::Set<dynamic> set40 = <dynamic>{};
+ core::Map<dynamic, dynamic> map40 = <dynamic, dynamic>{};
+ core::List<dynamic> lhs50 = <dynamic>[];
+ core::Set<dynamic> set50 = <dynamic>{};
+ core::Map<dynamic, dynamic> map50 = <dynamic, dynamic>{};
+ core::List<core::String> lhs60 = <core::String>[];
+ core::Set<core::String> set60 = <core::String>{};
+ core::Map<core::int, core::int> map60 = <core::int, core::int>{};
+ core::Map<core::String, core::String> map61 = <core::String, core::String>{};
+ core::List<core::int> lhs70 = <core::int>[];
+ core::Set<core::int> set70 = <core::int>{};
+ dynamic set71ambiguous = <dynamic, dynamic>{};
+ core::Map<core::String, core::int> map70 = <core::String, core::int>{};
+ core::List<core::int> lhs80 = <core::int>[];
+ core::Set<core::int> set80 = <core::int>{};
+ dynamic set81ambiguous = <dynamic, dynamic>{};
+ core::Map<core::String, core::int> map80 = <core::String, core::int>{};
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart.legacy.transformed.expect b/pkg/front_end/testcases/spread_collection_inference.dart.legacy.transformed.expect
index 8af1aa9..b419aeb 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/spread_collection_inference.dart.legacy.transformed.expect
@@ -2,102 +2,250 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/spread_collection_inference.dart:15:62: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:16:62: Error: Unexpected token '...'.
// var /*@type=List<dynamic>*/ lhs10 = /*@typeArgs=dynamic*/ [...
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:18:48: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:19:48: Error: Unexpected token '...'.
// var /*@type=Set<dynamic>*/ set10 = <dynamic>{... /*@typeArgs=dynamic*/ []};
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:20:54: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:21:66: Error: Unexpected token '...'.
+// var /*@type=Map<dynamic, dynamic>*/ map10 = <dynamic, dynamic>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:25:37: Error: Unexpected token '...'.
+// /*@typeArgs=dynamic, dynamic*/ {... /*@typeArgs=dynamic, dynamic*/ {}};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:27:54: Error: Unexpected token '...'.
// var /*@type=List<int>*/ lhs20 = /*@typeArgs=int*/ [...spread];
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:22:53: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:29:53: Error: Unexpected token '...'.
// var /*@type=Set<int>*/ set20 = /*@typeArgs=int*/ {...spread, 42};
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:24:62: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:31:62: Error: Unexpected token '...'.
+// var /*@type=Set<int>*/ set20ambiguous = /*@typeArgs=int*/ {...spread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:34:6: Error: Unexpected token '...'.
+// {...mapSpread, "baz": 42};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:37:6: Error: Unexpected token '...'.
+// {...mapSpread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:39:62: Error: Unexpected token '...'.
// var /*@type=List<dynamic>*/ lhs21 = /*@typeArgs=dynamic*/ [...(spread as
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:27:61: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:42:61: Error: Unexpected token '...'.
// var /*@type=Set<dynamic>*/ set21 = /*@typeArgs=dynamic*/ {...(spread as
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:30:40: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:46:6: Error: Unexpected token '...'.
+// {...(mapSpread as dynamic), "baz": 42};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:48:77: Error: Unexpected token '...'.
+// dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:51:40: Error: Unexpected token '...'.
// List<int> lhs22 = /*@typeArgs=int*/ [... /*@typeArgs=int*/ []];
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:32:39: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:53:39: Error: Unexpected token '...'.
// Set<int> set22 = /*@typeArgs=int*/ {... /*@typeArgs=int*/ [], 42};
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:34:52: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:55:48: Error: Unexpected token '...'.
+// Set<int> set22ambiguous = /*@typeArgs=int*/ {... /*@typeArgs=int*/ []};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:58:6: Error: Unexpected token '...'.
+// {... /*@typeArgs=String, int*/ {}};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:60:52: Error: Unexpected token '...'.
// List<List<int>> lhs23 = /*@typeArgs=List<int>*/ [... /*@typeArgs=List<int>*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:37:51: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:63:51: Error: Unexpected token '...'.
// Set<List<int>> set23 = /*@typeArgs=List<int>*/ {... /*@typeArgs=List<int>*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:40:63: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:67:6: Error: Unexpected token '...'.
+// {... /*@typeArgs=List<int>*/ [/*@typeArgs=int*/ []]};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:70:6: Error: Unexpected token '...'.
+// {... /*@typeArgs=String, List<int>*/ {"baz": /*@typeArgs=int*/ []}};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:72:77: Error: Unexpected token '...'.
+// dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:73:13: Error: Unexpected token '...'.
+// spread, ...mapSpread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:75:63: Error: Unexpected token '...'.
// int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:42:63: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:77:63: Error: Unexpected token '...'.
// int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:44:35: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:80:6: Error: Unexpected token '...'.
+// {...spread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:83:6: Error: Unexpected token '...'.
+// {...mapSpread, "baz": 42};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:86:6: Error: Unexpected token '...'.
+// {...mapSpread};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:88:35: Error: Unexpected token '...'.
// List<dynamic> lhs40 = <dynamic>[... /*@error=SpreadTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:47:34: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:91:34: Error: Unexpected token '...'.
// Set<dynamic> set40 = <dynamic>{... /*@error=SpreadTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:50:36: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:94:52: Error: Unexpected token '...'.
+// Map<dynamic, dynamic> map40 = <dynamic, dynamic>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:97:36: Error: Unexpected token '...'.
// List<dynamic> lhs50 = <dynamic> [... /*@error=SpreadTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:53:35: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:100:35: Error: Unexpected token '...'.
// Set<dynamic> set50 = <dynamic> {... /*@error=SpreadTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:56:33: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:103:52: Error: Unexpected token '...'.
+// Map<dynamic, dynamic> map50 = <dynamic, dynamic>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:106:33: Error: Unexpected token '...'.
// List<String> lhs60 = <String>[... /*@error=SpreadElementTypeMismatch*/
// ^^^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:59:32: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:109:32: Error: Unexpected token '...'.
// Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
// ^^^
//
+// pkg/front_end/testcases/spread_collection_inference.dart:111:36: Error: Unexpected token '...'.
+// Map<int, int> map60 = <int, int>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:114:48: Error: Unexpected token '...'.
+// Map<String, String> map61 = <String, String>{...
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:117:27: Error: Unexpected token '...'.
+// List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:119:26: Error: Unexpected token '...'.
+// Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:6: Error: Unexpected token '...'.
+// {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:52: Error: Unexpected token '...'.
+// {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:125:42: Error: Unexpected token '...'.
+// Map<String, int> map70 = <String, int>{... /*@error=NonNullAwareSpreadIsNull*/
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:128:27: Error: Unexpected token '...?'.
+// List<int> lhs80 = <int>[...?null];
+// ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:130:26: Error: Unexpected token '...?'.
+// Set<int> set80 = <int>{...?null};
+// ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:133:6: Error: Unexpected token '...?'.
+// {...?null, ... /*@typeArgs=dynamic*/ []};
+// ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:133:16: Error: Unexpected token '...'.
+// {...?null, ... /*@typeArgs=dynamic*/ []};
+// ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:135:42: Error: Unexpected token '...?'.
+// Map<String, int> map80 = <String, int>{...?null};
+// ^^^^
+//
import self as self;
import "dart:core" as core;
static method foo() → dynamic {
core::List<core::int> spread = <core::int>[1, 2, 3];
+ core::Map<core::String, core::int> mapSpread = <core::String, core::int>{"foo": 4, "bar": 2};
core::int notSpreadInt = 42;
() → core::int notSpreadFunction = null;
- dynamic lhs10 = <dynamic>[<dynamic>[]];
- dynamic set10 = <dynamic>{<dynamic>[]};
- dynamic lhs20 = <dynamic>[spread];
- dynamic set20 = <dynamic>{spread, 42};
- dynamic lhs21 = <dynamic>[spread as dynamic];
- dynamic set21 = <dynamic>{spread as dynamic, 42};
- core::List<core::int> lhs22 = <dynamic>[<dynamic>[]];
- core::Set<core::int> set22 = <dynamic>{<dynamic>[], 42};
- core::List<core::List<core::int>> lhs23 = <dynamic>[<dynamic>[<dynamic>[]]];
- core::Set<core::List<core::int>> set23 = <dynamic>{<dynamic>[<dynamic>[]], <core::int>[42]};
- core::int lhs30 = <dynamic>[spread];
- core::int set30 = <dynamic>{spread, 42};
- core::List<dynamic> lhs40 = <dynamic>[notSpreadInt];
- core::Set<dynamic> set40 = <dynamic>{notSpreadInt};
- core::List<dynamic> lhs50 = <dynamic>[notSpreadFunction];
- core::Set<dynamic> set50 = <dynamic>{notSpreadFunction};
- core::List<core::String> lhs60 = <core::String>[spread];
- core::Set<core::String> set60 = <core::String>{spread};
+ dynamic lhs10 = <dynamic>[];
+ dynamic set10 = <dynamic>{};
+ dynamic map10 = <dynamic, dynamic>{};
+ dynamic map10ambiguous = <dynamic, dynamic>{};
+ dynamic lhs20 = <dynamic>[];
+ dynamic set20 = <dynamic>{42};
+ dynamic set20ambiguous = <dynamic, dynamic>{};
+ dynamic map20 = <dynamic, dynamic>{"baz": 42};
+ dynamic map20ambiguous = <dynamic, dynamic>{};
+ dynamic lhs21 = <dynamic>[];
+ dynamic set21 = <dynamic>{42};
+ dynamic map21 = <dynamic, dynamic>{"baz": 42};
+ dynamic map21ambiguous = <dynamic, dynamic>{};
+ core::List<core::int> lhs22 = <dynamic>[];
+ core::Set<core::int> set22 = <dynamic>{42};
+ core::Set<core::int> set22ambiguous = <dynamic, dynamic>{};
+ core::Map<core::String, core::int> map22 = <dynamic, dynamic>{};
+ core::List<core::List<core::int>> lhs23 = <dynamic>[];
+ core::Set<core::List<core::int>> set23 = <dynamic>{<core::int>[42]};
+ core::Set<core::List<core::int>> set23ambiguous = <dynamic, dynamic>{};
+ core::Map<core::String, core::List<core::int>> map23 = <dynamic, dynamic>{};
+ dynamic map24ambiguous = <dynamic, dynamic>{};
+ core::int lhs30 = <dynamic>[];
+ core::int set30 = <dynamic>{42};
+ core::int set30ambiguous = <dynamic, dynamic>{};
+ core::int map30 = <dynamic, dynamic>{"baz": 42};
+ core::int map30ambiguous = <dynamic, dynamic>{};
+ core::List<dynamic> lhs40 = <dynamic>[];
+ core::Set<dynamic> set40 = <dynamic>{};
+ core::Map<dynamic, dynamic> map40 = <dynamic, dynamic>{};
+ core::List<dynamic> lhs50 = <dynamic>[];
+ core::Set<dynamic> set50 = <dynamic>{};
+ core::Map<dynamic, dynamic> map50 = <dynamic, dynamic>{};
+ core::List<core::String> lhs60 = <core::String>[];
+ core::Set<core::String> set60 = <core::String>{};
+ core::Map<core::int, core::int> map60 = <core::int, core::int>{};
+ core::Map<core::String, core::String> map61 = <core::String, core::String>{};
+ core::List<core::int> lhs70 = <core::int>[];
+ core::Set<core::int> set70 = <core::int>{};
+ dynamic set71ambiguous = <dynamic, dynamic>{};
+ core::Map<core::String, core::int> map70 = <core::String, core::int>{};
+ core::List<core::int> lhs80 = <core::int>[];
+ core::Set<core::int> set80 = <core::int>{};
+ dynamic set81ambiguous = <dynamic, dynamic>{};
+ core::Map<core::String, core::int> map80 = <core::String, core::int>{};
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart.strong.expect b/pkg/front_end/testcases/spread_collection_inference.dart.strong.expect
index c93245e..fa9fa70 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/spread_collection_inference.dart.strong.expect
@@ -2,48 +2,114 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/spread_collection_inference.dart:40:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+// pkg/front_end/testcases/spread_collection_inference.dart:48:76: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+// dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:72:76: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+// ^
+// pkg/front_end/testcases/spread_collection_inference.dart:73:5: Context: Iterable spread.
+// spread, ...mapSpread};
+// ^
+// pkg/front_end/testcases/spread_collection_inference.dart:73:16: Context: Map spread.
+// spread, ...mapSpread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:75:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
// - 'List' is from 'dart:core'.
// Try changing the type of the left hand side, or casting the right hand side to 'int'.
// int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:42:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+// pkg/front_end/testcases/spread_collection_inference.dart:77:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
// - 'Set' is from 'dart:core'.
// Try changing the type of the left hand side, or casting the right hand side to 'int'.
// int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:45:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:80:5: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+// - 'Set' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// {...spread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:83:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+// - 'Map' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// {...mapSpread, "baz": 42};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:86:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+// - 'Map' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// {...mapSpread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:89:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
// notSpreadInt];
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:48:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:92:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
// notSpreadInt};
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:51:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:95:43: Error: Unexpected type 'int' of a map spread entry. Expected 'dynamic' or a Map.
+// /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:98:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
// notSpreadFunction];
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:54:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:101:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
// notSpreadFunction};
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:57:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+// pkg/front_end/testcases/spread_collection_inference.dart:104:43: Error: Unexpected type 'int Function()' of a map spread entry. Expected 'dynamic' or a Map.
+// /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:107:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
// spread];
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:59:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+// pkg/front_end/testcases/spread_collection_inference.dart:109:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
// Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
// ^
//
+// pkg/front_end/testcases/spread_collection_inference.dart:112:53: Error: Can't assign spread entry keys of type 'String' to map entry keys of type 'int'.
+// /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:115:55: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
+// /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:117:67: Error: Can't spread a value with static type Null.
+// List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:119:66: Error: Can't spread a value with static type Null.
+// Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:46: Error: Can't spread a value with static type Null.
+// {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:126:5: Error: Can't spread a value with static type Null.
+// null};
+// ^
+//
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
static method foo() → dynamic {
core::List<core::int> spread = <core::int>[1, 2, 3];
+ core::Map<core::String, core::int> mapSpread = <core::String, core::int>{"foo": 4, "bar": 2};
core::int notSpreadInt = 42;
() → core::int notSpreadFunction = null;
core::List<dynamic> lhs10 = block {
@@ -56,86 +122,232 @@
for (final dynamic #t4 in <dynamic>[])
#t3.{core::Set::add}(#t4);
} =>#t3;
- core::List<core::int> lhs20 = block {
- final core::List<core::int> #t5 = <core::int>[];
- for (final core::int #t6 in spread)
- #t5.{core::List::add}(#t6);
+ core::Map<dynamic, dynamic> map10 = block {
+ final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
+ for (final core::MapEntry<dynamic, dynamic> #t6 in <dynamic, dynamic>{}.{core::Map::entries})
+ #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
} =>#t5;
- core::Set<core::int> set20 = block {
- final core::Set<core::int> #t7 = col::LinkedHashSet::•<core::int>();
- for (final core::int #t8 in spread)
- #t7.{core::Set::add}(#t8);
- #t7.{core::Set::add}(42);
+ core::Map<dynamic, dynamic> map10ambiguous = block {
+ final core::Map<dynamic, dynamic> #t7 = <dynamic, dynamic>{};
+ for (final core::MapEntry<dynamic, dynamic> #t8 in <dynamic, dynamic>{}.{core::Map::entries})
+ #t7.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
} =>#t7;
- core::List<dynamic> lhs21 = block {
- final core::List<dynamic> #t9 = <dynamic>[];
- for (final dynamic #t10 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+ core::List<core::int> lhs20 = block {
+ final core::List<core::int> #t9 = <core::int>[];
+ for (final core::int #t10 in spread)
#t9.{core::List::add}(#t10);
} =>#t9;
- core::Set<dynamic> set21 = block {
- final core::Set<dynamic> #t11 = col::LinkedHashSet::•<dynamic>();
- for (final dynamic #t12 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+ core::Set<core::int> set20 = block {
+ final core::Set<core::int> #t11 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t12 in spread)
#t11.{core::Set::add}(#t12);
#t11.{core::Set::add}(42);
} =>#t11;
- core::List<core::int> lhs22 = block {
- final core::List<core::int> #t13 = <core::int>[];
- for (final core::int #t14 in <core::int>[])
- #t13.{core::List::add}(#t14);
+ core::Set<core::int> set20ambiguous = block {
+ final core::Set<core::int> #t13 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t14 in spread)
+ #t13.{core::Set::add}(#t14);
} =>#t13;
- core::Set<core::int> set22 = block {
- final core::Set<core::int> #t15 = col::LinkedHashSet::•<core::int>();
- for (final core::int #t16 in <core::int>[])
- #t15.{core::Set::add}(#t16);
- #t15.{core::Set::add}(42);
+ core::Map<core::String, core::int> map20 = block {
+ final core::Map<core::String, core::int> #t15 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t16 in mapSpread.{core::Map::entries})
+ #t15.{core::Map::[]=}(#t16.{core::MapEntry::key}, #t16.{core::MapEntry::value});
+ #t15.{core::Map::[]=}("baz", 42);
} =>#t15;
- core::List<core::List<core::int>> lhs23 = block {
- final core::List<core::List<core::int>> #t17 = <core::List<core::int>>[];
- for (final core::List<core::int> #t18 in <core::List<core::int>>[<core::int>[]])
- #t17.{core::List::add}(#t18);
+ core::Map<core::String, core::int> map20ambiguous = block {
+ final core::Map<core::String, core::int> #t17 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t18 in mapSpread.{core::Map::entries})
+ #t17.{core::Map::[]=}(#t18.{core::MapEntry::key}, #t18.{core::MapEntry::value});
} =>#t17;
- core::Set<core::List<core::int>> set23 = block {
- final core::Set<core::List<core::int>> #t19 = col::LinkedHashSet::•<core::List<core::int>>();
- for (final core::List<core::int> #t20 in <core::List<core::int>>[<core::int>[]])
- #t19.{core::Set::add}(#t20);
- #t19.{core::Set::add}(<core::int>[42]);
+ core::List<dynamic> lhs21 = block {
+ final core::List<dynamic> #t19 = <dynamic>[];
+ for (final dynamic #t20 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+ #t19.{core::List::add}(#t20);
} =>#t19;
- core::int lhs30 = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:40:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+ core::Set<dynamic> set21 = block {
+ final core::Set<dynamic> #t21 = col::LinkedHashSet::•<dynamic>();
+ for (final dynamic #t22 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+ #t21.{core::Set::add}(#t22);
+ #t21.{core::Set::add}(42);
+ } =>#t21;
+ core::Map<dynamic, dynamic> map21 = block {
+ final core::Map<dynamic, dynamic> #t23 = <dynamic, dynamic>{};
+ for (final core::MapEntry<dynamic, dynamic> #t24 in ((mapSpread as dynamic) as{TypeError} core::Map<dynamic, dynamic>).{core::Map::entries})
+ #t23.{core::Map::[]=}(#t24.{core::MapEntry::key}, #t24.{core::MapEntry::value});
+ #t23.{core::Map::[]=}("baz", 42);
+ } =>#t23;
+ dynamic map21ambiguous = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:48:76: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+ dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+ ^";
+ core::List<core::int> lhs22 = block {
+ final core::List<core::int> #t25 = <core::int>[];
+ for (final core::int #t26 in <core::int>[])
+ #t25.{core::List::add}(#t26);
+ } =>#t25;
+ core::Set<core::int> set22 = block {
+ final core::Set<core::int> #t27 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t28 in <core::int>[])
+ #t27.{core::Set::add}(#t28);
+ #t27.{core::Set::add}(42);
+ } =>#t27;
+ core::Set<core::int> set22ambiguous = block {
+ final core::Set<core::int> #t29 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t30 in <core::int>[])
+ #t29.{core::Set::add}(#t30);
+ } =>#t29;
+ core::Map<core::String, core::int> map22 = block {
+ final core::Map<core::String, core::int> #t31 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t32 in <core::String, core::int>{}.{core::Map::entries})
+ #t31.{core::Map::[]=}(#t32.{core::MapEntry::key}, #t32.{core::MapEntry::value});
+ } =>#t31;
+ core::List<core::List<core::int>> lhs23 = block {
+ final core::List<core::List<core::int>> #t33 = <core::List<core::int>>[];
+ for (final core::List<core::int> #t34 in <core::List<core::int>>[<core::int>[]])
+ #t33.{core::List::add}(#t34);
+ } =>#t33;
+ core::Set<core::List<core::int>> set23 = block {
+ final core::Set<core::List<core::int>> #t35 = col::LinkedHashSet::•<core::List<core::int>>();
+ for (final core::List<core::int> #t36 in <core::List<core::int>>[<core::int>[]])
+ #t35.{core::Set::add}(#t36);
+ #t35.{core::Set::add}(<core::int>[42]);
+ } =>#t35;
+ core::Set<core::List<core::int>> set23ambiguous = block {
+ final core::Set<core::List<core::int>> #t37 = col::LinkedHashSet::•<core::List<core::int>>();
+ for (final core::List<core::int> #t38 in <core::List<core::int>>[<core::int>[]])
+ #t37.{core::Set::add}(#t38);
+ } =>#t37;
+ core::Map<core::String, core::List<core::int>> map23 = block {
+ final core::Map<core::String, core::List<core::int>> #t39 = <core::String, core::List<core::int>>{};
+ for (final core::MapEntry<core::String, core::List<core::int>> #t40 in <core::String, core::List<core::int>>{"baz": <core::int>[]}.{core::Map::entries})
+ #t39.{core::Map::[]=}(#t40.{core::MapEntry::key}, #t40.{core::MapEntry::value});
+ } =>#t39;
+ dynamic map24ambiguous = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:72:76: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+ dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+ ^";
+ core::int lhs30 = let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:75:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
- 'List' is from 'dart:core'.
Try changing the type of the left hand side, or casting the right hand side to 'int'.
int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
^" in ( block {
- final core::List<core::int> #t22 = <core::int>[];
- for (final core::int #t23 in spread)
- #t22.{core::List::add}(#t23);
- } =>#t22) as{TypeError} core::int;
- core::int set30 = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:42:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+ final core::List<core::int> #t42 = <core::int>[];
+ for (final core::int #t43 in spread)
+ #t42.{core::List::add}(#t43);
+ } =>#t42) as{TypeError} core::int;
+ core::int set30 = let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:77:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
- 'Set' is from 'dart:core'.
Try changing the type of the left hand side, or casting the right hand side to 'int'.
int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
^" in ( block {
- final core::Set<core::int> #t25 = col::LinkedHashSet::•<core::int>();
- for (final core::int #t26 in spread)
- #t25.{core::Set::add}(#t26);
- #t25.{core::Set::add}(42);
- } =>#t25) as{TypeError} core::int;
- core::List<dynamic> lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:45:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
+ final core::Set<core::int> #t45 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t46 in spread)
+ #t45.{core::Set::add}(#t46);
+ #t45.{core::Set::add}(42);
+ } =>#t45) as{TypeError} core::int;
+ core::int set30ambiguous = let final<BottomType> #t47 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:80:5: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+ - 'Set' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+ {...spread};
+ ^" in ( block {
+ final core::Set<core::int> #t48 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t49 in spread)
+ #t48.{core::Set::add}(#t49);
+ } =>#t48) as{TypeError} core::int;
+ core::int map30 = let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:83:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+ - 'Map' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+ {...mapSpread, \"baz\": 42};
+ ^" in ( block {
+ final core::Map<core::String, core::int> #t51 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t52 in mapSpread.{core::Map::entries})
+ #t51.{core::Map::[]=}(#t52.{core::MapEntry::key}, #t52.{core::MapEntry::value});
+ #t51.{core::Map::[]=}("baz", 42);
+ } =>#t51) as{TypeError} core::int;
+ core::int map30ambiguous = let final<BottomType> #t53 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:86:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+ - 'Map' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+ {...mapSpread};
+ ^" in ( block {
+ final core::Map<core::String, core::int> #t54 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t55 in mapSpread.{core::Map::entries})
+ #t54.{core::Map::[]=}(#t55.{core::MapEntry::key}, #t55.{core::MapEntry::value});
+ } =>#t54) as{TypeError} core::int;
+ core::List<dynamic> lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:89:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
notSpreadInt];
^"];
- core::Set<dynamic> set40 = let final core::Set<dynamic> #t27 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t28 = #t27.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:48:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
+ core::Set<dynamic> set40 = let final core::Set<dynamic> #t56 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t57 = #t56.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:92:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
notSpreadInt};
- ^") in #t27;
- core::List<dynamic> lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:51:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
+ ^") in #t56;
+ core::Map<dynamic, dynamic> map40 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:95:43: Error: Unexpected type 'int' of a map spread entry. Expected 'dynamic' or a Map.
+ /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+ ^": null};
+ core::List<dynamic> lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:98:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
notSpreadFunction];
^"];
- core::Set<dynamic> set50 = let final core::Set<dynamic> #t29 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t30 = #t29.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:54:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
+ core::Set<dynamic> set50 = let final core::Set<dynamic> #t58 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t59 = #t58.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:101:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
notSpreadFunction};
- ^") in #t29;
- core::List<core::String> lhs60 = <core::String>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:57:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+ ^") in #t58;
+ core::Map<dynamic, dynamic> map50 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:104:43: Error: Unexpected type 'int Function()' of a map spread entry. Expected 'dynamic' or a Map.
+ /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+ ^": null};
+ core::List<core::String> lhs60 = <core::String>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:107:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
spread];
^"];
- core::Set<core::String> set60 = let final core::Set<core::String> #t31 = col::LinkedHashSet::•<core::String>() in let final dynamic #t32 = #t31.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:59:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+ core::Set<core::String> set60 = let final core::Set<core::String> #t60 = col::LinkedHashSet::•<core::String>() in let final dynamic #t61 = #t60.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:109:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
- ^") in #t31;
+ ^") in #t60;
+ core::Map<core::int, core::int> map60 = <core::int, core::int>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:112:53: Error: Can't assign spread entry keys of type 'String' to map entry keys of type 'int'.
+ /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+ ^": null};
+ core::Map<core::String, core::String> map61 = <core::String, core::String>{null: invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:115:55: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
+ /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+ ^"};
+ core::List<core::int> lhs70 = <core::int>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:117:67: Error: Can't spread a value with static type Null.
+ List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+ ^"];
+ core::Set<core::int> set70 = let final core::Set<core::int> #t62 = col::LinkedHashSet::•<core::int>() in let final dynamic #t63 = #t62.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:119:66: Error: Can't spread a value with static type Null.
+ Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+ ^") in #t62;
+ core::Set<dynamic> set71ambiguous = block {
+ final core::Set<dynamic> #t64 = col::LinkedHashSet::•<dynamic>();
+ #t64.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:122:46: Error: Can't spread a value with static type Null.
+ {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+ ^");
+ for (final dynamic #t65 in <dynamic>[])
+ #t64.{core::Set::add}(#t65);
+ } =>#t64;
+ core::Map<core::String, core::int> map70 = <core::String, core::int>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:126:5: Error: Can't spread a value with static type Null.
+ null};
+ ^": null};
+ core::List<core::int> lhs80 = block {
+ final core::List<core::int> #t66 = <core::int>[];
+ final dynamic #t67 = null;
+ if(!#t67.{core::Object::==}(null))
+ for (final core::int #t68 in #t67)
+ #t66.{core::List::add}(#t68);
+ } =>#t66;
+ core::Set<core::int> set80 = block {
+ final core::Set<core::int> #t69 = col::LinkedHashSet::•<core::int>();
+ final dynamic #t70 = null;
+ if(!#t70.{core::Object::==}(null))
+ for (final core::int #t71 in #t70)
+ #t69.{core::Set::add}(#t71);
+ } =>#t69;
+ core::Set<dynamic> set81ambiguous = block {
+ final core::Set<dynamic> #t72 = col::LinkedHashSet::•<dynamic>();
+ final dynamic #t73 = null;
+ if(!#t73.{core::Object::==}(null))
+ for (final dynamic #t74 in #t73)
+ #t72.{core::Set::add}(#t74);
+ for (final dynamic #t75 in <dynamic>[])
+ #t72.{core::Set::add}(#t75);
+ } =>#t72;
+ core::Map<core::String, core::int> map80 = block {
+ final core::Map<core::String, core::int> #t76 = <core::String, core::int>{};
+ final core::Map<dynamic, dynamic> #t77 = null;
+ if(!#t77.{core::Object::==}(null))
+ for (final core::MapEntry<core::String, core::int> #t78 in #t77.{core::Map::entries})
+ #t76.{core::Map::[]=}(#t78.{core::MapEntry::key}, #t78.{core::MapEntry::value});
+ } =>#t76;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/spread_collection_inference.dart.strong.transformed.expect
index 81ec36f..d9fbaef 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/spread_collection_inference.dart.strong.transformed.expect
@@ -2,48 +2,114 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/spread_collection_inference.dart:40:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+// pkg/front_end/testcases/spread_collection_inference.dart:48:76: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+// dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:72:76: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+// ^
+// pkg/front_end/testcases/spread_collection_inference.dart:73:5: Context: Iterable spread.
+// spread, ...mapSpread};
+// ^
+// pkg/front_end/testcases/spread_collection_inference.dart:73:16: Context: Map spread.
+// spread, ...mapSpread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:75:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
// - 'List' is from 'dart:core'.
// Try changing the type of the left hand side, or casting the right hand side to 'int'.
// int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:42:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+// pkg/front_end/testcases/spread_collection_inference.dart:77:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
// - 'Set' is from 'dart:core'.
// Try changing the type of the left hand side, or casting the right hand side to 'int'.
// int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:45:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:80:5: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+// - 'Set' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// {...spread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:83:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+// - 'Map' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// {...mapSpread, "baz": 42};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:86:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+// - 'Map' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// {...mapSpread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:89:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
// notSpreadInt];
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:48:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:92:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
// notSpreadInt};
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:51:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:95:43: Error: Unexpected type 'int' of a map spread entry. Expected 'dynamic' or a Map.
+// /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:98:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
// notSpreadFunction];
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:54:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:101:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
// notSpreadFunction};
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:57:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+// pkg/front_end/testcases/spread_collection_inference.dart:104:43: Error: Unexpected type 'int Function()' of a map spread entry. Expected 'dynamic' or a Map.
+// /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:107:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
// spread];
// ^
//
-// pkg/front_end/testcases/spread_collection_inference.dart:59:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+// pkg/front_end/testcases/spread_collection_inference.dart:109:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
// Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
// ^
//
+// pkg/front_end/testcases/spread_collection_inference.dart:112:53: Error: Can't assign spread entry keys of type 'String' to map entry keys of type 'int'.
+// /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:115:55: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
+// /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:117:67: Error: Can't spread a value with static type Null.
+// List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:119:66: Error: Can't spread a value with static type Null.
+// Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:46: Error: Can't spread a value with static type Null.
+// {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+// ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:126:5: Error: Can't spread a value with static type Null.
+// null};
+// ^
+//
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
static method foo() → dynamic {
core::List<core::int> spread = <core::int>[1, 2, 3];
+ core::Map<core::String, core::int> mapSpread = <core::String, core::int>{"foo": 4, "bar": 2};
core::int notSpreadInt = 42;
() → core::int notSpreadFunction = null;
core::List<dynamic> lhs10 = block {
@@ -56,86 +122,232 @@
for (final dynamic #t4 in <dynamic>[])
#t3.{core::Set::add}(#t4);
} =>#t3;
- core::List<core::int> lhs20 = block {
- final core::List<core::int> #t5 = <core::int>[];
- for (final core::int #t6 in spread)
- #t5.{core::List::add}(#t6);
+ core::Map<dynamic, dynamic> map10 = block {
+ final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
+ for (final core::MapEntry<dynamic, dynamic> #t6 in <dynamic, dynamic>{}.{core::Map::entries})
+ #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
} =>#t5;
- core::Set<core::int> set20 = block {
- final core::Set<core::int> #t7 = col::LinkedHashSet::•<core::int>();
- for (final core::int #t8 in spread)
- #t7.{core::Set::add}(#t8);
- #t7.{core::Set::add}(42);
+ core::Map<dynamic, dynamic> map10ambiguous = block {
+ final core::Map<dynamic, dynamic> #t7 = <dynamic, dynamic>{};
+ for (final core::MapEntry<dynamic, dynamic> #t8 in <dynamic, dynamic>{}.{core::Map::entries})
+ #t7.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
} =>#t7;
- core::List<dynamic> lhs21 = block {
- final core::List<dynamic> #t9 = <dynamic>[];
- for (final dynamic #t10 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+ core::List<core::int> lhs20 = block {
+ final core::List<core::int> #t9 = <core::int>[];
+ for (final core::int #t10 in spread)
#t9.{core::List::add}(#t10);
} =>#t9;
- core::Set<dynamic> set21 = block {
- final core::Set<dynamic> #t11 = col::LinkedHashSet::•<dynamic>();
- for (final dynamic #t12 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+ core::Set<core::int> set20 = block {
+ final core::Set<core::int> #t11 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t12 in spread)
#t11.{core::Set::add}(#t12);
#t11.{core::Set::add}(42);
} =>#t11;
- core::List<core::int> lhs22 = block {
- final core::List<core::int> #t13 = <core::int>[];
- for (final core::int #t14 in <core::int>[])
- #t13.{core::List::add}(#t14);
+ core::Set<core::int> set20ambiguous = block {
+ final core::Set<core::int> #t13 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t14 in spread)
+ #t13.{core::Set::add}(#t14);
} =>#t13;
- core::Set<core::int> set22 = block {
- final core::Set<core::int> #t15 = col::LinkedHashSet::•<core::int>();
- for (final core::int #t16 in <core::int>[])
- #t15.{core::Set::add}(#t16);
- #t15.{core::Set::add}(42);
+ core::Map<core::String, core::int> map20 = block {
+ final core::Map<core::String, core::int> #t15 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t16 in mapSpread.{core::Map::entries})
+ #t15.{core::Map::[]=}(#t16.{core::MapEntry::key}, #t16.{core::MapEntry::value});
+ #t15.{core::Map::[]=}("baz", 42);
} =>#t15;
- core::List<core::List<core::int>> lhs23 = block {
- final core::List<core::List<core::int>> #t17 = <core::List<core::int>>[];
- for (final core::List<core::int> #t18 in <core::List<core::int>>[<core::int>[]])
- #t17.{core::List::add}(#t18);
+ core::Map<core::String, core::int> map20ambiguous = block {
+ final core::Map<core::String, core::int> #t17 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t18 in mapSpread.{core::Map::entries})
+ #t17.{core::Map::[]=}(#t18.{core::MapEntry::key}, #t18.{core::MapEntry::value});
} =>#t17;
- core::Set<core::List<core::int>> set23 = block {
- final core::Set<core::List<core::int>> #t19 = col::LinkedHashSet::•<core::List<core::int>>();
- for (final core::List<core::int> #t20 in <core::List<core::int>>[<core::int>[]])
- #t19.{core::Set::add}(#t20);
- #t19.{core::Set::add}(<core::int>[42]);
+ core::List<dynamic> lhs21 = block {
+ final core::List<dynamic> #t19 = <dynamic>[];
+ for (final dynamic #t20 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+ #t19.{core::List::add}(#t20);
} =>#t19;
- core::int lhs30 = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:40:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+ core::Set<dynamic> set21 = block {
+ final core::Set<dynamic> #t21 = col::LinkedHashSet::•<dynamic>();
+ for (final dynamic #t22 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+ #t21.{core::Set::add}(#t22);
+ #t21.{core::Set::add}(42);
+ } =>#t21;
+ core::Map<dynamic, dynamic> map21 = block {
+ final core::Map<dynamic, dynamic> #t23 = <dynamic, dynamic>{};
+ for (final core::MapEntry<dynamic, dynamic> #t24 in ((mapSpread as dynamic) as{TypeError} core::Map<dynamic, dynamic>).{core::Map::entries})
+ #t23.{core::Map::[]=}(#t24.{core::MapEntry::key}, #t24.{core::MapEntry::value});
+ #t23.{core::Map::[]=}("baz", 42);
+ } =>#t23;
+ dynamic map21ambiguous = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:48:76: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+ dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+ ^";
+ core::List<core::int> lhs22 = block {
+ final core::List<core::int> #t25 = <core::int>[];
+ for (final core::int #t26 in <core::int>[])
+ #t25.{core::List::add}(#t26);
+ } =>#t25;
+ core::Set<core::int> set22 = block {
+ final core::Set<core::int> #t27 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t28 in <core::int>[])
+ #t27.{core::Set::add}(#t28);
+ #t27.{core::Set::add}(42);
+ } =>#t27;
+ core::Set<core::int> set22ambiguous = block {
+ final core::Set<core::int> #t29 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t30 in <core::int>[])
+ #t29.{core::Set::add}(#t30);
+ } =>#t29;
+ core::Map<core::String, core::int> map22 = block {
+ final core::Map<core::String, core::int> #t31 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t32 in <core::String, core::int>{}.{core::Map::entries})
+ #t31.{core::Map::[]=}(#t32.{core::MapEntry::key}, #t32.{core::MapEntry::value});
+ } =>#t31;
+ core::List<core::List<core::int>> lhs23 = block {
+ final core::List<core::List<core::int>> #t33 = <core::List<core::int>>[];
+ for (final core::List<core::int> #t34 in <core::List<core::int>>[<core::int>[]])
+ #t33.{core::List::add}(#t34);
+ } =>#t33;
+ core::Set<core::List<core::int>> set23 = block {
+ final core::Set<core::List<core::int>> #t35 = col::LinkedHashSet::•<core::List<core::int>>();
+ for (final core::List<core::int> #t36 in <core::List<core::int>>[<core::int>[]])
+ #t35.{core::Set::add}(#t36);
+ #t35.{core::Set::add}(<core::int>[42]);
+ } =>#t35;
+ core::Set<core::List<core::int>> set23ambiguous = block {
+ final core::Set<core::List<core::int>> #t37 = col::LinkedHashSet::•<core::List<core::int>>();
+ for (final core::List<core::int> #t38 in <core::List<core::int>>[<core::int>[]])
+ #t37.{core::Set::add}(#t38);
+ } =>#t37;
+ core::Map<core::String, core::List<core::int>> map23 = block {
+ final core::Map<core::String, core::List<core::int>> #t39 = <core::String, core::List<core::int>>{};
+ for (final core::MapEntry<core::String, core::List<core::int>> #t40 in <core::String, core::List<core::int>>{"baz": <core::int>[]}.{core::Map::entries})
+ #t39.{core::Map::[]=}(#t40.{core::MapEntry::key}, #t40.{core::MapEntry::value});
+ } =>#t39;
+ dynamic map24ambiguous = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:72:76: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+ dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+ ^";
+ core::int lhs30 = let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:75:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
- 'List' is from 'dart:core'.
Try changing the type of the left hand side, or casting the right hand side to 'int'.
int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
^" in ( block {
- final core::List<core::int> #t22 = <core::int>[];
- for (final core::int #t23 in spread)
- #t22.{core::List::add}(#t23);
- } =>#t22) as{TypeError} core::int;
- core::int set30 = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:42:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+ final core::List<core::int> #t42 = <core::int>[];
+ for (final core::int #t43 in spread)
+ #t42.{core::List::add}(#t43);
+ } =>#t42) as{TypeError} core::int;
+ core::int set30 = let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:77:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
- 'Set' is from 'dart:core'.
Try changing the type of the left hand side, or casting the right hand side to 'int'.
int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
^" in ( block {
- final core::Set<core::int> #t25 = col::LinkedHashSet::•<core::int>();
- for (final core::int #t26 in spread)
- #t25.{core::Set::add}(#t26);
- #t25.{core::Set::add}(42);
- } =>#t25) as{TypeError} core::int;
- core::List<dynamic> lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:45:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
+ final core::Set<core::int> #t45 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t46 in spread)
+ #t45.{core::Set::add}(#t46);
+ #t45.{core::Set::add}(42);
+ } =>#t45) as{TypeError} core::int;
+ core::int set30ambiguous = let final<BottomType> #t47 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:80:5: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+ - 'Set' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+ {...spread};
+ ^" in ( block {
+ final core::Set<core::int> #t48 = col::LinkedHashSet::•<core::int>();
+ for (final core::int #t49 in spread)
+ #t48.{core::Set::add}(#t49);
+ } =>#t48) as{TypeError} core::int;
+ core::int map30 = let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:83:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+ - 'Map' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+ {...mapSpread, \"baz\": 42};
+ ^" in ( block {
+ final core::Map<core::String, core::int> #t51 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t52 in mapSpread.{core::Map::entries})
+ #t51.{core::Map::[]=}(#t52.{core::MapEntry::key}, #t52.{core::MapEntry::value});
+ #t51.{core::Map::[]=}("baz", 42);
+ } =>#t51) as{TypeError} core::int;
+ core::int map30ambiguous = let final<BottomType> #t53 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:86:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+ - 'Map' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+ {...mapSpread};
+ ^" in ( block {
+ final core::Map<core::String, core::int> #t54 = <core::String, core::int>{};
+ for (final core::MapEntry<core::String, core::int> #t55 in mapSpread.{core::Map::entries})
+ #t54.{core::Map::[]=}(#t55.{core::MapEntry::key}, #t55.{core::MapEntry::value});
+ } =>#t54) as{TypeError} core::int;
+ core::List<dynamic> lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:89:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
notSpreadInt];
^"];
- core::Set<dynamic> set40 = let final core::Set<dynamic> #t27 = col::LinkedHashSet::•<dynamic>() in let final core::bool #t28 = #t27.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:48:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
+ core::Set<dynamic> set40 = let final core::Set<dynamic> #t56 = col::LinkedHashSet::•<dynamic>() in let final core::bool #t57 = #t56.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:92:5: Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
notSpreadInt};
- ^") in #t27;
- core::List<dynamic> lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:51:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
+ ^") in #t56;
+ core::Map<dynamic, dynamic> map40 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:95:43: Error: Unexpected type 'int' of a map spread entry. Expected 'dynamic' or a Map.
+ /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+ ^": null};
+ core::List<dynamic> lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:98:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
notSpreadFunction];
^"];
- core::Set<dynamic> set50 = let final core::Set<dynamic> #t29 = col::LinkedHashSet::•<dynamic>() in let final core::bool #t30 = #t29.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:54:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
+ core::Set<dynamic> set50 = let final core::Set<dynamic> #t58 = col::LinkedHashSet::•<dynamic>() in let final core::bool #t59 = #t58.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:101:5: Error: Unexpected type 'int Function()' of a spread. Expected 'dynamic' or an Iterable.
notSpreadFunction};
- ^") in #t29;
- core::List<core::String> lhs60 = <core::String>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:57:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+ ^") in #t58;
+ core::Map<dynamic, dynamic> map50 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:104:43: Error: Unexpected type 'int Function()' of a map spread entry. Expected 'dynamic' or a Map.
+ /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+ ^": null};
+ core::List<core::String> lhs60 = <core::String>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:107:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
spread];
^"];
- core::Set<core::String> set60 = let final core::Set<core::String> #t31 = col::LinkedHashSet::•<core::String>() in let final core::bool #t32 = #t31.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:59:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+ core::Set<core::String> set60 = let final core::Set<core::String> #t60 = col::LinkedHashSet::•<core::String>() in let final core::bool #t61 = #t60.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:109:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
- ^") in #t31;
+ ^") in #t60;
+ core::Map<core::int, core::int> map60 = <core::int, core::int>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:112:53: Error: Can't assign spread entry keys of type 'String' to map entry keys of type 'int'.
+ /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+ ^": null};
+ core::Map<core::String, core::String> map61 = <core::String, core::String>{null: invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:115:55: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
+ /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+ ^"};
+ core::List<core::int> lhs70 = <core::int>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:117:67: Error: Can't spread a value with static type Null.
+ List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+ ^"];
+ core::Set<core::int> set70 = let final core::Set<core::int> #t62 = col::LinkedHashSet::•<core::int>() in let final core::bool #t63 = #t62.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:119:66: Error: Can't spread a value with static type Null.
+ Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+ ^") in #t62;
+ core::Set<dynamic> set71ambiguous = block {
+ final core::Set<dynamic> #t64 = col::LinkedHashSet::•<dynamic>();
+ #t64.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:122:46: Error: Can't spread a value with static type Null.
+ {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+ ^");
+ for (final dynamic #t65 in <dynamic>[])
+ #t64.{core::Set::add}(#t65);
+ } =>#t64;
+ core::Map<core::String, core::int> map70 = <core::String, core::int>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:126:5: Error: Can't spread a value with static type Null.
+ null};
+ ^": null};
+ core::List<core::int> lhs80 = block {
+ final core::List<core::int> #t66 = <core::int>[];
+ final dynamic #t67 = null;
+ if(!#t67.{core::Object::==}(null))
+ for (final core::int #t68 in #t67)
+ #t66.{core::List::add}(#t68);
+ } =>#t66;
+ core::Set<core::int> set80 = block {
+ final core::Set<core::int> #t69 = col::LinkedHashSet::•<core::int>();
+ final dynamic #t70 = null;
+ if(!#t70.{core::Object::==}(null))
+ for (final core::int #t71 in #t70)
+ #t69.{core::Set::add}(#t71);
+ } =>#t69;
+ core::Set<dynamic> set81ambiguous = block {
+ final core::Set<dynamic> #t72 = col::LinkedHashSet::•<dynamic>();
+ final dynamic #t73 = null;
+ if(!#t73.{core::Object::==}(null))
+ for (final dynamic #t74 in #t73)
+ #t72.{core::Set::add}(#t74);
+ for (final dynamic #t75 in <dynamic>[])
+ #t72.{core::Set::add}(#t75);
+ } =>#t72;
+ core::Map<core::String, core::int> map80 = block {
+ final core::Map<core::String, core::int> #t76 = <core::String, core::int>{};
+ final core::Map<dynamic, dynamic> #t77 = null;
+ if(!#t77.{core::Object::==}(null))
+ for (final core::MapEntry<core::String, core::int> #t78 in #t77.{core::Map::entries})
+ #t76.{core::Map::[]=}(#t78.{core::MapEntry::key}, #t78.{core::MapEntry::value});
+ } =>#t76;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 25ac322..d89dded 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -26,6 +26,7 @@
fallthrough: ExpectationFileMismatch
incomplete_field_formal_parameter: RuntimeError
inference/abstract_class_instantiation: InstrumentationMismatch # Issue #30040
+inference/conflicting_fields: TypeCheckError
inference/conflicts_can_happen: TypeCheckError
inference/conflicts_can_happen2: TypeCheckError
inference/constructors_infer_from_arguments_argument_not_assignable: TypeCheckError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index fe97d6b..4d5dc75 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -157,6 +157,7 @@
inference/complex_predecrement: TextSerializationFailure # Was: Pass
inference/conditional_lub: TextSerializationFailure # Was: Pass
inference/conditional_upwards_inference: TextSerializationFailure # Was: Pass
+inference/conflicting_fields: TypeCheckError
inference/conflicts_can_happen2: TypeCheckError
inference/conflicts_can_happen: TypeCheckError
inference/constructors_downwards_with_constraint: TextSerializationFailure # Was: Pass
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 6dd8999..a1457fc 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -299,7 +299,7 @@
"mode": "release",
"common": "--dart2js-batch --time -pcolor --report -ax64 -mrelease --write-result-log",
"command-lines": [
- "-cdart2js -rd8 --use-sdk --minified --dart2js-with-kernel language language_2 dart2js_extra dart2js_native corelib corelib_2"
+ "-cdart2js -rd8 --use-sdk --minified language language_2 dart2js_extra dart2js_native corelib corelib_2"
]
},
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 385d151..ae7650d 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -251,6 +251,7 @@
"--legacy": "--legacy-mode",
"--legacy-mode": false,
"--libraries-json": Uri,
+ "--no-defines": false,
"--output": Uri,
"--packages": Uri,
"--platform": Uri,
@@ -310,6 +311,8 @@
"Valid targets are:\n ${targets.keys.join("\n ")}");
}
+ final bool noDefines = options["--no-defines"];
+
final bool enableAsserts = options["--enable-asserts"];
final bool verify = options["--verify"];
@@ -385,7 +388,7 @@
..verify = verify
..bytecode = bytecode
..experimentalFlags = experimentalFlags
- ..environmentDefines = parsedArguments.defines,
+ ..environmentDefines = noDefines ? null : parsedArguments.defines,
inputs: <Uri>[Uri.parse(arguments[0])],
output: resolveInputUri(arguments[3]));
} else if (arguments.isEmpty) {
@@ -421,7 +424,7 @@
..verbose = verbose
..verify = verify
..experimentalFlags = experimentalFlags
- ..environmentDefines = parsedArguments.defines;
+ ..environmentDefines = noDefines ? null : parsedArguments.defines;
// TODO(ahe): What about chase dependencies?
diff --git a/pkg/front_end/tool/fasta b/pkg/front_end/tool/fasta
index 2567a4e..465f05b 100755
--- a/pkg/front_end/tool/fasta
+++ b/pkg/front_end/tool/fasta
@@ -23,6 +23,13 @@
export DART_CONFIGURATION=${DART_CONFIGURATION:-ReleaseX64}
+EXTRA_VM_ARGS=()
+
+while [[ "$1" == -* ]]; do
+ EXTRA_VM_ARGS+=("$1")
+ shift
+done
+
case "${1//_/-}" in
abcompile) SCRIPT="${TOOL_DIR}/abcompile.dart";;
compile) SCRIPT="${TOOL_DIR}/compile.dart";;
@@ -55,4 +62,4 @@
shift
-exec "${DART_VM}" -c "${SCRIPT}" "$@"
+exec "${DART_VM}" "${EXTRA_VM_ARGS[@]}" -c "${SCRIPT}" "$@"
diff --git a/pkg/front_end/tool/status_files/update_from_log.dart b/pkg/front_end/tool/status_files/update_from_log.dart
deleted file mode 100644
index 2fa2b11..0000000
--- a/pkg/front_end/tool/status_files/update_from_log.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/// Script that updates kernel status lines automatically for tests under the
-/// '$strong' configuration.
-///
-/// This script is hardcoded to only support this configuration and relies on
-/// a convention for how the status files are structured, In particular,
-/// every status file is expected to have these sections:
-///
-/// [ $compiler == dartk && $runtime == vm && $strong ]
-/// [ $compiler == dartk && $runtime == vm && $strong && $mode == debug ]
-/// [ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
-/// [ $compiler == dartkp && $runtime == dart_precompiled && $strong && $mode == debug]
-///
-/// we allow other sections specifying $checked mode, but the script currently
-/// has not been configured to update them.
-///
-/// [ $compiler == dartk && $runtime == vm && $strong && $checked ]
-/// [ $compiler == dartk && $runtime == vm && $strong && !$checked ]
-/// [ $compiler == dartkp && $runtime == dart_precompiled && $strong && $checked]
-/// [ $compiler == dartkp && $runtime == dart_precompiled && $strong && !$checked]
-///
-/// Note that this script is brittle and will not work properly if there are
-/// other overlapping sections. If you see the script adding entries like "Pass"
-/// it is a sign that a test was broadly marked as failing in a more general
-/// section (e.g. $runtime == vm, but no compiler was specified).
-
-library front_end.status_files.update_from_log;
-
-import '../../../compiler/tool/status_files/update_from_log.dart'
- show mainInternal;
-
-final kernelStrongConfigurations = {
- 'dartk': r'[ $compiler == dartk && $runtime == vm && $strong ]',
- 'dartk-debug':
- r'[ $compiler == dartk && $runtime == vm && $strong && $mode == debug]',
- 'dartkp':
- r'[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]',
- 'dartkp-debug':
- r'[ $compiler == dartkp && $runtime == dart_precompiled && $strong && $mode == debug]',
-};
-
-final kernelStrongStatusFiles = {
- 'corelib_2': 'tests/corelib_2/corelib_2.status',
- 'language_2': 'tests/language_2/language_2_kernel.status',
- 'lib_2': 'tests/lib_2/lib_2_kernel.status',
- 'standalone_2': 'tests/standalone_2/standalone_2_kernel.status',
-};
-
-main(args) {
- mainInternal(args, kernelStrongConfigurations, kernelStrongStatusFiles);
-}
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 5fab418..613741e7 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -137,7 +137,7 @@
type ComponentFile {
UInt32 magic = 0x90ABCDEF;
- UInt32 formatVersion = 20;
+ UInt32 formatVersion = 21;
List<String> problemsAsJson; // Described in problems.md.
Library[] libraries;
UriSource sourceMap;
@@ -696,6 +696,28 @@
List<Expression> expressions;
}
+type ListConcatenation extends Expression {
+ Byte tag = 111;
+ FileOffset fileOffset;
+ DartType typeArgument;
+ List<Expression> lists;
+}
+
+type SetConcatenation extends Expression {
+ Byte tag = 112;
+ FileOffset fileOffset;
+ DartType typeArgument;
+ List<Expression> sets;
+}
+
+type MapConcatenation extends Expression {
+ Byte tag = 113;
+ FileOffset fileOffset;
+ DartType keyType;
+ DartType valueType;
+ List<Expression> maps;
+}
+
type IsExpression extends Expression {
Byte tag = 37;
FileOffset fileOffset;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 939af1f..2d7e3a1 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -3204,6 +3204,116 @@
}
}
+/// Concatenate lists into a single list.
+///
+/// If [lists] is empty then an empty list is returned.
+///
+/// These arise from spread and control-flow elements in const list literals
+/// containing unevaluated subexpressions. They only ever occur within
+/// unevaluated constants in constant expressions.
+class ListConcatenation extends Expression {
+ DartType typeArgument;
+ final List<Expression> lists;
+
+ ListConcatenation(this.lists, {this.typeArgument: const DynamicType()}) {
+ setParents(lists, this);
+ }
+
+ DartType getStaticType(TypeEnvironment types) {
+ return types.literalListType(typeArgument);
+ }
+
+ accept(ExpressionVisitor v) => v.visitListConcatenation(this);
+ accept1(ExpressionVisitor1 v, arg) => v.visitListConcatenation(this, arg);
+
+ visitChildren(Visitor v) {
+ typeArgument?.accept(v);
+ visitList(lists, v);
+ }
+
+ transformChildren(Transformer v) {
+ typeArgument = v.visitDartType(typeArgument);
+ transformList(lists, v, this);
+ }
+}
+
+/// Concatenate sets into a single set.
+///
+/// If [sets] is empty then an empty set is returned.
+///
+/// These arise from spread and control-flow elements in const set literals
+/// containing unevaluated subexpressions. They only ever occur within
+/// unevaluated constants in constant expressions.
+///
+/// Duplicated values in or across the sets will result in a compile-time error
+/// during constant evaluation.
+class SetConcatenation extends Expression {
+ DartType typeArgument;
+ final List<Expression> sets;
+
+ SetConcatenation(this.sets, {this.typeArgument: const DynamicType()}) {
+ setParents(sets, this);
+ }
+
+ DartType getStaticType(TypeEnvironment types) {
+ return types.literalSetType(typeArgument);
+ }
+
+ accept(ExpressionVisitor v) => v.visitSetConcatenation(this);
+ accept1(ExpressionVisitor1 v, arg) => v.visitSetConcatenation(this, arg);
+
+ visitChildren(Visitor v) {
+ typeArgument?.accept(v);
+ visitList(sets, v);
+ }
+
+ transformChildren(Transformer v) {
+ typeArgument = v.visitDartType(typeArgument);
+ transformList(sets, v, this);
+ }
+}
+
+/// Concatenate maps into a single map.
+///
+/// If [maps] is empty then an empty map is returned.
+///
+/// These arise from spread and control-flow elements in const map literals
+/// containing unevaluated subexpressions. They only ever occur within
+/// unevaluated constants in constant expressions.
+///
+/// Duplicated keys in or across the maps will result in a compile-time error
+/// during constant evaluation.
+class MapConcatenation extends Expression {
+ DartType keyType;
+ DartType valueType;
+ final List<Expression> maps;
+
+ MapConcatenation(this.maps,
+ {this.keyType: const DynamicType(),
+ this.valueType: const DynamicType()}) {
+ setParents(maps, this);
+ }
+
+ DartType getStaticType(TypeEnvironment types) {
+ return types.literalMapType(keyType, valueType);
+ }
+
+ accept(ExpressionVisitor v) => v.visitMapConcatenation(this);
+ accept1(ExpressionVisitor1 v, arg) => v.visitMapConcatenation(this, arg);
+
+ visitChildren(Visitor v) {
+ keyType?.accept(v);
+ valueType?.accept(v);
+ visitList(maps, v);
+ }
+
+ transformChildren(Transformer v) {
+ keyType = v.visitDartType(keyType);
+ valueType = v.visitDartType(valueType);
+ transformList(maps, v, this);
+ }
+}
+
/// Expression of form `x is T`.
class IsExpression extends Expression {
Expression operand;
@@ -5585,6 +5695,10 @@
: root = nameRoot ?? new CanonicalName.root(),
libraries = libraries ?? <Library>[],
uriToSource = uriToSource ?? <Uri, Source>{} {
+ adoptChildren();
+ }
+
+ void adoptChildren() {
if (libraries != null) {
for (int i = 0; i < libraries.length; ++i) {
// The libraries are owned by this component, and so are their canonical
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 29fc2cc..f5b7c33 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -1511,6 +1511,25 @@
int offset = readOffset();
return new StringConcatenation(readExpressionList())
..fileOffset = offset;
+ case Tag.ListConcatenation:
+ int offset = readOffset();
+ var typeArgument = readDartType();
+ return new ListConcatenation(readExpressionList(),
+ typeArgument: typeArgument)
+ ..fileOffset = offset;
+ case Tag.SetConcatenation:
+ int offset = readOffset();
+ var typeArgument = readDartType();
+ return new SetConcatenation(readExpressionList(),
+ typeArgument: typeArgument)
+ ..fileOffset = offset;
+ case Tag.MapConcatenation:
+ int offset = readOffset();
+ var keyType = readDartType();
+ var valueType = readDartType();
+ return new MapConcatenation(readExpressionList(),
+ keyType: keyType, valueType: valueType)
+ ..fileOffset = offset;
case Tag.IsExpression:
int offset = readOffset();
return new IsExpression(readExpression(), readDartType())
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 383e6ba..db91bfb 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1466,6 +1466,31 @@
}
@override
+ void visitListConcatenation(ListConcatenation node) {
+ writeByte(Tag.ListConcatenation);
+ writeOffset(node.fileOffset);
+ writeNode(node.typeArgument);
+ writeNodeList(node.lists);
+ }
+
+ @override
+ void visitSetConcatenation(SetConcatenation node) {
+ writeByte(Tag.SetConcatenation);
+ writeOffset(node.fileOffset);
+ writeNode(node.typeArgument);
+ writeNodeList(node.sets);
+ }
+
+ @override
+ void visitMapConcatenation(MapConcatenation node) {
+ writeByte(Tag.MapConcatenation);
+ writeOffset(node.fileOffset);
+ writeNode(node.keyType);
+ writeNode(node.valueType);
+ writeNodeList(node.maps);
+ }
+
+ @override
void visitIsExpression(IsExpression node) {
writeByte(Tag.IsExpression);
writeOffset(node.fileOffset);
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index ff6e228..ba6cc4e 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -50,6 +50,9 @@
static const int LogicalExpression = 34;
static const int ConditionalExpression = 35;
static const int StringConcatenation = 36;
+ static const int ListConcatenation = 111;
+ static const int SetConcatenation = 112;
+ static const int MapConcatenation = 113;
static const int IsExpression = 37;
static const int AsExpression = 38;
static const int StringLiteral = 39;
@@ -123,6 +126,9 @@
/// 108 is occupied by [RedirectingFactoryConstructor] (member).
/// 109 is occupied by [SetLiteral] (expression).
/// 110 is occupied by [ConstSetLiteral] (expression).
+ /// 111 is occupied by [ListConcatenation] (expression).
+ /// 112 is occupied by [SetConcatenation] (expression).
+ /// 113 is occupied by [MapConcatenation] (expression).
static const int SpecializedTagHighBit = 0x80; // 10000000
static const int SpecializedTagMask = 0xF8; // 11111000
@@ -139,7 +145,7 @@
/// Internal version of kernel binary format.
/// Bump it when making incompatible changes in kernel binaries.
/// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
- static const int BinaryFormatVersion = 20;
+ static const int BinaryFormatVersion = 21;
}
abstract class ConstantTag {
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index a059436..4105a43 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -190,6 +190,21 @@
return new StringConcatenation(node.expressions.map(clone).toList());
}
+ visitListConcatenation(ListConcatenation node) {
+ return new ListConcatenation(node.lists.map(clone).toList(),
+ typeArgument: visitType(node.typeArgument));
+ }
+
+ visitSetConcatenation(SetConcatenation node) {
+ return new SetConcatenation(node.sets.map(clone).toList(),
+ typeArgument: visitType(node.typeArgument));
+ }
+
+ visitMapConcatenation(MapConcatenation node) {
+ return new MapConcatenation(node.maps.map(clone).toList(),
+ keyType: visitType(node.keyType), valueType: visitType(node.valueType));
+ }
+
visitIsExpression(IsExpression node) {
return new IsExpression(clone(node.operand), visitType(node.type));
}
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 94d2f55..29af291 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1272,6 +1272,33 @@
state = WORD;
}
+ visitListConcatenation(ListConcatenation node) {
+ bool first = true;
+ for (Expression part in node.lists) {
+ if (!first) writeSpaced('+');
+ writeExpression(part);
+ first = false;
+ }
+ }
+
+ visitSetConcatenation(SetConcatenation node) {
+ bool first = true;
+ for (Expression part in node.sets) {
+ if (!first) writeSpaced('+');
+ writeExpression(part);
+ first = false;
+ }
+ }
+
+ visitMapConcatenation(MapConcatenation node) {
+ bool first = true;
+ for (Expression part in node.maps) {
+ if (!first) writeSpaced('+');
+ writeExpression(part);
+ first = false;
+ }
+ }
+
visitIsExpression(IsExpression node) {
writeExpression(node.operand, Precedence.BITWISE_OR);
writeSpaced('is');
@@ -1993,11 +2020,16 @@
endLine(sb.toString());
}
+ visitStringConstant(StringConstant node) {
+ final String name = syntheticNames.nameConstant(node);
+ endLine(' $name = "${escapeString(node.value)}"');
+ }
+
visitUnevaluatedConstant(UnevaluatedConstant node) {
final String name = syntheticNames.nameConstant(node);
- write(' $name = ');
+ write(' $name = (');
writeExpression(node.expression);
- endLine();
+ endLine(')');
}
defaultNode(Node node) {
diff --git a/pkg/kernel/lib/text/text_serialization_verifier.dart b/pkg/kernel/lib/text/text_serialization_verifier.dart
index 2625376..b9f2662 100644
--- a/pkg/kernel/lib/text/text_serialization_verifier.dart
+++ b/pkg/kernel/lib/text/text_serialization_verifier.dart
@@ -888,6 +888,24 @@
}
@override
+ void visitListConcatenation(ListConcatenation node) {
+ storeLastSeenUriAndOffset(node);
+ makeExpressionRoundTrip(node);
+ }
+
+ @override
+ void visitSetConcatenation(SetConcatenation node) {
+ storeLastSeenUriAndOffset(node);
+ makeExpressionRoundTrip(node);
+ }
+
+ @override
+ void visitMapConcatenation(MapConcatenation node) {
+ storeLastSeenUriAndOffset(node);
+ makeExpressionRoundTrip(node);
+ }
+
+ @override
void visitConditionalExpression(ConditionalExpression node) {
storeLastSeenUriAndOffset(node);
makeExpressionRoundTrip(node);
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index f4361bd..e7c77df 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -1075,8 +1075,8 @@
if (left is UnevaluatedConstant) {
return unevaluated(
node,
- new LogicalExpression(
- unique(left.expression), node.operator, node.right));
+ new LogicalExpression(unique(left.expression), node.operator,
+ cloner.clone(node.right)));
}
switch (node.operator) {
case '||':
@@ -1138,8 +1138,11 @@
} else if (condition is UnevaluatedConstant) {
return unevaluated(
node,
- new ConditionalExpression(unique(condition.expression), node.then,
- node.otherwise, node.staticType));
+ new ConditionalExpression(
+ unique(condition.expression),
+ cloner.clone(node.then),
+ cloner.clone(node.otherwise),
+ node.staticType));
} else {
throw new _AbortCurrentEvaluation(errorReporter.invalidDartType(
contextChain, node, condition, typeEnvironment.boolType));
@@ -1211,7 +1214,7 @@
if (target.isConst) {
if (target.isInExternalLibrary && target.initializer == null) {
// The variable is unavailable due to separate compilation.
- return unevaluated(node, node);
+ return unevaluated(node, new StaticGet(target));
}
return runInsideContext(target, () {
return _evaluateSubexpression(target.initializer);
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index 5154517..4a401fa 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -188,7 +188,7 @@
assert(src.typeParameters.length == dst.typeParameters.length);
for (int j = 0; j < src.typeParameters.length; ++j) {
- dst.typeParameters[j].flags = src.typeParameters[i].flags;
+ dst.typeParameters[j].flags = src.typeParameters[j].flags;
}
for (int j = 0; j < src.positionalParameters.length; ++j) {
dst.positionalParameters[j].flags =
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 094bd2f..a8d41d4 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -275,6 +275,9 @@
@override
Supertype substituteSupertype(Supertype node) => node;
+
+ @override
+ String toString() => "Substitution.empty";
}
class _MapSubstitution extends Substitution {
@@ -286,6 +289,9 @@
DartType getSubstitute(TypeParameter parameter, bool upperBound) {
return upperBound ? upper[parameter] : lower[parameter];
}
+
+ @override
+ String toString() => "_MapSubstitution($upper, $lower)";
}
class _TopSubstitutor extends _TypeSubstitutor {
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 56eb744..7f04bce 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -683,6 +683,36 @@
}
@override
+ DartType visitListConcatenation(ListConcatenation node) {
+ DartType type = environment.literalListType(node.typeArgument);
+ for (Expression part in node.lists) {
+ DartType partType = visitExpression(part);
+ checkAssignable(node, type, partType);
+ }
+ return type;
+ }
+
+ @override
+ DartType visitSetConcatenation(SetConcatenation node) {
+ DartType type = environment.literalSetType(node.typeArgument);
+ for (Expression part in node.sets) {
+ DartType partType = visitExpression(part);
+ checkAssignable(node, type, partType);
+ }
+ return type;
+ }
+
+ @override
+ DartType visitMapConcatenation(MapConcatenation node) {
+ DartType type = environment.literalMapType(node.keyType, node.valueType);
+ for (Expression part in node.maps) {
+ DartType partType = visitExpression(part);
+ checkAssignable(node, type, partType);
+ }
+ return type;
+ }
+
+ @override
DartType visitStringLiteral(StringLiteral node) {
return environment.stringType;
}
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 53ea440..0cecee1 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -38,6 +38,9 @@
defaultExpression(node);
R visitStringConcatenation(StringConcatenation node) =>
defaultExpression(node);
+ R visitListConcatenation(ListConcatenation node) => defaultExpression(node);
+ R visitSetConcatenation(SetConcatenation node) => defaultExpression(node);
+ R visitMapConcatenation(MapConcatenation node) => defaultExpression(node);
R visitIsExpression(IsExpression node) => defaultExpression(node);
R visitAsExpression(AsExpression node) => defaultExpression(node);
R visitSymbolLiteral(SymbolLiteral node) => defaultExpression(node);
@@ -161,6 +164,9 @@
defaultExpression(node);
R visitStringConcatenation(StringConcatenation node) =>
defaultExpression(node);
+ R visitListConcatenation(ListConcatenation node) => defaultExpression(node);
+ R visitSetConcatenation(SetConcatenation node) => defaultExpression(node);
+ R visitMapConcatenation(MapConcatenation node) => defaultExpression(node);
R visitIsExpression(IsExpression node) => defaultExpression(node);
R visitAsExpression(AsExpression node) => defaultExpression(node);
R visitSymbolLiteral(SymbolLiteral node) => defaultExpression(node);
@@ -496,6 +502,12 @@
defaultExpression(node, arg);
R visitStringConcatenation(StringConcatenation node, T arg) =>
defaultExpression(node, arg);
+ R visitListConcatenation(ListConcatenation node, T arg) =>
+ defaultExpression(node, arg);
+ R visitSetConcatenation(SetConcatenation node, T arg) =>
+ defaultExpression(node, arg);
+ R visitMapConcatenation(MapConcatenation node, T arg) =>
+ defaultExpression(node, arg);
R visitIsExpression(IsExpression node, T arg) => defaultExpression(node, arg);
R visitAsExpression(AsExpression node, T arg) => defaultExpression(node, arg);
R visitSymbolLiteral(SymbolLiteral node, T arg) =>
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 02c4e5e..6072c7e 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -1,7 +1,7 @@
name: kernel
# Currently, kernel API is not stable and users should
# not depend on semver semantics when depending on this package.
-version: 0.3.13
+version: 0.3.14
author: Dart Team <misc@dartlang.org>
description: Dart IR (Intermediate Representation)
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index 803ac2b..1b1c268 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -249,6 +249,7 @@
name, architecture, compiler, mode, runtime, system,
builderTag: stringOption("builder-tag"),
vmOptions: stringListOption("vm-options"),
+ dart2jsOptions: stringListOption("dart2js-options"),
timeout: intOption("timeout"),
enableAsserts: boolOption("enable-asserts"),
isChecked: boolOption("checked"),
@@ -259,8 +260,6 @@
useAnalyzerCfe: boolOption("use-cfe"),
useAnalyzerFastaParser: boolOption("analyzer-use-fasta-parser"),
useBlobs: boolOption("use-blobs"),
- useDart2JSWithKernel: boolOption("dart2js-with-kernel"),
- useDart2JSOldFrontEnd: boolOption("dart2js-old-frontend"),
useHotReload: boolOption("hot-reload"),
useHotReloadRollback: boolOption("hot-reload-rollback"),
useSdk: boolOption("use-sdk"));
@@ -289,6 +288,8 @@
final List<String> vmOptions;
+ final List<String> dart2jsOptions;
+
int timeout;
final bool enableAsserts;
@@ -313,10 +314,6 @@
// TODO(rnystrom): What is this?
final bool useBlobs;
- // TODO(rnystrom): Remove these when Dart 1.0 is no longer supported.
- final bool useDart2JSWithKernel;
- final bool useDart2JSOldFrontEnd;
-
final bool useHotReload;
final bool useHotReloadRollback;
@@ -326,6 +323,7 @@
this.runtime, this.system,
{String builderTag,
List<String> vmOptions,
+ List<String> dart2jsOptions,
int timeout,
bool enableAsserts,
bool isChecked,
@@ -336,13 +334,12 @@
bool useAnalyzerCfe,
bool useAnalyzerFastaParser,
bool useBlobs,
- bool useDart2JSWithKernel,
- bool useDart2JSOldFrontEnd,
bool useHotReload,
bool useHotReloadRollback,
bool useSdk})
: builderTag = builderTag ?? "",
vmOptions = vmOptions ?? <String>[],
+ dart2jsOptions = dart2jsOptions ?? <String>[],
timeout = timeout,
enableAsserts = enableAsserts ?? false,
isChecked = isChecked ?? false,
@@ -353,8 +350,6 @@
useAnalyzerCfe = useAnalyzerCfe ?? false,
useAnalyzerFastaParser = useAnalyzerFastaParser ?? false,
useBlobs = useBlobs ?? false,
- useDart2JSWithKernel = useDart2JSWithKernel ?? false,
- useDart2JSOldFrontEnd = useDart2JSOldFrontEnd ?? false,
useHotReload = useHotReload ?? false,
useHotReloadRollback = useHotReloadRollback ?? false,
useSdk = useSdk ?? false;
@@ -369,6 +364,7 @@
system == other.system &&
builderTag == other.builderTag &&
vmOptions.join(" & ") == other.vmOptions.join(" & ") &&
+ dart2jsOptions.join(" & ") == other.dart2jsOptions.join(" & ") &&
timeout == other.timeout &&
enableAsserts == other.enableAsserts &&
isChecked == other.isChecked &&
@@ -379,8 +375,6 @@
useAnalyzerCfe == other.useAnalyzerCfe &&
useAnalyzerFastaParser == other.useAnalyzerFastaParser &&
useBlobs == other.useBlobs &&
- useDart2JSWithKernel == other.useDart2JSWithKernel &&
- useDart2JSOldFrontEnd == other.useDart2JSOldFrontEnd &&
useHotReload == other.useHotReload &&
useHotReloadRollback == other.useHotReloadRollback &&
useSdk == other.useSdk;
@@ -400,6 +394,7 @@
system.hashCode ^
builderTag.hashCode ^
vmOptions.join(" & ").hashCode ^
+ dart2jsOptions.join(" & ").hashCode ^
timeout.hashCode ^
_toBinary([
enableAsserts,
@@ -411,8 +406,6 @@
useAnalyzerCfe,
useAnalyzerFastaParser,
useBlobs,
- useDart2JSWithKernel,
- useDart2JSOldFrontEnd,
useHotReload,
useHotReloadRollback,
useSdk
@@ -432,6 +425,8 @@
if (builderTag != "") fields.add("builder-tag: $builderTag");
if (vmOptions != "") fields.add("vm-options: [${vmOptions.join(", ")}]");
+ if (dart2jsOptions != "")
+ fields.add("dart2js-options: [${dart2jsOptions.join(", ")}]");
if (timeout != 0) fields.add("timeout: $timeout");
if (enableAsserts) fields.add("enable-asserts");
if (isChecked) fields.add("checked");
@@ -442,8 +437,6 @@
if (useAnalyzerCfe) fields.add("use-cfe");
if (useAnalyzerFastaParser) fields.add("analyzer-use-fasta-parser");
if (useBlobs) fields.add("use-blobs");
- if (useDart2JSWithKernel) fields.add("dart2js-with-kernel");
- if (useDart2JSOldFrontEnd) fields.add("dart2js-old-frontend");
if (useHotReload) fields.add("hot-reload");
if (useHotReloadRollback) fields.add("hot-reload-rollback");
if (useSdk) fields.add("use-sdk");
@@ -475,6 +468,11 @@
var otherTag = "[${other.vmOptions.join(", ")}]";
fields.add("vm-options: $tag $otherTag");
}
+ if (dart2jsOptions != "" || other.dart2jsOptions != "") {
+ var tag = "[${dart2jsOptions.join(", ")}]";
+ var otherTag = "[${other.dart2jsOptions.join(", ")}]";
+ fields.add("dart2js-options: $tag $otherTag");
+ }
fields.add("timeout: $timeout ${other.timeout}");
if (enableAsserts || other.enableAsserts) {
fields.add("enable-asserts $enableAsserts ${other.enableAsserts}");
@@ -504,14 +502,6 @@
if (useBlobs || other.useBlobs) {
fields.add("useBlobs $useBlobs ${other.useBlobs}");
}
- if (useDart2JSWithKernel || other.useDart2JSWithKernel) {
- fields.add("useDart2JSWithKernel "
- "$useDart2JSWithKernel ${other.useDart2JSWithKernel}");
- }
- if (useDart2JSOldFrontEnd || other.useDart2JSOldFrontEnd) {
- fields.add("useDart2JSOldFrontEnd "
- "$useDart2JSOldFrontEnd ${other.useDart2JSOldFrontEnd}");
- }
if (useHotReload || other.useHotReload) {
fields.add("useHotReload $useHotReload ${other.useHotReload}");
}
diff --git a/pkg/smith/test/configuration_test.dart b/pkg/smith/test/configuration_test.dart
index 0952c72..9c77fb3 100644
--- a/pkg/smith/test/configuration_test.dart
+++ b/pkg/smith/test/configuration_test.dart
@@ -200,14 +200,13 @@
Configuration.parse("dart2js", {
"builder-tag": "the tag",
"vm-options": ["vm stuff", "more vm stuff"],
+ "dart2js-options": ["dart2js stuff", "more dart2js stuff"],
"enable-asserts": true,
"checked": true,
"csp": true,
"host-checked": true,
"minified": true,
"preview-dart-2": true,
- "dart2js-with-kernel": true,
- "dart2js-old-frontend": true,
"hot-reload": true,
"hot-reload-rollback": true,
"use-sdk": true,
@@ -221,14 +220,13 @@
System.host,
builderTag: "the tag",
vmOptions: ["vm stuff", "more vm stuff"],
+ dart2jsOptions: ["dart2js stuff", "more dart2js stuff"],
enableAsserts: true,
isChecked: true,
isCsp: true,
isHostChecked: true,
isMinified: true,
previewDart2: true,
- useDart2JSWithKernel: true,
- useDart2JSOldFrontEnd: true,
useHotReload: true,
useHotReloadRollback: true,
useSdk: true,
diff --git a/pkg/vm/bin/protobuf_aware_treeshaker.dart b/pkg/vm/bin/protobuf_aware_treeshaker.dart
new file mode 100644
index 0000000..b971b13
--- /dev/null
+++ b/pkg/vm/bin/protobuf_aware_treeshaker.dart
@@ -0,0 +1,169 @@
+#!/usr/bin/env dart
+// Copyright (c) 2019, 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 program will take a .dill file and do a protobuf aware tree-shaking.
+///
+/// All fields of GeneratedMessage subclasses that are not accessed with their
+/// getter or setter will have their metadata removed from the class definition.
+///
+/// Then a general treeshaking will be run, and
+/// all GeneratedMessage subclasses that are never used directly will be
+/// removed.
+///
+/// The processed program will have observable differences: The tree-shaken
+/// fields will be parsed as unknown fields.
+/// The toString method will treat the unknown fields as missing.
+///
+/// Using the `GeneratedMessage.info_` field to reflect on fields will have
+/// unpredictable behavior.
+///
+/// Constants are evaluated, this is mainly to enable detecting
+/// `@pragma('vm:entry-point')`.
+library vm.protobuf_aware_treeshaker;
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:args/args.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/binary/limited_ast_to_binary.dart';
+import 'package:kernel/target/targets.dart' show TargetFlags, getTarget;
+import 'package:meta/meta.dart';
+import 'package:vm/target/install.dart' show installAdditionalTargets;
+import 'package:vm/transformations/protobuf_aware_treeshaker/transformer.dart'
+ as treeshaker;
+
+ArgResults parseArgs(List<String> args) {
+ ArgParser argParser = ArgParser()
+ ..addOption('platform',
+ valueHelp: "path/to/vm_platform.dill",
+ help: 'A platform.dill file to append to the input. If not given, no '
+ 'platform.dill will be appended.')
+ ..addOption('target',
+ allowed: ['dart_runner', 'flutter', 'flutter-runner', 'vm'],
+ defaultsTo: 'vm',
+ help: 'A platform.dill file to append to the input. If not given, no '
+ 'platform.dill will be appended.')
+ ..addFlag('write-txt',
+ help: 'Also write the result in kernel-text format as <out.dill>.txt',
+ defaultsTo: false)
+ ..addFlag('remove-core-libs',
+ help:
+ 'If set, the resulting dill file will not include `dart:` libraries',
+ defaultsTo: false)
+ ..addMultiOption('define',
+ abbr: 'D',
+ help: 'Perform constant evaluation with this environment define set.',
+ valueHelp: 'variable=value')
+ ..addFlag('remove-source',
+ help: 'Removes source code from the emitted dill', defaultsTo: false)
+ ..addFlag('enable-asserts',
+ help: 'Enables asserts in the emitted dill', defaultsTo: false)
+ ..addFlag('verbose',
+ help: 'Write to stdout about what classes and fields where remeoved')
+ ..addFlag('help', help: 'Prints this help', negatable: false);
+
+ ArgResults argResults;
+ try {
+ argResults = argParser.parse(args);
+ } on FormatException catch (e) {
+ print(e.message);
+ }
+ if (argResults == null || argResults['help'] || argResults.rest.length != 2) {
+ String script = 'protobuf_aware_treeshaker.dart';
+ print(
+ 'A tool for removing protobuf messages types that are never referred by a program');
+ print('Usage: $script [args] <input.dill> <output.dill>');
+
+ print(argParser.usage);
+ exit(-1);
+ }
+
+ return argResults;
+}
+
+Future main(List<String> args) async {
+ ArgResults argResults = parseArgs(args);
+
+ final input = argResults.rest[0];
+ final output = argResults.rest[1];
+
+ final Map<String, String> environment = Map.fromIterable(
+ argResults['define'].map((x) => x.split('=')),
+ key: (x) => x[0],
+ value: (x) => x[1]);
+
+ var bytes = File(input).readAsBytesSync();
+ final platformFile = argResults['platform'];
+ if (platformFile != null) {
+ bytes = concatenate(File(platformFile).readAsBytesSync(), bytes);
+ }
+ final component = loadComponentFromBytes(bytes);
+
+ installAdditionalTargets();
+
+ treeshaker.TransformationInfo info = treeshaker.transformComponent(
+ component, environment, getTarget(argResults['target'], TargetFlags()),
+ collectInfo: argResults['verbose'],
+ enableAsserts: argResults['enable-asserts']);
+
+ if (argResults['verbose']) {
+ for (String fieldName in info.removedMessageFields) {
+ print('Removed $fieldName');
+ }
+ for (Class removedClass in info.removedMessageClasses) {
+ print('Removed $removedClass');
+ }
+ }
+
+ await writeComponent(component, output,
+ removeCoreLibs: argResults['remove-core-libs'],
+ removeSource: argResults['remove-source']);
+ if (argResults['write-txt']) {
+ writeComponentToText(component, path: output + '.txt');
+ }
+}
+
+Uint8List concatenate(Uint8List a, Uint8List b) {
+ final bytes = Uint8List(a.length + b.length);
+ bytes.setRange(0, a.length, a);
+ bytes.setRange(a.length, a.length + b.length, b);
+ return bytes;
+}
+
+Future writeComponent(Component component, String filename,
+ {@required bool removeCoreLibs, @required bool removeSource}) async {
+ if (removeSource) {
+ component.uriToSource.clear();
+ }
+
+ for (final lib in component.libraries) {
+ lib.dependencies.clear();
+ lib.additionalExports.clear();
+ lib.parts.clear();
+ }
+
+ final sink = File(filename).openWrite();
+ final printer = LimitedBinaryPrinter(sink, (lib) {
+ if (removeCoreLibs && isCoreLibrary(lib)) return false;
+ if (isLibEmpty(lib)) return false;
+ return true;
+ }, /*excludeUriToSource=*/ removeSource);
+
+ printer.writeComponentFile(component);
+ await sink.close();
+}
+
+bool isLibEmpty(Library lib) {
+ return lib.classes.isEmpty &&
+ lib.procedures.isEmpty &&
+ lib.fields.isEmpty &&
+ lib.typedefs.isEmpty;
+}
+
+bool isCoreLibrary(Library library) {
+ return library.importUri.scheme == 'dart';
+}
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index e0b9cfc..ecd0c8e 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -28,6 +28,7 @@
import 'package:vm/incremental_compiler.dart' show IncrementalCompiler;
import 'package:vm/kernel_front_end.dart'
show
+ asFileUri,
compileToKernel,
parseCommandLineDefines,
convertFileOrUriArgumentToUri,
@@ -115,16 +116,16 @@
String usage = '''
Usage: server [options] [input.dart]
-If input dart source code is provided on the command line, then the server
-compiles it, generates dill file and exits.
-If no input dart source is provided on the command line, server waits for
+If filename or uri pointing to the entrypoint is provided on the command line,
+then the server compiles it, generates dill file and exits.
+If no entrypoint is provided on the command line, server waits for
instructions from stdin.
Instructions:
- compile <input.dart>
- recompile [<input.dart>] <boundary-key>
-<path/to/updated/file1.dart>
-<path/to/updated/file2.dart>
+<invalidated file uri>
+<invalidated file uri>
...
<boundary-key>
- accept
@@ -152,20 +153,20 @@
/// Actions that every compiler should implement.
abstract class CompilerInterface {
- /// Compile given Dart program identified by `filename` with given list of
+ /// Compile given Dart program identified by `entryPoint` with given list of
/// `options`. When `generator` parameter is omitted, new instance of
/// `IncrementalKernelGenerator` is created by this method. Main use for this
/// parameter is for mocking in tests.
/// Returns [true] if compilation was successful and produced no errors.
Future<bool> compile(
- String filename,
+ String entryPoint,
ArgResults options, {
IncrementalCompiler generator,
});
/// Assuming some Dart program was previously compiled, recompile it again
/// taking into account some changed(invalidated) sources.
- Future<Null> recompileDelta({String filename});
+ Future<Null> recompileDelta({String entryPoint});
/// Accept results of previous compilation so that next recompilation cycle
/// won't recompile sources that were previously reported as changed.
@@ -240,30 +241,27 @@
String _kernelBinaryFilenameFull;
String _initializeFromDill;
+ Set<Uri> previouslyReportedDependencies = Set<Uri>();
+
final ProgramTransformer transformer;
final List<String> errors = new List<String>();
- void setMainSourceFilename(String filename) {
- final Uri filenameUri = _getFileOrUri(filename);
- _mainSource = filenameUri;
- }
-
@override
Future<bool> compile(
- String filename,
+ String entryPoint,
ArgResults options, {
IncrementalCompiler generator,
}) async {
_options = options;
_fileSystem = createFrontEndFileSystem(
options['filesystem-scheme'], options['filesystem-root']);
- setMainSourceFilename(filename);
- _kernelBinaryFilenameFull = _options['output-dill'] ?? '$filename.dill';
+ _mainSource = _getFileOrUri(entryPoint);
+ _kernelBinaryFilenameFull = _options['output-dill'] ?? '$entryPoint.dill';
_kernelBinaryFilenameIncremental = _options['output-incremental-dill'] ??
(_options['output-dill'] != null
? '${_options['output-dill']}.incremental.dill'
- : '$filename.incremental.dill');
+ : '$entryPoint.incremental.dill');
_kernelBinaryFilename = _kernelBinaryFilenameFull;
_initializeFromDill =
_options['initialize-from-dill'] ?? _kernelBinaryFilenameFull;
@@ -360,6 +358,8 @@
await writeDillFile(component, _kernelBinaryFilename,
filterExternal: importDill != null);
+ _outputStream.writeln(boundaryKey);
+ await _outputDependenciesDelta(component);
_outputStream
.writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
final String depfile = options['depfile'];
@@ -374,6 +374,27 @@
return errors.isEmpty;
}
+ void _outputDependenciesDelta(Component component) async {
+ Set<Uri> uris = new Set<Uri>();
+ for (Uri uri in component.uriToSource.keys) {
+ // Skip empty or corelib dependencies.
+ if (uri == null || uri.scheme == 'org-dartlang-sdk') continue;
+ uris.add(uri);
+ }
+ for (Uri uri in uris) {
+ if (previouslyReportedDependencies.contains(uri)) {
+ continue;
+ }
+ _outputStream.writeln('+${await asFileUri(_fileSystem, uri)}');
+ }
+ for (Uri uri in previouslyReportedDependencies) {
+ if (!uris.contains(uri)) {
+ _outputStream.writeln('-${await asFileUri(_fileSystem, uri)}');
+ }
+ }
+ previouslyReportedDependencies = uris;
+ }
+
writeDillFile(Component component, String filename,
{bool filterExternal: false}) async {
final IOSink sink = new File(filename).openWrite();
@@ -458,12 +479,12 @@
}
@override
- Future<Null> recompileDelta({String filename}) async {
+ Future<Null> recompileDelta({String entryPoint}) async {
final String boundaryKey = new Uuid().generateV4();
_outputStream.writeln('result $boundaryKey');
await invalidateIfInitializingFromDill();
- if (filename != null) {
- setMainSourceFilename(filename);
+ if (entryPoint != null) {
+ _mainSource = _getFileOrUri(entryPoint);
}
errors.clear();
final Component deltaProgram =
@@ -473,6 +494,8 @@
transformer.transform(deltaProgram);
}
await writeDillFile(deltaProgram, _kernelBinaryFilename);
+ _outputStream.writeln(boundaryKey);
+ await _outputDependenciesDelta(deltaProgram);
_outputStream
.writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
_kernelBinaryFilename = _kernelBinaryFilenameIncremental;
@@ -683,7 +706,7 @@
_State state = _State.READY_FOR_INSTRUCTION;
_CompileExpressionRequest compileExpressionRequest;
String boundaryKey;
- String recompileFilename;
+ String recompileEntryPoint;
input
.transform(utf8.decoder)
.transform(const LineSplitter())
@@ -695,17 +718,17 @@
const String COMPILE_EXPRESSION_INSTRUCTION_SPACE =
'compile-expression ';
if (string.startsWith(COMPILE_INSTRUCTION_SPACE)) {
- final String filename =
+ final String entryPoint =
string.substring(COMPILE_INSTRUCTION_SPACE.length);
- await compiler.compile(filename, options, generator: generator);
+ await compiler.compile(entryPoint, options, generator: generator);
} else if (string.startsWith(RECOMPILE_INSTRUCTION_SPACE)) {
- // 'recompile [<filename>] <boundarykey>'
+ // 'recompile [<entryPoint>] <boundarykey>'
// where <boundarykey> can't have spaces
final String remainder =
string.substring(RECOMPILE_INSTRUCTION_SPACE.length);
final int spaceDelim = remainder.lastIndexOf(' ');
if (spaceDelim > -1) {
- recompileFilename = remainder.substring(0, spaceDelim);
+ recompileEntryPoint = remainder.substring(0, spaceDelim);
boundaryKey = remainder.substring(spaceDelim + 1);
} else {
boundaryKey = remainder;
@@ -739,7 +762,7 @@
break;
case _State.RECOMPILE_LIST:
if (string == boundaryKey) {
- compiler.recompileDelta(filename: recompileFilename);
+ compiler.recompileDelta(entryPoint: recompileEntryPoint);
state = _State.READY_FOR_INSTRUCTION;
} else
compiler.invalidate(Uri.base.resolve(string));
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 78063e2..9313820 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -517,7 +517,7 @@
/// absolute URI.
///
/// If virtual multi-root file system is used, or [input] can be parsed to a
-/// URI with 'package' scheme, then [input] is interpreted as URI.
+/// URI with 'package' or 'file' scheme, then [input] is interpreted as URI.
/// Otherwise [input] is interpreted as a file path.
Uri convertFileOrUriArgumentToUri(FileSystem fileSystem, String input) {
if (input == null) {
@@ -530,7 +530,7 @@
}
try {
Uri uri = Uri.parse(input);
- if (uri.scheme == 'package') {
+ if (uri.scheme == 'package' || uri.scheme == 'file') {
return uri;
}
} on FormatException {
diff --git a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
new file mode 100644
index 0000000..fba5844
--- /dev/null
+++ b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
@@ -0,0 +1,270 @@
+// Copyright (c) 2019, 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:kernel/kernel.dart';
+import 'package:kernel/target/targets.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/transformations/constants.dart' as constants;
+import 'package:kernel/vm/constants_native_effects.dart' as vm_constants;
+import 'package:meta/meta.dart';
+import 'package:vm/transformations/type_flow/transformer.dart' as globalTypeFlow
+ show transformComponent;
+import 'package:vm/transformations/no_dynamic_invocations_annotator.dart'
+ show Selector;
+
+class TransformationInfo {
+ final List<String> removedMessageFields = <String>[];
+ final List<Class> removedMessageClasses = <Class>[];
+}
+
+TransformationInfo transformComponent(
+ Component component, Map<String, String> environment, Target target,
+ {@required bool collectInfo, @required bool enableAsserts}) {
+ final coreTypes = new CoreTypes(component);
+ component.computeCanonicalNames();
+
+ // Evaluate constants to ensure @pragma("vm:entry-point") is seen by the
+ // type-flow analysis.
+ final vmConstants = new vm_constants.VmConstantsBackend(coreTypes);
+ constants.transformComponent(component, vmConstants, environment, null,
+ keepFields: true,
+ evaluateAnnotations: true,
+ enableAsserts: enableAsserts);
+
+ TransformationInfo info = collectInfo ? TransformationInfo() : null;
+
+ _treeshakeProtos(target, component, coreTypes, info);
+ return info;
+}
+
+void _treeshakeProtos(Target target, Component component, CoreTypes coreTypes,
+ TransformationInfo info) {
+ globalTypeFlow.transformComponent(target, coreTypes, component);
+ final collector = _removeUnusedProtoReferences(component, coreTypes, info);
+ if (collector == null) {
+ return;
+ }
+ globalTypeFlow.transformComponent(target, coreTypes, component);
+ if (info != null) {
+ for (Class gmSubclass in collector.gmSubclasses) {
+ if (!gmSubclass.enclosingLibrary.classes.contains(gmSubclass)) {
+ info.removedMessageClasses.add(gmSubclass);
+ }
+ }
+ }
+ // Remove metadata added by the typeflow analysis.
+ component.metadata.clear();
+}
+
+InfoCollector _removeUnusedProtoReferences(
+ Component component, CoreTypes coreTypes, TransformationInfo info) {
+ final protobufUri = Uri.parse('package:protobuf/protobuf.dart');
+ final protobufLibs =
+ component.libraries.where((lib) => lib.importUri == protobufUri);
+ if (protobufLibs.isEmpty) {
+ return null;
+ }
+ final protobufLib = protobufLibs.single;
+
+ final gmClass = protobufLib.classes
+ .where((klass) => klass.name == 'GeneratedMessage')
+ .single;
+ final collector = InfoCollector(gmClass);
+
+ final biClass =
+ protobufLib.classes.where((klass) => klass.name == 'BuilderInfo').single;
+ final addMethod =
+ biClass.members.singleWhere((Member member) => member.name.name == 'add');
+
+ component.accept(collector);
+
+ _UnusedFieldMetadataPruner(
+ biClass, addMethod, collector.dynamicSelectors, coreTypes, info)
+ .removeMetadataForUnusedFields(
+ collector.gmSubclasses,
+ collector.gmSubclassesInvokedMethods,
+ coreTypes,
+ info,
+ );
+
+ return collector;
+}
+
+/// For protobuf fields which are not accessed, prune away its metadata.
+class _UnusedFieldMetadataPruner extends TreeVisitor<void> {
+ // All of those methods have the dart field name as second positional
+ // parameter.
+ // Method names are defined in:
+ // https://github.com/dart-lang/protobuf/blob/master/protobuf/lib/src/protobuf/builder_info.dart
+ // The code is generated by:
+ // https://github.com/dart-lang/protobuf/blob/master/protoc_plugin/lib/protobuf_field.dart.
+ static final fieldAddingMethods = Set<String>.from(const <String>[
+ 'a',
+ 'm',
+ 'pp',
+ 'pc',
+ 'e',
+ 'pc',
+ 'aOS',
+ 'aOB',
+ ]);
+
+ final Class builderInfoClass;
+ Class visitedClass;
+ final names = Set<String>();
+
+ final dynamicNames = Set<String>();
+ final CoreTypes coreTypes;
+ final TransformationInfo info;
+ final Member addMethod;
+
+ _UnusedFieldMetadataPruner(this.builderInfoClass, this.addMethod,
+ Set<Selector> dynamicSelectors, this.coreTypes, this.info) {
+ dynamicNames.addAll(dynamicSelectors.map((sel) => sel.target.name));
+ }
+
+ /// If a proto message field is never accessed (neither read nor written to),
+ /// remove its corresponding metadata in the construction of the Message._i
+ /// field (i.e. the BuilderInfo metadata).
+ void removeMetadataForUnusedFields(
+ Set<Class> gmSubclasses,
+ Map<Class, Set<Selector>> invokedMethods,
+ CoreTypes coreTypes,
+ TransformationInfo info) {
+ for (final klass in gmSubclasses) {
+ final selectors = invokedMethods[klass] ?? Set<Selector>();
+ final builderInfoFields = klass.fields.where((f) => f.name.name == '_i');
+ if (builderInfoFields.isEmpty) {
+ continue;
+ }
+ final builderInfoField = builderInfoFields.single;
+ _pruneBuilderInfoField(builderInfoField, selectors, klass);
+ }
+ }
+
+ void _pruneBuilderInfoField(
+ Field field, Set<Selector> selectors, Class gmSubclass) {
+ names.clear();
+ names.addAll(selectors.map((sel) => sel.target.name));
+ visitedClass = gmSubclass;
+ field.initializer.accept(this);
+ }
+
+ @override
+ visitLet(Let node) {
+ final initializer = node.variable.initializer;
+ if (initializer is MethodInvocation &&
+ initializer.interfaceTarget?.enclosingClass == builderInfoClass &&
+ fieldAddingMethods.contains(initializer.name.name)) {
+ final fieldName =
+ (initializer.arguments.positional[1] as StringLiteral).value;
+ final ucase = fieldName[0].toUpperCase() + fieldName.substring(1);
+ // The name of the related `clear` method.
+ final clearName = 'clear${ucase}';
+ // The name of the related `has` method.
+ final hasName = 'has${ucase}';
+
+ bool nameIsUsed(String name) =>
+ dynamicNames.contains(name) || names.contains(name);
+
+ if (!(nameIsUsed(fieldName) ||
+ nameIsUsed(clearName) ||
+ nameIsUsed(hasName))) {
+ if (info != null) {
+ info.removedMessageFields.add("${visitedClass.name}.$fieldName");
+ }
+
+ // Replace the field metadata method with a dummy call to
+ // `BuilderInfo.add`. This is to preserve the index calculations when
+ // removing a field.
+ // Change the tag-number to 0. Otherwise the decoder will get confused.
+ initializer.interfaceTarget = addMethod;
+ initializer.name = addMethod.name;
+ initializer.arguments.replaceWith(
+ Arguments(
+ <Expression>[
+ IntLiteral(0), // tagNumber
+ NullLiteral(), // name
+ NullLiteral(), // fieldType
+ NullLiteral(), // defaultOrMaker
+ NullLiteral(), // subBuilder
+ NullLiteral(), // valueOf
+ NullLiteral(), // enumValues
+ ],
+ types: <DartType>[InterfaceType(coreTypes.nullClass)],
+ ),
+ );
+ }
+ }
+ node.body.accept(this);
+ }
+}
+
+/// Finds all subclasses of [GeneratedMessage] and all methods invoked on them
+/// (potentially in a dynamic call).
+class InfoCollector extends RecursiveVisitor<void> {
+ final dynamicSelectors = Set<Selector>();
+ final Class generatedMessageClass;
+ final gmSubclasses = Set<Class>();
+ final gmSubclassesInvokedMethods = Map<Class, Set<Selector>>();
+
+ InfoCollector(this.generatedMessageClass);
+
+ @override
+ visitClass(Class klass) {
+ if (isGeneratedMethodSubclass(klass)) {
+ gmSubclasses.add(klass);
+ }
+ return super.visitClass(klass);
+ }
+
+ @override
+ visitMethodInvocation(MethodInvocation node) {
+ if (node.interfaceTarget == null) {
+ dynamicSelectors.add(Selector.doInvoke(node.name));
+ }
+
+ final targetClass = node.interfaceTarget?.enclosingClass;
+ if (isGeneratedMethodSubclass(targetClass)) {
+ addInvokedMethod(targetClass, Selector.doInvoke(node.name));
+ }
+ super.visitMethodInvocation(node);
+ }
+
+ @override
+ visitPropertyGet(PropertyGet node) {
+ if (node.interfaceTarget == null) {
+ dynamicSelectors.add(Selector.doGet(node.name));
+ }
+
+ final targetClass = node.interfaceTarget?.enclosingClass;
+ if (isGeneratedMethodSubclass(targetClass)) {
+ addInvokedMethod(targetClass, Selector.doGet(node.name));
+ }
+ super.visitPropertyGet(node);
+ }
+
+ @override
+ visitPropertySet(PropertySet node) {
+ if (node.interfaceTarget == null) {
+ dynamicSelectors.add(Selector.doSet(node.name));
+ }
+
+ final targetClass = node.interfaceTarget?.enclosingClass;
+ if (isGeneratedMethodSubclass(targetClass)) {
+ addInvokedMethod(targetClass, Selector.doSet(node.name));
+ }
+ super.visitPropertySet(node);
+ }
+
+ bool isGeneratedMethodSubclass(Class klass) {
+ return klass?.superclass == generatedMessageClass;
+ }
+
+ void addInvokedMethod(Class klass, Selector selector) {
+ final selectors =
+ gmSubclassesInvokedMethods.putIfAbsent(klass, () => Set<Selector>());
+ selectors.add(selector);
+ }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index f4e50e7..23f8d8b 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -870,6 +870,12 @@
}
@override
+ TypeExpr visitBlockExpression(BlockExpression node) {
+ _visit(node.body);
+ return _visit(node.value);
+ }
+
+ @override
TypeExpr visitListLiteral(ListLiteral node) {
node.expressions.forEach(_visit);
Class concreteClass =
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 4a4a7d8..bf7bf47 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -179,7 +179,7 @@
new StreamController<List<int>>();
final ReceivePort recompileCalled = new ReceivePort();
- when(compiler.recompileDelta(filename: null))
+ when(compiler.recompileDelta(entryPoint: null))
.thenAnswer((Invocation invocation) {
recompileCalled.sendPort.send(true);
});
@@ -195,7 +195,7 @@
verifyInOrder(<void>[
compiler.invalidate(Uri.base.resolve('file1.dart')),
compiler.invalidate(Uri.base.resolve('file2.dart')),
- await compiler.recompileDelta(filename: null),
+ await compiler.recompileDelta(entryPoint: null),
]);
inputStreamController.add('quit\n'.codeUnits);
expect(await result, 0);
@@ -207,7 +207,7 @@
new StreamController<List<int>>();
final ReceivePort recompileCalled = new ReceivePort();
- when(compiler.recompileDelta(filename: 'file2.dart'))
+ when(compiler.recompileDelta(entryPoint: 'file2.dart'))
.thenAnswer((Invocation invocation) {
recompileCalled.sendPort.send(true);
});
@@ -223,7 +223,7 @@
verifyInOrder(<void>[
compiler.invalidate(Uri.base.resolve('file1.dart')),
compiler.invalidate(Uri.base.resolve('file2.dart')),
- await compiler.recompileDelta(filename: 'file2.dart'),
+ await compiler.recompileDelta(entryPoint: 'file2.dart'),
]);
inputStreamController.add('quit\n'.codeUnits);
expect(await result, 0);
@@ -274,7 +274,7 @@
new StreamController<List<int>>();
final ReceivePort recompileCalled = new ReceivePort();
- when(compiler.recompileDelta(filename: null))
+ when(compiler.recompileDelta(entryPoint: null))
.thenAnswer((Invocation invocation) {
recompileCalled.sendPort.send(true);
});
@@ -295,7 +295,7 @@
compiler.acceptLastDelta(),
compiler.invalidate(Uri.base.resolve('file2.dart')),
compiler.invalidate(Uri.base.resolve('file3.dart')),
- await compiler.recompileDelta(filename: null),
+ await compiler.recompileDelta(entryPoint: null),
]);
inputStreamController.add('quit\n'.codeUnits);
expect(await result, 0);
@@ -426,41 +426,25 @@
final StreamController<List<int>> stdoutStreamController =
new StreamController<List<int>>();
final IOSink ioSink = new IOSink(stdoutStreamController.sink);
- StreamController<String> receivedResults = new StreamController<String>();
-
- String boundaryKey;
+ StreamController<Result> receivedResults = new StreamController<Result>();
+ final outputParser = new OutputParser(receivedResults);
stdoutStreamController.stream
.transform(utf8.decoder)
.transform(const LineSplitter())
- .listen((String s) {
- const String RESULT_OUTPUT_SPACE = 'result ';
- if (boundaryKey == null) {
- if (s.startsWith(RESULT_OUTPUT_SPACE)) {
- boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
- }
- } else {
- if (s.startsWith(boundaryKey)) {
- receivedResults.add(s.length > boundaryKey.length
- ? s.substring(boundaryKey.length + 1)
- : null);
- boundaryKey = null;
- }
- }
- });
+ .listen(outputParser.listener);
Future<int> result =
starter(args, input: streamController.stream, output: ioSink);
streamController.add('compile ${file.path}\n'.codeUnits);
int count = 0;
- receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+ receivedResults.stream.listen((Result compiledResult) {
+ CompilationResult result =
+ new CompilationResult.parse(compiledResult.status);
if (count == 0) {
// First request is to 'compile', which results in full kernel file.
- CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
-
+ expect(result.errorsCount, equals(0));
expect(dillFile.existsSync(), equals(true));
expect(result.filename, dillFile.path);
- expect(result.errorsCount, equals(0));
streamController.add('accept\n'.codeUnits);
// 'compile-expression <boundarykey>
@@ -474,26 +458,25 @@
// <libraryUri: String>
// <klass: String>
// <isStatic: true|false>
+ outputParser.expectSources = false;
streamController.add(
'compile-expression abc\n2+2\nabc\nabc\n${file.uri}\n\n\n'
.codeUnits);
count += 1;
} else if (count == 1) {
+ expect(result.errorsCount, isNull);
// Previous request should have failed because isStatic was blank
- expect(outputFilenameAndErrorCount, isNull);
+ expect(compiledResult.status, isNull);
+ outputParser.expectSources = false;
streamController.add(
'compile-expression abc\n2+2\nabc\nabc\n${file.uri}\n\nfalse\n'
.codeUnits);
count += 1;
} else if (count == 2) {
+ expect(result.errorsCount, equals(0));
// Second request is to 'compile-expression', which results in
// kernel file with a function that wraps compiled expression.
- expect(outputFilenameAndErrorCount, isNotNull);
- CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
-
- expect(result.errorsCount, equals(0));
File outputFile = new File(result.filename);
expect(outputFile.existsSync(), equals(true));
expect(outputFile.lengthSync(), isPositive);
@@ -503,9 +486,6 @@
} else {
expect(count, 3);
// Third request is to 'compile' non-existent file, that should fail.
- expect(outputFilenameAndErrorCount, isNotNull);
- CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
expect(result.errorsCount, greaterThan(0));
streamController.add('quit\n'.codeUnits);
@@ -515,6 +495,126 @@
expect(await result, 0);
});
+ test('compiler reports correct sources added', () async {
+ var libFile = new File('${tempDir.path}/lib.dart')
+ ..createSync(recursive: true)
+ ..writeAsStringSync("var foo = 42;");
+ var mainFile = new File('${tempDir.path}/main.dart')
+ ..createSync(recursive: true)
+ ..writeAsStringSync("main() => print('foo');\n");
+ var dillFile = new File('${tempDir.path}/app.dill');
+ expect(dillFile.existsSync(), equals(false));
+ final List<String> args = <String>[
+ '--sdk-root=${sdkRoot.toFilePath()}',
+ '--incremental',
+ '--platform=${platformKernel.path}',
+ '--output-dill=${dillFile.path}'
+ ];
+
+ final StreamController<List<int>> inputStreamController =
+ new StreamController<List<int>>();
+ final StreamController<List<int>> stdoutStreamController =
+ new StreamController<List<int>>();
+ final IOSink ioSink = new IOSink(stdoutStreamController.sink);
+ StreamController<Result> receivedResults = new StreamController<Result>();
+
+ final outputParser = new OutputParser(receivedResults);
+ stdoutStreamController.stream
+ .transform(utf8.decoder)
+ .transform(const LineSplitter())
+ .listen(outputParser.listener);
+
+ final Future<int> result =
+ starter(args, input: inputStreamController.stream, output: ioSink);
+ inputStreamController.add('compile ${mainFile.path}\n'.codeUnits);
+ int count = 0;
+ receivedResults.stream.listen((Result compiledResult) {
+ compiledResult.expectNoErrors();
+ if (count == 0) {
+ expect(compiledResult.sources.length, equals(1));
+ expect(compiledResult.sources, contains('+${mainFile.uri}'));
+
+ inputStreamController.add('accept\n'.codeUnits);
+ mainFile
+ .writeAsStringSync("import 'lib.dart'; main() => print(foo);\n");
+ inputStreamController.add('recompile ${mainFile.path} abc\n'
+ '${mainFile.uri}\n'
+ 'abc\n'
+ .codeUnits);
+ count += 1;
+ } else if (count == 1) {
+ expect(compiledResult.sources.length, equals(1));
+ expect(compiledResult.sources, contains('+${libFile.uri}'));
+ inputStreamController.add('accept\n'.codeUnits);
+ inputStreamController.add('quit\n'.codeUnits);
+ }
+ });
+
+ expect(await result, 0);
+ inputStreamController.close();
+ }, timeout: Timeout.factor(100));
+
+ test('compiler reports correct sources removed', () async {
+ var libFile = new File('${tempDir.path}/lib.dart')
+ ..createSync(recursive: true)
+ ..writeAsStringSync("var foo = 42;");
+ var mainFile = new File('${tempDir.path}/main.dart')
+ ..createSync(recursive: true)
+ ..writeAsStringSync("import 'lib.dart'; main() => print(foo);\n");
+ var dillFile = new File('${tempDir.path}/app.dill');
+ expect(dillFile.existsSync(), equals(false));
+ final List<String> args = <String>[
+ '--sdk-root=${sdkRoot.toFilePath()}',
+ '--incremental',
+ '--platform=${platformKernel.path}',
+ '--output-dill=${dillFile.path}'
+ ];
+
+ final StreamController<List<int>> inputStreamController =
+ new StreamController<List<int>>();
+ final StreamController<List<int>> stdoutStreamController =
+ new StreamController<List<int>>();
+ final IOSink ioSink = new IOSink(stdoutStreamController.sink);
+ StreamController<Result> receivedResults = new StreamController<Result>();
+
+ final outputParser = new OutputParser(receivedResults);
+ stdoutStreamController.stream
+ .transform(utf8.decoder)
+ .transform(const LineSplitter())
+ .listen(outputParser.listener);
+
+ final Future<int> result =
+ starter(args, input: inputStreamController.stream, output: ioSink);
+ inputStreamController.add('compile ${mainFile.path}\n'.codeUnits);
+ int count = 0;
+ receivedResults.stream.listen((Result compiledResult) {
+ compiledResult.expectNoErrors();
+ if (count == 0) {
+ expect(compiledResult.sources.length, equals(2));
+ expect(compiledResult.sources,
+ allOf(contains('+${mainFile.uri}'), contains('+${libFile.uri}')));
+
+ inputStreamController.add('accept\n'.codeUnits);
+ mainFile.writeAsStringSync("main() => print('foo');\n");
+ inputStreamController.add('recompile ${mainFile.path} abc\n'
+ '${mainFile.uri}\n'
+ 'abc\n'
+ .codeUnits);
+ count += 1;
+ } else if (count == 1) {
+ expect(compiledResult.sources.length, equals(1));
+ expect(compiledResult.sources, contains('-${libFile.uri}'));
+ inputStreamController.add('accept\n'.codeUnits);
+ inputStreamController.add('quit\n'.codeUnits);
+ }
+ });
+
+ expect(await result, 0);
+ inputStreamController.close();
+ },
+ timeout: Timeout.factor(100),
+ skip: true /* TODO(dartbug/36197): Unskip when compiler is fixed. */);
+
test('compile expression when delta is rejected', () async {
var fileLib = new File('${tempDir.path}/lib.dart')..createSync();
fileLib.writeAsStringSync("foo() => 42;\n");
@@ -534,42 +634,26 @@
final StreamController<List<int>> stdoutStreamController =
new StreamController<List<int>>();
final IOSink ioSink = new IOSink(stdoutStreamController.sink);
- StreamController<String> receivedResults = new StreamController<String>();
+ StreamController<Result> receivedResults = new StreamController<Result>();
- String boundaryKey;
+ final outputParser = new OutputParser(receivedResults);
stdoutStreamController.stream
.transform(utf8.decoder)
.transform(const LineSplitter())
- .listen((String s) {
- print(s);
- const String RESULT_OUTPUT_SPACE = 'result ';
- if (boundaryKey == null) {
- if (s.startsWith(RESULT_OUTPUT_SPACE)) {
- boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
- }
- } else {
- if (s.startsWith(boundaryKey)) {
- receivedResults.add(s.length > boundaryKey.length
- ? s.substring(boundaryKey.length + 1)
- : null);
- boundaryKey = null;
- }
- }
- });
+ .listen(outputParser.listener);
final Future<int> result =
starter(args, input: inputStreamController.stream, output: ioSink);
inputStreamController.add('compile ${file.path}\n'.codeUnits);
int count = 0;
- receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+ receivedResults.stream.listen((Result compiledResult) {
+ CompilationResult result =
+ new CompilationResult.parse(compiledResult.status);
if (count == 0) {
// First request was to 'compile', which resulted in full kernel file.
- CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
-
+ expect(result.errorsCount, 0);
expect(dillFile.existsSync(), equals(true));
expect(result.filename, dillFile.path);
- expect(result.errorsCount, equals(0));
inputStreamController.add('accept\n'.codeUnits);
// 'compile-expression <boundarykey>
@@ -583,6 +667,7 @@
// <libraryUri: String>
// <klass: String>
// <isStatic: true|false>
+ outputParser.expectSources = false;
inputStreamController.add('''
compile-expression abc
main1
@@ -597,12 +682,7 @@
} else if (count == 1) {
// Second request was to 'compile-expression', which resulted in
// kernel file with a function that wraps compiled expression.
- expect(outputFilenameAndErrorCount, isNotNull);
- CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
- print(outputFilenameAndErrorCount);
-
- expect(result.errorsCount, equals(0));
+ expect(result.errorsCount, 0);
File outputFile = new File(result.filename);
expect(outputFile.existsSync(), equals(true));
expect(outputFile.lengthSync(), isPositive);
@@ -616,15 +696,13 @@
count += 1;
} else if (count == 2) {
// Third request was to recompile the script after renaming a function.
- expect(outputFilenameAndErrorCount, isNotNull);
- CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
- expect(result.errorsCount, equals(0));
-
+ expect(result.errorsCount, 0);
+ outputParser.expectSources = false;
inputStreamController.add('reject\n'.codeUnits);
count += 1;
} else if (count == 3) {
// Fourth request was to reject the compilation results.
+ outputParser.expectSources = false;
inputStreamController.add(
'compile-expression abc\nmain1\nabc\nabc\n${file.uri}\n\ntrue\n'
.codeUnits);
@@ -633,10 +711,7 @@
expect(count, 4);
// Fifth request was to 'compile-expression' that references original
// function, which should still be successful.
- expect(outputFilenameAndErrorCount, isNotNull);
- CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
- expect(result.errorsCount, equals(0));
+ expect(result.errorsCount, 0);
inputStreamController.add('quit\n'.codeUnits);
}
});
@@ -662,37 +737,23 @@
final StreamController<List<int>> stdoutStreamController =
new StreamController<List<int>>();
final IOSink ioSink = new IOSink(stdoutStreamController.sink);
- StreamController<String> receivedResults = new StreamController<String>();
+ StreamController<Result> receivedResults = new StreamController<Result>();
- String boundaryKey;
+ final outputParser = new OutputParser(receivedResults);
stdoutStreamController.stream
.transform(utf8.decoder)
.transform(const LineSplitter())
- .listen((String s) {
- const String RESULT_OUTPUT_SPACE = 'result ';
- if (boundaryKey == null) {
- if (s.startsWith(RESULT_OUTPUT_SPACE)) {
- boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
- }
- } else {
- if (s.startsWith(boundaryKey)) {
- receivedResults.add(s.substring(boundaryKey.length + 1));
- boundaryKey = null;
- }
- }
- });
+ .listen(outputParser.listener);
+
Future<int> result =
starter(args, input: inputStreamController.stream, output: ioSink);
inputStreamController.add('compile ${file.path}\n'.codeUnits);
int count = 0;
- receivedResults.stream.listen((String outputFilenameAndErrorCount) {
- CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
+ receivedResults.stream.listen((Result compiledResult) {
if (count == 0) {
// First request is to 'compile', which results in full kernel file.
expect(dillFile.existsSync(), equals(true));
- expect(result.filename, dillFile.path);
- expect(result.errorsCount, 0);
+ compiledResult.expectNoErrors(filename: dillFile.path);
count += 1;
inputStreamController.add('accept\n'.codeUnits);
var file2 = new File('${tempDir.path}/bar.dart')..createSync();
@@ -706,8 +767,7 @@
// Second request is to 'recompile', which results in incremental
// kernel file.
var dillIncFile = new File('${dillFile.path}.incremental.dill');
- expect(result.filename, dillIncFile.path);
- expect(result.errorsCount, 0);
+ compiledResult.expectNoErrors(filename: dillIncFile.path);
expect(dillIncFile.existsSync(), equals(true));
inputStreamController.add('quit\n'.codeUnits);
}
@@ -771,32 +831,20 @@
final StreamController<List<int>> stdoutStreamController =
new StreamController<List<int>>();
final IOSink ioSink = new IOSink(stdoutStreamController.sink);
- StreamController<String> receivedResults = new StreamController<String>();
-
- String boundaryKey;
+ StreamController<Result> receivedResults = new StreamController<Result>();
+ final outputParser = new OutputParser(receivedResults);
stdoutStreamController.stream
.transform(utf8.decoder)
.transform(const LineSplitter())
- .listen((String s) {
- const String RESULT_OUTPUT_SPACE = 'result ';
- if (boundaryKey == null) {
- if (s.startsWith(RESULT_OUTPUT_SPACE)) {
- boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
- }
- } else {
- if (s.startsWith(boundaryKey)) {
- receivedResults.add(s.substring(boundaryKey.length + 1));
- boundaryKey = null;
- }
- }
- });
+ .listen(outputParser.listener);
+
Future<int> result =
starter(args, input: inputStreamController.stream, output: ioSink);
inputStreamController.add('compile ${file.path}\n'.codeUnits);
int count = 0;
- receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+ receivedResults.stream.listen((Result compiledResult) {
CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
+ new CompilationResult.parse(compiledResult.status);
switch (count) {
case 0:
expect(dillFile.existsSync(), equals(true));
@@ -854,32 +902,21 @@
final StreamController<List<int>> stdoutStreamController =
new StreamController<List<int>>();
final IOSink ioSink = new IOSink(stdoutStreamController.sink);
- StreamController<String> receivedResults = new StreamController<String>();
+ StreamController<Result> receivedResults = new StreamController<Result>();
- String boundaryKey;
+ final outputParser = new OutputParser(receivedResults);
stdoutStreamController.stream
.transform(utf8.decoder)
.transform(const LineSplitter())
- .listen((String s) {
- const String RESULT_OUTPUT_SPACE = 'result ';
- if (boundaryKey == null) {
- if (s.startsWith(RESULT_OUTPUT_SPACE)) {
- boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
- }
- } else {
- if (s.startsWith(boundaryKey)) {
- receivedResults.add(s.substring(boundaryKey.length + 1));
- boundaryKey = null;
- }
- }
- });
+ .listen(outputParser.listener);
+
Future<int> result =
starter(args, input: inputStreamController.stream, output: ioSink);
- inputStreamController.add('compile ${file.path}\n'.codeUnits);
+ inputStreamController.add('compile ${file.uri}\n'.codeUnits);
int count = 0;
- receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+ receivedResults.stream.listen((Result compiledResult) {
CompilationResult result =
- new CompilationResult.parse(outputFilenameAndErrorCount);
+ new CompilationResult.parse(compiledResult.status);
switch (count) {
case 0:
expect(dillFile.existsSync(), equals(true));
@@ -889,8 +926,8 @@
inputStreamController.add('accept\n'.codeUnits);
var file2 = new File('${tempDir.path}/bar.dart')..createSync();
file2.writeAsStringSync("main() { baz(); }\n");
- inputStreamController.add('recompile ${file2.path} abc\n'
- '${file2.path}\n'
+ inputStreamController.add('recompile ${file2.uri} abc\n'
+ '${file2.uri}\n'
'abc\n'
.codeUnits);
break;
@@ -902,8 +939,8 @@
inputStreamController.add('accept\n'.codeUnits);
var file2 = new File('${tempDir.path}/bar.dart')..createSync();
file2.writeAsStringSync("main() { }\n");
- inputStreamController.add('recompile ${file2.path} abc\n'
- '${file2.path}\n'
+ inputStreamController.add('recompile ${file2.uri} abc\n'
+ '${file2.uri}\n'
'abc\n'
.codeUnits);
break;
@@ -1035,36 +1072,23 @@
final StreamController<List<int>> stdoutStreamController =
new StreamController<List<int>>();
final IOSink ioSink = new IOSink(stdoutStreamController.sink);
- StreamController<String> receivedResults =
- new StreamController<String>();
+ StreamController<Result> receivedResults =
+ new StreamController<Result>();
- String boundaryKey;
+ final outputParser = new OutputParser(receivedResults);
stdoutStreamController.stream
.transform(utf8.decoder)
.transform(const LineSplitter())
- .listen((String s) {
- const String RESULT_OUTPUT_SPACE = 'result ';
- if (boundaryKey == null) {
- if (s.startsWith(RESULT_OUTPUT_SPACE)) {
- boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
- }
- } else {
- if (s.startsWith(boundaryKey)) {
- receivedResults.add(s.substring(boundaryKey.length + 1));
- boundaryKey = null;
- }
- }
- });
+ .listen(outputParser.listener);
Future<int> result =
starter(args, input: inputStreamController.stream, output: ioSink);
inputStreamController.add('compile ${dart2js.path}\n'.codeUnits);
int count = 0;
- receivedResults.stream.listen((String outputFilenameAndErrorCount) {
- int delim = outputFilenameAndErrorCount.lastIndexOf(' ');
- expect(delim > 0, equals(true));
- String outputFilename =
- outputFilenameAndErrorCount.substring(0, delim);
+ receivedResults.stream.listen((Result compiledResult) {
+ CompilationResult result =
+ CompilationResult.parse(compiledResult.status);
+ String outputFilename = result.filename;
print("$outputFilename -- count $count");
// Ensure that kernel file produced when compiler was initialized
@@ -1205,9 +1229,75 @@
int errorsCount;
CompilationResult.parse(String filenameAndErrorCount) {
+ if (filenameAndErrorCount == null) {
+ return;
+ }
int delim = filenameAndErrorCount.lastIndexOf(' ');
expect(delim > 0, equals(true));
filename = filenameAndErrorCount.substring(0, delim);
errorsCount = int.parse(filenameAndErrorCount.substring(delim + 1).trim());
}
}
+
+class Result {
+ String status;
+ List<String> sources;
+
+ Result(this.status, this.sources);
+
+ void expectNoErrors({String filename}) {
+ var result = CompilationResult.parse(status);
+ expect(result.errorsCount, equals(0));
+ if (filename != null) {
+ expect(result.filename, equals(filename));
+ }
+ }
+}
+
+class OutputParser {
+ OutputParser(this._receivedResults);
+ bool expectSources = true;
+
+ StreamController<Result> _receivedResults;
+ List<String> _receivedSources;
+
+ String _boundaryKey;
+ bool _readingSources;
+
+ void listener(String s) {
+ if (_boundaryKey == null) {
+ const String RESULT_OUTPUT_SPACE = 'result ';
+ if (s.startsWith(RESULT_OUTPUT_SPACE)) {
+ _boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
+ }
+ _readingSources = false;
+ _receivedSources?.clear();
+ return;
+ }
+
+ if (s.startsWith(_boundaryKey)) {
+ // First boundaryKey separates compiler output from list of sources
+ // (if we expect list of sources, which is indicated by receivedSources
+ // being not null)
+ if (expectSources && !_readingSources) {
+ _readingSources = true;
+ return;
+ }
+ // Second boundaryKey indicates end of frontend server response
+ expectSources = true;
+ _receivedResults.add(Result(
+ s.length > _boundaryKey.length
+ ? s.substring(_boundaryKey.length + 1)
+ : null,
+ _receivedSources));
+ _boundaryKey = null;
+ } else {
+ if (_readingSources) {
+ if (_receivedSources == null) {
+ _receivedSources = <String>[];
+ }
+ _receivedSources.add(s);
+ }
+ }
+ }
+}
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 7f4482d..349b566 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -36,12 +36,25 @@
};
group('basic', () {
- test('compile', () async {
- var systemTempDir = Directory.systemTemp;
- var file = new File('${systemTempDir.path}/foo.dart')..createSync();
- file.writeAsStringSync("main() {}\n");
+ Directory mytest;
+ File main;
- IncrementalCompiler compiler = new IncrementalCompiler(options, file.uri);
+ setUpAll(() {
+ mytest = Directory.systemTemp.createTempSync('incremental');
+ main = new File('${mytest.path}/main.dart')..createSync();
+ main.writeAsStringSync("main() {}\n");
+ });
+
+ tearDownAll(() {
+ try {
+ mytest.deleteSync(recursive: true);
+ } catch (_) {
+ // Ignore errors;
+ }
+ });
+
+ test('compile', () async {
+ IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
Component component = await compiler.compile();
final StringBuffer buffer = new StringBuffer();
@@ -56,13 +69,14 @@
});
test('compile exclude sources', () async {
- var systemTempDir = Directory.systemTemp;
- var file = new File('${systemTempDir.path}/foo.dart')..createSync();
- file.writeAsStringSync("main() {}\n");
-
- CompilerOptions optionsExcludeSources = options..embedSourceText = false;
+ CompilerOptions optionsExcludeSources = new CompilerOptions()
+ ..sdkRoot = options.sdkRoot
+ ..target = options.target
+ ..linkedDependencies = options.linkedDependencies
+ ..onDiagnostic = options.onDiagnostic
+ ..embedSourceText = false;
IncrementalCompiler compiler =
- new IncrementalCompiler(optionsExcludeSources, file.uri);
+ new IncrementalCompiler(optionsExcludeSources, main.uri);
Component component = await compiler.compile();
for (Source source in component.uriToSource.values) {
@@ -79,6 +93,37 @@
'\n'
'static method main() → dynamic {}\n'));
});
+
+ test('compile expressions errors are not re-reported', () async {
+ var errorsReported = 0;
+ CompilerOptions optionsAcceptErrors = new CompilerOptions()
+ ..sdkRoot = options.sdkRoot
+ ..target = options.target
+ ..linkedDependencies = options.linkedDependencies
+ ..onDiagnostic = (DiagnosticMessage message) {
+ errorsReported++;
+ message.plainTextFormatted.forEach(print);
+ };
+ IncrementalCompiler compiler =
+ new IncrementalCompiler(optionsAcceptErrors, main.uri);
+ await compiler.compile();
+ compiler.accept();
+ {
+ Procedure procedure = await compiler.compileExpression(
+ 'main', <String>[], <String>[], main.uri.toString(), null, true);
+ expect(procedure, isNotNull);
+ expect(errorsReported, equals(0));
+ }
+ {
+ Procedure procedure = await compiler.compileExpression(
+ 'main1', <String>[], <String>[], main.uri.toString(), null, true);
+ expect(procedure, isNotNull);
+ expect(errorsReported, equals(1));
+ errorsReported = 0;
+ }
+ await compiler.compile();
+ expect(errorsReported, equals(0));
+ });
});
group('multiple kernels', () {
diff --git a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
new file mode 100644
index 0000000..66d662e
--- /dev/null
+++ b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2019, 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:io';
+
+import 'package:kernel/target/targets.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/binary/limited_ast_to_binary.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+import 'package:vm/transformations/protobuf_aware_treeshaker/transformer.dart'
+ as treeshaker;
+
+import '../../common_test_utils.dart';
+
+final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
+
+runTestCase(Uri source) async {
+ final target = new TestingVmTarget(new TargetFlags());
+ Component component =
+ await compileTestCaseToKernelProgram(source, target: target);
+
+ List<Class> messageClasses = component.libraries
+ .expand(
+ (lib) => lib.classes.where((klass) =>
+ klass.superclass != null &&
+ klass.superclass.name == "GeneratedMessage"),
+ )
+ .toList();
+
+ treeshaker.transformComponent(component, {}, TestingVmTarget(TargetFlags()),
+ collectInfo: true, enableAsserts: false);
+
+ for (Class messageClass in messageClasses) {
+ expect(messageClass.enclosingLibrary.classes.contains(messageClass),
+ messageClass.name.endsWith('Keep'));
+ }
+
+ final systemTempDir = Directory.systemTemp;
+ final file =
+ new File('${systemTempDir.path}/${source.pathSegments.last}.dill');
+ try {
+ final sink = file.openWrite();
+ final printer =
+ LimitedBinaryPrinter(sink, (lib) => true, /*excludeUriToSource=*/ true);
+
+ printer.writeComponentFile(component);
+ await sink.close();
+
+ ProcessResult result =
+ Process.runSync(Platform.resolvedExecutable, [file.path]);
+ expect(result.exitCode, 0);
+ } finally {
+ if (file.existsSync()) {
+ file.deleteSync();
+ }
+ }
+}
+
+main() async {
+ final testCases = Directory(path.join(
+ pkgVmDir,
+ 'testcases',
+ 'transformations',
+ 'protobuf_aware_treeshaker',
+ 'lib',
+ )).listSync().where((f) => f.path.endsWith('_test.dart'));
+ for (final entry in testCases) {
+ test(entry.path, () => runTestCase(entry.uri));
+ }
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh
new file mode 100755
index 0000000..b4793ee
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+# Copyright (c) 2019, 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.
+
+# Running this script requires having protoc_plugin installed in your path.
+
+rm -rf lib/generated
+mkdir lib/generated
+
+# Directory of the script
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+GENERATED_DIR=$DIR/lib/generated
+
+protoc --dart_out=$GENERATED_DIR -I$DIR/protos $DIR/protos/*.proto
+rm $GENERATED_DIR/*.pbenum.dart $GENERATED_DIR/*.pbjson.dart $GENERATED_DIR/*.pbserver.dart
+
+dartfmt -w $DIR/lib/generated
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/create_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/create_test.dart
new file mode 100644
index 0000000..1912459
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/create_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'generated/foo.pb.dart';
+
+main() {
+ FooKeep foo = FooKeep()
+ ..barKeep = (BarKeep()..aKeep = 5)
+ ..mapKeep['foo'] = (BarKeep()..aKeep = 2)
+ ..aKeep = 43;
+ test('retrieving values', () {
+ expect(foo.barKeep.aKeep, 5);
+ expect(foo.mapKeep['foo'].aKeep, 2);
+ expect(foo.hasHasKeep(), false);
+ expect(foo.aKeep, 43);
+ foo.clearClearKeep();
+ });
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/decode_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/decode_test.dart
new file mode 100644
index 0000000..d33289f
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/decode_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'generated/foo.pb.dart';
+
+List<int> buffer = <int>[
+ 10, 4, 8, 5, 16, //
+ 4, 26, 9, 10, 3,
+ 102, 111, 111, 18, 2,
+ 8, 42, 34, 9, 10,
+ 3, 122, 111, 112, 18,
+ 2, 8, 3, 40, 43,
+ 50, 0, 58, 0,
+];
+
+main() {
+ FooKeep foo = FooKeep.fromBuffer(buffer);
+ test('Kept values are restored correctly', () {
+ expect(foo.mapKeep['foo'].aKeep, 42);
+ expect(foo.barKeep.aKeep, 5);
+ expect(foo.aKeep, 43);
+ expect(foo.hasHasKeep(), true);
+ foo.clearClearKeep();
+ });
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/encode_all_fields.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/encode_all_fields.dart
new file mode 100644
index 0000000..de756cc
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/encode_all_fields.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, 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:math';
+
+import 'generated/foo.pb.dart';
+
+main() {
+ FooKeep foo = FooKeep()
+ ..barKeep = (BarKeep()
+ ..aKeep = 5
+ ..bDrop = 4)
+ ..mapKeep['foo'] = (BarKeep()..aKeep = 42)
+ ..mapDrop['zop'] = (ZopDrop()..aDrop = 3)
+ ..aKeep = 43
+ ..hasKeep = HasKeep()
+ ..clearKeep = ClearKeep();
+ final buffer = foo.writeToBuffer();
+ print('List<int> buffer = <int>[');
+ for (int i = 0; i < buffer.length; i += 5) {
+ final numbers = buffer.sublist(i, min(buffer.length, i + 5)).join(', ');
+ print(' $numbers,${i == 0 ? ' //' : ''}');
+ }
+ print('];');
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/foo.pb.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/foo.pb.dart
new file mode 100644
index 0000000..4063773
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/foo.pb.dart
@@ -0,0 +1,253 @@
+///
+// Generated code. Do not modify.
+// source: foo.proto
+///
+// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import
+
+// ignore: UNUSED_SHOWN_NAME
+import 'dart:core' show int, bool, double, String, List, Map, override;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class FooKeep extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = new $pb.BuilderInfo('FooKeep')
+ ..a<BarKeep>(
+ 1, 'barKeep', $pb.PbFieldType.OM, BarKeep.getDefault, BarKeep.create)
+ ..a<BarKeep>(
+ 2, 'barDrop', $pb.PbFieldType.OM, BarKeep.getDefault, BarKeep.create)
+ ..m<String, BarKeep>(3, 'mapKeep', 'FooKeep.MapKeepEntry',
+ $pb.PbFieldType.OS, $pb.PbFieldType.OM, BarKeep.create, null, null)
+ ..m<String, ZopDrop>(4, 'mapDrop', 'FooKeep.MapDropEntry',
+ $pb.PbFieldType.OS, $pb.PbFieldType.OM, ZopDrop.create, null, null)
+ ..a<int>(5, 'aKeep', $pb.PbFieldType.O3)
+ ..a<HasKeep>(
+ 6, 'hasKeep', $pb.PbFieldType.OM, HasKeep.getDefault, HasKeep.create)
+ ..a<ClearKeep>(7, 'clearKeep', $pb.PbFieldType.OM, ClearKeep.getDefault,
+ ClearKeep.create)
+ ..hasRequiredFields = false;
+
+ FooKeep() : super();
+ FooKeep.fromBuffer(List<int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromBuffer(i, r);
+ FooKeep.fromJson(String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromJson(i, r);
+ FooKeep clone() => new FooKeep()..mergeFromMessage(this);
+ FooKeep copyWith(void Function(FooKeep) updates) =>
+ super.copyWith((message) => updates(message as FooKeep));
+ $pb.BuilderInfo get info_ => _i;
+ static FooKeep create() => new FooKeep();
+ FooKeep createEmptyInstance() => create();
+ static $pb.PbList<FooKeep> createRepeated() => new $pb.PbList<FooKeep>();
+ static FooKeep getDefault() => _defaultInstance ??= create()..freeze();
+ static FooKeep _defaultInstance;
+
+ BarKeep get barKeep => $_getN(0);
+ set barKeep(BarKeep v) {
+ setField(1, v);
+ }
+
+ bool hasBarKeep() => $_has(0);
+ void clearBarKeep() => clearField(1);
+
+ BarKeep get barDrop => $_getN(1);
+ set barDrop(BarKeep v) {
+ setField(2, v);
+ }
+
+ bool hasBarDrop() => $_has(1);
+ void clearBarDrop() => clearField(2);
+
+ Map<String, BarKeep> get mapKeep => $_getMap(2);
+
+ Map<String, ZopDrop> get mapDrop => $_getMap(3);
+
+ int get aKeep => $_get(4, 0);
+ set aKeep(int v) {
+ $_setSignedInt32(4, v);
+ }
+
+ bool hasAKeep() => $_has(4);
+ void clearAKeep() => clearField(5);
+
+ HasKeep get hasKeep => $_getN(5);
+ set hasKeep(HasKeep v) {
+ setField(6, v);
+ }
+
+ bool hasHasKeep() => $_has(5);
+ void clearHasKeep() => clearField(6);
+
+ ClearKeep get clearKeep => $_getN(6);
+ set clearKeep(ClearKeep v) {
+ setField(7, v);
+ }
+
+ bool hasClearKeep() => $_has(6);
+ void clearClearKeep() => clearField(7);
+}
+
+class BarKeep extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = new $pb.BuilderInfo('BarKeep')
+ ..a<int>(1, 'aKeep', $pb.PbFieldType.O3)
+ ..a<int>(2, 'bDrop', $pb.PbFieldType.O3)
+ ..hasRequiredFields = false;
+
+ BarKeep() : super();
+ BarKeep.fromBuffer(List<int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromBuffer(i, r);
+ BarKeep.fromJson(String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromJson(i, r);
+ BarKeep clone() => new BarKeep()..mergeFromMessage(this);
+ BarKeep copyWith(void Function(BarKeep) updates) =>
+ super.copyWith((message) => updates(message as BarKeep));
+ $pb.BuilderInfo get info_ => _i;
+ static BarKeep create() => new BarKeep();
+ BarKeep createEmptyInstance() => create();
+ static $pb.PbList<BarKeep> createRepeated() => new $pb.PbList<BarKeep>();
+ static BarKeep getDefault() => _defaultInstance ??= create()..freeze();
+ static BarKeep _defaultInstance;
+
+ int get aKeep => $_get(0, 0);
+ set aKeep(int v) {
+ $_setSignedInt32(0, v);
+ }
+
+ bool hasAKeep() => $_has(0);
+ void clearAKeep() => clearField(1);
+
+ int get bDrop => $_get(1, 0);
+ set bDrop(int v) {
+ $_setSignedInt32(1, v);
+ }
+
+ bool hasBDrop() => $_has(1);
+ void clearBDrop() => clearField(2);
+}
+
+class HasKeep extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = new $pb.BuilderInfo('HasKeep')
+ ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
+ ..hasRequiredFields = false;
+
+ HasKeep() : super();
+ HasKeep.fromBuffer(List<int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromBuffer(i, r);
+ HasKeep.fromJson(String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromJson(i, r);
+ HasKeep clone() => new HasKeep()..mergeFromMessage(this);
+ HasKeep copyWith(void Function(HasKeep) updates) =>
+ super.copyWith((message) => updates(message as HasKeep));
+ $pb.BuilderInfo get info_ => _i;
+ static HasKeep create() => new HasKeep();
+ HasKeep createEmptyInstance() => create();
+ static $pb.PbList<HasKeep> createRepeated() => new $pb.PbList<HasKeep>();
+ static HasKeep getDefault() => _defaultInstance ??= create()..freeze();
+ static HasKeep _defaultInstance;
+
+ int get aDrop => $_get(0, 0);
+ set aDrop(int v) {
+ $_setSignedInt32(0, v);
+ }
+
+ bool hasADrop() => $_has(0);
+ void clearADrop() => clearField(1);
+}
+
+class ClearKeep extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ClearKeep')
+ ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
+ ..hasRequiredFields = false;
+
+ ClearKeep() : super();
+ ClearKeep.fromBuffer(List<int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromBuffer(i, r);
+ ClearKeep.fromJson(String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromJson(i, r);
+ ClearKeep clone() => new ClearKeep()..mergeFromMessage(this);
+ ClearKeep copyWith(void Function(ClearKeep) updates) =>
+ super.copyWith((message) => updates(message as ClearKeep));
+ $pb.BuilderInfo get info_ => _i;
+ static ClearKeep create() => new ClearKeep();
+ ClearKeep createEmptyInstance() => create();
+ static $pb.PbList<ClearKeep> createRepeated() => new $pb.PbList<ClearKeep>();
+ static ClearKeep getDefault() => _defaultInstance ??= create()..freeze();
+ static ClearKeep _defaultInstance;
+
+ int get aDrop => $_get(0, 0);
+ set aDrop(int v) {
+ $_setSignedInt32(0, v);
+ }
+
+ bool hasADrop() => $_has(0);
+ void clearADrop() => clearField(1);
+}
+
+class ZopDrop extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ZopDrop')
+ ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
+ ..hasRequiredFields = false;
+
+ ZopDrop() : super();
+ ZopDrop.fromBuffer(List<int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromBuffer(i, r);
+ ZopDrop.fromJson(String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromJson(i, r);
+ ZopDrop clone() => new ZopDrop()..mergeFromMessage(this);
+ ZopDrop copyWith(void Function(ZopDrop) updates) =>
+ super.copyWith((message) => updates(message as ZopDrop));
+ $pb.BuilderInfo get info_ => _i;
+ static ZopDrop create() => new ZopDrop();
+ ZopDrop createEmptyInstance() => create();
+ static $pb.PbList<ZopDrop> createRepeated() => new $pb.PbList<ZopDrop>();
+ static ZopDrop getDefault() => _defaultInstance ??= create()..freeze();
+ static ZopDrop _defaultInstance;
+
+ int get aDrop => $_get(0, 0);
+ set aDrop(int v) {
+ $_setSignedInt32(0, v);
+ }
+
+ bool hasADrop() => $_has(0);
+ void clearADrop() => clearField(1);
+}
+
+class MobDrop extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = new $pb.BuilderInfo('MobDrop')
+ ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
+ ..hasRequiredFields = false;
+
+ MobDrop() : super();
+ MobDrop.fromBuffer(List<int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromBuffer(i, r);
+ MobDrop.fromJson(String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+ : super.fromJson(i, r);
+ MobDrop clone() => new MobDrop()..mergeFromMessage(this);
+ MobDrop copyWith(void Function(MobDrop) updates) =>
+ super.copyWith((message) => updates(message as MobDrop));
+ $pb.BuilderInfo get info_ => _i;
+ static MobDrop create() => new MobDrop();
+ MobDrop createEmptyInstance() => create();
+ static $pb.PbList<MobDrop> createRepeated() => new $pb.PbList<MobDrop>();
+ static MobDrop getDefault() => _defaultInstance ??= create()..freeze();
+ static MobDrop _defaultInstance;
+
+ int get aDrop => $_get(0, 0);
+ set aDrop(int v) {
+ $_setSignedInt32(0, v);
+ }
+
+ bool hasADrop() => $_has(0);
+ void clearADrop() => clearField(1);
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto
new file mode 100644
index 0000000..0a14433
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto
@@ -0,0 +1,41 @@
+// Copyright (c) 2019, 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.
+
+syntax = "proto3";
+
+message FooKeep {
+ BarKeep barKeep = 1;
+ BarKeep barDrop = 2;
+ map<string, BarKeep> mapKeep = 3;
+ map<string, ZopDrop> mapDrop = 4;
+ int32 aKeep = 5;
+ HasKeep hasKeep = 6;
+ ClearKeep clearKeep = 7;
+}
+
+message BarKeep {
+ int32 aKeep = 1;
+ int32 bDrop = 2;
+}
+
+message HasKeep {
+ int32 aDrop = 1;
+}
+
+message ClearKeep {
+ int32 aDrop = 1;
+}
+
+message ZopDrop {
+ int32 aDrop = 1;
+}
+
+message MobDrop {
+ int32 aDrop = 1;
+}
+
+message A {
+ B unused = 1;
+ C used = 2;
+}
\ No newline at end of file
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 51c708c..5724879 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -654,6 +654,27 @@
get_target_outputs(":platform_strong_dill_linkable")
}
+action("generate_abi_version_cc_file") {
+ inputs = [
+ "../../tools/utils.py",
+ "../../tools/VERSION",
+ "abi_version_in.cc",
+ ]
+ output = "$target_gen_dir/abi_version.cc"
+ outputs = [
+ output,
+ ]
+
+ script = "../../tools/make_version.py"
+ args = [
+ "--quiet",
+ "--output",
+ rebase_path(output, root_build_dir),
+ "--input",
+ rebase_path("abi_version_in.cc", root_build_dir),
+ ]
+}
+
template("dart_executable") {
extra_configs = []
if (defined(invoker.extra_configs)) {
@@ -702,6 +723,7 @@
"//third_party/boringssl",
"//third_party/zlib",
":crashpad",
+ ":generate_abi_version_cc_file",
] + extra_deps
defines = extra_defines
@@ -731,6 +753,7 @@
"snapshot_utils.h",
"vmservice_impl.cc",
"vmservice_impl.h",
+ "$target_gen_dir/abi_version.cc",
] + extra_sources
if (is_win) {
diff --git a/runtime/bin/abi_version.h b/runtime/bin/abi_version.h
new file mode 100644
index 0000000..acd0cdf
--- /dev/null
+++ b/runtime/bin/abi_version.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_BIN_ABI_VERSION_H_
+#define RUNTIME_BIN_ABI_VERSION_H_
+
+namespace dart {
+
+class AbiVersion {
+ public:
+ static int GetCurrent();
+ static int GetOldestSupported();
+};
+
+} // namespace dart
+
+#endif // RUNTIME_BIN_ABI_VERSION_H_
diff --git a/runtime/bin/abi_version_in.cc b/runtime/bin/abi_version_in.cc
new file mode 100644
index 0000000..ad737b2
--- /dev/null
+++ b/runtime/bin/abi_version_in.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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 "bin/abi_version.h"
+
+namespace dart {
+
+int AbiVersion::GetCurrent() {
+ return {{ABI_VERSION}};
+}
+
+int AbiVersion::GetOldestSupported() {
+ return {{OLDEST_SUPPORTED_ABI_VERSION}};
+}
+
+} // namespace dart
diff --git a/runtime/bin/builtin_impl_sources.gni b/runtime/bin/builtin_impl_sources.gni
index d4c7489..f329f03 100644
--- a/runtime/bin/builtin_impl_sources.gni
+++ b/runtime/bin/builtin_impl_sources.gni
@@ -7,6 +7,7 @@
# io_impl_sources.gypi.
builtin_impl_sources = [
+ "abi_version.h",
"crypto.cc",
"crypto.h",
"crypto_android.cc",
diff --git a/runtime/bin/dart_embedder_api_impl.cc b/runtime/bin/dart_embedder_api_impl.cc
index ba47d33..4700774 100644
--- a/runtime/bin/dart_embedder_api_impl.cc
+++ b/runtime/bin/dart_embedder_api_impl.cc
@@ -90,8 +90,6 @@
if (!bin::VmService::Setup(config.ip, config.port, config.dev_mode,
/*trace_loading=*/false, config.deterministic)) {
*error = strdup(bin::VmService::GetErrorMessage());
- Dart_ExitScope();
- Dart_ShutdownIsolate();
return nullptr;
}
diff --git a/runtime/bin/ffi_test_functions.cc b/runtime/bin/ffi_test_functions.cc
index 5d95e49..248020d 100644
--- a/runtime/bin/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test_functions.cc
@@ -4,13 +4,17 @@
// This file contains test functions for the dart:ffi test cases.
-// The tests which use this don't run on Windows yet.
-#if !defined(_WIN32)
-
#include <stddef.h>
#include <stdlib.h>
#include <sys/types.h>
+
+#include "platform/globals.h"
+#if defined(HOST_OS_WINDOWS)
+#include <psapi.h>
+#else
#include <unistd.h>
+#endif
+
#include <iostream>
#include <limits>
@@ -29,6 +33,11 @@
return retval;
}
+// Test 32-bit (int32_t) -> 64-bit (Dart int) sign extension and truncation.
+DART_EXPORT int32_t TestExtension() {
+ return 1UL << 31;
+}
+
// Performs some computation on various sized signed ints.
// Used for testing value ranges for signed ints.
DART_EXPORT int64_t IntComputation(int8_t a, int16_t b, int32_t c, int64_t d) {
@@ -403,9 +412,15 @@
}
DART_EXPORT void* SmallPointer() {
- return reinterpret_cast<void*>(-0x80000000L);
+ intptr_t value = 0x80000000;
+ return reinterpret_cast<void*>(-value);
}
+DART_EXPORT void* LargePointer() {
+ return reinterpret_cast<void*>(-0x8000000000000000L);
+}
+
+#if !defined(_WIN32)
DART_EXPORT int RedirectStderr() {
char filename[256];
snprintf(filename, sizeof(filename), "/tmp/captured_stderr_%d", getpid());
@@ -413,7 +428,6 @@
printf("Got file %s\n", filename);
return getpid();
}
+#endif
} // namespace dart
-
-#endif
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index 9ee69ea..9b480d5 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -590,11 +590,18 @@
return "/";
}
+static int fd_is_valid(int fd) {
+ return NO_RETRY_EXPECTED(fcntl(fd, F_GETFD)) != -1 || errno != EBADF;
+}
+
File::StdioHandleType File::GetStdioHandleType(int fd) {
struct stat buf;
int result = TEMP_FAILURE_RETRY(fstat(fd, &buf));
if (result == -1) {
- return kOther;
+ // fstat() on fds 0, 1, 2 on Fuchsia return -1 with errno ENOTSUP,
+ // but if they are opened, then we can read/write them, so pretend they
+ // are kPipe.
+ return ((errno == ENOTSUP) && fd_is_valid(fd)) ? kPipe : kOther;
}
if (S_ISCHR(buf.st_mode)) {
return kTerminal;
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 8dfc9202..6632130 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -424,6 +424,7 @@
intptr_t size = 0;
ReadFile(load_compilation_trace_filename, &buffer, &size);
Dart_Handle result = Dart_LoadCompilationTrace(buffer, size);
+ free(buffer);
CHECK_RESULT(result);
}
@@ -433,6 +434,7 @@
intptr_t size = 0;
ReadFile(load_type_feedback_filename, &buffer, &size);
Dart_Handle result = Dart_LoadTypeFeedback(buffer, size);
+ free(buffer);
CHECK_RESULT(result);
}
}
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 2d7ea6f..f572e20 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -883,11 +883,20 @@
LoadBytecode();
}
+ if (Options::load_compilation_trace_filename() != NULL) {
+ uint8_t* buffer = NULL;
+ intptr_t size = 0;
+ ReadFile(Options::load_compilation_trace_filename(), &buffer, &size);
+ result = Dart_LoadCompilationTrace(buffer, size);
+ free(buffer);
+ CHECK_RESULT(result);
+ }
if (Options::load_type_feedback_filename() != NULL) {
uint8_t* buffer = NULL;
intptr_t size = 0;
ReadFile(Options::load_type_feedback_filename(), &buffer, &size);
result = Dart_LoadTypeFeedback(buffer, size);
+ free(buffer);
CHECK_RESULT(result);
}
@@ -926,6 +935,13 @@
}
CHECK_RESULT(result);
+ if (Options::save_compilation_trace_filename() != NULL) {
+ uint8_t* buffer = NULL;
+ intptr_t size = 0;
+ result = Dart_SaveCompilationTrace(&buffer, &size);
+ CHECK_RESULT(result);
+ WriteFile(Options::save_compilation_trace_filename(), buffer, size);
+ }
if (Options::save_type_feedback_filename() != NULL) {
uint8_t* buffer = NULL;
intptr_t size = 0;
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index a7181f5..d68bfaa 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <string.h>
+#include "bin/abi_version.h"
#include "bin/log.h"
#include "bin/options.h"
#include "bin/platform.h"
@@ -324,6 +325,32 @@
return true;
}
+int Options::target_abi_version_ = AbiVersion::GetCurrent();
+bool Options::ProcessAbiVersionOption(const char* arg,
+ CommandLineOptions* vm_options) {
+ const char* value = OptionProcessor::ProcessOption(arg, "--use_abi_version=");
+ if (value == NULL) {
+ return false;
+ }
+ int ver = 0;
+ for (int i = 0; value[i]; ++i) {
+ if (value[i] >= '0' && value[i] <= '9') {
+ ver = (ver * 10) + value[i] - '0';
+ } else {
+ Log::PrintErr("--use_abi_version must be an int\n");
+ return false;
+ }
+ }
+ if (ver < AbiVersion::GetOldestSupported() ||
+ ver > AbiVersion::GetCurrent()) {
+ Log::PrintErr("--use_abi_version must be between %d and %d inclusive\n",
+ AbiVersion::GetOldestSupported(), AbiVersion::GetCurrent());
+ return false;
+ }
+ target_abi_version_ = ver;
+ return true;
+}
+
static bool checked_set = false;
int Options::ParseArguments(int argc,
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 2b668ac..e290696 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -24,6 +24,8 @@
V(depfile, depfile) \
V(depfile_output_filename, depfile_output_filename) \
V(shared_blobs, shared_blobs_filename) \
+ V(save_compilation_trace, save_compilation_trace_filename) \
+ V(load_compilation_trace, load_compilation_trace_filename) \
V(save_type_feedback, save_type_feedback_filename) \
V(load_type_feedback, load_type_feedback_filename) \
V(root_certs_file, root_certs_file) \
@@ -60,7 +62,8 @@
#define CB_OPTIONS_LIST(V) \
V(ProcessEnvironmentOption) \
V(ProcessEnableVmServiceOption) \
- V(ProcessObserveOption)
+ V(ProcessObserveOption) \
+ V(ProcessAbiVersionOption)
// This enum must match the strings in kSnapshotKindNames in main_options.cc.
enum SnapshotKind {
@@ -113,6 +116,8 @@
static const char* vm_service_server_ip() { return vm_service_server_ip_; }
static int vm_service_server_port() { return vm_service_server_port_; }
+ static int target_abi_version() { return target_abi_version_; }
+
#if !defined(DART_PRECOMPILED_RUNTIME)
static DFE* dfe() { return dfe_; }
static void set_dfe(DFE* dfe) { dfe_ = dfe; }
@@ -157,6 +162,8 @@
int default_port,
const char* default_ip);
+ static int target_abi_version_;
+
#define OPTION_FRIEND(flag, variable) friend class OptionProcessor_##flag;
STRING_OPTIONS_LIST(OPTION_FRIEND)
BOOL_OPTIONS_LIST(OPTION_FRIEND)
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 98ab964..93c7f6c 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -546,6 +546,9 @@
!Directory::SetCurrent(namespc_, working_directory_)) {
ReportChildError();
}
+ if (program_environment_ != NULL) {
+ environ = program_environment_;
+ }
// Report the final PID and do the exec.
ReportPid(getpid()); // getpid cannot fail.
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 402e01d..03b38aa 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -360,13 +360,17 @@
/**
* Add a timeline event to the embedder stream.
*
- * \param label The name of the evnet.
+ * \param label The name of the event. Its lifetime must extend at least until
+ * Dart_Cleanup.
* \param timestamp0 The first timestamp of the event.
* \param timestamp1_or_async_id The second timestamp of the event or
* the async id.
* \param argument_count The number of argument names and values.
- * \param argument_names An array of names of the arguments.
- * \param argument_values An array of values of the arguments.
+ * \param argument_names An array of names of the arguments. The lifetime of the
+ * names must extend at least until Dart_Cleanup. The array may be reclaimed
+ * when this call returns.
+ * \param argument_values An array of values of the arguments. The values and
+ * the array may be reclaimed when this call returns.
*/
DART_EXPORT void Dart_TimelineEvent(const char* label,
int64_t timestamp0,
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index be23866..2046284 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -2312,7 +2312,9 @@
var resultBits = new Uint8List(8);
var length = _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
- if (length - 53 > maxDoubleExponent) return double.infinity;
+ if (length > maxDoubleExponent + 53) {
+ return _isNegative ? double.negativeInfinity : double.infinity;
+ }
// The most significant bit is for the sign.
if (_isNegative) resultBits[7] = 0x80;
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 4186a1e..6e1903b 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -6,7 +6,6 @@
#include "include/dart_api.h"
#include "vm/bootstrap_natives.h"
#include "vm/class_finalizer.h"
-#include "vm/class_id.h"
#include "vm/compiler/assembler/assembler.h"
#include "vm/exceptions.h"
#include "vm/log.h"
@@ -227,10 +226,10 @@
GET_NON_NULL_NATIVE_ARGUMENT(Integer, argCount, arguments->NativeArgAt(0));
int64_t count = argCount.AsInt64Value();
classid_t type_cid = type_arg.type_class_id();
- int64_t max_count = INTPTR_MAX / ffi::ElementSizeInBytes(type_cid);
+ int64_t max_count = INTPTR_MAX / compiler::ffi::ElementSizeInBytes(type_cid);
CheckRange(argCount, 1, max_count, "count");
- size_t size = ffi::ElementSizeInBytes(type_cid) * count;
+ size_t size = compiler::ffi::ElementSizeInBytes(type_cid) * count;
intptr_t memory = reinterpret_cast<intptr_t>(malloc(size));
if (memory == 0) {
const String& error = String::Handle(String::NewFormatted(
@@ -268,9 +267,9 @@
classid_t class_id = pointer_type_arg.type_class_id();
Integer& address = Integer::Handle(zone, pointer.GetCMemoryAddress());
- address =
- Integer::New(address.AsInt64Value() +
- index.AsInt64Value() * ffi::ElementSizeInBytes(class_id));
+ address = Integer::New(address.AsInt64Value() +
+ index.AsInt64Value() *
+ compiler::ffi::ElementSizeInBytes(class_id));
RawPointer* result = Pointer::New(pointer_type_arg, address);
return result;
}
@@ -470,54 +469,7 @@
CheckSized(type_arg);
classid_t type_cid = type_arg.type_class_id();
- return Smi::New(ffi::ElementSizeInBytes(type_cid));
-}
-
-// Generates assembly to trampoline from Dart into C++.
-//
-// Attaches assembly code to the function with the folling features:
-// - unboxes arguments
-// - puts the arguments on the c stack
-// - invokes the c function
-// - reads the the result
-// - boxes the result and returns it.
-//
-// It inspects the signature to know what to box/unbox
-// Parameter `function` has the Dart types in its signature
-// Parameter `c_signature` has the C++ types in its signature
-static RawCode* TrampolineCode(const Function& function,
- const Function& c_signature) {
-#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
- // Currently we generate the trampoline when calling asFunction(), this means
- // the ffi cannot be used in AOT.
- // In order make it work in AOT we need to:
- // - collect all asFunction signatures ahead of time
- // - generate trampolines for those
- // - store these in the object store
- // - and read these from the object store when calling asFunction()
- // https://github.com/dart-lang/sdk/issues/35765
- UNREACHABLE();
-#elif !defined(TARGET_ARCH_X64)
- // https://github.com/dart-lang/sdk/issues/35774
- UNREACHABLE();
-#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
- // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
- // https://github.com/dart-lang/sdk/issues/35771 Windows
- // https://github.com/dart-lang/sdk/issues/35772 Arm64
- // https://github.com/dart-lang/sdk/issues/35773 DBC
- UNREACHABLE();
-#else
- extern void GenerateFfiTrampoline(Assembler * assembler,
- const Function& signature);
- ObjectPoolBuilder object_pool_builder;
- Assembler assembler(&object_pool_builder);
- GenerateFfiTrampoline(&assembler, c_signature);
- const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
- function, nullptr, &assembler, Code::PoolAttachment::kAttachPool));
- code.set_exception_handlers(
- ExceptionHandlers::Handle(ExceptionHandlers::New(0)));
- return code.raw();
-#endif
+ return Smi::New(compiler::ffi::ElementSizeInBytes(type_cid));
}
// TODO(dacoharkes): Cache the trampolines.
@@ -526,25 +478,37 @@
const Function& c_signature) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- const String& name =
+ String& name =
String::ZoneHandle(Symbols::New(Thread::Current(), "FfiTrampoline"));
const Library& lib = Library::Handle(Library::FfiLibrary());
const Class& owner_class = Class::Handle(lib.toplevel_class());
- Function& function = Function::ZoneHandle(
- zone, Function::New(name, RawFunction::kFfiTrampoline,
- true, // is_static
- false, // is_const
- false, // is_abstract
- false, // is_external
- true, // is_native
- owner_class, TokenPosition::kMinSource));
-
+ Function& function =
+ Function::Handle(zone, Function::New(name, RawFunction::kFfiTrampoline,
+ /*is_static=*/true,
+ /*is_const=*/false,
+ /*is_abstract=*/false,
+ /*is_external=*/false,
+ /*is_native=*/false, owner_class,
+ TokenPosition::kMinSource));
+ function.set_is_debuggable(false);
function.set_num_fixed_parameters(dart_signature.num_fixed_parameters());
function.set_result_type(AbstractType::Handle(dart_signature.result_type()));
function.set_parameter_types(Array::Handle(dart_signature.parameter_types()));
- const Code& code = Code::Handle(TrampolineCode(function, c_signature));
- function.AttachCode(code);
+ // The signature function won't have any names for the parameters. We need to
+ // assign unique names for scope building and error messages.
+ const intptr_t num_params = dart_signature.num_fixed_parameters();
+ const Array& parameter_names = Array::Handle(Array::New(num_params));
+ for (intptr_t i = 0; i < num_params; ++i) {
+ if (i == 0) {
+ name = Symbols::ClosureParameter().raw();
+ } else {
+ name = Symbols::NewFormatted(thread, ":ffiParam%" Pd, i);
+ }
+ parameter_names.SetAt(i, name);
+ }
+ function.set_parameter_names(parameter_names);
+ function.SetFfiCSignature(c_signature);
return function.raw();
}
@@ -588,9 +552,9 @@
#elif !defined(TARGET_ARCH_X64)
// https://github.com/dart-lang/sdk/issues/35774
UNREACHABLE();
-#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) && \
+ !defined(TARGET_OS_WINDOWS)
// https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
- // https://github.com/dart-lang/sdk/issues/35771 Windows
// https://github.com/dart-lang/sdk/issues/35772 Arm64
// https://github.com/dart-lang/sdk/issues/35773 DBC
UNREACHABLE();
diff --git a/runtime/lib/ffi_dynamic_library.cc b/runtime/lib/ffi_dynamic_library.cc
index 3af92da..af4a52e 100644
--- a/runtime/lib/ffi_dynamic_library.cc
+++ b/runtime/lib/ffi_dynamic_library.cc
@@ -3,12 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
#if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
-// TODO(dacoharkes): implement dynamic libraries for other targets.
-// see
-// - runtime/vm/native_symbol.h
-// - runtime/vm/native_symbol_linux.cc
-// - runtime/bin/extensions.h (but we cannot import from bin)
+// TODO(dacoharkes): Implement dynamic libraries for other targets & merge the
+// implementation with:
+// - runtime/bin/extensions.h
// - runtime/bin/extensions_linux.cc
+// TODO(dacoharkes): Make the code from bin available in a manner similar to
+// runtime/vm/dart.h Dart_FileReadCallback.
#else
#include <dlfcn.h>
#endif
@@ -19,29 +19,85 @@
namespace dart {
-DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
-#if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
- UNREACHABLE();
-#else
- GET_NON_NULL_NATIVE_ARGUMENT(String, lib_path, arguments->NativeArgAt(0));
-
- dlerror(); // Clear any errors.
- void* handle = dlopen(lib_path.ToCString(), RTLD_LAZY);
+static void* LoadExtensionLibrary(const char* library_file) {
+#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS)
+ void* handle = dlopen(library_file, RTLD_LAZY);
if (handle == nullptr) {
char* error = dlerror();
const String& msg = String::Handle(
- String::NewFormatted("Failed to load dynamic library(%s)", error));
+ String::NewFormatted("Failed to load dynamic library (%s)", error));
Exceptions::ThrowArgumentError(msg);
}
+ return handle;
+#elif defined(TARGET_OS_WINDOWS)
+ SetLastError(0); // Clear any errors.
+
+ // Convert to wchar_t string.
+ const int name_len =
+ MultiByteToWideChar(CP_UTF8, 0, library_file, -1, NULL, 0);
+ wchar_t* name = new wchar_t[name_len];
+ MultiByteToWideChar(CP_UTF8, 0, library_file, -1, name, name_len);
+
+ void* ext = LoadLibraryW(name);
+ delete[] name;
+
+ if (ext == nullptr) {
+ const int error = GetLastError();
+ const String& msg = String::Handle(
+ String::NewFormatted("Failed to load dynamic library (%i)", error));
+ Exceptions::ThrowArgumentError(msg);
+ }
+
+ return ext;
+#else
+ const Array& args = Array::Handle(Array::New(1));
+ args.SetAt(0,
+ String::Handle(String::New(
+ "The dart:ffi library is not available on this platform.")));
+ Exceptions::ThrowByType(Exceptions::kUnsupported, args);
+#endif
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(String, lib_path, arguments->NativeArgAt(0));
+
+ void* handle = LoadExtensionLibrary(lib_path.ToCString());
+
return DynamicLibrary::New(handle);
+}
+
+static void* ResolveSymbol(void* handle, const char* symbol) {
+#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS)
+ dlerror(); // Clear any errors.
+ void* pointer = dlsym(handle, symbol);
+ if (pointer == nullptr) {
+ char* error = dlerror();
+ const String& msg = String::Handle(
+ String::NewFormatted("Failed to lookup symbol (%s)", error));
+ Exceptions::ThrowArgumentError(msg);
+ }
+ return pointer;
+#elif defined(TARGET_OS_WINDOWS)
+ SetLastError(0);
+ void* pointer = GetProcAddress(reinterpret_cast<HMODULE>(handle), symbol);
+ if (pointer == nullptr) {
+ const int error = GetLastError();
+ const String& msg = String::Handle(
+ String::NewFormatted("Failed to lookup symbol (%i)", error));
+ Exceptions::ThrowArgumentError(msg);
+ }
+ return pointer;
+#else
+ const Array& args = Array::Handle(Array::New(1));
+ args.SetAt(0,
+ String::Handle(String::New(
+ "The dart:ffi library is not available on this platform.")));
+ Exceptions::ThrowByType(Exceptions::kUnsupported, args);
#endif
}
DEFINE_NATIVE_ENTRY(Ffi_dl_lookup, 1, 2) {
-#if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
- UNREACHABLE();
-#else
GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
@@ -50,22 +106,14 @@
void* handle = dlib.GetHandle();
- dlerror(); // Clear any errors.
- intptr_t pointer =
- reinterpret_cast<intptr_t>(dlsym(handle, argSymbolName.ToCString()));
- char* error;
- if ((error = dlerror()) != NULL) {
- const String& msg = String::Handle(
- String::NewFormatted("Failed to lookup symbol (%s)", error));
- Exceptions::ThrowArgumentError(msg);
- }
+ const intptr_t pointer = reinterpret_cast<intptr_t>(
+ ResolveSymbol(handle, argSymbolName.ToCString()));
- // TODO(dacoharkes): should this return NULL if addres is 0?
+ // TODO(dacoharkes): should this return Object::null() if address is 0?
// https://github.com/dart-lang/sdk/issues/35756
RawPointer* result =
Pointer::New(type_arg, Integer::Handle(zone, Integer::New(pointer)));
return result;
-#endif
}
DEFINE_NATIVE_ENTRY(Ffi_dl_getHandle, 0, 1) {
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 5592f20..5402def 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -328,15 +328,15 @@
Exceptions::ThrowByType(Exceptions::kArgument, args);
}
return OneByteString::New(array, start, length, space);
- } else if (RawObject::IsTypedDataViewClassId(list.GetClassId())) {
- const Instance& view = Instance::Cast(list);
- if (end > Smi::Value(TypedDataView::Length(view))) {
+ } else if (list.IsTypedDataView()) {
+ const auto& view = TypedDataView::Cast(list);
+ if (end > Smi::Value(view.length())) {
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0, end_obj);
Exceptions::ThrowByType(Exceptions::kArgument, args);
}
- const Instance& data_obj = Instance::Handle(TypedDataView::Data(view));
- intptr_t data_offset = Smi::Value(TypedDataView::OffsetInBytes(view));
+ const Instance& data_obj = Instance::Handle(view.typed_data());
+ intptr_t data_offset = Smi::Value(view.offset_in_bytes());
if (data_obj.IsTypedData()) {
const TypedData& array = TypedData::Cast(data_obj);
return OneByteString::New(array, data_offset + start, length, space);
@@ -422,16 +422,16 @@
}
return TwoByteString::New(array, start * sizeof(uint16_t), length, space);
} else if (RawObject::IsTypedDataViewClassId(list.GetClassId())) {
+ const auto& view = TypedDataView::Cast(list);
const intptr_t cid = list.GetClassId();
if (cid != kTypedDataUint16ArrayViewCid) {
Exceptions::ThrowArgumentError(list);
}
- if (end > Smi::Value(TypedDataView::Length(list))) {
+ if (end > Smi::Value(view.length())) {
Exceptions::ThrowArgumentError(end_obj);
}
- const Instance& data_obj =
- Instance::Handle(zone, TypedDataView::Data(list));
- intptr_t data_offset = Smi::Value(TypedDataView::OffsetInBytes(list));
+ const auto& data_obj = Instance::Handle(zone, view.typed_data());
+ const intptr_t data_offset = Smi::Value(view.offset_in_bytes());
if (data_obj.IsTypedData()) {
const TypedData& array = TypedData::Cast(data_obj);
return TwoByteString::New(array, data_offset + start * sizeof(uint16_t),
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc
index 4a373fc..1c55247 100644
--- a/runtime/lib/typed_data.cc
+++ b/runtime/lib/typed_data.cc
@@ -28,6 +28,15 @@
}
}
+static void AlignmentCheck(intptr_t offset_in_bytes, intptr_t element_size) {
+ if ((offset_in_bytes % element_size) != 0) {
+ const auto& error = String::Handle(String::NewFormatted(
+ "Offset in bytes (%" Pd ") must be a multiple of %" Pd "",
+ offset_in_bytes, element_size));
+ Exceptions::ThrowArgumentError(error);
+ }
+}
+
// Checks to see if a length will not result in an OOM error.
static void LengthCheck(intptr_t len, intptr_t max) {
if (len < 0 || len > max) {
@@ -53,6 +62,27 @@
return Integer::null();
}
+DEFINE_NATIVE_ENTRY(TypedDataView_offsetInBytes, 0, 1) {
+ // "this" is either a _*ArrayView class or _ByteDataView.
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
+ ASSERT(instance.IsTypedDataView());
+ return TypedDataView::Cast(instance).offset_in_bytes();
+}
+
+DEFINE_NATIVE_ENTRY(TypedDataView_length, 0, 1) {
+ // "this" is either a _*ArrayView class or _ByteDataView.
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
+ ASSERT(instance.IsTypedDataView());
+ return TypedDataView::Cast(instance).length();
+}
+
+DEFINE_NATIVE_ENTRY(TypedDataView_typedData, 0, 1) {
+ // "this" is either a _*ArrayView class or _ByteDataView.
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
+ ASSERT(instance.IsTypedDataView());
+ return TypedDataView::Cast(instance).typed_data();
+}
+
template <typename DstType, typename SrcType>
static RawBool* CopyData(const Instance& dst,
const Instance& src,
@@ -160,9 +190,9 @@
#define TYPED_DATA_NEW(name) \
DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 0, 2) { \
GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1)); \
- intptr_t cid = kTypedData##name##Cid; \
- intptr_t len = length.Value(); \
- intptr_t max = TypedData::MaxElements(cid); \
+ const intptr_t cid = kTypedData##name##Cid; \
+ const intptr_t len = length.Value(); \
+ const intptr_t max = TypedData::MaxElements(cid); \
LengthCheck(len, max); \
return TypedData::New(cid, len); \
}
@@ -170,6 +200,35 @@
#define TYPED_DATA_NEW_NATIVE(name) TYPED_DATA_NEW(name)
CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE)
+#undef TYPED_DATA_NEW_NATIVE
+#undef TYPED_DATA_NEW
+
+#define TYPED_DATA_VIEW_NEW(native_name, cid_name) \
+ DEFINE_NATIVE_ENTRY(native_name, 0, 4) { \
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, typed_data, \
+ arguments->NativeArgAt(1)); \
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, offset, arguments->NativeArgAt(2)); \
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, len, arguments->NativeArgAt(3)); \
+ const intptr_t backing_length = \
+ typed_data.IsTypedData() \
+ ? TypedData::Cast(typed_data).LengthInBytes() \
+ : ExternalTypedData::Cast(typed_data).LengthInBytes(); \
+ const intptr_t cid = cid_name; \
+ const intptr_t offset_in_bytes = offset.Value(); \
+ const intptr_t length = len.Value(); \
+ const intptr_t element_size = TypedDataView::ElementSizeInBytes(cid); \
+ AlignmentCheck(offset_in_bytes, element_size); \
+ LengthCheck(offset_in_bytes + length * element_size, backing_length); \
+ return TypedDataView::New(cid, typed_data, offset_in_bytes, length); \
+ }
+
+#define TYPED_DATA_NEW_NATIVE(name) \
+ TYPED_DATA_VIEW_NEW(TypedDataView_##name##View_new, kTypedData##name##ViewCid)
+
+CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE)
+TYPED_DATA_VIEW_NEW(TypedDataView_ByteDataView_new, kByteDataViewCid)
+#undef TYPED_DATA_NEW_NATIVE
+#undef TYPED_DATA_VIEW_NEW
#define TYPED_DATA_GETTER(getter, object, ctor, access_size) \
DEFINE_NATIVE_ENTRY(TypedData_##getter, 0, 2) { \
diff --git a/runtime/lib/typed_data_patch.dart b/runtime/lib/typed_data_patch.dart
index 56d4fe3..7af2181 100644
--- a/runtime/lib/typed_data_patch.dart
+++ b/runtime/lib/typed_data_patch.dart
@@ -1914,7 +1914,7 @@
length ??= (this.lengthInBytes - offsetInBytes) ~/ Int8List.bytesPerElement;
_rangeCheck(
this.lengthInBytes, offsetInBytes, length * Int8List.bytesPerElement);
- return new _Int8ArrayView(this, offsetInBytes, length);
+ return new _Int8ArrayView(this._data, offsetInBytes, length);
}
Uint8List asUint8List([int offsetInBytes = 0, int length]) {
@@ -1922,7 +1922,7 @@
(this.lengthInBytes - offsetInBytes) ~/ Uint8List.bytesPerElement;
_rangeCheck(
this.lengthInBytes, offsetInBytes, length * Uint8List.bytesPerElement);
- return new _Uint8ArrayView(this, offsetInBytes, length);
+ return new _Uint8ArrayView(this._data, offsetInBytes, length);
}
Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) {
@@ -1930,7 +1930,7 @@
Uint8ClampedList.bytesPerElement;
_rangeCheck(this.lengthInBytes, offsetInBytes,
length * Uint8ClampedList.bytesPerElement);
- return new _Uint8ClampedArrayView(this, offsetInBytes, length);
+ return new _Uint8ClampedArrayView(this._data, offsetInBytes, length);
}
Int16List asInt16List([int offsetInBytes = 0, int length]) {
@@ -1938,7 +1938,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Int16List.bytesPerElement;
_rangeCheck(
this.lengthInBytes, offsetInBytes, length * Int16List.bytesPerElement);
- return new _Int16ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Int16List.bytesPerElement);
+ return new _Int16ArrayView(this._data, offsetInBytes, length);
}
Uint16List asUint16List([int offsetInBytes = 0, int length]) {
@@ -1946,7 +1947,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Uint16List.bytesPerElement;
_rangeCheck(
this.lengthInBytes, offsetInBytes, length * Uint16List.bytesPerElement);
- return new _Uint16ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Uint16List.bytesPerElement);
+ return new _Uint16ArrayView(this._data, offsetInBytes, length);
}
Int32List asInt32List([int offsetInBytes = 0, int length]) {
@@ -1954,7 +1956,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Int32List.bytesPerElement;
_rangeCheck(
this.lengthInBytes, offsetInBytes, length * Int32List.bytesPerElement);
- return new _Int32ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Int32List.bytesPerElement);
+ return new _Int32ArrayView(this._data, offsetInBytes, length);
}
Uint32List asUint32List([int offsetInBytes = 0, int length]) {
@@ -1962,7 +1965,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Uint32List.bytesPerElement;
_rangeCheck(
this.lengthInBytes, offsetInBytes, length * Uint32List.bytesPerElement);
- return new _Uint32ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Uint32List.bytesPerElement);
+ return new _Uint32ArrayView(this._data, offsetInBytes, length);
}
Int64List asInt64List([int offsetInBytes = 0, int length]) {
@@ -1970,7 +1974,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Int64List.bytesPerElement;
_rangeCheck(
this.lengthInBytes, offsetInBytes, length * Int64List.bytesPerElement);
- return new _Int64ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Int64List.bytesPerElement);
+ return new _Int64ArrayView(this._data, offsetInBytes, length);
}
Uint64List asUint64List([int offsetInBytes = 0, int length]) {
@@ -1978,7 +1983,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Uint64List.bytesPerElement;
_rangeCheck(
this.lengthInBytes, offsetInBytes, length * Uint64List.bytesPerElement);
- return new _Uint64ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Uint64List.bytesPerElement);
+ return new _Uint64ArrayView(this._data, offsetInBytes, length);
}
Float32List asFloat32List([int offsetInBytes = 0, int length]) {
@@ -1986,7 +1992,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Float32List.bytesPerElement;
_rangeCheck(this.lengthInBytes, offsetInBytes,
length * Float32List.bytesPerElement);
- return new _Float32ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Float32List.bytesPerElement);
+ return new _Float32ArrayView(this._data, offsetInBytes, length);
}
Float64List asFloat64List([int offsetInBytes = 0, int length]) {
@@ -1994,7 +2001,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Float64List.bytesPerElement;
_rangeCheck(this.lengthInBytes, offsetInBytes,
length * Float64List.bytesPerElement);
- return new _Float64ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Float64List.bytesPerElement);
+ return new _Float64ArrayView(this._data, offsetInBytes, length);
}
Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) {
@@ -2002,7 +2010,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Float32x4List.bytesPerElement;
_rangeCheck(this.lengthInBytes, offsetInBytes,
length * Float32x4List.bytesPerElement);
- return new _Float32x4ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Float32x4List.bytesPerElement);
+ return new _Float32x4ArrayView(this._data, offsetInBytes, length);
}
Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) {
@@ -2010,7 +2019,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Int32x4List.bytesPerElement;
_rangeCheck(this.lengthInBytes, offsetInBytes,
length * Int32x4List.bytesPerElement);
- return new _Int32x4ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Int32x4List.bytesPerElement);
+ return new _Int32x4ArrayView(this._data, offsetInBytes, length);
}
Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) {
@@ -2018,7 +2028,8 @@
(this.lengthInBytes - offsetInBytes) ~/ Float64x2List.bytesPerElement;
_rangeCheck(this.lengthInBytes, offsetInBytes,
length * Float64x2List.bytesPerElement);
- return new _Float64x2ArrayView(this, offsetInBytes, length);
+ _offsetAlignmentCheck(offsetInBytes, Float64x2List.bytesPerElement);
+ return new _Float64x2ArrayView(this._data, offsetInBytes, length);
}
}
@@ -3562,11 +3573,6 @@
}
abstract class _TypedListView extends _TypedListBase implements TypedData {
- _TypedListView(_ByteBuffer _buffer, int _offset, int _length)
- : _typedData = _buffer._data,
- offsetInBytes = _offset,
- length = _length;
-
// Method(s) implementing the TypedData interface.
int get lengthInBytes {
@@ -3578,13 +3584,13 @@
}
@pragma("vm:non-nullable-result-type")
- final _TypedList _typedData;
+ _TypedList get _typedData native "TypedDataView_typedData";
@pragma("vm:exact-result-type", "dart:core#_Smi")
- final int offsetInBytes;
+ int get offsetInBytes native "TypedDataView_offsetInBytes";
@pragma("vm:exact-result-type", "dart:core#_Smi")
- final int length;
+ int get length native "TypedDataView_length";
}
@pragma("vm:entry-point")
@@ -3592,8 +3598,9 @@
with _IntListMixin
implements Int8List {
// Constructor.
- _Int8ArrayView(_ByteBuffer buffer, int offsetInBytes, int length)
- : super(buffer, offsetInBytes, length);
+ @pragma("vm:exact-result-type", _Int8ArrayView)
+ factory _Int8ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Int8ArrayView_new";
// Method(s) implementing List interface.
int operator [](int index) {
@@ -3628,8 +3635,9 @@
with _IntListMixin
implements Uint8List {
// Constructor.
- _Uint8ArrayView(_ByteBuffer buffer, int offsetInBytes, int length)
- : super(buffer, offsetInBytes, length);
+ @pragma("vm:exact-result-type", _Uint8ArrayView)
+ factory _Uint8ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Uint8ArrayView_new";
// Method(s) implementing List interface.
int operator [](int index) {
@@ -3664,8 +3672,9 @@
with _IntListMixin
implements Uint8ClampedList {
// Constructor.
- _Uint8ClampedArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length);
+ @pragma("vm:exact-result-type", _Uint8ClampedArrayView)
+ factory _Uint8ClampedArrayView(_TypedList buffer, int offsetInBytes,
+ int length) native "TypedDataView_Uint8ClampedArrayView_new";
// Method(s) implementing List interface.
int operator [](int index) {
@@ -3700,10 +3709,9 @@
with _IntListMixin
implements Int16List {
// Constructor.
- _Int16ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Int16List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Int16ArrayView)
+ factory _Int16ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Int16ArrayView_new";
// Method(s) implementing List interface.
int operator [](int index) {
@@ -3750,10 +3758,9 @@
with _IntListMixin
implements Uint16List {
// Constructor.
- _Uint16ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Uint16List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Uint16ArrayView)
+ factory _Uint16ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Uint16ArrayView_new";
// Method(s) implementing List interface.
int operator [](int index) {
@@ -3801,10 +3808,9 @@
with _IntListMixin
implements Int32List {
// Constructor.
- _Int32ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Int32List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Int32ArrayView)
+ factory _Int32ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Int32ArrayView_new";
// Method(s) implementing List interface.
int operator [](int index) {
@@ -3839,10 +3845,9 @@
with _IntListMixin
implements Uint32List {
// Constructor.
- _Uint32ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Uint32List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Uint32ArrayView)
+ factory _Uint32ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Uint32ArrayView_new";
// Method(s) implementing List interface.
int operator [](int index) {
@@ -3877,10 +3882,9 @@
with _IntListMixin
implements Int64List {
// Constructor.
- _Int64ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Int64List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Int64ArrayView)
+ factory _Int64ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Int64ArrayView_new";
// Method(s) implementing List interface.
int operator [](int index) {
@@ -3915,10 +3919,9 @@
with _IntListMixin
implements Uint64List {
// Constructor.
- _Uint64ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Uint64List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Uint64ArrayView)
+ factory _Uint64ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Uint64ArrayView_new";
// Method(s) implementing List interface.
int operator [](int index) {
@@ -3953,10 +3956,9 @@
with _DoubleListMixin
implements Float32List {
// Constructor.
- _Float32ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Float32List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Float32ArrayView)
+ factory _Float32ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Float32ArrayView_new";
// Method(s) implementing List interface.
double operator [](int index) {
@@ -3991,10 +3993,9 @@
with _DoubleListMixin
implements Float64List {
// Constructor.
- _Float64ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Float64List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Float64ArrayView)
+ factory _Float64ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Float64ArrayView_new";
// Method(s) implementing List interface.
double operator [](int index) {
@@ -4029,10 +4030,9 @@
with _Float32x4ListMixin
implements Float32x4List {
// Constructor.
- _Float32x4ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Float32x4List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Float32x4ArrayView)
+ factory _Float32x4ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Float32x4ArrayView_new";
// Method(s) implementing List interface.
Float32x4 operator [](int index) {
@@ -4067,10 +4067,9 @@
with _Int32x4ListMixin
implements Int32x4List {
// Constructor.
- _Int32x4ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Int32x4List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Int32x4ArrayView)
+ factory _Int32x4ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Int32x4ArrayView_new";
// Method(s) implementing List interface.
Int32x4 operator [](int index) {
@@ -4105,10 +4104,9 @@
with _Float64x2ListMixin
implements Float64x2List {
// Constructor.
- _Float64x2ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
- : super(buffer, _offsetInBytes, _length) {
- _offsetAlignmentCheck(_offsetInBytes, Float64x2List.bytesPerElement);
- }
+ @pragma("vm:exact-result-type", _Float64x2ArrayView)
+ factory _Float64x2ArrayView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_Float64x2ArrayView_new";
// Method(s) implementing List interface.
Float64x2 operator [](int index) {
@@ -4140,7 +4138,9 @@
@pragma("vm:entry-point")
class _ByteDataView implements ByteData {
- _ByteDataView(this._typedData, this._offset, this.length);
+ @pragma("vm:exact-result-type", _ByteDataView)
+ factory _ByteDataView(_TypedList buffer, int offsetInBytes, int length)
+ native "TypedDataView_ByteDataView_new";
// Method(s) implementing TypedData interface.
_ByteBuffer get buffer {
@@ -4151,10 +4151,6 @@
return length;
}
- int get offsetInBytes {
- return _offset;
- }
-
int get elementSizeInBytes {
return 1;
}
@@ -4165,35 +4161,35 @@
if (byteOffset < 0 || byteOffset >= length) {
throw new RangeError.index(byteOffset, this, "byteOffset");
}
- return _typedData._getInt8(_offset + byteOffset);
+ return _typedData._getInt8(offsetInBytes + byteOffset);
}
void setInt8(int byteOffset, int value) {
if (byteOffset < 0 || byteOffset >= length) {
throw new RangeError.index(byteOffset, this, "byteOffset");
}
- _typedData._setInt8(_offset + byteOffset, value);
+ _typedData._setInt8(offsetInBytes + byteOffset, value);
}
int getUint8(int byteOffset) {
if (byteOffset < 0 || byteOffset >= length) {
throw new RangeError.index(byteOffset, this, "byteOffset");
}
- return _typedData._getUint8(_offset + byteOffset);
+ return _typedData._getUint8(offsetInBytes + byteOffset);
}
void setUint8(int byteOffset, int value) {
if (byteOffset < 0 || byteOffset >= length) {
throw new RangeError.index(byteOffset, this, "byteOffset");
}
- _typedData._setUint8(_offset + byteOffset, value);
+ _typedData._setUint8(offsetInBytes + byteOffset, value);
}
int getInt16(int byteOffset, [Endian endian = Endian.big]) {
if (byteOffset < 0 || byteOffset + 1 >= length) {
throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
}
- var result = _typedData._getInt16(_offset + byteOffset);
+ var result = _typedData._getInt16(offsetInBytes + byteOffset);
if (identical(endian, Endian.host)) {
return result;
}
@@ -4204,7 +4200,7 @@
if (byteOffset < 0 || byteOffset + 1 >= length) {
throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
}
- _typedData._setInt16(_offset + byteOffset,
+ _typedData._setInt16(offsetInBytes + byteOffset,
identical(endian, Endian.host) ? value : _byteSwap16(value));
}
@@ -4212,7 +4208,7 @@
if (byteOffset < 0 || byteOffset + 1 >= length) {
throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
}
- var result = _typedData._getUint16(_offset + byteOffset);
+ var result = _typedData._getUint16(offsetInBytes + byteOffset);
if (identical(endian, Endian.host)) {
return result;
}
@@ -4223,7 +4219,7 @@
if (byteOffset < 0 || byteOffset + 1 >= length) {
throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
}
- _typedData._setUint16(_offset + byteOffset,
+ _typedData._setUint16(offsetInBytes + byteOffset,
identical(endian, Endian.host) ? value : _byteSwap16(value));
}
@@ -4231,7 +4227,7 @@
if (byteOffset < 0 || byteOffset + 3 >= length) {
throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
}
- var result = _typedData._getInt32(_offset + byteOffset);
+ var result = _typedData._getInt32(offsetInBytes + byteOffset);
if (identical(endian, Endian.host)) {
return result;
}
@@ -4242,7 +4238,7 @@
if (byteOffset < 0 || byteOffset + 3 >= length) {
throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
}
- _typedData._setInt32(_offset + byteOffset,
+ _typedData._setInt32(offsetInBytes + byteOffset,
identical(endian, Endian.host) ? value : _byteSwap32(value));
}
@@ -4250,7 +4246,7 @@
if (byteOffset < 0 || byteOffset + 3 >= length) {
throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
}
- var result = _typedData._getUint32(_offset + byteOffset);
+ var result = _typedData._getUint32(offsetInBytes + byteOffset);
if (identical(endian, Endian.host)) {
return result;
}
@@ -4261,7 +4257,7 @@
if (byteOffset < 0 || byteOffset + 3 >= length) {
throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
}
- _typedData._setUint32(_offset + byteOffset,
+ _typedData._setUint32(offsetInBytes + byteOffset,
identical(endian, Endian.host) ? value : _byteSwap32(value));
}
@@ -4269,7 +4265,7 @@
if (byteOffset < 0 || byteOffset + 7 >= length) {
throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
}
- var result = _typedData._getInt64(_offset + byteOffset);
+ var result = _typedData._getInt64(offsetInBytes + byteOffset);
if (identical(endian, Endian.host)) {
return result;
}
@@ -4280,7 +4276,7 @@
if (byteOffset < 0 || byteOffset + 7 >= length) {
throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
}
- _typedData._setInt64(_offset + byteOffset,
+ _typedData._setInt64(offsetInBytes + byteOffset,
identical(endian, Endian.host) ? value : _byteSwap64(value));
}
@@ -4288,7 +4284,7 @@
if (byteOffset < 0 || byteOffset + 7 >= length) {
throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
}
- var result = _typedData._getUint64(_offset + byteOffset);
+ var result = _typedData._getUint64(offsetInBytes + byteOffset);
if (identical(endian, Endian.host)) {
return result;
}
@@ -4299,7 +4295,7 @@
if (byteOffset < 0 || byteOffset + 7 >= length) {
throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
}
- _typedData._setUint64(_offset + byteOffset,
+ _typedData._setUint64(offsetInBytes + byteOffset,
identical(endian, Endian.host) ? value : _byteSwap64(value));
}
@@ -4308,9 +4304,10 @@
throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
}
if (identical(endian, Endian.host)) {
- return _typedData._getFloat32(_offset + byteOffset);
+ return _typedData._getFloat32(offsetInBytes + byteOffset);
}
- _convU32[0] = _byteSwap32(_typedData._getUint32(_offset + byteOffset));
+ _convU32[0] =
+ _byteSwap32(_typedData._getUint32(offsetInBytes + byteOffset));
return _convF32[0];
}
@@ -4319,11 +4316,11 @@
throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
}
if (identical(endian, Endian.host)) {
- _typedData._setFloat32(_offset + byteOffset, value);
+ _typedData._setFloat32(offsetInBytes + byteOffset, value);
return;
}
_convF32[0] = value;
- _typedData._setUint32(_offset + byteOffset, _byteSwap32(_convU32[0]));
+ _typedData._setUint32(offsetInBytes + byteOffset, _byteSwap32(_convU32[0]));
}
double getFloat64(int byteOffset, [Endian endian = Endian.big]) {
@@ -4331,9 +4328,10 @@
throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
}
if (identical(endian, Endian.host)) {
- return _typedData._getFloat64(_offset + byteOffset);
+ return _typedData._getFloat64(offsetInBytes + byteOffset);
}
- _convU64[0] = _byteSwap64(_typedData._getUint64(_offset + byteOffset));
+ _convU64[0] =
+ _byteSwap64(_typedData._getUint64(offsetInBytes + byteOffset));
return _convF64[0];
}
@@ -4342,11 +4340,11 @@
throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
}
if (identical(endian, Endian.host)) {
- _typedData._setFloat64(_offset + byteOffset, value);
+ _typedData._setFloat64(offsetInBytes + byteOffset, value);
return;
}
_convF64[0] = value;
- _typedData._setUint64(_offset + byteOffset, _byteSwap64(_convU64[0]));
+ _typedData._setUint64(offsetInBytes + byteOffset, _byteSwap64(_convU64[0]));
}
Float32x4 getFloat32x4(int byteOffset, [Endian endian = Endian.big]) {
@@ -4354,7 +4352,7 @@
throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
}
// TODO(johnmccutchan) : Need to resolve this for endianity.
- return _typedData._getFloat32x4(_offset + byteOffset);
+ return _typedData._getFloat32x4(offsetInBytes + byteOffset);
}
void setFloat32x4(int byteOffset, Float32x4 value,
@@ -4363,17 +4361,17 @@
throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
}
// TODO(johnmccutchan) : Need to resolve this for endianity.
- _typedData._setFloat32x4(_offset + byteOffset, value);
+ _typedData._setFloat32x4(offsetInBytes + byteOffset, value);
}
@pragma("vm:non-nullable-result-type")
- final _TypedList _typedData;
+ _TypedList get _typedData native "TypedDataView_typedData";
@pragma("vm:exact-result-type", "dart:core#_Smi")
- final int _offset;
+ int get offsetInBytes native "TypedDataView_offsetInBytes";
@pragma("vm:exact-result-type", "dart:core#_Smi")
- final int length;
+ int get length native "TypedDataView_length";
}
int _byteSwap16(int value) {
diff --git a/runtime/observatory/lib/src/models/repositories/eval.dart b/runtime/observatory/lib/src/models/repositories/eval.dart
index e127d84..2bd4c61 100644
--- a/runtime/observatory/lib/src/models/repositories/eval.dart
+++ b/runtime/observatory/lib/src/models/repositories/eval.dart
@@ -6,5 +6,6 @@
abstract class EvalRepository {
Future<ObjectRef> evaluate(
- IsolateRef isolate, ObjectRef context, String expression);
+ IsolateRef isolate, ObjectRef context, String expression,
+ {bool disableBreakpoints: false});
}
diff --git a/runtime/observatory/lib/src/repositories/eval.dart b/runtime/observatory/lib/src/repositories/eval.dart
index 90b8b12..57ab1ec 100644
--- a/runtime/observatory/lib/src/repositories/eval.dart
+++ b/runtime/observatory/lib/src/repositories/eval.dart
@@ -5,12 +5,14 @@
part of repositories;
class EvalRepository extends M.EvalRepository {
- Future<M.ObjectRef> evaluate(M.IsolateRef i, M.ObjectRef o, String e) async {
+ Future<M.ObjectRef> evaluate(M.IsolateRef i, M.ObjectRef o, String e,
+ {bool disableBreakpoints: false}) async {
S.Isolate isolate = i as S.Isolate;
S.ServiceObject object = o as S.HeapObject;
assert(isolate != null);
assert(object != null);
assert(e != null);
- return await isolate.eval(object, e);
+ return await isolate.eval(object, e,
+ disableBreakpoints: disableBreakpoints);
}
}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index aa59574..cc8f158 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1893,10 +1893,11 @@
}
Future<ServiceObject> eval(ServiceObject target, String expression,
- {Map<String, ServiceObject> scope}) {
+ {Map<String, ServiceObject> scope, bool disableBreakpoints: false}) {
Map params = {
'targetId': target.id,
'expression': expression,
+ 'disableBreakpoints': disableBreakpoints,
};
if (scope != null) {
Map<String, String> scopeWithIds = new Map();
@@ -1909,10 +1910,12 @@
}
Future<ServiceObject> evalFrame(int frameIndex, String expression,
- {Map<String, ServiceObject> scope}) async {
+ {Map<String, ServiceObject> scope,
+ bool disableBreakpoints: false}) async {
Map params = {
'frameIndex': frameIndex,
'expression': expression,
+ 'disableBreakpoints': disableBreakpoints,
};
if (scope != null) {
Map<String, String> scopeWithIds = new Map();
@@ -2482,8 +2485,9 @@
}
Future<ServiceObject> evaluate(String expression,
- {Map<String, ServiceObject> scope}) {
- return isolate.eval(this, expression, scope: scope);
+ {Map<String, ServiceObject> scope, bool disableBreakpoints: false}) {
+ return isolate.eval(this, expression,
+ scope: scope, disableBreakpoints: disableBreakpoints);
}
Script get rootScript {
@@ -2661,8 +2665,9 @@
}
Future<ServiceObject> evaluate(String expression,
- {Map<String, ServiceObject> scope}) {
- return isolate.eval(this, expression, scope: scope);
+ {Map<String, ServiceObject> scope, disableBreakpoints: false}) {
+ return isolate.eval(this, expression,
+ scope: scope, disableBreakpoints: disableBreakpoints);
}
Future<ServiceObject> setTraceAllocations(bool enable) {
@@ -3027,8 +3032,9 @@
}
Future<ServiceObject> evaluate(String expression,
- {Map<String, ServiceObject> scope}) {
- return isolate.eval(this, expression, scope: scope);
+ {Map<String, ServiceObject> scope, bool disableBreakpoints: false}) {
+ return isolate.eval(this, expression,
+ scope: scope, disableBreakpoints: disableBreakpoints);
}
String toString() => 'Instance($shortName)';
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart
index 5f143fa..0b7a072 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart
@@ -5,7 +5,8 @@
part of mocks;
typedef Future<M.Object> EvalRepositoryMockCallback(
- M.IsolateRef isolate, M.ObjectRef context, String expression);
+ M.IsolateRef isolate, M.ObjectRef context, String expression,
+ {bool disableBreakpoints});
class EvalRepositoryMock implements M.EvalRepository {
final EvalRepositoryMockCallback _get;
@@ -13,9 +14,11 @@
EvalRepositoryMock({EvalRepositoryMockCallback getter}) : _get = getter;
Future<M.Object> evaluate(
- M.IsolateRef isolate, M.ObjectRef context, String expression) {
+ M.IsolateRef isolate, M.ObjectRef context, String expression,
+ {bool disableBreakpoints: false}) {
if (_get != null) {
- return _get(isolate, context, expression);
+ return _get(isolate, context, expression,
+ disableBreakpoints: disableBreakpoints);
}
return new Future.value(null);
}
diff --git a/runtime/observatory/tests/service/eval_skip_breakpoint.dart b/runtime/observatory/tests/service/eval_skip_breakpoint.dart
new file mode 100644
index 0000000..447852f
--- /dev/null
+++ b/runtime/observatory/tests/service/eval_skip_breakpoint.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, 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=--verbose_debug
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 21;
+const int LINE_B = 16;
+
+bar() {
+ print('bar');
+}
+
+testMain() {
+ debugger();
+ bar();
+ print("Done");
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+// Add breakpoint
+ setBreakpointAtLine(LINE_B),
+// Evaluate 'bar()'
+ (Isolate isolate) async {
+ final lib = isolate.rootLibrary;
+ await lib.evaluate('bar()', disableBreakpoints: true);
+ },
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+ resumeIsolate,
+
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_B),
+ resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/get_memory_usage.dart b/runtime/observatory/tests/service/get_memory_usage.dart
new file mode 100644
index 0000000..96832c2
--- /dev/null
+++ b/runtime/observatory/tests/service/get_memory_usage.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2019, 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:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+ (VM vm) async {
+ var params = {
+ 'isolateId': vm.isolates.first.id,
+ };
+ var result = await vm.invokeRpcNoUpgrade('getMemoryUsage', params);
+ expect(result['type'], equals('MemoryUsage'));
+ expect(result['heapUsage'], isPositive);
+ expect(result['heapCapacity'], isPositive);
+ expect(result['externalUsage'], isPositive);
+ },
+ (VM vm) async {
+ var params = {
+ 'isolateId': 'badid',
+ };
+ bool caughtException;
+ try {
+ await vm.invokeRpcNoUpgrade('getMemoryUsage', params);
+ expect(false, isTrue, reason: 'Unreachable');
+ } on ServerRpcException catch (e) {
+ caughtException = true;
+ expect(e.code, equals(ServerRpcException.kInvalidParams));
+ expect(e.message, "getMemoryUsage: invalid 'isolateId' parameter: badid");
+ }
+ expect(caughtException, isTrue);
+ },
+
+ // Plausible isolate id, not found.
+ (VM vm) async {
+ var params = {
+ 'isolateId': 'isolates/9999999999',
+ };
+ var result = await vm.invokeRpcNoUpgrade('getMemoryUsage', params);
+ expect(result['type'], equals('Sentinel'));
+ expect(result['kind'], equals('Collected'));
+ expect(result['valueAsString'], equals('<collected>'));
+ },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/invoke_skip_breakpoint.dart b/runtime/observatory/tests/service/invoke_skip_breakpoint.dart
new file mode 100644
index 0000000..d2d258c
--- /dev/null
+++ b/runtime/observatory/tests/service/invoke_skip_breakpoint.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2019, 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:developer';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 21;
+const int LINE_B = 16;
+
+bar() {
+ print('bar');
+ return 'bar';
+}
+
+testMain() {
+ debugger();
+ bar();
+ print("Done");
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+ setBreakpointAtLine(LINE_B),
+ (Isolate isolate) async {
+ Library lib = isolate.rootLibrary;
+ await lib.load();
+
+ dynamic result = await isolate.invokeRpc("invoke", {
+ "targetId": lib.id,
+ "selector": "bar",
+ "argumentIds": [],
+ "disableBreakpoints": true
+ });
+ print(result);
+ expect(result.valueAsString, equals('bar'));
+ },
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_B),
+ resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart b/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
index a38c966..9f70deb 100644
--- a/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
+++ b/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
@@ -33,23 +33,23 @@
List<String> stops = [];
List<String> expected = [
- "$file:${LINE+0}:17", // on "Foo" (in "new Foo()")
- "$file:${LINE+1}:11", // on "="
- "list.dart:105:24", // on parameter to "contains"
- "list.dart:106:23", // on "length" in "this.length"
- "list.dart:107:16", // on "=" in "i = 0"
- "list.dart:107:23", // on "<" in "i < length"
- "list.dart:108:15", // on "[" in "this[i]"
- "$file:${LINE+13}:23", // on parameter in "operator []"
- "$file:${LINE+14}:5", // on "return"
- "list.dart:108:19", // on "=="
- "list.dart:109:26", // on "length" in "this.length"
- "list.dart:109:18", // on "!="
- "list.dart:107:34", // on "++" in "i++"
- "list.dart:107:23", // on "<" in "i < length"
- "list.dart:113:5", // on "return"
- "$file:${LINE+4}:5", // on "print"
- "$file:${LINE+6}:1" // on ending '}'
+ "$file:${LINE + 0}:17", // on "Foo" (in "new Foo()")
+ "$file:${LINE + 1}:11", // on "="
+ "list.dart:100:24", // on parameter to "contains"
+ "list.dart:101:23", // on "length" in "this.length"
+ "list.dart:102:16", // on "=" in "i = 0"
+ "list.dart:102:23", // on "<" in "i < length"
+ "list.dart:103:15", // on "[" in "this[i]"
+ "$file:${LINE + 13}:23", // on parameter in "operator []"
+ "$file:${LINE + 14}:5", // on "return"
+ "list.dart:103:19", // on "=="
+ "list.dart:104:26", // on "length" in "this.length"
+ "list.dart:104:18", // on "!="
+ "list.dart:102:34", // on "++" in "i++"
+ "list.dart:102:23", // on "<" in "i < length"
+ "list.dart:108:5", // on "return"
+ "$file:${LINE + 4}:5", // on "print"
+ "$file:${LINE + 6}:1" // on ending '}'
];
var tests = <IsolateTest>[
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 6171827..07d2d03 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -352,12 +352,6 @@
#error Unknown architecture.
#endif
-// Disable background threads by default on armv5te. The relevant
-// implementations are uniprocessors.
-#if !defined(TARGET_ARCH_ARM_5TE)
-#define ARCH_IS_MULTI_CORE 1
-#endif
-
#if !defined(TARGET_OS_ANDROID) && !defined(TARGET_OS_FUCHSIA) && \
!defined(TARGET_OS_MACOS_IOS) && !defined(TARGET_OS_LINUX) && \
!defined(TARGET_OS_MACOS) && !defined(TARGET_OS_WINDOWS)
@@ -380,6 +374,19 @@
#endif
#endif
+// Determine whether dual mapping of code pages is supported.
+// We test dual mapping on linux x64 and deploy it on fuchsia.
+#if defined(TARGET_OS_LINUX) && defined(TARGET_ARCH_X64) || \
+ defined(TARGET_OS_FUCHSIA)
+#define DUAL_MAPPING_SUPPORTED 1
+#endif
+
+// Disable background threads by default on armv5te. The relevant
+// implementations are uniprocessors.
+#if !defined(TARGET_ARCH_ARM_5TE)
+#define ARCH_IS_MULTI_CORE 1
+#endif
+
// Short form printf format specifiers
#define Pd PRIdPTR
#define Pu PRIuPTR
diff --git a/runtime/tests/vm/dart/compilation_trace_test.dart b/runtime/tests/vm/dart/compilation_trace_test.dart
new file mode 100644
index 0000000..4ebafb5
--- /dev/null
+++ b/runtime/tests/vm/dart/compilation_trace_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+
+import "package:path/path.dart" as p;
+
+import "snapshot_test_helper.dart";
+
+int fib(int n) {
+ if (n <= 1) return 1;
+ return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+ if (args.contains("--child")) {
+ print(fib(35));
+ return;
+ }
+
+ if (!Platform.script.toString().endsWith(".dart")) {
+ print("This test must run from source");
+ return;
+ }
+
+ await withTempDir((String tmp) async {
+ final String tracePath = p.join(tmp, "compilation_trace.txt");
+
+ final result1 = await runDart("generate compilation trace", [
+ "--save_compilation_trace=$tracePath",
+ Platform.script.toFilePath(),
+ "--child",
+ ]);
+ expectOutput("14930352", result1);
+
+ final result2 = await runDart("use compilation trace", [
+ "--load_compilation_trace=$tracePath",
+ Platform.script.toFilePath(),
+ "--child",
+ ]);
+ expectOutput("14930352", result2);
+ });
+}
diff --git a/runtime/tests/vm/dart/licm_and_assert_strengthening_test.dart b/runtime/tests/vm/dart/licm_and_assert_strengthening_test.dart
new file mode 100644
index 0000000..a1c962e
--- /dev/null
+++ b/runtime/tests/vm/dart/licm_and_assert_strengthening_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2019, 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=--optimization-counter-threshold=10 --no-background-compilation
+
+// This test checks for obscure interaction between LICM and AssertAssignable
+// strengthening performed by Type Propagator. The later would use deopt_id
+// from an environment attached to AssertAssignable, and this deopt id under
+// certain conditions would be set to -1. The code was changed to never
+// use deopt_id from the environment but this regression test is provided for
+// completeness.
+
+class A<T> {
+ var foo = 42;
+}
+
+class B extends A<String> {}
+
+class C extends B {}
+
+void foo(dynamic a) {
+ // To prevent AssertAssignable strengthening from occuring too early we
+ // need to hide the fact that CheckClass and AssertAssignable are performed
+ // against the same SSA value. To achieve that we store a into an array and
+ // then load it back. Load Forwarding would happen just before LICM and
+ // will remove the indirection. Then LICM would hoist both CheckClass
+ // and AssertAssignable out of the loop and then strengthening would happen.
+ final box = <dynamic>[null];
+ box[0] = a;
+
+ for (var i = 0; i < 1; i++) {
+ a as A<String>;
+ if (box[0].foo != 42) {
+ throw "unexpected";
+ }
+ }
+}
+
+void main() {
+ for (var i = 0; i < 100; i++) {
+ foo(B());
+ }
+
+ // Trigger deoptimization on the CheckClass produced by strengthened
+ // AssertAssignable - if this CheckClass has wrong deoptimization id a crash
+ // would occur.
+ foo(C());
+}
diff --git a/runtime/tests/vm/dart/reused_instructions_test.dart b/runtime/tests/vm/dart/reused_instructions_test.dart
new file mode 100644
index 0000000..a2316c8
--- /dev/null
+++ b/runtime/tests/vm/dart/reused_instructions_test.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+
+import "package:path/path.dart" as p;
+
+import "snapshot_test_helper.dart";
+
+int fib(int n) {
+ if (n <= 1) return 1;
+ return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+ if (args.contains("--child")) {
+ print(fib(35));
+ return;
+ }
+
+ if (!Platform.script.toString().endsWith(".dart")) {
+ print("This test must run from source");
+ return;
+ }
+
+ await withTempDir((String tmp) async {
+ final String coreVMDataPath = p.join(tmp, "core_vm_snapshot_data.bin");
+ final String coreIsoDataPath =
+ p.join(tmp, "core_isolate_snapshot_data.bin");
+ final String baselineIsoDataPath =
+ p.join(tmp, "baseline_isolate_snapshot_data.bin");
+ final String baselineIsoInstrPath =
+ p.join(tmp, "baseline_isolate_snapshot_instructions.bin");
+ final String patchIsoDataPath =
+ p.join(tmp, "patch_isolate_snapshot_data.bin");
+ final String patchIsoInstrPath =
+ p.join(tmp, "patch_isolate_snapshot_instr.bin");
+ final String kernelPath = p.join(tmp, "app.dill");
+ final String tracePath = p.join(tmp, "compilation_trace.txt");
+
+ // We don't support snapshot with code on IA32.
+ final String appSnapshotKind =
+ Platform.version.contains("ia32") ? "app" : "app-jit";
+
+ final result1 = await runGenKernel("generate kernel", [
+ Platform.script.toFilePath(),
+ "--output",
+ kernelPath,
+ ]);
+ expectOutput("", result1);
+
+ final result2 = await runDart("generate compilation trace", [
+ "--save_compilation_trace=$tracePath",
+ kernelPath,
+ "--child",
+ ]);
+ expectOutput("14930352", result2);
+
+ final result3 = await runGenSnapshot("generate core snapshot", [
+ "--snapshot_kind=core",
+ "--vm_snapshot_data=${coreVMDataPath}",
+ "--isolate_snapshot_data=${coreIsoDataPath}",
+ platformDill,
+ ]);
+ expectOutput("", result3);
+
+ final result4 = await runGenSnapshot("generate baseline app snapshot", [
+ "--snapshot_kind=${appSnapshotKind}",
+ "--load_vm_snapshot_data=${coreVMDataPath}",
+ "--load_isolate_snapshot_data=${coreIsoDataPath}",
+ "--isolate_snapshot_data=${baselineIsoDataPath}",
+ "--isolate_snapshot_instructions=${baselineIsoInstrPath}",
+ "--load_compilation_trace=$tracePath",
+ kernelPath,
+ ]);
+ expectOutput("", result4);
+
+ final result5 = await runGenSnapshot("generate patch app snapshot", [
+ "--snapshot_kind=${appSnapshotKind}",
+ "--load_vm_snapshot_data=${coreVMDataPath}",
+ "--load_isolate_snapshot_data=${coreIsoDataPath}",
+ "--isolate_snapshot_data=${patchIsoDataPath}",
+ "--isolate_snapshot_instructions=${patchIsoInstrPath}",
+ "--reused_instructions=${baselineIsoInstrPath}",
+ "--load_compilation_trace=$tracePath",
+ kernelPath,
+ ]);
+ expectOutput("", result5);
+ });
+}
diff --git a/runtime/tests/vm/dart/shared_snapshot_test.dart b/runtime/tests/vm/dart/shared_snapshot_test.dart
new file mode 100644
index 0000000..eff8068
--- /dev/null
+++ b/runtime/tests/vm/dart/shared_snapshot_test.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+
+import "package:path/path.dart" as p;
+
+import "snapshot_test_helper.dart";
+
+int fib(int n) {
+ if (n <= 1) return 1;
+ return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+ if (args.contains("--child")) {
+ print(fib(35));
+ return;
+ }
+
+ if (!Platform.script.toString().endsWith(".dart")) {
+ print("This test must run from source");
+ return;
+ }
+
+ await withTempDir((String tmp) async {
+ final String coreVMDataPath = p.join(tmp, "core_vm_snapshot_data.bin");
+ final String coreIsoDataPath =
+ p.join(tmp, "core_isolate_snapshot_data.bin");
+ final String baselineIsoDataPath =
+ p.join(tmp, "baseline_isolate_snapshot_data.bin");
+ final String baselineIsoInstrPath =
+ p.join(tmp, "baseline_isolate_snapshot_instructions.bin");
+ final String patchIsoDataPath =
+ p.join(tmp, "patch_isolate_snapshot_data.bin");
+ final String patchIsoInstrPath =
+ p.join(tmp, "patch_isolate_snapshot_instr.bin");
+ final String kernelPath = p.join(tmp, "app.dill");
+ final String tracePath = p.join(tmp, "compilation_trace.txt");
+
+ // We don't support snapshot with code on IA32.
+ final String appSnapshotKind =
+ Platform.version.contains("ia32") ? "app" : "app-jit";
+
+ final result1 = await runGenKernel("generate kernel", [
+ Platform.script.toFilePath(),
+ "--output",
+ kernelPath,
+ ]);
+ expectOutput("", result1);
+
+ final result2 = await runDart("generate compilation trace", [
+ "--save_compilation_trace=$tracePath",
+ kernelPath,
+ "--child",
+ ]);
+ expectOutput("14930352", result2);
+
+ final result3 = await runGenSnapshot("generate core snapshot", [
+ "--snapshot_kind=core",
+ "--vm_snapshot_data=${coreVMDataPath}",
+ "--isolate_snapshot_data=${coreIsoDataPath}",
+ platformDill,
+ ]);
+ expectOutput("", result3);
+
+ final result4 = await runGenSnapshot("generate baseline app snapshot", [
+ "--snapshot_kind=${appSnapshotKind}",
+ "--load_vm_snapshot_data=${coreVMDataPath}",
+ "--load_isolate_snapshot_data=${coreIsoDataPath}",
+ "--isolate_snapshot_data=${baselineIsoDataPath}",
+ "--isolate_snapshot_instructions=${baselineIsoInstrPath}",
+ "--load_compilation_trace=$tracePath",
+ kernelPath,
+ ]);
+ expectOutput("", result4);
+
+ final result5 = await runGenSnapshot("generate patch app snapshot", [
+ "--snapshot_kind=${appSnapshotKind}",
+ "--load_vm_snapshot_data=${coreVMDataPath}",
+ "--load_isolate_snapshot_data=${coreIsoDataPath}",
+ "--isolate_snapshot_data=${patchIsoDataPath}",
+ "--isolate_snapshot_instructions=${patchIsoInstrPath}",
+ "--shared_data=${baselineIsoDataPath}",
+ "--shared_instructions=${baselineIsoInstrPath}",
+ "--load_compilation_trace=$tracePath",
+ kernelPath,
+ ]);
+ expectOutput("", result5);
+ });
+}
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
index 5c27ced..0a043af 100644
--- a/runtime/tests/vm/dart/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -41,15 +41,39 @@
}
}
-Future<Result> runDartBinary(String prefix, List<String> arguments) async {
- final binary = Platform.executable;
- final actualArguments = <String>[]
+final String scriptSuffix = Platform.isWindows ? ".bat" : "";
+final String executableSuffix = Platform.isWindows ? ".exe" : "";
+final String buildDir = p.dirname(Platform.executable);
+final String platformDill = p.join(buildDir, "vm_platform_strong.dill");
+final String genSnapshot = p.join(buildDir, "gen_snapshot${executableSuffix}");
+final String genKernel =
+ p.join("pkg", "vm", "tool", "gen_kernel${scriptSuffix}");
+
+Future<Result> runDart(String prefix, List<String> arguments) {
+ final augmentedArguments = <String>[]
..addAll(Platform.executableArguments)
..addAll(arguments);
- print("+ $binary " + actualArguments.join(" "));
- final processResult = await Process.run(binary, actualArguments);
- final result = new Result(
- '[$prefix] ${binary} ${actualArguments.join(' ')}', processResult);
+ return runBinary(prefix, Platform.executable, augmentedArguments);
+}
+
+Future<Result> runGenKernel(String prefix, List<String> arguments) {
+ final augmentedArguments = <String>[]
+ ..add("--platform")
+ ..add(platformDill)
+ ..addAll(arguments);
+ return runBinary(prefix, genKernel, augmentedArguments);
+}
+
+Future<Result> runGenSnapshot(String prefix, List<String> arguments) {
+ return runBinary(prefix, genSnapshot, arguments);
+}
+
+Future<Result> runBinary(
+ String prefix, String binary, List<String> arguments) async {
+ print("+ $binary " + arguments.join(" "));
+ final processResult = await Process.run(binary, arguments);
+ final result =
+ new Result('[$prefix] ${binary} ${arguments.join(' ')}', processResult);
if (processResult.stdout.isNotEmpty) {
print('''
@@ -72,16 +96,23 @@
return result;
}
-Future<Null> checkDeterministicSnapshot(
- String snapshotKind, String expectedStdout) async {
- final Directory temp = Directory.systemTemp.createTempSync();
- final snapshot1Path = p.join(temp.path, 'snapshot1');
- final snapshot2Path = p.join(temp.path, 'snapshot2');
-
+withTempDir(Future fun(String dir)) async {
+ final Directory tempDir = Directory.systemTemp.createTempSync();
try {
+ await fun(tempDir.path);
+ } finally {
+ tempDir.deleteSync(recursive: true);
+ }
+}
+
+checkDeterministicSnapshot(String snapshotKind, String expectedStdout) async {
+ await withTempDir((String temp) async {
+ final snapshot1Path = p.join(temp, 'snapshot1');
+ final snapshot2Path = p.join(temp, 'snapshot2');
+
print("Version ${Platform.version}");
- final generate1Result = await runDartBinary('GENERATE SNAPSHOT 1', [
+ final generate1Result = await runDart('GENERATE SNAPSHOT 1', [
'--deterministic',
'--trace_class_finalization',
'--trace_type_finalization',
@@ -94,7 +125,7 @@
]);
expectOutput(expectedStdout, generate1Result);
- final generate2Result = await runDartBinary('GENERATE SNAPSHOT 2', [
+ final generate2Result = await runDart('GENERATE SNAPSHOT 2', [
'--deterministic',
'--trace_class_finalization',
'--trace_type_finalization',
@@ -117,42 +148,36 @@
}
}
Expect.equals(snapshot1Bytes.length, snapshot2Bytes.length);
- } finally {
- await temp.delete(recursive: true);
- }
+ });
}
-Future<void> runAppJitTest() async {
- final Directory temp = Directory.systemTemp.createTempSync();
- final snapshotPath = p.join(temp.path, 'app.jit');
- final testPath = Platform.script
- .toFilePath()
- .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
+runAppJitTest() async {
+ await withTempDir((String temp) async {
+ final snapshotPath = p.join(temp, 'app.jit');
+ final testPath = Platform.script
+ .toFilePath()
+ .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
- try {
- final trainingResult = await runDartBinary('TRAINING RUN', [
+ final trainingResult = await runDart('TRAINING RUN', [
'--snapshot=$snapshotPath',
'--snapshot-kind=app-jit',
testPath,
'--train'
]);
expectOutput("OK(Trained)", trainingResult);
- final runResult = await runDartBinary('RUN FROM SNAPSHOT', [snapshotPath]);
+ final runResult = await runDart('RUN FROM SNAPSHOT', [snapshotPath]);
expectOutput("OK(Run)", runResult);
- } finally {
- await temp.delete(recursive: true);
- }
+ });
}
Future<void> runAppJitBytecodeTest() async {
- final Directory temp = Directory.systemTemp.createTempSync();
- final snapshotPath = p.join(temp.path, 'app.jit');
- final testPath = Platform.script
- .toFilePath()
- .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
+ await withTempDir((String temp) async {
+ final snapshotPath = p.join(temp, 'app.jit');
+ final testPath = Platform.script
+ .toFilePath()
+ .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
- try {
- final trainingResult = await runDartBinary('TRAINING RUN', [
+ final trainingResult = await runDart('TRAINING RUN', [
'--enable_interpreter',
'--snapshot=$snapshotPath',
'--snapshot-kind=app-jit',
@@ -160,10 +185,8 @@
'--train'
]);
expectOutput("OK(Trained)", trainingResult);
- final runResult = await runDartBinary(
+ final runResult = await runDart(
'RUN FROM SNAPSHOT', ['--enable_interpreter', snapshotPath]);
expectOutput("OK(Run)", runResult);
- } finally {
- await temp.delete(recursive: true);
- }
+ });
}
diff --git a/runtime/tests/vm/dart/type_feedback_test.dart b/runtime/tests/vm/dart/type_feedback_test.dart
new file mode 100644
index 0000000..6211c70
--- /dev/null
+++ b/runtime/tests/vm/dart/type_feedback_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+
+import "package:path/path.dart" as p;
+
+import "snapshot_test_helper.dart";
+
+int fib(int n) {
+ if (n <= 1) return 1;
+ return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+ if (args.contains("--child")) {
+ print(fib(35));
+ return;
+ }
+
+ if (!Platform.script.toString().endsWith(".dart")) {
+ print("This test must run from source");
+ return;
+ }
+
+ await withTempDir((String tmp) async {
+ final String feedbackPath = p.join(tmp, "type_feedback.bin");
+
+ final result1 = await runDart("generate type feedback", [
+ "--save_type_feedback=$feedbackPath",
+ Platform.script.toFilePath(),
+ "--child",
+ ]);
+ expectOutput("14930352", result1);
+
+ final result2 = await runDart("use type feedback", [
+ "--load_type_feedback=$feedbackPath",
+ Platform.script.toFilePath(),
+ "--child",
+ ]);
+ expectOutput("14930352", result2);
+ });
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index a56a92eb..6554bb2 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -4,6 +4,7 @@
cc/AllocGeneric_Overflow: Crash, Fail # These tests are expected to crash on all platforms.
cc/ArrayNew_Overflow_Crash: Crash, Fail # These tests are expected to crash on all platforms.
+cc/CodeExecutability: Crash, Fail # These tests are expected to crash on all platforms.
cc/CodeImmutability: Crash, Fail # These tests are expected to crash on all platforms.
cc/Dart2JSCompileAll: Fail, Crash # Issue 27369
cc/Dart2JSCompilerStats: Fail, Crash # Issue 27369
@@ -28,6 +29,7 @@
dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
[ $builder_tag == asan ]
+cc/CodeExecutability: Fail, OK # Address Sanitizer turns a crash into a failure.
cc/CodeImmutability: Fail, OK # Address Sanitizer turns a crash into a failure.
[ $builder_tag == optimization_counter_threshold ]
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 194a86c..da9161f 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -211,6 +211,24 @@
V(TypedData_SetInt32x4, 3) \
V(TypedData_GetFloat64x2, 2) \
V(TypedData_SetFloat64x2, 3) \
+ V(TypedDataView_ByteDataView_new, 4) \
+ V(TypedDataView_Int8ArrayView_new, 4) \
+ V(TypedDataView_Uint8ArrayView_new, 4) \
+ V(TypedDataView_Uint8ClampedArrayView_new, 4) \
+ V(TypedDataView_Int16ArrayView_new, 4) \
+ V(TypedDataView_Uint16ArrayView_new, 4) \
+ V(TypedDataView_Int32ArrayView_new, 4) \
+ V(TypedDataView_Uint32ArrayView_new, 4) \
+ V(TypedDataView_Int64ArrayView_new, 4) \
+ V(TypedDataView_Uint64ArrayView_new, 4) \
+ V(TypedDataView_Float32ArrayView_new, 4) \
+ V(TypedDataView_Float64ArrayView_new, 4) \
+ V(TypedDataView_Float32x4ArrayView_new, 4) \
+ V(TypedDataView_Int32x4ArrayView_new, 4) \
+ V(TypedDataView_Float64x2ArrayView_new, 4) \
+ V(TypedDataView_length, 1) \
+ V(TypedDataView_offsetInBytes, 1) \
+ V(TypedDataView_typedData, 1) \
V(Float32x4_fromDoubles, 5) \
V(Float32x4_splat, 2) \
V(Float32x4_fromInt32x4Bits, 2) \
diff --git a/runtime/vm/catch_entry_moves_test.cc b/runtime/vm/catch_entry_moves_test.cc
new file mode 100644
index 0000000..faa41f6
--- /dev/null
+++ b/runtime/vm/catch_entry_moves_test.cc
@@ -0,0 +1,198 @@
+// Copyright (c) 2019, 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 <functional>
+#include <utility>
+
+#include "platform/assert.h"
+#include "vm/code_descriptors.h"
+#include "vm/exceptions.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+static CatchEntryMove NewMove(intptr_t src, intptr_t dst) {
+ return CatchEntryMove::FromSlot(CatchEntryMove::SourceKind::kTaggedSlot, src,
+ dst);
+}
+const auto kA = NewMove(1, 10);
+const auto kB = NewMove(2, 20);
+const auto kC = NewMove(3, 30);
+const auto kD = NewMove(4, 40);
+const auto kE = NewMove(5, 50);
+const auto kX = NewMove(-1, -10);
+
+const CatchEntryMove abcde[] = {kA, kB, kC, kD, kE};
+const CatchEntryMove abcdx[] = {kA, kB, kC, kD, kX};
+const CatchEntryMove xbcde[] = {kX, kB, kC, kD, kE};
+const CatchEntryMove abxde[] = {kA, kB, kX, kD, kE};
+const CatchEntryMove ab[] = {kA, kB};
+const CatchEntryMove de[] = {kD, kE};
+
+struct TestCaseMoves {
+ const CatchEntryMove* moves;
+ const intptr_t count;
+};
+
+void RunTestCaseWithPermutations(const TestCaseMoves* mapping,
+ intptr_t* insert_permutation,
+ intptr_t count) {
+ CatchEntryMovesMapBuilder b;
+
+ for (intptr_t i = 0; i < count; ++i) {
+ auto expected_moves = mapping[insert_permutation[i]];
+ b.NewMapping(/*pc_offset=*/insert_permutation[i]);
+ for (intptr_t j = 0; j < expected_moves.count; ++j) {
+ b.Append(expected_moves.moves[j]);
+ }
+ b.EndMapping();
+ }
+
+ const auto& bytes = TypedData::Handle(b.FinalizeCatchEntryMovesMap());
+ CatchEntryMovesMapReader reader(bytes);
+
+ for (intptr_t i = 0; i < count; ++i) {
+ auto expected_moves = mapping[i];
+ auto read_moves = reader.ReadMovesForPcOffset(i);
+ EXPECT_EQ(expected_moves.count, read_moves->count());
+ for (intptr_t j = 0; j < expected_moves.count; ++j) {
+ EXPECT(expected_moves.moves[j] == read_moves->At(j));
+ }
+ free(read_moves);
+ }
+}
+
+void RunTestCase(const TestCaseMoves* mapping, intptr_t count) {
+ std::unique_ptr<intptr_t[]> permutation(new intptr_t[count]);
+ for (intptr_t i = 0; i < count; ++i) {
+ permutation[i] = i;
+ }
+
+ std::function<void(intptr_t)> run_all_permutations = [&](intptr_t offset) {
+ if (offset == count) {
+ RunTestCaseWithPermutations(mapping, &permutation[0], count);
+ } else {
+ for (intptr_t i = offset; i < count; ++i) {
+ const intptr_t start = permutation[offset];
+ const intptr_t replacement = permutation[i];
+
+ permutation[offset] = replacement;
+ permutation[i] = start;
+
+ run_all_permutations(offset + 1);
+
+ permutation[offset] = start;
+ permutation[i] = replacement;
+ }
+ }
+ };
+
+ run_all_permutations(0);
+}
+
+ISOLATE_UNIT_TEST_CASE(CatchEntryMoves) {
+ // Common prefix.
+ const TestCaseMoves test1[] = {
+ TestCaseMoves{
+ abcde,
+ ARRAY_SIZE(abcde),
+ },
+ TestCaseMoves{
+ abcdx,
+ ARRAY_SIZE(abcdx),
+ },
+ };
+ RunTestCase(test1, ARRAY_SIZE(test1));
+
+ // Common suffix.
+ const TestCaseMoves test2[] = {
+ TestCaseMoves{
+ abcde,
+ ARRAY_SIZE(abcde),
+ },
+ TestCaseMoves{
+ xbcde,
+ ARRAY_SIZE(xbcde),
+ },
+ };
+ RunTestCase(test2, ARRAY_SIZE(test2));
+
+ // Common prefix and suffix.
+ const TestCaseMoves test3[] = {
+ TestCaseMoves{
+ abcde,
+ ARRAY_SIZE(abcde),
+ },
+ TestCaseMoves{
+ abxde,
+ ARRAY_SIZE(abxde),
+ },
+ };
+ RunTestCase(test3, ARRAY_SIZE(test3));
+
+ // Subset of suffix.
+ const TestCaseMoves test4[] = {
+ TestCaseMoves{
+ abcde,
+ ARRAY_SIZE(abcde),
+ },
+ TestCaseMoves{
+ de,
+ ARRAY_SIZE(de),
+ },
+ };
+ RunTestCase(test4, ARRAY_SIZE(test4));
+
+ // Subset of prefix.
+ const TestCaseMoves test5[] = {
+ TestCaseMoves{
+ abcde,
+ ARRAY_SIZE(abcde),
+ },
+ TestCaseMoves{
+ ab,
+ ARRAY_SIZE(ab),
+ },
+ };
+ RunTestCase(test5, ARRAY_SIZE(test5));
+
+ // All moves (with duplicates).
+ const TestCaseMoves test6[] = {
+ TestCaseMoves{
+ abcde,
+ ARRAY_SIZE(abcde),
+ },
+ TestCaseMoves{
+ abcde,
+ ARRAY_SIZE(abcde),
+ },
+ TestCaseMoves{
+ abcdx,
+ ARRAY_SIZE(abcdx),
+ },
+ TestCaseMoves{
+ xbcde,
+ ARRAY_SIZE(xbcde),
+ },
+ TestCaseMoves{
+ abxde,
+ ARRAY_SIZE(abxde),
+ },
+ TestCaseMoves{
+ ab,
+ ARRAY_SIZE(ab),
+ },
+ TestCaseMoves{
+ de,
+ ARRAY_SIZE(de),
+ },
+ TestCaseMoves{
+ de,
+ ARRAY_SIZE(de),
+ },
+ };
+ RunTestCase(test6, ARRAY_SIZE(test6));
+}
+
+} // namespace dart
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index fb88a4c..eb79223 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1225,6 +1225,12 @@
sentinel.SetStaticValue(enum_value, true);
sentinel.RecordStore(enum_value);
+ const GrowableObjectArray& pending_unevaluated_const_fields =
+ GrowableObjectArray::Handle(zone,
+ thread->isolate()
+ ->object_store()
+ ->pending_unevaluated_const_fields());
+
if (enum_cls.kernel_offset() > 0) {
Error& error = Error::Handle(zone);
for (intptr_t i = 0; i < fields.Length(); i++) {
@@ -1234,12 +1240,19 @@
continue;
}
// The eager evaluation of the enum values is required for hot-reload (see
- // commit e3ecc87).
+ // commit e3ecc87). However, while busy loading the constant table, we
+ // need to postpone this evaluation until table is done.
if (!FLAG_precompiled_mode) {
if (field.IsUninitialized()) {
- error = field.EvaluateInitializer();
- if (!error.IsNull()) {
- ReportError(error);
+ if (pending_unevaluated_const_fields.IsNull()) {
+ // Evaluate right away.
+ error = field.EvaluateInitializer();
+ if (!error.IsNull()) {
+ ReportError(error);
+ }
+ } else {
+ // Postpone evaluation until we have a constant table.
+ pending_unevaluated_const_fields.Add(field);
}
}
}
@@ -1387,52 +1400,6 @@
Error& error = Error::Handle(zone);
TypeParameter& type_param = TypeParameter::Handle(zone);
- // First verify field offsets of all the TypedDataView classes.
- for (intptr_t cid = kTypedDataInt8ArrayViewCid;
- cid <= kTypedDataFloat32x4ArrayViewCid; cid++) {
- cls = class_table.At(cid); // Get the TypedDataView class.
- error = cls.EnsureIsFinalized(thread);
- ASSERT(error.IsNull());
- cls = cls.SuperClass(); // Get it's super class '_TypedListView'.
- cls = cls.SuperClass();
- fields_array ^= cls.fields();
- ASSERT(fields_array.Length() == TypedDataView::NumberOfFields());
- field ^= fields_array.At(0);
- ASSERT(field.Offset() == TypedDataView::data_offset());
- name ^= field.name();
- expected_name ^= String::New("_typedData");
- ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
- field ^= fields_array.At(1);
- ASSERT(field.Offset() == TypedDataView::offset_in_bytes_offset());
- name ^= field.name();
- ASSERT(name.Equals("offsetInBytes"));
- field ^= fields_array.At(2);
- ASSERT(field.Offset() == TypedDataView::length_offset());
- name ^= field.name();
- ASSERT(name.Equals("length"));
- }
-
- // Now verify field offsets of '_ByteDataView' class.
- cls = class_table.At(kByteDataViewCid);
- error = cls.EnsureIsFinalized(thread);
- ASSERT(error.IsNull());
- fields_array ^= cls.fields();
- ASSERT(fields_array.Length() == TypedDataView::NumberOfFields());
- field ^= fields_array.At(0);
- ASSERT(field.Offset() == TypedDataView::data_offset());
- name ^= field.name();
- expected_name ^= String::New("_typedData");
- ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
- field ^= fields_array.At(1);
- ASSERT(field.Offset() == TypedDataView::offset_in_bytes_offset());
- name ^= field.name();
- expected_name ^= String::New("_offset");
- ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
- field ^= fields_array.At(2);
- ASSERT(field.Offset() == TypedDataView::length_offset());
- name ^= field.name();
- ASSERT(name.Equals("length"));
-
// Now verify field offsets of '_ByteBuffer' class.
cls = class_table.At(kByteBufferCid);
error = cls.EnsureIsFinalized(thread);
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index ddbd7a0..22cf733 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -66,6 +66,7 @@
V(Float64x2) \
V(TypedData) \
V(ExternalTypedData) \
+ V(TypedDataView) \
V(Pointer) \
V(DynamicLibrary) \
V(Capability) \
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 97e81e1..972d93e 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -3372,7 +3372,8 @@
Deserializer::InitializeHeader(
data, cid_, TypedData::InstanceSize(length_in_bytes), is_canonical);
data->ptr()->length_ = Smi::New(length);
- uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
+ data->ResetData();
+ uint8_t* cdata = data->ptr()->data();
d->ReadBytes(cdata, length_in_bytes);
}
}
@@ -4251,7 +4252,10 @@
ASSERT(code != Code::null());
const intptr_t offset = image_writer_->GetTextOffsetFor(instr, code);
- ASSERT(offset != 0);
+ if (offset == 0) {
+ // Code should have been removed by DropCodeWithoutReusableInstructions.
+ UnexpectedObject(code, "Expected instructions to reuse");
+ }
Write<int32_t>(offset);
// If offset < 0, it's pointing to a shared instruction. We don't profile
diff --git a/runtime/vm/code_patcher.cc b/runtime/vm/code_patcher.cc
index 4926926..7168231 100644
--- a/runtime/vm/code_patcher.cc
+++ b/runtime/vm/code_patcher.cc
@@ -12,6 +12,13 @@
DEFINE_FLAG(bool, write_protect_code, true, "Write protect jitted code");
+#if defined(DUAL_MAPPING_SUPPORTED)
+DEFINE_FLAG(bool, dual_map_code, true, "Dual map jitted code, RW and RX");
+#else
+DEFINE_FLAG(bool, dual_map_code, false, "Dual map jitted code, RW and RX");
+#endif // defined(DUAL_MAPPING_SUPPORTED)
+
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
WritableInstructionsScope::WritableInstructionsScope(uword address,
intptr_t size)
: address_(address), size_(size) {
@@ -27,6 +34,7 @@
VirtualMemory::kReadExecute);
}
}
+#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
bool MatchesPattern(uword end, const int16_t* pattern, intptr_t size) {
// When breaking within generated code in GDB, it may overwrite individual
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h
index 6aa62af..239a69d 100644
--- a/runtime/vm/code_patcher.h
+++ b/runtime/vm/code_patcher.h
@@ -19,10 +19,12 @@
class RawFunction;
class RawObject;
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
// Stack-allocated class to create a scope where the specified region
// [address, address + size] has write access enabled. This is used
// when patching generated code. Access is reset to read-execute in
// the destructor of this scope.
+// Dual mapping of instructions pages is not supported on these target arch.
class WritableInstructionsScope : public ValueObject {
public:
WritableInstructionsScope(uword address, intptr_t size);
@@ -32,6 +34,7 @@
const uword address_;
const intptr_t size_;
};
+#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
class CodePatcher : public AllStatic {
public:
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index 4c4db1e..65791e4 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -302,6 +302,11 @@
if (function.is_abstract()) {
return Object::null();
}
+ // Prevent premature code collection due to major GC during startup.
+ const intptr_t kFakeInitialUsage = 32;
+ if (function.usage_counter() < kFakeInitialUsage) {
+ function.set_usage_counter(kFakeInitialUsage);
+ }
return Compiler::CompileFunction(thread_, function);
}
@@ -467,6 +472,7 @@
: thread_(thread),
zone_(thread->zone()),
stream_(nullptr),
+ cid_map_(nullptr),
uri_(String::Handle(zone_)),
lib_(Library::Handle(zone_)),
cls_name_(String::Handle(zone_)),
@@ -485,6 +491,10 @@
GrowableObjectArray::Handle(zone_, GrowableObjectArray::New())),
error_(Error::Handle(zone_)) {}
+TypeFeedbackLoader::~TypeFeedbackLoader() {
+ delete[] cid_map_;
+}
+
RawObject* TypeFeedbackLoader::LoadFeedback(ReadStream* stream) {
stream_ = stream;
diff --git a/runtime/vm/compilation_trace.h b/runtime/vm/compilation_trace.h
index 106dbbe..699f08c 100644
--- a/runtime/vm/compilation_trace.h
+++ b/runtime/vm/compilation_trace.h
@@ -85,6 +85,7 @@
class TypeFeedbackLoader : public ValueObject {
public:
explicit TypeFeedbackLoader(Thread* thread);
+ ~TypeFeedbackLoader();
RawObject* LoadFeedback(ReadStream* stream);
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index c00607e..cf5264e 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -165,6 +165,8 @@
__ LoadImmediate(R8, 0); \
__ mov(R9, Operand(R8)); \
__ AddImmediate(R3, R0, target::TypedData::InstanceSize() - 1); \
+ __ StoreIntoObjectNoBarrier( \
+ R0, FieldAddress(R0, target::TypedData::data_offset()), R3); \
Label init_loop; \
__ Bind(&init_loop); \
__ AddImmediate(R3, 2 * target::kWordSize); \
@@ -693,13 +695,12 @@
// R4 = n ~/ _DIGIT_BITS
__ Asr(R4, R3, Operand(5));
// R8 = &x_digits[0]
- __ add(R8, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R8, FieldAddress(R1, target::TypedData::data_offset()));
// NOTFP = &x_digits[x_used]
__ add(NOTFP, R8, Operand(R0, LSL, 1));
// R6 = &r_digits[1]
- __ add(R6, R2,
- Operand(target::TypedData::data_offset() - kHeapObjectTag +
- kBytesPerBigIntDigit));
+ __ ldr(R6, FieldAddress(R2, target::TypedData::data_offset()));
+ __ add(R6, R6, Operand(kBytesPerBigIntDigit));
// R6 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1]
__ add(R4, R4, Operand(R0, ASR, 1));
__ add(R6, R6, Operand(R4, LSL, 2));
@@ -733,9 +734,9 @@
// R4 = n ~/ _DIGIT_BITS
__ Asr(R4, R3, Operand(5));
// R6 = &r_digits[0]
- __ add(R6, R2, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R6, FieldAddress(R2, target::TypedData::data_offset()));
// NOTFP = &x_digits[n ~/ _DIGIT_BITS]
- __ add(NOTFP, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(NOTFP, FieldAddress(R1, target::TypedData::data_offset()));
__ add(NOTFP, NOTFP, Operand(R4, LSL, 2));
// R8 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1]
__ add(R4, R4, Operand(1));
@@ -773,17 +774,17 @@
// R0 = used, R1 = digits
__ ldrd(R0, R1, SP, 3 * target::kWordSize);
// R1 = &digits[0]
- __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
// R2 = a_used, R3 = a_digits
__ ldrd(R2, R3, SP, 1 * target::kWordSize);
// R3 = &a_digits[0]
- __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
// R8 = r_digits
__ ldr(R8, Address(SP, 0 * target::kWordSize));
// R8 = &r_digits[0]
- __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R8, FieldAddress(R8, target::TypedData::data_offset()));
// NOTFP = &digits[a_used >> 1], a_used is Smi.
__ add(NOTFP, R1, Operand(R2, LSL, 1));
@@ -833,17 +834,17 @@
// R0 = used, R1 = digits
__ ldrd(R0, R1, SP, 3 * target::kWordSize);
// R1 = &digits[0]
- __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
// R2 = a_used, R3 = a_digits
__ ldrd(R2, R3, SP, 1 * target::kWordSize);
// R3 = &a_digits[0]
- __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
// R8 = r_digits
__ ldr(R8, Address(SP, 0 * target::kWordSize));
// R8 = &r_digits[0]
- __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R8, FieldAddress(R8, target::TypedData::data_offset()));
// NOTFP = &digits[a_used >> 1], a_used is Smi.
__ add(NOTFP, R1, Operand(R2, LSL, 1));
@@ -912,8 +913,8 @@
Label done;
// R3 = x, no_op if x == 0
__ ldrd(R0, R1, SP, 5 * target::kWordSize); // R0 = xi as Smi, R1 = x_digits.
- __ add(R1, R1, Operand(R0, LSL, 1));
__ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
+ __ ldr(R3, Address(R3, R0, LSL, 1));
__ tst(R3, Operand(R3));
__ b(&done, EQ);
@@ -924,13 +925,13 @@
// R4 = mip = &m_digits[i >> 1]
__ ldrd(R0, R1, SP, 3 * target::kWordSize); // R0 = i as Smi, R1 = m_digits.
- __ add(R1, R1, Operand(R0, LSL, 1));
- __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R4, FieldAddress(R1, target::TypedData::data_offset()));
+ __ add(R4, R4, Operand(R0, LSL, 1));
// R9 = ajp = &a_digits[j >> 1]
__ ldrd(R0, R1, SP, 1 * target::kWordSize); // R0 = j as Smi, R1 = a_digits.
- __ add(R1, R1, Operand(R0, LSL, 1));
- __ add(R9, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R9, FieldAddress(R1, target::TypedData::data_offset()));
+ __ add(R9, R9, Operand(R0, LSL, 1));
// R1 = c = 0
__ mov(R1, Operand(0));
@@ -1012,8 +1013,8 @@
// R4 = xip = &x_digits[i >> 1]
__ ldrd(R2, R3, SP, 2 * target::kWordSize); // R2 = i as Smi, R3 = x_digits
- __ add(R3, R3, Operand(R2, LSL, 1));
- __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R4, FieldAddress(R3, target::TypedData::data_offset()));
+ __ add(R4, R4, Operand(R2, LSL, 1));
// R3 = x = *xip++, return if x == 0
Label x_zero;
@@ -1023,8 +1024,8 @@
// NOTFP = ajp = &a_digits[i]
__ ldr(R1, Address(SP, 1 * target::kWordSize)); // a_digits
- __ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi.
- __ add(NOTFP, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(NOTFP, FieldAddress(R1, target::TypedData::data_offset()));
+ __ add(NOTFP, NOTFP, Operand(R2, LSL, 2)); // j == 2*i, i is Smi.
// R8:R0 = t = x*x + *ajp
__ ldr(R0, Address(NOTFP, 0));
@@ -1112,24 +1113,24 @@
// return 1;
// }
- // R4 = args
+ // R4 = &args[0]
__ ldr(R4, Address(SP, 2 * target::kWordSize)); // args
+ __ ldr(R4, FieldAddress(R4, target::TypedData::data_offset()));
// R3 = rho = args[2]
- __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
- 2 * kBytesPerBigIntDigit));
+ __ ldr(R3, Address(R4, 2 * kBytesPerBigIntDigit));
// R2 = digits[i >> 1]
__ ldrd(R0, R1, SP, 0 * target::kWordSize); // R0 = i as Smi, R1 = digits
- __ add(R1, R1, Operand(R0, LSL, 1));
__ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
+ __ add(R2, R2, Operand(R0, LSL, 1));
+ __ ldr(R2, Address(R2));
// R1:R0 = t = rho*d
__ umull(R0, R1, R2, R3);
// args[4] = t mod DIGIT_BASE = low32(t)
- __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
- 4 * kBytesPerBigIntDigit));
+ __ str(R0, Address(R4, 4 * kBytesPerBigIntDigit));
__ mov(R0, Operand(target::ToRawSmi(1))); // One digit processed.
__ Ret();
@@ -1495,6 +1496,7 @@
// Field '_state'.
__ ldr(R1, FieldAddress(R0, LookupFieldOffsetInBytes(state_field)));
// Addresses of _state[0] and _state[1].
+ __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
const int64_t disp_0 =
target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
@@ -1502,13 +1504,13 @@
disp_0 + target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
__ LoadImmediate(R0, a_int32_value);
- __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag);
- __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag);
+ __ LoadFromOffset(kWord, R2, R1, disp_0);
+ __ LoadFromOffset(kWord, R3, R1, disp_1);
__ mov(R8, Operand(0)); // Zero extend unsigned _state[kSTATE_HI].
// Unsigned 32-bit multiply and 64-bit accumulate into R8:R3.
__ umlal(R3, R8, R0, R2); // R8:R3 <- R8:R3 + R0 * R2.
- __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag);
- __ StoreToOffset(kWord, R8, R1, disp_1 - kHeapObjectTag);
+ __ StoreToOffset(kWord, R3, R1, disp_0);
+ __ StoreToOffset(kWord, R8, R1, disp_1);
ASSERT(target::ToRawSmi(0) == 0);
__ eor(R0, R0, Operand(R0));
__ Ret();
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 6ba42cd..0153c00 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -177,6 +177,8 @@
/* data area to be initialized. */ \
__ mov(R3, ZR); \
__ AddImmediate(R2, R0, target::TypedData::InstanceSize() - 1); \
+ __ StoreIntoObjectNoBarrier( \
+ R0, FieldAddress(R0, target::TypedData::data_offset()), R2); \
Label init_loop, done; \
__ Bind(&init_loop); \
__ cmp(R2, Operand(R1)); \
@@ -601,13 +603,12 @@
// R0 = n ~/ (2*_DIGIT_BITS)
__ AsrImmediate(R0, R5, 6);
// R6 = &x_digits[0]
- __ add(R6, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R6, FieldAddress(R3, target::TypedData::data_offset()));
// R7 = &x_digits[2*R2]
__ add(R7, R6, Operand(R2, LSL, 3));
// R8 = &r_digits[2*1]
- __ add(R8, R4,
- Operand(target::TypedData::data_offset() - kHeapObjectTag +
- 2 * kBytesPerBigIntDigit));
+ __ ldr(R8, FieldAddress(R4, target::TypedData::data_offset()));
+ __ add(R8, R8, Operand(2 * kBytesPerBigIntDigit));
// R8 = &r_digits[2*(R2 + n ~/ (2*_DIGIT_BITS) + 1)]
__ add(R0, R0, Operand(R2));
__ add(R8, R8, Operand(R0, LSL, 3));
@@ -645,9 +646,9 @@
// R0 = n ~/ (2*_DIGIT_BITS)
__ AsrImmediate(R0, R5, 6);
// R8 = &r_digits[0]
- __ add(R8, R4, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R8, FieldAddress(R4, target::TypedData::data_offset()));
// R7 = &x_digits[2*(n ~/ (2*_DIGIT_BITS))]
- __ add(R7, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R7, FieldAddress(R3, target::TypedData::data_offset()));
__ add(R7, R7, Operand(R0, LSL, 3));
// R6 = &r_digits[2*(R2 - n ~/ (2*_DIGIT_BITS) - 1)]
__ add(R0, R0, Operand(1));
@@ -689,19 +690,19 @@
__ add(R2, R2, Operand(2)); // used > 0, Smi. R2 = used + 1, round up.
__ add(R2, ZR, Operand(R2, ASR, 2)); // R2 = num of digit pairs to process.
// R3 = &digits[0]
- __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
// R4 = a_used, R5 = a_digits
__ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
__ add(R4, R4, Operand(2)); // a_used > 0, Smi. R4 = a_used + 1, round up.
__ add(R4, ZR, Operand(R4, ASR, 2)); // R4 = num of digit pairs to process.
// R5 = &a_digits[0]
- __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R5, FieldAddress(R5, target::TypedData::data_offset()));
// R6 = r_digits
__ ldr(R6, Address(SP, 0 * target::kWordSize));
// R6 = &r_digits[0]
- __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R6, FieldAddress(R6, target::TypedData::data_offset()));
// R7 = &digits[a_used rounded up to even number].
__ add(R7, R3, Operand(R4, LSL, 3));
@@ -755,19 +756,19 @@
__ add(R2, R2, Operand(2)); // used > 0, Smi. R2 = used + 1, round up.
__ add(R2, ZR, Operand(R2, ASR, 2)); // R2 = num of digit pairs to process.
// R3 = &digits[0]
- __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
// R4 = a_used, R5 = a_digits
__ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
__ add(R4, R4, Operand(2)); // a_used > 0, Smi. R4 = a_used + 1, round up.
__ add(R4, ZR, Operand(R4, ASR, 2)); // R4 = num of digit pairs to process.
// R5 = &a_digits[0]
- __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R5, FieldAddress(R5, target::TypedData::data_offset()));
// R6 = r_digits
__ ldr(R6, Address(SP, 0 * target::kWordSize));
// R6 = &r_digits[0]
- __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R6, FieldAddress(R6, target::TypedData::data_offset()));
// R7 = &digits[a_used rounded up to even number].
__ add(R7, R3, Operand(R4, LSL, 3));
@@ -838,8 +839,9 @@
// R3 = x, no_op if x == 0
// R0 = xi as Smi, R1 = x_digits.
__ ldp(R0, R1, Address(SP, 5 * target::kWordSize, Address::PairOffset));
- __ add(R1, R1, Operand(R0, LSL, 1));
__ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
+ __ add(R3, R3, Operand(R0, LSL, 1));
+ __ ldr(R3, Address(R3, 0));
__ tst(R3, Operand(R3));
__ b(&done, EQ);
@@ -852,14 +854,14 @@
// R4 = mip = &m_digits[i >> 1]
// R0 = i as Smi, R1 = m_digits.
__ ldp(R0, R1, Address(SP, 3 * target::kWordSize, Address::PairOffset));
- __ add(R1, R1, Operand(R0, LSL, 1));
- __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R4, FieldAddress(R1, target::TypedData::data_offset()));
+ __ add(R4, R4, Operand(R0, LSL, 1));
// R5 = ajp = &a_digits[j >> 1]
// R0 = j as Smi, R1 = a_digits.
__ ldp(R0, R1, Address(SP, 1 * target::kWordSize, Address::PairOffset));
- __ add(R1, R1, Operand(R0, LSL, 1));
- __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R5, FieldAddress(R1, target::TypedData::data_offset()));
+ __ add(R5, R5, Operand(R0, LSL, 1));
// R1 = c = 0
__ mov(R1, ZR);
@@ -946,8 +948,8 @@
// R4 = xip = &x_digits[i >> 1]
// R2 = i as Smi, R3 = x_digits
__ ldp(R2, R3, Address(SP, 2 * target::kWordSize, Address::PairOffset));
- __ add(R3, R3, Operand(R2, LSL, 1));
- __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R4, FieldAddress(R3, target::TypedData::data_offset()));
+ __ add(R4, R4, Operand(R2, LSL, 1));
// R3 = x = *xip++, return if x == 0
Label x_zero;
@@ -957,8 +959,8 @@
// R5 = ajp = &a_digits[i]
__ ldr(R1, Address(SP, 1 * target::kWordSize)); // a_digits
- __ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi.
- __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ ldr(R5, FieldAddress(R1, target::TypedData::data_offset()));
+ __ add(R5, R5, Operand(R2, LSL, 2)); // j == 2*i, i is Smi.
// R6:R1 = t = x*x + *ajp
__ ldr(R0, Address(R5, 0));
@@ -1076,18 +1078,19 @@
// return 2;
// }
- // R4 = args
+ // R4 = &args[0]
__ ldr(R4, Address(SP, 2 * target::kWordSize)); // args
+ __ ldr(R4, FieldAddress(R4, target::TypedData::data_offset()));
// R3 = yt = args[0..1]
- __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset()));
+ __ ldr(R3, Address(R4, 0));
// R2 = dh = digits[(i >> 1) - 1 .. i >> 1]
// R0 = i as Smi, R1 = digits
__ ldp(R0, R1, Address(SP, 0 * target::kWordSize, Address::PairOffset));
+ __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
__ add(R1, R1, Operand(R0, LSL, 1));
- __ ldr(R2, FieldAddress(
- R1, target::TypedData::data_offset() - kBytesPerBigIntDigit));
+ __ ldr(R2, Address(R1, -kBytesPerBigIntDigit));
// R0 = qd = (DIGIT_MASK << 32) | DIGIT_MASK = -1
__ movn(R0, Immediate(0), 0);
@@ -1098,8 +1101,7 @@
__ b(&return_qd, EQ);
// R1 = dl = digits[(i >> 1) - 3 .. (i >> 1) - 2]
- __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset() -
- 3 * kBytesPerBigIntDigit));
+ __ ldr(R1, Address(R1, -3 * kBytesPerBigIntDigit));
// R5 = yth = yt >> 32
__ orr(R5, ZR, Operand(R3, LSR, 32));
@@ -1203,8 +1205,7 @@
__ Bind(&return_qd);
// args[2..3] = qd
- __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
- 2 * kBytesPerBigIntDigit));
+ __ str(R0, Address(R4, 2 * kBytesPerBigIntDigit));
__ LoadImmediate(R0, target::ToRawSmi(2)); // Two digits processed.
__ ret();
@@ -1221,25 +1222,25 @@
// return 2;
// }
- // R4 = args
+ // R4 = &args[0]
__ ldr(R4, Address(SP, 2 * target::kWordSize)); // args
+ __ ldr(R4, FieldAddress(R4, target::TypedData::data_offset()));
// R3 = rho = args[2..3]
- __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
- 2 * kBytesPerBigIntDigit));
+ __ ldr(R3, Address(R4, 2 * kBytesPerBigIntDigit));
// R2 = digits[i >> 1 .. (i >> 1) + 1]
// R0 = i as Smi, R1 = digits
__ ldp(R0, R1, Address(SP, 0 * target::kWordSize, Address::PairOffset));
- __ add(R1, R1, Operand(R0, LSL, 1));
__ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
+ __ add(R2, R2, Operand(R0, LSL, 1));
+ __ ldr(R2, Address(R2, 0));
// R0 = rho*d mod DIGIT_BASE
__ mul(R0, R2, R3); // R0 = low64(R2*R3).
// args[4 .. 5] = R0
- __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
- 4 * kBytesPerBigIntDigit));
+ __ str(R0, Address(R4, 4 * kBytesPerBigIntDigit));
__ LoadImmediate(R0, target::ToRawSmi(2)); // Two digits processed.
__ ret();
@@ -1557,10 +1558,10 @@
// Field '_state'.
__ ldr(R1, FieldAddress(R0, LookupFieldOffsetInBytes(state_field)));
- // Addresses of _state[0].
+ // Address of _state[0].
+ __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
const int64_t disp =
- target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid) -
- kHeapObjectTag;
+ target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
__ LoadImmediate(R0, a_int_value);
__ LoadFromOffset(R2, R1, disp);
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index 392d129..88c48f9 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -167,6 +167,8 @@
/* data area to be initialized. */ \
__ xorl(ECX, ECX); /* Zero. */ \
__ leal(EDI, FieldAddress(EAX, target::TypedData::InstanceSize())); \
+ __ StoreIntoObjectNoBarrier( \
+ EAX, FieldAddress(EAX, target::TypedData::data_offset()), EDI); \
Label done, init_loop; \
__ Bind(&init_loop); \
__ cmpl(EDI, EBX); \
@@ -713,14 +715,14 @@
__ movl(EBX, Address(ESP, 2 * target::kWordSize)); // r_digits
__ movl(ESI, ECX);
__ sarl(ESI, Immediate(5)); // ESI = n ~/ _DIGIT_BITS.
- __ leal(EBX,
- FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
+ __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+ __ leal(EBX, Address(EBX, ESI, TIMES_4, 0));
__ movl(ESI, Address(ESP, 4 * target::kWordSize)); // x_used > 0, Smi.
__ SmiUntag(ESI);
__ decl(ESI);
__ xorl(EAX, EAX); // EAX = 0.
- __ movl(EDX,
- FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
+ __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+ __ movl(EDX, Address(EDI, ESI, TIMES_4, 0));
__ shldl(EAX, EDX, ECX);
__ movl(Address(EBX, ESI, TIMES_4, kBytesPerBigIntDigit), EAX);
Label last;
@@ -729,9 +731,7 @@
Label loop;
__ Bind(&loop);
__ movl(EAX, EDX);
- __ movl(EDX, FieldAddress(
- EDI, ESI, TIMES_4,
- target::TypedData::data_offset() - kBytesPerBigIntDigit));
+ __ movl(EDX, Address(EDI, ESI, TIMES_4, -kBytesPerBigIntDigit));
__ shldl(EAX, EDX, ECX);
__ movl(Address(EBX, ESI, TIMES_4, 0), EAX);
__ decl(ESI);
@@ -764,12 +764,12 @@
__ SmiUntag(ESI);
__ decl(ESI);
// EDI = &x_digits[x_used - 1].
- __ leal(EDI,
- FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
+ __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+ __ leal(EDI, Address(EDI, ESI, TIMES_4, 0));
__ subl(ESI, EDX);
// EBX = &r_digits[x_used - 1 - (n ~/ 32)].
- __ leal(EBX,
- FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
+ __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+ __ leal(EBX, Address(EBX, ESI, TIMES_4, 0));
__ negl(ESI);
__ movl(EDX, Address(EDI, ESI, TIMES_4, 0));
Label last;
@@ -811,6 +811,10 @@
__ SmiUntag(ECX); // a_used > 0.
__ movl(EBX, Address(ESP, 2 * target::kWordSize)); // r_digits
+ __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+ __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
+ __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+
// Precompute 'used - a_used' now so that carry flag is not lost later.
__ subl(EAX, ECX);
__ incl(EAX); // To account for the extra test between loops.
@@ -820,12 +824,9 @@
Label add_loop;
__ Bind(&add_loop);
// Loop a_used times, ECX = a_used, ECX > 0.
- __ movl(EAX,
- FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
- __ adcl(EAX,
- FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
- EAX);
+ __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
+ __ adcl(EAX, Address(ESI, EDX, TIMES_4, 0));
+ __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
__ incl(EDX); // Does not affect carry flag.
__ decl(ECX); // Does not affect carry flag.
__ j(NOT_ZERO, &add_loop, Assembler::kNearJump);
@@ -838,11 +839,9 @@
Label carry_loop;
__ Bind(&carry_loop);
// Loop used - a_used times, ECX = used - a_used, ECX > 0.
- __ movl(EAX,
- FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+ __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
__ adcl(EAX, Immediate(0));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
- EAX);
+ __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
__ incl(EDX); // Does not affect carry flag.
__ decl(ECX); // Does not affect carry flag.
__ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -850,8 +849,7 @@
__ Bind(&last_carry);
__ movl(EAX, Immediate(0));
__ adcl(EAX, Immediate(0));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
- EAX);
+ __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
// Restore THR and return.
__ popl(THR);
@@ -877,6 +875,10 @@
__ SmiUntag(ECX); // a_used > 0.
__ movl(EBX, Address(ESP, 2 * target::kWordSize)); // r_digits
+ __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+ __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
+ __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+
// Precompute 'used - a_used' now so that carry flag is not lost later.
__ subl(EAX, ECX);
__ incl(EAX); // To account for the extra test between loops.
@@ -886,12 +888,9 @@
Label sub_loop;
__ Bind(&sub_loop);
// Loop a_used times, ECX = a_used, ECX > 0.
- __ movl(EAX,
- FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
- __ sbbl(EAX,
- FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
- EAX);
+ __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
+ __ sbbl(EAX, Address(ESI, EDX, TIMES_4, 0));
+ __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
__ incl(EDX); // Does not affect carry flag.
__ decl(ECX); // Does not affect carry flag.
__ j(NOT_ZERO, &sub_loop, Assembler::kNearJump);
@@ -904,11 +903,9 @@
Label carry_loop;
__ Bind(&carry_loop);
// Loop used - a_used times, ECX = used - a_used, ECX > 0.
- __ movl(EAX,
- FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+ __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
__ sbbl(EAX, Immediate(0));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
- EAX);
+ __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
__ incl(EDX); // Does not affect carry flag.
__ decl(ECX); // Does not affect carry flag.
__ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -953,8 +950,8 @@
// EBX = x, no_op if x == 0
__ movl(ECX, Address(ESP, 7 * target::kWordSize)); // x_digits
__ movl(EAX, Address(ESP, 6 * target::kWordSize)); // xi is Smi
- __ movl(EBX,
- FieldAddress(ECX, EAX, TIMES_2, target::TypedData::data_offset()));
+ __ movl(EBX, FieldAddress(ECX, target::TypedData::data_offset()));
+ __ movl(EBX, Address(EBX, EAX, TIMES_2, 0));
__ testl(EBX, EBX);
__ j(ZERO, &no_op, Assembler::kNearJump);
@@ -970,14 +967,14 @@
// EDI = mip = &m_digits[i >> 1]
__ movl(EDI, Address(ESP, 6 * target::kWordSize)); // m_digits
__ movl(EAX, Address(ESP, 5 * target::kWordSize)); // i is Smi
- __ leal(EDI,
- FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
+ __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+ __ leal(EDI, Address(EDI, EAX, TIMES_2, 0));
// ESI = ajp = &a_digits[j >> 1]
__ movl(ESI, Address(ESP, 4 * target::kWordSize)); // a_digits
__ movl(EAX, Address(ESP, 3 * target::kWordSize)); // j is Smi
- __ leal(ESI,
- FieldAddress(ESI, EAX, TIMES_2, target::TypedData::data_offset()));
+ __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
+ __ leal(ESI, Address(ESI, EAX, TIMES_2, 0));
// Save n
__ pushl(EDX);
@@ -1074,8 +1071,8 @@
// EDI = xip = &x_digits[i >> 1]
__ movl(EDI, Address(ESP, 4 * target::kWordSize)); // x_digits
__ movl(EAX, Address(ESP, 3 * target::kWordSize)); // i is Smi
- __ leal(EDI,
- FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
+ __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+ __ leal(EDI, Address(EDI, EAX, TIMES_2, 0));
// EBX = x = *xip++, return if x == 0
Label x_zero;
@@ -1090,8 +1087,8 @@
// ESI = ajp = &a_digits[i]
__ movl(ESI, Address(ESP, 3 * target::kWordSize)); // a_digits
- __ leal(ESI,
- FieldAddress(ESI, EAX, TIMES_4, target::TypedData::data_offset()));
+ __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
+ __ leal(ESI, Address(ESI, EAX, TIMES_4, 0));
// EDX:EAX = t = x*x + *ajp
__ movl(EAX, EBX);
@@ -1196,18 +1193,18 @@
// return 1;
// }
- // EDI = args
+ // EDI = &args[0]
__ movl(EDI, Address(ESP, 3 * target::kWordSize)); // args
+ __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
// ECX = yt = args[1]
- __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
- kBytesPerBigIntDigit));
+ __ movl(ECX, Address(EDI, kBytesPerBigIntDigit));
// EBX = dp = &digits[i >> 1]
__ movl(EBX, Address(ESP, 2 * target::kWordSize)); // digits
__ movl(EAX, Address(ESP, 1 * target::kWordSize)); // i is Smi
- __ leal(EBX,
- FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
+ __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+ __ leal(EBX, Address(EBX, EAX, TIMES_2, 0));
// EDX = dh = dp[0]
__ movl(EDX, Address(EBX, 0));
@@ -1228,9 +1225,7 @@
__ Bind(&return_qd);
// args[2] = qd
- __ movl(FieldAddress(
- EDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
- EAX);
+ __ movl(Address(EDI, 2 * kBytesPerBigIntDigit), EAX);
__ movl(EAX, Immediate(target::ToRawSmi(1))); // One digit processed.
__ ret();
@@ -1247,26 +1242,24 @@
// return 1;
// }
- // EDI = args
+ // EDI = &args[0]
__ movl(EDI, Address(ESP, 3 * target::kWordSize)); // args
+ __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
// ECX = rho = args[2]
- __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
- 2 * kBytesPerBigIntDigit));
+ __ movl(ECX, Address(EDI, 2 * kBytesPerBigIntDigit));
// EAX = digits[i >> 1]
__ movl(EBX, Address(ESP, 2 * target::kWordSize)); // digits
__ movl(EAX, Address(ESP, 1 * target::kWordSize)); // i is Smi
- __ movl(EAX,
- FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
+ __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+ __ movl(EAX, Address(EBX, EAX, TIMES_2, 0));
// EDX:EAX = t = rho*d
__ mull(ECX);
// args[4] = t mod DIGIT_BASE = low32(t)
- __ movl(FieldAddress(
- EDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
- EAX);
+ __ movl(Address(EDI, 4 * kBytesPerBigIntDigit), EAX);
__ movl(EAX, Immediate(target::ToRawSmi(1))); // One digit processed.
__ ret();
@@ -1596,12 +1589,13 @@
// Field '_state'.
__ movl(EBX, FieldAddress(EAX, LookupFieldOffsetInBytes(state_field)));
// Addresses of _state[0] and _state[1].
+ __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
const intptr_t scale =
target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
const intptr_t offset =
target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
- Address addr_0 = FieldAddress(EBX, 0 * scale + offset);
- Address addr_1 = FieldAddress(EBX, 1 * scale + offset);
+ Address addr_0 = Address(EBX, 0 * scale + offset);
+ Address addr_1 = Address(EBX, 1 * scale + offset);
__ movl(EAX, Immediate(a_int32_value));
// 64-bit multiply EAX * value -> EDX:EAX.
__ mull(addr_0);
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 1c34df5..1532070 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -169,6 +169,8 @@
/* data area to be initialized. */ \
__ xorq(RBX, RBX); /* Zero. */ \
__ leaq(RDI, FieldAddress(RAX, target::TypedData::InstanceSize())); \
+ __ StoreIntoObjectNoBarrier( \
+ RAX, FieldAddress(RAX, target::TypedData::data_offset()), RDI); \
Label done, init_loop; \
__ Bind(&init_loop); \
__ cmpq(RDI, RCX); \
@@ -684,11 +686,11 @@
__ movq(RBX, Address(RSP, 1 * target::kWordSize)); // r_digits
__ movq(RSI, RCX);
__ sarq(RSI, Immediate(6)); // RSI = n ~/ (2*_DIGIT_BITS).
- __ leaq(RBX,
- FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
+ __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+ __ leaq(RBX, Address(RBX, RSI, TIMES_8, 0));
__ xorq(RAX, RAX); // RAX = 0.
- __ movq(RDX,
- FieldAddress(RDI, R8, TIMES_8, target::TypedData::data_offset()));
+ __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+ __ movq(RDX, Address(RDI, R8, TIMES_8, 0));
__ shldq(RAX, RDX, RCX);
__ movq(Address(RBX, R8, TIMES_8, 2 * kBytesPerBigIntDigit), RAX);
Label last;
@@ -697,9 +699,7 @@
Label loop;
__ Bind(&loop);
__ movq(RAX, RDX);
- __ movq(RDX, FieldAddress(RDI, R8, TIMES_8,
- target::TypedData::data_offset() -
- 2 * kBytesPerBigIntDigit));
+ __ movq(RDX, Address(RDI, R8, TIMES_8, -2 * kBytesPerBigIntDigit));
__ shldq(RAX, RDX, RCX);
__ movq(Address(RBX, R8, TIMES_8, 0), RAX);
__ decq(R8);
@@ -724,11 +724,11 @@
__ movq(RSI, Address(RSP, 3 * target::kWordSize)); // x_used is Smi
__ subq(RSI, Immediate(2)); // x_used > 0, Smi. RSI = x_used - 1, round up.
__ sarq(RSI, Immediate(2));
- __ leaq(RDI,
- FieldAddress(RDI, RSI, TIMES_8, target::TypedData::data_offset()));
+ __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+ __ leaq(RDI, Address(RDI, RSI, TIMES_8, 0));
__ subq(RSI, RDX); // RSI + 1 = number of digit pairs to read.
- __ leaq(RBX,
- FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
+ __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+ __ leaq(RBX, Address(RBX, RSI, TIMES_8, 0));
__ negq(RSI);
__ movq(RDX, Address(RDI, RSI, TIMES_8, 0));
Label last;
@@ -765,6 +765,10 @@
__ sarq(RCX, Immediate(2)); // R8 = number of digit pairs to process.
__ movq(RBX, Address(RSP, 1 * target::kWordSize)); // r_digits
+ __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+ __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+ __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
+
// Precompute 'used - a_used' now so that carry flag is not lost later.
__ subq(R8, RCX);
__ incq(R8); // To account for the extra test between loops.
@@ -773,12 +777,9 @@
Label add_loop;
__ Bind(&add_loop);
// Loop (a_used+1)/2 times, RCX > 0.
- __ movq(RAX,
- FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
- __ adcq(RAX,
- FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
- RAX);
+ __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
+ __ adcq(RAX, Address(RSI, RDX, TIMES_8, 0));
+ __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
__ incq(RDX); // Does not affect carry flag.
__ decq(RCX); // Does not affect carry flag.
__ j(NOT_ZERO, &add_loop, Assembler::kNearJump);
@@ -790,11 +791,9 @@
Label carry_loop;
__ Bind(&carry_loop);
// Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
- __ movq(RAX,
- FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+ __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
__ adcq(RAX, Immediate(0));
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
- RAX);
+ __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
__ incq(RDX); // Does not affect carry flag.
__ decq(R8); // Does not affect carry flag.
__ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -802,8 +801,7 @@
__ Bind(&last_carry);
Label done;
__ j(NOT_CARRY, &done);
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
- Immediate(1));
+ __ movq(Address(RBX, RDX, TIMES_8, 0), Immediate(1));
__ Bind(&done);
__ LoadObject(RAX, NullObject());
@@ -826,6 +824,10 @@
__ sarq(RCX, Immediate(2)); // R8 = number of digit pairs to process.
__ movq(RBX, Address(RSP, 1 * target::kWordSize)); // r_digits
+ __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+ __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+ __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
+
// Precompute 'used - a_used' now so that carry flag is not lost later.
__ subq(R8, RCX);
__ incq(R8); // To account for the extra test between loops.
@@ -834,12 +836,9 @@
Label sub_loop;
__ Bind(&sub_loop);
// Loop (a_used+1)/2 times, RCX > 0.
- __ movq(RAX,
- FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
- __ sbbq(RAX,
- FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
- RAX);
+ __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
+ __ sbbq(RAX, Address(RSI, RDX, TIMES_8, 0));
+ __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
__ incq(RDX); // Does not affect carry flag.
__ decq(RCX); // Does not affect carry flag.
__ j(NOT_ZERO, &sub_loop, Assembler::kNearJump);
@@ -851,11 +850,9 @@
Label carry_loop;
__ Bind(&carry_loop);
// Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
- __ movq(RAX,
- FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+ __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
__ sbbq(RAX, Immediate(0));
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
- RAX);
+ __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
__ incq(RDX); // Does not affect carry flag.
__ decq(R8); // Does not affect carry flag.
__ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -899,8 +896,8 @@
// RBX = x, done if x == 0
__ movq(RCX, Address(RSP, 7 * target::kWordSize)); // x_digits
__ movq(RAX, Address(RSP, 6 * target::kWordSize)); // xi is Smi
- __ movq(RBX,
- FieldAddress(RCX, RAX, TIMES_2, target::TypedData::data_offset()));
+ __ movq(RBX, FieldAddress(RCX, target::TypedData::data_offset()));
+ __ movq(RBX, Address(RBX, RAX, TIMES_2, 0));
__ testq(RBX, RBX);
__ j(ZERO, &done, Assembler::kNearJump);
@@ -913,14 +910,14 @@
// RDI = mip = &m_digits[i >> 1]
__ movq(RDI, Address(RSP, 5 * target::kWordSize)); // m_digits
__ movq(RAX, Address(RSP, 4 * target::kWordSize)); // i is Smi
- __ leaq(RDI,
- FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
+ __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+ __ leaq(RDI, Address(RDI, RAX, TIMES_2, 0));
// RSI = ajp = &a_digits[j >> 1]
__ movq(RSI, Address(RSP, 3 * target::kWordSize)); // a_digits
__ movq(RAX, Address(RSP, 2 * target::kWordSize)); // j is Smi
- __ leaq(RSI,
- FieldAddress(RSI, RAX, TIMES_2, target::TypedData::data_offset()));
+ __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
+ __ leaq(RSI, Address(RSI, RAX, TIMES_2, 0));
// RCX = c = 0
__ xorq(RCX, RCX);
@@ -1007,8 +1004,8 @@
// RDI = xip = &x_digits[i >> 1]
__ movq(RDI, Address(RSP, 4 * target::kWordSize)); // x_digits
__ movq(RAX, Address(RSP, 3 * target::kWordSize)); // i is Smi
- __ leaq(RDI,
- FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
+ __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+ __ leaq(RDI, Address(RDI, RAX, TIMES_2, 0));
// RBX = x = *xip++, return if x == 0
Label x_zero;
@@ -1019,8 +1016,8 @@
// RSI = ajp = &a_digits[i]
__ movq(RSI, Address(RSP, 2 * target::kWordSize)); // a_digits
- __ leaq(RSI,
- FieldAddress(RSI, RAX, TIMES_4, target::TypedData::data_offset()));
+ __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
+ __ leaq(RSI, Address(RSI, RAX, TIMES_4, 0));
// RDX:RAX = t = x*x + *ajp
__ movq(RAX, RBX);
@@ -1116,18 +1113,18 @@
// return 2;
// }
- // RDI = args
+ // RDI = &args[0]
__ movq(RDI, Address(RSP, 3 * target::kWordSize)); // args
+ __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
// RCX = yt = args[0..1]
- __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset()));
+ __ movq(RCX, Address(RDI, 0));
// RBX = dp = &digits[(i >> 1) - 1]
__ movq(RBX, Address(RSP, 2 * target::kWordSize)); // digits
__ movq(RAX, Address(RSP, 1 * target::kWordSize)); // i is Smi and odd.
- __ leaq(RBX, FieldAddress(
- RBX, RAX, TIMES_2,
- target::TypedData::data_offset() - kBytesPerBigIntDigit));
+ __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+ __ leaq(RBX, Address(RBX, RAX, TIMES_2, -kBytesPerBigIntDigit));
// RDX = dh = dp[0]
__ movq(RDX, Address(RBX, 0));
@@ -1148,9 +1145,7 @@
__ Bind(&return_qd);
// args[2..3] = qd
- __ movq(FieldAddress(
- RDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
- RAX);
+ __ movq(Address(RDI, 2 * kBytesPerBigIntDigit), RAX);
__ movq(RAX, Immediate(target::ToRawSmi(2))); // Two digits processed.
__ ret();
@@ -1167,26 +1162,24 @@
// return 2;
// }
- // RDI = args
+ // RDI = &args[0]
__ movq(RDI, Address(RSP, 3 * target::kWordSize)); // args
+ __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
// RCX = rho = args[2 .. 3]
- __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset() +
- 2 * kBytesPerBigIntDigit));
+ __ movq(RCX, Address(RDI, 2 * kBytesPerBigIntDigit));
// RAX = digits[i >> 1 .. (i >> 1) + 1]
__ movq(RBX, Address(RSP, 2 * target::kWordSize)); // digits
__ movq(RAX, Address(RSP, 1 * target::kWordSize)); // i is Smi
- __ movq(RAX,
- FieldAddress(RBX, RAX, TIMES_2, target::TypedData::data_offset()));
+ __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+ __ movq(RAX, Address(RBX, RAX, TIMES_2, 0));
// RDX:RAX = t = rho*d
__ mulq(RCX);
// args[4 .. 5] = t mod DIGIT_BASE^2 = low64(t)
- __ movq(FieldAddress(
- RDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
- RAX);
+ __ movq(Address(RDI, 4 * kBytesPerBigIntDigit), RAX);
__ movq(RAX, Immediate(target::ToRawSmi(2))); // Two digits processed.
__ ret();
@@ -1503,12 +1496,13 @@
// Field '_state'.
__ movq(RBX, FieldAddress(RAX, LookupFieldOffsetInBytes(state_field)));
// Addresses of _state[0] and _state[1].
+ __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
const intptr_t scale =
target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
const intptr_t offset =
target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
- Address addr_0 = FieldAddress(RBX, 0 * scale + offset);
- Address addr_1 = FieldAddress(RBX, 1 * scale + offset);
+ Address addr_0 = Address(RBX, 0 * scale + offset);
+ Address addr_1 = Address(RBX, 1 * scale + offset);
__ movq(RAX, Immediate(a_int_value));
__ movl(RCX, addr_0);
__ imulq(RCX, RAX);
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index d441d61..c7b7037 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3446,7 +3446,9 @@
intptr_t index,
Register temp) {
const int64_t offset_base =
- (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+ ((is_external || RawObject::IsTypedDataClassId(cid))
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
const int64_t offset =
offset_base + static_cast<int64_t>(index) * index_scale;
ASSERT(Utils::IsInt(32, offset));
@@ -3468,7 +3470,9 @@
Register array,
intptr_t index) {
const int64_t offset_base =
- (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+ ((is_external || RawObject::IsTypedDataClassId(cid))
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
const int64_t offset =
offset_base + static_cast<int64_t>(index) * index_scale;
ASSERT(Utils::IsInt(32, offset));
@@ -3483,8 +3487,9 @@
Register index) {
// Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
- int32_t offset =
- is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+ int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
const OperandSize size = Address::OperandSizeFor(cid);
ASSERT(array != IP);
ASSERT(index != IP);
@@ -3524,8 +3529,9 @@
Register index) {
// Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
- int32_t offset =
- is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+ int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
if (shift < 0) {
ASSERT(shift == -1);
add(address, array, Operand(index, ASR, 1));
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index b41c7a4..a7eaf8d 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1566,7 +1566,9 @@
intptr_t index) const {
const int64_t offset =
index * index_scale +
- (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+ ((is_external || RawObject::IsTypedDataClassId(cid))
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
ASSERT(Utils::IsInt(32, offset));
const OperandSize size = Address::OperandSizeFor(cid);
ASSERT(Address::CanHoldOffset(offset, Address::Offset, size));
@@ -1581,7 +1583,9 @@
intptr_t index) {
const int64_t offset =
index * index_scale +
- (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+ ((is_external || RawObject::IsTypedDataClassId(cid))
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
AddImmediate(address, array, offset);
}
@@ -1593,8 +1597,9 @@
Register index) {
// Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
- const int32_t offset =
- is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+ const int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
ASSERT(array != TMP);
ASSERT(index != TMP);
const Register base = is_load ? TMP : index;
@@ -1620,8 +1625,9 @@
Register index) {
// Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
- const int32_t offset =
- is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+ const int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
if (shift == 0) {
add(address, array, Operand(index));
} else if (shift < 0) {
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index f1ef6b1..38c3771 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2535,7 +2535,7 @@
Register array,
intptr_t index,
intptr_t extra_disp) {
- if (is_external) {
+ if (is_external || RawObject::IsTypedDataClassId(cid)) {
return Address(array, index * index_scale + extra_disp);
} else {
const int64_t disp = static_cast<int64_t>(index) * index_scale +
@@ -2573,7 +2573,7 @@
Register array,
Register index,
intptr_t extra_disp) {
- if (is_external) {
+ if (is_external || RawObject::IsTypedDataClassId(cid)) {
return Address(array, index, ToScaleFactor(index_scale), extra_disp);
} else {
return FieldAddress(array, index, ToScaleFactor(index_scale),
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index af6b564..ebccda6 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -2075,7 +2075,7 @@
intptr_t index_scale,
Register array,
intptr_t index) {
- if (is_external) {
+ if (is_external || RawObject::IsTypedDataClassId(cid)) {
return Address(array, index * index_scale);
} else {
const int64_t disp = static_cast<int64_t>(index) * index_scale +
@@ -2112,7 +2112,7 @@
intptr_t index_scale,
Register array,
Register index) {
- if (is_external) {
+ if (is_external || RawObject::IsTypedDataClassId(cid)) {
return Address(array, index, ToScaleFactor(index_scale), 0);
} else {
return FieldAddress(array, index, ToScaleFactor(index_scale),
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index db70602..8f2d56b 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -836,7 +836,7 @@
// ....
// locals space <=== RSP
// saved PP
- // pc (used to derive the RawInstruction Object of the dart code)
+ // code object (used to derive the RawInstruction Object of the dart code)
// saved RBP <=== RBP
// ret PC
// .....
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 12b10eb..7eab5b9 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -669,6 +669,10 @@
SetValue(instr, non_constant_);
}
+void ConstantPropagator::VisitFfiCall(FfiCallInstr* instr) {
+ SetValue(instr, non_constant_);
+}
+
void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) {
// Nothing to do.
}
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index b6d2fd9..41adc25 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -123,7 +123,8 @@
bool FlowGraph::ShouldReorderBlocks(const Function& function,
bool is_optimized) {
- return is_optimized && FLAG_reorder_basic_blocks && !function.is_intrinsic();
+ return is_optimized && FLAG_reorder_basic_blocks &&
+ !function.is_intrinsic() && !function.IsFfiTrampoline();
}
GrowableArray<BlockEntryInstr*>* FlowGraph::CodegenBlockOrder(
@@ -1236,9 +1237,6 @@
Value* use = it.CurrentValue();
use->definition()->AddEnvUse(use);
}
- if (instr->ComputeCanDeoptimize()) {
- instr->env()->set_deopt_id(instr->deopt_id());
- }
}
void FlowGraph::RenameRecursive(
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 9313103..f36f34f 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -174,14 +174,13 @@
(SupportsUnboxedDoubles() && (field.guarded_cid() == kDoubleCid)) ||
(SupportsUnboxedSimd128() && (field.guarded_cid() == kFloat32x4Cid)) ||
(SupportsUnboxedSimd128() && (field.guarded_cid() == kFloat64x2Cid));
- return field.is_unboxing_candidate() && !field.is_final() &&
- !field.is_nullable() && valid_class;
+ return field.is_unboxing_candidate() && !field.is_nullable() && valid_class;
}
bool FlowGraphCompiler::IsPotentialUnboxedField(const Field& field) {
return field.is_unboxing_candidate() &&
(FlowGraphCompiler::IsUnboxedField(field) ||
- (!field.is_final() && (field.guarded_cid() == kIllegalCid)));
+ (field.guarded_cid() == kIllegalCid));
}
void FlowGraphCompiler::InitCompiler() {
@@ -1822,6 +1821,7 @@
const Class& FlowGraphCompiler::BoxClassFor(Representation rep) {
switch (rep) {
+ case kUnboxedFloat:
case kUnboxedDouble:
return double_class();
case kUnboxedFloat32x4:
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 4dbdd20..3d2a546 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -15,6 +15,7 @@
#include "vm/compiler/backend/locations.h"
#include "vm/compiler/backend/loops.h"
#include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/ffi.h"
#include "vm/compiler/frontend/flow_graph_builder.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/compiler/method_recognizer.h"
@@ -1293,14 +1294,12 @@
flow_graph->zone(), this, call->ArgumentCount(),
flow_graph->constant_dead(),
result != NULL ? result : flow_graph->constant_dead());
- env()->set_deopt_id(deopt_id_);
}
void Instruction::InheritDeoptTarget(Zone* zone, Instruction* other) {
ASSERT(other->env() != NULL);
CopyDeoptIdFrom(*other);
other->env()->DeepCopyTo(zone, this);
- env()->set_deopt_id(deopt_id_);
}
void BranchInstr::InheritDeoptTarget(Zone* zone, Instruction* other) {
@@ -2555,6 +2554,7 @@
switch (slot().kind()) {
case Slot::Kind::kArray_length:
case Slot::Kind::kTypedData_length:
+ case Slot::Kind::kTypedDataView_length:
case Slot::Kind::kString_length:
return true;
case Slot::Kind::kGrowableObjectArray_length:
@@ -2570,6 +2570,8 @@
case Slot::Kind::kArgumentsDescriptor_positional_count:
case Slot::Kind::kArgumentsDescriptor_count:
case Slot::Kind::kTypeArguments:
+ case Slot::Kind::kTypedDataView_offset_in_bytes:
+ case Slot::Kind::kTypedDataView_data:
case Slot::Kind::kGrowableObjectArray_data:
case Slot::Kind::kContext_parent:
case Slot::Kind::kClosure_context:
@@ -2580,6 +2582,7 @@
case Slot::Kind::kClosure_hash:
case Slot::Kind::kCapturedVariable:
case Slot::Kind::kDartField:
+ case Slot::Kind::kPointer_c_memory_address:
return false;
}
UNREACHABLE();
@@ -3474,6 +3477,7 @@
return new BoxInt64Instr(value);
case kUnboxedDouble:
+ case kUnboxedFloat:
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4:
@@ -3491,8 +3495,12 @@
SpeculativeMode speculative_mode) {
switch (to) {
case kUnboxedInt32:
- return new UnboxInt32Instr(UnboxInt32Instr::kNoTruncation, value,
- deopt_id, speculative_mode);
+ // We must truncate if we can't deoptimize.
+ return new UnboxInt32Instr(
+ speculative_mode == SpeculativeMode::kNotSpeculative
+ ? UnboxInt32Instr::kTruncate
+ : UnboxInt32Instr::kNoTruncation,
+ value, deopt_id, speculative_mode);
case kUnboxedUint32:
return new UnboxUint32Instr(value, deopt_id, speculative_mode);
@@ -3501,6 +3509,7 @@
return new UnboxInt64Instr(value, deopt_id, speculative_mode);
case kUnboxedDouble:
+ case kUnboxedFloat:
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4:
@@ -3729,10 +3738,10 @@
#endif
__ Bind(compiler->GetJumpLabel(this));
- // In the AOT compiler we want to reduce code size, so generate no
- // fall-through code in [FlowGraphCompiler::CompileGraph()].
- // (As opposed to here where we don't check for the return value of
- // [Intrinsify]).
+// In the AOT compiler we want to reduce code size, so generate no
+// fall-through code in [FlowGraphCompiler::CompileGraph()].
+// (As opposed to here where we don't check for the return value of
+// [Intrinsify]).
#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM)
if (FLAG_precompiled_mode) {
const Function& function = compiler->parsed_function().function();
@@ -4633,6 +4642,7 @@
if (speculative_mode() == kNotSpeculative) {
switch (representation()) {
case kUnboxedDouble:
+ case kUnboxedFloat:
EmitLoadFromBox(compiler);
break;
@@ -4673,9 +4683,8 @@
const GrowableArray<Definition*>& definitions,
intptr_t fixed_parameter_count,
const ParsedFunction& parsed_function) {
- Environment* env =
- new (zone) Environment(definitions.length(), fixed_parameter_count,
- DeoptId::kNone, parsed_function, NULL);
+ Environment* env = new (zone) Environment(
+ definitions.length(), fixed_parameter_count, parsed_function, NULL);
for (intptr_t i = 0; i < definitions.length(); ++i) {
env->values_.Add(new (zone) Value(definitions[i]));
}
@@ -4688,9 +4697,10 @@
Environment* Environment::DeepCopy(Zone* zone, intptr_t length) const {
ASSERT(length <= values_.length());
- Environment* copy = new (zone)
- Environment(length, fixed_parameter_count_, deopt_id_, parsed_function_,
- (outer_ == NULL) ? NULL : outer_->DeepCopy(zone));
+ Environment* copy =
+ new (zone) Environment(length, fixed_parameter_count_, parsed_function_,
+ (outer_ == NULL) ? NULL : outer_->DeepCopy(zone));
+ copy->deopt_id_ = this->deopt_id_;
if (locations_ != NULL) {
Location* new_locations = zone->Alloc<Location>(length);
copy->set_locations(new_locations);
@@ -4742,12 +4752,15 @@
// Copies the environment as outer on an inlined instruction and updates the
// environment use lists.
-void Environment::DeepCopyToOuter(Zone* zone, Instruction* instr) const {
+void Environment::DeepCopyToOuter(Zone* zone,
+ Instruction* instr,
+ intptr_t outer_deopt_id) const {
// Create a deep copy removing caller arguments from the environment.
ASSERT(this != NULL);
ASSERT(instr->env()->outer() == NULL);
intptr_t argument_count = instr->env()->fixed_parameter_count();
Environment* copy = DeepCopy(zone, values_.length() - argument_count);
+ copy->deopt_id_ = outer_deopt_id;
instr->env()->outer_ = copy;
intptr_t use_index = instr->env()->Length(); // Start index after inner.
for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
@@ -5179,6 +5192,74 @@
set_native_c_function(native_function);
}
+#if defined(TARGET_ARCH_X64)
+
+#define Z zone_
+
+Representation FfiCallInstr::RequiredInputRepresentation(intptr_t idx) const {
+ if (idx == TargetAddressIndex()) {
+ return kUnboxedIntPtr;
+ } else {
+ return arg_representations_[idx];
+ }
+}
+
+LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
+ bool is_optimizing) const {
+ // The temporary register needs to be callee-saved and not an argument
+ // register.
+ ASSERT(((1 << CallingConventions::kFirstCalleeSavedCpuReg) &
+ CallingConventions::kArgumentRegisters) == 0);
+
+ LocationSummary* summary =
+ new (zone) LocationSummary(zone, /*num_inputs=*/InputCount(),
+ /*num_temps=*/1, LocationSummary::kCall);
+
+ summary->set_in(TargetAddressIndex(),
+ Location::RegisterLocation(
+ CallingConventions::kFirstNonArgumentRegister));
+ summary->set_temp(0, Location::RegisterLocation(
+ CallingConventions::kSecondNonArgumentRegister));
+ summary->set_out(0, compiler::ffi::ResultLocation(
+ compiler::ffi::ResultRepresentation(signature_)));
+
+ for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
+ Location target = arg_locations_[i];
+ if (target.IsMachineRegister()) {
+ summary->set_in(i, target);
+ } else {
+ // Since we have to push this input on the stack, there's no point in
+ // pinning it to any specific register.
+ summary->set_in(i, Location::Any());
+ }
+ }
+
+ return summary;
+}
+
+Representation FfiCallInstr::representation() const {
+ return compiler::ffi::ResultRepresentation(signature_);
+}
+
+#undef Z
+
+#else
+
+Representation FfiCallInstr::RequiredInputRepresentation(intptr_t idx) const {
+ UNREACHABLE();
+}
+
+LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
+ bool is_optimizing) const {
+ UNREACHABLE();
+}
+
+Representation FfiCallInstr::representation() const {
+ UNREACHABLE();
+}
+
+#endif
+
// SIMD
SimdOpInstr* SimdOpInstr::CreateFromCall(Zone* zone,
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 2d815ae..a16b035 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -11,6 +11,7 @@
#include "vm/compiler/backend/locations.h"
#include "vm/compiler/backend/slot.h"
#include "vm/compiler/compiler_state.h"
+#include "vm/compiler/ffi.h"
#include "vm/compiler/method_recognizer.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
@@ -355,6 +356,7 @@
M(AssertBoolean, _) \
M(SpecialParameter, kNoGC) \
M(ClosureCall, _) \
+ M(FfiCall, _) \
M(InstanceCall, _) \
M(PolymorphicInstanceCall, _) \
M(StaticCall, _) \
@@ -4087,6 +4089,63 @@
DISALLOW_COPY_AND_ASSIGN(NativeCallInstr);
};
+// Performs a call to native C code. In contrast to NativeCall, the arguments
+// are unboxed and passed through the native calling convention. However, not
+// all dart objects can be passed as arguments. Please see the FFI documentation
+// for more details.
+// TODO(35775): Add link to the documentation when it's written.
+class FfiCallInstr : public Definition {
+ public:
+ FfiCallInstr(Zone* zone,
+ intptr_t deopt_id,
+ const Function& signature,
+ const ZoneGrowableArray<Representation>& arg_reps,
+ const ZoneGrowableArray<Location>& arg_locs)
+ : Definition(deopt_id),
+ zone_(zone),
+ signature_(signature),
+ inputs_(arg_reps.length() + 1),
+ arg_representations_(arg_reps),
+ arg_locations_(arg_locs) {
+ inputs_.FillWith(nullptr, 0, arg_reps.length() + 1);
+ ASSERT(signature.IsZoneHandle());
+ }
+
+ DECLARE_INSTRUCTION(FfiCall)
+
+ // Number of arguments to the native function.
+ intptr_t NativeArgCount() const { return InputCount() - 1; }
+
+ // Input index of the function pointer to invoke.
+ intptr_t TargetAddressIndex() const { return NativeArgCount(); }
+
+ virtual intptr_t InputCount() const { return inputs_.length(); }
+ virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
+ virtual bool MayThrow() const { return false; }
+
+ // FfiCallInstr calls C code, which can call back into Dart.
+ virtual bool ComputeCanDeoptimize() const { return true; }
+
+ virtual bool HasUnknownSideEffects() const { return true; }
+
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const;
+ virtual Representation representation() const;
+
+ PRINT_OPERANDS_TO_SUPPORT
+
+ private:
+ virtual void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
+
+ Zone* const zone_;
+ const Function& signature_;
+
+ GrowableArray<Value*> inputs_;
+ const ZoneGrowableArray<Representation>& arg_representations_;
+ const ZoneGrowableArray<Location>& arg_locations_;
+
+ DISALLOW_COPY_AND_ASSIGN(FfiCallInstr);
+};
+
class DebugStepCheckInstr : public TemplateInstruction<0, NoThrow> {
public:
DebugStepCheckInstr(TokenPosition token_pos,
@@ -5362,6 +5421,7 @@
static intptr_t ValueOffset(Representation rep) {
switch (rep) {
+ case kUnboxedFloat:
case kUnboxedDouble:
return Double::value_offset();
@@ -5388,6 +5448,7 @@
case kUnboxedInt64:
return kMintCid;
case kUnboxedDouble:
+ case kUnboxedFloat:
return kDoubleCid;
case kUnboxedFloat32x4:
return kFloat32x4Cid;
@@ -6926,6 +6987,7 @@
DISALLOW_COPY_AND_ASSIGN(FloatToDoubleInstr);
};
+// TODO(sjindel): Replace with FFICallInstr.
class InvokeMathCFunctionInstr : public PureDefinition {
public:
InvokeMathCFunctionInstr(ZoneGrowableArray<Value*>* inputs,
@@ -7786,8 +7848,13 @@
locations_ = locations;
}
- void set_deopt_id(intptr_t deopt_id) { deopt_id_ = deopt_id; }
- intptr_t deopt_id() const { return deopt_id_; }
+ // Get deopt_id associated with this environment.
+ // Note that only outer environments have deopt id associated with
+ // them (set by DeepCopyToOuter).
+ intptr_t deopt_id() const {
+ ASSERT(deopt_id_ != DeoptId::kNone);
+ return deopt_id_;
+ }
Environment* outer() const { return outer_; }
@@ -7837,7 +7904,9 @@
Environment* DeepCopy(Zone* zone) const { return DeepCopy(zone, Length()); }
void DeepCopyTo(Zone* zone, Instruction* instr) const;
- void DeepCopyToOuter(Zone* zone, Instruction* instr) const;
+ void DeepCopyToOuter(Zone* zone,
+ Instruction* instr,
+ intptr_t outer_deopt_id) const;
void DeepCopyAfterTo(Zone* zone,
Instruction* instr,
@@ -7870,20 +7939,19 @@
Environment(intptr_t length,
intptr_t fixed_parameter_count,
- intptr_t deopt_id,
const ParsedFunction& parsed_function,
Environment* outer)
: values_(length),
- locations_(NULL),
fixed_parameter_count_(fixed_parameter_count),
- deopt_id_(deopt_id),
parsed_function_(parsed_function),
outer_(outer) {}
GrowableArray<Value*> values_;
- Location* locations_;
+ Location* locations_ = nullptr;
const intptr_t fixed_parameter_count_;
- intptr_t deopt_id_;
+ // Deoptimization id associated with this environment. Only set for
+ // outer environments.
+ intptr_t deopt_id_ = DeoptId::kNone;
const ParsedFunction& parsed_function_;
Environment* outer_;
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 033b200..e6766dc 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -982,6 +982,10 @@
__ Drop(ArgumentCount()); // Drop the arguments.
}
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNREACHABLE();
+}
+
LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -1180,7 +1184,9 @@
const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
const intptr_t scale = Instance::ElementSizeFor(cid);
const intptr_t base_offset =
- (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+ (is_external || RawObject::IsTypedDataClassId(cid)
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
const int64_t offset = index * scale + base_offset;
if (!Utils::IsAbsoluteUint(12, offset)) {
return false;
@@ -4048,6 +4054,11 @@
case kUnboxedDouble:
__ StoreDToOffset(value, out_reg, ValueOffset() - kHeapObjectTag);
break;
+ case kUnboxedFloat:
+ __ vcvtds(DTMP, EvenSRegisterOf(value));
+ __ StoreDToOffset(EvenDRegisterOf(FpuTMP), out_reg,
+ ValueOffset() - kHeapObjectTag);
+ break;
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4:
@@ -4098,6 +4109,13 @@
break;
}
+ case kUnboxedFloat: {
+ const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
+ __ LoadDFromOffset(result, box, ValueOffset() - kHeapObjectTag);
+ __ vcvtsd(EvenSRegisterOf(result), result);
+ break;
+ }
+
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4: {
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 64296ab..b10e64d 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -872,6 +872,10 @@
__ Drop(ArgumentCount()); // Drop the arguments.
}
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNREACHABLE();
+}
+
LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -1060,8 +1064,9 @@
const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
const intptr_t scale = Instance::ElementSizeFor(cid);
const int64_t offset =
- index * scale +
- (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+ index * scale + (is_external || RawObject::IsTypedDataClassId(cid)
+ ? 0
+ : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
if (!Utils::IsInt(32, offset)) {
return false;
}
@@ -2778,9 +2783,7 @@
compiler->AddSlowPathCode(slow_path);
__ ldr(TMP, Address(THR, Thread::stack_limit_offset()));
- // Compare to CSP not SP because CSP is closer to the stack limit. See
- // Assembler::EnterFrame.
- __ CompareRegisters(CSP, TMP);
+ __ CompareRegisters(SP, TMP);
__ b(slow_path->entry_label(), LS);
if (compiler->CanOSRFunction() && in_loop()) {
const Register temp = locs()->temp(0).reg();
@@ -3507,6 +3510,10 @@
case kUnboxedDouble:
__ StoreDFieldToOffset(value, out_reg, ValueOffset());
break;
+ case kUnboxedFloat:
+ __ fcvtds(FpuTMP, value);
+ __ StoreDFieldToOffset(FpuTMP, out_reg, ValueOffset());
+ break;
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4:
@@ -3546,6 +3553,13 @@
break;
}
+ case kUnboxedFloat: {
+ const VRegister result = locs()->out(0).fpu_reg();
+ __ LoadDFieldFromOffset(result, box, ValueOffset());
+ __ fcvtsd(result, result);
+ break;
+ }
+
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4: {
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index 70f8e2b..0ffd8d9 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -958,6 +958,10 @@
}
}
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNREACHABLE();
+}
+
EMIT_NATIVE_CODE(NativeCall,
0,
Location::NoLocation(),
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 3f6ee68..1d0b013 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -12,6 +12,7 @@
#include "vm/compiler/backend/locations.h"
#include "vm/compiler/backend/locations_helpers.h"
#include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/ffi.h"
#include "vm/compiler/frontend/flow_graph_builder.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_entry.h"
@@ -844,6 +845,10 @@
__ Drop(ArgumentCount()); // Drop the arguments.
}
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNREACHABLE();
+}
+
static bool CanBeImmediateIndex(Value* value, intptr_t cid) {
ConstantInstr* constant = value->definition()->AsConstant();
if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) {
@@ -3358,6 +3363,10 @@
case kUnboxedDouble:
__ movsd(FieldAddress(out_reg, ValueOffset()), value);
break;
+ case kUnboxedFloat:
+ __ cvtss2sd(FpuTMP, value);
+ __ movsd(FieldAddress(out_reg, ValueOffset()), FpuTMP);
+ break;
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4:
@@ -3410,6 +3419,13 @@
break;
}
+ case kUnboxedFloat: {
+ const FpuRegister result = locs()->out(0).fpu_reg();
+ __ movsd(result, FieldAddress(box, ValueOffset()));
+ __ cvtsd2ss(result, result);
+ break;
+ }
+
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4: {
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index a2a26ea..c6ab009 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -511,6 +511,18 @@
}
}
+void FfiCallInstr::PrintOperandsTo(BufferFormatter* f) const {
+ f->Print(" pointer=");
+ InputAt(TargetAddressIndex())->PrintTo(f);
+ f->Print(" signature=%s",
+ Type::Handle(signature_.SignatureType()).ToCString());
+ for (intptr_t i = 0, n = InputCount(); i < n - 1; ++i) {
+ f->Print(", ");
+ InputAt(i)->PrintTo(f);
+ f->Print(" (at %s) ", arg_locations_[i].ToCString());
+ }
+}
+
void InstanceCallInstr::PrintOperandsTo(BufferFormatter* f) const {
f->Print(" %s<%" Pd ">", function_name().ToCString(), type_args_len());
for (intptr_t i = 0; i < ArgumentCount(); ++i) {
@@ -910,6 +922,8 @@
return "untagged";
case kUnboxedDouble:
return "double";
+ case kUnboxedFloat:
+ return "float";
case kUnboxedInt32:
return "int32";
case kUnboxedUint32:
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 2c632c8..53c0b02 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -7,11 +7,13 @@
#include "vm/compiler/backend/il.h"
+#include "vm/compiler/assembler/assembler.h"
#include "vm/compiler/backend/flow_graph.h"
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/backend/locations.h"
#include "vm/compiler/backend/locations_helpers.h"
#include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/ffi.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_entry.h"
#include "vm/instructions.h"
@@ -877,6 +879,99 @@
__ Drop(ArgumentCount()); // Drop the arguments.
}
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register saved_fp = locs()->temp(0).reg();
+ Register target_address = locs()->in(TargetAddressIndex()).reg();
+
+ // Save frame pointer because we're going to update it when we enter the exit
+ // frame.
+ __ movq(saved_fp, FPREG);
+
+ // Make a space to put the return address.
+ __ pushq(Immediate(0));
+
+ // We need to create a dummy "exit frame". It will share the same pool pointer
+ // but have a null code object.
+ __ LoadObject(CODE_REG, Object::null_object());
+ __ set_constant_pool_allowed(false);
+ __ EnterDartFrame(
+ compiler::ffi::NumStackArguments(arg_locations_) * kWordSize, PP);
+
+ // Save exit frame information to enable stack walking as we are about to
+ // transition to Dart VM C++ code.
+ __ movq(Address(THR, Thread::top_exit_frame_info_offset()), FPREG);
+
+ // Align frame before entering C++ world.
+ if (OS::ActivationFrameAlignment() > 1) {
+ __ andq(SPREG, Immediate(~(OS::ActivationFrameAlignment() - 1)));
+ }
+
+ for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
+ Location origin = locs()->in(i);
+ Location target = arg_locations_[i];
+
+ if (target.IsStackSlot()) {
+ if (origin.IsRegister()) {
+ __ movq(target.ToStackSlotAddress(), origin.reg());
+ } else if (origin.IsFpuRegister()) {
+ __ movq(TMP, origin.fpu_reg());
+ __ movq(target.ToStackSlotAddress(), TMP);
+ } else if (origin.IsStackSlot() || origin.IsDoubleStackSlot()) {
+ // The base register cannot be SPREG because we've moved it.
+ ASSERT(origin.base_reg() == FPREG);
+ __ movq(TMP, Address(saved_fp, origin.ToStackSlotOffset()));
+ __ movq(target.ToStackSlotAddress(), TMP);
+ }
+ } else {
+ ASSERT(origin.Equals(target));
+ }
+ }
+
+ // Mark that the thread is executing VM code.
+ __ movq(Assembler::VMTagAddress(), target_address);
+
+// We need to copy the return address up into the dummy stack frame so the
+// stack walker will know which safepoint to use.
+#if defined(TARGET_OS_WINDOWS)
+ constexpr intptr_t kCallSequenceLength = 10;
+#else
+ constexpr intptr_t kCallSequenceLength = 6;
+#endif
+
+ // RIP points to the *next* instruction, so 'AddressRIPRelative' loads the
+ // address of the following 'movq'.
+ __ leaq(TMP, Address::AddressRIPRelative(kCallSequenceLength));
+
+ const intptr_t call_sequence_start = __ CodeSize();
+ __ movq(Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), TMP);
+ __ CallCFunction(target_address);
+
+ ASSERT(__ CodeSize() - call_sequence_start == kCallSequenceLength);
+
+ compiler->EmitCallsiteMetadata(TokenPosition::kNoSource, DeoptId::kNone,
+ RawPcDescriptors::Kind::kOther, locs());
+
+ // Mark that the thread is executing Dart code.
+ __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
+
+ // Reset exit frame information in Isolate structure.
+ __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+
+ // Although PP is a callee-saved register, it may have been moved by the GC.
+ __ LeaveDartFrame(compiler::kRestoreCallerPP);
+
+ // Restore the global object pool after returning from runtime (old space is
+ // moving, so the GOP could have been relocated).
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ __ movq(PP, Address(THR, Thread::global_object_pool_offset()));
+ }
+
+ __ set_constant_pool_allowed(true);
+
+ // Instead of returning to the "fake" return address, we just pop it.
+ __ popq(TMP);
+}
+
static bool CanBeImmediateIndex(Value* index, intptr_t cid) {
if (!index->definition()->IsConstant()) return false;
const Object& constant = index->definition()->AsConstant()->value();
@@ -3698,6 +3793,11 @@
case kUnboxedDouble:
__ movsd(FieldAddress(out_reg, ValueOffset()), value);
break;
+ case kUnboxedFloat: {
+ __ cvtss2sd(FpuTMP, value);
+ __ movsd(FieldAddress(out_reg, ValueOffset()), FpuTMP);
+ break;
+ }
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4:
@@ -3743,6 +3843,13 @@
break;
}
+ case kUnboxedFloat: {
+ const FpuRegister result = locs()->out(0).fpu_reg();
+ __ movsd(result, FieldAddress(box, ValueOffset()));
+ __ cvtsd2ss(result, result);
+ break;
+ }
+
case kUnboxedFloat32x4:
case kUnboxedFloat64x2:
case kUnboxedInt32x4: {
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index afde064..a81b2cc 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -535,8 +535,11 @@
if (!function.always_inline() && !function.IsRecognized()) {
return false;
}
- static constexpr intptr_t kAvgListedMethodSize = 20;
- instruction_count += (inl_size == 0 ? kAvgListedMethodSize : inl_size);
+ if (!function.always_inline()) {
+ static constexpr intptr_t kAvgListedMethodSize = 20;
+ instruction_count +=
+ (inl_size == 0 ? kAvgListedMethodSize : inl_size);
+ }
}
}
}
@@ -2436,9 +2439,11 @@
// 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());
+ } else if (RawObject::IsTypedDataClassId(array_cid) ||
+ RawObject::IsExternalTypedDataClassId(array_cid)) {
+ ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
+ LoadUntaggedInstr* elements = new (Z)
+ LoadUntaggedInstr(new (Z) Value(*array), TypedData::data_offset());
*cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
*array = elements;
}
@@ -2853,64 +2858,6 @@
FlowGraph::kValue);
}
-// Emits preparatory code for a typed getter/setter.
-// Handles three cases:
-// (1) dynamic: generates a conditional on the receiver cid
-// that handles external (load untagged) and
-// internal storage at runtime.
-// (2) external: generates load untagged.
-// (3) internal: no code required.
-static void PrepareInlineByteArrayBaseOp(FlowGraph* flow_graph,
- Instruction* call,
- Definition* receiver,
- intptr_t array_cid,
- Definition** array,
- Instruction** cursor,
- TargetEntryInstr** block_external,
- TargetEntryInstr** block_internal) {
- if (array_cid == kDynamicCid) {
- // Dynamic case: runtime resolution between external/internal typed data.
- // cid = LoadCid
- // if cid in [ kExternalTypedDataInt8ArrayCid,
- // kExternalTypedDataFloat64x2ArrayCid ]
- // block_external: LoadUntagged
- // ..
- // else
- // block_internal: ..
- //
- // TODO(ajcbik): as suggested above, subtract + single unsigned test.
- //
- LoadClassIdInstr* load_cid =
- new (Z) LoadClassIdInstr(new (Z) Value(receiver));
- *cursor = flow_graph->AppendTo(*cursor, load_cid, NULL, FlowGraph::kValue);
- ConstantInstr* cid_lo = flow_graph->GetConstant(
- Smi::ZoneHandle(Smi::New(kExternalTypedDataInt8ArrayCid)));
- RelationalOpInstr* le_lo = new (Z)
- RelationalOpInstr(call->token_pos(), Token::kLTE, new (Z) Value(cid_lo),
- new (Z) Value(load_cid), kSmiCid, call->deopt_id());
- ConstantInstr* cid_hi = flow_graph->GetConstant(
- Smi::ZoneHandle(Smi::New(kExternalTypedDataFloat64x2ArrayCid)));
- RelationalOpInstr* le_hi = new (Z) RelationalOpInstr(
- call->token_pos(), Token::kLTE, new (Z) Value(load_cid),
- new (Z) Value(cid_hi), kSmiCid, call->deopt_id());
- *cursor = flow_graph->NewDiamond(*cursor, call,
- FlowGraph::LogicalAnd(le_lo, le_hi),
- block_external, block_internal);
- LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
- new (Z) Value(*array), ExternalTypedData::data_offset());
- flow_graph->InsertAfter(*block_external, elements, NULL, FlowGraph::kValue);
- *array = elements; // return load untagged definition in array
- } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
- // External typed data: load untagged.
- LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
- new (Z) Value(*array), ExternalTypedData::data_offset());
- *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
- *array = elements;
- } else {
- // Internal typed data: no action.
- }
-}
-
static LoadIndexedInstr* NewLoad(FlowGraph* flow_graph,
Instruction* call,
Definition* array,
@@ -2962,44 +2909,16 @@
array, &index, &cursor);
}
- // Generates a template for the load, either a dynamic conditional
- // that dispatches on external and internal storage, or a single
- // case that deals with either external or internal storage.
- TargetEntryInstr* block_external = nullptr;
- TargetEntryInstr* block_internal = nullptr;
- PrepareInlineByteArrayBaseOp(flow_graph, call, receiver, array_cid, &array,
- &cursor, &block_external, &block_internal);
+ ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
+ LoadUntaggedInstr* elements =
+ new (Z) LoadUntaggedInstr(new (Z) Value(array), TypedData::data_offset());
+ cursor = flow_graph->AppendTo(cursor, elements, nullptr, FlowGraph::kValue);
- // Fill out the generated template with loads.
- if (array_cid == kDynamicCid) {
- ASSERT(block_external != nullptr && block_internal != nullptr);
- // Load from external in block_external and internal in block_internal
- // (resolves (B)). The former loads from "array", which is the returned
- // load untagged definition. The latter loads from the original "receiver".
- LoadIndexedInstr* load1 = NewLoad(flow_graph, call, array, index, view_cid);
- ASSERT(block_external->next() == array);
- flow_graph->InsertAfter(
- block_external->next(), load1,
- call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
- FlowGraph::kValue);
- LoadIndexedInstr* load2 =
- NewLoad(flow_graph, call, receiver, index, view_cid);
- flow_graph->InsertAfter(
- block_internal, load2,
- call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
- FlowGraph::kValue);
- // Construct phi of external and internal load.
- *last = flow_graph->AddPhi(cursor->AsJoinEntry(), load1, load2);
- } else {
- ASSERT(block_external == nullptr && block_internal == nullptr);
- // Load from either external or internal.
- LoadIndexedInstr* load = NewLoad(flow_graph, call, array, index, view_cid);
- flow_graph->AppendTo(
- cursor, load,
- call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
- FlowGraph::kValue);
- cursor = *last = load;
- }
+ LoadIndexedInstr* load = NewLoad(flow_graph, call, elements, index, view_cid);
+ flow_graph->AppendTo(
+ cursor, load, call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+ FlowGraph::kValue);
+ cursor = *last = load;
if (view_cid == kTypedDataFloat32ArrayCid) {
*last = new (Z) FloatToDoubleInstr(new (Z) Value((*last)->AsDefinition()),
@@ -3178,43 +3097,17 @@
FlowGraph::kValue);
}
- // Generates a template for the store, either a dynamic conditional
- // that dispatches on external and internal storage, or a single
- // case that deals with either external or internal storage.
- TargetEntryInstr* block_external = nullptr;
- TargetEntryInstr* block_internal = nullptr;
- PrepareInlineByteArrayBaseOp(flow_graph, call, receiver, array_cid, &array,
- &cursor, &block_external, &block_internal);
+ ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
+ LoadUntaggedInstr* elements =
+ new (Z) LoadUntaggedInstr(new (Z) Value(array), TypedData::data_offset());
+ cursor = flow_graph->AppendTo(cursor, elements, nullptr, FlowGraph::kValue);
- // Fill out the generated template with stores.
- if (array_cid == kDynamicCid) {
- ASSERT(block_external != nullptr && block_internal != nullptr);
- // Store to external in block_external and internal in block_internal
- // (resolves (B)). The former stores to "array", which is the returned
- // load untagged definition. The latter stores to the original "receiver".
- ASSERT(block_external->next() == array);
- flow_graph->InsertAfter(
- block_external->next(),
- NewStore(flow_graph, call, array, index, stored_value, view_cid),
- call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
- FlowGraph::kEffect);
- flow_graph->InsertAfter(
- block_internal,
- NewStore(flow_graph, call, receiver, index, stored_value, view_cid),
- call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
- FlowGraph::kEffect);
- *last = cursor;
- } else {
- ASSERT(block_external == nullptr && block_internal == nullptr);
- // Store on either external or internal.
- StoreIndexedInstr* store =
- NewStore(flow_graph, call, array, index, stored_value, view_cid);
- flow_graph->AppendTo(
- cursor, store,
- call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
- FlowGraph::kEffect);
- *last = store;
- }
+ StoreIndexedInstr* store =
+ NewStore(flow_graph, call, elements, index, stored_value, view_cid);
+ flow_graph->AppendTo(
+ cursor, store, call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+ FlowGraph::kEffect);
+ *last = store;
// We need a return value to replace uses of the original definition. However,
// the final instruction is a use of 'void operator[]=()', so we use null.
*result = flow_graph->constant_null();
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index b09079d..23b5189 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -824,8 +824,9 @@
static Location::Kind RegisterKindForResult(Instruction* instr) {
const Representation rep = instr->representation();
#if !defined(TARGET_ARCH_DBC)
- if ((rep == kUnboxedDouble) || (rep == kUnboxedFloat32x4) ||
- (rep == kUnboxedInt32x4) || (rep == kUnboxedFloat64x2)) {
+ if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) ||
+ (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) ||
+ (rep == kUnboxedFloat64x2)) {
return Location::kFpuRegister;
} else {
return Location::kRegister;
@@ -1454,7 +1455,7 @@
#if defined(DEBUG)
// Verify that temps, inputs and output were specified as fixed
// locations. Every register is blocked now so attempt to
- // allocate will not succeed.
+ // allocate will go on the stack.
for (intptr_t j = 0; j < locs->temp_count(); j++) {
ASSERT(!locs->temp(j).IsPairLocation());
ASSERT(!locs->temp(j).IsUnallocated());
@@ -1463,10 +1464,13 @@
for (intptr_t j = 0; j < locs->input_count(); j++) {
if (locs->in(j).IsPairLocation()) {
PairLocation* pair = locs->in_slot(j)->AsPairLocation();
- ASSERT(!pair->At(0).IsUnallocated());
- ASSERT(!pair->At(1).IsUnallocated());
+ ASSERT(!pair->At(0).IsUnallocated() ||
+ locs->in(j).policy() == Location::kAny);
+ ASSERT(!pair->At(1).IsUnallocated() ||
+ locs->in(j).policy() == Location::kAny);
} else {
- ASSERT(!locs->in(j).IsUnallocated());
+ ASSERT(!locs->in(j).IsUnallocated() ||
+ locs->in(j).policy() == Location::kAny);
}
}
@@ -2059,7 +2063,8 @@
ASSERT(need_quad);
location = Location::QuadStackSlot(slot_idx);
} else {
- ASSERT((range->representation() == kUnboxedDouble));
+ ASSERT(range->representation() == kUnboxedFloat ||
+ range->representation() == kUnboxedDouble);
location = Location::DoubleStackSlot(slot_idx);
}
range->set_spill_slot(location);
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index 9c76dd6..d1e6f00 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -23,6 +23,7 @@
kTagged,
kUntagged,
kUnboxedDouble,
+ kUnboxedFloat,
kUnboxedInt32,
kUnboxedUint32,
kUnboxedInt64,
@@ -33,6 +34,9 @@
kNumRepresentations
};
+static constexpr Representation kUnboxedIntPtr =
+ compiler::target::kWordSize == 4 ? kUnboxedInt32 : kUnboxedInt64;
+
// Location objects are used to connect register allocator and code generator.
// Instruction templates used by code generator have a corresponding
// LocationSummary object which specifies expected location for every input
@@ -636,7 +640,10 @@
void set_in(intptr_t index, Location loc) {
ASSERT(index >= 0);
ASSERT(index < num_inputs_);
- ASSERT(!always_calls() || loc.IsMachineRegister());
+ // See FlowGraphAllocator::ProcessOneInstruction for explanation of this
+ // restriction.
+ ASSERT(!always_calls() || loc.IsMachineRegister() ||
+ (loc.IsUnallocated() && loc.policy() == Location::kAny));
input_locations_[index] = loc;
}
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index e0f096b..755ff5e 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -699,7 +699,6 @@
last, instr, last->env(),
instr->IsDefinition() ? FlowGraph::kValue : FlowGraph::kEffect);
instr->CopyDeoptIdFrom(*last);
- instr->env()->set_deopt_id(instr->deopt_id_);
map_.Insert(instr);
emitted_.Add(instr);
@@ -2606,6 +2605,8 @@
break;
case Slot::Kind::kTypedData_length:
+ case Slot::Kind::kTypedDataView_length:
+ case Slot::Kind::kTypedDataView_offset_in_bytes:
*range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
break;
@@ -2630,6 +2631,8 @@
case Slot::Kind::kClosure_function:
case Slot::Kind::kClosure_function_type_arguments:
case Slot::Kind::kClosure_instantiator_type_arguments:
+ case Slot::Kind::kPointer_c_memory_address:
+ case Slot::Kind::kTypedDataView_data:
// Not an integer valued field.
UNREACHABLE();
break;
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index f1c01f9..695760d 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -73,6 +73,9 @@
RawObject::IsTypedDataClassId(array_cid)) {
return GetNativeSlot(Kind::kTypedData_length);
}
+ if (RawObject::IsTypedDataViewClassId(array_cid)) {
+ return GetNativeSlot(Kind::kTypedDataView_length);
+ }
switch (array_cid) {
case kGrowableObjectArrayCid:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index d448e40..fc82584 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -59,6 +59,9 @@
V(GrowableObjectArray, length, Smi, VAR) \
V(GrowableObjectArray, data, Array, VAR) \
V(TypedData, length, Smi, FINAL) \
+ V(TypedDataView, length, Smi, FINAL) \
+ V(TypedDataView, offset_in_bytes, Smi, FINAL) \
+ V(TypedDataView, data, Dynamic, FINAL) \
V(String, length, Smi, FINAL) \
V(LinkedHashMap, index, TypedDataUint32Array, VAR) \
V(LinkedHashMap, data, Array, VAR) \
@@ -67,7 +70,8 @@
V(LinkedHashMap, deleted_keys, Smi, VAR) \
V(ArgumentsDescriptor, type_args_len, Smi, FINAL) \
V(ArgumentsDescriptor, positional_count, Smi, FINAL) \
- V(ArgumentsDescriptor, count, Smi, FINAL)
+ V(ArgumentsDescriptor, count, Smi, FINAL) \
+ V(Pointer, c_memory_address, Integer, FINAL)
// Slot is an abstraction that describes an readable (and possibly writeable)
// location within an object.
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index ca5aadb..e3f4f7d 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -505,21 +505,19 @@
Instruction* check_clone = NULL;
if (check->IsCheckSmi()) {
- check_clone =
- new CheckSmiInstr(assert->value()->Copy(zone()),
- assert->env()->deopt_id(), check->token_pos());
+ check_clone = new CheckSmiInstr(assert->value()->Copy(zone()),
+ assert->deopt_id(), check->token_pos());
check_clone->AsCheckSmi()->set_licm_hoisted(
check->AsCheckSmi()->licm_hoisted());
} else {
ASSERT(check->IsCheckClass());
- check_clone = new CheckClassInstr(
- assert->value()->Copy(zone()), assert->env()->deopt_id(),
- check->AsCheckClass()->cids(), check->token_pos());
+ check_clone =
+ new CheckClassInstr(assert->value()->Copy(zone()), assert->deopt_id(),
+ check->AsCheckClass()->cids(), check->token_pos());
check_clone->AsCheckClass()->set_licm_hoisted(
check->AsCheckClass()->licm_hoisted());
}
ASSERT(check_clone != NULL);
- ASSERT(assert->deopt_id() == assert->env()->deopt_id());
check_clone->InsertBefore(assert);
assert->env()->DeepCopyTo(zone(), check_clone);
@@ -987,8 +985,8 @@
// Parameter is the receiver.
if ((index() == 0) &&
(function.IsDynamicFunction() || function.IsGenerativeConstructor())) {
- LocalScope* scope = graph_entry->parsed_function().node_sequence()->scope();
- const AbstractType& type = scope->VariableAt(index())->type();
+ const AbstractType& type =
+ graph_entry->parsed_function().ParameterVariable(index())->type();
if (type.IsObjectType() || type.IsNullType()) {
// Receiver can be null.
return CompileType::FromAbstractType(type, CompileType::kNullable);
@@ -1508,6 +1506,7 @@
CompileType UnboxInstr::ComputeType() const {
switch (representation()) {
+ case kUnboxedFloat:
case kUnboxedDouble:
return CompileType::FromCid(kDoubleCid);
@@ -1531,6 +1530,7 @@
CompileType BoxInstr::ComputeType() const {
switch (from_representation()) {
+ case kUnboxedFloat:
case kUnboxedDouble:
return CompileType::FromCid(kDoubleCid);
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 42e2f9b..51ac37f 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -949,7 +949,7 @@
}
// Inline implicit instance setter.
String& field_name = String::Handle(Z, instr->function_name().raw());
- if (Function::IsDynamicInvocationForwaderName(field_name)) {
+ if (Function::IsDynamicInvocationForwarderName(field_name)) {
field_name = Function::DemangleDynamicInvocationForwarderName(field_name);
}
field_name = Field::NameFromSetter(field_name);
@@ -1017,14 +1017,10 @@
// not in strong mode or if at a dynamic invocation.
bool needs_check = true;
if (!instr->interface_target().IsNull() && (field.kernel_offset() >= 0)) {
- bool is_covariant = false;
- bool is_generic_covariant = false;
- field.GetCovarianceAttributes(&is_covariant, &is_generic_covariant);
-
- if (is_covariant) {
+ if (field.is_covariant()) {
// Always type check covariant fields.
needs_check = true;
- } else if (is_generic_covariant) {
+ } else if (field.is_generic_covariant_impl()) {
// If field is generic covariant then we don't need to check it
// if the invocation was marked as unchecked (e.g. receiver of
// the invocation is also the receiver of the surrounding method).
diff --git a/runtime/vm/compiler/ffi.cc b/runtime/vm/compiler/ffi.cc
index e343fc7..375dc5d 100644
--- a/runtime/vm/compiler/ffi.cc
+++ b/runtime/vm/compiler/ffi.cc
@@ -6,6 +6,8 @@
namespace dart {
+namespace compiler {
+
namespace ffi {
#if defined(TARGET_ARCH_X64)
@@ -15,26 +17,22 @@
static const intptr_t kNumElementSizes = kFfiVoidCid - kFfiPointerCid + 1;
static const size_t element_size_table[kNumElementSizes] = {
- sizeof(intptr_t), // kFfiPointerCid
- kSizeUnknown, // kFfiNativeFunctionCid
- 1, // kFfiInt8Cid
- 2, // kFfiInt16Cid
- 4, // kFfiInt32Cid
- 8, // kFfiInt64Cid
- 1, // kFfiUint8Cid
- 2, // kFfiUint16Cid
- 4, // kFfiUint32Cid
- 8, // kFfiUint64Cid
- sizeof(intptr_t), // kFfiIntPtrCid
- 4, // kFfiFloatCid
- 8, // kFfiDoubleCid
- kSizeUnknown, // kFfiVoidCid
+ target::kWordSize, // kFfiPointerCid
+ kSizeUnknown, // kFfiNativeFunctionCid
+ 1, // kFfiInt8Cid
+ 2, // kFfiInt16Cid
+ 4, // kFfiInt32Cid
+ 8, // kFfiInt64Cid
+ 1, // kFfiUint8Cid
+ 2, // kFfiUint16Cid
+ 4, // kFfiUint32Cid
+ 8, // kFfiUint64Cid
+ target::kWordSize, // kFfiIntPtrCid
+ 4, // kFfiFloatCid
+ 8, // kFfiDoubleCid
+ kSizeUnknown, // kFfiVoidCid
};
-Representation WordRep() {
- return compiler::target::kWordSize > 4 ? kUnboxedInt64 : kUnboxedInt32;
-}
-
size_t ElementSizeInBytes(intptr_t class_id) {
ASSERT(class_id != kFfiNativeFunctionCid);
ASSERT(class_id != kFfiVoidCid);
@@ -46,45 +44,52 @@
return element_size_table[index];
}
-bool ElementIsSigned(intptr_t class_id) {
- switch (class_id) {
- case kFfiFloatCid:
- case kFfiDoubleCid:
- case kFfiInt8Cid:
- case kFfiInt16Cid:
- case kFfiInt32Cid:
- case kFfiInt64Cid:
- case kFfiIntPtrCid:
- return true;
- case kFfiUint8Cid:
- case kFfiUint16Cid:
- case kFfiUint32Cid:
- case kFfiUint64Cid:
- case kFfiPointerCid:
- default: // Subtypes of Pointer.
- return false;
- }
-}
-
Representation TypeRepresentation(const AbstractType& result_type) {
switch (result_type.type_class_id()) {
case kFfiFloatCid:
+ return kUnboxedFloat;
case kFfiDoubleCid:
return kUnboxedDouble;
case kFfiInt8Cid:
case kFfiInt16Cid:
case kFfiInt32Cid:
+ return kUnboxedInt32;
case kFfiUint8Cid:
case kFfiUint16Cid:
case kFfiUint32Cid:
- return kUnboxedInt32;
+ return kUnboxedUint32;
case kFfiInt64Cid:
case kFfiUint64Cid:
return kUnboxedInt64;
case kFfiIntPtrCid:
case kFfiPointerCid:
default: // Subtypes of Pointer.
- return WordRep();
+ return kUnboxedIntPtr;
+ }
+}
+
+bool NativeTypeIsVoid(const AbstractType& result_type) {
+ return result_type.type_class_id() == kFfiVoidCid;
+}
+
+bool NativeTypeIsPointer(const AbstractType& result_type) {
+ switch (result_type.type_class_id()) {
+ case kFfiVoidCid:
+ case kFfiFloatCid:
+ case kFfiDoubleCid:
+ case kFfiInt8Cid:
+ case kFfiInt16Cid:
+ case kFfiInt32Cid:
+ case kFfiUint8Cid:
+ case kFfiUint16Cid:
+ case kFfiUint32Cid:
+ case kFfiInt64Cid:
+ case kFfiUint64Cid:
+ case kFfiIntPtrCid:
+ return false;
+ case kFfiPointerCid:
+ default:
+ return true;
}
}
@@ -120,6 +125,7 @@
on_stack = true;
switch (arg_reps.At(i)) {
case kUnboxedInt32:
+ case kUnboxedUint32:
case kUnboxedInt64:
if (regs_used < CallingConventions::kNumArgRegs) {
data[i] = Location::RegisterLocation(
@@ -131,6 +137,7 @@
on_stack = false;
}
break;
+ case kUnboxedFloat:
case kUnboxedDouble:
if (xmm_regs_used < CallingConventions::kNumXmmArgRegs) {
data[i] = Location::FpuRegisterLocation(
@@ -146,7 +153,6 @@
UNREACHABLE();
}
if (on_stack) {
- // SAMIR_TODO: Is this correct?
data[i] = Location::StackSlot(nth_stack_argument, RSP);
nth_stack_argument++;
}
@@ -154,6 +160,36 @@
return result;
}
+Representation ResultRepresentation(const Function& signature) {
+ AbstractType& arg_type = AbstractType::Handle(signature.result_type());
+ return TypeRepresentation(arg_type);
+}
+
+Location ResultLocation(Representation result_rep) {
+ switch (result_rep) {
+ case kUnboxedInt32:
+ case kUnboxedUint32:
+ case kUnboxedInt64:
+ return Location::RegisterLocation(CallingConventions::kReturnReg);
+ case kUnboxedFloat:
+ case kUnboxedDouble:
+ return Location::FpuRegisterLocation(CallingConventions::kReturnFpuReg);
+ default:
+ UNREACHABLE();
+ }
+}
+
+intptr_t NumStackArguments(const ZoneGrowableArray<Location>& locations) {
+ intptr_t num_arguments = locations.length();
+ intptr_t num_stack_arguments = 0;
+ for (intptr_t i = 0; i < num_arguments; i++) {
+ if (locations.At(i).IsStackSlot()) {
+ num_stack_arguments++;
+ }
+ }
+ return num_stack_arguments;
+}
+
#else
size_t ElementSizeInBytes(intptr_t class_id) {
@@ -164,4 +200,6 @@
} // namespace ffi
+} // namespace compiler
+
} // namespace dart
diff --git a/runtime/vm/compiler/ffi.h b/runtime/vm/compiler/ffi.h
index b66818b..e3eca6f 100644
--- a/runtime/vm/compiler/ffi.h
+++ b/runtime/vm/compiler/ffi.h
@@ -14,26 +14,43 @@
namespace dart {
+namespace compiler {
+
namespace ffi {
-// Native data types sizes in bytes
-
+// Storage size for an FFI type (extends 'ffi.NativeType').
size_t ElementSizeInBytes(intptr_t class_id);
-bool ElementIsSigned(intptr_t class_id);
-
+// Unboxed representation of an FFI type (extends 'ffi.NativeType').
Representation TypeRepresentation(const AbstractType& result_type);
-Representation WordRep();
+// Whether a type which extends 'ffi.NativeType' also extends 'ffi.Pointer'.
+bool NativeTypeIsPointer(const AbstractType& result_type);
+// Whether a type is 'ffi.Void'.
+bool NativeTypeIsVoid(const AbstractType& result_type);
+
+// Unboxed representation of the result of a C signature function.
+Representation ResultRepresentation(const Function& signature);
+
+// Location for the result of a C signature function.
+Location ResultLocation(Representation result_rep);
+
+// Unboxed representations of the arguments to a C signature function.
ZoneGrowableArray<Representation>* ArgumentRepresentations(
const Function& signature);
+// Location for the arguments of a C signature function.
ZoneGrowableArray<Location>* ArgumentLocations(
const ZoneGrowableArray<Representation>& arg_reps);
+// Number of stack slots used in 'locations'.
+intptr_t NumStackArguments(const ZoneGrowableArray<Location>& locations);
+
} // namespace ffi
+} // namespace compiler
+
} // namespace dart
#endif // RUNTIME_VM_COMPILER_FFI_H_
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 83fe857..d134dc1 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -284,8 +284,7 @@
Fragment BaseFlowGraphBuilder::TestAnyTypeArgs(Fragment present,
Fragment absent) {
if (parsed_function_->function().IsClosureFunction()) {
- LocalVariable* closure =
- parsed_function_->node_sequence()->scope()->VariableAt(0);
+ LocalVariable* closure = parsed_function_->ParameterVariable(0);
JoinEntryInstr* complete = BuildJoinEntry();
JoinEntryInstr* present_entry = BuildJoinEntry();
@@ -703,6 +702,12 @@
return Fragment(instr);
}
+Fragment BaseFlowGraphBuilder::LoadClassId() {
+ LoadClassIdInstr* load = new (Z) LoadClassIdInstr(Pop());
+ Push(load);
+ return Fragment(load);
+}
+
} // namespace kernel
} // namespace dart
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 69ff503..fa4ff07 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -265,6 +265,7 @@
Fragment CreateArray();
Fragment InstantiateType(const AbstractType& type);
Fragment InstantiateTypeArguments(const TypeArguments& type_arguments);
+ Fragment LoadClassId();
// Returns true if we are building a graph for inlining of a call site that
// enters the function through the unchecked entry.
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 3853076..f5f3c3a 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -809,8 +809,193 @@
UNIMPLEMENTED(); // TODO(alexmarkov): interpreter
}
- // Default flow graph builder is used to compile native methods.
- UNREACHABLE();
+ ASSERT(function().is_native());
+
+ // TODO(alexmarkov): find a way to avoid code duplication with
+ // FlowGraphBuilder::NativeFunctionBody.
+ const MethodRecognizer::Kind kind =
+ MethodRecognizer::RecognizeKind(function());
+ switch (kind) {
+ case MethodRecognizer::kObjectEquals:
+ ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+ code_ += B->StrictCompare(Token::kEQ_STRICT);
+ break;
+ case MethodRecognizer::kStringBaseLength:
+ case MethodRecognizer::kStringBaseIsEmpty:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::String_length());
+ if (kind == MethodRecognizer::kStringBaseIsEmpty) {
+ code_ += B->IntConstant(0);
+ code_ += B->StrictCompare(Token::kEQ_STRICT);
+ }
+ break;
+ case MethodRecognizer::kGrowableArrayLength:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::GrowableObjectArray_length());
+ break;
+ case MethodRecognizer::kObjectArrayLength:
+ case MethodRecognizer::kImmutableArrayLength:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::Array_length());
+ break;
+ case MethodRecognizer::kTypedDataLength:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::TypedData_length());
+ break;
+ case MethodRecognizer::kClassIDgetID:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadClassId();
+ break;
+ case MethodRecognizer::kGrowableArrayCapacity:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::GrowableObjectArray_data());
+ code_ += B->LoadNativeField(Slot::Array_length());
+ break;
+ case MethodRecognizer::kListFactory: {
+ ASSERT((function().NumParameters() == 2) && !function().IsGeneric() &&
+ function().HasOptionalParameters());
+ ASSERT(scratch_var_ != nullptr);
+ // Generate code that performs:
+ //
+ // factory List<E>([int length]) {
+ // return (:arg_desc.positional_count == 2) ? new _List<E>(length)
+ // : new _GrowableList<E>(0);
+ // }
+ const auto& core_lib = Library::Handle(Z, Library::CoreLibrary());
+
+ TargetEntryInstr *allocate_non_growable, *allocate_growable;
+
+ code_ += B->Drop(); // Drop 'length'.
+ code_ += B->Drop(); // Drop 'type arguments'.
+ code_ += B->LoadArgDescriptor();
+ code_ += B->LoadNativeField(Slot::ArgumentsDescriptor_positional_count());
+ code_ += B->IntConstant(2);
+ code_ +=
+ B->BranchIfStrictEqual(&allocate_non_growable, &allocate_growable);
+
+ JoinEntryInstr* join = B->BuildJoinEntry();
+
+ {
+ const auto& cls = Class::Handle(
+ Z, core_lib.LookupClass(
+ Library::PrivateCoreLibName(Symbols::_List())));
+ ASSERT(!cls.IsNull());
+ const auto& func = Function::ZoneHandle(
+ Z, cls.LookupFactoryAllowPrivate(Symbols::_ListFactory()));
+ ASSERT(!func.IsNull());
+
+ code_ = Fragment(allocate_non_growable);
+ code_ += B->LoadLocal(LocalVariableAt(0));
+ code_ += B->LoadLocal(LocalVariableAt(1));
+ auto* call = new (Z) StaticCallInstr(
+ TokenPosition::kNoSource, func, 0, Array::null_array(),
+ GetArguments(2), *ic_data_array_, B->GetNextDeoptId(),
+ ICData::kStatic);
+ code_ <<= call;
+ B->Push(call);
+ code_ += B->StoreLocal(TokenPosition::kNoSource, scratch_var_);
+ code_ += B->Drop();
+ code_ += B->Goto(join);
+ }
+
+ {
+ const auto& cls = Class::Handle(
+ Z, core_lib.LookupClass(
+ Library::PrivateCoreLibName(Symbols::_GrowableList())));
+ ASSERT(!cls.IsNull());
+ const auto& func = Function::ZoneHandle(
+ Z, cls.LookupFactoryAllowPrivate(Symbols::_GrowableListFactory()));
+ ASSERT(!func.IsNull());
+
+ code_ = Fragment(allocate_growable);
+ code_ += B->LoadLocal(LocalVariableAt(0));
+ code_ += B->IntConstant(0);
+ auto* call = new (Z) StaticCallInstr(
+ TokenPosition::kNoSource, func, 0, Array::null_array(),
+ GetArguments(2), *ic_data_array_, B->GetNextDeoptId(),
+ ICData::kStatic);
+ code_ <<= call;
+ B->Push(call);
+ code_ += B->StoreLocal(TokenPosition::kNoSource, scratch_var_);
+ code_ += B->Drop();
+ code_ += B->Goto(join);
+ }
+
+ code_ = Fragment(join);
+ code_ += B->LoadLocal(scratch_var_);
+ break;
+ }
+ case MethodRecognizer::kObjectArrayAllocate:
+ ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+ code_ += B->CreateArray();
+ break;
+ case MethodRecognizer::kLinkedHashMap_getIndex:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::LinkedHashMap_index());
+ break;
+ case MethodRecognizer::kLinkedHashMap_setIndex:
+ ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+ code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+ Slot::LinkedHashMap_index());
+ code_ += B->NullConstant();
+ break;
+ case MethodRecognizer::kLinkedHashMap_getData:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::LinkedHashMap_data());
+ break;
+ case MethodRecognizer::kLinkedHashMap_setData:
+ ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+ code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+ Slot::LinkedHashMap_data());
+ code_ += B->NullConstant();
+ break;
+ case MethodRecognizer::kLinkedHashMap_getHashMask:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::LinkedHashMap_hash_mask());
+ break;
+ case MethodRecognizer::kLinkedHashMap_setHashMask:
+ ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+ code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+ Slot::LinkedHashMap_hash_mask(),
+ kNoStoreBarrier);
+ code_ += B->NullConstant();
+ break;
+ case MethodRecognizer::kLinkedHashMap_getUsedData:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::LinkedHashMap_used_data());
+ break;
+ case MethodRecognizer::kLinkedHashMap_setUsedData:
+ ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+ code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+ Slot::LinkedHashMap_used_data(),
+ kNoStoreBarrier);
+ code_ += B->NullConstant();
+ break;
+ case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
+ ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+ code_ += B->LoadNativeField(Slot::LinkedHashMap_deleted_keys());
+ break;
+ case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
+ ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+ code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+ Slot::LinkedHashMap_deleted_keys(),
+ kNoStoreBarrier);
+ code_ += B->NullConstant();
+ break;
+ default: {
+ B->InlineBailout("BytecodeFlowGraphBuilder::BuildNativeCall");
+ const auto& name = String::ZoneHandle(Z, function().native_name());
+ const intptr_t num_args =
+ function().NumParameters() + (function().IsGeneric() ? 1 : 0);
+ ArgumentArray arguments = GetArguments(num_args);
+ auto* call =
+ new (Z) NativeCallInstr(&name, &function(), FLAG_link_natives_lazily,
+ function().end_token_pos(), arguments);
+ code_ <<= call;
+ B->Push(call);
+ break;
+ }
+ }
}
void BytecodeFlowGraphBuilder::BuildAllocate() {
@@ -1471,6 +1656,9 @@
return KernelBytecode::DecodeC(instr) > 0;
case KernelBytecode::kEqualsNull:
return true;
+ case KernelBytecode::kNativeCall:
+ return MethodRecognizer::RecognizeKind(function()) ==
+ MethodRecognizer::kListFactory;
default:
return false;
}
@@ -1547,9 +1735,6 @@
}
FlowGraph* BytecodeFlowGraphBuilder::BuildGraph() {
- // Use default flow graph builder for native methods.
- ASSERT(!function().is_native());
-
const Bytecode& bytecode = Bytecode::Handle(Z, function().bytecode());
object_pool_ = bytecode.object_pool();
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.cc b/runtime/vm/compiler/frontend/constant_evaluator.cc
index 6733249..861a19a 100644
--- a/runtime/vm/compiler/frontend/constant_evaluator.cc
+++ b/runtime/vm/compiler/frontend/constant_evaluator.cc
@@ -94,6 +94,14 @@
case kStringConcatenation:
EvaluateStringConcatenation();
break;
+ case kListConcatenation:
+ case kSetConcatenation:
+ case kMapConcatenation:
+ // These only occur inside unevaluated constants, so if we decide to
+ // remove support for late evaluation of environment constants from
+ // dill files in the VM, an implementation here will not be necessary.
+ UNIMPLEMENTED();
+ break;
case kSymbolLiteral:
EvaluateSymbolLiteral();
break;
@@ -466,11 +474,11 @@
ASSERT(IsBuildingFlowGraph());
TokenPosition position = helper_->ReadPosition(); // read position.
- const LocalVariable* this_variable =
- flow_graph_builder_->scopes_->this_variable;
- ASSERT(this_variable->IsConst());
+ const LocalVariable* receiver_variable =
+ flow_graph_builder_->parsed_function_->receiver_var();
+ ASSERT(receiver_variable->IsConst());
const Instance& receiver =
- Instance::Handle(Z, this_variable->ConstValue()->raw());
+ Instance::Handle(Z, receiver_variable->ConstValue()->raw());
ASSERT(!receiver.IsNull());
Class& klass = Class::Handle(Z, active_class_->klass->SuperClass());
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index 00ff453..c1b1dea 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -51,6 +51,8 @@
// Attach the outer environment on each instruction in the callee graph.
ASSERT(call_->env() != NULL);
+ ASSERT(call_->deopt_id() != DeoptId::kNone);
+ const intptr_t outer_deopt_id = call_->deopt_id();
// Scale the edge weights by the call count for the inlined function.
double scale_factor =
static_cast<double>(call_->CallCount()) /
@@ -63,7 +65,8 @@
}
Instruction* instr = block;
if (block->env() != NULL) {
- call_->env()->DeepCopyToOuter(callee_graph->zone(), block);
+ call_->env()->DeepCopyToOuter(callee_graph->zone(), block,
+ outer_deopt_id);
}
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
instr = it.Current();
@@ -71,7 +74,8 @@
// optimizations need deoptimization info for non-deoptable instructions,
// eg, LICM on GOTOs.
if (instr->env() != NULL) {
- call_->env()->DeepCopyToOuter(callee_graph->zone(), instr);
+ call_->env()->DeepCopyToOuter(callee_graph->zone(), instr,
+ outer_deopt_id);
}
}
if (instr->IsGoto()) {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 7e77d3d..95b52d3 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -67,79 +67,18 @@
B->last_used_block_id_, prologue_info);
}
-FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldAccessor(
- LocalVariable* setter_value) {
+void StreamingFlowGraphBuilder::EvaluateConstFieldValue(const Field& field) {
+ ASSERT(field.is_const() && field.IsUninitialized());
+
FieldHelper field_helper(this);
- field_helper.ReadUntilIncluding(FieldHelper::kCanonicalName);
+ field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
+ Tag initializer_tag = ReadTag(); // read first part of initializer.
- const Function& function = parsed_function()->function();
+ ASSERT(initializer_tag == kSomething);
- // Instead of building a dynamic invocation forwarder that checks argument
- // type and then invokes original setter we simply generate the type check
- // and inlined field store. Scope builder takes care of setting correct
- // type check mode in this case.
- const bool is_setter = function.IsDynamicInvocationForwader() ||
- function.IsImplicitSetterFunction();
- const bool is_method = !function.IsStaticFunction();
- Field& field = Field::ZoneHandle(
- Z, H.LookupFieldByKernelField(field_helper.canonical_name_));
-
- B->graph_entry_ =
- new (Z) GraphEntryInstr(*parsed_function(), Compiler::kNoOSRDeoptId);
-
- auto normal_entry = B->BuildFunctionEntry(B->graph_entry_);
- B->graph_entry_->set_normal_entry(normal_entry);
-
- Fragment body(normal_entry);
- if (is_setter) {
- // We only expect to generate a dynamic invocation forwarder if
- // the value needs type check.
- ASSERT(!function.IsDynamicInvocationForwader() ||
- setter_value->needs_type_check());
- if (is_method) {
- body += LoadLocal(scopes()->this_variable);
- }
- body += LoadLocal(setter_value);
- if (I->argument_type_checks() && setter_value->needs_type_check()) {
- body += CheckArgumentType(setter_value, setter_value->type());
- }
- if (is_method) {
- body += flow_graph_builder_->StoreInstanceFieldGuarded(field, false);
- } else {
- body += StoreStaticField(TokenPosition::kNoSource, field);
- }
- body += NullConstant();
- } else if (is_method) {
- body += LoadLocal(scopes()->this_variable);
- body += flow_graph_builder_->LoadField(field);
- } else if (field.is_const()) {
- field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
- Tag initializer_tag = ReadTag(); // read first part of initializer.
-
- // If the parser needs to know the value of an uninitialized constant field
- // it will set the value to the transition sentinel (used to detect circular
- // initialization) and then call the implicit getter. Thus, the getter
- // cannot contain the InitStaticField instruction that normal static getters
- // contain because it would detect spurious circular initialization when it
- // checks for the transition sentinel.
- ASSERT(initializer_tag == kSomething);
- body += Constant(Instance::ZoneHandle(
- Z, constant_evaluator_.EvaluateExpression(ReaderOffset())));
- } else {
- // The field always has an initializer because static fields without
- // initializers are initialized eagerly and do not have implicit getters.
- ASSERT(field.has_initializer());
- body += Constant(field);
- body += flow_graph_builder_->InitStaticField(field);
- body += Constant(field);
- body += LoadStaticField();
- }
- body += Return(TokenPosition::kNoSource);
-
- PrologueInfo prologue_info(-1, -1);
- return new (Z)
- FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
- flow_graph_builder_->last_used_block_id_, prologue_info);
+ Instance& value = Instance::Handle(
+ Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
+ field.SetStaticValue(value);
}
void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
@@ -232,7 +171,7 @@
}
Fragment instructions;
- instructions += LoadLocal(scopes()->this_variable);
+ instructions += LoadLocal(parsed_function()->receiver_var());
instructions += BuildExpression();
instructions += flow_graph_builder_->StoreInstanceFieldGuarded(field, true);
return instructions;
@@ -328,7 +267,7 @@
NameIndex canonical_target =
ReadCanonicalNameReference(); // read target_reference.
- instructions += LoadLocal(scopes()->this_variable);
+ instructions += LoadLocal(parsed_function()->receiver_var());
instructions += PushArgument();
// TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
@@ -355,7 +294,7 @@
NameIndex canonical_target =
ReadCanonicalNameReference(); // read target_reference.
- instructions += LoadLocal(scopes()->this_variable);
+ instructions += LoadLocal(parsed_function()->receiver_var());
instructions += PushArgument();
// TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
@@ -448,162 +387,6 @@
parsed_function()->SetDefaultFunctionTypeArguments(default_types);
}
-Fragment StreamingFlowGraphBuilder::PushAllArguments(PushedArguments* pushed) {
- FunctionNodeHelper function_node_helper(this);
- function_node_helper.SetNext(FunctionNodeHelper::kTypeParameters);
-
- Fragment body;
-
- const intptr_t num_type_params = ReadListLength();
- if (num_type_params > 0) {
- // Skip type arguments.
- for (intptr_t i = 0; i < num_type_params; ++i) {
- TypeParameterHelper helper(this);
- helper.Finish();
- }
-
- body += LoadLocal(parsed_function()->function_type_arguments());
- body += PushArgument();
- pushed->type_args_len = num_type_params;
- }
- function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
- function_node_helper.ReadUntilExcluding(
- FunctionNodeHelper::kPositionalParameters);
-
- // Push receiver.
- body += LoadLocal(scopes()->this_variable);
- body += PushArgument();
-
- // Push positional parameters.
- const intptr_t num_positional_params = ReadListLength();
- for (intptr_t i = 0; i < num_positional_params; ++i) {
- // ith variable offset.
- const intptr_t offset = ReaderOffset();
- SkipVariableDeclaration();
-
- LocalVariable* param = LookupVariable(offset + data_program_offset_);
- body += LoadLocal(param);
- body += PushArgument();
- }
-
- // Push named parameters.
- const intptr_t num_named_params = ReadListLength();
- pushed->argument_names = Array::New(num_named_params, Heap::kOld);
- for (intptr_t i = 0; i < num_named_params; ++i) {
- // ith variable offset.
- const intptr_t offset = ReaderOffset();
- SkipVariableDeclaration();
-
- LocalVariable* param = LookupVariable(offset + data_program_offset_);
- pushed->argument_names.SetAt(i, param->name());
- body += LoadLocal(param);
- body += PushArgument();
- }
-
- pushed->argument_count = num_positional_params + num_named_params + 1;
-
- return body;
-}
-
-FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfDynamicInvocationForwarder() {
- const Function& dart_function = parsed_function()->function();
-
- // The prologue builder needs the default parameter values.
- SetupDefaultParameterValues();
- // BuildDefaultTypeHandling needs default function type arguments.
- ReadDefaultFunctionTypeArguments(dart_function);
-
- B->graph_entry_ = new (Z) GraphEntryInstr(*parsed_function(), B->osr_id_);
-
- auto normal_entry = B->BuildFunctionEntry(B->graph_entry_);
- B->graph_entry_->set_normal_entry(normal_entry);
-
- PrologueInfo prologue_info(-1, -1);
- auto instruction_cursor = B->BuildPrologue(normal_entry, &prologue_info);
-
- Fragment body;
- if (!dart_function.is_native()) {
- body += B->CheckStackOverflowInPrologue(dart_function.token_pos());
- }
-
- ASSERT(parsed_function()->node_sequence()->scope()->num_context_variables() ==
- 0);
-
- FunctionNodeHelper function_node_helper(this);
- function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
- const intptr_t type_parameters_offset = ReaderOffset();
- function_node_helper.ReadUntilExcluding(
- FunctionNodeHelper::kPositionalParameters);
- intptr_t first_parameter_offset = -1;
- {
- AlternativeReadingScope alt(&reader_);
- intptr_t list_length = ReadListLength(); // read number of positionals.
- if (list_length > 0) {
- first_parameter_offset = ReaderOffset() + data_program_offset_;
- }
- }
- USE(first_parameter_offset);
- // Current position: About to read list of positionals.
-
- // Should never build a dynamic invocation forwarder for equality
- // operator.
- ASSERT(dart_function.name() != Symbols::EqualOperator().raw());
-
- // Even if the caller did not pass argument vector we would still
- // call the target with instantiate-to-bounds type arguments.
- body += B->BuildDefaultTypeHandling(dart_function);
-
- String& name = String::Handle(Z, dart_function.name());
- name = Function::DemangleDynamicInvocationForwarderName(name);
- const Class& owner = Class::Handle(Z, dart_function.Owner());
- const Function& target =
- Function::ZoneHandle(Z, owner.LookupDynamicFunction(name));
- ASSERT(!target.IsNull());
-
- // Build argument type checks that complement those that are emitted in the
- // target.
- {
- AlternativeReadingScope alt(&reader_);
- SetOffset(type_parameters_offset);
- B->BuildArgumentTypeChecks(
- TypeChecksToBuild::kCheckNonCovariantTypeParameterBounds, &body, &body,
- nullptr);
- }
-
- // Push all arguments and invoke the original method.
- PushedArguments pushed = {0, 0, Array::ZoneHandle(Z)};
- {
- AlternativeReadingScope alt(&reader_);
- SetOffset(type_parameters_offset);
- body += PushAllArguments(&pushed);
- }
- body += StaticCall(TokenPosition::kNoSource, target, pushed.argument_count,
- pushed.argument_names, ICData::kNoRebind, nullptr,
- pushed.type_args_len);
-
- // Some IL optimization passes assume that result of operator []= invocation
- // is never used, so we drop it and replace with an explicit null constant.
- if (name.raw() == Symbols::AssignIndexToken().raw()) {
- body += Drop();
- body += NullConstant();
- }
-
- body += Return(TokenPosition::kNoSource);
-
- instruction_cursor->LinkTo(body.entry);
-
- GraphEntryInstr* graph_entry = B->graph_entry_;
- // When compiling for OSR, use a depth first search to find the OSR
- // entry and make graph entry jump to it instead of normal entry.
- // Catch entries are always considered reachable, even if they
- // become unreachable after OSR.
- if (B->IsCompiledForOsr()) {
- graph_entry->RelinkToOsrEntry(Z, B->last_used_block_id_ + 1);
- }
- return new (Z) FlowGraph(*parsed_function(), graph_entry,
- B->last_used_block_id_, prologue_info);
-}
-
Fragment StreamingFlowGraphBuilder::DebugStepCheckInPrologue(
const Function& dart_function,
TokenPosition position) {
@@ -616,8 +399,8 @@
const int parameter_count = dart_function.NumParameters();
TokenPosition check_pos = TokenPosition::kNoSource;
if (parameter_count > 0) {
- LocalScope* scope = parsed_function()->node_sequence()->scope();
- const LocalVariable& parameter = *scope->VariableAt(parameter_count - 1);
+ const LocalVariable& parameter =
+ *parsed_function()->ParameterVariable(parameter_count - 1);
check_pos = parameter.token_pos();
}
if (!check_pos.IsDebugPause()) {
@@ -670,8 +453,7 @@
if (dart_function.IsClosureFunction() &&
dart_function.NumParentTypeParameters() > 0) {
- LocalVariable* closure =
- parsed_function()->node_sequence()->scope()->VariableAt(0);
+ LocalVariable* closure = parsed_function()->ParameterVariable(0);
// Function with yield points can not be generic itself but the outer
// function can be.
@@ -801,7 +583,7 @@
const Function& function = pf.function();
for (intptr_t i = 0; i < parameter_count; ++i) {
- LocalVariable* variable = scope->VariableAt(i);
+ LocalVariable* variable = pf.ParameterVariable(i);
if (variable->is_captured()) {
LocalVariable& raw_parameter = *pf.RawParameterVariable(i);
ASSERT((function.HasOptionalParameters() &&
@@ -1143,7 +925,7 @@
SetOffset(kernel_offset);
if ((FLAG_use_bytecode_compiler || FLAG_enable_interpreter) &&
- function.IsBytecodeAllowed(Z) && !function.is_native()) {
+ function.IsBytecodeAllowed(Z)) {
if (!function.HasBytecode()) {
bytecode_metadata_helper_.ReadMetadata(function);
}
@@ -1211,17 +993,22 @@
case RawFunction::kImplicitGetter:
case RawFunction::kImplicitStaticFinalGetter:
case RawFunction::kImplicitSetter: {
- return IsFieldInitializer(function, Z)
- ? BuildGraphOfFieldInitializer()
- : BuildGraphOfFieldAccessor(scopes()->setter_value);
+ if (IsFieldInitializer(function, Z)) {
+ return BuildGraphOfFieldInitializer();
+ }
+ const Field& field = Field::Handle(Z, function.accessor_field());
+ if (field.is_const() && field.IsUninitialized()) {
+ EvaluateConstFieldValue(field);
+ }
+ return B->BuildGraphOfFieldAccessor(function);
}
case RawFunction::kDynamicInvocationForwarder:
- if (PeekTag() == kField) {
- return BuildGraphOfFieldAccessor(scopes()->setter_value);
- } else {
+ if (PeekTag() != kField) {
ReadUntilFunctionNode();
- return BuildGraphOfDynamicInvocationForwarder();
+ SetupDefaultParameterValues();
+ ReadDefaultFunctionTypeArguments(function);
}
+ return B->BuildGraphOfDynamicInvocationForwarder(function);
case RawFunction::kMethodExtractor:
return flow_graph_builder_->BuildGraphOfMethodExtractor(function);
case RawFunction::kNoSuchMethodDispatcher:
@@ -1233,9 +1020,10 @@
SetupDefaultParameterValues();
ReadDefaultFunctionTypeArguments(function);
return flow_graph_builder_->BuildGraphOfImplicitClosureFunction(function);
+ case RawFunction::kFfiTrampoline:
+ return flow_graph_builder_->BuildGraphOfFfiTrampoline(function);
case RawFunction::kSignatureFunction:
case RawFunction::kIrregexpFunction:
- case RawFunction::kFfiTrampoline:
break;
}
UNREACHABLE();
@@ -1299,6 +1087,13 @@
return BuildConditionalExpression(position);
case kStringConcatenation:
return BuildStringConcatenation(position);
+ case kListConcatenation:
+ case kSetConcatenation:
+ case kMapConcatenation:
+ // Collection concatenation operations are removed by the constant
+ // evaluator.
+ UNREACHABLE();
+ break;
case kIsExpression:
return BuildIsExpression(position);
case kAsExpression:
@@ -1331,10 +1126,8 @@
return BuildFunctionExpression();
case kLet:
return BuildLet(position);
- case kBlockExpression: {
- UNIMPLEMENTED();
- break;
- }
+ case kBlockExpression:
+ return BuildBlockExpression();
case kBigIntLiteral:
return BuildBigIntLiteral(position);
case kStringLiteral:
@@ -1477,6 +1270,18 @@
--flow_graph_builder_->try_depth_;
}
+intptr_t StreamingFlowGraphBuilder::block_expression_depth() {
+ return flow_graph_builder_->block_expression_depth_;
+}
+
+void StreamingFlowGraphBuilder::block_expression_depth_inc() {
+ ++flow_graph_builder_->block_expression_depth_;
+}
+
+void StreamingFlowGraphBuilder::block_expression_depth_dec() {
+ --flow_graph_builder_->block_expression_depth_;
+}
+
intptr_t StreamingFlowGraphBuilder::CurrentTryIndex() {
return flow_graph_builder_->CurrentTryIndex();
}
@@ -1831,7 +1636,7 @@
const intptr_t saved_context_depth = B->context_depth_;
const ProgramState state(B->breakable_block_, B->switch_block_,
B->loop_depth_, B->for_in_depth_, B->try_depth_,
- B->catch_depth_);
+ B->catch_depth_, B->block_expression_depth_);
Fragment instructions;
@@ -2368,12 +2173,12 @@
// Populate array containing the actual arguments. Just add [this] here.
instructions += LoadLocal(actuals_array); // array
instructions += IntConstant(num_type_arguments == 0 ? 0 : 1); // index
- instructions += LoadLocal(scopes()->this_variable); // receiver
+ instructions += LoadLocal(parsed_function()->receiver_var()); // receiver
instructions += StoreIndexed(kArrayCid);
instructions += build_rest_of_actuals;
// First argument is receiver.
- instructions += LoadLocal(scopes()->this_variable);
+ instructions += LoadLocal(parsed_function()->receiver_var());
instructions += PushArgument();
// Push the arguments for allocating the invocation mirror:
@@ -2473,7 +2278,7 @@
ASSERT(!klass.IsNull());
ASSERT(!function.IsNull());
- instructions += LoadLocal(scopes()->this_variable);
+ instructions += LoadLocal(parsed_function()->receiver_var());
instructions += PushArgument();
instructions +=
@@ -2530,7 +2335,7 @@
instructions += Drop(); // Drop array
} else {
// receiver
- instructions += LoadLocal(scopes()->this_variable);
+ instructions += LoadLocal(parsed_function()->receiver_var());
instructions += PushArgument();
instructions += BuildExpression(); // read value.
@@ -3126,7 +2931,7 @@
}
// receiver
- instructions += LoadLocal(scopes()->this_variable);
+ instructions += LoadLocal(parsed_function()->receiver_var());
instructions += PushArgument();
Array& argument_names = Array::ZoneHandle(Z);
@@ -3631,7 +3436,7 @@
TokenPosition* position) {
if (position != NULL) *position = TokenPosition::kNoSource;
- return LoadLocal(scopes()->this_variable);
+ return LoadLocal(parsed_function()->receiver_var());
}
Fragment StreamingFlowGraphBuilder::BuildRethrow(TokenPosition* p) {
@@ -3791,6 +3596,24 @@
return instructions;
}
+Fragment StreamingFlowGraphBuilder::BuildBlockExpression() {
+ block_expression_depth_inc();
+ const intptr_t offset = ReaderOffset() - 1; // Include the tag.
+
+ Fragment instructions;
+
+ instructions += EnterScope(offset);
+ const intptr_t list_length = ReadListLength(); // read number of statements.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ instructions += BuildStatement(); // read ith statement.
+ }
+ instructions += BuildExpression(); // read expression (inside scope).
+ instructions += ExitScope(offset);
+
+ block_expression_depth_dec();
+ return instructions;
+}
+
Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral(
TokenPosition* position) {
if (position != NULL) *position = TokenPosition::kNoSource;
@@ -4127,6 +3950,7 @@
}
Fragment StreamingFlowGraphBuilder::BuildWhileStatement() {
+ ASSERT(block_expression_depth() == 0); // no while in block-expr
loop_depth_inc();
const TokenPosition position = ReadPosition(); // read position.
TestFragment condition = TranslateConditionForControl(); // read condition.
@@ -4154,6 +3978,7 @@
}
Fragment StreamingFlowGraphBuilder::BuildDoStatement() {
+ ASSERT(block_expression_depth() == 0); // no do-while in block-expr
loop_depth_inc();
const TokenPosition position = ReadPosition(); // read position.
Fragment body = BuildStatement(); // read body.
@@ -4236,7 +4061,11 @@
body += Goto(join);
Fragment loop(join);
- loop += CheckStackOverflow(position);
+
+ // Avoid OSR point inside block-expressions.
+ // TODO(ajcbik): make sure OSR works inside BE too
+ if (block_expression_depth() == 0) loop += CheckStackOverflow(position);
+
if (condition.entry != nullptr) {
loop <<= condition.entry;
} else {
@@ -4309,7 +4138,11 @@
body += Goto(join);
Fragment loop(join);
- loop += CheckStackOverflow(position);
+
+ // Avoid OSR point inside block-expressions.
+ // TODO(ajcbik): make sure OSR works inside BE too
+ if (block_expression_depth() == 0) loop += CheckStackOverflow(position);
+
loop += condition;
} else {
instructions += condition;
@@ -4614,6 +4447,7 @@
}
Fragment StreamingFlowGraphBuilder::BuildTryCatch() {
+ ASSERT(block_expression_depth() == 0); // no try-catch in block-expr
InlineBailout("kernel::FlowgraphBuilder::VisitTryCatch");
intptr_t try_handler_index = AllocateTryIndex();
@@ -4743,6 +4577,7 @@
}
Fragment StreamingFlowGraphBuilder::BuildTryFinally() {
+ ASSERT(block_expression_depth() == 0); // no try-finally in block-expr
// Note on streaming:
// We only stream this TryFinally if we can stream everything inside it,
// so creating a "TryFinallyBlock" with a kernel binary offset instead of an
@@ -4878,9 +4713,8 @@
// ...
// }
//
- LocalScope* scope = parsed_function()->node_sequence()->scope();
- LocalVariable* exception_var = scope->VariableAt(2);
- LocalVariable* stack_trace_var = scope->VariableAt(3);
+ LocalVariable* exception_var = parsed_function()->ParameterVariable(2);
+ LocalVariable* stack_trace_var = parsed_function()->ParameterVariable(3);
ASSERT(exception_var->name().raw() == Symbols::ExceptionParameter().raw());
ASSERT(stack_trace_var->name().raw() ==
Symbols::StackTraceParameter().raw());
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index b12d4e3..bedc54e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -57,13 +57,12 @@
Thread* thread() const { return flow_graph_builder_->thread_; }
FlowGraph* BuildGraphOfFieldInitializer();
- FlowGraph* BuildGraphOfFieldAccessor(LocalVariable* setter_value);
+ void EvaluateConstFieldValue(const Field& field);
void SetupDefaultParameterValues();
void ReadDefaultFunctionTypeArguments(const Function& function);
Fragment BuildFieldInitializer(NameIndex canonical_name);
Fragment BuildInitializers(const Class& parent_class);
FlowGraph* BuildGraphOfFunction(bool constructor);
- FlowGraph* BuildGraphOfDynamicInvocationForwarder();
Fragment BuildExpression(TokenPosition* position = NULL);
Fragment BuildStatement();
@@ -112,6 +111,9 @@
void catch_depth_dec();
void try_depth_inc();
void try_depth_dec();
+ intptr_t block_expression_depth();
+ void block_expression_depth_inc();
+ void block_expression_depth_dec();
intptr_t CurrentTryIndex();
intptr_t AllocateTryIndex();
LocalVariable* CurrentException();
@@ -193,13 +195,6 @@
bool use_unchecked_entry = false,
const CallSiteAttributesMetadata* call_site_attrs = nullptr);
- struct PushedArguments {
- intptr_t type_args_len;
- intptr_t argument_count;
- Array& argument_names;
- };
- Fragment PushAllArguments(PushedArguments* pushed);
-
Fragment ThrowException(TokenPosition position);
Fragment BooleanNegate();
Fragment TranslateInstantiatedTypeArguments(
@@ -314,6 +309,7 @@
Fragment BuildMapLiteral(bool is_const, TokenPosition* position);
Fragment BuildFunctionExpression();
Fragment BuildLet(TokenPosition* position);
+ Fragment BuildBlockExpression();
Fragment BuildBigIntLiteral(TokenPosition* position);
Fragment BuildStringLiteral(TokenPosition* position);
Fragment BuildIntLiteral(uint8_t payload, TokenPosition* position);
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 58675d6..1a88f1ba 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -447,6 +447,13 @@
ReadPosition(); // read position.
CalculateListOfExpressionsFingerprint(); // read list of expressions.
return;
+ case kListConcatenation:
+ case kSetConcatenation:
+ case kMapConcatenation:
+ // Collection concatenation operations are removed by the constant
+ // evaluator.
+ UNREACHABLE();
+ break;
case kIsExpression:
ReadPosition(); // read position.
CalculateExpressionFingerprint(); // read operand.
@@ -505,10 +512,10 @@
CalculateVariableDeclarationFingerprint(); // read variable declaration.
CalculateExpressionFingerprint(); // read expression.
return;
- case kBlockExpression: {
- UNIMPLEMENTED();
+ case kBlockExpression:
+ CalculateStatementListFingerprint();
+ CalculateExpressionFingerprint(); // read expression.
return;
- }
case kInstantiation:
CalculateExpressionFingerprint(); // read expression.
CalculateListOfDartTypesFingerprint(); // read type arguments.
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 9da71ef..15b989b 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -2,11 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-#include "vm/compiler/aot/precompiler.h"
#include "vm/compiler/frontend/kernel_to_il.h"
+#include "vm/compiler/aot/precompiler.h"
+#include "vm/compiler/backend/locations.h"
#include "vm/compiler/backend/il.h"
#include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/ffi.h"
#include "vm/compiler/frontend/kernel_binary_flowgraph.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/compiler/frontend/prologue_builder.h"
@@ -54,6 +56,7 @@
try_depth_(0),
catch_depth_(0),
for_in_depth_(0),
+ block_expression_depth_(0),
graph_entry_(NULL),
scopes_(NULL),
breakable_block_(NULL),
@@ -137,10 +140,10 @@
ASSERT(function.IsFactory());
#endif
instructions += LoadLocal(scopes_->type_arguments_variable);
- } else if (scopes_->this_variable != NULL &&
+ } else if (parsed_function_->has_receiver_var() &&
active_class_.ClassNumTypeArguments() > 0) {
ASSERT(!parsed_function_->function().IsFactory());
- instructions += LoadLocal(scopes_->this_variable);
+ instructions += LoadLocal(parsed_function_->receiver_var());
instructions += LoadNativeField(
Slot::GetTypeArgumentsSlotFor(thread_, *active_class_.klass));
} else {
@@ -258,9 +261,8 @@
LocalVariable* context_variable = parsed_function_->current_context_var();
if (should_restore_closure_context) {
ASSERT(parsed_function_->function().IsClosureFunction());
- LocalScope* scope = parsed_function_->node_sequence()->scope();
- LocalVariable* closure_parameter = scope->VariableAt(0);
+ LocalVariable* closure_parameter = parsed_function_->ParameterVariable(0);
ASSERT(!closure_parameter->is_captured());
instructions += LoadLocal(closure_parameter);
instructions += LoadNativeField(Slot::Closure_context());
@@ -393,6 +395,25 @@
return Fragment(call);
}
+Fragment FlowGraphBuilder::FfiCall(
+ const Function& signature,
+ const ZoneGrowableArray<Representation>& arg_reps,
+ const ZoneGrowableArray<Location>& arg_locs) {
+ Fragment body;
+
+ FfiCallInstr* call =
+ new (Z) FfiCallInstr(Z, GetNextDeoptId(), signature, arg_reps, arg_locs);
+
+ for (intptr_t i = call->InputCount() - 1; i >= 0; --i) {
+ call->SetInputAt(i, Pop());
+ }
+
+ Push(call);
+ body <<= call;
+
+ return body;
+}
+
Fragment FlowGraphBuilder::RethrowException(TokenPosition position,
int catch_try_index) {
Fragment instructions;
@@ -410,12 +431,6 @@
return instructions;
}
-Fragment FlowGraphBuilder::LoadClassId() {
- LoadClassIdInstr* load = new (Z) LoadClassIdInstr(Pop());
- Push(load);
- return Fragment(load);
-}
-
Fragment FlowGraphBuilder::LoadLocal(LocalVariable* variable) {
if (variable->is_captured()) {
Fragment instructions;
@@ -733,14 +748,73 @@
const MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
bool omit_result_type_check = true;
switch (kind) {
+ case MethodRecognizer::kTypedData_ByteDataView_factory:
+ body += BuildTypedDataViewFactoryConstructor(function, kByteDataViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Int8ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(function,
+ kTypedDataInt8ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Uint8ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(function,
+ kTypedDataUint8ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Uint8ClampedArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(
+ function, kTypedDataUint8ClampedArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Int16ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(function,
+ kTypedDataInt16ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Uint16ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(
+ function, kTypedDataUint16ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Int32ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(function,
+ kTypedDataInt32ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Uint32ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(
+ function, kTypedDataUint32ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Int64ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(function,
+ kTypedDataInt64ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Uint64ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(
+ function, kTypedDataUint64ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Float32ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(
+ function, kTypedDataFloat32ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Float64ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(
+ function, kTypedDataFloat64ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Float32x4ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(
+ function, kTypedDataFloat32x4ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Int32x4ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(
+ function, kTypedDataInt32x4ArrayViewCid);
+ break;
+ case MethodRecognizer::kTypedData_Float64x2ArrayView_factory:
+ body += BuildTypedDataViewFactoryConstructor(
+ function, kTypedDataFloat64x2ArrayViewCid);
+ break;
case MethodRecognizer::kObjectEquals:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadLocal(first_parameter);
body += StrictCompare(Token::kEQ_STRICT);
break;
case MethodRecognizer::kStringBaseLength:
case MethodRecognizer::kStringBaseIsEmpty:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::String_length());
if (kind == MethodRecognizer::kStringBaseIsEmpty) {
body += IntConstant(0);
@@ -748,24 +822,39 @@
}
break;
case MethodRecognizer::kGrowableArrayLength:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::GrowableObjectArray_length());
break;
case MethodRecognizer::kObjectArrayLength:
case MethodRecognizer::kImmutableArrayLength:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::Array_length());
break;
case MethodRecognizer::kTypedDataLength:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::TypedData_length());
break;
+ case MethodRecognizer::kByteDataViewLength:
+ case MethodRecognizer::kTypedDataViewLength:
+ body += LoadLocal(parsed_function_->receiver_var());
+ body += LoadNativeField(Slot::TypedDataView_length());
+ break;
+ case MethodRecognizer::kByteDataViewOffsetInBytes:
+ case MethodRecognizer::kTypedDataViewOffsetInBytes:
+ body += LoadLocal(parsed_function_->receiver_var());
+ body += LoadNativeField(Slot::TypedDataView_offset_in_bytes());
+ break;
+ case MethodRecognizer::kByteDataViewTypedData:
+ case MethodRecognizer::kTypedDataViewTypedData:
+ body += LoadLocal(parsed_function_->receiver_var());
+ body += LoadNativeField(Slot::TypedDataView_data());
+ break;
case MethodRecognizer::kClassIDgetID:
body += LoadLocal(first_parameter);
body += LoadClassId();
break;
case MethodRecognizer::kGrowableArrayCapacity:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::GrowableObjectArray_data());
body += LoadNativeField(Slot::Array_length());
break;
@@ -839,33 +928,33 @@
body += CreateArray();
break;
case MethodRecognizer::kLinkedHashMap_getIndex:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::LinkedHashMap_index());
break;
case MethodRecognizer::kLinkedHashMap_setIndex:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadLocal(first_parameter);
body += StoreInstanceField(TokenPosition::kNoSource,
Slot::LinkedHashMap_index());
body += NullConstant();
break;
case MethodRecognizer::kLinkedHashMap_getData:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::LinkedHashMap_data());
break;
case MethodRecognizer::kLinkedHashMap_setData:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadLocal(first_parameter);
body += StoreInstanceField(TokenPosition::kNoSource,
Slot::LinkedHashMap_data());
body += NullConstant();
break;
case MethodRecognizer::kLinkedHashMap_getHashMask:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::LinkedHashMap_hash_mask());
break;
case MethodRecognizer::kLinkedHashMap_setHashMask:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadLocal(first_parameter);
body +=
StoreInstanceField(TokenPosition::kNoSource,
@@ -873,11 +962,11 @@
body += NullConstant();
break;
case MethodRecognizer::kLinkedHashMap_getUsedData:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::LinkedHashMap_used_data());
break;
case MethodRecognizer::kLinkedHashMap_setUsedData:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadLocal(first_parameter);
body +=
StoreInstanceField(TokenPosition::kNoSource,
@@ -885,11 +974,11 @@
body += NullConstant();
break;
case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadNativeField(Slot::LinkedHashMap_deleted_keys());
break;
case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
- body += LoadLocal(scopes_->this_variable);
+ body += LoadLocal(parsed_function_->receiver_var());
body += LoadLocal(first_parameter);
body += StoreInstanceField(TokenPosition::kNoSource,
Slot::LinkedHashMap_deleted_keys(),
@@ -915,24 +1004,55 @@
return body + Return(TokenPosition::kNoSource, omit_result_type_check);
}
-static const LocalScope* MakeImplicitClosureScope(Zone* Z,
- const Function& function) {
- Class& klass = Class::Handle(Z, function.Owner());
+Fragment FlowGraphBuilder::BuildTypedDataViewFactoryConstructor(
+ const Function& function,
+ classid_t cid) {
+ auto token_pos = function.token_pos();
+ auto class_table = Thread::Current()->isolate()->class_table();
+
+ ASSERT(class_table->HasValidClassAt(cid));
+ const auto& view_class = Class::ZoneHandle(H.zone(), class_table->At(cid));
+
+ LocalVariable* typed_data = parsed_function_->RawParameterVariable(1);
+ LocalVariable* offset_in_bytes = parsed_function_->RawParameterVariable(2);
+ LocalVariable* length = parsed_function_->RawParameterVariable(3);
+
+ Fragment body;
+
+ body += AllocateObject(token_pos, view_class, /*arg_count=*/0);
+ LocalVariable* view_object = MakeTemporary();
+
+ body += LoadLocal(view_object);
+ body += LoadLocal(typed_data);
+ body += StoreInstanceField(token_pos, Slot::TypedDataView_data());
+
+ body += LoadLocal(view_object);
+ body += LoadLocal(offset_in_bytes);
+ body += StoreInstanceField(token_pos, Slot::TypedDataView_offset_in_bytes());
+
+ body += LoadLocal(view_object);
+ body += LoadLocal(length);
+ body += StoreInstanceField(token_pos, Slot::TypedDataView_length());
+
+ return body;
+}
+
+static const LocalScope* MakeImplicitClosureScope(Zone* Z, const Class& klass) {
ASSERT(!klass.IsNull());
// Note that if klass is _Closure, DeclarationType will be _Closure,
// and not the signature type.
Type& klass_type = Type::ZoneHandle(Z, klass.DeclarationType());
- LocalVariable* this_variable = new (Z)
+ LocalVariable* receiver_variable = new (Z)
LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::This(), klass_type, /*param_type=*/nullptr);
- this_variable->set_is_captured();
- // this_variable->set_is_final();
+ receiver_variable->set_is_captured();
+ // receiver_variable->set_is_final();
LocalScope* scope = new (Z) LocalScope(NULL, 0, 0);
scope->set_context_level(0);
- scope->AddVariable(this_variable);
- scope->AddContextVariable(this_variable);
+ scope->AddVariable(receiver_variable);
+ scope->AddContextVariable(receiver_variable);
return scope;
}
@@ -959,7 +1079,7 @@
// Allocate a context that closes over `this`.
// Note: this must be kept in sync with ScopeBuilder::BuildScopes.
const LocalScope* implicit_closure_scope =
- MakeImplicitClosureScope(Z, target);
+ MakeImplicitClosureScope(Z, Class::Handle(Z, target.Owner()));
fragment += AllocateContext(implicit_closure_scope->context_variables());
LocalVariable* context = MakeTemporary();
@@ -982,7 +1102,7 @@
// The context is on top of the operand stack. Store `this`. The context
// doesn't need a parent pointer because it doesn't close over anything
// else.
- fragment += LoadLocal(scopes_->this_variable);
+ fragment += LoadLocal(parsed_function_->receiver_var());
fragment += StoreInstanceField(
TokenPosition::kNoSource,
Slot::GetContextVariableSlotFor(
@@ -1181,8 +1301,7 @@
// check them again at the call-site.
if (dart_function.IsClosureFunction() && !check_bounds.is_empty() &&
FLAG_eliminate_type_checks) {
- LocalVariable* closure =
- parsed_function_->node_sequence()->scope()->VariableAt(0);
+ LocalVariable* closure = parsed_function_->ParameterVariable(0);
*implicit_checks += TestDelayedTypeArgs(closure, /*present=*/{},
/*absent=*/check_bounds);
} else {
@@ -1192,8 +1311,7 @@
const intptr_t num_params = dart_function.NumParameters();
for (intptr_t i = dart_function.NumImplicitParameters(); i < num_params;
++i) {
- LocalVariable* param =
- parsed_function_->node_sequence()->scope()->VariableAt(i);
+ LocalVariable* param = parsed_function_->ParameterVariable(i);
if (!param->needs_type_check()) {
continue;
}
@@ -1242,6 +1360,34 @@
return instruction_cursor;
}
+RawArray* FlowGraphBuilder::GetOptionalParameterNames(
+ const Function& function) {
+ if (!function.HasOptionalNamedParameters()) {
+ return Array::null();
+ }
+
+ const intptr_t num_fixed_params = function.num_fixed_parameters();
+ const intptr_t num_opt_params = function.NumOptionalNamedParameters();
+ const auto& names = Array::Handle(Z, Array::New(num_opt_params, Heap::kOld));
+ auto& name = String::Handle(Z);
+ for (intptr_t i = 0; i < num_opt_params; ++i) {
+ name = function.ParameterNameAt(num_fixed_params + i);
+ names.SetAt(i, name);
+ }
+ return names.raw();
+}
+
+Fragment FlowGraphBuilder::PushExplicitParameters(const Function& function) {
+ Fragment instructions;
+ for (intptr_t i = function.NumImplicitParameters(),
+ n = function.NumParameters();
+ i < n; ++i) {
+ instructions += LoadLocal(parsed_function_->ParameterVariable(i));
+ instructions += PushArgument();
+ }
+ return instructions;
+}
+
FlowGraph* FlowGraphBuilder::BuildGraphOfMethodExtractor(
const Function& method) {
// A method extractor is the implicit getter for a method.
@@ -1299,8 +1445,7 @@
// The receiver is the first argument to noSuchMethod, and it is the first
// argument passed to the dispatcher function.
- LocalScope* scope = parsed_function_->node_sequence()->scope();
- body += LoadLocal(scope->VariableAt(0));
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
body += PushArgument();
// The second argument to noSuchMethod is an invocation mirror. Push the
@@ -1330,7 +1475,7 @@
for (intptr_t i = 0; i < descriptor.PositionalCount(); ++i) {
body += LoadLocal(array);
body += IntConstant(receiver_index + i);
- body += LoadLocal(scope->VariableAt(i));
+ body += LoadLocal(parsed_function_->ParameterVariable(i));
body += StoreIndexed(kArrayCid);
}
String& name = String::Handle(Z);
@@ -1340,7 +1485,7 @@
name = Symbols::New(H.thread(), name);
body += LoadLocal(array);
body += IntConstant(receiver_index + descriptor.PositionAt(i));
- body += LoadLocal(scope->VariableAt(parameter_index));
+ body += LoadLocal(parsed_function_->ParameterVariable(parameter_index));
body += StoreIndexed(kArrayCid);
}
body += PushArgument();
@@ -1432,8 +1577,6 @@
Fragment body(instruction_cursor);
body += CheckStackOverflowInPrologue(function.token_pos());
- LocalScope* scope = parsed_function_->node_sequence()->scope();
-
if (descriptor.TypeArgsLen() > 0) {
LocalVariable* type_args = parsed_function_->function_type_arguments();
ASSERT(type_args != NULL);
@@ -1443,13 +1586,13 @@
LocalVariable* closure = NULL;
if (is_closure_call) {
- closure = scope->VariableAt(0);
+ closure = parsed_function_->ParameterVariable(0);
// The closure itself is the first argument.
body += LoadLocal(closure);
} else {
// Invoke the getter to get the field value.
- body += LoadLocal(scope->VariableAt(0));
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
body += PushArgument();
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgsChecked = 1;
@@ -1463,7 +1606,7 @@
// Push all arguments onto the stack.
intptr_t pos = 1;
for (; pos < descriptor.Count(); pos++) {
- body += LoadLocal(scope->VariableAt(pos));
+ body += LoadLocal(parsed_function_->ParameterVariable(pos));
body += PushArgument();
}
@@ -1513,14 +1656,14 @@
body += LoadArgDescriptor();
body += LoadNativeField(Slot::ArgumentsDescriptor_count());
body += LoadLocal(parsed_function_->current_context_var());
- body += LoadNativeField(
- Slot::GetContextVariableSlotFor(thread_, *scopes_->this_variable));
+ body += LoadNativeField(Slot::GetContextVariableSlotFor(
+ thread_, *parsed_function_->receiver_var()));
body += StoreFpRelativeSlot(
kWordSize * compiler::target::frame_layout.param_end_from_fp);
} else {
body += LoadLocal(parsed_function_->current_context_var());
- body += LoadNativeField(
- Slot::GetContextVariableSlotFor(thread_, *scopes_->this_variable));
+ body += LoadNativeField(Slot::GetContextVariableSlotFor(
+ thread_, *parsed_function_->receiver_var()));
body += StoreFpRelativeSlot(
kWordSize * (compiler::target::frame_layout.param_end_from_fp +
function.NumParameters()));
@@ -1655,12 +1798,11 @@
body += Constant(type);
} else {
body += LoadLocal(parsed_function_->current_context_var());
- body += LoadNativeField(
- Slot::GetContextVariableSlotFor(thread_, *scopes_->this_variable));
+ body += LoadNativeField(Slot::GetContextVariableSlotFor(
+ thread_, *parsed_function_->receiver_var()));
}
} else {
- LocalScope* scope = parsed_function_->node_sequence()->scope();
- body += LoadLocal(scope->VariableAt(0));
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
}
body += PushArgument();
@@ -1705,8 +1847,7 @@
// Push the number of delayed type arguments.
if (function.IsClosureFunction()) {
- LocalVariable* closure =
- parsed_function_->node_sequence()->scope()->VariableAt(0);
+ LocalVariable* closure = parsed_function_->ParameterVariable(0);
Fragment then;
then += IntConstant(function.NumTypeParameters());
then += StoreLocal(TokenPosition::kNoSource, argument_count_var);
@@ -2000,50 +2141,28 @@
body += PushArgument();
}
- // Load all the arguments.
- auto scope = parsed_function_->node_sequence()->scope();
-
+ // Push receiver.
if (!target.is_static()) {
// The context has a fixed shape: a single variable which is the
// closed-over receiver.
- body += LoadLocal(scope->VariableAt(0));
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
body += LoadNativeField(Slot::Closure_context());
- body += LoadNativeField(
- Slot::GetContextVariableSlotFor(thread_, *scopes_->this_variable));
+ body += LoadNativeField(Slot::GetContextVariableSlotFor(
+ thread_, *parsed_function_->receiver_var()));
body += PushArgument();
}
- // Positional.
- intptr_t arg_index = function.NumImplicitParameters();
- const intptr_t named_argument_count = function.NumOptionalNamedParameters();
- const intptr_t positional_argument_count = function.NumParameters() -
- function.NumImplicitParameters() -
- named_argument_count;
- for (intptr_t i = 0; i < positional_argument_count; ++i, ++arg_index) {
- body += LoadLocal(scope->VariableAt(arg_index)); // ith variable offset.
- body += PushArgument();
- }
+ body += PushExplicitParameters(function);
- // Named.
- Array& argument_names = Array::ZoneHandle(Z);
- if (named_argument_count > 0) {
- argument_names = Array::New(named_argument_count, Heap::kOld);
- String& name = String::Handle(Z);
- for (intptr_t i = 0; i < named_argument_count; ++i, ++arg_index) {
- body += LoadLocal(scope->VariableAt(arg_index));
- body += PushArgument();
-
- name = function.ParameterNameAt(arg_index);
- argument_names.SetAt(i, name);
- }
- }
-
- // Forward them to the parent.
- intptr_t argument_count = positional_argument_count + named_argument_count;
- if (!parent.is_static()) {
- ++argument_count;
- }
+ // Forward parameters to the target.
+ intptr_t argument_count = function.NumParameters() -
+ function.NumImplicitParameters() +
+ (target.is_static() ? 0 : 1);
ASSERT(argument_count == target.NumParameters());
+
+ Array& argument_names =
+ Array::ZoneHandle(Z, GetOptionalParameterNames(function));
+
body += StaticCall(TokenPosition::kNoSource, target, argument_count,
argument_names, ICData::kNoRebind,
/* result_type = */ NULL, type_args_len);
@@ -2055,7 +2174,7 @@
FunctionEntryInstr* extra_entry = nullptr;
if (function.MayHaveUncheckedEntryPoint(I)) {
// The prologue for a closure will always have context handling (e.g.
- // setting up the 'this_variable'), but we don't need it on the unchecked
+ // setting up the receiver variable), but we don't need it on the unchecked
// entry because the only time we reference this is for loading the
// receiver, which we fetch directly from the context.
if (PrologueBuilder::PrologueSkippableOnUncheckedEntry(function)) {
@@ -2091,6 +2210,344 @@
prologue_info);
}
+FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
+ const Function& function) {
+ ASSERT(function.IsImplicitGetterOrSetter() ||
+ function.IsDynamicInvocationForwarder());
+
+ // Instead of building a dynamic invocation forwarder that checks argument
+ // type and then invokes original setter we simply generate the type check
+ // and inlined field store. Scope builder takes care of setting correct
+ // type check mode in this case.
+ const bool is_setter = function.IsDynamicInvocationForwarder() ||
+ function.IsImplicitSetterFunction();
+ const bool is_method = !function.IsStaticFunction();
+
+ Field& field = Field::ZoneHandle(Z, function.accessor_field());
+
+ graph_entry_ =
+ new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
+
+ auto normal_entry = BuildFunctionEntry(graph_entry_);
+ graph_entry_->set_normal_entry(normal_entry);
+
+ Fragment body(normal_entry);
+ if (is_setter) {
+ LocalVariable* setter_value =
+ parsed_function_->ParameterVariable(is_method ? 1 : 0);
+
+ // We only expect to generate a dynamic invocation forwarder if
+ // the value needs type check.
+ ASSERT(!function.IsDynamicInvocationForwarder() ||
+ setter_value->needs_type_check());
+ if (is_method) {
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
+ }
+ body += LoadLocal(setter_value);
+ if (I->argument_type_checks() && setter_value->needs_type_check()) {
+ body += CheckAssignable(setter_value->type(), setter_value->name(),
+ AssertAssignableInstr::kParameterCheck);
+ }
+ if (is_method) {
+ body += StoreInstanceFieldGuarded(field, false);
+ } else {
+ body += StoreStaticField(TokenPosition::kNoSource, field);
+ }
+ body += NullConstant();
+ } else if (is_method) {
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
+ body += LoadField(field);
+ } else if (field.is_const()) {
+ // If the parser needs to know the value of an uninitialized constant field
+ // it will set the value to the transition sentinel (used to detect circular
+ // initialization) and then call the implicit getter. Thus, the getter
+ // cannot contain the InitStaticField instruction that normal static getters
+ // contain because it would detect spurious circular initialization when it
+ // checks for the transition sentinel.
+ ASSERT(!field.IsUninitialized());
+ body += Constant(Instance::ZoneHandle(Z, field.StaticValue()));
+ } else {
+ // The field always has an initializer because static fields without
+ // initializers are initialized eagerly and do not have implicit getters.
+ ASSERT(field.has_initializer());
+ body += Constant(field);
+ body += InitStaticField(field);
+ body += Constant(field);
+ body += LoadStaticField();
+ }
+ body += Return(TokenPosition::kNoSource);
+
+ PrologueInfo prologue_info(-1, -1);
+ return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
+ prologue_info);
+}
+
+FlowGraph* FlowGraphBuilder::BuildGraphOfDynamicInvocationForwarder(
+ const Function& function) {
+ auto& name = String::Handle(Z, function.name());
+ name = Function::DemangleDynamicInvocationForwarderName(name);
+ const auto& owner = Class::Handle(Z, function.Owner());
+ const auto& target =
+ Function::ZoneHandle(Z, owner.LookupDynamicFunction(name));
+ ASSERT(!target.IsNull());
+ ASSERT(!target.IsImplicitGetterFunction());
+
+ if (target.IsImplicitSetterFunction()) {
+ return BuildGraphOfFieldAccessor(function);
+ }
+
+ graph_entry_ = new (Z) GraphEntryInstr(*parsed_function_, osr_id_);
+
+ auto normal_entry = BuildFunctionEntry(graph_entry_);
+ graph_entry_->set_normal_entry(normal_entry);
+
+ PrologueInfo prologue_info(-1, -1);
+ auto instruction_cursor = BuildPrologue(normal_entry, &prologue_info);
+
+ Fragment body;
+ if (!function.is_native()) {
+ body += CheckStackOverflowInPrologue(function.token_pos());
+ }
+
+ ASSERT(parsed_function_->node_sequence()->scope()->num_context_variables() ==
+ 0);
+
+ // Should never build a dynamic invocation forwarder for equality
+ // operator.
+ ASSERT(function.name() != Symbols::EqualOperator().raw());
+
+ // Even if the caller did not pass argument vector we would still
+ // call the target with instantiate-to-bounds type arguments.
+ body += BuildDefaultTypeHandling(function);
+
+ // Build argument type checks that complement those that are emitted in the
+ // target.
+ BuildArgumentTypeChecks(
+ TypeChecksToBuild::kCheckNonCovariantTypeParameterBounds, &body, &body,
+ nullptr);
+
+ // Push all arguments and invoke the original method.
+
+ intptr_t type_args_len = 0;
+ if (function.IsGeneric()) {
+ type_args_len = function.NumTypeParameters();
+ ASSERT(parsed_function_->function_type_arguments() != nullptr);
+ body += LoadLocal(parsed_function_->function_type_arguments());
+ body += PushArgument();
+ }
+
+ // Push receiver.
+ ASSERT(function.NumImplicitParameters() == 1);
+ body += LoadLocal(parsed_function_->receiver_var());
+ body += PushArgument();
+
+ body += PushExplicitParameters(function);
+
+ const intptr_t argument_count = function.NumParameters();
+ const auto& argument_names =
+ Array::ZoneHandle(Z, GetOptionalParameterNames(function));
+
+ body += StaticCall(TokenPosition::kNoSource, target, argument_count,
+ argument_names, ICData::kNoRebind, nullptr, type_args_len);
+
+ // Later optimization passes assume that result of a x.[]=(...) call is not
+ // used. We must guarantee this invariant because violation will lead to an
+ // illegal IL once we replace x.[]=(...) with a sequence that does not
+ // actually produce any value. See http://dartbug.com/29135 for more details.
+ if (name.raw() == Symbols::AssignIndexToken().raw()) {
+ body += Drop();
+ body += NullConstant();
+ }
+
+ body += Return(TokenPosition::kNoSource);
+
+ instruction_cursor->LinkTo(body.entry);
+
+ // When compiling for OSR, use a depth first search to find the OSR
+ // entry and make graph entry jump to it instead of normal entry.
+ // Catch entries are always considered reachable, even if they
+ // become unreachable after OSR.
+ if (IsCompiledForOsr()) {
+ graph_entry_->RelinkToOsrEntry(Z, last_used_block_id_ + 1);
+ }
+ return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
+ prologue_info);
+}
+
+Fragment FlowGraphBuilder::UnboxTruncate(Representation to) {
+ auto* unbox = UnboxInstr::Create(to, Pop(), DeoptId::kNone,
+ Instruction::kNotSpeculative);
+ Push(unbox);
+ return Fragment(unbox);
+}
+
+Fragment FlowGraphBuilder::LoadAddressFromFfiPointer() {
+ Fragment test;
+ TargetEntryInstr* null_entry;
+ TargetEntryInstr* not_null_entry;
+ JoinEntryInstr* join = BuildJoinEntry();
+
+ LocalVariable* result = parsed_function_->expression_temp_var();
+
+ LocalVariable* pointer = MakeTemporary();
+ test += LoadLocal(pointer);
+ test += BranchIfNull(&null_entry, ¬_null_entry);
+
+ Fragment load_0(null_entry);
+ load_0 += IntConstant(0);
+ load_0 += StoreLocal(TokenPosition::kNoSource, result);
+ load_0 += Drop();
+ load_0 += Goto(join);
+
+ Fragment unbox(not_null_entry);
+ unbox += LoadLocal(pointer);
+ unbox += LoadNativeField(Slot::Pointer_c_memory_address());
+ unbox += StoreLocal(TokenPosition::kNoSource, result);
+ unbox += Drop();
+ unbox += Goto(join);
+
+ Fragment done{test.entry, join};
+ done += Drop();
+ done += LoadLocal(result);
+
+ return done;
+}
+
+Fragment FlowGraphBuilder::Box(Representation from) {
+ BoxInstr* box = BoxInstr::Create(from, Pop());
+ Push(box);
+ return Fragment(box);
+}
+
+Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) {
+ Fragment test;
+ TargetEntryInstr* null_entry;
+ TargetEntryInstr* not_null_entry;
+ JoinEntryInstr* join = BuildJoinEntry();
+
+ LocalVariable* address = MakeTemporary();
+ LocalVariable* result = parsed_function_->expression_temp_var();
+
+ test += LoadLocal(address);
+ test += IntConstant(0);
+ test += BranchIfEqual(&null_entry, ¬_null_entry);
+
+ // If the result is 0, we return null because "0 means null".
+ Fragment load_null(null_entry);
+ {
+ load_null += NullConstant();
+ load_null += StoreLocal(TokenPosition::kNoSource, result);
+ load_null += Drop();
+ load_null += Goto(join);
+ }
+
+ Fragment box(not_null_entry);
+ {
+ Class& result_class = Class::ZoneHandle(Z, result_type.type_class());
+ TypeArguments& args = TypeArguments::ZoneHandle(Z, result_type.arguments());
+
+ // A kernel transform for FFI in the front-end ensures that type parameters
+ // do not appear in the type arguments to a any Pointer classes in an FFI
+ // signature.
+ ASSERT(args.IsNull() || args.IsInstantiated());
+
+ box += Constant(args);
+ box += PushArgument();
+ box += AllocateObject(TokenPosition::kNoSource, result_class, 1);
+ LocalVariable* pointer = MakeTemporary();
+ box += LoadLocal(pointer);
+ box += LoadLocal(address);
+ box += StoreInstanceField(TokenPosition::kNoSource,
+ Slot::Pointer_c_memory_address());
+ box += StoreLocal(TokenPosition::kNoSource, result);
+ box += Drop();
+ box += Goto(join);
+ }
+
+ Fragment rest(test.entry, join);
+ rest += Drop();
+ rest += LoadLocal(result);
+
+ return rest;
+}
+
+FlowGraph* FlowGraphBuilder::BuildGraphOfFfiTrampoline(
+ const Function& function) {
+#if !defined(TARGET_ARCH_X64)
+ UNREACHABLE();
+#else
+ graph_entry_ =
+ new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
+
+ auto normal_entry = BuildFunctionEntry(graph_entry_);
+ graph_entry_->set_normal_entry(normal_entry);
+
+ PrologueInfo prologue_info(-1, -1);
+
+ BlockEntryInstr* instruction_cursor =
+ BuildPrologue(normal_entry, &prologue_info);
+
+ Fragment body(instruction_cursor);
+ body += CheckStackOverflowInPrologue(function.token_pos());
+
+ const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature());
+ const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature);
+ const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps);
+
+ BuildArgumentTypeChecks(TypeChecksToBuild::kCheckAllTypeParameterBounds,
+ &body, &body, &body);
+
+ // Unbox and push the arguments.
+ AbstractType& ffi_type = AbstractType::Handle(Z);
+ for (intptr_t pos = 1; pos < function.num_fixed_parameters(); pos++) {
+ body += LoadLocal(parsed_function_->ParameterVariable(pos));
+ ffi_type = signature.ParameterTypeAt(pos);
+
+ // Check for 'null'. Only ffi.Pointers are allowed to be null.
+ if (!compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+ body += LoadLocal(parsed_function_->ParameterVariable(pos));
+ body <<=
+ new (Z) CheckNullInstr(Pop(), String::ZoneHandle(Z, function.name()),
+ GetNextDeoptId(), TokenPosition::kNoSource);
+ }
+
+ if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+ body += LoadAddressFromFfiPointer();
+ body += UnboxTruncate(kUnboxedIntPtr);
+ } else {
+ body += UnboxTruncate(arg_reps[pos - 1]);
+ }
+ }
+
+ // Push the function pointer, which is stored (boxed) in the first slot of the
+ // context.
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
+ body += LoadNativeField(Slot::Closure_context());
+ body += LoadNativeField(Slot::GetContextVariableSlotFor(
+ thread_, *MakeImplicitClosureScope(
+ Z, Class::Handle(I->object_store()->ffi_pointer_class()))
+ ->context_variables()[0]));
+ body += UnboxTruncate(kUnboxedIntPtr);
+ body += FfiCall(signature, arg_reps, arg_locs);
+
+ ffi_type = signature.result_type();
+ if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+ body += Box(kUnboxedIntPtr);
+ body += FfiPointerFromAddress(Type::Cast(ffi_type));
+ } else if (compiler::ffi::NativeTypeIsVoid(ffi_type)) {
+ body += Drop();
+ body += NullConstant();
+ } else {
+ body += Box(compiler::ffi::ResultRepresentation(signature));
+ }
+
+ body += Return(TokenPosition::kNoSource);
+
+ return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
+ prologue_info);
+#endif
+}
+
void FlowGraphBuilder::SetCurrentTryCatchBlock(TryCatchBlock* try_catch_block) {
try_catch_block_ = try_catch_block;
SetCurrentTryIndex(try_catch_block == nullptr ? kInvalidTryIndex
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index a2cb7ca..1e76f9a 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -91,13 +91,23 @@
BlockEntryInstr* BuildPrologue(BlockEntryInstr* normal_entry,
PrologueInfo* prologue_info);
+ // Return names of optional named parameters of [function].
+ RawArray* GetOptionalParameterNames(const Function& function);
+
+ // Generate fragment which pushes all explicit parameters of [function].
+ Fragment PushExplicitParameters(const Function& function);
+
FlowGraph* BuildGraphOfMethodExtractor(const Function& method);
FlowGraph* BuildGraphOfNoSuchMethodDispatcher(const Function& function);
FlowGraph* BuildGraphOfInvokeFieldDispatcher(const Function& function);
+ FlowGraph* BuildGraphOfFfiTrampoline(const Function& function);
Fragment NativeFunctionBody(const Function& function,
LocalVariable* first_parameter);
+ Fragment BuildTypedDataViewFactoryConstructor(const Function& function,
+ classid_t cid);
+
Fragment EnterScope(intptr_t kernel_offset,
const LocalScope** scope = nullptr);
Fragment ExitScope(intptr_t kernel_offset);
@@ -142,9 +152,11 @@
intptr_t argument_count,
const Array& argument_names,
bool use_unchecked_entry = false);
+ Fragment FfiCall(const Function& signature,
+ const ZoneGrowableArray<Representation>& arg_reps,
+ const ZoneGrowableArray<Location>& arg_locs);
Fragment RethrowException(TokenPosition position, int catch_try_index);
- Fragment LoadClassId();
Fragment LoadLocal(LocalVariable* variable);
Fragment InitStaticField(const Field& field);
Fragment NativeCall(const String* name, const Function* function);
@@ -198,6 +210,25 @@
bool NeedsDebugStepCheck(Value* value, TokenPosition position);
Fragment DebugStepCheck(TokenPosition position);
+ // Truncates (instead of deoptimizing) if the origin does not fit into the
+ // target representation.
+ Fragment UnboxTruncate(Representation to);
+
+ // Sign-extends kUnboxedInt32 and zero-extends kUnboxedUint32.
+ Fragment Box(Representation from);
+
+ // Pops an 'ffi.Pointer' off the stack.
+ // If it's null, pushes 0.
+ // Otherwise pushes the address (in boxed representation).
+ Fragment LoadAddressFromFfiPointer();
+
+ // Reverse of 'LoadPointerFromFfiPointer':
+ // Pops an integer off the the stack.
+ // If it's zero, pushes null.
+ // If it's nonzero, creates an 'ffi.Pointer' holding the address and pushes
+ // the pointer.
+ Fragment FfiPointerFromAddress(const Type& result_type);
+
LocalVariable* LookupVariable(intptr_t kernel_offset);
// Build argument type checks for the current function.
@@ -258,6 +289,8 @@
// Builds flow graph for implicit closure function (tear-off).
//
// ParsedFunction should have the following information:
+ // - DefaultFunctionTypeArguments()
+ // - function_type_arguments()
// - default_parameter_values()
// - is_forwarding_stub()
// - forwarding_stub_super_target()
@@ -268,6 +301,32 @@
//
FlowGraph* BuildGraphOfImplicitClosureFunction(const Function& function);
+ // Builds flow graph of implicit field getter, setter, or a
+ // dynamic invocation forwarder to a field setter.
+ //
+ // If field is const, its value should be evaluated and stored in
+ // - StaticValue()
+ //
+ // Scope should be populated with parameter variables including
+ // - needs_type_check()
+ //
+ FlowGraph* BuildGraphOfFieldAccessor(const Function& function);
+
+ // Builds flow graph of dynamic invocation forwarder.
+ //
+ // ParsedFunction should have the following information:
+ // - DefaultFunctionTypeArguments()
+ // - function_type_arguments()
+ // - default_parameter_values()
+ // - is_forwarding_stub()
+ // - forwarding_stub_super_target()
+ //
+ // Scope should be populated with parameter variables including
+ // - needs_type_check()
+ // - is_explicit_covariant_parameter()
+ //
+ FlowGraph* BuildGraphOfDynamicInvocationForwarder(const Function& function);
+
TranslationHelper translation_helper_;
Thread* thread_;
Zone* zone_;
@@ -283,6 +342,7 @@
intptr_t try_depth_;
intptr_t catch_depth_;
intptr_t for_in_depth_;
+ intptr_t block_expression_depth_;
GraphEntryInstr* graph_entry_;
@@ -355,13 +415,15 @@
intptr_t loop_depth,
intptr_t for_in_depth,
intptr_t try_depth,
- intptr_t catch_depth)
+ intptr_t catch_depth,
+ intptr_t block_expression_depth)
: breakable_block_(breakable_block),
switch_block_(switch_block),
loop_depth_(loop_depth),
for_in_depth_(for_in_depth),
try_depth_(try_depth),
- catch_depth_(catch_depth) {}
+ catch_depth_(catch_depth),
+ block_expression_depth_(block_expression_depth) {}
void assignTo(FlowGraphBuilder* builder) const {
builder->breakable_block_ = breakable_block_;
@@ -370,6 +432,7 @@
builder->for_in_depth_ = for_in_depth_;
builder->try_depth_ = try_depth_;
builder->catch_depth_ = catch_depth_;
+ builder->block_expression_depth_ = block_expression_depth_;
}
private:
@@ -379,6 +442,7 @@
const intptr_t for_in_depth_;
const intptr_t try_depth_;
const intptr_t catch_depth_;
+ const intptr_t block_expression_depth_;
};
class SwitchBlock {
@@ -505,7 +569,8 @@
builder_->loop_depth_,
builder_->for_in_depth_,
builder_->try_depth_ - 1,
- builder_->catch_depth_) {
+ builder_->catch_depth_,
+ builder_->block_expression_depth_) {
builder_->try_finally_block_ = this;
}
~TryFinallyBlock() { builder_->try_finally_block_ = outer_; }
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 6194c70..ebd4ed7 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -2197,6 +2197,13 @@
ReadPosition(); // read position.
SkipListOfExpressions(); // read list of expressions.
return;
+ case kListConcatenation:
+ case kSetConcatenation:
+ case kMapConcatenation:
+ // Collection concatenation operations are removed by the constant
+ // evaluator.
+ UNREACHABLE();
+ break;
case kIsExpression:
ReadPosition(); // read position.
SkipExpression(); // read operand.
@@ -2255,10 +2262,10 @@
SkipVariableDeclaration(); // read variable declaration.
SkipExpression(); // read expression.
return;
- case kBlockExpression: {
- UNIMPLEMENTED();
+ case kBlockExpression:
+ SkipStatementList();
+ SkipExpression(); // read expression.
return;
- }
case kInstantiation:
SkipExpression(); // read expression.
SkipListOfDartTypes(); // read type arguments.
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index 1149d15..3c5103c 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -29,7 +29,7 @@
bool PrologueBuilder::HasEmptyPrologue(const Function& function) {
return !function.HasOptionalParameters() && !function.IsGeneric() &&
- !function.IsClosureFunction();
+ !function.CanReceiveDynamicInvocation();
}
BlockEntryInstr* PrologueBuilder::BuildPrologue(BlockEntryInstr* entry,
@@ -41,7 +41,7 @@
const bool load_optional_arguments = function_.HasOptionalParameters();
const bool expect_type_args = function_.IsGeneric();
- const bool check_arguments = function_.IsClosureFunction();
+ const bool check_arguments = function_.CanReceiveDynamicInvocation();
Fragment prologue = Fragment(entry);
JoinEntryInstr* nsm = NULL;
@@ -383,9 +383,7 @@
}
Fragment PrologueBuilder::BuildClosureContextHandling() {
- LocalScope* scope = parsed_function_->node_sequence()->scope();
- LocalVariable* closure_parameter = scope->VariableAt(0);
-
+ LocalVariable* closure_parameter = parsed_function_->ParameterVariable(0);
LocalVariable* context = parsed_function_->current_context_var();
// Load closure.context & store it into the context variable.
@@ -419,8 +417,7 @@
handling += TestTypeArgsLen(store_null, store_type_args, 0);
if (parsed_function_->function().IsClosureFunction()) {
- LocalVariable* closure =
- parsed_function_->node_sequence()->scope()->VariableAt(0);
+ LocalVariable* closure = parsed_function_->ParameterVariable(0);
// Currently, delayed type arguments can only be introduced through type
// inference in the FE. So if they are present, we can assume they are
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 71c2e61..e23bf10 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -96,14 +96,15 @@
// load instantiator type arguments if they are needed.
Class& klass = Class::Handle(Z, function.Owner());
Type& klass_type = H.GetDeclarationType(klass);
- result_->this_variable =
+ LocalVariable* receiver_variable =
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::This(), klass_type);
- result_->this_variable->set_is_captured();
+ parsed_function_->set_receiver_var(receiver_variable);
+ receiver_variable->set_is_captured();
enclosing_scope = new (Z) LocalScope(NULL, 0, 0);
enclosing_scope->set_context_level(0);
- enclosing_scope->AddVariable(result_->this_variable);
- enclosing_scope->AddContextVariable(result_->this_variable);
+ enclosing_scope->AddVariable(receiver_variable);
+ enclosing_scope->AddContextVariable(receiver_variable);
} else if (function.IsLocalFunction()) {
enclosing_scope = LocalScope::RestoreOuterScope(
ContextScope::Handle(Z, function.context_scope()));
@@ -126,6 +127,10 @@
scope_->AddVariable(parsed_function_->arg_desc_var());
}
+ if (parsed_function_->function().IsFfiTrampoline()) {
+ needs_expr_temp_ = true;
+ }
+
LocalVariable* context_var = parsed_function_->current_context_var();
context_var->set_is_forced_stack();
scope_->AddVariable(context_var);
@@ -170,7 +175,7 @@
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::This(), klass_type);
scope_->InsertParameterAt(pos++, variable);
- result_->this_variable = variable;
+ parsed_function_->set_receiver_var(variable);
// We visit instance field initializers because they might contain
// [Let] expressions and we need to have a mapping.
@@ -279,7 +284,7 @@
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::This(), klass_type);
scope_->InsertParameterAt(pos++, variable);
- result_->this_variable = variable;
+ parsed_function_->set_receiver_var(variable);
}
if (is_setter) {
result_->setter_value = MakeVariable(
@@ -290,12 +295,10 @@
if (is_method &&
MethodCanSkipTypeChecksForNonCovariantArguments(function, attrs)) {
- FieldHelper field_helper(&helper_);
- field_helper.ReadUntilIncluding(FieldHelper::kFlags);
-
- if (field_helper.IsCovariant()) {
+ const auto& field = Field::Handle(Z, function.accessor_field());
+ if (field.is_covariant()) {
result_->setter_value->set_is_explicit_covariant_parameter();
- } else if (!field_helper.IsGenericCovariantImpl() ||
+ } else if (!field.is_generic_covariant_impl() ||
(!attrs.has_non_this_uses && !attrs.has_tearoff_uses)) {
result_->setter_value->set_type_check_mode(
LocalVariable::kTypeCheckedByCaller);
@@ -320,16 +323,16 @@
if (helper_.PeekTag() == kField) {
#ifdef DEBUG
String& name = String::Handle(Z, function.name());
- ASSERT(Function::IsDynamicInvocationForwaderName(name));
+ ASSERT(Function::IsDynamicInvocationForwarderName(name));
name = Function::DemangleDynamicInvocationForwarderName(name);
ASSERT(Field::IsSetterName(name));
#endif
// Create [this] variable.
const Class& klass = Class::Handle(Z, function.Owner());
- result_->this_variable =
+ parsed_function_->set_receiver_var(
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
- Symbols::This(), H.GetDeclarationType(klass));
- scope_->InsertParameterAt(0, result_->this_variable);
+ Symbols::This(), H.GetDeclarationType(klass)));
+ scope_->InsertParameterAt(0, parsed_function_->receiver_var());
// Create setter value variable.
result_->setter_value = MakeVariable(
@@ -345,10 +348,10 @@
// Create [this] variable.
intptr_t pos = 0;
Class& klass = Class::Handle(Z, function.Owner());
- result_->this_variable =
+ parsed_function_->set_receiver_var(
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
- Symbols::This(), H.GetDeclarationType(klass));
- scope_->InsertParameterAt(pos++, result_->this_variable);
+ Symbols::This(), H.GetDeclarationType(klass)));
+ scope_->InsertParameterAt(pos++, parsed_function_->receiver_var());
// Create all positional and named parameters.
AddPositionalAndNamedParameters(
@@ -368,22 +371,24 @@
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::This(), klass_type);
scope_->InsertParameterAt(0, variable);
- result_->this_variable = variable;
+ parsed_function_->set_receiver_var(variable);
break;
}
case RawFunction::kNoSuchMethodDispatcher:
case RawFunction::kInvokeFieldDispatcher:
+ case RawFunction::kFfiTrampoline:
for (intptr_t i = 0; i < function.NumParameters(); ++i) {
- LocalVariable* variable =
- MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
- String::ZoneHandle(Z, function.ParameterNameAt(i)),
- AbstractType::dynamic_type());
+ LocalVariable* variable = MakeVariable(
+ TokenPosition::kNoSource, TokenPosition::kNoSource,
+ String::ZoneHandle(Z, function.ParameterNameAt(i)),
+ AbstractType::ZoneHandle(Z, function.IsFfiTrampoline()
+ ? function.ParameterTypeAt(i)
+ : Object::dynamic_type().raw()));
scope_->InsertParameterAt(i, variable);
}
break;
case RawFunction::kSignatureFunction:
case RawFunction::kIrregexpFunction:
- case RawFunction::kFfiTrampoline:
UNREACHABLE();
}
if (needs_expr_temp_) {
@@ -513,12 +518,11 @@
}
if (function_node_helper.async_marker_ == FunctionNodeHelper::kSyncYielding) {
- LocalScope* scope = parsed_function_->node_sequence()->scope();
intptr_t offset = parsed_function_->function().num_fixed_parameters();
for (intptr_t i = 0;
i < parsed_function_->function().NumOptionalPositionalParameters();
i++) {
- scope->VariableAt(offset + i)->set_is_forced_stack();
+ parsed_function_->ParameterVariable(offset + i)->set_is_forced_stack();
}
}
@@ -678,13 +682,13 @@
VisitExpression(); // read value·
return;
case kSuperPropertyGet:
- HandleSpecialLoad(&result_->this_variable, Symbols::This());
+ HandleLoadReceiver();
helper_.ReadPosition(); // read position.
helper_.SkipName(); // read name.
helper_.SkipCanonicalNameReference(); // read target_reference.
return;
case kSuperPropertySet:
- HandleSpecialLoad(&result_->this_variable, Symbols::This());
+ HandleLoadReceiver();
helper_.ReadPosition(); // read position.
helper_.SkipName(); // read name.
VisitExpression(); // read value.
@@ -714,7 +718,7 @@
VisitArguments(); // read arguments.
return;
case kSuperMethodInvocation:
- HandleSpecialLoad(&result_->this_variable, Symbols::This());
+ HandleLoadReceiver();
helper_.ReadPosition(); // read position.
helper_.SkipName(); // read name.
VisitArguments(); // read arguments.
@@ -758,6 +762,13 @@
}
return;
}
+ case kListConcatenation:
+ case kSetConcatenation:
+ case kMapConcatenation:
+ // Collection concatenation operations are removed by the constant
+ // evaluator.
+ UNREACHABLE();
+ break;
case kIsExpression:
helper_.ReadPosition(); // read position.
VisitExpression(); // read operand.
@@ -776,7 +787,7 @@
VisitDartType(); // read type.
return;
case kThisExpression:
- HandleSpecialLoad(&result_->this_variable, Symbols::This());
+ HandleLoadReceiver();
return;
case kRethrow:
helper_.ReadPosition(); // read position.
@@ -833,7 +844,19 @@
return;
}
case kBlockExpression: {
- UNIMPLEMENTED();
+ PositionScope scope(&helper_.reader_);
+ intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
+
+ EnterScope(offset);
+
+ intptr_t list_length =
+ helper_.ReadListLength(); // read number of statements.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ VisitStatement(); // read ith statement.
+ }
+ VisitExpression(); // read expression.
+
+ ExitScope(helper_.reader_.min_position(), helper_.reader_.max_position());
return;
}
case kBigIntLiteral:
@@ -1342,7 +1365,7 @@
// object, so we need to capture 'this'.
Class& parent_class = Class::Handle(Z, function.Owner());
if (index < parent_class.NumTypeParameters()) {
- HandleSpecialLoad(&result_->this_variable, Symbols::This());
+ HandleLoadReceiver();
}
}
@@ -1689,6 +1712,24 @@
return H.DartSymbolObfuscate(name);
}
+void ScopeBuilder::HandleLoadReceiver() {
+ if (!parsed_function_->has_receiver_var() &&
+ current_function_scope_->parent() != nullptr) {
+ // Lazily populate receiver variable using the parent function scope.
+ parsed_function_->set_receiver_var(
+ current_function_scope_->parent()->LookupVariable(Symbols::This(),
+ true));
+ }
+
+ if ((current_function_scope_->parent() != nullptr) ||
+ (scope_->function_level() > 0)) {
+ // Every scope we use the [receiver] from needs to be notified of the usage
+ // in order to ensure that preserving the context scope on that particular
+ // use-site also includes the [receiver].
+ scope_->CaptureVariable(parsed_function_->receiver_var());
+ }
+}
+
void ScopeBuilder::HandleSpecialLoad(LocalVariable** variable,
const String& symbol) {
if (current_function_scope_->parent() != NULL) {
diff --git a/runtime/vm/compiler/frontend/scope_builder.h b/runtime/vm/compiler/frontend/scope_builder.h
index 12521be..b2227aa 100644
--- a/runtime/vm/compiler/frontend/scope_builder.h
+++ b/runtime/vm/compiler/frontend/scope_builder.h
@@ -116,6 +116,7 @@
const String& GenerateName(const char* prefix, intptr_t suffix);
+ void HandleLoadReceiver();
void HandleSpecialLoad(LocalVariable** variable, const String& symbol);
void LookupCapturedVariableByName(LocalVariable** variable,
const String& name);
@@ -171,8 +172,7 @@
class ScopeBuildingResult : public ZoneAllocated {
public:
ScopeBuildingResult()
- : this_variable(NULL),
- type_arguments_variable(NULL),
+ : type_arguments_variable(NULL),
switch_variable(NULL),
finally_return_variable(NULL),
setter_value(NULL),
@@ -184,9 +184,6 @@
IntMap<LocalScope*> scopes;
GrowableArray<FunctionScope> function_scopes;
- // Only non-NULL for instance functions.
- LocalVariable* this_variable;
-
// Only non-NULL for factory constructor functions.
LocalVariable* type_arguments_variable;
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index bac9f7e..85c5e6c 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -162,7 +162,6 @@
current_(entry),
fall_through_env_(new Environment(0,
0,
- DeoptId::kNone,
flow_graph->parsed_function(),
NULL)) {}
@@ -276,7 +275,9 @@
index = PrepareIndexedOp(flow_graph, &builder, array, index,
Slot::GetLengthFieldForArrayCid(array_cid));
- if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ if (RawObject::IsTypedDataClassId(array_cid) ||
+ RawObject::IsExternalTypedDataClassId(array_cid)) {
+ ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
array = builder.AddDefinition(new LoadUntaggedInstr(
new Value(array), ExternalTypedData::data_offset()));
}
@@ -422,7 +423,9 @@
UNREACHABLE();
}
- if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ if (RawObject::IsTypedDataClassId(array_cid) ||
+ RawObject::IsExternalTypedDataClassId(array_cid)) {
+ ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
array = builder.AddDefinition(new LoadUntaggedInstr(
new Value(array), ExternalTypedData::data_offset()));
}
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index b8e2fdb..db4a507 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -381,8 +381,11 @@
// CreateDeoptInfo uses the object pool and needs to be done before
// FinalizeCode.
- const Array& deopt_info_array =
- Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler));
+ Array& deopt_info_array = Array::Handle(zone, Object::empty_array().raw());
+ if (!function.ForceOptimize()) {
+ deopt_info_array = graph_compiler->CreateDeoptInfo(assembler);
+ }
+
// Allocates instruction object. Since this occurs only at safepoint,
// there can be no concurrent access to the instruction page.
Code& code = Code::Handle(Code::FinalizeCode(
@@ -431,7 +434,13 @@
graph_compiler->FinalizeStaticCallTargetsTable(code);
graph_compiler->FinalizeCodeSourceMap(code);
- if (optimized()) {
+ if (function.ForceOptimize()) {
+ ASSERT(optimized() && thread()->IsMutatorThread());
+ code.set_is_optimized(false);
+ function.AttachCode(code);
+ function.set_unoptimized_code(code);
+ function.SetWasCompiled(true);
+ } else if (optimized()) {
// Installs code while at safepoint.
if (thread()->IsMutatorThread()) {
const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
@@ -764,6 +773,7 @@
intptr_t osr_id) {
ASSERT(!FLAG_precompiled_mode);
ASSERT(!optimized || function.WasCompiled());
+ if (function.ForceOptimize()) optimized = true;
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
Thread* const thread = Thread::Current();
@@ -1058,13 +1068,6 @@
ASSERT(function.ShouldCompilerOptimize());
- // If we are in the optimizing in the mutator/Dart thread, then
- // this is either an OSR compilation or background compilation is
- // not currently allowed.
- ASSERT(!thread->IsMutatorThread() || (osr_id != kNoOSRDeoptId) ||
- !FLAG_background_compilation ||
- BackgroundCompiler::IsDisabled(Isolate::Current()) ||
- !function.is_background_optimizable());
CompilationPipeline* pipeline =
CompilationPipeline::New(thread->zone(), function);
return CompileFunctionHelper(pipeline, function, /* optimized = */ true,
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index be12f08..0973fed 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -304,7 +304,7 @@
String& name = thread->StringHandle();
name = name_.raw();
ASSERT(name.IsSymbol());
- if (Function::IsDynamicInvocationForwaderName(name)) {
+ if (Function::IsDynamicInvocationForwarderName(name)) {
name = Function::DemangleDynamicInvocationForwarderName(name);
}
if (name.raw() == Symbols::Plus().raw()) {
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index fa35d7c..a0baa73 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -8,7 +8,7 @@
namespace dart {
// clang-format off
-// (class-name, function-name, recognized enum, result type, fingerprint).
+// (class-name, function-name, recognized enum, fingerprint).
// When adding a new function add a 0 as fingerprint, build and run to get the
// correct fingerprint from the mismatch error (or use Library::GetFunction()
// and print func.SourceFingerprint()).
@@ -42,6 +42,27 @@
V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d) \
V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e) \
V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54) \
+ V(_ByteDataView, get:length, ByteDataViewLength, 0x0) \
+ V(_ByteDataView, get:offsetInBytes, ByteDataViewOffsetInBytes, 0x0) \
+ V(_ByteDataView, get:_typedData, ByteDataViewTypedData, 0x0) \
+ V(_TypedListView, get:length, TypedDataViewLength, 0x0) \
+ V(_TypedListView, get:offsetInBytes, TypedDataViewOffsetInBytes, 0x0) \
+ V(_TypedListView, get:_typedData, TypedDataViewTypedData, 0x0) \
+ V(_ByteDataView, ., TypedData_ByteDataView_factory, 0x0) \
+ V(_Int8ArrayView, ., TypedData_Int8ArrayView_factory, 0x0) \
+ V(_Uint8ArrayView, ., TypedData_Uint8ArrayView_factory, 0x0) \
+ V(_Uint8ClampedArrayView, ., TypedData_Uint8ClampedArrayView_factory, 0x0) \
+ V(_Int16ArrayView, ., TypedData_Int16ArrayView_factory, 0x0) \
+ V(_Uint16ArrayView, ., TypedData_Uint16ArrayView_factory, 0x0) \
+ V(_Int32ArrayView, ., TypedData_Int32ArrayView_factory, 0x0) \
+ V(_Uint32ArrayView, ., TypedData_Uint32ArrayView_factory, 0x0) \
+ V(_Int64ArrayView, ., TypedData_Int64ArrayView_factory, 0x0) \
+ V(_Uint64ArrayView, ., TypedData_Uint64ArrayView_factory, 0x0) \
+ V(_Float32ArrayView, ., TypedData_Float32ArrayView_factory, 0x0) \
+ V(_Float64ArrayView, ., TypedData_Float64ArrayView_factory, 0x0) \
+ V(_Float32x4ArrayView, ., TypedData_Float32x4ArrayView_factory, 0x0) \
+ V(_Int32x4ArrayView, ., TypedData_Int32x4ArrayView_factory, 0x0) \
+ V(_Float64x2ArrayView, ., TypedData_Float64x2ArrayView_factory, 0x0) \
V(::, _toClampedUint8, ConvertIntToClampedUint8, 0x564b0435) \
V(_StringBase, _interpolate, StringBaseInterpolate, 0x01ecb15a) \
V(_IntegerImplementation, toDouble, IntegerToDouble, 0x05da96ed) \
@@ -352,6 +373,9 @@
V(_List, get:length, ObjectArrayLength, 0x25952390) \
V(_ImmutableList, get:length, ImmutableArrayLength, 0x25952390) \
V(_TypedList, get:length, TypedDataLength, 0x2091c4d8) \
+ V(_TypedListView, get:length, TypedDataViewLength, 0x0) \
+ V(_TypedListView, get:offsetInBytes, TypedDataViewOffsetInBytes, 0x0) \
+ V(_TypedListView, get:_typedData, TypedDataViewTypedData, 0x0) \
V(_GrowableList, get:length, GrowableArrayLength, 0x18dd86b4) \
V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x2e04be60) \
V(_GrowableList, add, GrowableListAdd, 0x40b490b8) \
@@ -390,6 +414,9 @@
V(_Float32ArrayView, []=, Float32ArrayViewSetIndexed, 0xc9b691bd) \
V(_Float64ArrayView, [], Float64ArrayViewGetIndexed, 0x9d83f585) \
V(_Float64ArrayView, []=, Float64ArrayViewSetIndexed, 0x3c1adabd) \
+ V(_ByteDataView, get:length, ByteDataViewLength, 0x0) \
+ V(_ByteDataView, get:offsetInBytes, ByteDataViewOffsetInBytes, 0x0) \
+ V(_ByteDataView, get:_typedData, ByteDataViewTypedData, 0x0) \
V(_ByteDataView, setInt8, ByteDataViewSetInt8, 0x6395293e) \
V(_ByteDataView, setUint8, ByteDataViewSetUint8, 0x79979d1f) \
V(_ByteDataView, setInt16, ByteDataViewSetInt16, 0x525ec534) \
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index 467aa78..5d4d35f 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -5,6 +5,7 @@
#include "vm/compiler/relocation.h"
#include "vm/code_patcher.h"
+#include "vm/heap/pages.h"
#include "vm/instructions.h"
#include "vm/object_store.h"
#include "vm/stub_code.h"
@@ -362,8 +363,11 @@
auto caller = Code::InstructionsOf(unresolved_call->caller);
const int32_t distance = destination_text - call_text_offset;
{
- PcRelativeCallPattern call(Instructions::PayloadStart(caller) +
- call_offset);
+ uword addr = Instructions::PayloadStart(caller) + call_offset;
+ if (FLAG_write_protect_code) {
+ addr -= HeapPage::Of(caller)->AliasOffset();
+ }
+ PcRelativeCallPattern call(addr);
ASSERT(call.IsValid());
call.set_distance(static_cast<int32_t>(distance));
ASSERT(call.distance() == distance);
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index ce66591..ba72cc1 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -254,6 +254,10 @@
const word RawObject::kBarrierOverlapShift =
dart::RawObject::kBarrierOverlapShift;
+bool RawObject::IsTypedDataClassId(intptr_t cid) {
+ return dart::RawObject::IsTypedDataClassId(cid);
+}
+
intptr_t ObjectPool::element_offset(intptr_t index) {
return dart::ObjectPool::element_offset(index);
}
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 8df8767..652c1b3 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -335,6 +335,8 @@
static const word kSizeTagMaxSizeTag;
static const word kTagBitsSizeTagPos;
static const word kBarrierOverlapShift;
+
+ static bool IsTypedDataClassId(intptr_t cid);
};
class RawAbstractType : public AllStatic {
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 5de7ddc..00affe4 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -145,9 +145,9 @@
#define R(reg) (1 << (reg))
-#if defined(_WIN64)
class CallingConventions {
public:
+#if defined(_WIN64)
static const Register kArg1Reg = RCX;
static const Register kArg2Reg = RDX;
static const Register kArg3Reg = R8;
@@ -186,10 +186,10 @@
// Windows x64 ABI specifies that small objects are passed in registers.
// Otherwise they are passed by reference.
static const size_t kRegisterTransferLimit = 16;
-};
+
+ static constexpr Register kReturnReg = RAX;
+ static constexpr FpuRegister kReturnFpuReg = XMM0;
#else
-class CallingConventions {
- public:
static const Register kArg1Reg = RDI;
static const Register kArg2Reg = RSI;
static const Register kArg3Reg = RDX;
@@ -229,9 +229,24 @@
static const intptr_t kCalleeSaveXmmRegisters = 0;
static const XmmRegister xmmFirstNonParameterReg = XMM8;
-};
+
+ static constexpr Register kReturnReg = RAX;
+ static constexpr FpuRegister kReturnFpuReg = XMM0;
#endif
+ COMPILE_ASSERT((kArgumentRegisters & kReservedCpuRegisters) == 0);
+
+ static constexpr Register kFirstCalleeSavedCpuReg = RBX;
+ static constexpr Register kFirstNonArgumentRegister = RAX;
+ static constexpr Register kSecondNonArgumentRegister = RBX;
+
+ COMPILE_ASSERT(((R(kFirstCalleeSavedCpuReg)) & kCalleeSaveCpuRegisters) != 0);
+
+ COMPILE_ASSERT(((R(kFirstNonArgumentRegister) |
+ R(kSecondNonArgumentRegister)) &
+ kArgumentRegisters) == 0);
+};
+
#undef R
class Instr {
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 3e81020..0c51e1a 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -3087,19 +3087,19 @@
}
}
if (RawObject::IsTypedDataViewClassId(obj.GetClassId())) {
- const Instance& view = Instance::Cast(obj);
+ const auto& view = TypedDataView::Cast(obj);
if (TypedDataView::ElementSizeInBytes(view) == 1) {
- intptr_t view_length = Smi::Value(TypedDataView::Length(view));
+ const intptr_t view_length = Smi::Value(view.length());
if (!Utils::RangeCheck(offset, length, view_length)) {
return Api::NewError(
"Invalid length passed in to access list elements");
}
- const Instance& data = Instance::Handle(TypedDataView::Data(view));
+ const auto& data = Instance::Handle(view.typed_data());
if (data.IsTypedData()) {
const TypedData& array = TypedData::Cast(data);
if (array.ElementSizeInBytes() == 1) {
- intptr_t data_offset =
- Smi::Value(TypedDataView::OffsetInBytes(view)) + offset;
+ const intptr_t data_offset =
+ Smi::Value(view.offset_in_bytes()) + offset;
// Range check already performed on the view object.
ASSERT(Utils::RangeCheck(data_offset, length, array.Length()));
return CopyBytes(array, data_offset, native_array, length);
@@ -3389,10 +3389,9 @@
if (RawObject::IsTypedDataViewClassId(class_id)) {
// Check if data object of the view is external.
Zone* zone = thread->zone();
- const Instance& view_obj = Api::UnwrapInstanceHandle(zone, object);
+ const auto& view_obj = Api::UnwrapTypedDataViewHandle(zone, object);
ASSERT(!view_obj.IsNull());
- const Instance& data_obj =
- Instance::Handle(zone, TypedDataView::Data(view_obj));
+ const auto& data_obj = Instance::Handle(zone, view_obj.typed_data());
if (ExternalTypedData::IsExternalTypedData(data_obj)) {
return GetType(class_id);
}
@@ -3744,15 +3743,15 @@
data_tmp = obj.DataAddr(0);
} else {
ASSERT(RawObject::IsTypedDataViewClassId(class_id));
- const Instance& view_obj = Api::UnwrapInstanceHandle(Z, object);
+ const auto& view_obj = Api::UnwrapTypedDataViewHandle(Z, object);
ASSERT(!view_obj.IsNull());
Smi& val = Smi::Handle();
- val ^= TypedDataView::Length(view_obj);
+ val ^= view_obj.length();
length = val.Value();
size_in_bytes = length * TypedDataView::ElementSizeInBytes(class_id);
- val ^= TypedDataView::OffsetInBytes(view_obj);
+ val ^= view_obj.offset_in_bytes();
intptr_t offset_in_bytes = val.Value();
- const Instance& obj = Instance::Handle(TypedDataView::Data(view_obj));
+ const auto& obj = Instance::Handle(view_obj.typed_data());
T->IncrementNoSafepointScopeDepth();
START_NO_CALLBACK_SCOPE(T);
if (TypedData::IsTypedData(obj)) {
@@ -4900,7 +4899,7 @@
return Symbols::False().raw();
}
- if (!Api::ffiEnabled() && name.Equals(Symbols::DartLibraryFfi())) {
+ if (!Api::IsFfiEnabled() && name.Equals(Symbols::DartLibraryFfi())) {
return Symbols::False().raw();
}
@@ -5839,7 +5838,6 @@
if (event == NULL) {
return;
}
- label = strdup(label);
switch (type) {
case Dart_Timeline_Event_Begin:
event->Begin(label, timestamp0);
@@ -5877,7 +5875,6 @@
default:
FATAL("Unknown Dart_Timeline_Event_Type");
}
- event->set_owns_label(true);
event->SetNumArguments(argument_count);
for (intptr_t i = 0; i < argument_count; i++) {
event->CopyArgument(i, argument_names[i], argument_values[i]);
@@ -5945,6 +5942,10 @@
API_TIMELINE_DURATION(thread);
DARTSCOPE(thread);
CHECK_NULL(buffer);
+ Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
+ if (Api::IsError(state)) {
+ return state;
+ }
CompilationTraceLoader loader(thread);
const Object& error =
Object::Handle(loader.CompileTrace(buffer, buffer_length));
@@ -5964,6 +5965,10 @@
API_TIMELINE_DURATION(thread);
DARTSCOPE(thread);
CHECK_NULL(buffer);
+ Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
+ if (Api::IsError(state)) {
+ return state;
+ }
ReadStream stream(buffer, buffer_length);
TypeFeedbackLoader loader(thread);
const Object& error = Object::Handle(loader.LoadFeedback(&stream));
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 76a6b0d..41f7383 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -295,14 +295,14 @@
static RawString* GetEnvironmentValue(Thread* thread, const String& name);
- static bool ffiEnabled() {
+ static bool IsFfiEnabled() {
// dart:ffi is not implemented for the following configurations
#if !defined(TARGET_ARCH_X64)
- // https://github.com/dart-lang/sdk/issues/35774
+ // https://github.com/dart-lang/sdk/issues/35774 IA32
return false;
-#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) && \
+ !defined(TARGET_OS_WINDOWS)
// https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
- // https://github.com/dart-lang/sdk/issues/35771 Windows
// https://github.com/dart-lang/sdk/issues/35772 Arm64
// https://github.com/dart-lang/sdk/issues/35773 DBC
return false;
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 6b4b612..88c6c92 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -243,39 +243,6 @@
return value;
}
-static Dart_TypedData_Type GetTypedDataTypeFromView(
- Dart_CObject_Internal* object,
- char* class_name) {
- struct {
- const char* name;
- Dart_TypedData_Type type;
- } view_class_names[] = {
- {"_Int8ArrayView", Dart_TypedData_kInt8},
- {"_Uint8ArrayView", Dart_TypedData_kUint8},
- {"_Uint8ClampedArrayView", Dart_TypedData_kUint8Clamped},
- {"_Int16ArrayView", Dart_TypedData_kInt16},
- {"_Uint16ArrayView", Dart_TypedData_kUint16},
- {"_Int32ArrayView", Dart_TypedData_kInt32},
- {"_Uint32ArrayView", Dart_TypedData_kUint32},
- {"_Int64ArrayView", Dart_TypedData_kInt64},
- {"_Uint64ArrayView", Dart_TypedData_kUint64},
- {"_ByteDataView", Dart_TypedData_kUint8},
- {"_Float32ArrayView", Dart_TypedData_kFloat32},
- {"_Float64ArrayView", Dart_TypedData_kFloat64},
- {NULL, Dart_TypedData_kInvalid},
- };
-
- int i = 0;
- while (view_class_names[i].name != NULL) {
- if (strncmp(view_class_names[i].name, class_name,
- strlen(view_class_names[i].name)) == 0) {
- return view_class_names[i].type;
- }
- i++;
- }
- return Dart_TypedData_kInvalid;
-}
-
Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
// Read the class header information and lookup the class.
intptr_t class_header = Read<int32_t>();
@@ -299,46 +266,6 @@
}
ASSERT(object->type == static_cast<Dart_CObject_Type>(
Dart_CObject_Internal::kUninitialized));
-
- char* library_uri =
- object->cls->internal.as_class.library_url->value.as_string;
- char* class_name =
- object->cls->internal.as_class.class_name->value.as_string;
-
- // Handle typed data views.
- if (strcmp("dart:typed_data", library_uri) == 0) {
- Dart_TypedData_Type type = GetTypedDataTypeFromView(object, class_name);
- if (type != Dart_TypedData_kInvalid) {
- object->type =
- static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView);
- Dart_CObject_Internal* cls =
- reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
- ASSERT(cls == object->cls);
- object->internal.as_view.buffer = ReadObjectImpl();
- object->internal.as_view.offset_in_bytes = ReadSmiValue();
- object->internal.as_view.length = ReadSmiValue();
-
- // The buffer is fully read now as typed data objects are
- // serialized in-line.
- Dart_CObject* buffer = object->internal.as_view.buffer;
- ASSERT(buffer->type == Dart_CObject_kTypedData);
-
- // Now turn the view into a byte array.
- object->type = Dart_CObject_kTypedData;
- object->value.as_typed_data.type = type;
- object->value.as_typed_data.length =
- object->internal.as_view.length * GetTypedDataSizeInBytes(type);
- object->value.as_typed_data.values =
- buffer->value.as_typed_data.values +
- object->internal.as_view.offset_in_bytes;
- } else {
- // TODO(sgjesse): Handle other instances. Currently this will
- // skew the reading as the fields of the instance is not read.
- }
- } else {
- // TODO(sgjesse): Handle other instances. Currently this will
- // skew the reading as the fields of the instance is not read.
- }
return object;
}
@@ -531,7 +458,6 @@
return value;
}
case kTypeParameterCid: {
- // TODO(sgjesse): Fix this workaround ignoring the type parameter.
Dart_CObject* value = &dynamic_type_marker;
AddBackRef(object_id, value, kIsDeserialized);
intptr_t index = Read<int32_t>();
@@ -657,60 +583,59 @@
return object; \
}
- case kTypedDataInt8ArrayCid:
- READ_TYPED_DATA(Int8, int8_t);
- case kExternalTypedDataInt8ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Int8, int8_t);
+#define READ_TYPED_DATA_VIEW(tname, ctype) \
+ { \
+ Dart_CObject_Internal* object = \
+ AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized); \
+ AddBackRef(object_id, object, kIsDeserialized); \
+ object->type = \
+ static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView); \
+ object->internal.as_view.offset_in_bytes = ReadSmiValue(); \
+ object->internal.as_view.length = ReadSmiValue(); \
+ object->internal.as_view.buffer = ReadObjectImpl(); \
+ Dart_CObject* buffer = object->internal.as_view.buffer; \
+ RELEASE_ASSERT(buffer->type == Dart_CObject_kTypedData); \
+ \
+ /* Now turn the view into a byte array.*/ \
+ const Dart_TypedData_Type type = Dart_TypedData_k##tname; \
+ object->type = Dart_CObject_kTypedData; \
+ object->value.as_typed_data.type = type; \
+ object->value.as_typed_data.length = \
+ object->internal.as_view.length * GetTypedDataSizeInBytes(type); \
+ object->value.as_typed_data.values = \
+ buffer->value.as_typed_data.values + \
+ object->internal.as_view.offset_in_bytes; \
+ return object; \
+ }
- case kTypedDataUint8ArrayCid:
- READ_TYPED_DATA(Uint8, uint8_t);
- case kExternalTypedDataUint8ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Uint8, uint8_t);
+#define TYPED_DATA_LIST(V) \
+ V(Int8, int8_t) \
+ V(Uint8, uint8_t) \
+ V(Uint8Clamped, uint8_t) \
+ V(Int16, int16_t) \
+ V(Uint16, uint16_t) \
+ V(Int32, int32_t) \
+ V(Uint32, uint32_t) \
+ V(Int64, int64_t) \
+ V(Uint64, uint64_t) \
+ V(Float32, float) \
+ V(Float64, double)
- case kTypedDataUint8ClampedArrayCid:
- READ_TYPED_DATA(Uint8Clamped, uint8_t);
- case kExternalTypedDataUint8ClampedArrayCid:
- READ_EXTERNAL_TYPED_DATA(Uint8Clamped, uint8_t);
+#define EMIT_TYPED_DATA_CASES(type, c_type) \
+ case kTypedData##type##ArrayCid: \
+ READ_TYPED_DATA(type, c_type); \
+ case kExternalTypedData##type##ArrayCid: \
+ READ_EXTERNAL_TYPED_DATA(type, c_type); \
+ case kTypedData##type##ArrayViewCid: \
+ READ_TYPED_DATA_VIEW(type, c_type);
- case kTypedDataInt16ArrayCid:
- READ_TYPED_DATA(Int16, int16_t);
- case kExternalTypedDataInt16ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Int16, int16_t);
-
- case kTypedDataUint16ArrayCid:
- READ_TYPED_DATA(Uint16, uint16_t);
- case kExternalTypedDataUint16ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Uint16, uint16_t);
-
- case kTypedDataInt32ArrayCid:
- READ_TYPED_DATA(Int32, int32_t);
- case kExternalTypedDataInt32ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Int32, int32_t);
-
- case kTypedDataUint32ArrayCid:
- READ_TYPED_DATA(Uint32, uint32_t);
- case kExternalTypedDataUint32ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Uint32, uint32_t);
-
- case kTypedDataInt64ArrayCid:
- READ_TYPED_DATA(Int64, int64_t);
- case kExternalTypedDataInt64ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Int64, int64_t);
-
- case kTypedDataUint64ArrayCid:
- READ_TYPED_DATA(Uint64, uint64_t);
- case kExternalTypedDataUint64ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Uint64, uint64_t);
-
- case kTypedDataFloat32ArrayCid:
- READ_TYPED_DATA(Float32, float);
- case kExternalTypedDataFloat32ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Float32, float);
-
- case kTypedDataFloat64ArrayCid:
- READ_TYPED_DATA(Float64, double);
- case kExternalTypedDataFloat64ArrayCid:
- READ_EXTERNAL_TYPED_DATA(Float64, double);
+ TYPED_DATA_LIST(EMIT_TYPED_DATA_CASES)
+#undef EMIT_TYPED_DATA_CASES
+#undef TYPED_DATA_LIST
+#undef READ_TYPED_DATA
+#undef READ_EXTERNAL_TYPED_DATA
+#undef READ_TYPED_DATA_VIEW
+#undef READ_TYPED_DATA_HEADER
case kGrowableObjectArrayCid: {
// A GrowableObjectArray is serialized as its type arguments and
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 759a180..011dcca 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -522,6 +522,11 @@
bool IsPaused() const { return pause_event_ != NULL; }
+ bool ignore_breakpoints() const { return ignore_breakpoints_; }
+ void set_ignore_breakpoints(bool ignore_breakpoints) {
+ ignore_breakpoints_ = ignore_breakpoints;
+ }
+
// Put the isolate into single stepping mode when Dart code next runs.
//
// This is used by the vm service to allow the user to step while
@@ -780,6 +785,26 @@
DISALLOW_COPY_AND_ASSIGN(Debugger);
};
+class DisableBreakpointsScope : public ValueObject {
+ public:
+ DisableBreakpointsScope(Debugger* debugger, bool disable)
+ : debugger_(debugger) {
+ ASSERT(debugger_ != NULL);
+ initial_state_ = debugger_->ignore_breakpoints();
+ debugger_->set_ignore_breakpoints(disable);
+ }
+
+ ~DisableBreakpointsScope() {
+ debugger_->set_ignore_breakpoints(initial_state_);
+ }
+
+ private:
+ Debugger* debugger_;
+ bool initial_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(DisableBreakpointsScope);
+};
+
} // namespace dart
#endif // RUNTIME_VM_DEBUGGER_H_
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index 9529569..76ca7b7 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -105,16 +105,13 @@
Exceptions::PropagateError(error);
}
const Code& code = Code::Handle(zone, function.unoptimized_code());
-// Check that deopt_id exists.
-// TODO(vegorov): verify after deoptimization targets as well.
-#ifdef DEBUG
- ASSERT(DeoptId::IsDeoptAfter(deopt_id_) ||
- (code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kDeopt) != 0));
-#endif
uword continue_at_pc =
code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kDeopt);
- ASSERT(continue_at_pc != 0);
+ if (continue_at_pc == 0) {
+ FATAL2("Can't locate continuation PC for deoptid %" Pd " within %s\n",
+ deopt_id_, function.ToFullyQualifiedCString());
+ }
uword* dest_addr = reinterpret_cast<uword*>(slot());
*dest_addr = continue_at_pc;
@@ -306,7 +303,11 @@
value.ToCString());
}
} else {
- ASSERT(offset.Value() == cls.type_arguments_field_offset());
+ // In addition to the type arguments vector we can also have lazy
+ // materialization of e.g. _ByteDataView objects which don't have
+ // explicit fields in Dart (all accesses to the fields are done via
+ // recognized native methods).
+ ASSERT(offset.Value() < cls.instance_size());
obj.SetFieldAtOffset(offset.Value(), value);
if (FLAG_trace_deoptimization_verbose) {
OS::PrintErr(" null Field @ offset(%" Pd ") <- %s\n",
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 487b22a..058d9c7 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -239,12 +239,15 @@
}
void ExecuteCatchEntryMoves(const CatchEntryMoves& moves) {
+ Zone* zone = Thread::Current()->zone();
+ auto& value = Object::Handle(zone);
+ auto& dst_values = Array::Handle(zone, Array::New(moves.count()));
+
uword fp = handler_fp;
ObjectPool* pool = nullptr;
for (int j = 0; j < moves.count(); j++) {
const CatchEntryMove& move = moves.At(j);
- RawObject* value;
switch (move.source_kind()) {
case CatchEntryMove::SourceKind::kConstant:
if (pool == nullptr) {
@@ -295,64 +298,28 @@
UNREACHABLE();
}
- *TaggedSlotAt(fp, move.dest_slot()) = value;
+ dst_values.SetAt(j, value);
+ }
+
+ {
+ NoSafepointScope no_safepoint_scope;
+
+ for (int j = 0; j < moves.count(); j++) {
+ const CatchEntryMove& move = moves.At(j);
+ value = dst_values.At(j);
+ *TaggedSlotAt(fp, move.dest_slot()) = value.raw();
+ }
}
}
#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
void ReadCompressedCatchEntryMoves() {
- intptr_t pc_offset = pc_ - code_->PayloadStart();
- const TypedData& td = TypedData::Handle(code_->catch_entry_moves_maps());
- NoSafepointScope no_safepoint;
- ReadStream stream(static_cast<uint8_t*>(td.DataAddr(0)), td.Length());
+ const intptr_t pc_offset = pc_ - code_->PayloadStart();
+ const auto& td = TypedData::Handle(code_->catch_entry_moves_maps());
- intptr_t prefix_length = 0, suffix_length = 0, suffix_offset = 0;
- while (stream.PendingBytes() > 0) {
- intptr_t target_pc_offset = Reader::Read(&stream);
- prefix_length = Reader::Read(&stream);
- suffix_length = Reader::Read(&stream);
- suffix_offset = Reader::Read(&stream);
- if (pc_offset == target_pc_offset) {
- break;
- }
-
- // Skip the moves.
- for (intptr_t j = 0; j < prefix_length; j++) {
- CatchEntryMove::ReadFrom(&stream);
- }
- }
- ASSERT((stream.PendingBytes() > 0) || (prefix_length == 0));
-
- CatchEntryMoves* moves =
- CatchEntryMoves::Allocate(prefix_length + suffix_length);
- for (int j = 0; j < prefix_length; j++) {
- moves->At(j) = CatchEntryMove::ReadFrom(&stream);
- }
- ReadCompressedCatchEntryMovesSuffix(&stream, suffix_offset, suffix_length,
- moves, prefix_length);
- catch_entry_moves_ = moves;
+ CatchEntryMovesMapReader reader(td);
+ catch_entry_moves_ = reader.ReadMovesForPcOffset(pc_offset);
}
-
- void ReadCompressedCatchEntryMovesSuffix(ReadStream* stream,
- intptr_t offset,
- intptr_t length,
- CatchEntryMoves* moves,
- intptr_t moves_offset) {
- stream->SetPosition(offset);
- Reader::Read(stream); // skip pc_offset
- Reader::Read(stream); // skip variables
- intptr_t suffix_length = Reader::Read(stream);
- intptr_t suffix_offset = Reader::Read(stream);
- intptr_t to_read = length - suffix_length;
- for (int j = 0; j < to_read; j++) {
- moves->At(moves_offset + j) = CatchEntryMove::ReadFrom(stream);
- }
- if (suffix_length > 0) {
- ReadCompressedCatchEntryMovesSuffix(stream, suffix_offset, suffix_length,
- moves, moves_offset + to_read);
- }
- }
-
#else
void GetCatchEntryMovesFromDeopt(intptr_t num_vars, StackFrame* frame) {
Isolate* isolate = thread_->isolate();
@@ -415,6 +382,79 @@
}
#endif
+CatchEntryMoves* CatchEntryMovesMapReader::ReadMovesForPcOffset(
+ intptr_t pc_offset) {
+ NoSafepointScope no_safepoint;
+
+ ReadStream stream(static_cast<uint8_t*>(bytes_.DataAddr(0)), bytes_.Length());
+
+ intptr_t position = 0;
+ intptr_t length = 0;
+ FindEntryForPc(&stream, pc_offset, &position, &length);
+
+ return ReadCompressedCatchEntryMovesSuffix(&stream, position, length);
+}
+
+void CatchEntryMovesMapReader::FindEntryForPc(ReadStream* stream,
+ intptr_t pc_offset,
+ intptr_t* position,
+ intptr_t* length) {
+ using Reader = ReadStream::Raw<sizeof(intptr_t), intptr_t>;
+
+ while (stream->PendingBytes() > 0) {
+ const intptr_t stream_position = stream->Position();
+ const intptr_t target_pc_offset = Reader::Read(stream);
+ const intptr_t prefix_length = Reader::Read(stream);
+ const intptr_t suffix_length = Reader::Read(stream);
+ Reader::Read(stream); // Skip suffix_offset
+ if (pc_offset == target_pc_offset) {
+ *position = stream_position;
+ *length = prefix_length + suffix_length;
+ return;
+ }
+
+ // Skip the prefix moves.
+ for (intptr_t j = 0; j < prefix_length; j++) {
+ CatchEntryMove::ReadFrom(stream);
+ }
+ }
+
+ UNREACHABLE();
+}
+
+CatchEntryMoves* CatchEntryMovesMapReader::ReadCompressedCatchEntryMovesSuffix(
+ ReadStream* stream,
+ intptr_t offset,
+ intptr_t length) {
+ using Reader = ReadStream::Raw<sizeof(intptr_t), intptr_t>;
+
+ CatchEntryMoves* moves = CatchEntryMoves::Allocate(length);
+
+ intptr_t remaining_length = length;
+
+ intptr_t moves_offset = 0;
+ while (remaining_length > 0) {
+ stream->SetPosition(offset);
+ Reader::Read(stream); // skip pc_offset
+ Reader::Read(stream); // skip prefix length
+ const intptr_t suffix_length = Reader::Read(stream);
+ const intptr_t suffix_offset = Reader::Read(stream);
+ const intptr_t to_read = remaining_length - suffix_length;
+ if (to_read > 0) {
+ for (int j = 0; j < to_read; j++) {
+ // The prefix is written from the back.
+ moves->At(moves_offset + to_read - j - 1) =
+ CatchEntryMove::ReadFrom(stream);
+ }
+ remaining_length -= to_read;
+ moves_offset += to_read;
+ }
+ offset = suffix_offset;
+ }
+
+ return moves;
+}
+
static void FindErrorHandler(uword* handler_pc,
uword* handler_sp,
uword* handler_fp) {
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index d43201f..894f374 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -27,6 +27,7 @@
class WriteStream;
class String;
class Thread;
+class TypedData;
class Exceptions : AllStatic {
public:
@@ -190,7 +191,7 @@
(dest_slot() == src_slot());
}
- bool operator==(const CatchEntryMove& rhs) {
+ bool operator==(const CatchEntryMove& rhs) const {
return src_ == rhs.src_ && dest_and_kind_ == rhs.dest_and_kind_;
}
@@ -253,6 +254,30 @@
// Followed by CatchEntryMove[count_]
};
+// Used for reading the [CatchEntryMoves] from the compressed form.
+class CatchEntryMovesMapReader : public ValueObject {
+ public:
+ explicit CatchEntryMovesMapReader(const TypedData& bytes) : bytes_(bytes) {}
+
+ // The returned [CatchEntryMoves] must be freed by the caller via [free].
+ CatchEntryMoves* ReadMovesForPcOffset(intptr_t pc_offset);
+
+ private:
+ // Given the [pc_offset] this function will find the [position] at which to
+ // read the catch entries and the [length] of the catch entry moves array.
+ void FindEntryForPc(ReadStream* stream,
+ intptr_t pc_offset,
+ intptr_t* position,
+ intptr_t* length);
+
+ // Reads the [length] catch entry moves from [offset] in the [stream].
+ CatchEntryMoves* ReadCompressedCatchEntryMovesSuffix(ReadStream* stream,
+ intptr_t offset,
+ intptr_t length);
+
+ const TypedData& bytes_;
+};
+
// A simple reference counting wrapper for CatchEntryMoves.
//
// TODO(vegorov) switch this to intrusive reference counting.
diff --git a/runtime/vm/ffi_trampoline_stubs_x64.cc b/runtime/vm/ffi_trampoline_stubs_x64.cc
index 1afc9b5..a98236d 100644
--- a/runtime/vm/ffi_trampoline_stubs_x64.cc
+++ b/runtime/vm/ffi_trampoline_stubs_x64.cc
@@ -31,432 +31,13 @@
namespace dart {
-static intptr_t NumStackArguments(
- const ZoneGrowableArray<Location>& locations) {
- intptr_t num_arguments = locations.length();
- intptr_t num_stack_arguments = 0;
- for (intptr_t i = 0; i < num_arguments; i++) {
- if (locations.At(i).IsStackSlot()) {
- num_stack_arguments++;
- }
- }
- return num_stack_arguments;
-}
-
-// Input parameters:
-// Register reg : a Null, or something else
-static void GenerateNotNullCheck(Assembler* assembler, Register reg) {
- Label not_null;
- Address throw_null_pointer_address =
- Address(THR, Thread::OffsetFromThread(&kArgumentNullErrorRuntimeEntry));
-
- __ CompareObject(reg, Object::null_object());
- __ j(NOT_EQUAL, ¬_null, Assembler::kNearJump);
-
- // TODO(dacoharkes): Create the message here and use
- // kArgumentErrorRuntimeEntry to report which argument was null.
- __ movq(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
- __ movq(RBX, throw_null_pointer_address);
- __ movq(R10, Immediate(0));
- __ call(Address(THR, Thread::call_to_runtime_entry_point_offset()));
-
- __ Bind(¬_null);
-}
-
-// Saves an int64 in the thread so GC does not trip.
-//
-// Input parameters:
-// Register src : a C int64
-static void GenerateSaveInt64GCSafe(Assembler* assembler, Register src) {
- __ movq(Address(THR, Thread::unboxed_int64_runtime_arg_offset()), src);
-}
-
-// Loads an int64 from the thread.
-static void GenerateLoadInt64GCSafe(Assembler* assembler, Register dst) {
- __ movq(dst, Address(THR, Thread::unboxed_int64_runtime_arg_offset()));
-}
-
-// Takes a Dart int and converts it to a C int64.
-//
-// Input parameters:
-// Register reg : a Dart Null, Smi, or Mint
-// Output parameters:
-// Register reg : a C int64
-// Invariant: keeps ArgumentRegisters and XmmArgumentRegisters intact
-void GenerateMarshalInt64(Assembler* assembler, Register reg) {
- ASSERT(reg != TMP);
- ASSERT((1 << TMP & CallingConventions::kArgumentRegisters) == 0);
- Label done, not_smi;
-
- // Exception on Null
- GenerateNotNullCheck(assembler, reg);
-
- // Smi or Mint?
- __ movq(TMP, reg);
- __ testq(TMP, Immediate(kSmiTagMask));
- __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump);
-
- // Smi
- __ SmiUntag(reg);
- __ jmp(&done, Assembler::kNearJump);
-
- // Mint
- __ Bind(¬_smi);
- __ movq(reg, FieldAddress(reg, Mint::value_offset()));
- __ Bind(&done);
-}
-
-// Takes a C int64 and converts it to a Dart int.
-//
-// Input parameters:
-// RAX : a C int64
-// Output paramaters:
-// RAX : a Dart Smi or Mint
-static void GenerateUnmarshalInt64(Assembler* assembler) {
- const Class& mint_class =
- Class::ZoneHandle(Isolate::Current()->object_store()->mint_class());
- ASSERT(!mint_class.IsNull());
- const auto& mint_allocation_stub =
- Code::ZoneHandle(StubCode::GetAllocationStubForClass(mint_class));
- ASSERT(!mint_allocation_stub.IsNull());
- Label done;
-
- // Try whether it fits in a Smi.
- __ movq(TMP, RAX);
- __ SmiTag(RAX);
- __ j(NO_OVERFLOW, &done, Assembler::kNearJump);
-
- // Mint
- // Backup result value (to avoid GC).
- GenerateSaveInt64GCSafe(assembler, TMP);
-
- // Allocate object (can call into runtime).
- __ Call(mint_allocation_stub);
-
- // Store result value.
- GenerateLoadInt64GCSafe(assembler, TMP);
- __ movq(FieldAddress(RAX, Mint::value_offset()), TMP);
-
- __ Bind(&done);
-}
-
-// Takes a Dart double and converts it into a C double.
-//
-// Input parameters:
-// Register reg : a Dart Null or Double
-// Output parameters:
-// XmmRegister xmm_reg : a C double
-// Invariant: keeps ArgumentRegisters and other XmmArgumentRegisters intact
-static void GenerateMarshalDouble(Assembler* assembler,
- Register reg,
- XmmRegister xmm_reg) {
- ASSERT((1 << reg & CallingConventions::kArgumentRegisters) == 0);
-
- // Throw a Dart Exception on Null.
- GenerateNotNullCheck(assembler, reg);
-
- __ movq(reg, FieldAddress(reg, Double::value_offset()));
- __ movq(xmm_reg, reg);
-}
-
-// Takes a C double and converts it into a Dart double.
-//
-// Input parameters:
-// XMM0 : a C double
-// Output parameters:
-// RAX : a Dart Double
-static void GenerateUnmarshalDouble(Assembler* assembler) {
- const auto& double_class =
- Class::ZoneHandle(Isolate::Current()->object_store()->double_class());
- ASSERT(!double_class.IsNull());
- const auto& double_allocation_stub =
- Code::ZoneHandle(StubCode::GetAllocationStubForClass(double_class));
- ASSERT(!double_allocation_stub.IsNull());
-
- // Backup result value (to avoid GC).
- __ movq(RAX, XMM0);
- GenerateSaveInt64GCSafe(assembler, RAX);
-
- // Allocate object (can call into runtime).
- __ Call(double_allocation_stub);
-
- // Store the result value.
- GenerateLoadInt64GCSafe(assembler, TMP);
- __ movq(FieldAddress(RAX, Double::value_offset()), TMP);
-}
-
-// Takes a Dart double and converts into a C float.
-//
-// Input parameters:
-// Register reg : a Dart double
-// Output parameters:
-// XmmRegister xxmReg : a C float
-// Invariant: keeps ArgumentRegisters and other XmmArgumentRegisters intact
-static void GenerateMarshalFloat(Assembler* assembler,
- Register reg,
- XmmRegister xmm_reg) {
- ASSERT((1 << reg & CallingConventions::kArgumentRegisters) == 0);
-
- GenerateMarshalDouble(assembler, reg, xmm_reg);
-
- __ cvtsd2ss(xmm_reg, xmm_reg);
-}
-
-// Takes a C float and converts it into a Dart double.
-//
-// Input parameters:
-// XMM0 : a C float
-// Output paramaters:
-// RAX : a Dart Double
-static void GenerateUnmarshalFloat(Assembler* assembler) {
- __ cvtss2sd(XMM0, XMM0);
- GenerateUnmarshalDouble(assembler);
-}
-
-// Takes a Dart ffi.Pointer and converts it into a C pointer.
-//
-// Input parameters:
-// Register reg : a Dart ffi.Pointer or Null
-// Output parameters:
-// Register reg : a C pointer
-static void GenerateMarshalPointer(Assembler* assembler, Register reg) {
- Label done, not_null;
-
- __ CompareObject(reg, Object::null_object());
- __ j(NOT_EQUAL, ¬_null, Assembler::kNearJump);
-
- // If null, the address is 0.
- __ movq(reg, Immediate(0));
- __ jmp(&done);
-
- // If not null but a Pointer, load the address.
- __ Bind(¬_null);
- __ movq(reg, FieldAddress(reg, Pointer::c_memory_address_offset()));
- GenerateMarshalInt64(assembler, reg);
- __ Bind(&done);
-}
-
-// Takes a C pointer and converts it into a Dart ffi.Pointer or Null.
-//
-// Input parameters:
-// RAX : a C pointer
-// Outpot paramaters:
-// RAX : a Dart ffi.Pointer or Null
-static void GenerateUnmarshalPointer(Assembler* assembler,
- Address closure_dart,
- const Class& pointer_class) {
- Label done, not_null;
- ASSERT(!pointer_class.IsNull());
- const auto& pointer_allocation_stub =
- Code::ZoneHandle(StubCode::GetAllocationStubForClass(pointer_class));
- ASSERT(!pointer_allocation_stub.IsNull());
-
- // If the address is 0, return a Dart Null.
- __ cmpq(RAX, Immediate(0));
- __ j(NOT_EQUAL, ¬_null, Assembler::kNearJump);
- __ LoadObject(RAX, Object::null_object());
- __ jmp(&done);
-
- __ Bind(¬_null);
- GenerateUnmarshalInt64(assembler);
- __ pushq(RAX);
-
- // Allocate object (can call into runtime).
- __ movq(TMP, closure_dart);
- __ movq(TMP, FieldAddress(TMP, Closure::function_offset()));
- __ movq(TMP, FieldAddress(TMP, Function::result_type_offset()));
- __ pushq(FieldAddress(TMP, Type::arguments_offset()));
- __ Call(pointer_allocation_stub);
- __ popq(TMP); // Pop type arguments.
-
- // Store the result value.
- __ popq(RDX);
- __ movq(FieldAddress(RAX, Pointer::c_memory_address_offset()), RDX);
- __ Bind(&done);
-}
-
-static void GenerateMarshalArgument(Assembler* assembler,
- const AbstractType& arg_type,
- Register reg,
- XmmRegister xmm_reg) {
- switch (arg_type.type_class_id()) {
- case kFfiInt8Cid:
- case kFfiInt16Cid:
- case kFfiInt32Cid:
- case kFfiInt64Cid:
- case kFfiUint8Cid:
- case kFfiUint16Cid:
- case kFfiUint32Cid:
- case kFfiUint64Cid:
- case kFfiIntPtrCid:
- // TODO(dacoharkes): Truncate and sign extend 8 bit and 16 bit, and write
- // tests. https://github.com/dart-lang/sdk/issues/35787
- GenerateMarshalInt64(assembler, reg);
- return;
- case kFfiFloatCid:
- GenerateMarshalFloat(assembler, reg, xmm_reg);
- return;
- case kFfiDoubleCid:
- GenerateMarshalDouble(assembler, reg, xmm_reg);
- return;
- case kFfiPointerCid:
- default: // Subtypes of Pointer.
- GenerateMarshalPointer(assembler, reg);
- return;
- }
-}
-
-static void GenerateUnmarshalResult(Assembler* assembler,
- const AbstractType& result_type,
- Address closure_dart) {
- switch (result_type.type_class_id()) {
- case kFfiVoidCid:
- __ LoadObject(RAX, Object::null_object());
- return;
- case kFfiInt8Cid:
- case kFfiInt16Cid:
- case kFfiInt32Cid:
- case kFfiInt64Cid:
- case kFfiUint8Cid:
- case kFfiUint16Cid:
- case kFfiUint32Cid:
- case kFfiUint64Cid:
- case kFfiIntPtrCid:
- GenerateUnmarshalInt64(assembler);
- return;
- case kFfiFloatCid:
- GenerateUnmarshalFloat(assembler);
- return;
- case kFfiDoubleCid:
- GenerateUnmarshalDouble(assembler);
- return;
- case kFfiPointerCid:
- default: // subtypes of Pointer
- break;
- }
- Class& cls = Class::ZoneHandle(Thread::Current()->zone(),
- Type::Cast(result_type).type_class());
-
- GenerateUnmarshalPointer(assembler, closure_dart, cls);
-}
-
-// Generates a assembly for dart:ffi trampolines:
-// - marshal arguments
-// - put the arguments in registers and on the c stack
-// - invoke the c function
-// - (c result register is the same as dart, so keep in place)
-// - unmarshal c result
-// - return
-//
-// Input parameters:
-// RSP + kWordSize * num_arguments : closure.
-// RSP + kWordSize * (num_arguments - 1) : arg 1.
-// RSP + kWordSize * (num_arguments - 2) : arg 2.
-// RSP + kWordSize : arg n.
-// After entering stub:
-// RBP = RSP (before stub) - kWordSize
-// RBP + kWordSize * (num_arguments + 1) : closure.
-// RBP + kWordSize * num_arguments : arg 1.
-// RBP + kWordSize * (num_arguments - 1) : arg 2.
-// RBP + kWordSize * 2 : arg n.
-//
-// TODO(dacoharkes): Test truncation on non 64 bits ints and floats.
-void GenerateFfiTrampoline(Assembler* assembler, const Function& signature) {
- ZoneGrowableArray<Representation>* arg_representations =
- ffi::ArgumentRepresentations(signature);
- ZoneGrowableArray<Location>* arg_locations =
- ffi::ArgumentLocations(*arg_representations);
-
- intptr_t num_dart_arguments = signature.num_fixed_parameters();
- intptr_t num_arguments = num_dart_arguments - 1; // ignore closure
-
- __ EnterStubFrame();
-
- // Save exit frame information to enable stack walking as we are about
- // to transition to Dart VM C++ code.
- __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
-
-#if defined(DEBUG)
- {
- Label ok;
- // Check that we are always entering from Dart code.
- __ movq(TMP, Immediate(VMTag::kDartCompiledTagId));
- __ cmpq(TMP, Assembler::VMTagAddress());
- __ j(EQUAL, &ok, Assembler::kNearJump);
- __ Stop("Not coming from Dart code.");
- __ Bind(&ok);
- }
-#endif
-
- // Reserve space for arguments and align frame before entering C++ world.
- __ subq(RSP, Immediate(NumStackArguments(*arg_locations) * kWordSize));
- if (OS::ActivationFrameAlignment() > 1) {
- __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
- }
-
- // Prepare address for calling the C function.
- Address closure_dart = Address(RBP, (num_dart_arguments + 1) * kWordSize);
- __ movq(RBX, closure_dart);
- __ movq(RBX, FieldAddress(RBX, Closure::context_offset()));
- __ movq(RBX, FieldAddress(RBX, Context::variable_offset(0)));
- GenerateMarshalInt64(assembler, RBX); // Address is a Smi or Mint.
-
- // Marshal arguments and store in the right register.
- for (intptr_t i = 0; i < num_arguments; i++) {
- Representation rep = arg_representations->At(i);
- Location loc = arg_locations->At(i);
-
- // We do marshalling in the the target register or in RAX.
- Register reg = loc.IsRegister() ? loc.reg() : RAX;
- // For doubles and floats we use target xmm register or first non param reg.
- FpuRegister xmm_reg = loc.IsFpuRegister()
- ? loc.fpu_reg()
- : CallingConventions::xmmFirstNonParameterReg;
-
- // Load parameter from Dart stack.
- __ movq(reg, Address(RBP, (num_arguments + 1 - i) * kWordSize));
-
- // Marshal argument.
- AbstractType& arg_type =
- AbstractType::Handle(signature.ParameterTypeAt(i + 1));
- GenerateMarshalArgument(assembler, arg_type, reg, xmm_reg);
-
- // Store marshalled argument where c expects value.
- if (loc.IsStackSlot()) {
- if (rep == kUnboxedDouble) {
- __ movq(reg, xmm_reg);
- }
- __ movq(loc.ToStackSlotAddress(), reg);
- }
- }
-
- // Mark that the thread is executing VM code.
- __ movq(Assembler::VMTagAddress(), RBX);
-
- __ CallCFunction(RBX);
-
- // Mark that the thread is executing Dart code.
- __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
-
- // Unmarshal result.
- AbstractType& return_type = AbstractType::Handle(signature.result_type());
- GenerateUnmarshalResult(assembler, return_type, closure_dart);
-
- // Reset exit frame information in Isolate structure.
- __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
-
- __ LeaveStubFrame();
-
- __ ret();
-}
-
void GenerateFfiInverseTrampoline(Assembler* assembler,
const Function& signature,
void* dart_entry_point) {
ZoneGrowableArray<Representation>* arg_representations =
- ffi::ArgumentRepresentations(signature);
+ compiler::ffi::ArgumentRepresentations(signature);
ZoneGrowableArray<Location>* arg_locations =
- ffi::ArgumentLocations(*arg_representations);
+ compiler::ffi::ArgumentLocations(*arg_representations);
intptr_t num_dart_arguments = signature.num_fixed_parameters();
intptr_t num_arguments = num_dart_arguments - 1; // Ignore closure.
diff --git a/runtime/vm/heap/compactor.cc b/runtime/vm/heap/compactor.cc
index e3073a0..91e2058 100644
--- a/runtime/vm/heap/compactor.cc
+++ b/runtime/vm/heap/compactor.cc
@@ -483,6 +483,10 @@
// Slide the object down.
memmove(reinterpret_cast<void*>(new_addr),
reinterpret_cast<void*>(old_addr), size);
+
+ if (RawObject::IsTypedDataClassId(new_obj->GetClassId())) {
+ reinterpret_cast<RawTypedData*>(new_obj)->ResetData();
+ }
}
new_obj->ClearMarkBit();
new_obj->VisitPointers(compactor_);
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 35675f4..a7220d1 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -727,6 +727,18 @@
: old_space_.ExternalInWords();
}
+int64_t Heap::TotalUsedInWords() const {
+ return UsedInWords(kNew) + UsedInWords(kOld);
+}
+
+int64_t Heap::TotalCapacityInWords() const {
+ return CapacityInWords(kNew) + CapacityInWords(kOld);
+}
+
+int64_t Heap::TotalExternalInWords() const {
+ return ExternalInWords(kNew) + ExternalInWords(kOld);
+}
+
int64_t Heap::GCTimeInMicros(Space space) const {
if (space == kNew) {
return new_space_.gc_time_micros();
@@ -851,6 +863,14 @@
old_space_.PrintToJSONObject(object);
}
}
+
+void Heap::PrintMemoryUsageJSON(JSONStream* stream) const {
+ JSONObject jsobj(stream);
+ jsobj.AddProperty("type", "MemoryUsage");
+ jsobj.AddProperty64("heapUsage", TotalUsedInWords() * kWordSize);
+ jsobj.AddProperty64("heapCapacity", TotalCapacityInWords() * kWordSize);
+ jsobj.AddProperty64("externalUsage", TotalExternalInWords() * kWordSize);
+}
#endif // PRODUCT
void Heap::RecordBeforeGC(GCType type, GCReason reason) {
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 5ae4083..628ab15 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -180,6 +180,10 @@
int64_t UsedInWords(Space space) const;
int64_t CapacityInWords(Space space) const;
int64_t ExternalInWords(Space space) const;
+
+ int64_t TotalUsedInWords() const;
+ int64_t TotalCapacityInWords() const;
+ int64_t TotalExternalInWords() const;
// Return the amount of GCing in microseconds.
int64_t GCTimeInMicros(Space space) const;
@@ -268,6 +272,10 @@
#ifndef PRODUCT
void PrintToJSONObject(Space space, JSONObject* object) const;
+ // Returns a JSON object with total memory usage statistics for both new and
+ // old space combined.
+ void PrintMemoryUsageJSON(JSONStream* stream) const;
+
// The heap map contains the sizes and class ids for the objects in each page.
void PrintHeapMapToJSONStream(Isolate* isolate, JSONStream* stream) {
old_space_.PrintHeapMapToJSONStream(isolate, stream);
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 03c9683..6f4a183 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -368,6 +368,10 @@
}
static bool TryAcquireMarkBit(RawObject* raw_obj) {
+ if (FLAG_write_protect_code && raw_obj->IsInstructions()) {
+ // A non-writable alias mapping may exist for instruction pages.
+ raw_obj = HeapPage::ToWritable(raw_obj);
+ }
if (!sync) {
raw_obj->SetMarkBitUnsynchronized();
return true;
@@ -487,8 +491,9 @@
isolate_->ReleaseStoreBuffers();
#ifndef DART_PRECOMPILED_RUNTIME
- if (isolate_->IsMutatorThreadScheduled()) {
- Interpreter* interpreter = isolate_->mutator_thread()->interpreter();
+ Thread* mutator_thread = isolate_->mutator_thread();
+ if (mutator_thread != NULL) {
+ Interpreter* interpreter = mutator_thread->interpreter();
if (interpreter != NULL) {
interpreter->MajorGC();
}
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index e1ac801..19d8f04 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -57,11 +57,8 @@
HeapPage* HeapPage::Allocate(intptr_t size_in_words,
PageType type,
const char* name) {
- bool is_executable = (type == kExecutable);
- // Create the new page executable (RWX) only if we're not in W^X mode
- bool create_executable = !FLAG_write_protect_code && is_executable;
VirtualMemory* memory = VirtualMemory::AllocateAligned(
- size_in_words << kWordSizeLog2, kPageSize, create_executable, name);
+ size_in_words << kWordSizeLog2, kPageSize, type == kExecutable, name);
if (memory == NULL) {
return NULL;
}
@@ -214,7 +211,7 @@
VirtualMemory::Protection prot;
if (read_only) {
- if (type_ == kExecutable) {
+ if ((type_ == kExecutable) && (memory_->AliasOffset() == 0)) {
prot = VirtualMemory::kReadExecute;
} else {
prot = VirtualMemory::kReadOnly;
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 98d480f..d7381d7 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -40,7 +40,8 @@
HeapPage* next() const { return next_; }
void set_next(HeapPage* next) { next_ = next; }
- bool Contains(uword addr) { return memory_->Contains(addr); }
+ bool Contains(uword addr) const { return memory_->Contains(addr); }
+ intptr_t AliasOffset() const { return memory_->AliasOffset(); }
uword object_start() const { return memory_->start() + ObjectStartOffset(); }
uword object_end() const { return object_end_; }
@@ -70,7 +71,8 @@
}
// Warning: This does not work for objects on image pages because image pages
- // are not aligned.
+ // are not aligned. However, it works for objects on large pages, because
+ // only one object is allocated per large page.
static HeapPage* Of(RawObject* obj) {
ASSERT(obj->IsHeapObject());
ASSERT(obj->IsOldObject());
@@ -78,10 +80,45 @@
kPageMask);
}
- static HeapPage* Of(uintptr_t addr) {
+ // Warning: This does not work for addresses on image pages or on large pages.
+ static HeapPage* Of(uword addr) {
return reinterpret_cast<HeapPage*>(addr & kPageMask);
}
+ // Warning: This does not work for objects on image pages.
+ static RawObject* ToExecutable(RawObject* obj) {
+ HeapPage* page = Of(obj);
+ VirtualMemory* memory = page->memory_;
+ const intptr_t alias_offset = memory->AliasOffset();
+ if (alias_offset == 0) {
+ return obj; // Not aliased.
+ }
+ uword addr = RawObject::ToAddr(obj);
+ if (memory->Contains(addr)) {
+ return RawObject::FromAddr(addr + alias_offset);
+ }
+ // obj is executable.
+ ASSERT(memory->ContainsAlias(addr));
+ return obj;
+ }
+
+ // Warning: This does not work for objects on image pages.
+ static RawObject* ToWritable(RawObject* obj) {
+ HeapPage* page = Of(obj);
+ VirtualMemory* memory = page->memory_;
+ const intptr_t alias_offset = memory->AliasOffset();
+ if (alias_offset == 0) {
+ return obj; // Not aliased.
+ }
+ uword addr = RawObject::ToAddr(obj);
+ if (memory->ContainsAlias(addr)) {
+ return RawObject::FromAddr(addr - alias_offset);
+ }
+ // obj is writable.
+ ASSERT(memory->Contains(addr));
+ return obj;
+ }
+
// 1 card = 128 slots.
static const intptr_t kSlotsPerCardLog2 = 7;
static const intptr_t kBytesPerCardLog2 = kWordSizeLog2 + kSlotsPerCardLog2;
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 7abe066..0242715 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -60,6 +60,31 @@
*reinterpret_cast<uword*>(original) = target | kForwarded;
}
+static inline void objcpy(void* dst, const void* src, size_t size) {
+ // A memcopy specialized for objects. We can assume:
+ // - dst and src do not overlap
+ ASSERT(
+ (reinterpret_cast<uword>(dst) + size <= reinterpret_cast<uword>(src)) ||
+ (reinterpret_cast<uword>(src) + size <= reinterpret_cast<uword>(dst)));
+ // - dst and src are word aligned
+ ASSERT(Utils::IsAligned(reinterpret_cast<uword>(dst), sizeof(uword)));
+ ASSERT(Utils::IsAligned(reinterpret_cast<uword>(src), sizeof(uword)));
+ // - size is strictly positive
+ ASSERT(size > 0);
+ // - size is a multiple of double words
+ ASSERT(Utils::IsAligned(size, 2 * sizeof(uword)));
+
+ uword* __restrict dst_cursor = reinterpret_cast<uword*>(dst);
+ const uword* __restrict src_cursor = reinterpret_cast<const uword*>(src);
+ do {
+ uword a = *src_cursor++;
+ uword b = *src_cursor++;
+ *dst_cursor++ = a;
+ *dst_cursor++ = b;
+ size -= (2 * sizeof(uword));
+ } while (size > 0);
+}
+
class ScavengerVisitor : public ObjectPointerVisitor {
public:
explicit ScavengerVisitor(Isolate* isolate,
@@ -163,8 +188,8 @@
// current objects to the to space.
ASSERT(new_addr != 0);
// Copy the object to the new location.
- memmove(reinterpret_cast<void*>(new_addr),
- reinterpret_cast<void*>(raw_addr), size);
+ objcpy(reinterpret_cast<void*>(new_addr),
+ reinterpret_cast<void*>(raw_addr), size);
RawObject* new_obj = RawObject::FromAddr(new_addr);
if (new_obj->IsOldObject()) {
@@ -183,6 +208,10 @@
new_obj->ptr()->tags_ = tags;
}
+ if (RawObject::IsTypedDataClassId(new_obj->GetClassId())) {
+ reinterpret_cast<RawTypedData*>(new_obj)->ResetData();
+ }
+
// Remember forwarding address.
ForwardTo(raw_addr, new_addr);
}
@@ -422,6 +451,7 @@
NOT_IN_PRODUCT(isolate->class_table()->ResetCountersNew());
isolate->ReleaseStoreBuffers();
+ AbandonTLABs(isolate);
// Flip the two semi-spaces so that to_ is always the space for allocating
// objects.
@@ -833,11 +863,12 @@
}
}
-void Scavenger::MakeAllTLABsIterable(Isolate* isolate) const {
- MonitorLocker ml(isolate->threads_lock(), false);
+void Scavenger::MakeNewSpaceIterable() const {
ASSERT(Thread::Current()->IsAtSafepoint() ||
(Thread::Current()->task_kind() == Thread::kMarkerTask) ||
(Thread::Current()->task_kind() == Thread::kCompactorTask));
+ Isolate* isolate = heap_->isolate();
+ MonitorLocker ml(isolate->threads_lock(), false);
Thread* current = heap_->isolate()->thread_registry()->active_list();
while (current != NULL) {
if (current->HasActiveTLAB()) {
@@ -846,22 +877,12 @@
current = current->next();
}
Thread* mutator_thread = isolate->mutator_thread();
- if ((mutator_thread != NULL) && (!isolate->IsMutatorThreadScheduled())) {
+ if (mutator_thread != NULL) {
heap_->MakeTLABIterable(mutator_thread);
}
}
-void Scavenger::MakeNewSpaceIterable() const {
- ASSERT(heap_ != NULL);
- ASSERT(Thread::Current()->IsAtSafepoint() ||
- (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
- (Thread::Current()->task_kind() == Thread::kCompactorTask));
- if (!scavenging_) {
- MakeAllTLABsIterable(heap_->isolate());
- }
-}
-
-void Scavenger::AbandonAllTLABs(Isolate* isolate) {
+void Scavenger::AbandonTLABs(Isolate* isolate) {
ASSERT(Thread::Current()->IsAtSafepoint());
MonitorLocker ml(isolate->threads_lock(), false);
Thread* current = isolate->thread_registry()->active_list();
@@ -870,7 +891,7 @@
current = current->next();
}
Thread* mutator_thread = isolate->mutator_thread();
- if ((mutator_thread != NULL) && (!isolate->IsMutatorThreadScheduled())) {
+ if (mutator_thread != NULL) {
heap_->AbandonRemainingTLAB(mutator_thread);
}
}
@@ -975,13 +996,6 @@
int64_t safe_point = OS::GetCurrentMonotonicMicros();
heap_->RecordTime(kSafePoint, safe_point - start);
- AbandonAllTLABs(isolate);
-
- Thread* mutator_thread = isolate->mutator_thread();
- if ((mutator_thread != NULL) && (mutator_thread->HasActiveTLAB())) {
- heap_->AbandonRemainingTLAB(mutator_thread);
- }
-
// TODO(koda): Make verification more compatible with concurrent sweep.
if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) {
OS::PrintErr("Verifying before Scavenge...");
@@ -990,7 +1004,6 @@
}
// Prepare for a scavenge.
- MakeNewSpaceIterable();
SpaceUsage usage_before = GetCurrentUsage();
intptr_t promo_candidate_words =
(survivor_end_ - FirstObjectStart()) / kWordSize;
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index 1a6fe0a..7e5f623 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -218,8 +218,7 @@
void MakeNewSpaceIterable() const;
int64_t FreeSpaceInWords(Isolate* isolate) const;
- void MakeAllTLABsIterable(Isolate* isolate) const;
- void AbandonAllTLABs(Isolate* isolate);
+ void AbandonTLABs(Isolate* isolate);
private:
// Ids for time and data records in Heap::GCStats.
diff --git a/runtime/vm/heap/verifier.cc b/runtime/vm/heap/verifier.cc
index 8ea2fdb..237777e 100644
--- a/runtime/vm/heap/verifier.cc
+++ b/runtime/vm/heap/verifier.cc
@@ -49,6 +49,10 @@
RawObject* raw_obj = *current;
if (raw_obj->IsHeapObject()) {
if (!allocated_set_->Contains(raw_obj)) {
+ if (raw_obj->IsInstructions() &&
+ allocated_set_->Contains(HeapPage::ToWritable(raw_obj))) {
+ continue;
+ }
uword raw_addr = RawObject::ToAddr(raw_obj);
FATAL1("Invalid object pointer encountered %#" Px "\n", raw_addr);
}
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 88e6bb9..4ca767d 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -157,8 +157,9 @@
ObjectOffsetPair* pair = reuse_instructions_.Lookup(instructions);
if (pair == NULL) {
// Code should have been removed by DropCodeWithoutReusableInstructions.
- FATAL("Expected instructions to reuse\n");
+ return 0;
}
+ ASSERT(pair->offset != 0);
return pair->offset;
}
@@ -167,6 +168,7 @@
// Negative offsets tell the reader the offset is w/r/t the shared
// instructions image instead of the app-specific instructions image.
// Compare ImageReader::GetInstructionsAt.
+ ASSERT(pair->offset != 0);
return -pair->offset;
}
@@ -175,6 +177,7 @@
next_text_offset_ += instructions->HeapSize();
instructions_.Add(InstructionsData(instructions, code, offset));
+ ASSERT(offset != 0);
return offset;
}
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 49a8ddc..3e897e7 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -584,8 +584,40 @@
RawInstance* instance = reinterpret_cast<RawInstance*>(*call_base);
RawField* field = reinterpret_cast<RawField*>(function->ptr()->data_);
intptr_t offset_in_words = Smi::Value(field->ptr()->value_.offset_);
+ RawObject* value =
+ reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
+
+ const bool unboxing =
+ (field->ptr()->is_nullable_ != kNullCid) &&
+ Field::UnboxingCandidateBit::decode(field->ptr()->kind_bits_);
+ classid_t guarded_cid = field->ptr()->guarded_cid_;
+ if (unboxing && (guarded_cid == kDoubleCid)) {
+ double raw_value = Double::RawCast(value)->ptr()->value_;
+ if (!AllocateDoubleBox(thread, raw_value, *pc, *FP, *SP)) {
+ *invoked = true;
+ return false;
+ }
+ value = Double::RawCast(*SP[0]);
+ } else if (unboxing && (guarded_cid == kFloat32x4Cid)) {
+ simd128_value_t raw_value;
+ raw_value.readFrom(Float32x4::RawCast(value)->ptr()->value_);
+ if (!AllocateFloat32x4Box(thread, raw_value, *pc, *FP, *SP)) {
+ *invoked = true;
+ return false;
+ }
+ value = Float32x4::RawCast(*SP[0]);
+ } else if (unboxing && (guarded_cid == kFloat64x2Cid)) {
+ simd128_value_t raw_value;
+ raw_value.readFrom(Float64x2::RawCast(value)->ptr()->value_);
+ if (!AllocateFloat64x2Box(thread, raw_value, *pc, *FP, *SP)) {
+ *invoked = true;
+ return false;
+ }
+ value = Float64x2::RawCast(*SP[0]);
+ }
+
*SP = call_base;
- **SP = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
+ **SP = value;
*invoked = true;
return true;
}
@@ -669,9 +701,39 @@
instance = reinterpret_cast<RawInstance*>(call_base[0]);
value = call_base[1];
}
- instance->StorePointer(
- reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
- value, thread);
+
+ const bool unboxing =
+ (field->ptr()->is_nullable_ != kNullCid) &&
+ Field::UnboxingCandidateBit::decode(field->ptr()->kind_bits_);
+ classid_t guarded_cid = field->ptr()->guarded_cid_;
+ if (unboxing && (guarded_cid == kDoubleCid)) {
+ double raw_value = Double::RawCast(value)->ptr()->value_;
+ RawDouble* box =
+ *(reinterpret_cast<RawDouble**>(instance->ptr()) + offset_in_words);
+ ASSERT(box != null_value); // Non-initializing store.
+ box->ptr()->value_ = raw_value;
+ } else if (unboxing && (guarded_cid == kFloat32x4Cid)) {
+ simd128_value_t raw_value;
+ raw_value.readFrom(Float32x4::RawCast(value)->ptr()->value_);
+ RawFloat32x4* box =
+ *(reinterpret_cast<RawFloat32x4**>(instance->ptr()) +
+ offset_in_words);
+ ASSERT(box != null_value); // Non-initializing store.
+ raw_value.writeTo(box->ptr()->value_);
+ } else if (unboxing && (guarded_cid == kFloat64x2Cid)) {
+ simd128_value_t raw_value;
+ raw_value.readFrom(Float64x2::RawCast(value)->ptr()->value_);
+ RawFloat64x2* box =
+ *(reinterpret_cast<RawFloat64x2**>(instance->ptr()) +
+ offset_in_words);
+ ASSERT(box != null_value); // Non-initializing store.
+ raw_value.writeTo(box->ptr()->value_);
+ } else {
+ instance->StorePointer(
+ reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
+ value, thread);
+ }
+
*SP = call_base;
**SP = null_value;
*invoked = true;
@@ -1350,8 +1412,111 @@
if (!InvokeRuntime(thread, this, DRT_AllocateObject, args)) {
return false;
}
- *reinterpret_cast<int64_t*>(reinterpret_cast<uword>(SP[0]) -
- kHeapObjectTag + Mint::value_offset()) = value;
+ reinterpret_cast<RawMint*>(SP[0])->ptr()->value_ = value;
+ return true;
+ }
+}
+
+// Allocate _Double box for the given double value and puts it into SP[0].
+// Returns false on exception.
+DART_NOINLINE bool Interpreter::AllocateDoubleBox(Thread* thread,
+ double value,
+ uint32_t* pc,
+ RawObject** FP,
+ RawObject** SP) {
+ const intptr_t instance_size = Double::InstanceSize();
+ const uword start =
+ thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
+ if (LIKELY(start != 0)) {
+ uword tags = 0;
+ tags = RawObject::ClassIdTag::update(kDoubleCid, tags);
+ tags = RawObject::SizeTag::update(instance_size, tags);
+ tags = RawObject::NewBit::update(true, tags);
+ // Also writes zero in the hash_ field.
+ *reinterpret_cast<uword*>(start + Double::tags_offset()) = tags;
+ *reinterpret_cast<double*>(start + Double::value_offset()) = value;
+ SP[0] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
+ return true;
+ } else {
+ SP[0] = 0; // Space for the result.
+ SP[1] = thread->isolate()->object_store()->double_class(); // Class object.
+ SP[2] = Object::null(); // Type arguments.
+ Exit(thread, FP, SP + 3, pc);
+ NativeArguments args(thread, 2, SP + 1, SP);
+ if (!InvokeRuntime(thread, this, DRT_AllocateObject, args)) {
+ return false;
+ }
+ reinterpret_cast<RawDouble*>(SP[0])->ptr()->value_ = value;
+ return true;
+ }
+}
+
+// Allocate _Float32x4 box for the given simd value and puts it into SP[0].
+// Returns false on exception.
+DART_NOINLINE bool Interpreter::AllocateFloat32x4Box(Thread* thread,
+ simd128_value_t value,
+ uint32_t* pc,
+ RawObject** FP,
+ RawObject** SP) {
+ const intptr_t instance_size = Float32x4::InstanceSize();
+ const uword start =
+ thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
+ if (LIKELY(start != 0)) {
+ uword tags = 0;
+ tags = RawObject::ClassIdTag::update(kFloat32x4Cid, tags);
+ tags = RawObject::SizeTag::update(instance_size, tags);
+ tags = RawObject::NewBit::update(true, tags);
+ // Also writes zero in the hash_ field.
+ *reinterpret_cast<uword*>(start + Float32x4::tags_offset()) = tags;
+ SP[0] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
+ value.writeTo(reinterpret_cast<RawFloat32x4*>(SP[0])->ptr()->value_);
+ return true;
+ } else {
+ SP[0] = 0; // Space for the result.
+ SP[1] =
+ thread->isolate()->object_store()->float32x4_class(); // Class object.
+ SP[2] = Object::null(); // Type arguments.
+ Exit(thread, FP, SP + 3, pc);
+ NativeArguments args(thread, 2, SP + 1, SP);
+ if (!InvokeRuntime(thread, this, DRT_AllocateObject, args)) {
+ return false;
+ }
+ value.writeTo(reinterpret_cast<RawFloat32x4*>(SP[0])->ptr()->value_);
+ return true;
+ }
+}
+
+// Allocate _Float64x2 box for the given simd value and puts it into SP[0].
+// Returns false on exception.
+DART_NOINLINE bool Interpreter::AllocateFloat64x2Box(Thread* thread,
+ simd128_value_t value,
+ uint32_t* pc,
+ RawObject** FP,
+ RawObject** SP) {
+ const intptr_t instance_size = Float64x2::InstanceSize();
+ const uword start =
+ thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
+ if (LIKELY(start != 0)) {
+ uword tags = 0;
+ tags = RawObject::ClassIdTag::update(kFloat64x2Cid, tags);
+ tags = RawObject::SizeTag::update(instance_size, tags);
+ tags = RawObject::NewBit::update(true, tags);
+ // Also writes zero in the hash_ field.
+ *reinterpret_cast<uword*>(start + Float64x2::tags_offset()) = tags;
+ SP[0] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
+ value.writeTo(reinterpret_cast<RawFloat64x2*>(SP[0])->ptr()->value_);
+ return true;
+ } else {
+ SP[0] = 0; // Space for the result.
+ SP[1] =
+ thread->isolate()->object_store()->float64x2_class(); // Class object.
+ SP[2] = Object::null(); // Type arguments.
+ Exit(thread, FP, SP + 3, pc);
+ NativeArguments args(thread, 2, SP + 1, SP);
+ if (!InvokeRuntime(thread, this, DRT_AllocateObject, args)) {
+ return false;
+ }
+ value.writeTo(reinterpret_cast<RawFloat32x4*>(SP[0])->ptr()->value_);
return true;
}
}
@@ -2230,30 +2395,74 @@
RawField* field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
RawObject* value = reinterpret_cast<RawObject*>(SP[0]);
- SP -= 2; // Drop instance and value.
intptr_t offset_in_words = Smi::Value(field->ptr()->value_.offset_);
if (thread->isolate()->use_field_guards() &&
InterpreterHelpers::FieldNeedsGuardUpdate(field, value)) {
- SP[1] = instance; // Preserve.
- SP[2] = 0; // Unused result of runtime call.
- SP[3] = field;
- SP[4] = value;
- Exit(thread, FP, SP + 5, pc);
- NativeArguments args(thread, 2, /* argv */ SP + 3, /* retval */ SP + 2);
+ SP[1] = 0; // Unused result of runtime call.
+ SP[2] = field;
+ SP[3] = value;
+ Exit(thread, FP, SP + 4, pc);
+ NativeArguments args(thread, 2, /* argv */ SP + 2, /* retval */ SP + 1);
if (!InvokeRuntime(thread, this, DRT_UpdateFieldCid, args)) {
HANDLE_EXCEPTION;
}
// Reload objects after the call which may trigger GC.
- instance = reinterpret_cast<RawInstance*>(SP[1]);
- value = SP[4];
+ field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
+ instance = reinterpret_cast<RawInstance*>(SP[-1]);
+ value = SP[0];
}
- instance->StorePointer(
- reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words, value,
- thread);
+ const bool unboxing =
+ (field->ptr()->is_nullable_ != kNullCid) &&
+ Field::UnboxingCandidateBit::decode(field->ptr()->kind_bits_);
+ classid_t guarded_cid = field->ptr()->guarded_cid_;
+ if (unboxing && (guarded_cid == kDoubleCid)) {
+ double raw_value = Double::RawCast(value)->ptr()->value_;
+ ASSERT(*(reinterpret_cast<RawDouble**>(instance->ptr()) +
+ offset_in_words) == null_value); // Initializing store.
+ if (!AllocateDoubleBox(thread, raw_value, pc, FP, SP)) {
+ HANDLE_EXCEPTION;
+ }
+ RawDouble* box = Double::RawCast(SP[0]);
+ instance = reinterpret_cast<RawInstance*>(SP[-1]);
+ instance->StorePointer(
+ reinterpret_cast<RawDouble**>(instance->ptr()) + offset_in_words, box,
+ thread);
+ } else if (unboxing && (guarded_cid == kFloat32x4Cid)) {
+ simd128_value_t raw_value;
+ raw_value.readFrom(Float32x4::RawCast(value)->ptr()->value_);
+ ASSERT(*(reinterpret_cast<RawFloat32x4**>(instance->ptr()) +
+ offset_in_words) == null_value); // Initializing store.
+ if (!AllocateFloat32x4Box(thread, raw_value, pc, FP, SP)) {
+ HANDLE_EXCEPTION;
+ }
+ RawFloat32x4* box = Float32x4::RawCast(SP[0]);
+ instance = reinterpret_cast<RawInstance*>(SP[-1]);
+ instance->StorePointer(
+ reinterpret_cast<RawFloat32x4**>(instance->ptr()) + offset_in_words,
+ box, thread);
+ } else if (unboxing && (guarded_cid == kFloat64x2Cid)) {
+ simd128_value_t raw_value;
+ raw_value.readFrom(Float64x2::RawCast(value)->ptr()->value_);
+ ASSERT(*(reinterpret_cast<RawFloat64x2**>(instance->ptr()) +
+ offset_in_words) == null_value); // Initializing store.
+ if (!AllocateFloat64x2Box(thread, raw_value, pc, FP, SP)) {
+ HANDLE_EXCEPTION;
+ }
+ RawFloat64x2* box = Float64x2::RawCast(SP[0]);
+ instance = reinterpret_cast<RawInstance*>(SP[-1]);
+ instance->StorePointer(
+ reinterpret_cast<RawFloat64x2**>(instance->ptr()) + offset_in_words,
+ box, thread);
+ } else {
+ instance->StorePointer(
+ reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
+ value, thread);
+ }
+ SP -= 2; // Drop instance and value.
DISPATCH();
}
@@ -2289,6 +2498,16 @@
{
BYTECODE(LoadFieldTOS, __D);
+#if defined(DEBUG)
+ // Currently only used to load closure fields, which are not unboxed.
+ // If used for general field, code for copying the mutable box must be
+ // added.
+ RawField* field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
+ const bool unboxing =
+ (field->ptr()->is_nullable_ != kNullCid) &&
+ Field::UnboxingCandidateBit::decode(field->ptr()->kind_bits_);
+ ASSERT(!unboxing);
+#endif
const uword offset_in_words =
static_cast<uword>(Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))));
RawInstance* instance = static_cast<RawInstance*>(SP[0]);
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index 4e98f3e..effc48a 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -210,6 +210,21 @@
uint32_t* pc,
RawObject** FP,
RawObject** SP);
+ bool AllocateDoubleBox(Thread* thread,
+ double value,
+ uint32_t* pc,
+ RawObject** FP,
+ RawObject** SP);
+ bool AllocateFloat32x4Box(Thread* thread,
+ simd128_value_t value,
+ uint32_t* pc,
+ RawObject** FP,
+ RawObject** SP);
+ bool AllocateFloat64x2Box(Thread* thread,
+ simd128_value_t value,
+ uint32_t* pc,
+ RawObject** FP,
+ RawObject** SP);
#if defined(DEBUG)
// Returns true if tracing of executed instructions is enabled.
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 6be1715..ce8ed3f 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2288,6 +2288,14 @@
jsobj.AddProperty("_threads", thread_registry_);
}
+
+void Isolate::PrintMemoryUsageJSON(JSONStream* stream) {
+ if (!FLAG_support_service) {
+ return;
+ }
+ heap()->PrintMemoryUsageJSON(stream);
+}
+
#endif
void Isolate::set_tag_table(const GrowableObjectArray& value) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 086831b..40f0c6f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -238,11 +238,6 @@
Thread* mutator_thread() const;
- // Mutator thread is not scheduled if NULL or no heap is attached
- // to it. The latter only occurs when the mutator thread object
- // is unscheduled by the isolate (or never scheduled).
- bool IsMutatorThreadScheduled() { return scheduled_mutator_thread_ != NULL; }
-
const char* name() const { return name_; }
void set_name(const char* name);
@@ -520,6 +515,10 @@
#ifndef PRODUCT
void PrintJSON(JSONStream* stream, bool ref = true);
+
+ // Creates an object with the total heap memory usage statistics for this
+ // isolate.
+ void PrintMemoryUsageJSON(JSONStream* stream);
#endif
#if !defined(PRODUCT)
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index edf12af..5d67407 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -4,6 +4,7 @@
#include "vm/kernel.h"
+#include "vm/bit_vector.h"
#include "vm/compiler/frontend/constant_evaluator.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/longjump.h"
@@ -585,91 +586,100 @@
}
}
-bool NeedsDynamicInvocationForwarder(const Function& function) {
+void ReadParameterCovariance(const Function& function,
+ BitVector* is_covariant,
+ BitVector* is_generic_covariant_impl) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- TranslationHelper helper(thread);
- Script& script = Script::Handle(zone, function.script());
- helper.InitFromScript(script);
+ const intptr_t num_params = function.NumParameters();
+ ASSERT(is_covariant->length() == num_params);
+ ASSERT(is_generic_covariant_impl->length() == num_params);
- // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
- // e.g. for type translation.
-
- const Class& owner_class = Class::Handle(zone, function.Owner());
- Function& outermost_function =
- Function::Handle(zone, function.GetOutermostFunction());
-
- ActiveClass active_class;
- ActiveClassScope active_class_scope(&active_class, &owner_class);
- ActiveMemberScope active_member(&active_class, &outermost_function);
- ActiveTypeParametersScope active_type_params(&active_class, function, zone);
+ const auto& script = Script::Handle(zone, function.script());
+ TranslationHelper translation_helper(thread);
+ translation_helper.InitFromScript(script);
KernelReaderHelper reader_helper(
- zone, &helper, script,
+ zone, &translation_helper, script,
ExternalTypedData::Handle(zone, function.KernelData()),
function.KernelDataProgramOffset());
- TypeTranslator type_translator(&reader_helper, &active_class,
- /* finalize= */ true);
-
reader_helper.SetOffset(function.kernel_offset());
-
- // Handle setters.
- if (reader_helper.PeekTag() == kField) {
- ASSERT(function.IsImplicitSetterFunction());
- FieldHelper field_helper(&reader_helper);
- field_helper.ReadUntilIncluding(FieldHelper::kFlags);
- return !(field_helper.IsCovariant() ||
- field_helper.IsGenericCovariantImpl());
- }
-
reader_helper.ReadUntilFunctionNode();
FunctionNodeHelper function_node_helper(&reader_helper);
- function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
- intptr_t num_type_params = reader_helper.ReadListLength();
-
- for (intptr_t i = 0; i < num_type_params; ++i) {
- TypeParameterHelper helper(&reader_helper);
- helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
- AbstractType& bound = type_translator.BuildType(); // read bound
- helper.Finish();
-
- if (!bound.IsTopType() && !helper.IsGenericCovariantImpl()) {
- return true;
- }
- }
- function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
function_node_helper.ReadUntilExcluding(
FunctionNodeHelper::kPositionalParameters);
// Positional.
const intptr_t num_positional_params = reader_helper.ReadListLength();
- for (intptr_t i = 0; i < num_positional_params; ++i) {
+ intptr_t param_index = function.NumImplicitParameters();
+ for (intptr_t i = 0; i < num_positional_params; ++i, ++param_index) {
VariableDeclarationHelper helper(&reader_helper);
- helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
- AbstractType& type = type_translator.BuildType(); // read type.
- helper.SetJustRead(VariableDeclarationHelper::kType);
helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
- if (!type.IsTopType() && !helper.IsGenericCovariantImpl() &&
- !helper.IsCovariant()) {
- return true;
+ if (helper.IsCovariant()) {
+ is_covariant->Add(param_index);
+ }
+ if (helper.IsGenericCovariantImpl()) {
+ is_generic_covariant_impl->Add(param_index);
}
}
// Named.
const intptr_t num_named_params = reader_helper.ReadListLength();
- for (intptr_t i = 0; i < num_named_params; ++i) {
+ for (intptr_t i = 0; i < num_named_params; ++i, ++param_index) {
VariableDeclarationHelper helper(&reader_helper);
- helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
- AbstractType& type = type_translator.BuildType(); // read type.
- helper.SetJustRead(VariableDeclarationHelper::kType);
helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
- if (!type.IsTopType() && !helper.IsGenericCovariantImpl() &&
- !helper.IsCovariant()) {
+ if (helper.IsCovariant()) {
+ is_covariant->Add(param_index);
+ }
+ if (helper.IsGenericCovariantImpl()) {
+ is_generic_covariant_impl->Add(param_index);
+ }
+ }
+}
+
+bool NeedsDynamicInvocationForwarder(const Function& function) {
+ Zone* zone = Thread::Current()->zone();
+
+ // Covariant parameters (both explicitly covariant and generic-covariant-impl)
+ // are checked in the body of a function and therefore don't need checks in a
+ // dynamic invocation forwarder. So dynamic invocation forwarder is only
+ // needed if there are non-covariant parameters of non-top type.
+
+ ASSERT(!function.IsImplicitGetterFunction());
+ if (function.IsImplicitSetterFunction()) {
+ const auto& field = Field::Handle(zone, function.accessor_field());
+ return !(field.is_covariant() || field.is_generic_covariant_impl());
+ }
+
+ const auto& type_params =
+ TypeArguments::Handle(zone, function.type_parameters());
+ if (!type_params.IsNull()) {
+ auto& type_param = TypeParameter::Handle(zone);
+ auto& bound = AbstractType::Handle(zone);
+ for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
+ type_param ^= type_params.TypeAt(i);
+ bound = type_param.bound();
+ if (!bound.IsTopType() && !type_param.IsGenericCovariantImpl()) {
+ return true;
+ }
+ }
+ }
+
+ const intptr_t num_params = function.NumParameters();
+ BitVector is_covariant(zone, num_params);
+ BitVector is_generic_covariant_impl(zone, num_params);
+ ReadParameterCovariance(function, &is_covariant, &is_generic_covariant_impl);
+
+ auto& type = AbstractType::Handle(zone);
+ for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
+ type = function.ParameterTypeAt(i);
+ if (!type.IsTopType() && !is_generic_covariant_impl.Contains(i) &&
+ !is_covariant.Contains(i)) {
return true;
}
}
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 34609b8..db52690 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -32,6 +32,7 @@
#if !defined(DART_PRECOMPILED_RUNTIME)
namespace dart {
+class BitVector;
class Field;
class ParsedFunction;
class Zone;
@@ -194,6 +195,15 @@
bool is_annotations_offset);
RawObject* BuildParameterDescriptor(const Function& function);
+// Fills in [is_covariant] and [is_generic_covariant_impl] vectors
+// according to covariance attributes of [function] parameters.
+//
+// [is_covariant] and [is_generic_covariant_impl] should contain bitvectors
+// of function.NumParameters() length.
+void ReadParameterCovariance(const Function& function,
+ BitVector* is_covariant,
+ BitVector* is_generic_covariant_impl);
+
// Returns true if the given function needs dynamic invocation forwarder:
// that is if any of the arguments require checking on the dynamic
// call-site: if function has no parameters or has only covariant parameters
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 7129b5f..28e92be 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
// Both version numbers are inclusive.
static const uint32_t kMinSupportedKernelFormatVersion = 18;
-static const uint32_t kMaxSupportedKernelFormatVersion = 20;
+static const uint32_t kMaxSupportedKernelFormatVersion = 21;
// Keep in sync with package:kernel/lib/binary/tag.dart
#define KERNEL_TAG_LIST(V) \
@@ -62,6 +62,9 @@
V(LogicalExpression, 34) \
V(ConditionalExpression, 35) \
V(StringConcatenation, 36) \
+ V(ListConcatenation, 111) \
+ V(SetConcatenation, 112) \
+ V(MapConcatenation, 113) \
V(IsExpression, 37) \
V(AsExpression, 38) \
V(StringLiteral, 39) \
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index d962d85..fa5549e 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -676,6 +676,14 @@
}
}
+ // Set pending fields array to flag constant table loading.
+ ASSERT(I->object_store()->pending_unevaluated_const_fields() ==
+ GrowableObjectArray::null());
+ GrowableObjectArray& pending_unevaluated_const_fields =
+ GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
+ I->object_store()->set_pending_unevaluated_const_fields(
+ pending_unevaluated_const_fields);
+
// All classes were successfully loaded, so let's:
// a) load & canonicalize the constant table
const Array& constants = ReadConstantTable();
@@ -690,6 +698,22 @@
kernel_program_info_.set_constants(constants);
kernel_program_info_.set_constants_table(ExternalTypedData::Handle(Z));
+ // d) evaluate pending field initializers
+ Error& error = Error::Handle(Z);
+ Field& field = Field::Handle(Z);
+ for (intptr_t i = 0, n = pending_unevaluated_const_fields.Length(); i < n;
+ i++) {
+ field ^= pending_unevaluated_const_fields.At(i);
+ error = field.EvaluateInitializer();
+ if (!error.IsNull()) {
+ H.ReportError(error, "postponed field initializer");
+ }
+ }
+ pending_unevaluated_const_fields = GrowableObjectArray::null();
+ I->object_store()->set_pending_unevaluated_const_fields(
+ pending_unevaluated_const_fields);
+
+ // e) evaluate pragmas that were delayed
EvaluateDelayedPragmas();
NameIndex main = program_->main_method();
@@ -1067,6 +1091,9 @@
// In the VM all const fields are implicitly final whereas in Kernel they
// are not final because they are not explicitly declared that way.
const bool is_final = field_helper.IsConst() || field_helper.IsFinal();
+ // Only instance fields could be covariant.
+ ASSERT(!field_helper.IsCovariant() &&
+ !field_helper.IsGenericCovariantImpl());
const Field& field = Field::Handle(
Z,
Field::NewTopLevel(name, is_final, field_helper.IsConst(), script_class,
@@ -1197,7 +1224,7 @@
target_library.url() == Symbols::DartMirrors().raw()) {
H.ReportError("import of dart:mirrors with --enable-mirrors=false");
}
- if (!Api::ffiEnabled() &&
+ if (!Api::IsFfiEnabled() &&
target_library.url() == Symbols::DartFfi().raw()) {
H.ReportError("import of dart:ffi with --enable-ffi=false");
}
@@ -1490,6 +1517,9 @@
field_helper.position_, field_helper.end_position_));
field.set_kernel_offset(field_offset);
field.set_has_pragma(has_pragma_annotation);
+ field.set_is_covariant(field_helper.IsCovariant());
+ field.set_is_generic_covariant_impl(
+ field_helper.IsGenericCovariantImpl());
ReadInferredType(field, field_offset + library_kernel_offset_);
CheckForInitializer(field);
field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 864555d..86b63a5 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1223,6 +1223,7 @@
intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0));
ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size);
raw->StoreSmi(&(raw->ptr()->length_), Smi::New(leftover_len));
+ raw->ResetData();
} else {
// Update the leftover space as a basic object.
ASSERT(leftover_size == Object::InstanceSize());
@@ -1641,9 +1642,11 @@
pending_classes.Add(cls);
CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
+
cls = Class::NewTypedDataViewClass(kByteDataViewCid);
RegisterPrivateClass(cls, Symbols::_ByteDataView(), lib);
pending_classes.Add(cls);
+
#undef REGISTER_TYPED_DATA_VIEW_CLASS
#define REGISTER_EXT_TYPED_DATA_CLASS(clazz) \
cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid); \
@@ -2015,7 +2018,12 @@
bool Object::IsReadOnly() const {
if (FLAG_verify_handles && raw()->IsReadOnly()) {
Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
- ASSERT(vm_isolate_heap->Contains(RawObject::ToAddr(raw())));
+ uword addr = RawObject::ToAddr(raw());
+ if (!vm_isolate_heap->Contains(addr)) {
+ ASSERT(FLAG_write_protect_code);
+ addr = RawObject::ToAddr(HeapPage::ToWritable(raw()));
+ ASSERT(vm_isolate_heap->Contains(addr));
+ }
}
return raw()->IsReadOnly();
}
@@ -2072,8 +2080,12 @@
Isolate* isolate = Isolate::Current();
Heap* isolate_heap = isolate->heap();
Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
- ASSERT(isolate_heap->Contains(RawObject::ToAddr(raw_)) ||
- vm_isolate_heap->Contains(RawObject::ToAddr(raw_)));
+ uword addr = RawObject::ToAddr(raw_);
+ if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
+ ASSERT(FLAG_write_protect_code);
+ addr = RawObject::ToAddr(HeapPage::ToWritable(raw_));
+ ASSERT(isolate_heap->Contains(addr) || vm_isolate_heap->Contains(addr));
+ }
}
}
#endif
@@ -2997,7 +3009,7 @@
return false;
}
-bool Function::IsDynamicInvocationForwaderName(const String& name) {
+bool Function::IsDynamicInvocationForwarderName(const String& name) {
return name.StartsWith(Symbols::DynamicPrefix());
}
@@ -3047,7 +3059,7 @@
RawFunction* Function::GetDynamicInvocationForwarder(
const String& mangled_name,
bool allow_add /* = true */) const {
- ASSERT(IsDynamicInvocationForwaderName(mangled_name));
+ ASSERT(IsDynamicInvocationForwarderName(mangled_name));
const Class& owner = Class::Handle(Owner());
Function& result = Function::Handle(owner.GetInvocationDispatcher(
mangled_name, Array::null_array(),
@@ -3699,9 +3711,11 @@
RawClass* Class::NewTypedDataViewClass(intptr_t class_id) {
ASSERT(RawObject::IsTypedDataViewClassId(class_id));
- Class& result = Class::Handle(New<Instance>(class_id));
- result.set_instance_size(0);
- result.set_next_field_offset(-kWordSize);
+ const intptr_t instance_size = TypedDataView::InstanceSize();
+ Class& result = Class::Handle(New<TypedDataView>(class_id));
+ result.set_instance_size(instance_size);
+ result.set_next_field_offset(TypedDataView::NextFieldOffset());
+ result.set_is_prefinalized();
return result.raw();
}
@@ -5857,7 +5871,8 @@
RawField* Function::accessor_field() const {
ASSERT(kind() == RawFunction::kImplicitGetter ||
kind() == RawFunction::kImplicitSetter ||
- kind() == RawFunction::kImplicitStaticFinalGetter);
+ kind() == RawFunction::kImplicitStaticFinalGetter ||
+ kind() == RawFunction::kDynamicInvocationForwarder);
return Field::RawCast(raw_ptr()->data_);
}
@@ -5975,6 +5990,20 @@
}
}
+void Function::SetFfiCSignature(const Function& sig) const {
+ ASSERT(IsFfiTrampoline());
+ const Object& obj = Object::Handle(raw_ptr()->data_);
+ ASSERT(!obj.IsNull());
+ FfiTrampolineData::Cast(obj).set_c_signature(sig);
+}
+
+RawFunction* Function::FfiCSignature() const {
+ ASSERT(IsFfiTrampoline());
+ const Object& obj = Object::Handle(raw_ptr()->data_);
+ ASSERT(!obj.IsNull());
+ return FfiTrampolineData::Cast(obj).c_signature();
+}
+
RawType* Function::SignatureType() const {
Type& type = Type::Handle(ExistingSignatureType());
if (type.IsNull()) {
@@ -7334,46 +7363,17 @@
// Change covariant parameter types to Object in the implicit closure.
if (!is_static()) {
- const Script& function_script = Script::Handle(zone, script());
- kernel::TranslationHelper translation_helper(thread);
- translation_helper.InitFromScript(function_script);
+ BitVector is_covariant(zone, NumParameters());
+ BitVector is_generic_covariant_impl(zone, NumParameters());
+ kernel::ReadParameterCovariance(*this, &is_covariant,
+ &is_generic_covariant_impl);
- kernel::KernelReaderHelper kernel_reader_helper(
- zone, &translation_helper, function_script,
- ExternalTypedData::Handle(zone, KernelData()),
- KernelDataProgramOffset());
-
- kernel_reader_helper.SetOffset(kernel_offset());
- kernel_reader_helper.ReadUntilFunctionNode();
-
- kernel::FunctionNodeHelper fn_helper(&kernel_reader_helper);
-
- // Check the positional parameters, including the optional positional ones.
- fn_helper.ReadUntilExcluding(
- kernel::FunctionNodeHelper::kPositionalParameters);
- intptr_t num_pos_params = kernel_reader_helper.ReadListLength();
- ASSERT(num_pos_params ==
- num_fixed_params - 1 + (has_opt_pos_params ? num_opt_params : 0));
const Type& object_type = Type::Handle(zone, Type::ObjectType());
- for (intptr_t i = 0; i < num_pos_params; ++i) {
- kernel::VariableDeclarationHelper var_helper(&kernel_reader_helper);
- var_helper.ReadUntilExcluding(kernel::VariableDeclarationHelper::kEnd);
- if (var_helper.IsCovariant() || var_helper.IsGenericCovariantImpl()) {
- closure_function.SetParameterTypeAt(i + 1, object_type);
- }
- }
- fn_helper.SetJustRead(kernel::FunctionNodeHelper::kPositionalParameters);
-
- // Check the optional named parameters.
- fn_helper.ReadUntilExcluding(kernel::FunctionNodeHelper::kNamedParameters);
- intptr_t num_named_params = kernel_reader_helper.ReadListLength();
- ASSERT(num_named_params == (has_opt_pos_params ? 0 : num_opt_params));
- for (intptr_t i = 0; i < num_named_params; ++i) {
- kernel::VariableDeclarationHelper var_helper(&kernel_reader_helper);
- var_helper.ReadUntilExcluding(kernel::VariableDeclarationHelper::kEnd);
- if (var_helper.IsCovariant() || var_helper.IsGenericCovariantImpl()) {
- closure_function.SetParameterTypeAt(num_pos_params + 1 + i,
- object_type);
+ for (intptr_t i = kClosure; i < num_params; ++i) {
+ const intptr_t original_param_index = has_receiver - kClosure + i;
+ if (is_covariant.Contains(original_param_index) ||
+ is_generic_covariant_impl.Contains(original_param_index)) {
+ closure_function.SetParameterTypeAt(i, object_type);
}
}
}
@@ -7991,13 +7991,13 @@
kind_str = " no-such-method-dispatcher";
break;
case RawFunction::kDynamicInvocationForwarder:
- kind_str = " dynamic-invocation-forwader";
+ kind_str = " dynamic-invocation-forwarder";
break;
case RawFunction::kInvokeFieldDispatcher:
- kind_str = "invoke-field-dispatcher";
+ kind_str = " invoke-field-dispatcher";
break;
case RawFunction::kIrregexpFunction:
- kind_str = "irregexp-function";
+ kind_str = " irregexp-function";
break;
case RawFunction::kFfiTrampoline:
kind_str = " ffi-trampoline-function";
@@ -8117,6 +8117,10 @@
StorePointer(&raw_ptr()->signature_type_, value.raw());
}
+void FfiTrampolineData::set_c_signature(const Function& value) const {
+ StorePointer(&raw_ptr()->c_signature_, value.raw());
+}
+
RawFfiTrampolineData* FfiTrampolineData::New() {
ASSERT(Object::ffi_trampoline_data_class() != Class::null());
RawObject* raw =
@@ -8278,27 +8282,6 @@
return PatchClass::Cast(obj).library_kernel_offset();
}
-#if !defined(DART_PRECOMPILED_RUNTIME)
-void Field::GetCovarianceAttributes(bool* is_covariant,
- bool* is_generic_covariant) const {
- Thread* thread = Thread::Current();
- Zone* zone = Thread::Current()->zone();
- auto& script = Script::Handle(zone, Script());
-
- kernel::TranslationHelper translation_helper(thread);
- translation_helper.InitFromScript(script);
-
- kernel::KernelReaderHelper kernel_reader_helper(
- zone, &translation_helper, script,
- ExternalTypedData::Handle(zone, KernelData()), KernelDataProgramOffset());
- kernel_reader_helper.SetOffset(kernel_offset());
- kernel::FieldHelper field_helper(&kernel_reader_helper);
- field_helper.ReadUntilIncluding(kernel::FieldHelper::kFlags);
- *is_covariant = field_helper.IsCovariant();
- *is_generic_covariant = field_helper.IsGenericCovariantImpl();
-}
-#endif
-
// Called at finalization time
void Field::SetFieldType(const AbstractType& value) const {
ASSERT(Thread::Current()->IsMutatorThread());
@@ -8339,7 +8322,7 @@
result.set_token_pos(token_pos);
result.set_end_token_pos(end_token_pos);
result.set_has_initializer(false);
- result.set_is_unboxing_candidate(true);
+ result.set_is_unboxing_candidate(!is_final);
result.set_initializer_changed_after_initialization(false);
result.set_kernel_offset(0);
result.set_has_pragma(false);
@@ -13357,7 +13340,7 @@
#if !defined(DART_PRECOMPILED_RUNTIME)
if (smi_op_target.IsNull() &&
- Function::IsDynamicInvocationForwaderName(name)) {
+ Function::IsDynamicInvocationForwarderName(name)) {
const String& demangled =
String::Handle(Function::DemangleDynamicInvocationForwarderName(name));
smi_op_target = Resolver::ResolveDynamicAnyArgs(zone, smi_class, demangled);
@@ -13423,7 +13406,7 @@
bool ICData::ValidateInterceptor(const Function& target) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
const String& name = String::Handle(target_name());
- if (Function::IsDynamicInvocationForwaderName(name)) {
+ if (Function::IsDynamicInvocationForwarderName(name)) {
return Function::DemangleDynamicInvocationForwarderName(name) ==
target.name();
}
@@ -14562,6 +14545,24 @@
object->raw());
}
+ // Write protect instructions and, if supported by OS, use dual mapping
+ // for execution.
+ if (FLAG_write_protect_code) {
+ uword address = RawObject::ToAddr(instrs.raw());
+ // Check if a dual mapping exists.
+ instrs = Instructions::RawCast(HeapPage::ToExecutable(instrs.raw()));
+ uword exec_address = RawObject::ToAddr(instrs.raw());
+ if (exec_address != address) {
+ VirtualMemory::Protect(reinterpret_cast<void*>(address),
+ instrs.raw()->HeapSize(),
+ VirtualMemory::kReadOnly);
+ address = exec_address;
+ }
+ VirtualMemory::Protect(reinterpret_cast<void*>(address),
+ instrs.raw()->HeapSize(),
+ VirtualMemory::kReadExecute);
+ }
+
// Hook up Code and Instructions objects.
code.SetActiveInstructions(instrs);
code.set_instructions(instrs);
@@ -14572,13 +14573,6 @@
code.set_object_pool(object_pool->raw());
}
- if (FLAG_write_protect_code) {
- uword address = RawObject::ToAddr(instrs.raw());
- VirtualMemory::Protect(reinterpret_cast<void*>(address),
- instrs.raw()->HeapSize(),
- VirtualMemory::kReadExecute);
- }
-
#if defined(DART_PRECOMPILER)
if (stats != nullptr) {
stats->Finalize();
@@ -16391,13 +16385,11 @@
intptr_t Instance::DataOffsetFor(intptr_t cid) {
if (RawObject::IsExternalTypedDataClassId(cid) ||
- RawObject::IsExternalStringClassId(cid)) {
- // Elements start at offset 0 of the external data.
+ RawObject::IsExternalStringClassId(cid) ||
+ RawObject::IsTypedDataClassId(cid)) {
+ // Elements start at offset 0 of the external and typed data.
return 0;
}
- if (RawObject::IsTypedDataClassId(cid)) {
- return TypedData::data_offset();
- }
switch (cid) {
case kArrayCid:
case kImmutableArrayCid:
@@ -20863,9 +20855,11 @@
NoSafepointScope no_safepoint;
result ^= raw;
result.SetLength(len);
+ result.ResetData();
if (len > 0) {
memset(result.DataAddr(0), 0, lengthInBytes);
}
+ ASSERT(result.Length() == len);
}
return result.raw();
}
@@ -20907,6 +20901,37 @@
return result.raw();
}
+RawTypedDataView* TypedDataView::New(intptr_t class_id, Heap::Space space) {
+ auto& result = TypedDataView::Handle();
+ {
+ RawObject* raw =
+ Object::Allocate(class_id, TypedDataView::InstanceSize(), space);
+ NoSafepointScope no_safepoint;
+ result ^= raw;
+ result.clear_typed_data();
+ result.set_offset_in_bytes(0);
+ result.set_length(0);
+ }
+ return result.raw();
+}
+
+RawTypedDataView* TypedDataView::New(intptr_t class_id,
+ const Instance& typed_data,
+ intptr_t offset_in_bytes,
+ intptr_t length,
+ Heap::Space space) {
+ auto& result = TypedDataView::Handle(TypedDataView::New(class_id, space));
+ result.set_typed_data(typed_data);
+ result.set_offset_in_bytes(offset_in_bytes);
+ result.set_length(length);
+ return result.raw();
+}
+
+const char* TypedDataView::ToCString() const {
+ auto zone = Thread::Current()->zone();
+ return OS::SCreate(zone, "TypedDataView(cid: %" Pd ")", GetClassId());
+}
+
const char* ExternalTypedData::ToCString() const {
return "ExternalTypedData";
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index e19f357..044ecc5 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1256,7 +1256,7 @@
// Allocate the raw TypedData classes.
static RawClass* NewTypedDataClass(intptr_t class_id);
- // Allocate the raw TypedDataView classes.
+ // Allocate the raw TypedDataView/ByteDataView classes.
static RawClass* NewTypedDataViewClass(intptr_t class_id);
// Allocate the raw ExternalTypedData classes.
@@ -1978,6 +1978,14 @@
// Update the signature type (with a canonical version).
void SetSignatureType(const Type& value) const;
+ // Set the "C signature" function for an FFI trampoline.
+ // Can only be used on FFI trampolines.
+ void SetFfiCSignature(const Function& sig) const;
+
+ // Retrieves the "C signature" function for an FFI trampoline.
+ // Can only be used on FFI trampolines.
+ RawFunction* FfiCSignature() const;
+
// Return a new function with instantiated result and parameter types.
RawFunction* InstantiateSignatureFrom(
const TypeArguments& instantiator_type_arguments,
@@ -2185,7 +2193,7 @@
return kind() == RawFunction::kInvokeFieldDispatcher;
}
- bool IsDynamicInvocationForwader() const {
+ bool IsDynamicInvocationForwarder() const {
return kind() == RawFunction::kDynamicInvocationForwarder;
}
@@ -2244,6 +2252,13 @@
bool IsFactory() const {
return (kind() == RawFunction::kConstructor) && is_static();
}
+
+ // Whether this function can receive an invocation where the number and names
+ // of arguments have not been checked.
+ bool CanReceiveDynamicInvocation() const {
+ return IsClosureFunction() || IsFfiTrampoline();
+ }
+
bool IsDynamicFunction(bool allow_abstract = false) const {
if (is_static() || (!allow_abstract && is_abstract())) {
return false;
@@ -2420,6 +2435,13 @@
bool IsOptimizable() const;
void SetIsOptimizable(bool value) const;
+ // Whether this function must be optimized immediately and cannot be compiled
+ // with the unoptimizing compiler. Such a function must be sure to not
+ // deoptimize, since we won't generate deoptimization info or register
+ // dependencies. It will be compiled into optimized code immediately when it's
+ // run.
+ bool ForceOptimize() const { return IsFfiTrampoline(); }
+
bool CanBeInlined() const;
MethodRecognizer::Kind recognized_kind() const {
@@ -2655,7 +2677,7 @@
RawFunction* CreateMethodExtractor(const String& getter_name) const;
RawFunction* GetMethodExtractor(const String& getter_name) const;
- static bool IsDynamicInvocationForwaderName(const String& name);
+ static bool IsDynamicInvocationForwarderName(const String& name);
static RawString* DemangleDynamicInvocationForwarderName(const String& name);
@@ -2989,6 +3011,9 @@
RawType* signature_type() const { return raw_ptr()->signature_type_; }
void set_signature_type(const Type& value) const;
+ RawFunction* c_signature() const { return raw_ptr()->c_signature_; }
+ void set_c_signature(const Function& value) const;
+
static RawFfiTrampolineData* New();
FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
@@ -3055,6 +3080,21 @@
set_kind_bits(HasPragmaBit::update(value, raw_ptr()->kind_bits_));
}
+ bool is_covariant() const {
+ return CovariantBit::decode(raw_ptr()->kind_bits_);
+ }
+ void set_is_covariant(bool value) const {
+ set_kind_bits(CovariantBit::update(value, raw_ptr()->kind_bits_));
+ }
+
+ bool is_generic_covariant_impl() const {
+ return GenericCovariantImplBit::decode(raw_ptr()->kind_bits_);
+ }
+ void set_is_generic_covariant_impl(bool value) const {
+ set_kind_bits(
+ GenericCovariantImplBit::update(value, raw_ptr()->kind_bits_));
+ }
+
intptr_t kernel_offset() const {
#if defined(DART_PRECOMPILED_RUNTIME)
return 0;
@@ -3073,11 +3113,6 @@
intptr_t KernelDataProgramOffset() const;
-#if !defined(DART_PRECOMPILED_RUNTIME)
- void GetCovarianceAttributes(bool* is_covariant,
- bool* is_generic_covariant) const;
-#endif
-
inline intptr_t Offset() const;
// Called during class finalization.
inline void SetOffset(intptr_t offset_in_bytes) const;
@@ -3301,6 +3336,7 @@
const Object& owner,
TokenPosition token_pos,
TokenPosition end_token_pos);
+ friend class Interpreter; // Access to bit field.
friend class StoreInstanceFieldInstr; // Generated code access to bit field.
enum {
@@ -3313,6 +3349,8 @@
kDoubleInitializedBit,
kInitializerChangedAfterInitializatonBit,
kHasPragmaBit,
+ kCovariantBit,
+ kGenericCovariantImplBit,
};
class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
class StaticBit : public BitField<uint16_t, bool, kStaticBit, 1> {};
@@ -3330,6 +3368,9 @@
kInitializerChangedAfterInitializatonBit,
1> {};
class HasPragmaBit : public BitField<uint16_t, bool, kHasPragmaBit, 1> {};
+ class CovariantBit : public BitField<uint16_t, bool, kCovariantBit, 1> {};
+ class GenericCovariantImplBit
+ : public BitField<uint16_t, bool, kGenericCovariantImplBit, 1> {};
// Update guarded cid and guarded length for this field. Returns true, if
// deoptimization of dependent code is required.
@@ -4651,6 +4692,7 @@
class Code : public Object {
public:
+ // When dual mapping, this returns the executable view.
RawInstructions* active_instructions() const {
#if defined(DART_PRECOMPILED_RUNTIME)
UNREACHABLE();
@@ -4660,6 +4702,7 @@
#endif
}
+ // When dual mapping, these return the executable view.
RawInstructions* instructions() const { return raw_ptr()->instructions_; }
static RawInstructions* InstructionsOf(const RawCode* code) {
return code->ptr()->instructions_;
@@ -5140,6 +5183,7 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(Code, Object);
friend class Class;
+ friend class CodeTestHelper;
friend class SnapshotWriter;
friend class StubCode; // for set_object_pool
friend class Precompiler; // for set_object_pool
@@ -8177,13 +8221,9 @@
static intptr_t length_offset() { return OFFSET_OF(RawTypedData, length_); }
- static intptr_t data_offset() {
- return OFFSET_OF_RETURNED_VALUE(RawTypedData, data);
- }
+ static intptr_t data_offset() { return OFFSET_OF(RawTypedData, data_); }
static intptr_t InstanceSize() {
- ASSERT(sizeof(RawTypedData) ==
- OFFSET_OF_RETURNED_VALUE(RawTypedData, data));
return 0;
}
@@ -8275,6 +8315,13 @@
StoreSmi(&raw_ptr()->length_, Smi::New(value));
}
+ void SetData(uint8_t* data) const {
+ ASSERT(Isolate::Current()->heap()->Contains(reinterpret_cast<uword>(data)));
+ StoreNonPointer(&raw_ptr()->data_, data);
+ }
+
+ void ResetData() { raw()->ResetData(); }
+
private:
// Provides const access to non-pointer, non-aligned data within the object.
// Such access does not need a write barrier, but it is *not* GC-safe, since
@@ -8419,49 +8466,55 @@
friend class Class;
};
-class TypedDataView : public AllStatic {
+class TypedDataView : public Instance {
public:
- static intptr_t ElementSizeInBytes(const Instance& view_obj) {
+ static RawTypedDataView* New(intptr_t class_id,
+ Heap::Space space = Heap::kNew);
+ static RawTypedDataView* New(intptr_t class_id,
+ const Instance& typed_data,
+ intptr_t offset_in_bytes,
+ intptr_t length,
+ Heap::Space space = Heap::kNew);
+
+ static intptr_t InstanceSize() {
+ return RoundedAllocationSize(sizeof(RawTypedDataView));
+ }
+
+ static intptr_t ElementSizeInBytes(const TypedDataView& view_obj) {
ASSERT(!view_obj.IsNull());
intptr_t cid = view_obj.raw()->GetClassId();
return ElementSizeInBytes(cid);
}
- static RawInstance* Data(const Instance& view_obj) {
- ASSERT(!view_obj.IsNull());
- return *reinterpret_cast<RawInstance* const*>(view_obj.raw_ptr() +
- kDataOffset);
+ static RawInstance* Data(const TypedDataView& view) {
+ return view.typed_data();
}
- static RawSmi* OffsetInBytes(const Instance& view_obj) {
- ASSERT(!view_obj.IsNull());
- return *reinterpret_cast<RawSmi* const*>(view_obj.raw_ptr() +
- kOffsetInBytesOffset);
+ static RawSmi* OffsetInBytes(const TypedDataView& view) {
+ return view.offset_in_bytes();
}
- static RawSmi* Length(const Instance& view_obj) {
- ASSERT(!view_obj.IsNull());
- return *reinterpret_cast<RawSmi* const*>(view_obj.raw_ptr() +
- kLengthOffset);
- }
+ static RawSmi* Length(const TypedDataView& view) { return view.length(); }
- static bool IsExternalTypedDataView(const Instance& view_obj) {
- const Instance& data = Instance::Handle(Data(view_obj));
+ static bool IsExternalTypedDataView(const TypedDataView& view_obj) {
+ const auto& data = Instance::Handle(Data(view_obj));
intptr_t cid = data.raw()->GetClassId();
ASSERT(RawObject::IsTypedDataClassId(cid) ||
RawObject::IsExternalTypedDataClassId(cid));
return RawObject::IsExternalTypedDataClassId(cid);
}
- static intptr_t NumberOfFields() { return kLengthOffset; }
-
- static intptr_t data_offset() { return kWordSize * kDataOffset; }
-
- static intptr_t offset_in_bytes_offset() {
- return kWordSize * kOffsetInBytesOffset;
+ static intptr_t data_offset() {
+ return OFFSET_OF(RawTypedDataView, typed_data_);
}
- static intptr_t length_offset() { return kWordSize * kLengthOffset; }
+ static intptr_t length_offset() {
+ return OFFSET_OF(RawTypedDataView, length_);
+ }
+
+ static intptr_t offset_in_bytes_offset() {
+ return OFFSET_OF(RawTypedDataView, offset_in_bytes_);
+ }
static intptr_t ElementSizeInBytes(intptr_t class_id) {
ASSERT(RawObject::IsTypedDataViewClassId(class_id));
@@ -8470,12 +8523,34 @@
: TypedData::element_size(class_id - kTypedDataInt8ArrayViewCid);
}
+ RawInstance* typed_data() const { return raw_ptr()->typed_data_; }
+
+ void set_typed_data(const Instance& typed_data) {
+ const classid_t cid = typed_data.GetClassId();
+ ASSERT(RawObject::IsTypedDataClassId(cid) ||
+ RawObject::IsExternalTypedDataClassId(cid));
+ StorePointer(&raw_ptr()->typed_data_, typed_data.raw());
+ }
+
+ void set_length(intptr_t value) {
+ StorePointer(&raw_ptr()->length_, Smi::New(value));
+ }
+
+ void set_offset_in_bytes(intptr_t value) {
+ StorePointer(&raw_ptr()->offset_in_bytes_, Smi::New(value));
+ }
+
+ RawSmi* offset_in_bytes() const { return raw_ptr()->offset_in_bytes_; }
+
+ RawSmi* length() const { return raw_ptr()->length_; }
+
private:
- enum {
- kDataOffset = 1,
- kOffsetInBytesOffset = 2,
- kLengthOffset = 3,
- };
+ void clear_typed_data() {
+ StorePointer(&raw_ptr()->typed_data_, Instance::RawCast(Object::null()));
+ }
+
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedDataView, Instance);
+ friend class Class;
};
class ByteBuffer : public AllStatic {
@@ -9140,8 +9215,12 @@
Isolate* isolate = Isolate::Current();
Heap* isolate_heap = isolate->heap();
Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
- ASSERT(isolate_heap->Contains(RawObject::ToAddr(raw_)) ||
- vm_isolate_heap->Contains(RawObject::ToAddr(raw_)));
+ uword addr = RawObject::ToAddr(raw_);
+ if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
+ ASSERT(FLAG_write_protect_code);
+ addr = RawObject::ToAddr(HeapPage::ToWritable(raw_));
+ ASSERT(isolate_heap->Contains(addr) || vm_isolate_heap->Contains(addr));
+ }
}
#endif
}
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 5a5e740..3e52f53 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -44,7 +44,12 @@
if (!include_vm_objects_ && !IsUserClass((*current)->GetClassId())) {
continue;
}
- (*current)->SetGraphMarked();
+ if (FLAG_write_protect_code && (*current)->IsInstructions()) {
+ // A non-writable alias mapping may exist for instruction pages.
+ HeapPage::ToWritable(*current)->SetGraphMarked();
+ } else {
+ (*current)->SetGraphMarked();
+ }
Node node;
node.ptr = current;
node.obj = *current;
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 1562714..8157ccf 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -1389,6 +1389,10 @@
}
}
+void TypedDataView::PrintJSONImpl(JSONStream* stream, bool ref) const {
+ Instance::PrintJSONImpl(stream, ref);
+}
+
void ExternalTypedData::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 3b9a10b..d3277a4 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -105,6 +105,7 @@
RW(Array, libraries_map) \
RW(GrowableObjectArray, closure_functions) \
RW(GrowableObjectArray, pending_classes) \
+ RW(GrowableObjectArray, pending_unevaluated_const_fields) \
R_(GrowableObjectArray, pending_deferred_loads) \
R_(GrowableObjectArray, resume_capabilities) \
R_(GrowableObjectArray, exit_listeners) \
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index c0d9526..4664ee7 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -23,6 +23,7 @@
namespace dart {
+DECLARE_FLAG(bool, dual_map_code);
DECLARE_FLAG(bool, write_protect_code);
static RawClass* CreateDummyClass(const String& class_name,
@@ -2507,8 +2508,56 @@
if (!FLAG_write_protect_code) {
// Since this test is expected to crash, crash if write protection of code
// is switched off.
- // TODO(regis, fschneider): Should this be FATAL() instead?
- OS::DebugBreak();
+ FATAL("Test requires --write-protect-code; skip by forcing expected crash");
+ }
+ MallocHooks::set_stack_trace_collection_enabled(
+ stack_trace_collection_enabled);
+}
+
+class CodeTestHelper {
+ public:
+ static void SetInstructions(const Code& code,
+ const Instructions& instructions) {
+ code.SetActiveInstructions(instructions);
+ code.set_instructions(instructions);
+ }
+};
+
+// Test for executability of generated instructions. The test crashes with a
+// segmentation fault when executing the writeable view.
+ISOLATE_UNIT_TEST_CASE(CodeExecutability) {
+ bool stack_trace_collection_enabled =
+ MallocHooks::stack_trace_collection_enabled();
+ MallocHooks::set_stack_trace_collection_enabled(false);
+ extern void GenerateIncrement(Assembler * assembler);
+ ObjectPoolBuilder object_pool_builder;
+ Assembler _assembler_(&object_pool_builder);
+ GenerateIncrement(&_assembler_);
+ const Function& function = Function::Handle(CreateFunction("Test_Code"));
+ Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
+ function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
+ function.AttachCode(code);
+ Instructions& instructions = Instructions::Handle(code.instructions());
+ uword payload_start = instructions.PayloadStart();
+ EXPECT_EQ(instructions.raw(), Instructions::FromPayloadStart(payload_start));
+ // Execute the executable view of the instructions (default).
+ Object& result =
+ Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
+ EXPECT_EQ(1, Smi::Cast(result).Value());
+ // Switch to the writeable but non-executable view of the instructions.
+ instructions ^= HeapPage::ToWritable(instructions.raw());
+ payload_start = instructions.PayloadStart();
+ EXPECT_EQ(instructions.raw(), Instructions::FromPayloadStart(payload_start));
+ // Hook up Code and Instructions objects.
+ CodeTestHelper::SetInstructions(code, instructions);
+ function.AttachCode(code);
+ // Try executing the generated code, expected to crash.
+ result = DartEntry::InvokeFunction(function, Array::empty_array());
+ EXPECT_EQ(1, Smi::Cast(result).Value());
+ if (!FLAG_dual_map_code) {
+ // Since this test is expected to crash, crash if dual mapping of code
+ // is switched off.
+ FATAL("Test requires --dual-map-code; skip by forcing expected crash");
}
MallocHooks::set_stack_trace_collection_enabled(
stack_trace_collection_enabled);
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 1079bdb..20db94d 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -558,9 +558,7 @@
}
}
-// TODO(regis, iposva): When this function is no longer called from the
-// CodeImmutability test in object_test.cc, it will be called only from the
-// simulator, which means that only the Intel implementation is needed.
+// TODO(regis): Function called only from the simulator.
void OS::DebugBreak() {
__builtin_trap();
}
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index b4b4135..17a4a79 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -78,7 +78,8 @@
const bool load_optional_arguments = function.HasOptionalParameters();
- const bool check_arguments = function_.IsClosureFunction();
+ const bool check_arguments =
+ function_.IsClosureFunction() || function.IsFfiTrampoline();
const bool need_argument_descriptor =
load_optional_arguments || check_arguments || reify_generic_argument;
@@ -216,7 +217,7 @@
raw_parameters_ = new (Z) ZoneGrowableArray<LocalVariable*>(Z, num_params);
for (intptr_t param = 0; param < num_params; ++param) {
- LocalVariable* variable = scope->VariableAt(param);
+ LocalVariable* variable = ParameterVariable(param);
LocalVariable* raw_parameter = variable;
if (variable->is_captured()) {
String& tmp = String::ZoneHandle(Z);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index bc7b0d2..25dc2b6 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -103,6 +103,17 @@
bool has_arg_desc_var() const { return arg_desc_var_ != NULL; }
LocalVariable* arg_desc_var() const { return arg_desc_var_; }
+ LocalVariable* receiver_var() const {
+ ASSERT(receiver_var_ != nullptr);
+ return receiver_var_;
+ }
+ void set_receiver_var(LocalVariable* value) {
+ ASSERT(receiver_var_ == nullptr);
+ ASSERT(value != nullptr);
+ receiver_var_ = value;
+ }
+ bool has_receiver_var() const { return receiver_var_ != nullptr; }
+
LocalVariable* expression_temp_var() const {
ASSERT(has_expression_temp_var());
return expression_temp_var_;
@@ -198,6 +209,12 @@
return raw_parameters_->At(i);
}
+ LocalVariable* ParameterVariable(intptr_t i) const {
+ ASSERT((i >= 0) && (i < function_.NumParameters()));
+ ASSERT(node_sequence() != nullptr && node_sequence()->scope() != nullptr);
+ return node_sequence()->scope()->VariableAt(i);
+ }
+
void SetDefaultFunctionTypeArguments(const TypeArguments& value) {
default_function_type_arguments_ = value.raw();
}
@@ -216,6 +233,7 @@
LocalVariable* parent_type_arguments_;
LocalVariable* current_context_var_;
LocalVariable* arg_desc_var_;
+ LocalVariable* receiver_var_ = nullptr;
LocalVariable* expression_temp_var_;
LocalVariable* entry_points_temp_var_;
LocalVariable* finally_return_temp_var_;
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 7735f4d..1e933eb 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -269,22 +269,25 @@
#undef RAW_VISITPOINTERS
#define RAW_VISITPOINTERS(clazz) case kExternalTypedData##clazz##Cid:
CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) {
- RawExternalTypedData* raw_obj =
- reinterpret_cast<RawExternalTypedData*>(this);
+ auto raw_obj = reinterpret_cast<RawExternalTypedData*>(this);
size = RawExternalTypedData::VisitExternalTypedDataPointers(raw_obj,
visitor);
break;
}
#undef RAW_VISITPOINTERS
-#define RAW_VISITPOINTERS(clazz) case kTypedData##clazz##ViewCid:
- CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS)
case kByteDataViewCid:
+#define RAW_VISITPOINTERS(clazz) case kTypedData##clazz##ViewCid:
+ CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) {
+ auto raw_obj = reinterpret_cast<RawTypedDataView*>(this);
+ size = RawTypedDataView::VisitTypedDataViewPointers(raw_obj, visitor);
+ break;
+ }
+#undef RAW_VISITPOINTERS
case kByteBufferCid: {
RawInstance* raw_obj = reinterpret_cast<RawInstance*>(this);
size = RawInstance::VisitInstancePointers(raw_obj, visitor);
break;
}
-#undef RAW_VISITPOINTERS
case kFfiPointerCid: {
RawPointer* raw_obj = reinterpret_cast<RawPointer*>(this);
size = RawPointer::VisitPointerPointers(raw_obj, visitor);
@@ -427,6 +430,7 @@
COMPRESSED_VISITOR(GrowableObjectArray)
COMPRESSED_VISITOR(LinkedHashMap)
COMPRESSED_VISITOR(ExternalTypedData)
+REGULAR_VISITOR(TypedDataView)
REGULAR_VISITOR(ReceivePort)
REGULAR_VISITOR(StackTrace)
REGULAR_VISITOR(RegExp)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 5cd9448..79372ea 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -712,6 +712,7 @@
friend class RawInstance;
friend class RawString;
friend class RawTypedData;
+ friend class RawTypedDataView;
friend class Scavenger;
friend class ScavengerVisitor;
friend class SizeExcludingClassVisitor; // GetClassId
@@ -1036,7 +1037,8 @@
VISIT_FROM(RawObject*, signature_type_);
RawType* signature_type_;
- VISIT_TO(RawObject*, signature_type_);
+ RawFunction* c_signature_;
+ VISIT_TO(RawObject*, c_signature_);
};
class RawField : public RawObject {
@@ -2080,6 +2082,25 @@
friend class String;
};
+// All _*ArrayView/_ByteDataView classes share the same layout.
+class RawTypedDataView : public RawInstance {
+ RAW_HEAP_OBJECT_IMPLEMENTATION(TypedDataView);
+
+ protected:
+ VISIT_FROM(RawObject*, typed_data_)
+ RawInstance* typed_data_;
+ RawSmi* offset_in_bytes_;
+ RawSmi* length_;
+ VISIT_TO(RawObject*, length_)
+
+ friend class Api;
+ friend class Object;
+ friend class ObjectPoolDeserializationCluster;
+ friend class ObjectPoolSerializationCluster;
+ friend class RawObjectPool;
+ friend class SnapshotReader;
+};
+
class RawExternalOneByteString : public RawString {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalOneByteString);
@@ -2227,13 +2248,31 @@
class RawTypedData : public RawInstance {
RAW_HEAP_OBJECT_IMPLEMENTATION(TypedData);
+ public:
+ // Reset data_ pointer to internal data.
+ void ResetData() { ptr()->data_ = ptr()->internal_data(); }
+
protected:
VISIT_FROM(RawCompressed, length_)
RawSmi* length_;
VISIT_TO_LENGTH(RawCompressed, &ptr()->length_)
+
+ uint8_t* data_;
// Variable length data follows here.
- uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
- const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
+
+ uint8_t* internal_data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
+ const uint8_t* internal_data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
+
+ uint8_t* data() {
+ // TODO(alexmarkov): revise after merging with ExternalTypedData
+ ASSERT(data_ == internal_data());
+ return data_;
+ }
+ const uint8_t* data() const {
+ // TODO(alexmarkov): revise after merging with ExternalTypedData
+ ASSERT(data_ == internal_data());
+ return data_;
+ }
friend class Api;
friend class Instance;
@@ -2620,7 +2659,7 @@
// is defined by the VM but are used in the VM code by computing the
// implicit field offsets of the various fields in the dart object.
inline bool RawObject::IsImplicitFieldClassId(intptr_t index) {
- return (IsTypedDataViewClassId(index) || index == kByteBufferCid);
+ return index == kByteBufferCid;
}
inline intptr_t RawObject::NumberOfTypedDataClasses() {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index f743ea6..58ec79e 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1964,6 +1964,45 @@
IsolateMessageTypedDataFinalizer);
}
+void RawTypedDataView::WriteTo(SnapshotWriter* writer,
+ intptr_t object_id,
+ Snapshot::Kind kind,
+ bool as_reference) {
+ // Write out the serialization header value for this object.
+ writer->WriteInlinedObjectHeader(object_id);
+
+ // Write out the class and tags information.
+ writer->WriteIndexedObject(GetClassId());
+ writer->WriteTags(writer->GetObjectTags(this));
+
+ // Write members.
+ writer->Write<RawObject*>(ptr()->offset_in_bytes_);
+ writer->Write<RawObject*>(ptr()->length_);
+ writer->WriteObjectImpl(ptr()->typed_data_, as_reference);
+}
+
+RawTypedDataView* TypedDataView::ReadFrom(SnapshotReader* reader,
+ intptr_t object_id,
+ intptr_t tags,
+ Snapshot::Kind kind,
+ bool as_reference) {
+ auto& typed_data = *reader->InstanceHandle();
+ const classid_t cid = RawObject::ClassIdTag::decode(tags);
+
+ auto& view = *reader->TypedDataViewHandle();
+ view = TypedDataView::New(cid);
+ reader->AddBackRef(object_id, &view, kIsDeserialized);
+
+ const intptr_t offset_in_bytes = reader->ReadSmiValue();
+ const intptr_t length = reader->ReadSmiValue();
+ typed_data ^= reader->ReadObjectImpl(as_reference);
+ view.set_offset_in_bytes(offset_in_bytes);
+ view.set_length(length);
+ view.set_typed_data(typed_data);
+
+ return view.raw();
+}
+
RawPointer* Pointer::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 9e7e8bb..c2b4fe7 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -317,6 +317,8 @@
inline bool ignore_case() { return ignore_case_; }
inline bool one_byte() const { return is_one_byte_; }
+ bool read_backward() { return read_backward_; }
+ void set_read_backward(bool value) { read_backward_ = value; }
FrequencyCollator* frequency_collator() { return &frequency_collator_; }
intptr_t current_expansion_factor() { return current_expansion_factor_; }
@@ -337,6 +339,7 @@
bool ignore_case_;
bool is_one_byte_;
bool reg_exp_too_big_;
+ bool read_backward_;
intptr_t current_expansion_factor_;
FrequencyCollator frequency_collator_;
Zone* zone_;
@@ -368,6 +371,7 @@
ignore_case_(ignore_case),
is_one_byte_(is_one_byte),
reg_exp_too_big_(false),
+ read_backward_(false),
current_expansion_factor_(1),
zone_(Thread::Current()->zone()) {
accept_ = new (Z) EndNode(EndNode::ACCEPT, Z);
@@ -520,7 +524,8 @@
intptr_t value = 0;
bool absolute = false;
bool clear = false;
- intptr_t store_position = -1;
+ static const intptr_t kNoStore = kMinInt32;
+ intptr_t store_position = kNoStore;
// This is a little tricky because we are scanning the actions in reverse
// historical order (newest first).
for (DeferredAction* action = actions_; action != NULL;
@@ -540,7 +545,7 @@
// can set undo_action to ACTION_IGNORE if we know there is no
// value to restore.
undo_action = ACTION_RESTORE;
- ASSERT(store_position == -1);
+ ASSERT(store_position == kNoStore);
ASSERT(!clear);
break;
}
@@ -548,14 +553,14 @@
if (!absolute) {
value++;
}
- ASSERT(store_position == -1);
+ ASSERT(store_position == kNoStore);
ASSERT(!clear);
undo_action = ACTION_RESTORE;
break;
case ActionNode::STORE_POSITION: {
Trace::DeferredCapture* pc =
static_cast<Trace::DeferredCapture*>(action);
- if (!clear && store_position == -1) {
+ if (!clear && store_position == kNoStore) {
store_position = pc->cp_offset();
}
@@ -579,7 +584,7 @@
// Since we're scanning in reverse order, if we've already
// set the position we have to ignore historically earlier
// clearing operations.
- if (store_position == -1) {
+ if (store_position == kNoStore) {
clear = true;
}
undo_action = ACTION_RESTORE;
@@ -602,7 +607,7 @@
}
// Perform the chronologically last action (or accumulated increment)
// for the register.
- if (store_position != -1) {
+ if (store_position != kNoStore) {
assembler->WriteCurrentPositionToRegister(reg, store_position);
} else if (clear) {
assembler->ClearRegisters(reg, reg);
@@ -1494,6 +1499,7 @@
intptr_t BackReferenceNode::EatsAtLeast(intptr_t still_to_find,
intptr_t budget,
bool not_at_start) {
+ if (read_backward()) return 0;
if (budget <= 0) return 0;
return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start);
}
@@ -1501,6 +1507,7 @@
intptr_t TextNode::EatsAtLeast(intptr_t still_to_find,
intptr_t budget,
bool not_at_start) {
+ if (read_backward()) return 0;
intptr_t answer = Length();
if (answer >= still_to_find) return answer;
if (budget <= 0) return answer;
@@ -1509,9 +1516,9 @@
on_success()->EatsAtLeast(still_to_find - answer, budget - 1, true);
}
-intptr_t NegativeLookaheadChoiceNode::EatsAtLeast(intptr_t still_to_find,
- intptr_t budget,
- bool not_at_start) {
+intptr_t NegativeLookaroundChoiceNode::EatsAtLeast(intptr_t still_to_find,
+ intptr_t budget,
+ bool not_at_start) {
if (budget <= 0) return 0;
// Alternative 0 is the negative lookahead, alternative 1 is what comes
// afterwards.
@@ -1519,7 +1526,7 @@
return node->EatsAtLeast(still_to_find, budget - 1, not_at_start);
}
-void NegativeLookaheadChoiceNode::GetQuickCheckDetails(
+void NegativeLookaroundChoiceNode::GetQuickCheckDetails(
QuickCheckDetails* details,
RegExpCompiler* compiler,
intptr_t filled_in,
@@ -1682,6 +1689,9 @@
ASSERT(details->characters() == 1 ||
(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__));
#endif
+ // Do not collect any quick check details if the text node reads backward,
+ // since it reads in the opposite direction than we use for quick checks.
+ if (read_backward()) return;
ASSERT(characters_filled_in < details->characters());
intptr_t characters = details->characters();
intptr_t char_mask;
@@ -1838,8 +1848,9 @@
}
void QuickCheckDetails::Advance(intptr_t by, bool one_byte) {
- ASSERT(by >= 0);
- if (by >= characters_) {
+ if (by >= characters_ || by < 0) {
+ // check that by < 0 => characters_ == 0
+ ASSERT(by >= 0 || characters_ == 0);
Clear();
return;
}
@@ -2060,8 +2071,8 @@
return this;
}
-RegExpNode* NegativeLookaheadChoiceNode::FilterOneByte(intptr_t depth,
- bool ignore_case) {
+RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(intptr_t depth,
+ bool ignore_case) {
if (info()->replacement_calculated) return replacement();
if (depth < 0) return this;
if (info()->visited) return this;
@@ -2294,9 +2305,9 @@
return;
}
if (trace->at_start() == Trace::UNKNOWN) {
- assembler->CheckNotAtStart(trace->backtrack());
+ assembler->CheckNotAtStart(trace->cp_offset(), trace->backtrack());
Trace at_start_trace = *trace;
- at_start_trace.set_at_start(true);
+ at_start_trace.set_at_start(Trace::TRUE_VALUE);
on_success()->Emit(compiler, &at_start_trace);
return;
}
@@ -2365,9 +2376,10 @@
BlockLabel* backtrack = trace->backtrack();
QuickCheckDetails* quick_check = trace->quick_check_performed();
intptr_t element_count = elms_->length();
+ intptr_t backward_offset = read_backward() ? -Length() : 0;
for (intptr_t i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
TextElement elm = elms_->At(i);
- intptr_t cp_offset = trace->cp_offset() + elm.cp_offset();
+ intptr_t cp_offset = trace->cp_offset() + elm.cp_offset() + backward_offset;
if (elm.text_type() == TextElement::ATOM) {
ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
for (intptr_t j = preloaded ? 0 : quarks->length() - 1; j >= 0; j--) {
@@ -2395,9 +2407,11 @@
break;
}
if (emit_function != NULL) {
- bool bound_checked = emit_function(
- Z, compiler, quarks->At(j), backtrack, cp_offset + j,
- *checked_up_to < cp_offset + j, preloaded);
+ const bool bounds_check =
+ *checked_up_to < (cp_offset + j) || read_backward();
+ bool bound_checked =
+ emit_function(Z, compiler, quarks->At(j), backtrack,
+ cp_offset + j, bounds_check, preloaded);
if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
}
}
@@ -2407,8 +2421,9 @@
if (first_element_checked && i == 0) continue;
if (DeterminedAlready(quick_check, elm.cp_offset())) continue;
RegExpCharacterClass* cc = elm.char_class();
+ bool bounds_check = *checked_up_to < cp_offset || read_backward();
EmitCharClass(assembler, cc, one_byte, backtrack, cp_offset,
- *checked_up_to < cp_offset, preloaded, Z);
+ bounds_check, preloaded, Z);
UpdateBoundsCheck(cp_offset, checked_up_to);
}
}
@@ -2475,8 +2490,11 @@
}
Trace successor_trace(*trace);
- successor_trace.set_at_start(false);
- successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler);
+ // If we advance backward, we may end up at the start.
+ successor_trace.AdvanceCurrentPositionInTrace(
+ read_backward() ? -Length() : Length(), compiler);
+ successor_trace.set_at_start(read_backward() ? Trace::UNKNOWN
+ : Trace::FALSE_VALUE);
RecursionCheck rc(compiler);
on_success()->Emit(compiler, &successor_trace);
}
@@ -2487,7 +2505,6 @@
void Trace::AdvanceCurrentPositionInTrace(intptr_t by,
RegExpCompiler* compiler) {
- ASSERT(by > 0);
// We don't have an instruction for shifting the current character register
// down or for using a shifted value for anything so lets just forget that
// we preloaded any characters into it.
@@ -2530,6 +2547,7 @@
RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode(
RegExpCompiler* compiler) {
+ if (read_backward()) return nullptr;
if (elms_->length() != 1) return NULL;
TextElement elm = elms_->At(0);
if (elm.text_type() != TextElement::CHAR_CLASS) return NULL;
@@ -2574,7 +2592,7 @@
SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node);
node = seq_node->on_success();
}
- return length;
+ return read_backward() ? -length : length;
}
void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) {
@@ -3002,7 +3020,7 @@
GreedyLoopState::GreedyLoopState(bool not_at_start) {
counter_backtrack_trace_.set_backtrack(&label_);
- if (not_at_start) counter_backtrack_trace_.set_at_start(false);
+ if (not_at_start) counter_backtrack_trace_.set_at_start(Trace::FALSE_VALUE);
}
void ChoiceNode::AssertGuardsMentionRegisters(Trace* trace) {
@@ -3115,7 +3133,7 @@
macro_assembler->PushCurrentPosition();
BlockLabel greedy_match_failed;
Trace greedy_match_trace;
- if (not_at_start()) greedy_match_trace.set_at_start(false);
+ if (not_at_start()) greedy_match_trace.set_at_start(Trace::FALSE_VALUE);
greedy_match_trace.set_backtrack(&greedy_match_failed);
BlockLabel loop_label;
macro_assembler->BindBlock(&loop_label);
@@ -3446,10 +3464,15 @@
ASSERT(start_reg_ + 1 == end_reg_);
if (compiler->ignore_case()) {
- assembler->CheckNotBackReferenceIgnoreCase(start_reg_, trace->backtrack());
+ assembler->CheckNotBackReferenceIgnoreCase(start_reg_, read_backward(),
+ trace->backtrack());
} else {
- assembler->CheckNotBackReference(start_reg_, trace->backtrack());
+ assembler->CheckNotBackReference(start_reg_, read_backward(),
+ trace->backtrack());
}
+ // We are going to advance backward, so we may end up at the start.
+ if (read_backward()) trace->set_at_start(Trace::UNKNOWN);
+
on_success()->Emit(compiler, trace);
}
@@ -3694,7 +3717,7 @@
ZoneGrowableArray<TextElement>* elms =
new (OZ) ZoneGrowableArray<TextElement>(1);
elms->Add(TextElement::Atom(this));
- return new (OZ) TextNode(elms, on_success);
+ return new (OZ) TextNode(elms, compiler->read_backward(), on_success);
}
RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
@@ -3704,7 +3727,7 @@
for (intptr_t i = 0; i < elements()->length(); i++) {
elms->Add(elements()->At(i));
}
- return new (OZ) TextNode(elms, on_success);
+ return new (OZ) TextNode(elms, compiler->read_backward(), on_success);
}
static bool CompareInverseRanges(ZoneGrowableArray<CharacterRange>* ranges,
@@ -3795,7 +3818,7 @@
RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
RegExpNode* on_success) {
- return new (OZ) TextNode(this, on_success);
+ return new (OZ) TextNode(this, compiler->read_backward(), on_success);
}
RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
@@ -3931,7 +3954,9 @@
GuardedAlternative(body->ToNode(compiler, answer)));
}
answer = alternation;
- if (not_at_start) alternation->set_not_at_start();
+ if (not_at_start && !compiler->read_backward()) {
+ alternation->set_not_at_start();
+ }
}
return answer;
}
@@ -3942,9 +3967,9 @@
bool needs_counter = has_min || has_max;
intptr_t reg_ctr = needs_counter ? compiler->AllocateRegister()
: RegExpCompiler::kNoRegister;
- LoopChoiceNode* center =
- new (zone) LoopChoiceNode(body->min_match() == 0, zone);
- if (not_at_start) center->set_not_at_start();
+ LoopChoiceNode* center = new (zone)
+ LoopChoiceNode(body->min_match() == 0, compiler->read_backward(), zone);
+ if (not_at_start && !compiler->read_backward()) center->set_not_at_start();
RegExpNode* loop_return =
needs_counter ? static_cast<RegExpNode*>(
ActionNode::IncrementRegister(reg_ctr, center))
@@ -4015,12 +4040,13 @@
new ZoneGrowableArray<CharacterRange>(3);
CharacterRange::AddClassEscape('n', newline_ranges);
RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n');
- TextNode* newline_matcher = new TextNode(
- newline_atom, ActionNode::PositiveSubmatchSuccess(
- stack_pointer_register, position_register,
- 0, // No captures inside.
- -1, // Ignored if no captures.
- on_success));
+ TextNode* newline_matcher =
+ new TextNode(newline_atom, /*read_backwards=*/false,
+ ActionNode::PositiveSubmatchSuccess(
+ stack_pointer_register, position_register,
+ 0, // No captures inside.
+ -1, // Ignored if no captures.
+ on_success));
// Create an end-of-input matcher.
RegExpNode* end_of_line = ActionNode::BeginSubmatch(
stack_pointer_register, position_register, newline_matcher);
@@ -4039,9 +4065,9 @@
RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
RegExpNode* on_success) {
- return new (OZ)
- BackReferenceNode(RegExpCapture::StartRegister(index()),
- RegExpCapture::EndRegister(index()), on_success);
+ return new (OZ) BackReferenceNode(RegExpCapture::StartRegister(index()),
+ RegExpCapture::EndRegister(index()),
+ compiler->read_backward(), on_success);
}
RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler,
@@ -4049,8 +4075,47 @@
return on_success;
}
-RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler,
- RegExpNode* on_success) {
+RegExpLookaround::Builder::Builder(bool is_positive,
+ RegExpNode* on_success,
+ intptr_t stack_pointer_register,
+ intptr_t position_register,
+ intptr_t capture_register_count,
+ intptr_t capture_register_start)
+ : is_positive_(is_positive),
+ on_success_(on_success),
+ stack_pointer_register_(stack_pointer_register),
+ position_register_(position_register) {
+ if (is_positive_) {
+ on_match_success_ = ActionNode::PositiveSubmatchSuccess(
+ stack_pointer_register, position_register, capture_register_count,
+ capture_register_start, on_success);
+ } else {
+ on_match_success_ = new (OZ) NegativeSubmatchSuccess(
+ stack_pointer_register, position_register, capture_register_count,
+ capture_register_start, OZ);
+ }
+}
+
+RegExpNode* RegExpLookaround::Builder::ForMatch(RegExpNode* match) {
+ if (is_positive_) {
+ return ActionNode::BeginSubmatch(stack_pointer_register_,
+ position_register_, match);
+ } else {
+ Zone* zone = on_success_->zone();
+ // We use a ChoiceNode to represent the negative lookaround. The first
+ // alternative is the negative match. On success, the end node backtracks.
+ // On failure, the second alternative is tried and leads to success.
+ // NegativeLookaroundChoiceNode is a special ChoiceNode that ignores the
+ // first exit when calculating quick checks.
+ ChoiceNode* choice_node = new (zone) NegativeLookaroundChoiceNode(
+ GuardedAlternative(match), GuardedAlternative(on_success_), zone);
+ return ActionNode::BeginSubmatch(stack_pointer_register_,
+ position_register_, choice_node);
+ }
+}
+
+RegExpNode* RegExpLookaround::ToNode(RegExpCompiler* compiler,
+ RegExpNode* on_success) {
intptr_t stack_pointer_register = compiler->AllocateRegister();
intptr_t position_register = compiler->AllocateRegister();
@@ -4060,36 +4125,15 @@
intptr_t register_start =
register_of_first_capture + capture_from_ * registers_per_capture;
- RegExpNode* success;
- if (is_positive()) {
- RegExpNode* node = ActionNode::BeginSubmatch(
- stack_pointer_register, position_register,
- body()->ToNode(compiler,
- ActionNode::PositiveSubmatchSuccess(
- stack_pointer_register, position_register,
- register_count, register_start, on_success)));
- return node;
- } else {
- // We use a ChoiceNode for a negative lookahead because it has most of
- // the characteristics we need. It has the body of the lookahead as its
- // first alternative and the expression after the lookahead of the second
- // alternative. If the first alternative succeeds then the
- // NegativeSubmatchSuccess will unwind the stack including everything the
- // choice node set up and backtrack. If the first alternative fails then
- // the second alternative is tried, which is exactly the desired result
- // for a negative lookahead. The NegativeLookaheadChoiceNode is a special
- // ChoiceNode that knows to ignore the first exit when calculating quick
- // checks.
-
- GuardedAlternative body_alt(
- body()->ToNode(compiler, success = new (OZ) NegativeSubmatchSuccess(
- stack_pointer_register, position_register,
- register_count, register_start, OZ)));
- ChoiceNode* choice_node = new (OZ) NegativeLookaheadChoiceNode(
- body_alt, GuardedAlternative(on_success), OZ);
- return ActionNode::BeginSubmatch(stack_pointer_register, position_register,
- choice_node);
- }
+ RegExpNode* result;
+ bool was_reading_backward = compiler->read_backward();
+ compiler->set_read_backward(type() == LOOKBEHIND);
+ Builder builder(is_positive(), on_success, stack_pointer_register,
+ position_register, register_count, register_start);
+ RegExpNode* match = body_->ToNode(compiler, builder.on_match_success());
+ result = builder.ForMatch(match);
+ compiler->set_read_backward(was_reading_backward);
+ return result;
}
RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
@@ -4101,8 +4145,14 @@
intptr_t index,
RegExpCompiler* compiler,
RegExpNode* on_success) {
+ ASSERT(body != nullptr);
intptr_t start_reg = RegExpCapture::StartRegister(index);
intptr_t end_reg = RegExpCapture::EndRegister(index);
+ if (compiler->read_backward()) {
+ intptr_t tmp = end_reg;
+ end_reg = start_reg;
+ start_reg = tmp;
+ }
RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success);
RegExpNode* body_node = body->ToNode(compiler, store_end);
return ActionNode::StorePosition(start_reg, true, body_node);
@@ -4112,8 +4162,14 @@
RegExpNode* on_success) {
ZoneGrowableArray<RegExpTree*>* children = nodes();
RegExpNode* current = on_success;
- for (intptr_t i = children->length() - 1; i >= 0; i--) {
- current = children->At(i)->ToNode(compiler, current);
+ if (compiler->read_backward()) {
+ for (intptr_t i = 0; i < children->length(); i++) {
+ current = children->At(i)->ToNode(compiler, current);
+ }
+ } else {
+ for (intptr_t i = children->length() - 1; i >= 0; i--) {
+ current = children->At(i)->ToNode(compiler, current);
+ }
}
return current;
}
@@ -4686,8 +4742,9 @@
// at the start of input.
ChoiceNode* first_step_node = new (zone) ChoiceNode(2, zone);
first_step_node->AddAlternative(GuardedAlternative(captured_body));
- first_step_node->AddAlternative(GuardedAlternative(new (zone) TextNode(
- new (zone) RegExpCharacterClass('*'), loop_node)));
+ first_step_node->AddAlternative(GuardedAlternative(
+ new (zone) TextNode(new (zone) RegExpCharacterClass('*'),
+ /*read_backwards=*/false, loop_node)));
node = first_step_node;
} else {
node = loop_node;
@@ -4789,8 +4846,9 @@
// at the start of input.
ChoiceNode* first_step_node = new (zone) ChoiceNode(2, zone);
first_step_node->AddAlternative(GuardedAlternative(captured_body));
- first_step_node->AddAlternative(GuardedAlternative(new (zone) TextNode(
- new (zone) RegExpCharacterClass('*'), loop_node)));
+ first_step_node->AddAlternative(GuardedAlternative(
+ new (zone) TextNode(new (zone) RegExpCharacterClass('*'),
+ /*read_backwards=*/false, loop_node)));
node = first_step_node;
} else {
node = loop_node;
diff --git a/runtime/vm/regexp.h b/runtime/vm/regexp.h
index b263166..3a477e9 100644
--- a/runtime/vm/regexp.h
+++ b/runtime/vm/regexp.h
@@ -121,7 +121,7 @@
VISIT(Atom) \
VISIT(Quantifier) \
VISIT(Capture) \
- VISIT(Lookahead) \
+ VISIT(Lookaround) \
VISIT(BackReference) \
VISIT(Empty) \
VISIT(Text)
@@ -549,11 +549,16 @@
class TextNode : public SeqRegExpNode {
public:
- TextNode(ZoneGrowableArray<TextElement>* elms, RegExpNode* on_success)
- : SeqRegExpNode(on_success), elms_(elms) {}
- TextNode(RegExpCharacterClass* that, RegExpNode* on_success)
+ TextNode(ZoneGrowableArray<TextElement>* elms,
+ bool read_backward,
+ RegExpNode* on_success)
+ : SeqRegExpNode(on_success), elms_(elms), read_backward_(read_backward) {}
+ TextNode(RegExpCharacterClass* that,
+ bool read_backward,
+ RegExpNode* on_success)
: SeqRegExpNode(on_success),
- elms_(new (zone()) ZoneGrowableArray<TextElement>(1)) {
+ elms_(new (zone()) ZoneGrowableArray<TextElement>(1)),
+ read_backward_(read_backward) {
elms_->Add(TextElement::CharClass(that));
}
virtual void Accept(NodeVisitor* visitor);
@@ -566,6 +571,7 @@
intptr_t characters_filled_in,
bool not_at_start);
ZoneGrowableArray<TextElement>* elements() { return elms_; }
+ bool read_backward() { return read_backward_; }
void MakeCaseIndependent(bool is_one_byte);
virtual intptr_t GreedyLoopTextLength();
virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
@@ -596,6 +602,7 @@
intptr_t* checked_up_to);
intptr_t Length();
ZoneGrowableArray<TextElement>* elms_;
+ bool read_backward_;
};
class AssertionNode : public SeqRegExpNode {
@@ -652,11 +659,16 @@
public:
BackReferenceNode(intptr_t start_reg,
intptr_t end_reg,
+ bool read_backward,
RegExpNode* on_success)
- : SeqRegExpNode(on_success), start_reg_(start_reg), end_reg_(end_reg) {}
+ : SeqRegExpNode(on_success),
+ start_reg_(start_reg),
+ end_reg_(end_reg),
+ read_backward_(read_backward) {}
virtual void Accept(NodeVisitor* visitor);
intptr_t start_register() { return start_reg_; }
intptr_t end_register() { return end_reg_; }
+ bool read_backward() { return read_backward_; }
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
virtual intptr_t EatsAtLeast(intptr_t still_to_find,
intptr_t recursion_depth,
@@ -675,6 +687,7 @@
private:
intptr_t start_reg_;
intptr_t end_reg_;
+ bool read_backward_;
};
class EndNode : public RegExpNode {
@@ -799,6 +812,7 @@
return true;
}
virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case);
+ virtual bool read_backward() { return false; }
protected:
intptr_t GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative);
@@ -840,11 +854,11 @@
bool being_calculated_;
};
-class NegativeLookaheadChoiceNode : public ChoiceNode {
+class NegativeLookaroundChoiceNode : public ChoiceNode {
public:
- explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail,
- GuardedAlternative then_do_this,
- Zone* zone)
+ explicit NegativeLookaroundChoiceNode(GuardedAlternative this_must_fail,
+ GuardedAlternative then_do_this,
+ Zone* zone)
: ChoiceNode(2, zone) {
AddAlternative(this_must_fail);
AddAlternative(then_do_this);
@@ -877,11 +891,14 @@
class LoopChoiceNode : public ChoiceNode {
public:
- explicit LoopChoiceNode(bool body_can_be_zero_length, Zone* zone)
+ explicit LoopChoiceNode(bool body_can_be_zero_length,
+ bool read_backward,
+ Zone* zone)
: ChoiceNode(2, zone),
loop_node_(NULL),
continue_node_(NULL),
- body_can_be_zero_length_(body_can_be_zero_length) {}
+ body_can_be_zero_length_(body_can_be_zero_length),
+ read_backward_(read_backward) {}
void AddLoopAlternative(GuardedAlternative alt);
void AddContinueAlternative(GuardedAlternative alt);
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
@@ -899,6 +916,7 @@
RegExpNode* loop_node() { return loop_node_; }
RegExpNode* continue_node() { return continue_node_; }
bool body_can_be_zero_length() { return body_can_be_zero_length_; }
+ virtual bool read_backward() { return read_backward_; }
virtual void Accept(NodeVisitor* visitor);
virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case);
@@ -913,6 +931,7 @@
RegExpNode* loop_node_;
RegExpNode* continue_node_;
bool body_can_be_zero_length_;
+ bool read_backward_;
};
// Improve the speed that we scan for an initial point where a non-anchored
@@ -1161,9 +1180,7 @@
quick_check_performed_.characters() == 0 && at_start_ == UNKNOWN;
}
TriBool at_start() { return at_start_; }
- void set_at_start(bool at_start) {
- at_start_ = at_start ? TRUE_VALUE : FALSE_VALUE;
- }
+ void set_at_start(TriBool at_start) { at_start_ = at_start; }
BlockLabel* backtrack() { return backtrack_; }
BlockLabel* loop_label() { return loop_label_; }
RegExpNode* stop_node() { return stop_node_; }
diff --git a/runtime/vm/regexp_assembler.h b/runtime/vm/regexp_assembler.h
index 23d32c7..a7b087e 100644
--- a/runtime/vm/regexp_assembler.h
+++ b/runtime/vm/regexp_assembler.h
@@ -120,10 +120,13 @@
virtual void CheckCharacterGT(uint16_t limit, BlockLabel* on_greater) = 0;
virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less) = 0;
virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position) = 0;
- virtual void CheckNotAtStart(BlockLabel* on_not_at_start) = 0;
+ virtual void CheckNotAtStart(intptr_t cp_offset,
+ BlockLabel* on_not_at_start) = 0;
virtual void CheckNotBackReference(intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_no_match) = 0;
virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_no_match) = 0;
// Check the current character for a match with a literal character. If we
// fail to match then goto the on_failure label. End of input always
diff --git a/runtime/vm/regexp_assembler_bytecode.cc b/runtime/vm/regexp_assembler_bytecode.cc
index f63bfec..fac8a82 100644
--- a/runtime/vm/regexp_assembler_bytecode.cc
+++ b/runtime/vm/regexp_assembler_bytecode.cc
@@ -246,8 +246,9 @@
}
void BytecodeRegExpMacroAssembler::CheckNotAtStart(
+ intptr_t cp_offset,
BlockLabel* on_not_at_start) {
- Emit(BC_CHECK_NOT_AT_START, 0);
+ Emit(BC_CHECK_NOT_AT_START, cp_offset);
EmitOrLink(on_not_at_start);
}
@@ -336,19 +337,24 @@
void BytecodeRegExpMacroAssembler::CheckNotBackReference(
intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_not_equal) {
ASSERT(start_reg >= 0);
ASSERT(start_reg <= kMaxRegister);
- Emit(BC_CHECK_NOT_BACK_REF, start_reg);
+ Emit(read_backward ? BC_CHECK_NOT_BACK_REF_BACKWARD : BC_CHECK_NOT_BACK_REF,
+ start_reg);
EmitOrLink(on_not_equal);
}
void BytecodeRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_not_equal) {
ASSERT(start_reg >= 0);
ASSERT(start_reg <= kMaxRegister);
- Emit(BC_CHECK_NOT_BACK_REF_NO_CASE, start_reg);
+ Emit(read_backward ? BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD
+ : BC_CHECK_NOT_BACK_REF_NO_CASE,
+ start_reg);
EmitOrLink(on_not_equal);
}
diff --git a/runtime/vm/regexp_assembler_bytecode.h b/runtime/vm/regexp_assembler_bytecode.h
index 81e8d3d..3e17d49 100644
--- a/runtime/vm/regexp_assembler_bytecode.h
+++ b/runtime/vm/regexp_assembler_bytecode.h
@@ -62,7 +62,7 @@
virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less);
virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position);
virtual void CheckAtStart(BlockLabel* on_at_start);
- virtual void CheckNotAtStart(BlockLabel* on_not_at_start);
+ virtual void CheckNotAtStart(intptr_t cp_offset, BlockLabel* on_not_at_start);
virtual void CheckNotCharacter(unsigned c, BlockLabel* on_not_equal);
virtual void CheckNotCharacterAfterAnd(unsigned c,
unsigned mask,
@@ -79,8 +79,10 @@
BlockLabel* on_not_in_range);
virtual void CheckBitInTable(const TypedData& table, BlockLabel* on_bit_set);
virtual void CheckNotBackReference(intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_no_match);
virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_no_match);
virtual void IfRegisterLT(intptr_t register_index,
intptr_t comparand,
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index 888061d..bc0a132 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -770,38 +770,27 @@
void IRRegExpMacroAssembler::CheckAtStart(BlockLabel* on_at_start) {
TAG();
- BlockLabel not_at_start;
-
- // Did we start the match at the start of the string at all?
- BranchOrBacktrack(
- Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)),
- ¬_at_start);
-
- // If we did, are we still at the start of the input, i.e. is
- // (offset == string_length * -1)?
+ // Are we at the start of the input, i.e. is (offset == string_length * -1)?
Definition* neg_len_def =
InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
PushLocal(string_param_length_));
Definition* offset_def = LoadLocal(current_position_);
BranchOrBacktrack(Comparison(kEQ, neg_len_def, offset_def), on_at_start);
-
- BindBlock(¬_at_start);
}
-void IRRegExpMacroAssembler::CheckNotAtStart(BlockLabel* on_not_at_start) {
+// cp_offset => offset from the current (character) pointer
+// This offset may be negative due to traversing backwards during lookbehind.
+void IRRegExpMacroAssembler::CheckNotAtStart(intptr_t cp_offset,
+ BlockLabel* on_not_at_start) {
TAG();
- // Did we start the match at the start of the string at all?
- BranchOrBacktrack(
- Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)),
- on_not_at_start);
-
- // If we did, are we still at the start of the input, i.e. is
- // (offset == string_length * -1)?
- Definition* neg_len_def =
- InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
- PushLocal(string_param_length_));
- Definition* offset_def = LoadLocal(current_position_);
+ // Are we at the start of the input, i.e. is (offset == string_length * -1)?
+ auto offset_def =
+ PushArgument(Bind(Add(PushLocal(current_position_),
+ PushArgument(Bind(Int64Constant(cp_offset))))));
+ auto neg_len_def = PushArgument(
+ Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
+ PushLocal(string_param_length_))));
BranchOrBacktrack(Comparison(kNE, neg_len_def, offset_def), on_not_at_start);
}
@@ -832,6 +821,7 @@
void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_no_match) {
TAG();
ASSERT(start_reg + 1 <= registers_count_);
@@ -857,20 +847,38 @@
Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)),
&fallthrough);
- // Check that there are sufficient characters left in the input.
- PushArgumentInstr* pos_push = PushLocal(current_position_);
- PushArgumentInstr* len_push = PushLocal(capture_length_);
- BranchOrBacktrack(
- Comparison(kGT,
- InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
- pos_push, len_push),
- Uint64Constant(0)),
- on_no_match);
+ PushArgumentInstr* pos_push = nullptr;
+ PushArgumentInstr* len_push = nullptr;
+
+ if (!read_backward) {
+ // Check that there are sufficient characters left in the input.
+ pos_push = PushLocal(current_position_);
+ len_push = PushLocal(capture_length_);
+ BranchOrBacktrack(
+ Comparison(kGT,
+ InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
+ pos_push, len_push),
+ Uint64Constant(0)),
+ on_no_match);
+ }
pos_push = PushLocal(current_position_);
len_push = PushLocal(string_param_length_);
StoreLocal(match_start_index_, Bind(Add(pos_push, len_push)));
+ if (read_backward) {
+ // First check that there are enough characters before this point in
+ // the string that we can match the backreference.
+ BranchOrBacktrack(Comparison(kLT, LoadLocal(match_start_index_),
+ LoadLocal(capture_length_)),
+ on_no_match);
+
+ // The string to check is before the current position, not at it.
+ pos_push = PushLocal(match_start_index_);
+ len_push = PushLocal(capture_length_);
+ StoreLocal(match_start_index_, Bind(Sub(pos_push, len_push)));
+ }
+
pos_push = PushArgument(LoadRegister(start_reg));
len_push = PushLocal(string_param_length_);
StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push)));
@@ -970,15 +978,23 @@
BindBlock(&success);
- // Move current character position to position after match.
- PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
- len_push = PushLocal(string_param_length_);
- StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
+ if (read_backward) {
+ // Move current character position to start of match.
+ pos_push = PushLocal(current_position_);
+ len_push = PushLocal(capture_length_);
+ StoreLocal(current_position_, Bind(Sub(pos_push, len_push)));
+ } else {
+ // Move current character position to position after match.
+ PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
+ len_push = PushLocal(string_param_length_);
+ StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
+ }
BindBlock(&fallthrough);
}
void IRRegExpMacroAssembler::CheckNotBackReference(intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_no_match) {
TAG();
ASSERT(start_reg + 1 <= registers_count_);
@@ -1001,21 +1017,39 @@
Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)),
&fallthrough);
- // Check that there are sufficient characters left in the input.
- PushArgumentInstr* pos_push = PushLocal(current_position_);
- PushArgumentInstr* len_push = PushLocal(capture_length_);
- BranchOrBacktrack(
- Comparison(kGT,
- InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
- pos_push, len_push),
- Uint64Constant(0)),
- on_no_match);
+ PushArgumentInstr* pos_push = nullptr;
+ PushArgumentInstr* len_push = nullptr;
+
+ if (!read_backward) {
+ // Check that there are sufficient characters left in the input.
+ pos_push = PushLocal(current_position_);
+ len_push = PushLocal(capture_length_);
+ BranchOrBacktrack(
+ Comparison(kGT,
+ InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
+ pos_push, len_push),
+ Uint64Constant(0)),
+ on_no_match);
+ }
// Compute pointers to match string and capture string.
pos_push = PushLocal(current_position_);
len_push = PushLocal(string_param_length_);
StoreLocal(match_start_index_, Bind(Add(pos_push, len_push)));
+ if (read_backward) {
+ // First check that there are enough characters before this point in
+ // the string that we can match the backreference.
+ BranchOrBacktrack(Comparison(kLT, LoadLocal(match_start_index_),
+ LoadLocal(capture_length_)),
+ on_no_match);
+
+ // The string to check is before the current position, not at it.
+ pos_push = PushLocal(match_start_index_);
+ len_push = PushLocal(capture_length_);
+ StoreLocal(match_start_index_, Bind(Sub(pos_push, len_push)));
+ }
+
pos_push = PushArgument(LoadRegister(start_reg));
len_push = PushLocal(string_param_length_);
StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push)));
@@ -1050,10 +1084,17 @@
BindBlock(&success);
- // Move current character position to position after match.
- PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
- len_push = PushLocal(string_param_length_);
- StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
+ if (read_backward) {
+ // Move current character position to start of match.
+ pos_push = PushLocal(current_position_);
+ len_push = PushLocal(capture_length_);
+ StoreLocal(current_position_, Bind(Sub(pos_push, len_push)));
+ } else {
+ // Move current character position to position after match.
+ PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
+ len_push = PushLocal(string_param_length_);
+ StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
+ }
BindBlock(&fallthrough);
}
@@ -1361,10 +1402,13 @@
bool check_bounds,
intptr_t characters) {
TAG();
- ASSERT(cp_offset >= -1); // ^ and \b can look behind one character.
ASSERT(cp_offset < (1 << 30)); // Be sane! (And ensure negation works)
if (check_bounds) {
- CheckPosition(cp_offset + characters - 1, on_end_of_input);
+ if (cp_offset >= 0) {
+ CheckPosition(cp_offset + characters - 1, on_end_of_input);
+ } else {
+ CheckPosition(cp_offset, on_end_of_input);
+ }
}
LoadCurrentCharacterUnchecked(cp_offset, characters);
}
@@ -1594,13 +1638,24 @@
void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset,
BlockLabel* on_outside_input) {
TAG();
- Definition* curpos_def = LoadLocal(current_position_);
- Definition* cp_off_def = Int64Constant(-cp_offset);
+ if (cp_offset >= 0) {
+ Definition* curpos_def = LoadLocal(current_position_);
+ Definition* cp_off_def = Int64Constant(-cp_offset);
+ // If (current_position_ < -cp_offset), we are in bounds.
+ // Remember, current_position_ is a negative offset from the string end.
- // If (current_position_ < -cp_offset), we are in bounds.
- // Remember, current_position_ is a negative offset from the string end.
-
- BranchOrBacktrack(Comparison(kGTE, curpos_def, cp_off_def), on_outside_input);
+ BranchOrBacktrack(Comparison(kGTE, curpos_def, cp_off_def),
+ on_outside_input);
+ } else {
+ // We need to see if there's enough characters left in the string to go
+ // back cp_offset characters, so get the normalized position and then
+ // make sure that (normalized_position >= -cp_offset).
+ PushArgumentInstr* pos_push = PushLocal(current_position_);
+ PushArgumentInstr* len_push = PushLocal(string_param_length_);
+ BranchOrBacktrack(
+ Comparison(kLT, Add(pos_push, len_push), Uint64Constant(-cp_offset)),
+ on_outside_input);
+ }
}
void IRRegExpMacroAssembler::BranchOrBacktrack(ComparisonInstr* comparison,
diff --git a/runtime/vm/regexp_assembler_ir.h b/runtime/vm/regexp_assembler_ir.h
index 3652b72..c4f6e1f 100644
--- a/runtime/vm/regexp_assembler_ir.h
+++ b/runtime/vm/regexp_assembler_ir.h
@@ -61,10 +61,12 @@
// A "greedy loop" is a loop that is both greedy and with a simple
// body. It has a particularly simple implementation.
virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position);
- virtual void CheckNotAtStart(BlockLabel* on_not_at_start);
+ virtual void CheckNotAtStart(intptr_t cp_offset, BlockLabel* on_not_at_start);
virtual void CheckNotBackReference(intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_no_match);
virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
+ bool read_backward,
BlockLabel* on_no_match);
virtual void CheckNotCharacter(uint32_t c, BlockLabel* on_not_equal);
virtual void CheckNotCharacterAfterAnd(uint32_t c,
diff --git a/runtime/vm/regexp_ast.cc b/runtime/vm/regexp_ast.cc
index 5b51a6f..e096e2b 100644
--- a/runtime/vm/regexp_ast.cc
+++ b/runtime/vm/regexp_ast.cc
@@ -43,7 +43,7 @@
return ListCaptureRegisters(alternatives());
}
-Interval RegExpLookahead::CaptureRegisters() const {
+Interval RegExpLookaround::CaptureRegisters() const {
return body()->CaptureRegisters();
}
@@ -108,8 +108,8 @@
return true;
}
-bool RegExpLookahead::IsAnchoredAtStart() const {
- return is_positive() && body()->IsAnchoredAtStart();
+bool RegExpLookaround::IsAnchoredAtStart() const {
+ return is_positive() && type() == LOOKAHEAD && body()->IsAnchoredAtStart();
}
bool RegExpCapture::IsAnchoredAtStart() const {
@@ -241,8 +241,11 @@
return NULL;
}
-void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
- OS::PrintErr("(-> %s", (that->is_positive() ? "+ " : "- "));
+void* RegExpUnparser::VisitLookaround(RegExpLookaround* that, void* data) {
+ OS::PrintErr("(");
+ OS::PrintErr("(%s %s",
+ (that->type() == RegExpLookaround::LOOKAHEAD ? "->" : "<-"),
+ (that->is_positive() ? "+ " : "- "));
that->body()->Accept(this, data);
OS::PrintErr(")");
return NULL;
diff --git a/runtime/vm/regexp_ast.h b/runtime/vm/regexp_ast.h
index 438dc3c..55f2f8c 100644
--- a/runtime/vm/regexp_ast.h
+++ b/runtime/vm/regexp_ast.h
@@ -21,7 +21,7 @@
class RegExpCompiler;
class RegExpDisjunction;
class RegExpEmpty;
-class RegExpLookahead;
+class RegExpLookaround;
class RegExpQuantifier;
class RegExpText;
@@ -277,8 +277,7 @@
class RegExpCapture : public RegExpTree {
public:
- explicit RegExpCapture(RegExpTree* body, intptr_t index)
- : body_(body), index_(index) {}
+ explicit RegExpCapture(intptr_t index) : body_(nullptr), index_(index) {}
virtual void* Accept(RegExpVisitor* visitor, void* data);
virtual RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success);
static RegExpNode* ToNode(RegExpTree* body,
@@ -293,6 +292,11 @@
virtual intptr_t min_match() const { return body_->min_match(); }
virtual intptr_t max_match() const { return body_->max_match(); }
RegExpTree* body() const { return body_; }
+ // When a backreference is parsed before the corresponding capture group,
+ // which can happen because of lookbehind, we create the capture object when
+ // we create the backreference, and fill in the body later when the actual
+ // capture group is parsed.
+ void set_body(RegExpTree* body) { body_ = body; }
intptr_t index() const { return index_; }
static intptr_t StartRegister(intptr_t index) { return index * 2; }
static intptr_t EndRegister(intptr_t index) { return index * 2 + 1; }
@@ -302,22 +306,25 @@
intptr_t index_;
};
-class RegExpLookahead : public RegExpTree {
+class RegExpLookaround : public RegExpTree {
public:
- RegExpLookahead(RegExpTree* body,
- bool is_positive,
- intptr_t capture_count,
- intptr_t capture_from)
+ enum Type { LOOKAHEAD, LOOKBEHIND };
+ RegExpLookaround(RegExpTree* body,
+ bool is_positive,
+ intptr_t capture_count,
+ intptr_t capture_from,
+ Type type)
: body_(body),
is_positive_(is_positive),
capture_count_(capture_count),
- capture_from_(capture_from) {}
+ capture_from_(capture_from),
+ type_(type) {}
virtual void* Accept(RegExpVisitor* visitor, void* data);
virtual RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success);
- virtual RegExpLookahead* AsLookahead();
+ virtual RegExpLookaround* AsLookaround();
virtual Interval CaptureRegisters() const;
- virtual bool IsLookahead() const;
+ virtual bool IsLookaround() const;
virtual bool IsAnchoredAtStart() const;
virtual intptr_t min_match() const { return 0; }
virtual intptr_t max_match() const { return 0; }
@@ -325,12 +332,36 @@
bool is_positive() const { return is_positive_; }
intptr_t capture_count() const { return capture_count_; }
intptr_t capture_from() const { return capture_from_; }
+ Type type() const { return type_; }
+
+ // The RegExpLookaround::Builder class abstracts out the process of building
+ // the compiling a RegExpLookaround object by splitting it into two phases,
+ // represented by the provided methods.
+ class Builder : public ValueObject {
+ public:
+ Builder(bool is_positive,
+ RegExpNode* on_success,
+ intptr_t stack_pointer_register,
+ intptr_t position_register,
+ intptr_t capture_register_count = 0,
+ intptr_t capture_register_start = 0);
+ RegExpNode* on_match_success() { return on_match_success_; }
+ RegExpNode* ForMatch(RegExpNode* match);
+
+ private:
+ bool is_positive_;
+ RegExpNode* on_match_success_;
+ RegExpNode* on_success_;
+ intptr_t stack_pointer_register_;
+ intptr_t position_register_;
+ };
private:
RegExpTree* body_;
bool is_positive_;
intptr_t capture_count_;
intptr_t capture_from_;
+ Type type_;
};
class RegExpBackReference : public RegExpTree {
@@ -341,7 +372,10 @@
virtual RegExpBackReference* AsBackReference();
virtual bool IsBackReference() const;
virtual intptr_t min_match() const { return 0; }
- virtual intptr_t max_match() const { return capture_->max_match(); }
+ // The back reference may be recursive, e.g. /(\2)(\1)/. To avoid infinite
+ // recursion, we give up and just assume arbitrary length, which matches v8's
+ // behavior.
+ virtual intptr_t max_match() const { return kInfinity; }
intptr_t index() const { return capture_->index(); }
RegExpCapture* capture() const { return capture_; }
diff --git a/runtime/vm/regexp_bytecodes.h b/runtime/vm/regexp_bytecodes.h
index c2ef82b..858eef5 100644
--- a/runtime/vm/regexp_bytecodes.h
+++ b/runtime/vm/regexp_bytecodes.h
@@ -55,15 +55,17 @@
V(CHECK_GT, 36, 8) /* bc8 pad8 uc16 addr32 */ \
V(CHECK_NOT_BACK_REF, 37, 8) /* bc8 reg_idx24 addr32 */ \
V(CHECK_NOT_BACK_REF_NO_CASE, 38, 8) /* bc8 reg_idx24 addr32 */ \
-V(CHECK_NOT_REGS_EQUAL, 39, 12) /* bc8 regidx24 reg_idx32 addr32 */ \
-V(CHECK_REGISTER_LT, 40, 12) /* bc8 reg_idx24 value32 addr32 */ \
-V(CHECK_REGISTER_GE, 41, 12) /* bc8 reg_idx24 value32 addr32 */ \
-V(CHECK_REGISTER_EQ_POS, 42, 8) /* bc8 reg_idx24 addr32 */ \
-V(CHECK_AT_START, 43, 8) /* bc8 pad24 addr32 */ \
-V(CHECK_NOT_AT_START, 44, 8) /* bc8 pad24 addr32 */ \
-V(CHECK_GREEDY, 45, 8) /* bc8 pad24 addr32 */ \
-V(ADVANCE_CP_AND_GOTO, 46, 8) /* bc8 offset24 addr32 */ \
-V(SET_CURRENT_POSITION_FROM_END, 47, 4) /* bc8 idx24 */
+V(CHECK_NOT_BACK_REF_BACKWARD, 39, 8) /* bc8 reg_idx24 addr32 */ \
+V(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD, 40, 8) /* bc8 reg_idx24 addr32 */ \
+V(CHECK_NOT_REGS_EQUAL, 41, 12) /* bc8 regidx24 reg_idx32 addr32 */ \
+V(CHECK_REGISTER_LT, 42, 12) /* bc8 reg_idx24 value32 addr32 */ \
+V(CHECK_REGISTER_GE, 43, 12) /* bc8 reg_idx24 value32 addr32 */ \
+V(CHECK_REGISTER_EQ_POS, 44, 8) /* bc8 reg_idx24 addr32 */ \
+V(CHECK_AT_START, 45, 8) /* bc8 pad24 addr32 */ \
+V(CHECK_NOT_AT_START, 46, 8) /* bc8 offset24 addr32 */ \
+V(CHECK_GREEDY, 47, 8) /* bc8 pad24 addr32 */ \
+V(ADVANCE_CP_AND_GOTO, 48, 8) /* bc8 offset24 addr32 */ \
+V(SET_CURRENT_POSITION_FROM_END, 49, 4) /* bc8 idx24 */
// clang-format on
diff --git a/runtime/vm/regexp_interpreter.cc b/runtime/vm/regexp_interpreter.cc
index c83f474..ecc7586 100644
--- a/runtime/vm/regexp_interpreter.cc
+++ b/runtime/vm/regexp_interpreter.cc
@@ -268,7 +268,7 @@
break;
BYTECODE(LOAD_CURRENT_CHAR) {
int pos = current + (insn >> BYTECODE_SHIFT);
- if (pos >= subject_length) {
+ if (pos < 0 || pos >= subject_length) {
pc = code_base + Load32Aligned(pc + 4);
} else {
current_char = subject.CharAt(pos);
@@ -534,6 +534,55 @@
}
break;
}
+ BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) {
+ const int from = registers[insn >> BYTECODE_SHIFT];
+ const int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+ if (from < 0 || len <= 0) {
+ pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
+ break;
+ }
+ if ((current - len) < 0) {
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ } else {
+ // When looking behind, the string to match (if it is there) lies
+ // before the current position, so we will check the [len] characters
+ // before the current position, excluding the current position itself.
+ const int start = current - len;
+ int i;
+ for (i = 0; i < len; i++) {
+ if (subject.CharAt(from + i) != subject.CharAt(start + i)) {
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ }
+ }
+ if (i < len) break;
+ current -= len;
+ }
+ pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
+ break;
+ }
+ BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
+ int from = registers[insn >> BYTECODE_SHIFT];
+ int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+ if (from < 0 || len <= 0) {
+ pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
+ break;
+ }
+ if (current < len) {
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ } else {
+ if (BackRefMatchesNoCase<Char>(&canonicalize, from, current - len,
+ len, subject)) {
+ current -= len;
+ pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
+ } else {
+ pc = code_base + Load32Aligned(pc + 4);
+ }
+ }
+ break;
+ }
BYTECODE(CHECK_AT_START)
if (current == 0) {
pc = code_base + Load32Aligned(pc + 4);
@@ -541,13 +590,15 @@
pc += BC_CHECK_AT_START_LENGTH;
}
break;
- BYTECODE(CHECK_NOT_AT_START)
- if (current == 0) {
- pc += BC_CHECK_NOT_AT_START_LENGTH;
- } else {
- pc = code_base + Load32Aligned(pc + 4);
+ BYTECODE(CHECK_NOT_AT_START) {
+ const int32_t cp_offset = insn >> BYTECODE_SHIFT;
+ if (current + cp_offset == 0) {
+ pc += BC_CHECK_NOT_AT_START_LENGTH;
+ } else {
+ pc = code_base + Load32Aligned(pc + 4);
+ }
+ break;
}
- break;
BYTECODE(SET_CURRENT_POSITION_FROM_END) {
int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
if (subject_length - current > by) {
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc
index 10c9c00..e08071a 100644
--- a/runtime/vm/regexp_parser.cc
+++ b/runtime/vm/regexp_parser.cc
@@ -129,13 +129,13 @@
return new (Z) RegExpDisjunction(alternatives);
}
-void RegExpBuilder::AddQuantifierToAtom(
+bool RegExpBuilder::AddQuantifierToAtom(
intptr_t min,
intptr_t max,
RegExpQuantifier::QuantifierType quantifier_type) {
if (pending_empty_) {
pending_empty_ = false;
- return;
+ return true;
}
RegExpTree* atom;
if (characters_ != NULL) {
@@ -167,22 +167,28 @@
} else if (terms_.length() > 0) {
DEBUG_ASSERT(last_added_ == ADD_ATOM);
atom = terms_.RemoveLast();
+ if (auto lookaround = atom->AsLookaround()) {
+ // Lookbehinds are not quantifiable.
+ if (lookaround->type() == RegExpLookaround::LOOKBEHIND) {
+ return false;
+ }
+ }
if (atom->max_match() == 0) {
// Guaranteed to only match an empty string.
LAST(ADD_TERM);
if (min == 0) {
- return;
+ return true;
}
terms_.Add(atom);
- return;
+ return true;
}
} else {
// Only call immediately after adding an atom or character!
UNREACHABLE();
- return;
}
terms_.Add(new (Z) RegExpQuantifier(min, max, quantifier_type, atom));
LAST(ADD_TERM);
+ return true;
}
// ----------------------------------------------------------------------------
@@ -194,6 +200,7 @@
in_(in),
current_(kEndMarker),
next_pos_(0),
+ captures_started_(0),
capture_count_(0),
has_more_(true),
multiline_(multiline),
@@ -275,7 +282,8 @@
// Atom Quantifier
RegExpTree* RegExpParser::ParseDisjunction() {
// Used to store current state while parsing subexpressions.
- RegExpParserState initial_state(NULL, INITIAL, 0, Z);
+ RegExpParserState initial_state(NULL, INITIAL, RegExpLookaround::LOOKAHEAD, 0,
+ Z);
RegExpParserState* stored_state = &initial_state;
// Cache the builder in a local variable for quick access.
RegExpBuilder* builder = initial_state.builder();
@@ -307,23 +315,24 @@
intptr_t capture_index = stored_state->capture_index();
SubexpressionType group_type = stored_state->group_type();
+ // Build result of subexpression.
+ if (group_type == CAPTURE) {
+ RegExpCapture* capture = GetCapture(capture_index);
+ capture->set_body(body);
+ body = capture;
+ } else if (group_type != GROUPING) {
+ ASSERT(group_type == POSITIVE_LOOKAROUND ||
+ group_type == NEGATIVE_LOOKAROUND);
+ bool is_positive = (group_type == POSITIVE_LOOKAROUND);
+ body = new (Z) RegExpLookaround(
+ body, is_positive, end_capture_index - capture_index,
+ capture_index, stored_state->lookaround_type());
+ }
+
// Restore previous state.
stored_state = stored_state->previous_state();
builder = stored_state->builder();
- // Build result of subexpression.
- if (group_type == CAPTURE) {
- RegExpCapture* capture = new (Z) RegExpCapture(body, capture_index);
- (*captures_)[capture_index - 1] = capture;
- body = capture;
- } else if (group_type != GROUPING) {
- ASSERT(group_type == POSITIVE_LOOKAHEAD ||
- group_type == NEGATIVE_LOOKAHEAD);
- bool is_positive = (group_type == POSITIVE_LOOKAHEAD);
- body = new (Z)
- RegExpLookahead(body, is_positive,
- end_capture_index - capture_index, capture_index);
- }
builder->AddAtom(body);
// For compatibility with JSC and ES3, we allow quantifiers after
// lookaheads, and break in all cases.
@@ -370,37 +379,7 @@
break;
}
case '(': {
- SubexpressionType subexpr_type = CAPTURE;
- Advance();
- if (current() == '?') {
- switch (Next()) {
- case ':':
- subexpr_type = GROUPING;
- break;
- case '=':
- subexpr_type = POSITIVE_LOOKAHEAD;
- break;
- case '!':
- subexpr_type = NEGATIVE_LOOKAHEAD;
- break;
- default:
- ReportError("Invalid group");
- UNREACHABLE();
- }
- Advance(2);
- } else {
- if (captures_ == NULL) {
- captures_ = new ZoneGrowableArray<RegExpCapture*>(2);
- }
- if (captures_started() >= kMaxCaptures) {
- ReportError("Too many captures");
- UNREACHABLE();
- }
- captures_->Add(NULL);
- }
- // Store current state and begin new disjunction parsing.
- stored_state = new RegExpParserState(stored_state, subexpr_type,
- captures_started(), Z);
+ stored_state = ParseOpenParenthesis(stored_state);
builder = stored_state->builder();
continue;
}
@@ -457,16 +436,18 @@
case '9': {
intptr_t index = 0;
if (ParseBackReferenceIndex(&index)) {
- RegExpCapture* capture = NULL;
- if (captures_ != NULL && index <= captures_->length()) {
- capture = captures_->At(index - 1);
- }
- if (capture == NULL) {
+ if (stored_state->IsInsideCaptureGroup(index)) {
+ // The back reference is inside the capture group it refers to.
+ // Nothing can possibly have been captured yet, so we use empty
+ // instead. This ensures that, when checking a back reference,
+ // the capture registers of the referenced capture are either
+ // both set or both cleared.
builder->AddEmpty();
- break;
+ } else {
+ RegExpCapture* capture = GetCapture(index);
+ RegExpTree* atom = new RegExpBackReference(capture);
+ builder->AddAtom(atom);
}
- RegExpTree* atom = new RegExpBackReference(capture);
- builder->AddAtom(atom);
break;
}
uint32_t first_digit = Next();
@@ -610,7 +591,10 @@
quantifier_type = RegExpQuantifier::POSSESSIVE;
Advance();
}
- builder->AddQuantifierToAtom(min, max, quantifier_type);
+ if (!builder->AddQuantifierToAtom(min, max, quantifier_type)) {
+ ReportError("invalid quantifier.");
+ UNREACHABLE();
+ }
}
}
@@ -631,6 +615,57 @@
}
#endif
+RegExpParser::RegExpParserState* RegExpParser::ParseOpenParenthesis(
+ RegExpParserState* state) {
+ RegExpLookaround::Type lookaround_type = state->lookaround_type();
+ SubexpressionType subexpr_type = CAPTURE;
+ Advance();
+ if (current() == '?') {
+ switch (Next()) {
+ case ':':
+ Advance(2);
+ subexpr_type = GROUPING;
+ break;
+ case '=':
+ Advance(2);
+ lookaround_type = RegExpLookaround::LOOKAHEAD;
+ subexpr_type = POSITIVE_LOOKAROUND;
+ break;
+ case '!':
+ Advance(2);
+ lookaround_type = RegExpLookaround::LOOKAHEAD;
+ subexpr_type = NEGATIVE_LOOKAROUND;
+ break;
+ case '<':
+ Advance();
+ if (Next() == '=') {
+ Advance(2);
+ lookaround_type = RegExpLookaround::LOOKBEHIND;
+ subexpr_type = POSITIVE_LOOKAROUND;
+ } else if (Next() == '!') {
+ Advance(2);
+ lookaround_type = RegExpLookaround::LOOKBEHIND;
+ subexpr_type = NEGATIVE_LOOKAROUND;
+ }
+ break;
+ default:
+ ReportError("Invalid group");
+ UNREACHABLE();
+ }
+ }
+
+ if (subexpr_type == CAPTURE) {
+ if (captures_started_ >= kMaxCaptures) {
+ ReportError("Too many captures");
+ UNREACHABLE();
+ }
+ captures_started_++;
+ }
+ // Store current state and begin new disjunction parsing.
+ return new RegExpParserState(state, subexpr_type, lookaround_type,
+ captures_started_, Z);
+}
+
// In order to know whether an escape is a backreference or not we have to scan
// the entire regexp and find the number of capturing parentheses. However we
// don't want to scan the regexp twice unless it is necessary. This mini-parser
@@ -638,6 +673,8 @@
// noncapturing parentheses and can skip character classes and backslash-escaped
// characters.
void RegExpParser::ScanForCaptures() {
+ ASSERT(!is_scanned_for_captures_);
+ const intptr_t saved_position = position();
// Start with captures started previous to current position
intptr_t capture_count = captures_started();
// Add count of captures after this position.
@@ -667,6 +704,7 @@
}
capture_count_ = capture_count;
is_scanned_for_captures_ = true;
+ Reset(saved_position);
}
static inline bool IsDecimalDigit(int32_t c) {
@@ -695,11 +733,7 @@
}
}
if (value > captures_started()) {
- if (!is_scanned_for_captures_) {
- intptr_t saved_position = position();
- ScanForCaptures();
- Reset(saved_position);
- }
+ if (!is_scanned_for_captures_) ScanForCaptures();
if (value > capture_count_) {
Reset(start);
return false;
@@ -709,6 +743,32 @@
return true;
}
+RegExpCapture* RegExpParser::GetCapture(intptr_t index) {
+ // The index for the capture groups are one-based. Its index in the list is
+ // zero-based.
+ const intptr_t know_captures =
+ is_scanned_for_captures_ ? capture_count_ : captures_started_;
+ ASSERT(index <= know_captures);
+ if (captures_ == nullptr) {
+ captures_ = new (Z) ZoneGrowableArray<RegExpCapture*>(know_captures);
+ }
+ while (captures_->length() < know_captures) {
+ captures_->Add(new (Z) RegExpCapture(captures_->length() + 1));
+ }
+ return captures_->At(index - 1);
+}
+
+bool RegExpParser::RegExpParserState::IsInsideCaptureGroup(intptr_t index) {
+ for (RegExpParserState* s = this; s != nullptr; s = s->previous_state()) {
+ if (s->group_type() != CAPTURE) continue;
+ // Return true if we found the matching capture index.
+ if (index == s->capture_index()) return true;
+ // Abort if index is larger than what has been parsed up till this state.
+ if (index > s->capture_index()) return false;
+ }
+ return false;
+}
+
// QuantifierPrefix ::
// { DecimalDigits }
// { DecimalDigits , }
diff --git a/runtime/vm/regexp_parser.h b/runtime/vm/regexp_parser.h
index 51e44c5..c4e127b 100644
--- a/runtime/vm/regexp_parser.h
+++ b/runtime/vm/regexp_parser.h
@@ -23,7 +23,10 @@
void AddAtom(RegExpTree* tree);
void AddAssertion(RegExpTree* tree);
void NewAlternative(); // '|'
- void AddQuantifierToAtom(intptr_t min,
+ // Attempt to add a quantifier to the last atom added. The return value
+ // denotes whether the attempt succeeded, since some atoms like lookbehind
+ // cannot be quantified.
+ bool AddQuantifierToAtom(intptr_t min,
intptr_t max,
RegExpQuantifier::QuantifierType type);
RegExpTree* ToRegExp();
@@ -93,9 +96,7 @@
bool simple();
bool contains_anchor() { return contains_anchor_; }
void set_contains_anchor() { contains_anchor_ = true; }
- intptr_t captures_started() {
- return captures_ == NULL ? 0 : captures_->length();
- }
+ intptr_t captures_started() { return captures_started_; }
intptr_t position() { return next_pos_ - 1; }
static const intptr_t kMaxCaptures = 1 << 16;
@@ -105,8 +106,8 @@
enum SubexpressionType {
INITIAL,
CAPTURE, // All positive values represent captures.
- POSITIVE_LOOKAHEAD,
- NEGATIVE_LOOKAHEAD,
+ POSITIVE_LOOKAROUND,
+ NEGATIVE_LOOKAROUND,
GROUPING
};
@@ -114,11 +115,13 @@
public:
RegExpParserState(RegExpParserState* previous_state,
SubexpressionType group_type,
+ RegExpLookaround::Type lookaround_type,
intptr_t disjunction_capture_index,
Zone* zone)
: previous_state_(previous_state),
builder_(new (zone) RegExpBuilder()),
group_type_(group_type),
+ lookaround_type_(lookaround_type),
disjunction_capture_index_(disjunction_capture_index) {}
// Parser state of containing expression, if any.
RegExpParserState* previous_state() { return previous_state_; }
@@ -127,11 +130,16 @@
RegExpBuilder* builder() { return builder_; }
// Type of regexp being parsed (parenthesized group or entire regexp).
SubexpressionType group_type() { return group_type_; }
+ // Lookahead or lookbehind.
+ RegExpLookaround::Type lookaround_type() { return lookaround_type_; }
// Index in captures array of first capture in this sub-expression, if any.
// Also the capture index of this sub-expression itself, if group_type
// is CAPTURE.
intptr_t capture_index() { return disjunction_capture_index_; }
+ // Check whether the parser is inside a capture group with the given index.
+ bool IsInsideCaptureGroup(intptr_t index);
+
private:
// Linked list implementation of stack of states.
RegExpParserState* previous_state_;
@@ -139,10 +147,17 @@
RegExpBuilder* builder_;
// Stored disjunction type (capture, look-ahead or grouping), if any.
SubexpressionType group_type_;
+ // Stored read direction.
+ const RegExpLookaround::Type lookaround_type_;
// Stored disjunction's capture index (if any).
intptr_t disjunction_capture_index_;
};
+ // Return the 1-indexed RegExpCapture object, allocate if necessary.
+ RegExpCapture* GetCapture(intptr_t index);
+
+ RegExpParserState* ParseOpenParenthesis(RegExpParserState* state);
+
Zone* zone() { return zone_; }
uint32_t current() { return current_; }
@@ -157,6 +172,7 @@
const String& in_;
uint32_t current_;
intptr_t next_pos_;
+ intptr_t captures_started_;
// The capture count is only valid after we have scanned for captures.
intptr_t capture_count_;
bool has_more_;
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index bd13f8c..d7a9fc6 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -78,7 +78,7 @@
demangled ^= Field::NameFromGetter(function_name);
}
- if (Function::IsDynamicInvocationForwaderName(function_name)) {
+ if (Function::IsDynamicInvocationForwarderName(function_name)) {
demangled ^=
Function::DemangleDynamicInvocationForwarderName(function_name);
#ifdef DART_PRECOMPILED_RUNTIME
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 212b0fd..8e90333 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -1041,7 +1041,7 @@
// Handle noSuchMethod for dyn:methodName by getting a noSuchMethod dispatcher
// (or a call-through getter for methodName).
- if (Function::IsDynamicInvocationForwaderName(target_name)) {
+ if (Function::IsDynamicInvocationForwarderName(target_name)) {
const String& demangled = String::Handle(
Function::DemangleDynamicInvocationForwarderName(target_name));
return InlineCacheMissHelper(receiver, args_descriptor, demangled);
@@ -1682,7 +1682,7 @@
target_name = MegamorphicCache::Cast(ic_data_or_cache).target_name();
}
- if (Function::IsDynamicInvocationForwaderName(target_name)) {
+ if (Function::IsDynamicInvocationForwarderName(target_name)) {
target_name = Function::DemangleDynamicInvocationForwarderName(target_name);
}
@@ -1805,6 +1805,11 @@
// - hot reload
static void HandleStackOverflowTestCases(Thread* thread) {
Isolate* isolate = thread->isolate();
+
+ if (FLAG_shared_slow_path_triggers_gc) {
+ isolate->heap()->CollectAllGarbage();
+ }
+
bool do_deopt = false;
bool do_stacktrace = false;
bool do_reload = false;
@@ -2023,15 +2028,11 @@
// persist.
uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags();
- if (FLAG_shared_slow_path_triggers_gc) {
- isolate->heap()->CollectAllGarbage();
- }
-
bool interpreter_stack_overflow = false;
#if !defined(DART_PRECOMPILED_RUNTIME)
if (FLAG_enable_interpreter) {
// Do not allocate an interpreter, if none is allocated yet.
- Interpreter* interpreter = Thread::Current()->interpreter();
+ Interpreter* interpreter = thread->interpreter();
if (interpreter != NULL) {
interpreter_stack_overflow =
interpreter->get_sp() >= interpreter->overflow_stack_limit();
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index c866994..f08dc42 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -173,13 +173,16 @@
Object& object = Object::Handle();
{
Api::Scope api_scope(T);
- TransitionVMToNative transition(T);
- if (get_service_assets_callback_ == NULL) {
- return Object::null();
- }
- Dart_Handle handle = get_service_assets_callback_();
- if (Dart_IsError(handle)) {
- Dart_PropagateError(handle);
+ Dart_Handle handle;
+ {
+ TransitionVMToNative transition(T);
+ if (get_service_assets_callback_ == NULL) {
+ return Object::null();
+ }
+ handle = get_service_assets_callback_();
+ if (Dart_IsError(handle)) {
+ Dart_PropagateError(handle);
+ }
}
object = Api::UnwrapHandle(handle);
}
@@ -1374,6 +1377,16 @@
return true;
}
+static const MethodParameter* get_memory_usage_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+static bool GetMemoryUsage(Thread* thread, JSONStream* js) {
+ thread->isolate()->PrintMemoryUsageJSON(js);
+ return true;
+}
+
static const MethodParameter* get_scripts_params[] = {
RUNNABLE_ISOLATE_PARAMETER,
NULL,
@@ -2362,6 +2375,11 @@
return true;
}
+ bool disable_breakpoints =
+ BoolParameter::Parse(js->LookupParam("disableBreakpoints"), false);
+ DisableBreakpointsScope db(thread->isolate()->debugger(),
+ disable_breakpoints);
+
Zone* zone = thread->zone();
ObjectIdRing::LookupResult lookup_result;
Object& receiver = Object::Handle(
@@ -2842,6 +2860,11 @@
}
Isolate* isolate = thread->isolate();
+
+ bool disable_breakpoints =
+ BoolParameter::Parse(js->LookupParam("disableBreakpoints"), false);
+ DisableBreakpointsScope db(isolate->debugger(), disable_breakpoints);
+
DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
intptr_t frame_pos = UIntParameter::Parse(js->LookupParam("frameIndex"));
if (frame_pos >= stack->Length()) {
@@ -4863,6 +4886,8 @@
get_instances_params },
{ "getIsolate", GetIsolate,
get_isolate_params },
+ { "getMemoryUsage", GetMemoryUsage,
+ get_memory_usage_params },
{ "_getIsolateMetric", GetIsolateMetric,
get_isolate_metric_params },
{ "_getIsolateMetricList", GetIsolateMetricList,
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index df5e2da..0040087 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.14
+# Dart VM Service Protocol 3.16
> Please post feedback to the [observatory-discuss group][discuss-list]
-This document describes of _version 3.14_ of the Dart VM Service Protocol. This
+This document describes of _version 3.16_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -31,6 +31,7 @@
- [evaluateInFrame](#evaluateinframe)
- [getFlagList](#getflaglist)
- [getIsolate](#getisolate)
+ - [getMemoryUsage](#getmemoryusage)
- [getScripts](#getscripts)
- [getObject](#getobject)
- [getSourceReport](#getsourcereport)
@@ -75,6 +76,7 @@
- [Library](#library)
- [LibraryDependency](#librarydependency)
- [MapAssociation](#mapassociation)
+ - [MemoryUsage](#memoryusage)
- [Message](#message)
- [Null](#null)
- [Object](#object)
@@ -479,7 +481,8 @@
@Instance|@Error|Sentinel invoke(string isolateId,
string targetId,
string selector,
- string[] argumentIds)
+ string[] argumentIds,
+ bool disableBreakpoints [optional])
```
The _invoke_ RPC is used to perform regular method invocation on some receiver,
@@ -491,6 +494,10 @@
Each elements of _argumentId_ may refer to an [Instance](#instance).
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this invocation are ignored, including pauses resulting from a call
+to `debugger()` from `dart:developer`. Defaults to false if not provided.
+
If _targetId_ or any element of _argumentIds_ is a temporary id which has
expired, then the _Expired_ [Sentinel](#sentinel) is returned.
@@ -513,7 +520,8 @@
@Instance|@Error|Sentinel evaluate(string isolateId,
string targetId,
string expression,
- map<string,string> scope [optional])
+ map<string,string> scope [optional],
+ bool disableBreakpoints [optional])
```
The _evaluate_ RPC is used to evaluate an expression in the context of
@@ -535,6 +543,9 @@
targets respectively. This means bindings provided in _scope_ may shadow
instance members, class members and top-level members.
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this evaluation are ignored. Defaults to false if not provided.
+
If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
"Expression compilation error" is returned.
@@ -550,7 +561,8 @@
@Instance|@Error|Sentinel evaluateInFrame(string isolateId,
int frameIndex,
string expression,
- map<string,string> scope [optional])
+ map<string,string> scope [optional],
+ bool disableBreakpoints [optional])
```
The _evaluateInFrame_ RPC is used to evaluate an expression in the
@@ -564,6 +576,9 @@
provided in _scope_ may shadow instance members, class members, top-level
members, parameters and locals.
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this evaluation are ignored. Defaults to false if not provided.
+
If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
"Expression compilation error" is returned.
@@ -597,6 +612,20 @@
See [Isolate](#isolate).
+### getMemoryUsage
+
+```
+MemoryUsage|Sentinel getMemoryUsage(string isolateId)
+```
+
+The _getMemoryUsage_ RPC is used to lookup an isolate's memory usage
+statistics by its _id_.
+
+If _isolateId_ refers to an isolate which has exited, then the
+_Collected_ [Sentinel](#sentinel) is returned.
+
+See [Isolate](#isolate).
+
### getScripts
```
@@ -2194,6 +2223,31 @@
}
```
+### MemoryUsage
+
+```
+class MemoryUsage extends Response {
+ // The amount of non-Dart memory that is retained by Dart objects. For
+ // example, memory associated with Dart objects through APIs such as
+ // Dart_NewWeakPersistentHandle and Dart_NewExternalTypedData. This usage is
+ // only as accurate as the values supplied to these APIs from the VM embedder or
+ // native extensions. This external memory applies GC pressure, but is separate
+ // from heapUsage and heapCapacity.
+ int externalUsage;
+
+ // The total capacity of the heap in bytes. This is the amount of memory used
+ // by the Dart heap from the perspective of the operating system.
+ int heapCapacity;
+
+ // The current heap memory usage in bytes. Heap usage is always less than or
+ // equal to the heap capacity.
+ int heapUsage;
+}
+```
+
+An _MemoryUsage_ object provides heap usage information for a specific
+isolate at a given point in time.
+
### Message
```
@@ -2751,5 +2805,7 @@
3.12 | Add 'getScripts' RPC and `ScriptList` object.
3.13 | Class 'mixin' field now properly set for kernel transformed mixin applications.
3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
+3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
+3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service/service_dev.md b/runtime/vm/service/service_dev.md
index 1808c86..a440425 100644
--- a/runtime/vm/service/service_dev.md
+++ b/runtime/vm/service/service_dev.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.15-dev
+# Dart VM Service Protocol 3.17-dev
> Please post feedback to the [observatory-discuss group][discuss-list]
-This document describes of _version 3.15-dev_ of the Dart VM Service Protocol. This
+This document describes of _version 3.17-dev_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -31,6 +31,7 @@
- [evaluateInFrame](#evaluateinframe)
- [getFlagList](#getflaglist)
- [getIsolate](#getisolate)
+ - [getMemoryUsage](#getmemoryusage)
- [getScripts](#getscripts)
- [getObject](#getobject)
- [getSourceReport](#getsourcereport)
@@ -75,6 +76,7 @@
- [Library](#library)
- [LibraryDependency](#librarydependency)
- [MapAssociation](#mapassociation)
+ - [MemoryUsage](#memoryusage)
- [Message](#message)
- [Null](#null)
- [Object](#object)
@@ -479,7 +481,8 @@
@Instance|@Error|Sentinel invoke(string isolateId,
string targetId,
string selector,
- string[] argumentIds)
+ string[] argumentIds,
+ bool disableBreakpoints [optional])
```
The _invoke_ RPC is used to perform regular method invocation on some receiver,
@@ -491,6 +494,10 @@
Each elements of _argumentId_ may refer to an [Instance](#instance).
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this invocation are ignored, including pauses resulting from a call
+to `debugger()` from `dart:developer`. Defaults to false if not provided.
+
If _targetId_ or any element of _argumentIds_ is a temporary id which has
expired, then the _Expired_ [Sentinel](#sentinel) is returned.
@@ -513,7 +520,8 @@
@Instance|@Error|Sentinel evaluate(string isolateId,
string targetId,
string expression,
- map<string,string> scope [optional])
+ map<string,string> scope [optional],
+ bool disableBreakpoints [optional])
```
The _evaluate_ RPC is used to evaluate an expression in the context of
@@ -535,6 +543,9 @@
targets respectively. This means bindings provided in _scope_ may shadow
instance members, class members and top-level members.
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this evaluation are ignored. Defaults to false if not provided.
+
If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
"Expression compilation error" is returned.
@@ -550,7 +561,8 @@
@Instance|@Error|Sentinel evaluateInFrame(string isolateId,
int frameIndex,
string expression,
- map<string,string> scope [optional])
+ map<string,string> scope [optional],
+ bool disableBreakpoints [optional])
```
The _evaluateInFrame_ RPC is used to evaluate an expression in the
@@ -564,6 +576,9 @@
provided in _scope_ may shadow instance members, class members, top-level
members, parameters and locals.
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this evaluation are ignored. Defaults to false if not provided.
+
If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
"Expression compilation error" is returned.
@@ -597,6 +612,20 @@
See [Isolate](#isolate).
+### getMemoryUsage
+
+```
+MemoryUsage|Sentinel getMemoryUsage(string isolateId)
+```
+
+The _getMemoryUsage_ RPC is used to lookup an isolate's memory usage
+statistics by its _id_.
+
+If _isolateId_ refers to an isolate which has exited, then the
+_Collected_ [Sentinel](#sentinel) is returned.
+
+See [Isolate](#isolate).
+
### getScripts
```
@@ -2194,6 +2223,31 @@
}
```
+### MemoryUsage
+
+```
+class MemoryUsage extends Response {
+ // The amount of non-Dart memory that is retained by Dart objects. For
+ // example, memory associated with Dart objects through APIs such as
+ // Dart_NewWeakPersistentHandle and Dart_NewExternalTypedData. This usage is
+ // only as accurate as the values supplied to these APIs from the VM embedder or
+ // native extensions. This external memory applies GC pressure, but is separate
+ // from heapUsage and heapCapacity.
+ int externalUsage;
+
+ // The total capacity of the heap in bytes. This is the amount of memory used
+ // by the Dart heap from the perspective of the operating system.
+ int heapCapacity;
+
+ // The current heap memory usage in bytes. Heap usage is always less than or
+ // equal to the heap capacity.
+ int heapUsage;
+}
+```
+
+An _MemoryUsage_ object provides heap usage information for a specific
+isolate at a given point in time.
+
### Message
```
@@ -2751,5 +2805,7 @@
3.12 | Add 'getScripts' RPC and `ScriptList` object.
3.13 | Class 'mixin' field now properly set for kernel transformed mixin applications.
3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
+3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
+3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 0b9df59..58b38e3 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -37,15 +37,15 @@
(class_id >= kNullCid && class_id <= kVoidCid));
}
-static bool IsObjectStoreClassId(intptr_t class_id) {
- // Check if this is a class which is stored in the object store.
+static bool IsBootstrapedClassId(intptr_t class_id) {
+ // Check if this is a class which is created during bootstrapping.
return (class_id == kObjectCid ||
(class_id >= kInstanceCid && class_id <= kUserTagCid) ||
class_id == kArrayCid || class_id == kImmutableArrayCid ||
RawObject::IsStringClassId(class_id) ||
RawObject::IsTypedDataClassId(class_id) ||
RawObject::IsExternalTypedDataClassId(class_id) ||
- class_id == kNullCid);
+ RawObject::IsTypedDataViewClassId(class_id) || class_id == kNullCid);
}
static bool IsObjectStoreTypeId(intptr_t index) {
@@ -70,7 +70,6 @@
static intptr_t ObjectIdFromClassId(intptr_t class_id) {
ASSERT((class_id > kIllegalCid) && (class_id < kNumPredefinedCids));
- ASSERT(!(RawObject::IsImplicitFieldClassId(class_id)));
return (class_id + kClassIdsOffset);
}
@@ -209,6 +208,7 @@
old_space_(thread_->isolate()->heap()->old_space()),
cls_(Class::Handle(zone_)),
code_(Code::Handle(zone_)),
+ instance_(Instance::Handle(zone_)),
instructions_(Instructions::Handle(zone_)),
obj_(Object::Handle(zone_)),
pobj_(PassiveObject::Handle(zone_)),
@@ -221,6 +221,7 @@
tokens_(GrowableObjectArray::Handle(zone_)),
data_(ExternalTypedData::Handle(zone_)),
typed_data_(TypedData::Handle(zone_)),
+ typed_data_view_(TypedDataView::Handle(zone_)),
function_(Function::Handle(zone_)),
error_(UnhandledException::Handle(zone_)),
set_class_(Class::ZoneHandle(
@@ -315,7 +316,7 @@
ASSERT(!IsVMIsolateObject(class_header) ||
!IsSingletonClassId(GetVMIsolateObjectId(class_header)));
ASSERT((SerializedHeaderTag::decode(class_header) != kObjectId) ||
- !IsObjectStoreClassId(SerializedHeaderData::decode(class_header)));
+ !IsBootstrapedClassId(SerializedHeaderData::decode(class_header)));
Class& cls = Class::ZoneHandle(zone(), Class::null());
AddBackRef(object_id, &cls, kIsDeserialized);
// Read the library/class information and lookup the class.
@@ -479,6 +480,15 @@
break;
}
#undef SNAPSHOT_READ
+#define SNAPSHOT_READ(clazz) case kTypedData##clazz##ViewCid:
+
+ case kByteDataViewCid:
+ CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
+ tags = RawObject::ClassIdTag::update(class_id, tags);
+ pobj_ = TypedDataView::ReadFrom(this, object_id, tags, kind_, true);
+ break;
+ }
+#undef SNAPSHOT_READ
#define SNAPSHOT_READ(clazz) case kFfi##clazz##Cid:
CLASS_LIST_FFI(SNAPSHOT_READ) { UNREACHABLE(); }
@@ -688,7 +698,7 @@
}
ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
intptr_t class_id = SerializedHeaderData::decode(class_header);
- ASSERT(IsObjectStoreClassId(class_id) || IsSingletonClassId(class_id));
+ ASSERT(IsBootstrapedClassId(class_id) || IsSingletonClassId(class_id));
return class_id;
}
@@ -758,7 +768,7 @@
RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) {
intptr_t class_id = ClassIdFromObjectId(object_id);
- if (IsObjectStoreClassId(class_id)) {
+ if (IsBootstrapedClassId(class_id)) {
return isolate()->class_table()->At(class_id); // get singleton class.
}
if (IsObjectStoreTypeId(object_id)) {
@@ -1025,7 +1035,7 @@
if (cid == kClassCid) {
RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj);
intptr_t class_id = raw_class->ptr()->id_;
- if (IsObjectStoreClassId(class_id)) {
+ if (IsBootstrapedClassId(class_id)) {
intptr_t object_id = ObjectIdFromClassId(class_id);
WriteIndexedObject(object_id);
return true;
@@ -1110,6 +1120,16 @@
return;
}
#undef SNAPSHOT_WRITE
+#define SNAPSHOT_WRITE(clazz) case kTypedData##clazz##ViewCid:
+
+ case kByteDataViewCid:
+ CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
+ auto* raw_obj = reinterpret_cast<RawTypedDataView*>(raw);
+ raw_obj->WriteTo(this, object_id, kind_, as_reference);
+ return;
+ }
+#undef SNAPSHOT_WRITE
+
#define SNAPSHOT_WRITE(clazz) case kFfi##clazz##Cid:
CLASS_LIST_FFI(SNAPSHOT_WRITE) { UNREACHABLE(); }
@@ -1171,7 +1191,7 @@
void SnapshotWriter::WriteClassId(RawClass* cls) {
ASSERT(!Snapshot::IsFull(kind_));
int class_id = cls->ptr()->id_;
- ASSERT(!IsSingletonClassId(class_id) && !IsObjectStoreClassId(class_id));
+ ASSERT(!IsSingletonClassId(class_id) && !IsBootstrapedClassId(class_id));
// Write out the library url and class name.
RawLibrary* library = cls->ptr()->library_;
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 5a4ab63..248127c 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -28,6 +28,7 @@
class ExternalTypedData;
class GrowableObjectArray;
class Heap;
+class Instance;
class Instructions;
class LanguageError;
class Library;
@@ -37,6 +38,7 @@
class ObjectStore;
class MegamorphicCache;
class PageSpace;
+class TypedDataView;
class RawApiError;
class RawArray;
class RawCapability;
@@ -86,6 +88,7 @@
class RawType;
class RawTypeArguments;
class RawTypedData;
+class RawTypedDataView;
class RawTypeParameter;
class RawTypeRef;
class RawUnhandledException;
@@ -98,8 +101,8 @@
// Serialized object header encoding is as follows:
// - Smi: the Smi value is written as is (last bit is not tagged).
// - VM object (from VM isolate): (object id in vm isolate | 0x3)
-// This valus is serialized as a negative number.
-// (note VM objects are never serialized they are expected to be found
+// This value is serialized as a negative number.
+// (note VM objects are never serialized, they are expected to be found
// using ths unique ID assigned to them).
// - Reference to object that has already been written: (object id | 0x3)
// This valus is serialized as a positive number.
@@ -300,6 +303,7 @@
Array* ArrayHandle() { return &array_; }
Class* ClassHandle() { return &cls_; }
Code* CodeHandle() { return &code_; }
+ Instance* InstanceHandle() { return &instance_; }
Instructions* InstructionsHandle() { return &instructions_; }
String* StringHandle() { return &str_; }
AbstractType* TypeHandle() { return &type_; }
@@ -307,6 +311,7 @@
GrowableObjectArray* TokensHandle() { return &tokens_; }
ExternalTypedData* DataHandle() { return &data_; }
TypedData* TypedDataHandle() { return &typed_data_; }
+ TypedDataView* TypedDataViewHandle() { return &typed_data_view_; }
Function* FunctionHandle() { return &function_; }
Snapshot::Kind kind() const { return kind_; }
@@ -386,6 +391,7 @@
PageSpace* old_space_; // Old space of the current isolate.
Class& cls_; // Temporary Class handle.
Code& code_; // Temporary Code handle.
+ Instance& instance_; // Temporary Instance handle
Instructions& instructions_; // Temporary Instructions handle
Object& obj_; // Temporary Object handle.
PassiveObject& pobj_; // Temporary PassiveObject handle.
@@ -398,6 +404,7 @@
GrowableObjectArray& tokens_; // Temporary tokens handle.
ExternalTypedData& data_; // Temporary stream data handle.
TypedData& typed_data_; // Temporary typed data handle.
+ TypedDataView& typed_data_view_; // Temporary typed data view handle.
Function& function_; // Temporary function handle.
UnhandledException& error_; // Error handle.
const Class& set_class_; // The LinkedHashSet class.
@@ -433,6 +440,7 @@
friend class SignatureData;
friend class SubtypeTestCache;
friend class Type;
+ friend class TypedDataView;
friend class TypeArguments;
friend class TypeParameter;
friend class TypeRef;
@@ -705,6 +713,7 @@
friend class RawStackTrace;
friend class RawSubtypeTestCache;
friend class RawType;
+ friend class RawTypedDataView;
friend class RawTypeRef;
friend class RawTypeArguments;
friend class RawTypeParameter;
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 78cea42..b204514 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -405,7 +405,7 @@
// The thread setting the stack limit is not necessarily the thread which
// the stack limit is being set on.
MonitorLocker ml(thread_lock_);
- if (stack_limit_ == saved_stack_limit_) {
+ if (!HasScheduledInterrupts()) {
// No interrupt pending, set stack_limit_ too.
stack_limit_ = limit;
}
diff --git a/runtime/vm/timeline_linux.cc b/runtime/vm/timeline_linux.cc
index 4dbad22..dc45ffb 100644
--- a/runtime/vm/timeline_linux.cc
+++ b/runtime/vm/timeline_linux.cc
@@ -28,9 +28,9 @@
const char* kSystraceDebugPath = "/sys/kernel/debug/tracing/trace_marker";
const char* kSystracePath = "/sys/kernel/tracing/trace_marker";
- int fd = TEMP_FAILURE_RETRY(::open(kSystraceDebugPath, O_WRONLY));
+ int fd = TEMP_FAILURE_RETRY(::open(kSystracePath, O_WRONLY));
if (fd < 0) {
- fd = TEMP_FAILURE_RETRY(::open(kSystracePath, O_WRONLY));
+ fd = TEMP_FAILURE_RETRY(::open(kSystraceDebugPath, O_WRONLY));
}
if (fd < 0 && FLAG_trace_timeline) {
diff --git a/runtime/vm/unicode.cc b/runtime/vm/unicode.cc
index a3b4fb9..90379d1 100644
--- a/runtime/vm/unicode.cc
+++ b/runtime/vm/unicode.cc
@@ -344,6 +344,7 @@
return false; // Invalid input.
}
if (is_supplementary) {
+ if (j == (len - 1)) return false; // Output overflow.
Utf16::Encode(ch, &dst[j]);
j = j + 1;
} else {
diff --git a/runtime/vm/version.h b/runtime/vm/version.h
index 24540c3..fdc6bb0 100644
--- a/runtime/vm/version.h
+++ b/runtime/vm/version.h
@@ -14,7 +14,6 @@
static const char* String();
static const char* SnapshotString();
static const char* CommitString();
- static int TargetAbiVersion();
static int CurrentAbiVersion();
static int OldestSupportedAbiVersion();
diff --git a/runtime/vm/version_in.cc b/runtime/vm/version_in.cc
index d59584b..ae3cff7 100644
--- a/runtime/vm/version_in.cc
+++ b/runtime/vm/version_in.cc
@@ -10,12 +10,6 @@
namespace dart {
-DEFINE_FLAG(int,
- use_abi_version,
- Version::CurrentAbiVersion(),
- "ABI version to use. Valid values are "
- "{{OLDEST_SUPPORTED_ABI_VERSION}} to {{ABI_VERSION}}.");
-
// TODO(iposva): Avoid racy initialization.
static const char* formatted_version = NULL;
@@ -36,14 +30,6 @@
return commit_;
}
-int Version::TargetAbiVersion() {
- int ver = FLAG_use_abi_version;
- if (ver < OldestSupportedAbiVersion() || ver > CurrentAbiVersion()) {
- ver = CurrentAbiVersion();
- }
- return ver;
-}
-
int Version::CurrentAbiVersion() {
return {{ABI_VERSION}};
}
diff --git a/runtime/vm/virtual_memory.cc b/runtime/vm/virtual_memory.cc
index 6d73ba0..48ba867 100644
--- a/runtime/vm/virtual_memory.cc
+++ b/runtime/vm/virtual_memory.cc
@@ -17,12 +17,18 @@
void VirtualMemory::Truncate(intptr_t new_size) {
ASSERT(Utils::IsAligned(new_size, PageSize()));
ASSERT(new_size <= size());
- if (reserved_.size() == region_.size()) { // Don't create holes in reservation.
+ if (reserved_.size() ==
+ region_.size()) { // Don't create holes in reservation.
FreeSubSegment(reinterpret_cast<void*>(start() + new_size),
size() - new_size);
reserved_.set_size(new_size);
+ if (AliasOffset() != 0) {
+ FreeSubSegment(reinterpret_cast<void*>(alias_.start() + new_size),
+ alias_.size() - new_size);
+ }
}
region_.Subregion(region_, 0, new_size);
+ alias_.Subregion(alias_, 0, new_size);
}
VirtualMemory* VirtualMemory::ForImagePage(void* pointer, uword size) {
@@ -31,7 +37,7 @@
MemoryRegion region(pointer, size);
MemoryRegion reserved(0, 0); // NULL reservation indicates VM should not
// attempt to free this memory.
- VirtualMemory* memory = new VirtualMemory(region, reserved);
+ VirtualMemory* memory = new VirtualMemory(region, region, reserved);
ASSERT(!memory->vm_owns_region());
return memory;
}
diff --git a/runtime/vm/virtual_memory.h b/runtime/vm/virtual_memory.h
index 6d74541..496e63c 100644
--- a/runtime/vm/virtual_memory.h
+++ b/runtime/vm/virtual_memory.h
@@ -28,10 +28,14 @@
uword end() const { return region_.end(); }
void* address() const { return region_.pointer(); }
intptr_t size() const { return region_.size(); }
+ intptr_t AliasOffset() const { return alias_.start() - region_.start(); }
static void Init();
bool Contains(uword addr) const { return region_.Contains(addr); }
+ bool ContainsAlias(uword addr) const {
+ return (AliasOffset() != 0) && alias_.Contains(addr);
+ }
// Changes the protection of the virtual memory area.
static void Protect(void* address, intptr_t size, Protection mode);
@@ -72,14 +76,22 @@
// can give back the virtual memory to the system. Returns true on success.
static void FreeSubSegment(void* address, intptr_t size);
- // This constructor is only used internally when reserving new virtual spaces.
- // It does not reserve any virtual address space on its own.
+ // These constructors are only used internally when reserving new virtual
+ // spaces. They do not reserve any virtual address space on their own.
VirtualMemory(const MemoryRegion& region,
+ const MemoryRegion& alias,
const MemoryRegion& reserved)
- : region_(region), reserved_(reserved) {}
+ : region_(region), alias_(alias), reserved_(reserved) {}
+
+ VirtualMemory(const MemoryRegion& region, const MemoryRegion& reserved)
+ : region_(region), alias_(region), reserved_(reserved) {}
MemoryRegion region_;
+ // Optional secondary mapping of region_ to a virtual space with different
+ // protection, e.g. allowing code execution.
+ MemoryRegion alias_;
+
// The underlying reservation not yet given back to the OS.
// Its address might disagree with region_ due to aligned allocations.
// Its size might disagree with region_ due to Truncate.
@@ -87,6 +99,10 @@
static uword page_size_;
+#if defined(HOST_OS_FUCHSIA)
+ static uword base_; // Cached base of root vmar.
+#endif
+
DISALLOW_IMPLICIT_CONSTRUCTORS(VirtualMemory);
};
diff --git a/runtime/vm/virtual_memory_fuchsia.cc b/runtime/vm/virtual_memory_fuchsia.cc
index 63c47ae..b627ddf 100644
--- a/runtime/vm/virtual_memory_fuchsia.cc
+++ b/runtime/vm/virtual_memory_fuchsia.cc
@@ -35,15 +35,29 @@
namespace dart {
+DECLARE_FLAG(bool, dual_map_code);
DECLARE_FLAG(bool, write_protect_code);
uword VirtualMemory::page_size_ = 0;
+uword VirtualMemory::base_ = 0;
void VirtualMemory::Init() {
page_size_ = getpagesize();
+
+ // Cache the base of zx_vmar_root_self() which is used to align mappings.
+ zx_info_vmar_t buf[1];
+ size_t actual;
+ size_t avail;
+ zx_status_t status =
+ zx_object_get_info(zx_vmar_root_self(), ZX_INFO_VMAR, buf,
+ sizeof(zx_info_vmar_t), &actual, &avail);
+ if (status != ZX_OK) {
+ FATAL1("zx_object_get_info failed: %s\n", zx_status_get_string(status));
+ }
+ base_ = buf[0].base;
}
-static void unmap(zx_handle_t vmar, uword start, uword end) {
+static void Unmap(zx_handle_t vmar, uword start, uword end) {
ASSERT(start <= end);
const uword size = end - start;
if (size == 0) {
@@ -56,28 +70,61 @@
}
}
+static void* MapAligned(zx_handle_t vmar,
+ zx_handle_t vmo,
+ zx_vm_option_t options,
+ uword size,
+ uword alignment,
+ uword vmar_base,
+ uword padded_size) {
+ uword base;
+ zx_status_t status =
+ zx_vmar_map(vmar, options, 0, vmo, 0u, padded_size, &base);
+ LOG_INFO("zx_vmar_map(%u, 0x%lx, 0x%lx)\n", options, base, padded_size);
+
+ if (status != ZX_OK) {
+ LOG_ERR("zx_vmar_map(%u, 0x%lx, 0x%lx) failed: %s\n", options, base,
+ padded_size, zx_status_get_string(status));
+ return NULL;
+ }
+ const uword aligned_base = Utils::RoundUp(base, alignment);
+ const zx_vm_option_t overwrite_options = options | ZX_VM_SPECIFIC_OVERWRITE;
+ status = zx_vmar_map(vmar, overwrite_options, aligned_base - vmar_base, vmo,
+ 0u, size, &base);
+ LOG_INFO("zx_vmar_map(%u, 0x%lx, 0x%lx)\n", overwrite_options,
+ aligned_base - vmar_base, size);
+
+ if (status != ZX_OK) {
+ LOG_ERR("zx_vmar_map(%u, 0x%lx, 0x%lx) failed: %s\n", overwrite_options,
+ aligned_base - vmar_base, size, zx_status_get_string(status));
+ return NULL;
+ }
+ ASSERT(base == aligned_base);
+ return reinterpret_cast<void*>(base);
+}
+
VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
intptr_t alignment,
bool is_executable,
const char* name) {
- // When FLAG_write_protect_code is active, the VM allocates code
- // memory with !is_executable, and later changes to executable via
- // VirtualMemory::Protect, which requires ZX_RIGHT_EXECUTE on the
- // underlying VMO. Conservatively assume all memory needs to be
- // executable in this mode.
- // TODO(mdempsky): Make into parameter.
- const bool can_prot_exec = FLAG_write_protect_code;
+ // When FLAG_write_protect_code is active, code memory (indicated by
+ // is_executable = true) is allocated as non-executable and later
+ // changed to executable via VirtualMemory::Protect, which requires
+ // ZX_RIGHT_EXECUTE on the underlying VMO.
+ // In addition, dual mapping of the same underlying code memory is provided.
+ const bool dual_mapping =
+ is_executable && FLAG_write_protect_code && FLAG_dual_map_code;
ASSERT(Utils::IsAligned(size, page_size_));
ASSERT(Utils::IsPowerOfTwo(alignment));
ASSERT(Utils::IsAligned(alignment, page_size_));
- const intptr_t allocated_size = size + alignment - page_size_;
+ const intptr_t padded_size = size + alignment - page_size_;
zx_handle_t vmar = zx_vmar_root_self();
zx_handle_t vmo = ZX_HANDLE_INVALID;
- zx_status_t status = zx_vmo_create(allocated_size, 0u, &vmo);
+ zx_status_t status = zx_vmo_create(size, 0u, &vmo);
if (status != ZX_OK) {
- LOG_ERR("zx_vmo_create(%ld) failed: %s\n", size,
+ LOG_ERR("zx_vmo_create(0x%lx) failed: %s\n", size,
zx_status_get_string(status));
return NULL;
}
@@ -86,9 +133,9 @@
zx_object_set_property(vmo, ZX_PROP_NAME, name, strlen(name));
}
- if (is_executable || can_prot_exec) {
+ if (is_executable) {
// Add ZX_RIGHT_EXECUTE permission to VMO, so it can be mapped
- // into memory as executable.
+ // into memory as executable (now or later).
status = zx_vmo_replace_as_executable(vmo, ZX_HANDLE_INVALID, &vmo);
if (status != ZX_OK) {
LOG_ERR("zx_vmo_replace_as_executable() failed: %s\n",
@@ -97,39 +144,59 @@
}
}
- const zx_vm_option_t options = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE |
- (is_executable ? ZX_VM_PERM_EXECUTE : 0);
- uword base;
- status = zx_vmar_map(vmar, options, 0u, vmo, 0u, allocated_size, &base);
- zx_handle_close(vmo);
- if (status != ZX_OK) {
- LOG_ERR("zx_vmar_map(%u, %ld) failed: %s\n", flags, size,
- zx_status_get_string(status));
+ const zx_vm_option_t region_options =
+ ZX_VM_PERM_READ | ZX_VM_PERM_WRITE |
+ ((is_executable && !FLAG_write_protect_code) ? ZX_VM_PERM_EXECUTE : 0);
+ void* region_ptr = MapAligned(vmar, vmo, region_options, size, alignment,
+ base_, padded_size);
+ if (region_ptr == NULL) {
return NULL;
}
+ MemoryRegion region(region_ptr, size);
- const uword aligned_base = Utils::RoundUp(base, alignment);
+ VirtualMemory* result;
- unmap(vmar, base, aligned_base);
- unmap(vmar, aligned_base + size, base + allocated_size);
-
- MemoryRegion region(reinterpret_cast<void*>(aligned_base), size);
- return new VirtualMemory(region, region);
+ if (dual_mapping) {
+ // ZX_VM_PERM_EXECUTE is added later via VirtualMemory::Protect.
+ const zx_vm_option_t alias_options = ZX_VM_PERM_READ;
+ void* alias_ptr = MapAligned(vmar, vmo, alias_options, size, alignment,
+ base_, padded_size);
+ if (alias_ptr == NULL) {
+ const uword region_base = reinterpret_cast<uword>(region_ptr);
+ Unmap(vmar, region_base, region_base + size);
+ return NULL;
+ }
+ ASSERT(region_ptr != alias_ptr);
+ MemoryRegion alias(alias_ptr, size);
+ result = new VirtualMemory(region, alias, region);
+ } else {
+ result = new VirtualMemory(region, region, region);
+ }
+ zx_handle_close(vmo);
+ return result;
}
VirtualMemory::~VirtualMemory() {
// Reserved region may be empty due to VirtualMemory::Truncate.
if (vm_owns_region() && reserved_.size() != 0) {
- unmap(zx_vmar_root_self(), reserved_.start(), reserved_.end());
- LOG_INFO("zx_vmar_unmap(%lx, %lx) success\n", reserved_.start(),
+ Unmap(zx_vmar_root_self(), reserved_.start(), reserved_.end());
+ LOG_INFO("zx_vmar_unmap(0x%lx, 0x%lx) success\n", reserved_.start(),
reserved_.size());
+
+ const intptr_t alias_offset = AliasOffset();
+ if (alias_offset != 0) {
+ Unmap(zx_vmar_root_self(), reserved_.start() + alias_offset,
+ reserved_.end() + alias_offset);
+ LOG_INFO("zx_vmar_unmap(0x%lx, 0x%lx) success\n",
+ reserved_.start() + alias_offset, reserved_.size());
+ }
}
}
void VirtualMemory::FreeSubSegment(void* address, intptr_t size) {
const uword start = reinterpret_cast<uword>(address);
- unmap(zx_vmar_root_self(), start, start + size);
- LOG_INFO("zx_vmar_unmap(%p, %lx) success\n", address, size);
+ Unmap(zx_vmar_root_self(), start, start + size);
+ LOG_INFO("zx_vmar_unmap(0x%p, 0x%lx) success\n", address, size);
}
void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
@@ -161,12 +228,12 @@
}
zx_status_t status = zx_vmar_protect(zx_vmar_root_self(), prot, page_address,
end_address - page_address);
+ LOG_INFO("zx_vmar_protect(%u, 0x%lx, 0x%lx)\n", prot, page_address,
+ end_address - page_address);
if (status != ZX_OK) {
- FATAL3("zx_vmar_protect(%lx, %lx) failed: %s\n", page_address,
+ FATAL3("zx_vmar_protect(0x%lx, 0x%lx) failed: %s\n", page_address,
end_address - page_address, zx_status_get_string(status));
}
- LOG_INFO("zx_vmar_protect(%lx, %lx, %x) success\n", page_address,
- end_address - page_address, prot);
}
} // namespace dart
diff --git a/runtime/vm/virtual_memory_posix.cc b/runtime/vm/virtual_memory_posix.cc
index 31c7f15..5751e7f 100644
--- a/runtime/vm/virtual_memory_posix.cc
+++ b/runtime/vm/virtual_memory_posix.cc
@@ -8,14 +8,23 @@
#include "vm/virtual_memory.h"
#include <errno.h>
+#include <fcntl.h>
#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
#include <unistd.h>
#include "platform/assert.h"
#include "platform/utils.h"
-
#include "vm/isolate.h"
+// #define VIRTUAL_MEMORY_LOGGING 1
+#if defined(VIRTUAL_MEMORY_LOGGING)
+#define LOG_INFO(msg, ...) OS::PrintErr(msg, ##__VA_ARGS__)
+#else
+#define LOG_INFO(msg, ...)
+#endif // defined(VIRTUAL_MEMORY_LOGGING)
+
namespace dart {
// standard MAP_FAILED causes "error: use of old-style cast" as it
@@ -23,10 +32,38 @@
#undef MAP_FAILED
#define MAP_FAILED reinterpret_cast<void*>(-1)
+DECLARE_FLAG(bool, dual_map_code);
+DECLARE_FLAG(bool, write_protect_code);
+
uword VirtualMemory::page_size_ = 0;
void VirtualMemory::Init() {
page_size_ = getpagesize();
+
+#if defined(DUAL_MAPPING_SUPPORTED)
+ // Detect dual mapping exec permission limitation on some platforms,
+ // such as on docker containers, and disable dual mapping in this case.
+ // Also detect for missing support of memfd_create syscall.
+ if (FLAG_dual_map_code) {
+ intptr_t size = page_size_;
+ intptr_t alignment = 256 * 1024; // e.g. heap page size.
+ VirtualMemory* vm = AllocateAligned(size, alignment, true, NULL);
+ if (vm == NULL) {
+ LOG_INFO("memfd_create not supported; disabling dual mapping of code.\n");
+ FLAG_dual_map_code = false;
+ return;
+ }
+ void* region = reinterpret_cast<void*>(vm->region_.start());
+ void* alias = reinterpret_cast<void*>(vm->alias_.start());
+ if (region == alias ||
+ mprotect(region, size, PROT_READ) != 0 || // Remove PROT_WRITE.
+ mprotect(alias, size, PROT_READ | PROT_EXEC) != 0) { // Add PROT_EXEC.
+ LOG_INFO("mprotect fails; disabling dual mapping of code.\n");
+ FLAG_dual_map_code = false;
+ }
+ delete vm;
+ }
+#endif // defined(DUAL_MAPPING_SUPPORTED)
}
static void unmap(uword start, uword end) {
@@ -45,17 +82,110 @@
}
}
+#if defined(DUAL_MAPPING_SUPPORTED)
+// Do not leak file descriptors to child processes.
+#if !defined(MFD_CLOEXEC)
+#define MFD_CLOEXEC 0x0001U
+#endif
+
+// Wrapper to call memfd_create syscall.
+static inline int memfd_create(const char* name, unsigned int flags) {
+#if !defined(__NR_memfd_create)
+ errno = ENOSYS;
+ return -1;
+#else
+ return syscall(__NR_memfd_create, name, flags);
+#endif
+}
+
+static void* MapAligned(int fd,
+ int prot,
+ intptr_t size,
+ intptr_t alignment,
+ intptr_t allocated_size) {
+ void* address =
+ mmap(NULL, allocated_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ LOG_INFO("mmap(NULL, 0x%" Px ", PROT_NONE, ...): %p\n", allocated_size,
+ address);
+ if (address == MAP_FAILED) {
+ return NULL;
+ }
+
+ const uword base = reinterpret_cast<uword>(address);
+ const uword aligned_base = Utils::RoundUp(base, alignment);
+
+ // Guarantee the alignment by mapping at a fixed address inside the above
+ // mapping. Overlapping region will be automatically discarded in the above
+ // mapping. Manually discard non-overlapping regions.
+ address = mmap(reinterpret_cast<void*>(aligned_base), size, prot,
+ MAP_SHARED | MAP_FIXED, fd, 0);
+ LOG_INFO("mmap(0x%" Px ", 0x%" Px ", %u, ...): %p\n", aligned_base, size,
+ prot, address);
+ if (address == MAP_FAILED) {
+ unmap(base, base + allocated_size);
+ return NULL;
+ }
+ ASSERT(address == reinterpret_cast<void*>(aligned_base));
+ unmap(base, aligned_base);
+ unmap(aligned_base + size, base + allocated_size);
+ return address;
+}
+#endif // defined(DUAL_MAPPING_SUPPORTED)
+
VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
intptr_t alignment,
bool is_executable,
const char* name) {
+ // When FLAG_write_protect_code is active, code memory (indicated by
+ // is_executable = true) is allocated as non-executable and later
+ // changed to executable via VirtualMemory::Protect.
ASSERT(Utils::IsAligned(size, page_size_));
ASSERT(Utils::IsPowerOfTwo(alignment));
ASSERT(Utils::IsAligned(alignment, page_size_));
const intptr_t allocated_size = size + alignment - page_size_;
- const int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+#if defined(DUAL_MAPPING_SUPPORTED)
+ int fd = -1;
+ const bool dual_mapping =
+ is_executable && FLAG_write_protect_code && FLAG_dual_map_code;
+ if (dual_mapping) {
+ fd = memfd_create("dart_vm", MFD_CLOEXEC);
+ if (fd == -1) {
+ return NULL;
+ }
+ if (ftruncate(fd, size) == -1) {
+ close(fd);
+ return NULL;
+ }
+ const int region_prot = PROT_READ | PROT_WRITE;
+ void* region_ptr =
+ MapAligned(fd, region_prot, size, alignment, allocated_size);
+ if (region_ptr == NULL) {
+ close(fd);
+ return NULL;
+ }
+ MemoryRegion region(region_ptr, size);
+ // PROT_EXEC is added later via VirtualMemory::Protect.
+ const int alias_prot = PROT_READ;
+ void* alias_ptr =
+ MapAligned(fd, alias_prot, size, alignment, allocated_size);
+ close(fd);
+ if (alias_ptr == NULL) {
+ const uword region_base = reinterpret_cast<uword>(region_ptr);
+ unmap(region_base, region_base + size);
+ return NULL;
+ }
+ ASSERT(region_ptr != alias_ptr);
+ MemoryRegion alias(alias_ptr, size);
+ return new VirtualMemory(region, alias, region);
+ }
+#endif // defined(DUAL_MAPPING_SUPPORTED)
+ const int prot =
+ PROT_READ | PROT_WRITE |
+ ((is_executable && !FLAG_write_protect_code) ? PROT_EXEC : 0);
void* address =
- mmap(NULL, allocated_size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
+ mmap(NULL, allocated_size, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ LOG_INFO("mmap(NULL, 0x%" Px ", %u, ...): %p\n", allocated_size, prot,
+ address);
if (address == MAP_FAILED) {
return NULL;
}
@@ -73,6 +203,10 @@
VirtualMemory::~VirtualMemory() {
if (vm_owns_region()) {
unmap(reserved_.start(), reserved_.end());
+ const intptr_t alias_offset = AliasOffset();
+ if (alias_offset != 0) {
+ unmap(reserved_.start() + alias_offset, reserved_.end() + alias_offset);
+ }
}
}
@@ -114,11 +248,15 @@
int error = errno;
const int kBufferSize = 1024;
char error_buf[kBufferSize];
+ LOG_INFO("mprotect(0x%" Px ", 0x%" Px ", %u) failed\n", page_address,
+ end_address - page_address, prot);
FATAL2("mprotect error: %d (%s)", error,
Utils::StrError(error, error_buf, kBufferSize));
}
+ LOG_INFO("mprotect(0x%" Px ", 0x%" Px ", %u) ok\n", page_address,
+ end_address - page_address, prot);
}
} // namespace dart
-#endif // defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS)
+#endif // defined(HOST_OS_ANDROID ... HOST_OS_LINUX ... HOST_OS_MACOS)
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index 9c917b3..3ec743f0 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -14,6 +14,8 @@
namespace dart {
+DECLARE_FLAG(bool, write_protect_code);
+
uword VirtualMemory::page_size_ = 0;
void VirtualMemory::Init() {
@@ -26,11 +28,16 @@
intptr_t alignment,
bool is_executable,
const char* name) {
+ // When FLAG_write_protect_code is active, code memory (indicated by
+ // is_executable = true) is allocated as non-executable and later
+ // changed to executable via VirtualMemory::Protect.
ASSERT(Utils::IsAligned(size, page_size_));
ASSERT(Utils::IsPowerOfTwo(alignment));
ASSERT(Utils::IsAligned(alignment, page_size_));
intptr_t reserved_size = size + alignment - page_size_;
- int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
+ int prot = (is_executable && !FLAG_write_protect_code)
+ ? PAGE_EXECUTE_READWRITE
+ : PAGE_READWRITE;
void* address = VirtualAlloc(NULL, reserved_size, MEM_RESERVE, prot);
if (address == NULL) {
return NULL;
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 717b50c..4081d35 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -373,6 +373,7 @@
"bitfield_test.cc",
"bitmap_test.cc",
"boolfield_test.cc",
+ "catch_entry_moves_test.cc",
"class_finalizer_test.cc",
"code_descriptors_test.cc",
"code_patcher_arm64_test.cc",
diff --git a/samples/ffi/dylib_utils.dart b/samples/ffi/dylib_utils.dart
index 1929961..1c924d4 100644
--- a/samples/ffi/dylib_utils.dart
+++ b/samples/ffi/dylib_utils.dart
@@ -9,6 +9,7 @@
if (path == null) path = "";
if (Platform.isLinux) return path + "lib" + name + ".so";
if (Platform.isMacOS) return path + "lib" + name + ".dylib";
+ if (Platform.isWindows) return path + name + ".dll";
throw Exception("Platform not implemented");
}
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 3f48b0a..50c2682 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -495,6 +495,16 @@
]
}
+copy("copy_abi_dill_files") {
+ visibility = [ ":create_common_sdk" ]
+ sources = [
+ "../tools/abiversions",
+ ]
+ outputs = [
+ "$root_out_dir/dart-sdk/lib/_internal/abiversions",
+ ]
+}
+
copy("copy_dart2js_dill_files") {
visibility = [ ":create_full_sdk" ]
deps = [
@@ -889,6 +899,7 @@
group("create_common_sdk") {
visibility = [ ":create_sdk" ]
public_deps = [
+ ":copy_abi_dill_files",
":copy_analysis_summaries",
":copy_api_readme",
":copy_dart",
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 045a2f1..e31fe29 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -2662,7 +2662,9 @@
var resultBits = new Uint8List(8);
var length = _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
- if (length - 53 > maxDoubleExponent) return double.infinity;
+ if (length > maxDoubleExponent + 53) {
+ return _isNegative ? double.negativeInfinity : double.infinity;
+ }
// The most significant bit is for the sign.
if (_isNegative) resultBits[7] = 0x80;
diff --git a/sdk/lib/_internal/js_runtime/lib/js_string.dart b/sdk/lib/_internal/js_runtime/lib/js_string.dart
index b5be305..39370d7 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_string.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_string.dart
@@ -59,8 +59,7 @@
}
String replaceAll(Pattern from, String to) {
- checkString(to);
- return stringReplaceAllUnchecked(this, from, to);
+ return stringReplaceAllUnchecked(this, from, checkString(to));
}
String replaceAllMapped(Pattern from, String convert(Match match)) {
diff --git a/sdk/lib/_internal/js_runtime/lib/math_patch.dart b/sdk/lib/_internal/js_runtime/lib/math_patch.dart
index a3d3fc9..677953e 100644
--- a/sdk/lib/_internal/js_runtime/lib/math_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/math_patch.dart
@@ -63,14 +63,14 @@
@patch
class Random {
- static final _secureRandom = new _JSSecureRandom();
+ static Random _secureRandom;
@patch
factory Random([int seed]) =>
(seed == null) ? const _JSRandom() : new _Random(seed);
@patch
- factory Random.secure() => _secureRandom;
+ factory Random.secure() => _secureRandom ??= _JSSecureRandom();
}
class _JSRandom implements Random {
diff --git a/sdk/lib/_internal/js_runtime/lib/string_helper.dart b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
index 0180369..ea5374e 100644
--- a/sdk/lib/_internal/js_runtime/lib/string_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
@@ -117,12 +117,23 @@
}
}
-stringReplaceJS(receiver, replacer, replacement) {
- // The JavaScript String.replace method recognizes replacement
- // patterns in the replacement string. Dart does not have that
- // behavior.
- replacement = JS('String', r'#.replace(/\$/g, "$$$$")', replacement);
- return JS('String', r'#.replace(#, #)', receiver, replacer, replacement);
+String stringReplaceJS(String receiver, jsRegExp, String replacement) {
+ return JS('String', r'#.replace(#, #)', receiver, jsRegExp,
+ escapeReplacement(replacement));
+}
+
+String escapeReplacement(String replacement) {
+ // The JavaScript `String.prototype.replace` method recognizes replacement
+ // patterns in the replacement string. Dart does not have that behavior, so
+ // the replacement patterns need to be escaped.
+
+ // `String.prototype.replace` tends to be slower when there are replacement
+ // patterns, and the escaping itself uses replacement patterns, so it is
+ // worthwhile checking for `$` first.
+ if (stringContainsStringUnchecked(replacement, r'$', 0)) {
+ return JS('String', r'#.replace(/\$/g, "$$$$")', replacement);
+ }
+ return replacement;
}
stringReplaceFirstRE(receiver, regexp, replacement, startIndex) {
@@ -136,38 +147,73 @@
/// Returns a string for a RegExp pattern that matches [string]. This is done by
/// escaping all RegExp metacharacters.
quoteStringForRegExp(string) {
- return JS('String', r'#.replace(/[[\]{}()*+?.\\^$|]/g, "\\$&")', string);
+ // We test and replace essentially the same RegExp because replacement when
+ // there are replacement patterns is slow enough to be worth avoiding.
+ if (JS('bool', r'/[[\]{}()*+?.\\^$|]/.test(#)', string)) {
+ return JS('String', r'#.replace(/[[\]{}()*+?.\\^$|]/g, "\\$&")', string);
+ }
+ return string;
}
stringReplaceAllUnchecked(receiver, pattern, replacement) {
checkString(replacement);
if (pattern is String) {
- if (pattern == "") {
- if (receiver == "") {
- return JS('String', '#', replacement); // help type inference.
- } else {
- StringBuffer result = new StringBuffer('');
- int length = receiver.length;
- result.write(replacement);
- for (int i = 0; i < length; i++) {
- result.write(receiver[i]);
- result.write(replacement);
- }
- return result.toString();
- }
- } else {
- var quoted = quoteStringForRegExp(pattern);
- var replacer = JS('', "new RegExp(#, 'g')", quoted);
- return stringReplaceJS(receiver, replacer, replacement);
- }
- } else if (pattern is JSSyntaxRegExp) {
+ return stringReplaceAllUncheckedString(receiver, pattern, replacement);
+ }
+
+ if (pattern is JSSyntaxRegExp) {
var re = regExpGetGlobalNative(pattern);
return stringReplaceJS(receiver, re, replacement);
- } else {
- checkNull(pattern);
- // TODO(floitsch): implement generic String.replace (with patterns).
- throw "String.replaceAll(Pattern) UNIMPLEMENTED";
}
+
+ checkNull(pattern);
+ // TODO(floitsch): implement generic String.replace (with patterns).
+ throw "String.replaceAll(Pattern) UNIMPLEMENTED";
+}
+
+/// Replaces all non-overlapping occurences of [pattern] in [receiver] with
+/// [replacement]. This should be replace with
+/// (String.prototype.replaceAll)[https://github.com/tc39/proposal-string-replace-all]
+/// when available.
+String stringReplaceAllUncheckedString(
+ String receiver, String pattern, String replacement) {
+ if (pattern == "") {
+ if (receiver == "") {
+ return JS('String', '#', replacement); // help type inference.
+ }
+ StringBuffer result = new StringBuffer('');
+ int length = receiver.length;
+ result.write(replacement);
+ for (int i = 0; i < length; i++) {
+ result.write(receiver[i]);
+ result.write(replacement);
+ }
+ return result.toString();
+ }
+
+ if (!const bool.fromEnvironment(
+ 'dart2js.testing.String.replaceAll.force.regexp')) {
+ // First check for no match.
+ int index = stringIndexOfStringUnchecked(receiver, pattern, 0);
+ if (index < 0) return receiver;
+
+ // The fastest approach in general is to replace with a global RegExp, but
+ // this requires the receiver string to be long enough to amortize the cost
+ // of creating the RegExp, and the replacement to have no '$' patterns,
+ // which tend to make `String.prototype.replace` much slower. In these
+ // cases, using split-join usually wins.
+ if (receiver.length < 500 ||
+ stringContainsStringUnchecked(replacement, r'$', 0)) {
+ return stringReplaceAllUsingSplitJoin(receiver, pattern, replacement);
+ }
+ }
+ var quoted = quoteStringForRegExp(pattern);
+ var replacer = JS('', "new RegExp(#, 'g')", quoted);
+ return stringReplaceJS(receiver, replacer, replacement);
+}
+
+String stringReplaceAllUsingSplitJoin(receiver, pattern, replacement) {
+ return JS('String', '#.split(#).join(#)', receiver, pattern, replacement);
}
String _matchString(Match match) => match[0];
diff --git a/sdk/lib/collection/collection.dart b/sdk/lib/collection/collection.dart
index 7c667ec..b050a48 100644
--- a/sdk/lib/collection/collection.dart
+++ b/sdk/lib/collection/collection.dart
@@ -2,15 +2,13 @@
// 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.
-/**
- * Classes and utilities that supplement the collection support in dart:core.
- *
- * To use this library in your code:
- *
- * import 'dart:collection';
- *
- * {@category Core}
- */
+/// Classes and utilities that supplement the collection support in dart:core.
+///
+/// To use this library in your code:
+///
+/// import 'dart:collection';
+///
+/// {@category Core}
library dart.collection;
import 'dart:_internal' hide Symbol;
diff --git a/sdk/lib/collection/collections.dart b/sdk/lib/collection/collections.dart
index d02257b..9b43996 100644
--- a/sdk/lib/collection/collections.dart
+++ b/sdk/lib/collection/collections.dart
@@ -4,24 +4,20 @@
part of dart.collection;
-/**
- * An unmodifiable [List] view of another List.
- *
- * The source of the elements may be a [List] or any [Iterable] with
- * efficient [Iterable.length] and [Iterable.elementAt].
- */
+/// An unmodifiable [List] view of another List.
+///
+/// The source of the elements may be a [List] or any [Iterable] with
+/// efficient [Iterable.length] and [Iterable.elementAt].
class UnmodifiableListView<E> extends UnmodifiableListBase<E> {
final Iterable<E> _source;
- /**
- * Creates an unmodifiable list backed by [source].
- *
- * The [source] of the elements may be a [List] or any [Iterable] with
- * efficient [Iterable.length] and [Iterable.elementAt].
- */
+ /// Creates an unmodifiable list backed by [source].
+ ///
+ /// The [source] of the elements may be a [List] or any [Iterable] with
+ /// efficient [Iterable.length] and [Iterable.elementAt].
UnmodifiableListView(Iterable<E> source) : _source = source;
- List<R> cast<R>() => new UnmodifiableListView(_source.cast<R>());
+ List<R> cast<R>() => UnmodifiableListView(_source.cast<R>());
int get length => _source.length;
E operator [](int index) => _source.elementAt(index);
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index 728ff9e6..525f43a 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -4,165 +4,152 @@
part of dart.collection;
-/** Default function for equality comparison in customized HashMaps */
+/// Default function for equality comparison in customized HashMaps
bool _defaultEquals(a, b) => a == b;
-/** Default function for hash-code computation in customized HashMaps */
+
+/// Default function for hash-code computation in customized HashMaps
int _defaultHashCode(a) => a.hashCode;
-/** Type of custom equality function */
-typedef bool _Equality<K>(K a, K b);
-/** Type of custom hash code function. */
-typedef int _Hasher<K>(K object);
+/// Type of custom equality function
+typedef _Equality<K> = bool Function(K a, K b);
-/**
- * A hash-table based implementation of [Map].
- *
- * The keys of a `HashMap` must have consistent [Object.==]
- * and [Object.hashCode] implementations. This means that the `==` operator
- * must define a stable equivalence relation on the keys (reflexive,
- * symmetric, transitive, and consistent over time), and that `hashCode`
- * must be the same for objects that are considered equal by `==`.
- *
- * The map allows `null` as a key.
- *
- * Iterating the map's keys, values or entries (through [forEach])
- * may happen in any order.
- * The iteration order only changes when the map is modified.
- * Values are iterated in the same order as their associated keys,
- * so iterating the [keys] and [values] in parallel
- * will give matching key and value pairs.
- */
+/// Type of custom hash code function.
+typedef _Hasher<K> = int Function(K object);
+
+/// A hash-table based implementation of [Map].
+///
+/// The keys of a `HashMap` must have consistent [Object.==]
+/// and [Object.hashCode] implementations. This means that the `==` operator
+/// must define a stable equivalence relation on the keys (reflexive,
+/// symmetric, transitive, and consistent over time), and that `hashCode`
+/// must be the same for objects that are considered equal by `==`.
+///
+/// The map allows `null` as a key.
+///
+/// Iterating the map's keys, values or entries (through [forEach])
+/// may happen in any order.
+/// The iteration order only changes when the map is modified.
+/// Values are iterated in the same order as their associated keys,
+/// so iterating the [keys] and [values] in parallel
+/// will give matching key and value pairs.
abstract class HashMap<K, V> implements Map<K, V> {
- /**
- * Creates an unordered hash-table based [Map].
- *
- * The created map is not ordered in any way. When iterating the keys or
- * values, the iteration order is unspecified except that it will stay the
- * same as long as the map isn't changed.
- *
- * If [equals] is provided, it is used to compare the keys in the table with
- * new keys. If [equals] is omitted, the key's own [Object.==] is used
- * instead.
- *
- * Similar, if [hashCode] is provided, it is used to produce a hash value
- * for keys in order to place them in the hash table. If it is omitted, the
- * key's own [Object.hashCode] is used.
- *
- * If using methods like [operator []], [remove] and [containsKey] together
- * with a custom equality and hashcode, an extra `isValidKey` function
- * can be supplied. This function is called before calling [equals] or
- * [hashCode] with an argument that may not be a [K] instance, and if the
- * call returns false, the key is assumed to not be in the set.
- * The [isValidKey] function defaults to just testing if the object is a
- * [K] instance.
- *
- * Example:
- *
- * new HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
- * hashCode: (int e) => e % 5)
- *
- * This example map does not need an `isValidKey` function to be passed.
- * The default function accepts only `int` values, which can safely be
- * passed to both the `equals` and `hashCode` functions.
- *
- * If neither `equals`, `hashCode`, nor `isValidKey` is provided,
- * the default `isValidKey` instead accepts all keys.
- * The default equality and hashcode operations are assumed to work on all
- * objects.
- *
- * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
- * and `isValidKey` is omitted, the resulting map is identity based,
- * and the `isValidKey` defaults to accepting all keys.
- * Such a map can be created directly using [HashMap.identity].
- *
- * The used `equals` and `hashCode` method should always be consistent,
- * so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
- * of an object, or what it compares equal to, should not change while the
- * object is a key in the map. If it does change, the result is unpredictable.
- *
- * If you supply one of [equals] and [hashCode],
- * you should generally also to supply the other.
- */
+ /// Creates an unordered hash-table based [Map].
+ ///
+ /// The created map is not ordered in any way. When iterating the keys or
+ /// values, the iteration order is unspecified except that it will stay the
+ /// same as long as the map isn't changed.
+ ///
+ /// If [equals] is provided, it is used to compare the keys in the table with
+ /// new keys. If [equals] is omitted, the key's own [Object.==] is used
+ /// instead.
+ ///
+ /// Similar, if [hashCode] is provided, it is used to produce a hash value
+ /// for keys in order to place them in the hash table. If it is omitted, the
+ /// key's own [Object.hashCode] is used.
+ ///
+ /// If using methods like [operator []], [remove] and [containsKey] together
+ /// with a custom equality and hashcode, an extra `isValidKey` function
+ /// can be supplied. This function is called before calling [equals] or
+ /// [hashCode] with an argument that may not be a [K] instance, and if the
+ /// call returns false, the key is assumed to not be in the set.
+ /// The [isValidKey] function defaults to just testing if the object is a
+ /// [K] instance.
+ ///
+ /// Example:
+ ///
+ /// new HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
+ /// hashCode: (int e) => e % 5)
+ ///
+ /// This example map does not need an `isValidKey` function to be passed.
+ /// The default function accepts only `int` values, which can safely be
+ /// passed to both the `equals` and `hashCode` functions.
+ ///
+ /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
+ /// the default `isValidKey` instead accepts all keys.
+ /// The default equality and hashcode operations are assumed to work on all
+ /// objects.
+ ///
+ /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
+ /// and `isValidKey` is omitted, the resulting map is identity based,
+ /// and the `isValidKey` defaults to accepting all keys.
+ /// Such a map can be created directly using [HashMap.identity].
+ ///
+ /// The used `equals` and `hashCode` method should always be consistent,
+ /// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
+ /// of an object, or what it compares equal to, should not change while the
+ /// object is a key in the map. If it does change, the result is
+ /// unpredictable.
+ ///
+ /// If you supply one of [equals] and [hashCode],
+ /// you should generally also to supply the other.
external factory HashMap(
{bool equals(K key1, K key2),
int hashCode(K key),
bool isValidKey(potentialKey)});
- /**
- * Creates an unordered identity-based map.
- *
- * Effectively a shorthand for:
- *
- * new HashMap<K, V>(equals: identical,
- * hashCode: identityHashCode)
- */
+ /// Creates an unordered identity-based map.
+ ///
+ /// Effectively a shorthand for:
+ ///
+ /// new HashMap<K, V>(equals: identical,
+ /// hashCode: identityHashCode)
external factory HashMap.identity();
- /**
- * Creates a [HashMap] that contains all key/value pairs of [other].
- *
- * The keys must all be instances of [K] and the values of [V].
- * The [other] map itself can have any type.
- */
+ /// Creates a [HashMap] that contains all key/value pairs of [other].
+ ///
+ /// The keys must all be instances of [K] and the values of [V].
+ /// The [other] map itself can have any type.
factory HashMap.from(Map other) {
- Map<K, V> result = new HashMap<K, V>();
+ Map<K, V> result = HashMap<K, V>();
other.forEach((k, v) {
result[k] = v;
});
return result;
}
- /**
- * Creates a [HashMap] that contains all key/value pairs of [other].
- */
- factory HashMap.of(Map<K, V> other) => new HashMap<K, V>()..addAll(other);
+ /// Creates a [HashMap] that contains all key/value pairs of [other].
+ factory HashMap.of(Map<K, V> other) => HashMap<K, V>()..addAll(other);
- /**
- * Creates a [HashMap] where the keys and values are computed from the
- * [iterable].
- *
- * For each element of the [iterable] this constructor computes a key/value
- * pair, by applying [key] and [value] respectively.
- *
- * The keys of the key/value pairs do not need to be unique. The last
- * occurrence of a key will simply overwrite any previous value.
- *
- * If no values are specified for [key] and [value] the default is the
- * identity function.
- */
+ /// Creates a [HashMap] where the keys and values are computed from the
+ /// [iterable].
+ ///
+ /// For each element of the [iterable] this constructor computes a key/value
+ /// pair, by applying [key] and [value] respectively.
+ ///
+ /// The keys of the key/value pairs do not need to be unique. The last
+ /// occurrence of a key will simply overwrite any previous value.
+ ///
+ /// If no values are specified for [key] and [value] the default is the
+ /// identity function.
factory HashMap.fromIterable(Iterable iterable,
{K key(element), V value(element)}) {
- Map<K, V> map = new HashMap<K, V>();
+ Map<K, V> map = HashMap<K, V>();
MapBase._fillMapWithMappedIterable(map, iterable, key, value);
return map;
}
- /**
- * Creates a [HashMap] associating the given [keys] to [values].
- *
- * This constructor iterates over [keys] and [values] and maps each element of
- * [keys] to the corresponding element of [values].
- *
- * If [keys] contains the same object multiple times, the last occurrence
- * overwrites the previous value.
- *
- * It is an error if the two [Iterable]s don't have the same length.
- */
+ /// Creates a [HashMap] associating the given [keys] to [values].
+ ///
+ /// This constructor iterates over [keys] and [values] and maps each element
+ /// of [keys] to the corresponding element of [values].
+ ///
+ /// If [keys] contains the same object multiple times, the last occurrence
+ /// overwrites the previous value.
+ ///
+ /// It is an error if the two [Iterable]s don't have the same length.
factory HashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
- Map<K, V> map = new HashMap<K, V>();
+ Map<K, V> map = HashMap<K, V>();
MapBase._fillMapWithIterables(map, keys, values);
return map;
}
- /**
- * Creates a [HashMap] containing the entries of [entries].
- *
- * Returns a new `HashMap<K, V>` where all entries of [entries]
- * have been added in iteration order.
- *
- * If multiple [entries] have the same key,
- * later occurrences overwrite the earlier ones.
- */
+ /// Creates a [HashMap] containing the entries of [entries].
+ ///
+ /// Returns a new `HashMap<K, V>` where all entries of [entries]
+ /// have been added in iteration order.
+ ///
+ /// If multiple [entries] have the same key,
+ /// later occurrences overwrite the earlier ones.
@Since("2.1")
factory HashMap.fromEntries(Iterable<MapEntry<K, V>> entries) =>
HashMap<K, V>()..addEntries(entries);
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index d93e550..3fd00fe 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -4,125 +4,112 @@
part of dart.collection;
-/**
- * An unordered hash-table based [Set] implementation.
- *
- * The elements of a `HashSet` must have consistent equality
- * and hashCode implementations. This means that the equals operation
- * must define a stable equivalence relation on the elements (reflexive,
- * symmetric, transitive, and consistent over time), and that the hashCode
- * must consistent with equality, so that the same for objects that are
- * considered equal.
- *
- * The set allows `null` as an element.
- *
- * Most simple operations on `HashSet` are done in (potentially amortized)
- * constant time: [add], [contains], [remove], and [length], provided the hash
- * codes of objects are well distributed.
- *
- * The iteration order of the set is not specified and depends on
- * the hashcodes of the provided elements. However, the order is stable:
- * multiple iterations over the same set produce the same order, as long as
- * the set is not modified.
- */
+/// An unordered hash-table based [Set] implementation.
+///
+/// The elements of a `HashSet` must have consistent equality
+/// and hashCode implementations. This means that the equals operation
+/// must define a stable equivalence relation on the elements (reflexive,
+/// symmetric, transitive, and consistent over time), and that the hashCode
+/// must consistent with equality, so that the same for objects that are
+/// considered equal.
+///
+/// The set allows `null` as an element.
+///
+/// Most simple operations on `HashSet` are done in (potentially amortized)
+/// constant time: [add], [contains], [remove], and [length], provided the hash
+/// codes of objects are well distributed.
+///
+/// The iteration order of the set is not specified and depends on
+/// the hashcodes of the provided elements. However, the order is stable:
+/// multiple iterations over the same set produce the same order, as long as
+/// the set is not modified.
abstract class HashSet<E> implements Set<E> {
- /**
- * Create a hash set using the provided [equals] as equality.
- *
- * The provided [equals] must define a stable equivalence relation, and
- * [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
- * methods won't work on all objects, but only on some instances of E, the
- * [isValidKey] predicate can be used to restrict the keys that the functions
- * are applied to.
- * Any key for which [isValidKey] returns false is automatically assumed
- * to not be in the set when asking `contains`.
- *
- * If [equals] or [hashCode] are omitted, the set uses
- * the elements' intrinsic [Object.==] and [Object.hashCode].
- *
- * If you supply one of [equals] and [hashCode],
- * you should generally also to supply the other.
- *
- * If the supplied `equals` or `hashCode` functions won't work on all [E]
- * objects, and the map will be used in a setting where a non-`E` object
- * is passed to, e.g., `contains`, then the [isValidKey] function should
- * also be supplied.
- *
- * If [isValidKey] is omitted, it defaults to testing if the object is an
- * [E] instance. That means that:
- *
- * new HashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
- * hashCode: (int e) => e % 5)
- *
- * does not need an `isValidKey` argument, because it defaults to only
- * accepting `int` values which are accepted by both `equals` and `hashCode`.
- *
- * If neither `equals`, `hashCode`, nor `isValidKey` is provided,
- * the default `isValidKey` instead accepts all values.
- * The default equality and hashcode operations are assumed to work on all
- * objects.
- *
- * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
- * and `isValidKey` is omitted, the resulting set is identity based,
- * and the `isValidKey` defaults to accepting all keys.
- * Such a map can be created directly using [HashSet.identity].
- */
+ /// Create a hash set using the provided [equals] as equality.
+ ///
+ /// The provided [equals] must define a stable equivalence relation, and
+ /// [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
+ /// methods won't work on all objects, but only on some instances of E, the
+ /// [isValidKey] predicate can be used to restrict the keys that the functions
+ /// are applied to.
+ /// Any key for which [isValidKey] returns false is automatically assumed
+ /// to not be in the set when asking `contains`.
+ ///
+ /// If [equals] or [hashCode] are omitted, the set uses
+ /// the elements' intrinsic [Object.==] and [Object.hashCode].
+ ///
+ /// If you supply one of [equals] and [hashCode],
+ /// you should generally also to supply the other.
+ ///
+ /// If the supplied `equals` or `hashCode` functions won't work on all [E]
+ /// objects, and the map will be used in a setting where a non-`E` object
+ /// is passed to, e.g., `contains`, then the [isValidKey] function should
+ /// also be supplied.
+ ///
+ /// If [isValidKey] is omitted, it defaults to testing if the object is an
+ /// [E] instance. That means that:
+ ///
+ /// new HashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
+ /// hashCode: (int e) => e % 5)
+ ///
+ /// does not need an `isValidKey` argument, because it defaults to only
+ /// accepting `int` values which are accepted by both `equals` and `hashCode`.
+ ///
+ /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
+ /// the default `isValidKey` instead accepts all values.
+ /// The default equality and hashcode operations are assumed to work on all
+ /// objects.
+ ///
+ /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
+ /// and `isValidKey` is omitted, the resulting set is identity based,
+ /// and the `isValidKey` defaults to accepting all keys.
+ /// Such a map can be created directly using [HashSet.identity].
external factory HashSet(
{bool equals(E e1, E e2),
int hashCode(E e),
bool isValidKey(potentialKey)});
- /**
- * Creates an unordered identity-based set.
- *
- * Effectively a shorthand for:
- *
- * new HashSet<E>(equals: identical,
- * hashCode: identityHashCode)
- */
+ /// Creates an unordered identity-based set.
+ ///
+ /// Effectively a shorthand for:
+ ///
+ /// new HashSet<E>(equals: identical,
+ /// hashCode: identityHashCode)
external factory HashSet.identity();
- /**
- * Create a hash set containing all [elements].
- *
- * Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
- * to the set. The elements are added in order. If [elements] contains
- * two entries that are equal, but not identical, then the first one is
- * the one in the resulting set.
- *
- * All the [elements] should be instances of [E].
- * The `elements` iterable itself may have any element type, so this
- * constructor can be used to down-cast a `Set`, for example as:
- * ```dart
- * Set<SuperType> superSet = ...;
- * Set<SubType> subSet =
- * new HashSet<SubType>.from(superSet.whereType<SubType>());
- * ```
- */
+ /// Create a hash set containing all [elements].
+ ///
+ /// Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
+ /// to the set. The elements are added in order. If [elements] contains
+ /// two entries that are equal, but not identical, then the first one is
+ /// the one in the resulting set.
+ ///
+ /// All the [elements] should be instances of [E].
+ /// The `elements` iterable itself may have any element type, so this
+ /// constructor can be used to down-cast a `Set`, for example as:
+ /// ```dart
+ /// Set<SuperType> superSet = ...;
+ /// Set<SubType> subSet =
+ /// new HashSet<SubType>.from(superSet.whereType<SubType>());
+ /// ```
factory HashSet.from(Iterable elements) {
- HashSet<E> result = new HashSet<E>();
+ HashSet<E> result = HashSet<E>();
for (final e in elements) {
result.add(e);
}
return result;
}
- /**
- * Create a hash set containing all [elements].
- *
- * Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
- * to the set. The elements are added in order. If [elements] contains
- * two entries that are equal, but not identical, then the first one is
- * the one in the resulting set.
- */
- factory HashSet.of(Iterable<E> elements) =>
- new HashSet<E>()..addAll(elements);
+ /// Create a hash set containing all [elements].
+ ///
+ /// Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
+ /// to the set. The elements are added in order. If [elements] contains
+ /// two entries that are equal, but not identical, then the first one is
+ /// the one in the resulting set.
+ factory HashSet.of(Iterable<E> elements) => HashSet<E>()..addAll(elements);
- /**
- * Provides an iterator that iterates over the elements of this set.
- *
- * The order of iteration is unspecified,
- * but consistent between changes to the set.
- */
+ /// Provides an iterator that iterates over the elements of this set.
+ ///
+ /// The order of iteration is unspecified,
+ /// but consistent between changes to the set.
Iterator<E> get iterator;
}
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index b7b5497..14e7226 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -4,11 +4,9 @@
part of dart.collection;
-/**
- * This [Iterable] mixin implements all [Iterable] members except `iterator`.
- *
- * All other methods are implemented in terms of `iterator`.
- */
+/// This [Iterable] mixin implements all [Iterable] members except `iterator`.
+///
+/// All other methods are implemented in terms of `iterator`.
abstract class IterableMixin<E> implements Iterable<E> {
// This class has methods copied verbatim into:
// - IterableBase
@@ -16,23 +14,23 @@
// If changing a method here, also change the other copies.
Iterable<R> cast<R>() => Iterable.castFrom<E, R>(this);
- Iterable<T> map<T>(T f(E element)) => new MappedIterable<E, T>(this, f);
+ Iterable<T> map<T>(T f(E element)) => MappedIterable<E, T>(this, f);
- Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
+ Iterable<E> where(bool f(E element)) => WhereIterable<E>(this, f);
- Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+ Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
Iterable<T> expand<T>(Iterable<T> f(E element)) =>
- new ExpandIterable<E, T>(this, f);
+ ExpandIterable<E, T>(this, f);
Iterable<E> followedBy(Iterable<E> other) {
// Type workaround because IterableMixin<E> doesn't promote
// to EfficientLengthIterable<E>.
Iterable<E> self = this;
if (self is EfficientLengthIterable<E>) {
- return new FollowedByIterable<E>.firstEfficient(self, other);
+ return FollowedByIterable<E>.firstEfficient(self, other);
}
- return new FollowedByIterable<E>(this, other);
+ return FollowedByIterable<E>(this, other);
}
bool contains(Object element) {
@@ -74,7 +72,7 @@
String join([String separator = ""]) {
Iterator<E> iterator = this.iterator;
if (!iterator.moveNext()) return "";
- StringBuffer buffer = new StringBuffer();
+ StringBuffer buffer = StringBuffer();
if (separator == null || separator == "") {
do {
buffer.write("${iterator.current}");
@@ -96,10 +94,10 @@
return false;
}
- List<E> toList({bool growable: true}) =>
- new List<E>.from(this, growable: growable);
+ List<E> toList({bool growable = true}) =>
+ List<E>.from(this, growable: growable);
- Set<E> toSet() => new Set<E>.from(this);
+ Set<E> toSet() => Set<E>.from(this);
int get length {
assert(this is! EfficientLengthIterable);
@@ -116,19 +114,19 @@
bool get isNotEmpty => !isEmpty;
Iterable<E> take(int count) {
- return new TakeIterable<E>(this, count);
+ return TakeIterable<E>(this, count);
}
Iterable<E> takeWhile(bool test(E value)) {
- return new TakeWhileIterable<E>(this, test);
+ return TakeWhileIterable<E>(this, test);
}
Iterable<E> skip(int count) {
- return new SkipIterable<E>(this, count);
+ return SkipIterable<E>(this, count);
}
Iterable<E> skipWhile(bool test(E value)) {
- return new SkipWhileIterable<E>(this, test);
+ return SkipWhileIterable<E>(this, test);
}
E get first {
@@ -206,29 +204,25 @@
if (index == elementIndex) return element;
elementIndex++;
}
- throw new RangeError.index(index, this, "index", null, elementIndex);
+ throw RangeError.index(index, this, "index", null, elementIndex);
}
String toString() => IterableBase.iterableToShortString(this, '(', ')');
}
-/**
- * Base class for implementing [Iterable].
- *
- * This class implements all methods of [Iterable], except [Iterable.iterator],
- * in terms of `iterator`.
- */
+/// Base class for implementing [Iterable].
+///
+/// This class implements all methods of [Iterable], except [Iterable.iterator],
+/// in terms of `iterator`.
abstract class IterableBase<E> extends Iterable<E> {
const IterableBase();
- /**
- * Convert an `Iterable` to a string like [IterableBase.toString].
- *
- * Allows using other delimiters than '(' and ')'.
- *
- * Handles circular references where converting one of the elements
- * to a string ends up converting [iterable] to a string again.
- */
+ /// Convert an `Iterable` to a string like [IterableBase.toString].
+ ///
+ /// Allows using other delimiters than '(' and ')'.
+ ///
+ /// Handles circular references where converting one of the elements
+ /// to a string ends up converting [iterable] to a string again.
static String iterableToShortString(Iterable iterable,
[String leftDelimiter = '(', String rightDelimiter = ')']) {
if (_isToStringVisiting(iterable)) {
@@ -246,30 +240,28 @@
assert(identical(_toStringVisiting.last, iterable));
_toStringVisiting.removeLast();
}
- return (new StringBuffer(leftDelimiter)
+ return (StringBuffer(leftDelimiter)
..writeAll(parts, ", ")
..write(rightDelimiter))
.toString();
}
- /**
- * Converts an `Iterable` to a string.
- *
- * Converts each elements to a string, and separates the results by ", ".
- * Then wraps the result in [leftDelimiter] and [rightDelimiter].
- *
- * Unlike [iterableToShortString], this conversion doesn't omit any
- * elements or puts any limit on the size of the result.
- *
- * Handles circular references where converting one of the elements
- * to a string ends up converting [iterable] to a string again.
- */
+ /// Converts an `Iterable` to a string.
+ ///
+ /// Converts each elements to a string, and separates the results by ", ".
+ /// Then wraps the result in [leftDelimiter] and [rightDelimiter].
+ ///
+ /// Unlike [iterableToShortString], this conversion doesn't omit any
+ /// elements or puts any limit on the size of the result.
+ ///
+ /// Handles circular references where converting one of the elements
+ /// to a string ends up converting [iterable] to a string again.
static String iterableToFullString(Iterable iterable,
[String leftDelimiter = '(', String rightDelimiter = ')']) {
if (_isToStringVisiting(iterable)) {
return "$leftDelimiter...$rightDelimiter";
}
- StringBuffer buffer = new StringBuffer(leftDelimiter);
+ StringBuffer buffer = StringBuffer(leftDelimiter);
_toStringVisiting.add(iterable);
try {
buffer.writeAll(iterable, ", ");
@@ -282,10 +274,10 @@
}
}
-/** A collection used to identify cyclic lists during toString() calls. */
+/// A collection used to identify cyclic lists during toString() calls.
final List _toStringVisiting = [];
-/** Check if we are currently visiting `o` in a toString call. */
+/// Check if we are currently visiting `o` in a toString call.
bool _isToStringVisiting(Object o) {
for (int i = 0; i < _toStringVisiting.length; i++) {
if (identical(o, _toStringVisiting[i])) return true;
@@ -293,9 +285,7 @@
return false;
}
-/**
- * Convert elements of [iterable] to strings and store them in [parts].
- */
+/// Convert elements of [iterable] to strings and store them in [parts].
void _iterablePartsToStrings(Iterable iterable, List<String> parts) {
/*
* This is the complicated part of [iterableToShortString].
diff --git a/sdk/lib/collection/iterator.dart b/sdk/lib/collection/iterator.dart
index f870711..671f0ee 100644
--- a/sdk/lib/collection/iterator.dart
+++ b/sdk/lib/collection/iterator.dart
@@ -4,12 +4,10 @@
part of dart.collection;
-/**
- * The [HasNextIterator] class wraps an [Iterator] and provides methods to
- * iterate over an object using `hasNext` and `next`.
- *
- * An [HasNextIterator] does not implement the [Iterator] interface.
- */
+/// The [HasNextIterator] class wraps an [Iterator] and provides methods to
+/// iterate over an object using `hasNext` and `next`.
+///
+/// An [HasNextIterator] does not implement the [Iterator] interface.
class HasNextIterator<E> {
static const int _HAS_NEXT_AND_NEXT_IN_CURRENT = 0;
static const int _NO_NEXT = 1;
@@ -28,7 +26,7 @@
E next() {
// Call to hasNext is necessary to make sure we are positioned at the first
// element when we start iterating.
- if (!hasNext) throw new StateError("No more elements");
+ if (!hasNext) throw StateError("No more elements");
assert(_state == _HAS_NEXT_AND_NEXT_IN_CURRENT);
E result = _iterator.current;
_move();
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index 91f95ad..e3a650d 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.dart
@@ -4,153 +4,137 @@
part of dart.collection;
-/**
- * A hash-table based implementation of [Map].
- *
- * The insertion order of keys is remembered,
- * and keys are iterated in the order they were inserted into the map.
- * Values are iterated in their corresponding key's order.
- * Changing a key's value, when the key is already in the map,
- * does not change the iteration order,
- * but removing the key and adding it again
- * will make it be last in the iteration order.
- *
- * The keys of a `LinkedHashMap` must have consistent [Object.==]
- * and [Object.hashCode] implementations. This means that the `==` operator
- * must define a stable equivalence relation on the keys (reflexive,
- * symmetric, transitive, and consistent over time), and that `hashCode`
- * must be the same for objects that are considered equal by `==`.
- *
- * The map allows `null` as a key.
- */
+/// A hash-table based implementation of [Map].
+///
+/// The insertion order of keys is remembered,
+/// and keys are iterated in the order they were inserted into the map.
+/// Values are iterated in their corresponding key's order.
+/// Changing a key's value, when the key is already in the map,
+/// does not change the iteration order,
+/// but removing the key and adding it again
+/// will make it be last in the iteration order.
+///
+/// The keys of a `LinkedHashMap` must have consistent [Object.==]
+/// and [Object.hashCode] implementations. This means that the `==` operator
+/// must define a stable equivalence relation on the keys (reflexive,
+/// symmetric, transitive, and consistent over time), and that `hashCode`
+/// must be the same for objects that are considered equal by `==`.
+///
+/// The map allows `null` as a key.
abstract class LinkedHashMap<K, V> implements Map<K, V> {
- /**
- * Creates an insertion-ordered hash-table based [Map].
- *
- * If [equals] is provided, it is used to compare the keys in the table with
- * new keys. If [equals] is omitted, the key's own [Object.==] is used
- * instead.
- *
- * Similar, if [hashCode] is provided, it is used to produce a hash value
- * for keys in order to place them in the hash table. If it is omitted, the
- * key's own [Object.hashCode] is used.
- *
- * If using methods like [operator []], [remove] and [containsKey] together
- * with a custom equality and hashcode, an extra `isValidKey` function
- * can be supplied. This function is called before calling [equals] or
- * [hashCode] with an argument that may not be a [K] instance, and if the
- * call returns false, the key is assumed to not be in the set.
- * The [isValidKey] function defaults to just testing if the object is a
- * [K] instance.
- *
- * Example:
- *
- * new LinkedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
- * hashCode: (int e) => e % 5)
- *
- * This example map does not need an `isValidKey` function to be passed.
- * The default function accepts only `int` values, which can safely be
- * passed to both the `equals` and `hashCode` functions.
- *
- * If neither `equals`, `hashCode`, nor `isValidKey` is provided,
- * the default `isValidKey` instead accepts all keys.
- * The default equality and hashcode operations are assumed to work on all
- * objects.
- *
- * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
- * and `isValidKey` is omitted, the resulting map is identity based,
- * and the `isValidKey` defaults to accepting all keys.
- * Such a map can be created directly using [LinkedHashMap.identity].
- *
- * The used `equals` and `hashCode` method should always be consistent,
- * so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
- * of an object, or what it compares equal to, should not change while the
- * object is in the table. If it does change, the result is unpredictable.
- *
- * If you supply one of [equals] and [hashCode],
- * you should generally also to supply the other.
- */
+ /// Creates an insertion-ordered hash-table based [Map].
+ ///
+ /// If [equals] is provided, it is used to compare the keys in the table with
+ /// new keys. If [equals] is omitted, the key's own [Object.==] is used
+ /// instead.
+ ///
+ /// Similar, if [hashCode] is provided, it is used to produce a hash value
+ /// for keys in order to place them in the hash table. If it is omitted, the
+ /// key's own [Object.hashCode] is used.
+ ///
+ /// If using methods like [operator []], [remove] and [containsKey] together
+ /// with a custom equality and hashcode, an extra `isValidKey` function
+ /// can be supplied. This function is called before calling [equals] or
+ /// [hashCode] with an argument that may not be a [K] instance, and if the
+ /// call returns false, the key is assumed to not be in the set.
+ /// The [isValidKey] function defaults to just testing if the object is a
+ /// [K] instance.
+ ///
+ /// Example:
+ ///
+ /// new LinkedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
+ /// hashCode: (int e) => e % 5)
+ ///
+ /// This example map does not need an `isValidKey` function to be passed.
+ /// The default function accepts only `int` values, which can safely be
+ /// passed to both the `equals` and `hashCode` functions.
+ ///
+ /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
+ /// the default `isValidKey` instead accepts all keys.
+ /// The default equality and hashcode operations are assumed to work on all
+ /// objects.
+ ///
+ /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
+ /// and `isValidKey` is omitted, the resulting map is identity based,
+ /// and the `isValidKey` defaults to accepting all keys.
+ /// Such a map can be created directly using [LinkedHashMap.identity].
+ ///
+ /// The used `equals` and `hashCode` method should always be consistent,
+ /// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
+ /// of an object, or what it compares equal to, should not change while the
+ /// object is in the table. If it does change, the result is unpredictable.
+ ///
+ /// If you supply one of [equals] and [hashCode],
+ /// you should generally also to supply the other.
external factory LinkedHashMap(
{bool equals(K key1, K key2),
int hashCode(K key),
bool isValidKey(potentialKey)});
- /**
- * Creates an insertion-ordered identity-based map.
- *
- * Effectively a shorthand for:
- *
- * new LinkedHashMap<K, V>(equals: identical,
- * hashCode: identityHashCode)
- */
+ /// Creates an insertion-ordered identity-based map.
+ ///
+ /// Effectively a shorthand for:
+ ///
+ /// new LinkedHashMap<K, V>(equals: identical,
+ /// hashCode: identityHashCode)
external factory LinkedHashMap.identity();
- /**
- * Creates a [LinkedHashMap] that contains all key value pairs of [other].
- *
- * The keys must all be instances of [K] and the values to [V].
- * The [other] map itself can have any type.
- */
+ /// Creates a [LinkedHashMap] that contains all key value pairs of [other].
+ ///
+ /// The keys must all be instances of [K] and the values to [V].
+ /// The [other] map itself can have any type.
factory LinkedHashMap.from(Map other) {
- LinkedHashMap<K, V> result = new LinkedHashMap<K, V>();
+ LinkedHashMap<K, V> result = LinkedHashMap<K, V>();
other.forEach((k, v) {
result[k] = v;
});
return result;
}
- /**
- * Creates a [LinkedHashMap] that contains all key value pairs of [other].
- */
+ /// Creates a [LinkedHashMap] that contains all key value pairs of [other].
factory LinkedHashMap.of(Map<K, V> other) =>
- new LinkedHashMap<K, V>()..addAll(other);
+ LinkedHashMap<K, V>()..addAll(other);
- /**
- * Creates a [LinkedHashMap] where the keys and values are computed from the
- * [iterable].
- *
- * For each element of the [iterable] this constructor computes a key/value
- * pair, by applying [key] and [value] respectively.
- *
- * The keys of the key/value pairs do not need to be unique. The last
- * occurrence of a key will simply overwrite any previous value.
- *
- * If no values are specified for [key] and [value] the default is the
- * identity function.
- */
+ /// Creates a [LinkedHashMap] where the keys and values are computed from the
+ /// [iterable].
+ ///
+ /// For each element of the [iterable] this constructor computes a key/value
+ /// pair, by applying [key] and [value] respectively.
+ ///
+ /// The keys of the key/value pairs do not need to be unique. The last
+ /// occurrence of a key will simply overwrite any previous value.
+ ///
+ /// If no values are specified for [key] and [value] the default is the
+ /// identity function.
factory LinkedHashMap.fromIterable(Iterable iterable,
{K key(element), V value(element)}) {
- LinkedHashMap<K, V> map = new LinkedHashMap<K, V>();
+ LinkedHashMap<K, V> map = LinkedHashMap<K, V>();
MapBase._fillMapWithMappedIterable(map, iterable, key, value);
return map;
}
- /**
- * Creates a [LinkedHashMap] associating the given [keys] to [values].
- *
- * This constructor iterates over [keys] and [values] and maps each element of
- * [keys] to the corresponding element of [values].
- *
- * If [keys] contains the same object multiple times, the last occurrence
- * overwrites the previous value.
- *
- * It is an error if the two [Iterable]s don't have the same length.
- */
+ /// Creates a [LinkedHashMap] associating the given [keys] to [values].
+ ///
+ /// This constructor iterates over [keys] and [values] and maps each element of
+ /// [keys] to the corresponding element of [values].
+ ///
+ /// If [keys] contains the same object multiple times, the last occurrence
+ /// overwrites the previous value.
+ ///
+ /// It is an error if the two [Iterable]s don't have the same length.
factory LinkedHashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
- LinkedHashMap<K, V> map = new LinkedHashMap<K, V>();
+ LinkedHashMap<K, V> map = LinkedHashMap<K, V>();
MapBase._fillMapWithIterables(map, keys, values);
return map;
}
- /**
- * Creates a [LinkedHashMap] containing the entries of [entries].
- *
- * Returns a new `LinkedHashMap<K, V>` where all entries of [entries]
- * have been added in iteration order.
- *
- * If multiple [entries] have the same key,
- * later occurrences overwrite the earlier ones.
- */
+ /// Creates a [LinkedHashMap] containing the entries of [entries].
+ ///
+ /// Returns a new `LinkedHashMap<K, V>` where all entries of [entries]
+ /// have been added in iteration order.
+ ///
+ /// If multiple [entries] have the same key,
+ /// later occurrences overwrite the earlier ones.
@Since("2.1")
factory LinkedHashMap.fromEntries(Iterable<MapEntry<K, V>> entries) =>
<K, V>{}..addEntries(entries);
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index 2fff2ec..a058b5e 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -4,131 +4,117 @@
part of dart.collection;
-/**
- * A [LinkedHashSet] is a hash-table based [Set] implementation.
- *
- * The `LinkedHashSet` also keep track of the order that elements were inserted
- * in, and iteration happens in first-to-last insertion order.
- *
- * The elements of a `LinkedHashSet` must have consistent [Object.==]
- * and [Object.hashCode] implementations. This means that the `==` operator
- * must define a stable equivalence relation on the elements (reflexive,
- * symmetric, transitive, and consistent over time), and that `hashCode`
- * must be the same for objects that are considered equal by `==`.
- *
- * The set allows `null` as an element.
- *
- * Iteration of elements is done in element insertion order.
- * An element that was added after another will occur later in the iteration.
- * Adding an element that is already in the set
- * does not change its position in the iteration order,
- * but removing an element and adding it again,
- * will make it the last element of an iteration.
- *
- * Most simple operations on `HashSet` are done in (potentially amortized)
- * constant time: [add], [contains], [remove], and [length], provided the hash
- * codes of objects are well distributed..
- */
+/// A [LinkedHashSet] is a hash-table based [Set] implementation.
+///
+/// The `LinkedHashSet` also keep track of the order that elements were inserted
+/// in, and iteration happens in first-to-last insertion order.
+///
+/// The elements of a `LinkedHashSet` must have consistent [Object.==]
+/// and [Object.hashCode] implementations. This means that the `==` operator
+/// must define a stable equivalence relation on the elements (reflexive,
+/// symmetric, transitive, and consistent over time), and that `hashCode`
+/// must be the same for objects that are considered equal by `==`.
+///
+/// The set allows `null` as an element.
+///
+/// Iteration of elements is done in element insertion order.
+/// An element that was added after another will occur later in the iteration.
+/// Adding an element that is already in the set
+/// does not change its position in the iteration order,
+/// but removing an element and adding it again,
+/// will make it the last element of an iteration.
+///
+/// Most simple operations on `HashSet` are done in (potentially amortized)
+/// constant time: [add], [contains], [remove], and [length], provided the hash
+/// codes of objects are well distributed..
abstract class LinkedHashSet<E> implements Set<E> {
- /**
- * Create an insertion-ordered hash set using the provided
- * [equals] and [hashCode].
- *
- * The provided [equals] must define a stable equivalence relation, and
- * [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
- * methods won't work on all objects, but only on some instances of E, the
- * [isValidKey] predicate can be used to restrict the keys that the functions
- * are applied to.
- * Any key for which [isValidKey] returns false is automatically assumed
- * to not be in the set when asking `contains`.
- *
- * If [equals] or [hashCode] are omitted, the set uses
- * the elements' intrinsic [Object.==] and [Object.hashCode],
- * and [isValidKey] is ignored since these operations are assumed
- * to work on all objects.
- *
- * If you supply one of [equals] and [hashCode],
- * you should generally also to supply the other.
- *
- * If the supplied `equals` or `hashCode` functions won't work on all [E]
- * objects, and the map will be used in a setting where a non-`E` object
- * is passed to, e.g., `contains`, then the [isValidKey] function should
- * also be supplied.
- *
- * If [isValidKey] is omitted, it defaults to testing if the object is an
- * [E] instance. That means that:
- *
- * new LinkedHashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
- * hashCode: (int e) => e % 5)
- *
- * does not need an `isValidKey` argument, because it defaults to only
- * accepting `int` values which are accepted by both `equals` and `hashCode`.
- *
- * If neither `equals`, `hashCode`, nor `isValidKey` is provided,
- * the default `isValidKey` instead accepts all values.
- * The default equality and hashcode operations are assumed to work on all
- * objects.
- *
- * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
- * and `isValidKey` is omitted, the resulting set is identity based,
- * and the `isValidKey` defaults to accepting all keys.
- * Such a map can be created directly using [LinkedHashSet.identity].
- */
+ /// Create an insertion-ordered hash set using the provided
+ /// [equals] and [hashCode].
+ ///
+ /// The provided [equals] must define a stable equivalence relation, and
+ /// [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
+ /// methods won't work on all objects, but only on some instances of E, the
+ /// [isValidKey] predicate can be used to restrict the keys that the functions
+ /// are applied to.
+ /// Any key for which [isValidKey] returns false is automatically assumed
+ /// to not be in the set when asking `contains`.
+ ///
+ /// If [equals] or [hashCode] are omitted, the set uses
+ /// the elements' intrinsic [Object.==] and [Object.hashCode],
+ /// and [isValidKey] is ignored since these operations are assumed
+ /// to work on all objects.
+ ///
+ /// If you supply one of [equals] and [hashCode],
+ /// you should generally also to supply the other.
+ ///
+ /// If the supplied `equals` or `hashCode` functions won't work on all [E]
+ /// objects, and the map will be used in a setting where a non-`E` object
+ /// is passed to, e.g., `contains`, then the [isValidKey] function should
+ /// also be supplied.
+ ///
+ /// If [isValidKey] is omitted, it defaults to testing if the object is an
+ /// [E] instance. That means that:
+ ///
+ /// new LinkedHashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
+ /// hashCode: (int e) => e % 5)
+ ///
+ /// does not need an `isValidKey` argument, because it defaults to only
+ /// accepting `int` values which are accepted by both `equals` and `hashCode`.
+ ///
+ /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
+ /// the default `isValidKey` instead accepts all values.
+ /// The default equality and hashcode operations are assumed to work on all
+ /// objects.
+ ///
+ /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
+ /// and `isValidKey` is omitted, the resulting set is identity based,
+ /// and the `isValidKey` defaults to accepting all keys.
+ /// Such a map can be created directly using [LinkedHashSet.identity].
external factory LinkedHashSet(
{bool equals(E e1, E e2),
int hashCode(E e),
bool isValidKey(potentialKey)});
- /**
- * Creates an insertion-ordered identity-based set.
- *
- * Effectively a shorthand for:
- *
- * new LinkedHashSet<E>(equals: identical,
- * hashCode: identityHashCode)
- */
+ /// Creates an insertion-ordered identity-based set.
+ ///
+ /// Effectively a shorthand for:
+ ///
+ /// new LinkedHashSet<E>(equals: identical,
+ /// hashCode: identityHashCode)
external factory LinkedHashSet.identity();
- /**
- * Create a linked hash set containing all [elements].
- *
- * Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
- * element of `elements` to this set in the order they are iterated.
- *
- * All the [elements] should be instances of [E].
- * The `elements` iterable itself may have any element type,
- * so this constructor can be used to down-cast a `Set`, for example as:
- *
- * Set<SuperType> superSet = ...;
- * Iterable<SuperType> tmp = superSet.where((e) => e is SubType);
- * Set<SubType> subSet = new LinkedHashSet<SubType>.from(tmp);
- */
+ /// Create a linked hash set containing all [elements].
+ ///
+ /// Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
+ /// element of `elements` to this set in the order they are iterated.
+ ///
+ /// All the [elements] should be instances of [E].
+ /// The `elements` iterable itself may have any element type,
+ /// so this constructor can be used to down-cast a `Set`, for example as:
+ ///
+ /// Set<SuperType> superSet = ...;
+ /// Iterable<SuperType> tmp = superSet.where((e) => e is SubType);
+ /// Set<SubType> subSet = new LinkedHashSet<SubType>.from(tmp);
factory LinkedHashSet.from(Iterable elements) {
- LinkedHashSet<E> result = new LinkedHashSet<E>();
+ LinkedHashSet<E> result = LinkedHashSet<E>();
for (final element in elements) {
result.add(element);
}
return result;
}
- /**
- * Create a linked hash set from [elements].
- *
- * Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
- * element of `elements` to this set in the order they are iterated.
- */
+ /// Create a linked hash set from [elements].
+ ///
+ /// Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
+ /// element of `elements` to this set in the order they are iterated.
factory LinkedHashSet.of(Iterable<E> elements) =>
- new LinkedHashSet<E>()..addAll(elements);
+ LinkedHashSet<E>()..addAll(elements);
- /**
- * Executes a function on each element of the set.
- *
- * The elements are iterated in insertion order.
- */
+ /// Executes a function on each element of the set.
+ ///
+ /// The elements are iterated in insertion order.
void forEach(void action(E element));
- /**
- * Provides an iterator that iterates over the elements in insertion order.
- */
+ /// Provides an iterator that iterates over the elements in insertion order.
Iterator<E> get iterator;
}
diff --git a/sdk/lib/collection/linked_list.dart b/sdk/lib/collection/linked_list.dart
index 4ba329c..91461cb 100644
--- a/sdk/lib/collection/linked_list.dart
+++ b/sdk/lib/collection/linked_list.dart
@@ -4,82 +4,68 @@
part of dart.collection;
-/**
- * A specialized double-linked list of elements that extends [LinkedListEntry].
- *
- * This is not a generic data structure. It only accepts elements that extend
- * the [LinkedListEntry] class. See the [Queue] implementations for
- * generic collections that allow constant time adding and removing at the ends.
- *
- * This is not a [List] implementation. Despite its name, this class does not
- * implement the [List] interface. It does not allow constant time lookup by
- * index.
- *
- * Because the elements themselves contain the links of this linked list,
- * each element can be in only one list at a time. To add an element to another
- * list, it must first be removed from its current list (if any).
- *
- * In return, each element knows its own place in the linked list, as well as
- * which list it is in. This allows constant time [LinkedListEntry.insertAfter],
- * [LinkedListEntry.insertBefore] and [LinkedListEntry.unlink] operations
- * when all you have is the element.
- *
- * A `LinkedList` also allows constant time adding and removing at either end,
- * and a constant time length getter.
- */
+/// A specialized double-linked list of elements that extends [LinkedListEntry].
+///
+/// This is not a generic data structure. It only accepts elements that extend
+/// the [LinkedListEntry] class. See the [Queue] implementations for generic
+/// collections that allow constant time adding and removing at the ends.
+///
+/// This is not a [List] implementation. Despite its name, this class does not
+/// implement the [List] interface. It does not allow constant time lookup by
+/// index.
+///
+/// Because the elements themselves contain the links of this linked list,
+/// each element can be in only one list at a time. To add an element to another
+/// list, it must first be removed from its current list (if any).
+///
+/// In return, each element knows its own place in the linked list, as well as
+/// which list it is in. This allows constant time
+/// [LinkedListEntry.insertAfter], [LinkedListEntry.insertBefore] and
+/// [LinkedListEntry.unlink] operations when all you have is the element.
+///
+/// A `LinkedList` also allows constant time adding and removing at either end,
+/// and a constant time length getter.
class LinkedList<E extends LinkedListEntry<E>> extends Iterable<E> {
int _modificationCount = 0;
int _length = 0;
E _first;
- /**
- * Construct a new empty linked list.
- */
+ /// Construct a new empty linked list.
LinkedList();
- /**
- * Add [entry] to the beginning of the linked list.
- */
+ /// Add [entry] to the beginning of the linked list.
void addFirst(E entry) {
_insertBefore(_first, entry, updateFirst: true);
_first = entry;
}
- /**
- * Add [entry] to the end of the linked list.
- */
+ /// Add [entry] to the end of the linked list.
void add(E entry) {
_insertBefore(_first, entry, updateFirst: false);
}
- /**
- * Add [entries] to the end of the linked list.
- */
+ /// Add [entries] to the end of the linked list.
void addAll(Iterable<E> entries) {
entries.forEach(add);
}
- /**
- * Remove [entry] from the linked list.
- *
- * Returns false and does nothing if [entry] is not in this linked list.
- *
- * This is equivalent to calling `entry.unlink()` if the entry is in this
- * list.
- */
+ /// Remove [entry] from the linked list.
+ ///
+ /// Returns false and does nothing if [entry] is not in this linked list.
+ ///
+ /// This is equivalent to calling `entry.unlink()` if the entry is in this
+ /// list.
bool remove(E entry) {
if (entry._list != this) return false;
_unlink(entry); // Unlink will decrement length.
return true;
}
- Iterator<E> get iterator => new _LinkedListIterator<E>(this);
+ Iterator<E> get iterator => _LinkedListIterator<E>(this);
int get length => _length;
- /**
- * Remove all elements from this linked list.
- */
+ /// Remove all elements from this linked list.
void clear() {
_modificationCount++;
if (isEmpty) return;
@@ -97,33 +83,31 @@
E get first {
if (isEmpty) {
- throw new StateError('No such element');
+ throw StateError('No such element');
}
return _first;
}
E get last {
if (isEmpty) {
- throw new StateError('No such element');
+ throw StateError('No such element');
}
return _first._previous;
}
E get single {
if (isEmpty) {
- throw new StateError('No such element');
+ throw StateError('No such element');
}
if (_length > 1) {
- throw new StateError('Too many elements');
+ throw StateError('Too many elements');
}
return _first;
}
- /**
- * Call [action] with each entry in this linked list.
- *
- * It's an error if [action] modify the linked list.
- */
+ /// Call [action] with each entry in this linked list.
+ ///
+ /// It's an error if [action] modify the linked list.
void forEach(void action(E entry)) {
int modificationCount = _modificationCount;
if (isEmpty) return;
@@ -132,7 +116,7 @@
do {
action(current);
if (modificationCount != _modificationCount) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
current = current._next;
} while (!identical(current, _first));
@@ -146,7 +130,7 @@
/// updates the [_first] field to point to the [newEntry] as first entry.
void _insertBefore(E entry, E newEntry, {bool updateFirst}) {
if (newEntry.list != null) {
- throw new StateError('LinkedListEntry is already in a LinkedList');
+ throw StateError('LinkedListEntry is already in a LinkedList');
}
_modificationCount++;
@@ -201,7 +185,7 @@
bool moveNext() {
if (_modificationCount != _list._modificationCount) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
if (_list.isEmpty || (_visitedFirst && identical(_next, _list.first))) {
_current = null;
@@ -214,79 +198,65 @@
}
}
-/**
- * An object that can be an element in a [LinkedList].
- *
- * All elements of a `LinkedList` must extend this class.
- * The class provides the internal links that link elements together
- * in the `LinkedList`, and a reference to the linked list itself
- * that an element is currently part of.
- *
- * An entry can be in at most one linked list at a time.
- * While an entry is in a linked list, the [list] property points to that
- * linked list, and otherwise the `list` property is `null`.
- *
- * When created, an entry is not in any linked list.
- */
+/// An object that can be an element in a [LinkedList].
+///
+/// All elements of a `LinkedList` must extend this class.
+/// The class provides the internal links that link elements together
+/// in the `LinkedList`, and a reference to the linked list itself
+/// that an element is currently part of.
+///
+/// An entry can be in at most one linked list at a time.
+/// While an entry is in a linked list, the [list] property points to that
+/// linked list, and otherwise the `list` property is `null`.
+///
+/// When created, an entry is not in any linked list.
abstract class LinkedListEntry<E extends LinkedListEntry<E>> {
LinkedList<E> _list;
E _next;
E _previous;
- /**
- * Get the linked list containing this element.
- *
- * Returns `null` if this entry is not currently in any list.
- */
+ /// Get the linked list containing this element.
+ ///
+ /// Returns `null` if this entry is not currently in any list.
LinkedList<E> get list => _list;
- /**
- * Unlink the element from its linked list.
- *
- * The entry must currently be in a linked list when this method is called.
- */
+ /// Unlink the element from its linked list.
+ ///
+ /// The entry must currently be in a linked list when this method is called.
void unlink() {
_list._unlink(this);
}
- /**
- * Return the successor of this element in its linked list.
- *
- * Returns `null` if there is no successor in the linked list, or if this
- * entry is not currently in any list.
- */
+ /// Return the successor of this element in its linked list.
+ ///
+ /// Returns `null` if there is no successor in the linked list, or if this
+ /// entry is not currently in any list.
E get next {
if (_list == null || identical(_list.first, _next)) return null;
return _next;
}
- /**
- * Return the predecessor of this element in its linked list.
- *
- * Returns `null` if there is no predecessor in the linked list, or if this
- * entry is not currently in any list.
- */
+ /// Return the predecessor of this element in its linked list.
+ ///
+ /// Returns `null` if there is no predecessor in the linked list, or if this
+ /// entry is not currently in any list.
E get previous {
if (_list == null || identical(this, _list.first)) return null;
return _previous;
}
- /**
- * Insert an element after this element in this element's linked list.
- *
- * This entry must be in a linked list when this method is called.
- * The [entry] must not be in a linked list.
- */
+ /// Insert an element after this element in this element's linked list.
+ ///
+ /// This entry must be in a linked list when this method is called.
+ /// The [entry] must not be in a linked list.
void insertAfter(E entry) {
_list._insertBefore(_next, entry, updateFirst: false);
}
- /**
- * Insert an element before this element in this element's linked list.
- *
- * This entry must be in a linked list when this method is called.
- * The [entry] must not be in a linked list.
- */
+ /// Insert an element before this element in this element's linked list.
+ ///
+ /// This entry must be in a linked list when this method is called.
+ /// The [entry] must not be in a linked list.
void insertBefore(E entry) {
_list._insertBefore(this, entry, updateFirst: true);
}
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index 0c01350..77ce66a 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -4,70 +4,65 @@
part of dart.collection;
-/**
- * Abstract implementation of a list.
- *
- * `ListBase` can be used as a base class for implementing the `List` interface.
- *
- * All operations are defined in terms of `length`, `operator[]`,
- * `operator[]=` and `length=`, which need to be implemented.
- *
- * *NOTICE*: Forwarding just these four operations to a normal growable [List]
- * (as created by `new List()`) will give very bad performance for `add` and
- * `addAll` operations of `ListBase`. These operations are implemented by
- * increasing the length of the list by one for each `add` operation, and
- * repeatedly increasing the length of a growable list is not efficient.
- * To avoid this, either override 'add' and 'addAll' to also forward directly
- * to the growable list, or, preferably, use `DelegatingList` from
- * "package:collection/wrappers.dart" instead.
- */
+/// Abstract implementation of a list.
+///
+/// `ListBase` can be used as a base class for implementing the `List`
+/// interface.
+///
+/// All operations are defined in terms of `length`, `operator[]`,
+/// `operator[]=` and `length=`, which need to be implemented.
+///
+/// *NOTICE*: Forwarding just these four operations to a normal growable [List]
+/// (as created by `new List()`) will give very bad performance for `add` and
+/// `addAll` operations of `ListBase`. These operations are implemented by
+/// increasing the length of the list by one for each `add` operation, and
+/// repeatedly increasing the length of a growable list is not efficient.
+/// To avoid this, either override 'add' and 'addAll' to also forward directly
+/// to the growable list, or, preferably, use `DelegatingList` from
+/// "package:collection/wrappers.dart" instead.
abstract class ListBase<E> extends Object with ListMixin<E> {
- /**
- * Convert a `List` to a string as `[each, element, as, string]`.
- *
- * Handles circular references where converting one of the elements
- * to a string ends up converting [list] to a string again.
- */
+ /// Convert a `List` to a string as `[each, element, as, string]`.
+ ///
+ /// Handles circular references where converting one of the elements
+ /// to a string ends up converting [list] to a string again.
static String listToString(List list) =>
IterableBase.iterableToFullString(list, '[', ']');
}
-/**
- * Base implementation of a [List] class.
- *
- * `ListMixin` can be used as a mixin to make a class implement
- * the `List` interface.
- *
- * This implements all read operations using only the `length` and
- * `operator[]` members. It implements write operations using those and
- * `length=` and `operator[]=`
- *
- * *NOTICE*: Forwarding just these four operations to a normal growable [List]
- * (as created by `new List()`) will give very bad performance for `add` and
- * `addAll` operations of `ListBase`. These operations are implemented by
- * increasing the length of the list by one for each `add` operation, and
- * repeatedly increasing the length of a growable list is not efficient.
- * To avoid this, either override 'add' and 'addAll' to also forward directly
- * to the growable list, or, if possible, use `DelegatingList` from
- * "package:collection/wrappers.dart" instead.
- */
+/// Base implementation of a [List] class.
+///
+/// `ListMixin` can be used as a mixin to make a class implement
+/// the `List` interface.
+///
+/// This implements all read operations using only the `length` and
+/// `operator[]` members. It implements write operations using those and
+/// `length=` and `operator[]=`
+///
+/// *NOTICE*: Forwarding just these four operations to a normal growable [List]
+/// (as created by `new List()`) will give very bad performance for `add` and
+/// `addAll` operations of `ListBase`. These operations are implemented by
+/// increasing the length of the list by one for each `add` operation, and
+/// repeatedly increasing the length of a growable list is not efficient.
+/// To avoid this, either override 'add' and 'addAll' to also forward directly
+/// to the growable list, or, if possible, use `DelegatingList` from
+/// "package:collection/wrappers.dart" instead.
abstract class ListMixin<E> implements List<E> {
// Iterable interface.
// TODO(lrn): When we get composable mixins, reuse IterableMixin instead
// of redaclating everything.
- Iterator<E> get iterator => new ListIterator<E>(this);
+ Iterator<E> get iterator => ListIterator<E>(this);
E elementAt(int index) => this[index];
Iterable<E> followedBy(Iterable<E> other) =>
- new FollowedByIterable<E>.firstEfficient(this, other);
+ FollowedByIterable<E>.firstEfficient(this, other);
void forEach(void action(E element)) {
int length = this.length;
for (int i = 0; i < length; i++) {
action(this[i]);
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
}
@@ -107,7 +102,7 @@
for (int i = 0; i < length; i++) {
if (this[i] == element) return true;
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
return false;
@@ -118,7 +113,7 @@
for (int i = 0; i < length; i++) {
if (!test(this[i])) return false;
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
return true;
@@ -129,7 +124,7 @@
for (int i = 0; i < length; i++) {
if (test(this[i])) return true;
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
return false;
@@ -141,7 +136,7 @@
E element = this[i];
if (test(element)) return element;
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
if (orElse != null) return orElse();
@@ -154,7 +149,7 @@
E element = this[i];
if (test(element)) return element;
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
if (orElse != null) return orElse();
@@ -175,7 +170,7 @@
match = element;
}
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
if (matchFound) return match;
@@ -185,18 +180,18 @@
String join([String separator = ""]) {
if (length == 0) return "";
- StringBuffer buffer = new StringBuffer()..writeAll(this, separator);
+ StringBuffer buffer = StringBuffer()..writeAll(this, separator);
return buffer.toString();
}
- Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test);
+ Iterable<E> where(bool test(E element)) => WhereIterable<E>(this, test);
- Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+ Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
- Iterable<T> map<T>(T f(E element)) => new MappedListIterable<E, T>(this, f);
+ Iterable<T> map<T>(T f(E element)) => MappedListIterable<E, T>(this, f);
Iterable<T> expand<T>(Iterable<T> f(E element)) =>
- new ExpandIterable<E, T>(this, f);
+ ExpandIterable<E, T>(this, f);
E reduce(E combine(E previousValue, E element)) {
int length = this.length;
@@ -205,7 +200,7 @@
for (int i = 1; i < length; i++) {
value = combine(value, this[i]);
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
return value;
@@ -217,30 +212,30 @@
for (int i = 0; i < length; i++) {
value = combine(value, this[i]);
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
return value;
}
- Iterable<E> skip(int count) => new SubListIterable<E>(this, count, null);
+ Iterable<E> skip(int count) => SubListIterable<E>(this, count, null);
Iterable<E> skipWhile(bool test(E element)) {
- return new SkipWhileIterable<E>(this, test);
+ return SkipWhileIterable<E>(this, test);
}
- Iterable<E> take(int count) => new SubListIterable<E>(this, 0, count);
+ Iterable<E> take(int count) => SubListIterable<E>(this, 0, count);
Iterable<E> takeWhile(bool test(E element)) {
- return new TakeWhileIterable<E>(this, test);
+ return TakeWhileIterable<E>(this, test);
}
- List<E> toList({bool growable: true}) {
+ List<E> toList({bool growable = true}) {
List<E> result;
if (growable) {
result = <E>[]..length = length;
} else {
- result = new List<E>(length);
+ result = List<E>(length);
}
for (int i = 0; i < length; i++) {
result[i] = this[i];
@@ -249,7 +244,7 @@
}
Set<E> toSet() {
- Set<E> result = new Set<E>();
+ Set<E> result = Set<E>();
for (int i = 0; i < length; i++) {
result.add(this[i]);
}
@@ -264,7 +259,7 @@
void addAll(Iterable<E> iterable) {
int i = this.length;
for (E element in iterable) {
- assert(this.length == i || (throw new ConcurrentModificationError(this)));
+ assert(this.length == i || (throw ConcurrentModificationError(this)));
this.length = i + 1;
this[i] = element;
i++;
@@ -312,7 +307,7 @@
retained.add(element);
}
if (length != this.length) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
if (retained.length != this.length) {
@@ -346,7 +341,7 @@
}
void shuffle([Random random]) {
- random ??= new Random();
+ random ??= Random();
int length = this.length;
while (length > 1) {
int pos = random.nextInt(length);
@@ -358,7 +353,7 @@
}
Map<int, E> asMap() {
- return new ListMapView<E>(this);
+ return ListMapView<E>(this);
}
List<E> operator +(List<E> other) {
@@ -382,7 +377,7 @@
Iterable<E> getRange(int start, int end) {
RangeError.checkValidRange(start, end, this.length);
- return new SubListIterable<E>(this, start, end);
+ return SubListIterable<E>(this, start, end);
}
void removeRange(int start, int end) {
@@ -517,7 +512,7 @@
// If the iterable's length is linked to this list's length somehow,
// we can't insert one in the other.
this.length -= insertionLength;
- throw new ConcurrentModificationError(iterable);
+ throw ConcurrentModificationError(iterable);
}
setRange(index + insertionLength, this.length, this, index);
setAll(index, iterable);
@@ -533,7 +528,7 @@
}
}
- Iterable<E> get reversed => new ReversedListIterable<E>(this);
+ Iterable<E> get reversed => ReversedListIterable<E>(this);
String toString() => IterableBase.iterableToFullString(this, '[', ']');
}
diff --git a/sdk/lib/collection/maps.dart b/sdk/lib/collection/maps.dart
index f54404f..8159342 100644
--- a/sdk/lib/collection/maps.dart
+++ b/sdk/lib/collection/maps.dart
@@ -4,22 +4,20 @@
part of dart.collection;
-/**
- * Base class for implementing a [Map].
- *
- * This class has a basic implementation of all but five of the members of
- * [Map].
- * A basic `Map` class can be implemented by extending this class and
- * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`.
- * The remaining operations are implemented in terms of these five.
- *
- * The `keys` iterable should have efficient [Iterable.length] and
- * [Iterable.contains] operations, and it should catch concurrent modifications
- * of the keys while iterating.
- *
- * A more efficient implementation is usually possible by overriding
- * some of the other members as well.
- */
+/// Base class for implementing a [Map].
+///
+/// This class has a basic implementation of all but five of the members of
+/// [Map].
+/// A basic `Map` class can be implemented by extending this class and
+/// implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`.
+/// The remaining operations are implemented in terms of these five.
+///
+/// The `keys` iterable should have efficient [Iterable.length] and
+/// [Iterable.contains] operations, and it should catch concurrent modifications
+/// of the keys while iterating.
+///
+/// A more efficient implementation is usually possible by overriding
+/// some of the other members as well.
abstract class MapBase<K, V> extends MapMixin<K, V> {
static String mapToString(Map m) {
// Reuses the list in IterableBase for detecting toString cycles.
@@ -27,7 +25,7 @@
return '{...}';
}
- var result = new StringBuffer();
+ var result = StringBuffer();
try {
_toStringVisiting.add(m);
result.write('{');
@@ -52,12 +50,10 @@
static _id(x) => x;
- /**
- * Fills a [Map] with key/value pairs computed from [iterable].
- *
- * This method is used by [Map] classes in the named constructor
- * `fromIterable`.
- */
+ /// Fills a [Map] with key/value pairs computed from [iterable].
+ ///
+ /// This method is used by [Map] classes in the named constructor
+ /// `fromIterable`.
static void _fillMapWithMappedIterable(
Map map, Iterable iterable, key(element), value(element)) {
key ??= _id;
@@ -68,12 +64,10 @@
}
}
- /**
- * Fills a map by associating the [keys] to [values].
- *
- * This method is used by [Map] classes in the named constructor
- * `fromIterables`.
- */
+ /// Fills a map by associating the [keys] to [values].
+ ///
+ /// This method is used by [Map] classes in the named constructor
+ /// `fromIterables`.
static void _fillMapWithIterables(Map map, Iterable keys, Iterable values) {
Iterator keyIterator = keys.iterator;
Iterator valueIterator = values.iterator;
@@ -88,27 +82,25 @@
}
if (hasNextKey || hasNextValue) {
- throw new ArgumentError("Iterables do not have same length.");
+ throw ArgumentError("Iterables do not have same length.");
}
}
}
-/**
- * Mixin implementing a [Map].
- *
- * This mixin has a basic implementation of all but five of the members of
- * [Map].
- * A basic `Map` class can be implemented by mixin in this class and
- * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`.
- * The remaining operations are implemented in terms of these five.
- *
- * The `keys` iterable should have efficient [Iterable.length] and
- * [Iterable.contains] operations, and it should catch concurrent modifications
- * of the keys while iterating.
- *
- * A more efficient implementation is usually possible by overriding
- * some of the other members as well.
- */
+/// Mixin implementing a [Map].
+///
+/// This mixin has a basic implementation of all but five of the members of
+/// [Map].
+/// A basic `Map` class can be implemented by mixin in this class and
+/// implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`.
+/// The remaining operations are implemented in terms of these five.
+///
+/// The `keys` iterable should have efficient [Iterable.length] and
+/// [Iterable.contains] operations, and it should catch concurrent modifications
+/// of the keys while iterating.
+///
+/// A more efficient implementation is usually possible by overriding
+/// some of the other members as well.
abstract class MapMixin<K, V> implements Map<K, V> {
Iterable<K> get keys;
V operator [](Object key);
@@ -152,7 +144,7 @@
if (ifAbsent != null) {
return this[key] = ifAbsent();
}
- throw new ArgumentError.value(key, "key", "Key not in map.");
+ throw ArgumentError.value(key, "key", "Key not in map.");
}
void updateAll(V update(K key, V value)) {
@@ -162,7 +154,7 @@
}
Iterable<MapEntry<K, V>> get entries {
- return keys.map((K key) => new MapEntry<K, V>(key, this[key]));
+ return keys.map((K key) => MapEntry<K, V>(key, this[key]));
}
Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) {
@@ -194,39 +186,35 @@
int get length => keys.length;
bool get isEmpty => keys.isEmpty;
bool get isNotEmpty => keys.isNotEmpty;
- Iterable<V> get values => new _MapBaseValueIterable<K, V>(this);
+ Iterable<V> get values => _MapBaseValueIterable<K, V>(this);
String toString() => MapBase.mapToString(this);
}
-/**
- * Basic implementation of an unmodifiable [Map].
- *
- * This class has a basic implementation of all but two of the members of
- * an umodifiable [Map].
- * A simple unmodifiable `Map` class can be implemented by extending this
- * class and implementing `keys` and `operator[]`.
- *
- * Modifying operations throw when used.
- * The remaining non-modifying operations are implemented in terms of `keys`
- * and `operator[]`.
- *
- * The `keys` iterable should have efficient [Iterable.length] and
- * [Iterable.contains] operations, and it should catch concurrent modifications
- * of the keys while iterating.
- *
- * A more efficient implementation is usually possible by overriding
- * some of the other members as well.
- */
+/// Basic implementation of an unmodifiable [Map].
+///
+/// This class has a basic implementation of all but two of the members of
+/// an umodifiable [Map].
+/// A simple unmodifiable `Map` class can be implemented by extending this
+/// class and implementing `keys` and `operator[]`.
+///
+/// Modifying operations throw when used.
+/// The remaining non-modifying operations are implemented in terms of `keys`
+/// and `operator[]`.
+///
+/// The `keys` iterable should have efficient [Iterable.length] and
+/// [Iterable.contains] operations, and it should catch concurrent modifications
+/// of the keys while iterating.
+///
+/// A more efficient implementation is usually possible by overriding
+/// some of the other members as well.
abstract class UnmodifiableMapBase<K, V> = MapBase<K, V>
with _UnmodifiableMapMixin<K, V>;
-/**
- * Implementation of [Map.values] based on the map and its [Map.keys] iterable.
- *
- * Iterable that iterates over the values of a `Map`.
- * It accesses the values by iterating over the keys of the map, and using the
- * map's `operator[]` to lookup the keys.
- */
+/// Implementation of [Map.values] based on the map and its [Map.keys] iterable.
+///
+/// Iterable that iterates over the values of a `Map`.
+/// It accesses the values by iterating over the keys of the map, and using the
+/// map's `operator[]` to lookup the keys.
class _MapBaseValueIterable<K, V> extends EfficientLengthIterable<V> {
final Map<K, V> _map;
_MapBaseValueIterable(this._map);
@@ -238,15 +226,13 @@
V get single => _map[_map.keys.single];
V get last => _map[_map.keys.last];
- Iterator<V> get iterator => new _MapBaseValueIterator<K, V>(_map);
+ Iterator<V> get iterator => _MapBaseValueIterator<K, V>(_map);
}
-/**
- * Iterator created by [_MapBaseValueIterable].
- *
- * Iterates over the values of a map by iterating its keys and lookup up the
- * values.
- */
+/// Iterator created by [_MapBaseValueIterable].
+///
+/// Iterates over the values of a map by iterating its keys and lookup up the
+/// values.
class _MapBaseValueIterator<K, V> implements Iterator<V> {
final Iterator<K> _keys;
final Map<K, V> _map;
@@ -268,64 +254,62 @@
V get current => _current;
}
-/**
- * Mixin that overrides mutating map operations with implementations that throw.
- */
+/// Mixin that overrides mutating map operations with implementations that
+/// throw.
abstract class _UnmodifiableMapMixin<K, V> implements Map<K, V> {
- /** This operation is not supported by an unmodifiable map. */
+ /// This operation is not supported by an unmodifiable map.
void operator []=(K key, V value) {
- throw new UnsupportedError("Cannot modify unmodifiable map");
+ throw UnsupportedError("Cannot modify unmodifiable map");
}
- /** This operation is not supported by an unmodifiable map. */
+ /// This operation is not supported by an unmodifiable map.
void addAll(Map<K, V> other) {
- throw new UnsupportedError("Cannot modify unmodifiable map");
+ throw UnsupportedError("Cannot modify unmodifiable map");
}
- /** This operation is not supported by an unmodifiable map. */
+ /// This operation is not supported by an unmodifiable map.
void addEntries(Iterable<MapEntry<K, V>> entries) {
- throw new UnsupportedError("Cannot modify unmodifiable map");
+ throw UnsupportedError("Cannot modify unmodifiable map");
}
- /** This operation is not supported by an unmodifiable map. */
+ /// This operation is not supported by an unmodifiable map.
void clear() {
- throw new UnsupportedError("Cannot modify unmodifiable map");
+ throw UnsupportedError("Cannot modify unmodifiable map");
}
- /** This operation is not supported by an unmodifiable map. */
+ /// This operation is not supported by an unmodifiable map.
V remove(Object key) {
- throw new UnsupportedError("Cannot modify unmodifiable map");
+ throw UnsupportedError("Cannot modify unmodifiable map");
}
- /** This operation is not supported by an unmodifiable map. */
+ /// This operation is not supported by an unmodifiable map.
void removeWhere(bool test(K key, V value)) {
- throw new UnsupportedError("Cannot modify unmodifiable map");
+ throw UnsupportedError("Cannot modify unmodifiable map");
}
- /** This operation is not supported by an unmodifiable map. */
+ /// This operation is not supported by an unmodifiable map.
V putIfAbsent(K key, V ifAbsent()) {
- throw new UnsupportedError("Cannot modify unmodifiable map");
+ throw UnsupportedError("Cannot modify unmodifiable map");
}
- /** This operation is not supported by an unmodifiable map. */
+ /// This operation is not supported by an unmodifiable map.
V update(K key, V update(V value), {V ifAbsent()}) {
- throw new UnsupportedError("Cannot modify unmodifiable map");
+ throw UnsupportedError("Cannot modify unmodifiable map");
}
- /** This operation is not supported by an unmodifiable map. */
+ /// This operation is not supported by an unmodifiable map.
void updateAll(V update(K key, V value)) {
- throw new UnsupportedError("Cannot modify unmodifiable map");
+ throw UnsupportedError("Cannot modify unmodifiable map");
}
}
-/**
- * Wrapper around a class that implements [Map] that only exposes `Map` members.
- *
- * A simple wrapper that delegates all `Map` members to the map provided in the
- * constructor.
- *
- * Base for delegating map implementations like [UnmodifiableMapView].
- */
+/// Wrapper around a class that implements [Map] that only exposes `Map`
+/// members.
+///
+/// A simple wrapper that delegates all `Map` members to the map provided in the
+/// constructor.
+///
+/// Base for delegating map implementations like [UnmodifiableMapView].
class MapView<K, V> implements Map<K, V> {
final Map<K, V> _map;
const MapView(Map<K, V> map) : _map = map;
@@ -380,17 +364,15 @@
}
}
-/**
- * View of a [Map] that disallow modifying the map.
- *
- * A wrapper around a `Map` that forwards all members to the map provided in
- * the constructor, except for operations that modify the map.
- * Modifying operations throw instead.
- */
+/// View of a [Map] that disallow modifying the map.
+///
+/// A wrapper around a `Map` that forwards all members to the map provided in
+/// the constructor, except for operations that modify the map.
+/// Modifying operations throw instead.
class UnmodifiableMapView<K, V> extends MapView<K, V>
with _UnmodifiableMapMixin<K, V> {
UnmodifiableMapView(Map<K, V> map) : super(map);
Map<RK, RV> cast<RK, RV>() =>
- new UnmodifiableMapView<RK, RV>(_map.cast<RK, RV>());
+ UnmodifiableMapView<RK, RV>(_map.cast<RK, RV>());
}
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 7f82357..62994b9 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -4,140 +4,108 @@
part of dart.collection;
-/**
- * A [Queue] is a collection that can be manipulated at both ends. One
- * can iterate over the elements of a queue through [forEach] or with
- * an [Iterator].
- *
- * It is generally not allowed to modify the queue (add or remove entries) while
- * an operation on the queue is being performed, for example during a call to
- * [forEach].
- * Modifying the queue while it is being iterated will most likely break the
- * iteration.
- * This goes both for using the [iterator] directly, or for iterating an
- * `Iterable` returned by a method like [map] or [where].
- */
+/// A [Queue] is a collection that can be manipulated at both ends. One
+/// can iterate over the elements of a queue through [forEach] or with
+/// an [Iterator].
+///
+/// It is generally not allowed to modify the queue (add or remove entries)
+/// while an operation on the queue is being performed, for example during a
+/// call to [forEach].
+/// Modifying the queue while it is being iterated will most likely break the
+/// iteration.
+/// This goes both for using the [iterator] directly, or for iterating an
+/// `Iterable` returned by a method like [map] or [where].
abstract class Queue<E> implements EfficientLengthIterable<E> {
- /**
- * Creates a queue.
- */
+ /// Creates a queue.
factory Queue() = ListQueue<E>;
- /**
- * Creates a queue containing all [elements].
- *
- * The element order in the queue is as if the elements were added using
- * [addLast] in the order provided by [elements.iterator].
- *
- * All the [elements] should be instances of [E].
- * The `elements` iterable itself may have any element type, so this
- * constructor can be used to down-cast a `Queue`, for example as:
- * ```dart
- * Queue<SuperType> superQueue = ...;
- * Queue<SubType> subQueue =
- * new Queue<SubType>.from(superSet.whereType<SubType>());
- * ```
- */
+ /// Creates a queue containing all [elements].
+ ///
+ /// The element order in the queue is as if the elements were added using
+ /// [addLast] in the order provided by [elements.iterator].
+ ///
+ /// All the [elements] should be instances of [E].
+ /// The `elements` iterable itself may have any element type, so this
+ /// constructor can be used to down-cast a `Queue`, for example as:
+ /// ```dart
+ /// Queue<SuperType> superQueue = ...;
+ /// Queue<SubType> subQueue =
+ /// new Queue<SubType>.from(superSet.whereType<SubType>());
+ /// ```
factory Queue.from(Iterable elements) = ListQueue<E>.from;
- /**
- * Creates a queue from [elements].
- *
- * The element order in the queue is as if the elements were added using
- * [addLast] in the order provided by [elements.iterator].
- */
+ /// Creates a queue from [elements].
+ ///
+ /// The element order in the queue is as if the elements were added using
+ /// [addLast] in the order provided by [elements.iterator].
factory Queue.of(Iterable<E> elements) = ListQueue<E>.of;
- /**
- * Adapts [source] to be a `Queue<T>`.
- *
- * Any time the queue would produce an element that is not a [T],
- * the element access will throw.
- *
- * Any time a [T] value is attempted stored into the adapted queue,
- * the store will throw unless the value is also an instance of [S].
- *
- * If all accessed elements of [source] are actually instances of [T],
- * and if all elements stored into the returned queue are actually instance
- * of [S],
- * then the returned queue can be used as a `Queue<T>`.
- */
- static Queue<T> castFrom<S, T>(Queue<S> source) =>
- new CastQueue<S, T>(source);
+ /// Adapts [source] to be a `Queue<T>`.
+ ///
+ /// Any time the queue would produce an element that is not a [T],
+ /// the element access will throw.
+ ///
+ /// Any time a [T] value is attempted stored into the adapted queue,
+ /// the store will throw unless the value is also an instance of [S].
+ ///
+ /// If all accessed elements of [source] are actually instances of [T],
+ /// and if all elements stored into the returned queue are actually instance
+ /// of [S],
+ /// then the returned queue can be used as a `Queue<T>`.
+ static Queue<T> castFrom<S, T>(Queue<S> source) => CastQueue<S, T>(source);
- /**
- * Provides a view of this queue as a queue of [R] instances, if necessary.
- *
- * If this queue contains only instances of [R], all read operations
- * will work correctly. If any operation tries to access an element
- * that is not an instance of [R], the access will throw instead.
- *
- * Elements added to the queue (e.g., by using [addFirst] or [addAll])
- * must be instance of [R] to be valid arguments to the adding function,
- * and they must be instances of [E] as well to be accepted by
- * this queue as well.
- */
+ /// Provides a view of this queue as a queue of [R] instances, if necessary.
+ ///
+ /// If this queue contains only instances of [R], all read operations
+ /// will work correctly. If any operation tries to access an element
+ /// that is not an instance of [R], the access will throw instead.
+ ///
+ /// Elements added to the queue (e.g., by using [addFirst] or [addAll])
+ /// must be instance of [R] to be valid arguments to the adding function,
+ /// and they must be instances of [E] as well to be accepted by
+ /// this queue as well.
Queue<R> cast<R>();
- /**
- * Removes and returns the first element of this queue.
- *
- * The queue must not be empty when this method is called.
- */
+
+ /// Removes and returns the first element of this queue.
+ ///
+ /// The queue must not be empty when this method is called.
E removeFirst();
- /**
- * Removes and returns the last element of the queue.
- *
- * The queue must not be empty when this method is called.
- */
+ /// Removes and returns the last element of the queue.
+ ///
+ /// The queue must not be empty when this method is called.
E removeLast();
- /**
- * Adds [value] at the beginning of the queue.
- */
+ /// Adds [value] at the beginning of the queue.
void addFirst(E value);
- /**
- * Adds [value] at the end of the queue.
- */
+ /// Adds [value] at the end of the queue.
void addLast(E value);
- /**
- * Adds [value] at the end of the queue.
- */
+ /// Adds [value] at the end of the queue.
void add(E value);
- /**
- * Remove a single instance of [value] from the queue.
- *
- * Returns `true` if a value was removed, or `false` if the queue
- * contained no element equal to [value].
- */
+ /// Remove a single instance of [value] from the queue.
+ ///
+ /// Returns `true` if a value was removed, or `false` if the queue
+ /// contained no element equal to [value].
bool remove(Object value);
- /**
- * Adds all elements of [iterable] at the end of the queue. The
- * length of the queue is extended by the length of [iterable].
- */
+ /// Adds all elements of [iterable] at the end of the queue. The
+ /// length of the queue is extended by the length of [iterable].
void addAll(Iterable<E> iterable);
- /**
- * Removes all elements matched by [test] from the queue.
- *
- * The `test` function must not throw or modify the queue.
- */
+ /// Removes all elements matched by [test] from the queue.
+ ///
+ /// The `test` function must not throw or modify the queue.
void removeWhere(bool test(E element));
- /**
- * Removes all elements not matched by [test] from the queue.
- *
- * The `test` function must not throw or modify the queue.
- */
+ /// Removes all elements not matched by [test] from the queue.
+ ///
+ /// The `test` function must not throw or modify the queue.
void retainWhere(bool test(E element));
- /**
- * Removes all elements in the queue. The size of the queue becomes zero.
- */
+ /// Removes all elements in the queue. The size of the queue becomes zero.
void clear();
}
@@ -160,10 +128,8 @@
}
}
-/**
- * An entry in a doubly linked list. It contains a pointer to the next
- * entry, the previous entry, and the boxed element.
- */
+/// An entry in a doubly linked list. It contains a pointer to the next
+/// entry, the previous entry, and the boxed element.
class DoubleLinkedQueueEntry<E> extends _DoubleLink<DoubleLinkedQueueEntry<E>> {
/// The element in the queue.
E element;
@@ -172,12 +138,12 @@
/// Appends the given [e] as entry just after this entry.
void append(E e) {
- new DoubleLinkedQueueEntry<E>(e)._link(this, _nextLink);
+ DoubleLinkedQueueEntry<E>(e)._link(this, _nextLink);
}
/// Prepends the given [e] as entry just before this entry.
void prepend(E e) {
- new DoubleLinkedQueueEntry<E>(e)._link(_previousLink, this);
+ DoubleLinkedQueueEntry<E>(e)._link(_previousLink, this);
}
E remove() {
@@ -192,14 +158,12 @@
DoubleLinkedQueueEntry<E> nextEntry() => _nextLink;
}
-/**
- * Interface for the link classes used by [DoubleLinkedQueue].
- *
- * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel]
- * implement this interface.
- * The entry contains a link back to the queue, so calling `append`
- * or `prepend` can correctly update the element count.
- */
+/// Interface for the link classes used by [DoubleLinkedQueue].
+///
+/// Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel]
+/// implement this interface.
+/// The entry contains a link back to the queue, so calling `append`
+/// or `prepend` can correctly update the element count.
abstract class _DoubleLinkedQueueEntry<E> extends DoubleLinkedQueueEntry<E> {
DoubleLinkedQueue<E> _queue;
_DoubleLinkedQueueEntry(E element, this._queue) : super(element);
@@ -207,11 +171,11 @@
DoubleLinkedQueueEntry<E> _asNonSentinelEntry();
void _append(E e) {
- new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink);
+ _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink);
}
void _prepend(E e) {
- new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this);
+ _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this);
}
E _remove();
@@ -229,12 +193,10 @@
}
}
-/**
- * The actual entry type used by the [DoubleLinkedQueue].
- *
- * The entry contains a reference to the queue, allowing
- * [append]/[prepend] to update the list length.
- */
+/// The actual entry type used by the [DoubleLinkedQueue].
+///
+/// The entry contains a reference to the queue, allowing
+/// [append]/[prepend] to update the list length.
class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> {
_DoubleLinkedQueueElement(E element, DoubleLinkedQueue<E> queue)
: super(element, queue);
@@ -265,14 +227,12 @@
}
}
-/**
- * A sentinel in a double linked list is used to manipulate the list
- * at both ends.
- * A double linked list has exactly one sentinel,
- * which is the only entry when the list is constructed.
- * Initially, a sentinel has its next and previous entry point to itself.
- * A sentinel does not box any user element.
- */
+/// A sentinel in a double linked list is used to manipulate the list
+/// at both ends.
+/// A double linked list has exactly one sentinel,
+/// which is the only entry when the list is constructed.
+/// Initially, a sentinel has its next and previous entry point to itself.
+/// A sentinel does not box any user element.
class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> {
_DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue) : super(null, queue) {
_previousLink = this;
@@ -283,61 +243,55 @@
return null;
}
- /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */
+ /// Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty.
E _remove() {
throw IterableElementError.noElement();
}
- /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */
+ /// Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty.
E get _element {
throw IterableElementError.noElement();
}
}
-/**
- * A [Queue] implementation based on a double-linked list.
- *
- * Allows constant time add, remove-at-ends and peek operations.
- */
+/// A [Queue] implementation based on a double-linked list.
+///
+/// Allows constant time add, remove-at-ends and peek operations.
class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> {
_DoubleLinkedQueueSentinel<E> _sentinel;
int _elementCount = 0;
DoubleLinkedQueue() {
- _sentinel = new _DoubleLinkedQueueSentinel<E>(this);
+ _sentinel = _DoubleLinkedQueueSentinel<E>(this);
}
- /**
- * Creates a double-linked queue containing all [elements].
- *
- * The element order in the queue is as if the elements were added using
- * [addLast] in the order provided by [elements.iterator].
- *
- * All the [elements] should be instances of [E].
- * The `elements` iterable itself may have any element type, so this
- * constructor can be used to down-cast a `Queue`, for example as:
- * ```dart
- * Queue<SuperType> superQueue = ...;
- * Queue<SubType> subQueue =
- * new DoubleLinkedQueue<SubType>.from(superQueue.whereType<SubType>());
- * ```
- */
+ /// Creates a double-linked queue containing all [elements].
+ ///
+ /// The element order in the queue is as if the elements were added using
+ /// [addLast] in the order provided by [elements.iterator].
+ ///
+ /// All the [elements] should be instances of [E].
+ /// The `elements` iterable itself may have any element type, so this
+ /// constructor can be used to down-cast a `Queue`, for example as:
+ /// ```dart
+ /// Queue<SuperType> superQueue = ...;
+ /// Queue<SubType> subQueue =
+ /// new DoubleLinkedQueue<SubType>.from(superQueue.whereType<SubType>());
+ /// ```
factory DoubleLinkedQueue.from(Iterable elements) {
- Queue<E> list = new DoubleLinkedQueue<E>();
+ Queue<E> list = DoubleLinkedQueue<E>();
for (final e in elements) {
list.addLast(e);
}
return list;
}
- /**
- * Creates a double-linked queue from [elements].
- *
- * The element order in the queue is as if the elements were added using
- * [addLast] in the order provided by [elements.iterator].
- */
+ /// Creates a double-linked queue from [elements].
+ ///
+ /// The element order in the queue is as if the elements were added using
+ /// [addLast] in the order provided by [elements.iterator].
factory DoubleLinkedQueue.of(Iterable<E> elements) =>
- new DoubleLinkedQueue<E>()..addAll(elements);
+ DoubleLinkedQueue<E>()..addAll(elements);
Queue<R> cast<R>() => Queue.castFrom<E, R>(this);
int get length => _elementCount;
@@ -384,7 +338,7 @@
bool equals = (entry._element == o);
if (!identical(this, entry._queue)) {
// Entry must still be in the queue.
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
if (equals) {
entry._remove();
@@ -402,7 +356,7 @@
bool matches = test(entry._element);
if (!identical(this, entry._queue)) {
// Entry must still be in the queue.
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
_DoubleLinkedQueueEntry<E> next = entry._nextLink; // Cannot be null.
if (identical(removeMatching, matches)) {
@@ -441,30 +395,26 @@
throw IterableElementError.tooMany();
}
- /**
- * The entry object of the first element in the queue.
- *
- * Each element of the queue has an associated [DoubleLinkedQueueEntry].
- * Returns the entry object corresponding to the first element of the queue.
- *
- * The entry objects can also be accessed using [lastEntry],
- * and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
- * [DoubleLinkedQueueEntry.previousEntry()].
- */
+ /// The entry object of the first element in the queue.
+ ///
+ /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
+ /// Returns the entry object corresponding to the first element of the queue.
+ ///
+ /// The entry objects can also be accessed using [lastEntry],
+ /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
+ /// [DoubleLinkedQueueEntry.previousEntry()].
DoubleLinkedQueueEntry<E> firstEntry() {
return _sentinel.nextEntry();
}
- /**
- * The entry object of the last element in the queue.
- *
- * Each element of the queue has an associated [DoubleLinkedQueueEntry].
- * Returns the entry object corresponding to the last element of the queue.
- *
- * The entry objects can also be accessed using [firstEntry],
- * and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
- * [DoubleLinkedQueueEntry.previousEntry()].
- */
+ /// The entry object of the last element in the queue.
+ ///
+ /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
+ /// Returns the entry object corresponding to the last element of the queue.
+ ///
+ /// The entry objects can also be accessed using [firstEntry],
+ /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
+ /// [DoubleLinkedQueueEntry.previousEntry()].
DoubleLinkedQueueEntry<E> lastEntry() {
return _sentinel.previousEntry();
}
@@ -479,24 +429,22 @@
_elementCount = 0;
}
- /**
- * Calls [action] for each entry object of this double-linked queue.
- *
- * Each element of the queue has an associated [DoubleLinkedQueueEntry].
- * This method iterates the entry objects from first to last and calls
- * [action] with each object in turn.
- *
- * The entry objects can also be accessed using [firstEntry] and [lastEntry],
- * and iterated using [DoubleLinkedQueueEntry.nextEntry()] and
- * [DoubleLinkedQueueEntry.previousEntry()].
- *
- * The [action] function can use methods on [DoubleLinkedQueueEntry] to remove
- * the entry or it can insert elements before or after then entry.
- * If the current entry is removed, iteration continues with the entry that
- * was following the current entry when [action] was called. Any elements
- * inserted after the current element before it is removed will not be
- * visited by the iteration.
- */
+ /// Calls [action] for each entry object of this double-linked queue.
+ ///
+ /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
+ /// This method iterates the entry objects from first to last and calls
+ /// [action] with each object in turn.
+ ///
+ /// The entry objects can also be accessed using [firstEntry] and [lastEntry],
+ /// and iterated using [DoubleLinkedQueueEntry.nextEntry()] and
+ /// [DoubleLinkedQueueEntry.previousEntry()].
+ ///
+ /// The [action] function can use methods on [DoubleLinkedQueueEntry] to
+ /// remove the entry or it can insert elements before or after then entry.
+ /// If the current entry is removed, iteration continues with the entry that
+ /// was following the current entry when [action] was called. Any elements
+ /// inserted after the current element before it is removed will not be
+ /// visited by the iteration.
void forEachEntry(void action(DoubleLinkedQueueEntry<E> element)) {
_DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink;
while (!identical(entry, _sentinel)) {
@@ -510,14 +458,14 @@
if (identical(this, entry._queue)) {
next = entry._nextLink;
} else if (!identical(this, next._queue)) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
entry = next;
}
}
_DoubleLinkedQueueIterator<E> get iterator {
- return new _DoubleLinkedQueueIterator<E>(_sentinel);
+ return _DoubleLinkedQueueIterator<E>(_sentinel);
}
String toString() => IterableBase.iterableToFullString(this, '{', '}');
@@ -541,7 +489,7 @@
}
_DoubleLinkedQueueElement<E> elementEntry = _nextEntry;
if (!identical(_sentinel._queue, elementEntry._queue)) {
- throw new ConcurrentModificationError(_sentinel._queue);
+ throw ConcurrentModificationError(_sentinel._queue);
}
_current = elementEntry._element;
_nextEntry = elementEntry._nextLink;
@@ -551,15 +499,13 @@
E get current => _current;
}
-/**
- * List based [Queue].
- *
- * Keeps a cyclic buffer of elements, and grows to a larger buffer when
- * it fills up. This guarantees constant time peek and remove operations, and
- * amortized constant time add operations.
- *
- * The structure is efficient for any queue or stack usage.
- */
+/// List based [Queue].
+///
+/// Keeps a cyclic buffer of elements, and grows to a larger buffer when
+/// it fills up. This guarantees constant time peek and remove operations, and
+/// amortized constant time add operations.
+///
+/// The structure is efficient for any queue or stack usage.
class ListQueue<E> extends ListIterable<E> implements Queue<E> {
static const int _INITIAL_CAPACITY = 8;
List<E> _table;
@@ -567,12 +513,10 @@
int _tail;
int _modificationCount = 0;
- /**
- * Create an empty queue.
- *
- * If [initialCapacity] is given, prepare the queue for at least that many
- * elements.
- */
+ /// Create an empty queue.
+ ///
+ /// If [initialCapacity] is given, prepare the queue for at least that many
+ /// elements.
ListQueue([int initialCapacity])
: _head = 0,
_tail = 0 {
@@ -582,28 +526,26 @@
initialCapacity = _nextPowerOf2(initialCapacity);
}
assert(_isPowerOf2(initialCapacity));
- _table = new List<E>(initialCapacity);
+ _table = List<E>(initialCapacity);
}
- /**
- * Create a `ListQueue` containing all [elements].
- *
- * The elements are added to the queue, as by [addLast], in the order given by
- * `elements.iterator`.
- *
- * All the [elements] should be instances of [E].
- * The `elements` iterable itself may have any element type, so this
- * constructor can be used to down-cast a `Queue`, for example as:
- * ```dart
- * Queue<SuperType> superQueue = ...;
- * Queue<SubType> subQueue =
- * new ListQueue<SubType>.from(superQueue.whereType<SubType>());
- * ```
- */
+ /// Create a `ListQueue` containing all [elements].
+ ///
+ /// The elements are added to the queue, as by [addLast], in the order given
+ /// by `elements.iterator`.
+ ///
+ /// All the [elements] should be instances of [E].
+ /// The `elements` iterable itself may have any element type, so this
+ /// constructor can be used to down-cast a `Queue`, for example as:
+ /// ```dart
+ /// Queue<SuperType> superQueue = ...;
+ /// Queue<SubType> subQueue =
+ /// new ListQueue<SubType>.from(superQueue.whereType<SubType>());
+ /// ```
factory ListQueue.from(Iterable elements) {
if (elements is List) {
int length = elements.length;
- ListQueue<E> queue = new ListQueue<E>(length + 1);
+ ListQueue<E> queue = ListQueue<E>(length + 1);
assert(queue._table.length > length);
for (int i = 0; i < length; i++) {
queue._table[i] = elements[i];
@@ -615,7 +557,7 @@
if (elements is EfficientLengthIterable) {
capacity = elements.length;
}
- ListQueue<E> result = new ListQueue<E>(capacity);
+ ListQueue<E> result = ListQueue<E>(capacity);
for (final element in elements) {
result.addLast(element);
}
@@ -623,19 +565,17 @@
}
}
- /**
- * Create a `ListQueue` from [elements].
- *
- * The elements are added to the queue, as by [addLast], in the order given by
- * `elements.iterator`.
- */
+ /// Create a `ListQueue` from [elements].
+ ///
+ /// The elements are added to the queue, as by [addLast], in the order given
+ /// by `elements.iterator`.
factory ListQueue.of(Iterable<E> elements) =>
- new ListQueue<E>()..addAll(elements);
+ ListQueue<E>()..addAll(elements);
// Iterable interface.
Queue<R> cast<R>() => Queue.castFrom<E, R>(this);
- Iterator<E> get iterator => new _ListQueueIterator<E>(this);
+ Iterator<E> get iterator => _ListQueueIterator<E>(this);
void forEach(void f(E element)) {
int modificationCount = _modificationCount;
@@ -670,12 +610,12 @@
return _table[(_head + index) & (_table.length - 1)];
}
- List<E> toList({bool growable: true}) {
+ List<E> toList({bool growable = true}) {
List<E> list;
if (growable) {
list = <E>[]..length = length;
} else {
- list = new List<E>(length);
+ list = List<E>(length);
}
_writeToList(list);
return list;
@@ -744,22 +684,18 @@
}
}
- /**
- * Remove all elements matched by [test].
- *
- * This method is inefficient since it works by repeatedly removing single
- * elements, each of which can take linear time.
- */
+ /// Remove all elements matched by [test].
+ ///
+ /// This method is inefficient since it works by repeatedly removing single
+ /// elements, each of which can take linear time.
void removeWhere(bool test(E element)) {
_filterWhere(test, true);
}
- /**
- * Remove all elements not matched by [test].
- *
- * This method is inefficient since it works by repeatedly removing single
- * elements, each of which can take linear time.
- */
+ /// Remove all elements not matched by [test].
+ ///
+ /// This method is inefficient since it works by repeatedly removing single
+ /// elements, each of which can take linear time.
void retainWhere(bool test(E element)) {
_filterWhere(test, false);
}
@@ -809,20 +745,16 @@
// Internal helper functions.
- /**
- * Whether [number] is a power of two.
- *
- * Only works for positive numbers.
- */
+ /// Whether [number] is a power of two.
+ ///
+ /// Only works for positive numbers.
static bool _isPowerOf2(int number) => (number & (number - 1)) == 0;
- /**
- * Rounds [number] up to the nearest power of 2.
- *
- * If [number] is a power of 2 already, it is returned.
- *
- * Only works for positive numbers.
- */
+ /// Rounds [number] up to the nearest power of 2.
+ ///
+ /// If [number] is a power of 2 already, it is returned.
+ ///
+ /// Only works for positive numbers.
static int _nextPowerOf2(int number) {
assert(number > 0);
number = (number << 1) - 1;
@@ -833,14 +765,14 @@
}
}
- /** Check if the queue has been modified during iteration. */
+ /// Check if the queue has been modified during iteration.
void _checkModification(int expectedModificationCount) {
if (expectedModificationCount != _modificationCount) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
}
- /** Adds element at end of queue. Used by both [add] and [addAll]. */
+ /// Adds element at end of queue. Used by both [add] and [addAll].
void _add(E element) {
_table[_tail] = element;
_tail = (_tail + 1) & (_table.length - 1);
@@ -848,16 +780,14 @@
_modificationCount++;
}
- /**
- * Removes the element at [offset] into [_table].
- *
- * Removal is performed by linearly moving elements either before or after
- * [offset] by one position.
- *
- * Returns the new offset of the following element. This may be the same
- * offset or the following offset depending on how elements are moved
- * to fill the hole.
- */
+ /// Removes the element at [offset] into [_table].
+ ///
+ /// Removal is performed by linearly moving elements either before or after
+ /// [offset] by one position.
+ ///
+ /// Returns the new offset of the following element. This may be the same
+ /// offset or the following offset depending on how elements are moved
+ /// to fill the hole.
int _remove(int offset) {
int mask = _table.length - 1;
int startDistance = (offset - _head) & mask;
@@ -886,11 +816,9 @@
}
}
- /**
- * Grow the table when full.
- */
+ /// Grow the table when full.
void _grow() {
- List<E> newTable = new List<E>(_table.length * 2);
+ List<E> newTable = List<E>(_table.length * 2);
int split = _table.length - _head;
newTable.setRange(0, split, _table, _head);
newTable.setRange(split, split + _head, _table, 0);
@@ -913,7 +841,7 @@
}
}
- /** Grows the table even if it is not full. */
+ /// Grows the table even if it is not full.
void _preGrow(int newElementCount) {
assert(newElementCount >= length);
@@ -921,18 +849,16 @@
// expansion.
newElementCount += newElementCount >> 1;
int newCapacity = _nextPowerOf2(newElementCount);
- List<E> newTable = new List<E>(newCapacity);
+ List<E> newTable = List<E>(newCapacity);
_tail = _writeToList(newTable);
_table = newTable;
_head = 0;
}
}
-/**
- * Iterator for a [ListQueue].
- *
- * Considers any add or remove operation a concurrent modification.
- */
+/// Iterator for a [ListQueue].
+///
+/// Considers any add or remove operation a concurrent modification.
class _ListQueueIterator<E> implements Iterator<E> {
final ListQueue<E> _queue;
final int _end;
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index 4f21b77..7508b23 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.dart
@@ -2,28 +2,24 @@
// 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.
-/**
- * Base implementations of [Set].
- */
+/// Base implementations of [Set].
part of dart.collection;
-/**
- * Mixin implementation of [Set].
- *
- * This class provides a base implementation of a `Set` that depends only
- * on the abstract members: [add], [contains], [lookup], [remove],
- * [iterator], [length] and [toSet].
- *
- * Some of the methods assume that `toSet` creates a modifiable set.
- * If using this mixin for an unmodifiable set,
- * where `toSet` should return an unmodifiable set,
- * it's necessary to reimplement
- * [retainAll], [union], [intersection] and [difference].
- *
- * Implementations of `Set` using this mixin should consider also implementing
- * `clear` in constant time. The default implementation works by removing every
- * element.
- */
+/// Mixin implementation of [Set].
+///
+/// This class provides a base implementation of a `Set` that depends only
+/// on the abstract members: [add], [contains], [lookup], [remove],
+/// [iterator], [length] and [toSet].
+///
+/// Some of the methods assume that `toSet` creates a modifiable set.
+/// If using this mixin for an unmodifiable set,
+/// where `toSet` should return an unmodifiable set,
+/// it's necessary to reimplement
+/// [retainAll], [union], [intersection] and [difference].
+///
+/// Implementations of `Set` using this mixin should consider also implementing
+/// `clear` in constant time. The default implementation works by removing every
+/// element.
abstract class SetMixin<E> implements Set<E> {
// This class reimplements all of [IterableMixin].
// If/when Dart mixins get more powerful, we should just create a single
@@ -49,9 +45,9 @@
Set<R> cast<R>() => Set.castFrom<E, R>(this);
Iterable<E> followedBy(Iterable<E> other) =>
- new FollowedByIterable<E>.firstEfficient(this, other);
+ FollowedByIterable<E>.firstEfficient(this, other);
- Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+ Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
void clear() {
removeAll(toList());
@@ -118,15 +114,15 @@
return result;
}
- List<E> toList({bool growable: true}) {
- List<E> result = growable ? (<E>[]..length = length) : new List<E>(length);
+ List<E> toList({bool growable = true}) {
+ List<E> result = growable ? (<E>[]..length = length) : List<E>(length);
int i = 0;
for (E element in this) result[i++] = element;
return result;
}
Iterable<T> map<T>(T f(E element)) =>
- new EfficientLengthMappedIterable<E, T>(this, f);
+ EfficientLengthMappedIterable<E, T>(this, f);
E get single {
if (length > 1) throw IterableElementError.tooMany();
@@ -141,10 +137,10 @@
// Copied from IterableMixin.
// Should be inherited if we had multi-level mixins.
- Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
+ Iterable<E> where(bool f(E element)) => WhereIterable<E>(this, f);
Iterable<T> expand<T>(Iterable<T> f(E element)) =>
- new ExpandIterable<E, T>(this, f);
+ ExpandIterable<E, T>(this, f);
void forEach(void f(E element)) {
for (E element in this) f(element);
@@ -178,7 +174,7 @@
String join([String separator = ""]) {
Iterator<E> iterator = this.iterator;
if (!iterator.moveNext()) return "";
- StringBuffer buffer = new StringBuffer();
+ StringBuffer buffer = StringBuffer();
if (separator == null || separator == "") {
do {
buffer.write(iterator.current);
@@ -201,19 +197,19 @@
}
Iterable<E> take(int n) {
- return new TakeIterable<E>(this, n);
+ return TakeIterable<E>(this, n);
}
Iterable<E> takeWhile(bool test(E value)) {
- return new TakeWhileIterable<E>(this, test);
+ return TakeWhileIterable<E>(this, test);
}
Iterable<E> skip(int n) {
- return new SkipIterable<E>(this, n);
+ return SkipIterable<E>(this, n);
}
Iterable<E> skipWhile(bool test(E value)) {
- return new SkipWhileIterable<E>(this, test);
+ return SkipWhileIterable<E>(this, test);
}
E get first {
@@ -283,39 +279,35 @@
if (index == elementIndex) return element;
elementIndex++;
}
- throw new RangeError.index(index, this, "index", null, elementIndex);
+ throw RangeError.index(index, this, "index", null, elementIndex);
}
}
-/**
- * Base implementation of [Set].
- *
- * This class provides a base implementation of a `Set` that depends only
- * on the abstract members: [add], [contains], [lookup], [remove],
- * [iterator], [length] and [toSet].
- *
- * Some of the methods assume that `toSet` creates a modifiable set.
- * If using this base class for an unmodifiable set,
- * where `toSet` should return an unmodifiable set,
- * it's necessary to reimplement
- * [retainAll], [union], [intersection] and [difference].
- *
- * Implementations of `Set` using this base should consider also implementing
- * `clear` in constant time. The default implementation works by removing every
- * element.
- */
+/// Base implementation of [Set].
+///
+/// This class provides a base implementation of a `Set` that depends only
+/// on the abstract members: [add], [contains], [lookup], [remove],
+/// [iterator], [length] and [toSet].
+///
+/// Some of the methods assume that `toSet` creates a modifiable set.
+/// If using this base class for an unmodifiable set,
+/// where `toSet` should return an unmodifiable set,
+/// it's necessary to reimplement
+/// [retainAll], [union], [intersection] and [difference].
+///
+/// Implementations of `Set` using this base should consider also implementing
+/// `clear` in constant time. The default implementation works by removing every
+/// element.
abstract class SetBase<E> extends Object with SetMixin<E> {
- /**
- * Convert a `Set` to a string as `{each, element, as, string}`.
- *
- * Handles circular references where converting one of the elements
- * to a string ends up converting [set] to a string again.
- */
+ /// Convert a `Set` to a string as `{each, element, as, string}`.
+ ///
+ /// Handles circular references where converting one of the elements
+ /// to a string ends up converting [set] to a string again.
static String setToString(Set set) =>
IterableBase.iterableToFullString(set, '{', '}');
}
-/** Common internal implementation of some [Set] methods. */
+/// Common internal implementation of some [Set] methods.
// TODO(35548): Make this mix-in SetMixin, by adding `with SetMixin<E>`
// and removing the copied members below,
// when analyzer supports const constructors for mixin applications.
@@ -358,9 +350,9 @@
bool get isNotEmpty => length != 0;
Iterable<E> followedBy(Iterable<E> other) =>
- new FollowedByIterable<E>.firstEfficient(this, other);
+ FollowedByIterable<E>.firstEfficient(this, other);
- Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+ Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
void clear() {
removeAll(toList());
@@ -411,15 +403,15 @@
return toSet()..addAll(other);
}
- List<E> toList({bool growable: true}) {
- List<E> result = growable ? (<E>[]..length = length) : new List<E>(length);
+ List<E> toList({bool growable = true}) {
+ List<E> result = growable ? (<E>[]..length = length) : List<E>(length);
int i = 0;
for (E element in this) result[i++] = element;
return result;
}
Iterable<T> map<T>(T f(E element)) =>
- new EfficientLengthMappedIterable<E, T>(this, f);
+ EfficientLengthMappedIterable<E, T>(this, f);
E get single {
if (length > 1) throw IterableElementError.tooMany();
@@ -431,10 +423,10 @@
String toString() => IterableBase.iterableToFullString(this, '{', '}');
- Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
+ Iterable<E> where(bool f(E element)) => WhereIterable<E>(this, f);
Iterable<T> expand<T>(Iterable<T> f(E element)) =>
- new ExpandIterable<E, T>(this, f);
+ ExpandIterable<E, T>(this, f);
void forEach(void f(E element)) {
for (E element in this) f(element);
@@ -468,7 +460,7 @@
String join([String separator = ""]) {
Iterator<E> iterator = this.iterator;
if (!iterator.moveNext()) return "";
- StringBuffer buffer = new StringBuffer();
+ StringBuffer buffer = StringBuffer();
if (separator == null || separator == "") {
do {
buffer.write(iterator.current);
@@ -491,19 +483,19 @@
}
Iterable<E> take(int n) {
- return new TakeIterable<E>(this, n);
+ return TakeIterable<E>(this, n);
}
Iterable<E> takeWhile(bool test(E value)) {
- return new TakeWhileIterable<E>(this, test);
+ return TakeWhileIterable<E>(this, test);
}
Iterable<E> skip(int n) {
- return new SkipIterable<E>(this, n);
+ return SkipIterable<E>(this, n);
}
Iterable<E> skipWhile(bool test(E value)) {
- return new SkipWhileIterable<E>(this, test);
+ return SkipWhileIterable<E>(this, test);
}
E get first {
@@ -573,11 +565,11 @@
if (index == elementIndex) return element;
elementIndex++;
}
- throw new RangeError.index(index, this, "index", null, elementIndex);
+ throw RangeError.index(index, this, "index", null, elementIndex);
}
}
-/** Class used to implement const sets. */
+/// Class used to implement const sets.
class _UnmodifiableSet<E> extends _SetBase<E> {
final Map<E, Null> _map;
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 9856d55..5f71934 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -4,12 +4,10 @@
part of dart.collection;
-typedef bool _Predicate<T>(T value);
+typedef _Predicate<T> = bool Function(T value);
-/**
- * A node in a splay tree. It holds the sorting key and the left
- * and right children in the tree.
- */
+/// A node in a splay tree. It holds the sorting key and the left
+/// and right children in the tree.
class _SplayTreeNode<K> {
final K key;
_SplayTreeNode<K> left;
@@ -18,24 +16,20 @@
_SplayTreeNode(this.key);
}
-/**
- * A node in a splay tree based map.
- *
- * A [_SplayTreeNode] that also contains a value
- */
+/// A node in a splay tree based map.
+///
+/// A [_SplayTreeNode] that also contains a value
class _SplayTreeMapNode<K, V> extends _SplayTreeNode<K> {
V value;
_SplayTreeMapNode(K key, this.value) : super(key);
}
-/**
- * A splay tree is a self-balancing binary search tree.
- *
- * It has the additional property that recently accessed elements
- * are quick to access again.
- * It performs basic operations such as insertion, look-up and
- * removal, in O(log(n)) amortized time.
- */
+/// A splay tree is a self-balancing binary search tree.
+///
+/// It has the additional property that recently accessed elements
+/// are quick to access again.
+/// It performs basic operations such as insertion, look-up and
+/// removal, in O(log(n)) amortized time.
abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
// The root node of the splay tree. It will contain either the last
// element inserted or the last element looked up.
@@ -49,40 +43,34 @@
// Number of elements in the splay tree.
int _count = 0;
- /**
- * Counter incremented whenever the keys in the map changes.
- *
- * Used to detect concurrent modifications.
- */
+ /// Counter incremented whenever the keys in the map changes.
+ ///
+ /// Used to detect concurrent modifications.
int _modificationCount = 0;
- /**
- * Counter incremented whenever the tree structure changes.
- *
- * Used to detect that an in-place traversal cannot use
- * cached information that relies on the tree structure.
- */
+ /// Counter incremented whenever the tree structure changes.
+ ///
+ /// Used to detect that an in-place traversal cannot use
+ /// cached information that relies on the tree structure.
int _splayCount = 0;
- /** The comparator that is used for this splay tree. */
+ /// The comparator that is used for this splay tree.
Comparator<K> get _comparator;
- /** The predicate to determine that a given object is a valid key. */
+ /// The predicate to determine that a given object is a valid key.
_Predicate get _validKey;
- /** Comparison used to compare keys. */
+ /// Comparison used to compare keys.
int _compare(K key1, K key2);
- /**
- * Perform the splay operation for the given key. Moves the node with
- * the given key to the top of the tree. If no node has the given
- * key, the last node on the search path is moved to the top of the
- * tree. This is the simplified top-down splaying algorithm from:
- * "Self-adjusting Binary Search Trees" by Sleator and Tarjan.
- *
- * Returns the result of comparing the new root of the tree to [key].
- * Returns -1 if the table is empty.
- */
+ /// Perform the splay operation for the given key. Moves the node with
+ /// the given key to the top of the tree. If no node has the given
+ /// key, the last node on the search path is moved to the top of the
+ /// tree. This is the simplified top-down splaying algorithm from:
+ /// "Self-adjusting Binary Search Trees" by Sleator and Tarjan.
+ ///
+ /// Returns the result of comparing the new root of the tree to [key].
+ /// Returns -1 if the table is empty.
int _splay(K key) {
if (_root == null) return -1;
@@ -177,12 +165,10 @@
return result;
}
- /**
- * Adds a new root node with the given [key] or [value].
- *
- * The [comp] value is the result of comparing the existing root's key
- * with key.
- */
+ /// Adds a new root node with the given [key] or [value].
+ ///
+ /// The [comp] value is the result of comparing the existing root's key
+ /// with key.
void _addNewRoot(Node node, int comp) {
_count++;
_modificationCount++;
@@ -239,34 +225,31 @@
return _dynamicCompare;
}
-/**
- * A [Map] of objects that can be ordered relative to each other.
- *
- * The map is based on a self-balancing binary tree. It allows most operations
- * in amortized logarithmic time.
- *
- * Keys of the map are compared using the `compare` function passed in
- * the constructor, both for ordering and for equality.
- * If the map contains only the key `a`, then `map.containsKey(b)`
- * will return `true` if and only if `compare(a, b) == 0`,
- * and the value of `a == b` is not even checked.
- * If the compare function is omitted, the objects are assumed to be
- * [Comparable], and are compared using their [Comparable.compareTo] method.
- * Non-comparable objects (including `null`) will not work as keys
- * in that case.
- *
- * To allow calling [operator []], [remove] or [containsKey] with objects
- * that are not supported by the `compare` function, an extra `isValidKey`
- * predicate function can be supplied. This function is tested before
- * using the `compare` function on an argument value that may not be a [K]
- * value. If omitted, the `isValidKey` function defaults to testing if the
- * value is a [K].
- */
+/// A [Map] of objects that can be ordered relative to each other.
+///
+/// The map is based on a self-balancing binary tree. It allows most operations
+/// in amortized logarithmic time.
+///
+/// Keys of the map are compared using the `compare` function passed in
+/// the constructor, both for ordering and for equality.
+/// If the map contains only the key `a`, then `map.containsKey(b)`
+/// will return `true` if and only if `compare(a, b) == 0`,
+/// and the value of `a == b` is not even checked.
+/// If the compare function is omitted, the objects are assumed to be
+/// [Comparable], and are compared using their [Comparable.compareTo] method.
+/// Non-comparable objects (including `null`) will not work as keys
+/// in that case.
+///
+/// To allow calling [operator []], [remove] or [containsKey] with objects
+/// that are not supported by the `compare` function, an extra `isValidKey`
+/// predicate function can be supplied. This function is tested before
+/// using the `compare` function on an argument value that may not be a [K]
+/// value. If omitted, the `isValidKey` function defaults to testing if the
+/// value is a [K].
class SplayTreeMap<K, V> extends _SplayTree<K, _SplayTreeMapNode<K, V>>
with MapMixin<K, V> {
_SplayTreeMapNode<K, V> _root;
- final _SplayTreeMapNode<K, V> _dummy =
- new _SplayTreeMapNode<K, V>(null, null);
+ final _SplayTreeMapNode<K, V> _dummy = _SplayTreeMapNode<K, V>(null, null);
Comparator<K> _comparator;
_Predicate _validKey;
@@ -275,65 +258,57 @@
: _comparator = compare ?? _defaultCompare<K>(),
_validKey = isValidKey ?? ((v) => v is K);
- /**
- * Creates a [SplayTreeMap] that contains all key/value pairs of [other].
- *
- * The keys must all be instances of [K] and the values of [V].
- * The [other] map itself can have any type.
- */
+ /// Creates a [SplayTreeMap] that contains all key/value pairs of [other].
+ ///
+ /// The keys must all be instances of [K] and the values of [V].
+ /// The [other] map itself can have any type.
factory SplayTreeMap.from(Map other,
[int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
- SplayTreeMap<K, V> result = new SplayTreeMap<K, V>(compare, isValidKey);
+ SplayTreeMap<K, V> result = SplayTreeMap<K, V>(compare, isValidKey);
other.forEach((k, v) {
result[k] = v;
});
return result;
}
- /**
- * Creates a [SplayTreeMap] that contains all key/value pairs of [other].
- */
+ /// Creates a [SplayTreeMap] that contains all key/value pairs of [other].
factory SplayTreeMap.of(Map<K, V> other,
[int compare(K key1, K key2), bool isValidKey(potentialKey)]) =>
- new SplayTreeMap<K, V>(compare, isValidKey)..addAll(other);
+ SplayTreeMap<K, V>(compare, isValidKey)..addAll(other);
- /**
- * Creates a [SplayTreeMap] where the keys and values are computed from the
- * [iterable].
- *
- * For each element of the [iterable] this constructor computes a key/value
- * pair, by applying [key] and [value] respectively.
- *
- * The keys of the key/value pairs do not need to be unique. The last
- * occurrence of a key will simply overwrite any previous value.
- *
- * If no functions are specified for [key] and [value] the default is to
- * use the iterable value itself.
- */
+ /// Creates a [SplayTreeMap] where the keys and values are computed from the
+ /// [iterable].
+ ///
+ /// For each element of the [iterable] this constructor computes a key/value
+ /// pair, by applying [key] and [value] respectively.
+ ///
+ /// The keys of the key/value pairs do not need to be unique. The last
+ /// occurrence of a key will simply overwrite any previous value.
+ ///
+ /// If no functions are specified for [key] and [value] the default is to
+ /// use the iterable value itself.
factory SplayTreeMap.fromIterable(Iterable iterable,
{K key(element),
V value(element),
int compare(K key1, K key2),
bool isValidKey(potentialKey)}) {
- SplayTreeMap<K, V> map = new SplayTreeMap<K, V>(compare, isValidKey);
+ SplayTreeMap<K, V> map = SplayTreeMap<K, V>(compare, isValidKey);
MapBase._fillMapWithMappedIterable(map, iterable, key, value);
return map;
}
- /**
- * Creates a [SplayTreeMap] associating the given [keys] to [values].
- *
- * This constructor iterates over [keys] and [values] and maps each element of
- * [keys] to the corresponding element of [values].
- *
- * If [keys] contains the same object multiple times, the last occurrence
- * overwrites the previous value.
- *
- * It is an error if the two [Iterable]s don't have the same length.
- */
+ /// Creates a [SplayTreeMap] associating the given [keys] to [values].
+ ///
+ /// This constructor iterates over [keys] and [values] and maps each element
+ /// of [keys] to the corresponding element of [values].
+ ///
+ /// If [keys] contains the same object multiple times, the last occurrence
+ /// overwrites the previous value.
+ ///
+ /// It is an error if the two [Iterable]s don't have the same length.
factory SplayTreeMap.fromIterables(Iterable<K> keys, Iterable<V> values,
[int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
- SplayTreeMap<K, V> map = new SplayTreeMap<K, V>(compare, isValidKey);
+ SplayTreeMap<K, V> map = SplayTreeMap<K, V>(compare, isValidKey);
MapBase._fillMapWithIterables(map, keys, values);
return map;
}
@@ -361,7 +336,7 @@
}
void operator []=(K key, V value) {
- if (key == null) throw new ArgumentError(key);
+ if (key == null) throw ArgumentError(key);
// Splay on the key to move the last node on the search path for
// the key to the root of the tree.
int comp = _splay(key);
@@ -369,11 +344,11 @@
_root.value = value;
return;
}
- _addNewRoot(new _SplayTreeMapNode(key, value), comp);
+ _addNewRoot(_SplayTreeMapNode(key, value), comp);
}
V putIfAbsent(K key, V ifAbsent()) {
- if (key == null) throw new ArgumentError(key);
+ if (key == null) throw ArgumentError(key);
int comp = _splay(key);
if (comp == 0) {
return _root.value;
@@ -382,14 +357,14 @@
int splayCount = _splayCount;
V value = ifAbsent();
if (modificationCount != _modificationCount) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
if (splayCount != _splayCount) {
comp = _splay(key);
// Key is still not there, otherwise _modificationCount would be changed.
assert(comp != 0);
}
- _addNewRoot(new _SplayTreeMapNode(key, value), comp);
+ _addNewRoot(_SplayTreeMapNode(key, value), comp);
return value;
}
@@ -406,7 +381,7 @@
bool get isNotEmpty => !isEmpty;
void forEach(void f(K key, V value)) {
- Iterator<_SplayTreeNode<K>> nodes = new _SplayTreeNodeIterator<K>(this);
+ Iterator<_SplayTreeNode<K>> nodes = _SplayTreeNodeIterator<K>(this);
while (nodes.moveNext()) {
_SplayTreeMapNode<K, V> node = nodes.current;
f(node.key, node.value);
@@ -431,7 +406,7 @@
while (node != null) {
if (node.value == value) return true;
if (initialSplayCount != _splayCount) {
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
if (node.right != null && visit(node.right)) return true;
node = node.left;
@@ -442,32 +417,26 @@
return visit(_root);
}
- Iterable<K> get keys => new _SplayTreeKeyIterable<K>(this);
+ Iterable<K> get keys => _SplayTreeKeyIterable<K>(this);
- Iterable<V> get values => new _SplayTreeValueIterable<K, V>(this);
+ Iterable<V> get values => _SplayTreeValueIterable<K, V>(this);
- /**
- * Get the first key in the map. Returns [:null:] if the map is empty.
- */
+ /// Get the first key in the map. Returns [:null:] if the map is empty.
K firstKey() {
if (_root == null) return null;
return _first.key;
}
- /**
- * Get the last key in the map. Returns [:null:] if the map is empty.
- */
+ /// Get the last key in the map. Returns [:null:] if the map is empty.
K lastKey() {
if (_root == null) return null;
return _last.key;
}
- /**
- * Get the last key in the map that is strictly smaller than [key]. Returns
- * [:null:] if no key was not found.
- */
+ /// Get the last key in the map that is strictly smaller than [key]. Returns
+ /// [:null:] if no key was not found.
K lastKeyBefore(K key) {
- if (key == null) throw new ArgumentError(key);
+ if (key == null) throw ArgumentError(key);
if (_root == null) return null;
int comp = _splay(key);
if (comp < 0) return _root.key;
@@ -479,12 +448,10 @@
return node.key;
}
- /**
- * Get the first key in the map that is strictly larger than [key]. Returns
- * [:null:] if no key was not found.
- */
+ /// Get the first key in the map that is strictly larger than [key]. Returns
+ /// [:null:] if no key was not found.
K firstKeyAfter(K key) {
- if (key == null) throw new ArgumentError(key);
+ if (key == null) throw ArgumentError(key);
if (_root == null) return null;
int comp = _splay(key);
if (comp > 0) return _root.key;
@@ -499,37 +466,32 @@
abstract class _SplayTreeIterator<K, T> implements Iterator<T> {
final _SplayTree<K, _SplayTreeNode<K>> _tree;
- /**
- * Worklist of nodes to visit.
- *
- * These nodes have been passed over on the way down in a
- * depth-first left-to-right traversal. Visiting each node,
- * and their right subtrees will visit the remainder of
- * the nodes of a full traversal.
- *
- * Only valid as long as the original tree isn't reordered.
- */
+
+ /// Worklist of nodes to visit.
+ ///
+ /// These nodes have been passed over on the way down in a
+ /// depth-first left-to-right traversal. Visiting each node,
+ /// and their right subtrees will visit the remainder of
+ /// the nodes of a full traversal.
+ ///
+ /// Only valid as long as the original tree isn't reordered.
final List<_SplayTreeNode<K>> _workList = <_SplayTreeNode<K>>[];
- /**
- * Original modification counter of [_tree].
- *
- * Incremented on [_tree] when a key is added or removed.
- * If it changes, iteration is aborted.
- *
- * Not final because some iterators may modify the tree knowingly,
- * and they update the modification count in that case.
- */
+ /// Original modification counter of [_tree].
+ ///
+ /// Incremented on [_tree] when a key is added or removed.
+ /// If it changes, iteration is aborted.
+ ///
+ /// Not final because some iterators may modify the tree knowingly,
+ /// and they update the modification count in that case.
int _modificationCount;
- /**
- * Count of splay operations on [_tree] when [_workList] was built.
- *
- * If the splay count on [_tree] increases, [_workList] becomes invalid.
- */
+ /// Count of splay operations on [_tree] when [_workList] was built.
+ ///
+ /// If the splay count on [_tree] increases, [_workList] becomes invalid.
int _splayCount;
- /** Current node. */
+ /// Current node.
_SplayTreeNode<K> _currentNode;
_SplayTreeIterator(_SplayTree<K, _SplayTreeNode<K>> tree)
@@ -565,14 +527,12 @@
}
}
- /**
- * Called when the tree structure of the tree has changed.
- *
- * This can be caused by a splay operation.
- * If the key-set changes, iteration is aborted before getting
- * here, so we know that the keys are the same as before, it's
- * only the tree that has been reordered.
- */
+ /// Called when the tree structure of the tree has changed.
+ ///
+ /// This can be caused by a splay operation.
+ /// If the key-set changes, iteration is aborted before getting
+ /// here, so we know that the keys are the same as before, it's
+ /// only the tree that has been reordered.
void _rebuildWorkList(_SplayTreeNode<K> currentNode) {
assert(_workList.isNotEmpty);
_workList.clear();
@@ -587,7 +547,7 @@
bool moveNext() {
if (_modificationCount != _tree._modificationCount) {
- throw new ConcurrentModificationError(_tree);
+ throw ConcurrentModificationError(_tree);
}
// Picks the next element in the worklist as current.
// Updates the worklist with the left-most path of the current node's
@@ -614,11 +574,10 @@
_SplayTreeKeyIterable(this._tree);
int get length => _tree._count;
bool get isEmpty => _tree._count == 0;
- Iterator<K> get iterator => new _SplayTreeKeyIterator<K>(_tree);
+ Iterator<K> get iterator => _SplayTreeKeyIterator<K>(_tree);
Set<K> toSet() {
- SplayTreeSet<K> set =
- new SplayTreeSet<K>(_tree._comparator, _tree._validKey);
+ SplayTreeSet<K> set = SplayTreeSet<K>(_tree._comparator, _tree._validKey);
set._count = _tree._count;
set._root = set._copyNode(_tree._root);
return set;
@@ -630,7 +589,7 @@
_SplayTreeValueIterable(this._map);
int get length => _map._count;
bool get isEmpty => _map._count == 0;
- Iterator<V> get iterator => new _SplayTreeValueIterator<K, V>(_map);
+ Iterator<V> get iterator => _SplayTreeValueIterator<K, V>(_map);
}
class _SplayTreeKeyIterator<K> extends _SplayTreeIterator<K, K> {
@@ -655,76 +614,70 @@
_SplayTreeNode<K> _getValue(_SplayTreeNode<K> node) => node;
}
-/**
- * A [Set] of objects that can be ordered relative to each other.
- *
- * The set is based on a self-balancing binary tree. It allows most operations
- * in amortized logarithmic time.
- *
- * Elements of the set are compared using the `compare` function passed in
- * the constructor, both for ordering and for equality.
- * If the set contains only an object `a`, then `set.contains(b)`
- * will return `true` if and only if `compare(a, b) == 0`,
- * and the value of `a == b` is not even checked.
- * If the compare function is omitted, the objects are assumed to be
- * [Comparable], and are compared using their [Comparable.compareTo] method.
- * Non-comparable objects (including `null`) will not work as an element
- * in that case.
- */
+/// A [Set] of objects that can be ordered relative to each other.
+///
+/// The set is based on a self-balancing binary tree. It allows most operations
+/// in amortized logarithmic time.
+///
+/// Elements of the set are compared using the `compare` function passed in
+/// the constructor, both for ordering and for equality.
+/// If the set contains only an object `a`, then `set.contains(b)`
+/// will return `true` if and only if `compare(a, b) == 0`,
+/// and the value of `a == b` is not even checked.
+/// If the compare function is omitted, the objects are assumed to be
+/// [Comparable], and are compared using their [Comparable.compareTo] method.
+/// Non-comparable objects (including `null`) will not work as an element
+/// in that case.
class SplayTreeSet<E> extends _SplayTree<E, _SplayTreeNode<E>>
with IterableMixin<E>, SetMixin<E> {
_SplayTreeNode<E> _root;
- final _SplayTreeNode<E> _dummy = new _SplayTreeNode<E>(null);
+ final _SplayTreeNode<E> _dummy = _SplayTreeNode<E>(null);
Comparator<E> _comparator;
_Predicate _validKey;
- /**
- * Create a new [SplayTreeSet] with the given compare function.
- *
- * If the [compare] function is omitted, it defaults to [Comparable.compare],
- * and the elements must be comparable.
- *
- * A provided `compare` function may not work on all objects. It may not even
- * work on all `E` instances.
- *
- * For operations that add elements to the set, the user is supposed to not
- * pass in objects that doesn't work with the compare function.
- *
- * The methods [contains], [remove], [lookup], [removeAll] or [retainAll]
- * are typed to accept any object(s), and the [isValidKey] test can used to
- * filter those objects before handing them to the `compare` function.
- *
- * If [isValidKey] is provided, only values satisfying `isValidKey(other)`
- * are compared using the `compare` method in the methods mentioned above.
- * If the `isValidKey` function returns false for an object, it is assumed to
- * not be in the set.
- *
- * If omitted, the `isValidKey` function defaults to checking against the
- * type parameter: `other is E`.
- */
+ /// Create a new [SplayTreeSet] with the given compare function.
+ ///
+ /// If the [compare] function is omitted, it defaults to [Comparable.compare],
+ /// and the elements must be comparable.
+ ///
+ /// A provided `compare` function may not work on all objects. It may not even
+ /// work on all `E` instances.
+ ///
+ /// For operations that add elements to the set, the user is supposed to not
+ /// pass in objects that doesn't work with the compare function.
+ ///
+ /// The methods [contains], [remove], [lookup], [removeAll] or [retainAll]
+ /// are typed to accept any object(s), and the [isValidKey] test can used to
+ /// filter those objects before handing them to the `compare` function.
+ ///
+ /// If [isValidKey] is provided, only values satisfying `isValidKey(other)`
+ /// are compared using the `compare` method in the methods mentioned above.
+ /// If the `isValidKey` function returns false for an object, it is assumed to
+ /// not be in the set.
+ ///
+ /// If omitted, the `isValidKey` function defaults to checking against the
+ /// type parameter: `other is E`.
SplayTreeSet([int compare(E key1, E key2), bool isValidKey(potentialKey)])
: _comparator = compare ?? _defaultCompare<E>(),
_validKey = isValidKey ?? ((v) => v is E);
- /**
- * Creates a [SplayTreeSet] that contains all [elements].
- *
- * The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
- *
- * All the [elements] should be instances of [E] and valid arguments to
- * [compare].
- * The `elements` iterable itself may have any element type, so this
- * constructor can be used to down-cast a `Set`, for example as:
- * ```dart
- * Set<SuperType> superSet = ...;
- * Set<SubType> subSet =
- * new SplayTreeSet<SubType>.from(superSet.whereType<SubType>());
- * ```
- */
+ /// Creates a [SplayTreeSet] that contains all [elements].
+ ///
+ /// The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
+ ///
+ /// All the [elements] should be instances of [E] and valid arguments to
+ /// [compare].
+ /// The `elements` iterable itself may have any element type, so this
+ /// constructor can be used to down-cast a `Set`, for example as:
+ /// ```dart
+ /// Set<SuperType> superSet = ...;
+ /// Set<SubType> subSet =
+ /// new SplayTreeSet<SubType>.from(superSet.whereType<SubType>());
+ /// ```
factory SplayTreeSet.from(Iterable elements,
[int compare(E key1, E key2), bool isValidKey(potentialKey)]) {
- SplayTreeSet<E> result = new SplayTreeSet<E>(compare, isValidKey);
+ SplayTreeSet<E> result = SplayTreeSet<E>(compare, isValidKey);
for (final element in elements) {
E e = element;
result.add(e);
@@ -732,26 +685,24 @@
return result;
}
- /**
- * Creates a [SplayTreeSet] from [elements].
- *
- * The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
- *
- * All the [elements] should be valid as arguments to the [compare] function.
- */
+ /// Creates a [SplayTreeSet] from [elements].
+ ///
+ /// The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
+ ///
+ /// All the [elements] should be valid as arguments to the [compare] function.
factory SplayTreeSet.of(Iterable<E> elements,
[int compare(E key1, E key2), bool isValidKey(potentialKey)]) =>
- new SplayTreeSet(compare, isValidKey)..addAll(elements);
+ SplayTreeSet(compare, isValidKey)..addAll(elements);
Set<T> _newSet<T>() =>
- new SplayTreeSet<T>((T a, T b) => _comparator(a as E, b as E), _validKey);
+ SplayTreeSet<T>((T a, T b) => _comparator(a as E, b as E), _validKey);
Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newSet);
int _compare(E e1, E e2) => _comparator(e1, e2);
// From Iterable.
- Iterator<E> get iterator => new _SplayTreeKeyIterator<E>(this);
+ Iterator<E> get iterator => _SplayTreeKeyIterator<E>(this);
int get length => _count;
bool get isEmpty => _root == null;
@@ -781,7 +732,7 @@
bool add(E element) {
int compare = _splay(element);
if (compare == 0) return false;
- _addNewRoot(new _SplayTreeNode(element), compare);
+ _addNewRoot(_SplayTreeNode(element), compare);
return true;
}
@@ -794,7 +745,7 @@
for (E element in elements) {
int compare = _splay(element);
if (compare != 0) {
- _addNewRoot(new _SplayTreeNode(element), compare);
+ _addNewRoot(_SplayTreeNode(element), compare);
}
}
}
@@ -807,12 +758,12 @@
void retainAll(Iterable<Object> elements) {
// Build a set with the same sense of equality as this set.
- SplayTreeSet<E> retainSet = new SplayTreeSet<E>(_comparator, _validKey);
+ SplayTreeSet<E> retainSet = SplayTreeSet<E>(_comparator, _validKey);
int modificationCount = _modificationCount;
for (Object object in elements) {
if (modificationCount != _modificationCount) {
// The iterator should not have side effects.
- throw new ConcurrentModificationError(this);
+ throw ConcurrentModificationError(this);
}
// Equivalent to this.contains(object).
if (_validKey(object) && _splay(object) == 0) {
@@ -835,7 +786,7 @@
}
Set<E> intersection(Set<Object> other) {
- Set<E> result = new SplayTreeSet<E>(_comparator, _validKey);
+ Set<E> result = SplayTreeSet<E>(_comparator, _validKey);
for (E element in this) {
if (other.contains(element)) result.add(element);
}
@@ -843,7 +794,7 @@
}
Set<E> difference(Set<Object> other) {
- Set<E> result = new SplayTreeSet<E>(_comparator, _validKey);
+ Set<E> result = SplayTreeSet<E>(_comparator, _validKey);
for (E element in this) {
if (!other.contains(element)) result.add(element);
}
@@ -855,7 +806,7 @@
}
SplayTreeSet<E> _clone() {
- var set = new SplayTreeSet<E>(_comparator, _validKey);
+ var set = SplayTreeSet<E>(_comparator, _validKey);
set._count = _count;
set._root = _copyNode(_root);
return set;
@@ -865,7 +816,7 @@
// Works on _SplayTreeMapNode as well, but only copies the keys,
_SplayTreeNode<E> _copyNode(_SplayTreeNode<E> node) {
if (node == null) return null;
- return new _SplayTreeNode<E>(node.key)
+ return _SplayTreeNode<E>(node.key)
..left = _copyNode(node.left)
..right = _copyNode(node.right);
}
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index afad926..33b8177 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -100,6 +100,7 @@
* print(double.infinity < double.nan); // => false
* print(double.nan < double.infinity); // => false
* print(double.nan == double.infinity); // => false
+ * ```
*/
int compareTo(num other);
diff --git a/sdk/lib/developer/developer.dart b/sdk/lib/developer/developer.dart
index 6c3fa82..c446fdf 100644
--- a/sdk/lib/developer/developer.dart
+++ b/sdk/lib/developer/developer.dart
@@ -30,7 +30,7 @@
/// Returns the value of [when]. Some debuggers may display [message].
///
/// NOTE: When invoked, the isolate will not return until a debugger
-/// continues execution. When running in the Dart VM the behaviour is the same
+/// continues execution. When running in the Dart VM, the behaviour is the same
/// regardless of whether or not a debugger is connected. When compiled to
/// JavaScript, this uses the "debugger" statement, and behaves exactly as
/// that does.
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 6e43fb7..6a737fe 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -40,7 +40,7 @@
*
* An `Isolate` object is a reference to an isolate, usually different from
* the current isolate.
- * It represents, and can be used control, the other isolate.
+ * It represents, and can be used to control, the other isolate.
*
* When spawning a new isolate, the spawning isolate receives an `Isolate`
* object representing the new isolate when the spawn operation succeeds.
diff --git a/sdk/lib/vmservice/running_isolates.dart b/sdk/lib/vmservice/running_isolates.dart
index 5e7b6dd..24b155c 100644
--- a/sdk/lib/vmservice/running_isolates.dart
+++ b/sdk/lib/vmservice/running_isolates.dart
@@ -185,6 +185,7 @@
Map<String, dynamic> params = _setupParams();
params['isolateId'] = _message.params['isolateId'];
params['kernelBytes'] = kernelBase64;
+ params['disableBreakpoints'] = _message.params['disableBreakpoints'];
Map runParams = {
'method': '_evaluateCompiledExpression',
'id': _message.serial,
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index a4d8adc..25a153a 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -4,9 +4,13 @@
[ $compiler == dart2js ]
Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign
+LanguageFeatures/Control-flow-collections/*: Skip
LibTest/io/*: SkipByDesign # dart:io not supported.
LibTest/isolate/*: SkipByDesign # dart:isolate not supported.
+[ $compiler == dartdevk ]
+LanguageFeatures/Control-flow-collections/*: Skip
+
[ $builder_tag != run_webgl_tests && $compiler == dart2js ]
LayoutTests/fast/canvas/webgl*: Skip # Only run WebGL on special builders, issue 29961
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 3339868..f732f93 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -3,19 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
[ $compiler == dartk ]
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A02_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t02: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t02: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t02: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A02_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t02: DartkCrash, CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t01: DartkCrash
+LanguageFeatures/Control-flow-collections/*: Skip
LanguageFeatures/Set-literals/semantics_A05_t02: RuntimeError
LanguageFeatures/Set-literals/syntax_compatibility_A01_t02: RuntimeError
LanguageFeatures/Spread-collections/ConstSpreads_A01_t01: CompileTimeError
@@ -65,6 +53,7 @@
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t04: RuntimeError
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t05/none: RuntimeError
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t06/none: RuntimeError
+LanguageFeatures/Control-flow-collections/*: Skip
LanguageFeatures/Set-literals/semantics_A05_t02: RuntimeError
LanguageFeatures/Set-literals/syntax_compatibility_A01_t02: RuntimeError
LanguageFeatures/Spread-collections/ConstSpreads_A01_t01: DartkCrash
@@ -137,9 +126,88 @@
Language/Statements/For/syntax_t13: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
Language/Statements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: Crash
-LanguageFeatures/Spread-collections/Ambiguity_A01_t05/01: MissingCompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t05/02: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A03_t02/12: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A02_t03: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A02_t04: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/04: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/05: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/06: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/07: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/08: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/09: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/10: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/11: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/12: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/14: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A04_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A05_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A06_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A07_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A07_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/scoping_A01_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/scoping_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A01_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A01_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A01_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A02_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A02_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A02_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A03_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A03_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A03_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A04_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A04_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A04_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A04_t01/04: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/05: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/06: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/09: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/10: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/11: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/12: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/17: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/18: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/19: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/20: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/21: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/22: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/23: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/24: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A01_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A01_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A01_t03: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A02_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A03_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A01_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A04_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A05_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A06_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A08_t01: CompileTimeError
+LanguageFeatures/Spread-collections/Ambiguity_A02_t02/01: MissingCompileTimeError
+LanguageFeatures/Spread-collections/Ambiguity_A02_t03: CompileTimeError
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/01: MissingCompileTimeError
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/02: MissingCompileTimeError
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/03: MissingCompileTimeError
@@ -148,18 +216,17 @@
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/06: MissingCompileTimeError
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/07: MissingCompileTimeError
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/08: MissingCompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Map_A01_t01: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Map_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Map_A02_t03: CompileTimeError
+LanguageFeatures/Spread-collections/DynamicSemantics_Map_A02_t01: CompileTimeError
LanguageFeatures/Spread-collections/NullAware_A01_t01: CompileTimeError
LanguageFeatures/Spread-collections/NullAware_A01_t02: CompileTimeError
LanguageFeatures/Spread-collections/NullAware_A01_t03: CompileTimeError
LanguageFeatures/Spread-collections/NullAware_A01_t04: CompileTimeError
+LanguageFeatures/Spread-collections/NullAware_A01_t05: CompileTimeError
+LanguageFeatures/Spread-collections/NullAware_A01_t06: CompileTimeError
LanguageFeatures/Spread-collections/StaticSemantic_A04_t01/04: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/01: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/02: MissingCompileTimeError
+LanguageFeatures/Spread-collections/StaticSemantic_A04_t02/04: MissingCompileTimeError
LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/04: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/05: MissingCompileTimeError
+LanguageFeatures/Spread-collections/StaticSemantic_A08_t01/02: MissingCompileTimeError
[ $runtime == vm ]
LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Slow # Does many calls
@@ -243,12 +310,17 @@
Language/Expressions/Shift/syntax_t01: CompileTimeError
Language/Expressions/Unary_Expressions/syntax_t10: CompileTimeError
Language/Expressions/Unary_Expressions/syntax_t27: CompileTimeError
-Language/Generics/class_A01_t02/none: CompileTimeError
-Language/Generics/syntax_t21: CompileTimeError
+Language/Generics/syntax_t20: CompileTimeError
+Language/Generics/syntax_t22: CompileTimeError
Language/Generics/syntax_t23: CompileTimeError
Language/Generics/syntax_t24: CompileTimeError
Language/Generics/syntax_t25: CompileTimeError
-Language/Generics/syntax_t26: CompileTimeError
+Language/Generics/syntax_t27/none: CompileTimeError
+Language/Generics/typedef_A01_t01: CompileTimeError
+Language/Generics/typedef_A01_t06/none: CompileTimeError
+Language/Generics/typedef_A01_t07: CompileTimeError
+Language/Generics/typedef_A01_t08: CompileTimeError
+Language/Generics/typedef_A01_t10: CompileTimeError
Language/Libraries_and_Scripts/Imports/library_name_t01: MissingCompileTimeError # Expects an error, but this is a warning in Dart 2
Language/Mixins/Mixin_Application/abstract_t09: Crash
Language/Mixins/Mixin_Application/abstract_t10: Crash
@@ -265,7 +337,14 @@
Language/Mixins/Mixin_Application/interfaces_t07: Crash
Language/Mixins/Mixin_Application/static_warning_t01: MissingCompileTimeError # Mixin super equirement
Language/Mixins/Mixin_Application/superclass_t03: Crash
-Language/Mixins/Mixin_Application/superinterfaces_t07: MissingCompileTimeError
+Language/Mixins/Mixin_Application/superclass_t04: Crash
+Language/Mixins/Mixin_Application/superinterfaces_t10: Crash
+Language/Mixins/Mixin_Application/superinterfaces_t11: Crash
+Language/Mixins/Mixin_Application/superinterfaces_t12: CompileTimeError
+Language/Mixins/Mixin_Application/superinterfaces_t13: Crash
+Language/Mixins/Mixin_Application/superinterfaces_t14: Crash
+Language/Mixins/Mixin_Application/syntax_t26: Crash
+Language/Mixins/Mixin_Application/warning_t04: Crash
Language/Mixins/declaring_constructor_t05: MissingCompileTimeError # Mixin constructor
Language/Mixins/declaring_constructor_t06: MissingCompileTimeError # Mixin constructor
Language/Overview/Privacy/private_and_public_t11: CompileTimeError
@@ -292,6 +371,41 @@
Language/Types/Type_Aliases/syntax_t02: CompileTimeError
Language/Types/Type_Aliases/syntax_t03: CompileTimeError
Language/Types/Type_Aliases/syntax_t04: CompileTimeError
+Language/Types/Type_Aliases/syntax_t20: CompileTimeError
+Language/Types/Type_Aliases/syntax_t21: CompileTimeError
+LanguageFeatures/Constant-update-2018/CastOperator_A01_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/CastOperator_A02_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/CastOperator_A02_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/CastOperator_A04_t02/none: CompileTimeError
+LanguageFeatures/Constant-update-2018/EqualityOperator_A01_t09: MissingCompileTimeError
+LanguageFeatures/Constant-update-2018/EqualityOperator_A01_t10: MissingCompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t05: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t06: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t09: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t10: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A01_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A01_t07: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A02_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A02_t08: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A03_t01: Crash
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A03_t02: Crash
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A03_t05: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A03_t06: CompileTimeError
+
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t03: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t05: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t06: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t07: CompileTimeError
+LanguageFeatures/Constant-update-2018/TypeTestOperator_A01_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/TypeTestOperator_A01_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/TypeTestOperator_A02_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/TypeTestOperator_A02_t02: CompileTimeError
LanguageFeatures/Constant_update2018/CastOperator_A01_t01: CompileTimeError
LanguageFeatures/Constant_update2018/CastOperator_A02_t01: CompileTimeError
LanguageFeatures/Constant_update2018/CastOperator_A02_t02: CompileTimeError
@@ -343,54 +457,6 @@
LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t04/none: CompileTimeError
LanguageFeatures/Constant_update2018/TypeTestOperator_A04_t01/none: CompileTimeError
LanguageFeatures/Constant_update2018/TypeTestOperator_A04_t02/none: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A01_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A02_t03: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A02_t04: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A05_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A06_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A07_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A07_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A07_t03: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A01_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A01_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A01_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/scoping_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/scoping_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A03_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A04_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A05_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A06_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A07_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A08_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A09_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A10_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A11_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_semantics_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_semantics_A01_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_semantics_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_semantics_A02_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A01_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A01_t03: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A02_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A03_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A03_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A04_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A05_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A06_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A07_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A08_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_promotion_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_promotion_A01_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t01: Crash
LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t02: CompileTimeError
LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t03: Crash
@@ -659,58 +725,14 @@
LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t04/01: MissingCompileTimeError
LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t04/02: MissingCompileTimeError
LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t10: CompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t01: CompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t03: CompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t05: MissingCompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t06: MissingCompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t07: CompileTimeError
LanguageFeatures/Spread-collections/Ambiguity_A02_t01/01: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A01_t02: CompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A03_t02/12: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/01: MissingCompileTimeError
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/02: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/03: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/04: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/05: MissingCompileTimeError
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/06: MissingCompileTimeError
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/07: MissingCompileTimeError
LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/08: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A06_t02: CompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A06_t03: CompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A07_t03: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t01: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t03: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t05: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t07: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t08: CompileTimeError
-LanguageFeatures/Spread-collections/NullAware_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/NullAware_A02_t03: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A01_t01: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A01_t03: CompileTimeError
LanguageFeatures/Spread-collections/StaticSemantic_A01_t05: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A01_t06: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A05_t01/none: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A05_t02/none: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/01: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/02: MissingCompileTimeError
LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/04: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/05: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A07_t01/none: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A08_t01/none: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A01_t03: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t01: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t04: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t06: CompileTimeError
LanguageFeatures/Spread-collections/Syntax_A02_t08: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t09: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t10: CompileTimeError
-LanguageFeatures/Spread-collections/TypeInference_A01_t01: CompileTimeError
-LanguageFeatures/Spread-collections/TypeInference_A01_t02: CompileTimeError
-LanguageFeatures/Spread-collections/TypeInference_A02_t01: CompileTimeError
-LanguageFeatures/Spread-collections/TypeInference_A03_t01: CompileTimeError
LanguageFeatures/Super-mixins/covariance_t03: MissingCompileTimeError # Issue 35111
LanguageFeatures/Super-mixins/covariance_t06: MissingCompileTimeError # Issue 35111
LanguageFeatures/Super-mixins/covariance_t07: MissingCompileTimeError # Issue 35111
@@ -727,18 +749,6 @@
LanguageFeatures/Constant_update2018/NewOperators_A02_t02: Pass
LanguageFeatures/Constant_update2018/NewOperators_A02_t04: Pass
LanguageFeatures/Constant_update2018/NewOperators_A02_t05: Pass
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t01: CompileTimeError
LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # Issue http://dartbug.com/35242
LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # Issue http://dartbug.com/35242
LibTest/core/List/List_class_A01_t02: Crash # Issue http://dartbug.com/35242
@@ -819,34 +829,6 @@
LibTest/isolate/Isolate/ping_A03_t02: RuntimeError, Pass
LibTest/isolate/Isolate/removeErrorListener_A02_t01: Crash, Pass
-[ $arch != simdbc64 && $compiler == dartk ]
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/01: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/02: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/03: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/04: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/05: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/06: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/07: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/08: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/09: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/10: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/11: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/12: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/13: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/14: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/15: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/16: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/21: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/22: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/23: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/24: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/25: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/26: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/27: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/28: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/29: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/30: DartkCrash
-
[ $compiler != dart2js && $runtime != vm && $fasta ]
Language/Classes/Constructors/Constant_Constructors/invalid_constant_initializer_t02: MissingCompileTimeError # Issue 34192
Language/Expressions/Constants/exception_t01: MissingCompileTimeError # Issue 31936
@@ -887,49 +869,6 @@
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t01: Crash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t02: Crash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/01: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/02: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/03: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/04: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/05: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/06: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/07: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/08: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/09: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/10: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/11: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/12: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/13: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/14: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/15: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/16: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/17: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/18: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/19: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/20: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/21: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/22: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/23: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/24: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/25: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/26: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/27: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/28: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/29: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/30: Crash, Pass
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t01: CompileTimeError
[ $runtime == vm && $system == linux && ($compiler == dartk || $compiler == dartkb) ]
LibTest/io/Link/stat_A01_t01: RuntimeError
diff --git a/tests/compiler/dart2js/analyses/analysis_helper.dart b/tests/compiler/dart2js/analyses/analysis_helper.dart
index 715352e..6505445 100644
--- a/tests/compiler/dart2js/analyses/analysis_helper.dart
+++ b/tests/compiler/dart2js/analyses/analysis_helper.dart
@@ -69,6 +69,7 @@
}
class StaticTypeVisitorBase extends StaticTypeVisitor {
+ @override
VariableScopeModel variableScopeModel;
StaticTypeVisitorBase(
@@ -95,7 +96,7 @@
// Skip synthetic .dill members.
return;
}
- variableScopeModel = ScopeModel.computeScopeModel(node)?.variableScopeModel;
+ variableScopeModel = new ScopeModel.from(node).variableScopeModel;
super.visitProcedure(node);
variableScopeModel = null;
}
@@ -106,7 +107,7 @@
// Skip synthetic .dill members.
return;
}
- variableScopeModel = ScopeModel.computeScopeModel(node)?.variableScopeModel;
+ variableScopeModel = new ScopeModel.from(node).variableScopeModel;
super.visitField(node);
variableScopeModel = null;
}
@@ -117,7 +118,7 @@
// Skip synthetic .dill members.
return;
}
- variableScopeModel = ScopeModel.computeScopeModel(node)?.variableScopeModel;
+ variableScopeModel = new ScopeModel.from(node).variableScopeModel;
super.visitConstructor(node);
variableScopeModel = null;
}
@@ -291,6 +292,7 @@
}
}
+ @override
ir.DartType visitNode(ir.Node node) {
ir.DartType staticType = node?.accept(this);
assert(
diff --git a/tests/compiler/dart2js/analyses/api_allowed.json b/tests/compiler/dart2js/analyses/api_allowed.json
index 3139ef5..a7a08a3 100644
--- a/tests/compiler/dart2js/analyses/api_allowed.json
+++ b/tests/compiler/dart2js/analyses/api_allowed.json
@@ -28,8 +28,8 @@
"Dynamic invocation of '_js_helper::_execGlobal'.": 1,
"Dynamic access of 'start'.": 1,
"Dynamic access of 'end'.": 1,
- "Dynamic access of 'length'.": 4,
- "Dynamic invocation of '[]'.": 2,
+ "Dynamic access of 'length'.": 3,
+ "Dynamic invocation of '[]'.": 1,
"Dynamic invocation of 'call'.": 13,
"Dynamic invocation of 'codeUnitAt'.": 2,
"Dynamic access of 'iterator'.": 2,
@@ -244,4 +244,4 @@
"Dynamic access of 'port'.": 1,
"Dynamic invocation of 'dart._http::_toJSON'.": 1
}
-}
\ No newline at end of file
+}
diff --git a/tests/compiler/dart2js/analyses/dart2js_allowed.json b/tests/compiler/dart2js/analyses/dart2js_allowed.json
index a095c40..de743f0 100644
--- a/tests/compiler/dart2js/analyses/dart2js_allowed.json
+++ b/tests/compiler/dart2js/analyses/dart2js_allowed.json
@@ -270,12 +270,6 @@
"pkg/compiler/lib/src/ssa/value_set.dart": {
"Dynamic invocation of 'add'.": 2
},
- "pkg/compiler/lib/src/inferrer/node_tracer.dart": {
- "Dynamic access of 'receiver'.": 1,
- "Dynamic access of 'selector'.": 3,
- "Dynamic access of 'isIndex'.": 1,
- "Dynamic access of 'name'.": 2
- },
"pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart": {
"Dynamic access of 'keys'.": 1,
"Dynamic invocation of 'toSet'.": 1,
diff --git a/tests/compiler/dart2js/analysis_options.yaml b/tests/compiler/dart2js/analysis_options.yaml
index 40dc4a9..efa1621 100644
--- a/tests/compiler/dart2js/analysis_options.yaml
+++ b/tests/compiler/dart2js/analysis_options.yaml
@@ -3,13 +3,15 @@
# BSD-style license that can be found in the LICENSE file.
analyzer:
- language:
- enableSuperMixins: false
-
errors:
todo: ignore
deprecated_member_use: ignore
exclude:
- - data/*
- - sourcemaps/data/*
+ - '**/data/*'
+ - '**/model_data/*'
+ - 'deferred_loading/libs/*'
+
+linter:
+ rules:
+ - annotate_overrides
diff --git a/tests/compiler/dart2js/closure/closure_test.dart b/tests/compiler/dart2js/closure/closure_test.dart
index 26d0d92..da6b882 100644
--- a/tests/compiler/dart2js/closure/closure_test.dart
+++ b/tests/compiler/dart2js/closure/closure_test.dart
@@ -95,6 +95,7 @@
? closureRepresentationInfoStack.head
: null;
+ @override
visitFunctionExpression(ir.FunctionExpression node) {
ClosureRepresentationInfo info = closureDataLookup.getClosureInfo(node);
pushMember(info.callMethod);
@@ -104,6 +105,7 @@
popMember();
}
+ @override
visitFunctionDeclaration(ir.FunctionDeclaration node) {
ClosureRepresentationInfo info = closureDataLookup.getClosureInfo(node);
pushMember(info.callMethod);
@@ -113,18 +115,21 @@
popMember();
}
+ @override
visitForStatement(ir.ForStatement node) {
pushLoopNode(node);
super.visitForStatement(node);
popLoop();
}
+ @override
visitWhileStatement(ir.WhileStatement node) {
pushLoopNode(node);
super.visitWhileStatement(node);
popLoop();
}
+ @override
visitForInStatement(ir.ForInStatement node) {
pushLoopNode(node);
super.visitForInStatement(node);
diff --git a/tests/compiler/dart2js/codegen/model_data/capture.dart b/tests/compiler/dart2js/codegen/model_data/capture.dart
index ca9279e..5e44fb0 100644
--- a/tests/compiler/dart2js/codegen/model_data/capture.dart
+++ b/tests/compiler/dart2js/codegen/model_data/capture.dart
@@ -4,7 +4,7 @@
/*element: method1:params=0*/
@pragma('dart2js:noInline')
-method1([a]) => /*params=0*/ () => a;
+method1([a]) => /*access=[a],params=0*/ () => a;
class Class {
/*element: Class.f:emitted*/
@@ -13,14 +13,14 @@
/*element: Class.capture:params=0*/
@pragma('dart2js:noInline')
- Class.capture([a]) : f = (/*params=0*/ () => a);
+ Class.capture([a]) : f = (/*access=[a],params=0*/ () => a);
// TODO(johnniwinther): Remove the redundant assignment of elided boxed
// parameters.
/*element: Class.box:assign=[a,a],params=0*/
@pragma('dart2js:noInline')
Class.box([a])
- : f = (/*assign=[a],params=0*/ () {
+ : f = (/*access=[_box_0],assign=[a],params=0*/ () {
a = 42;
});
@@ -30,12 +30,12 @@
class Subclass extends Class {
/*element: Subclass.capture:params=0*/
@pragma('dart2js:noInline')
- Subclass.capture([a]) : super.internal(/*params=0*/ () => a);
+ Subclass.capture([a]) : super.internal(/*access=[a],params=0*/ () => a);
/*element: Subclass.box:assign=[a,a],params=0*/
@pragma('dart2js:noInline')
Subclass.box([a])
- : super.internal(/*assign=[a],params=0*/ () {
+ : super.internal(/*access=[_box_0],assign=[a],params=0*/ () {
a = 42;
});
}
diff --git a/tests/compiler/dart2js/codegen/model_data/regress_36222.dart b/tests/compiler/dart2js/codegen/model_data/regress_36222.dart
new file mode 100644
index 0000000..8ab6ea3
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/regress_36222.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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 BinaryFunc(int x, int y);
+
+class A {
+ const A({this.foo = A.defaultFoo});
+
+ /*element: A.defaultFoo:params=2*/
+ static int defaultFoo(int x, int y) {
+ return x + y;
+ }
+
+ /*element: A.foo:elided,stubCalls=[foo$2:call$2(arg0,arg1),foo$2:main_A_defaultFoo$closure(0)]*/
+ final BinaryFunc foo;
+}
+
+/*element: test:calls=[foo$2(2)],params=1*/
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+test(dynamic a) => a.foo(1, 2);
+
+/*element: main:calls=[test(1)],params=0*/
+main() {
+ test(new A());
+}
diff --git a/tests/compiler/dart2js/codegen/model_test.dart b/tests/compiler/dart2js/codegen/model_test.dart
index 84cda3f..af0b3c8 100644
--- a/tests/compiler/dart2js/codegen/model_test.dart
+++ b/tests/compiler/dart2js/codegen/model_test.dart
@@ -59,6 +59,8 @@
static const String parameterCount = 'params';
static const String call = 'calls';
static const String parameterStub = 'stubs';
+ static const String callStubCall = 'stubCalls';
+ static const String callStubAccesses = 'stubAccesses';
static const String isEmitted = 'emitted';
static const String isElided = 'elided';
static const String assignment = 'assign';
@@ -83,6 +85,75 @@
: _programLookup = new ProgramLookup(compiler),
super(reporter, actualMap);
+ void registerCalls(Features features, String tag, js.Node node,
+ {String prefix = '', Set<js.PropertyAccess> handledAccesses}) {
+ forEachNode(node, onCall: (js.Call node) {
+ js.Node target = node.target;
+ if (target is js.PropertyAccess) {
+ js.Node selector = target.selector;
+ bool fixedNameCall = false;
+ String name;
+ if (selector is js.Name) {
+ name = selector.key;
+ fixedNameCall = selector is StringBackedName;
+ } else if (selector is js.LiteralString) {
+ /// Call to fixed backend name, so we include the argument
+ /// values to test encoding of optional parameters in native
+ /// methods.
+ name = selector.value.substring(1, selector.value.length - 1);
+ fixedNameCall = true;
+ }
+ if (name != null) {
+ if (fixedNameCall) {
+ String arguments = node.arguments.map(js.nodeToString).join(',');
+ features.addElement(tag, '${prefix}${name}(${arguments})');
+ } else {
+ features.addElement(
+ tag, '${prefix}${name}(${node.arguments.length})');
+ }
+ handledAccesses?.add(target);
+ }
+ }
+ });
+ }
+
+ void registerAccesses(Features features, String tag, js.Node code,
+ {String prefix = '', Set<js.PropertyAccess> handledAccesses}) {
+ forEachNode(code, onPropertyAccess: (js.PropertyAccess node) {
+ if (handledAccesses?.contains(node) ?? false) {
+ return;
+ }
+
+ js.Node receiver = node.receiver;
+ String receiverName;
+ if (receiver is js.VariableUse) {
+ receiverName = receiver.name;
+ if (receiverName == receiverName.toUpperCase() &&
+ receiverName != r'$') {
+ // Skip holder access.
+ receiverName = null;
+ }
+ } else if (receiver is js.This) {
+ receiverName = 'this';
+ }
+
+ js.Node selector = node.selector;
+ String name;
+ if (selector is js.Name) {
+ name = selector.key;
+ } else if (selector is js.LiteralString) {
+ /// Call to fixed backend name, so we include the argument
+ /// values to test encoding of optional parameters in native
+ /// methods.
+ name = selector.value.substring(1, selector.value.length - 1);
+ }
+
+ if (receiverName != null && name != null) {
+ features.addElement(tag, '${prefix}${name}');
+ }
+ });
+ }
+
Features getMemberValue(MemberEntity member) {
if (member is FieldEntity) {
Field field = _programLookup.getField(member);
@@ -115,6 +186,16 @@
registerFlags(Tags.getterFlags, field.getterFlags);
registerFlags(Tags.setterFlags, field.setterFlags);
+ Class cls = _programLookup.getClass(member.enclosingClass);
+ for (StubMethod stub in cls.callStubs) {
+ if (stub.element == member) {
+ registerCalls(features, Tags.callStubCall, stub.code,
+ prefix: '${stub.name.key}:');
+ registerAccesses(features, Tags.callStubAccesses, stub.code,
+ prefix: '${stub.name.key}:');
+ }
+ }
+
return features;
}
StaticField staticField = _programLookup.getStaticField(member);
@@ -137,42 +218,12 @@
Set<js.PropertyAccess> handledAccesses = new Set();
- void registerCalls(String tag, js.Node node, [String prefix = '']) {
- forEachNode(node, onCall: (js.Call node) {
- js.Node target = node.target;
- if (target is js.PropertyAccess) {
- js.Node selector = target.selector;
- bool fixedNameCall = false;
- String name;
- if (selector is js.Name) {
- name = selector.key;
- fixedNameCall = selector is StringBackedName;
- } else if (selector is js.LiteralString) {
- /// Call to fixed backend name, so we include the argument
- /// values to test encoding of optional parameters in native
- /// methods.
- name = selector.value.substring(1, selector.value.length - 1);
- fixedNameCall = true;
- }
- if (name != null) {
- if (fixedNameCall) {
- String arguments =
- node.arguments.map(js.nodeToString).join(',');
- features.addElement(tag, '${prefix}${name}(${arguments})');
- } else {
- features.addElement(
- tag, '${prefix}${name}(${node.arguments.length})');
- }
- handledAccesses.add(target);
- }
- }
- });
- }
-
- registerCalls(Tags.call, code);
+ registerCalls(features, Tags.call, code,
+ handledAccesses: handledAccesses);
if (method is DartMethod) {
for (ParameterStubMethod stub in method.parameterStubs) {
- registerCalls(Tags.parameterStub, stub.code, '${stub.name.key}:');
+ registerCalls(features, Tags.parameterStub, stub.code,
+ prefix: '${stub.name.key}:', handledAccesses: handledAccesses);
}
}
@@ -193,37 +244,8 @@
}
});
- forEachNode(code, onPropertyAccess: (js.PropertyAccess node) {
- if (handledAccesses.contains(node)) {
- return;
- }
-
- js.Node receiver = node.receiver;
- String receiverName;
- if (receiver is js.VariableUse) {
- receiverName = receiver.name;
- if (receiverName == receiverName.toUpperCase() &&
- receiverName != r'$') {
- // Skip holder access.
- receiverName = null;
- }
- }
-
- js.Node selector = node.selector;
- String name;
- if (selector is js.Name) {
- name = selector.key;
- } else if (selector is js.LiteralString) {
- /// Call to fixed backend name, so we include the argument
- /// values to test encoding of optional parameters in native
- /// methods.
- name = selector.value.substring(1, selector.value.length - 1);
- }
-
- if (receiverName != null && name != null) {
- features.addElement(Tags.propertyAccess, '${name}');
- }
- });
+ registerAccesses(features, Tags.propertyAccess, code,
+ handledAccesses: handledAccesses);
forEachNode(code, onSwitch: (js.Switch node) {
features.add(Tags.switchCase);
diff --git a/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart b/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart
index b386ea1..ba55341 100644
--- a/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart
+++ b/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart
@@ -29,21 +29,33 @@
class CollectingFormattingDiagnosticHandler
implements FormattingDiagnosticHandler {
+ @override
final provider = null;
+ @override
bool showWarnings = true;
+ @override
bool showHints = true;
+ @override
bool verbose = true;
+ @override
bool isAborting = false;
+ @override
bool enableColors = false;
+ @override
bool throwOnError = false;
+ @override
bool autoReadFileUri = false;
+ @override
var lastKind = null;
+ @override
final int FATAL = 0;
+ @override
final int INFO = 1;
final messages = [];
+ @override
void info(var message, [kind = Diagnostic.VERBOSE_INFO]) {
messages.add([message, kind]);
}
@@ -58,12 +70,15 @@
report(null, uri, begin, end, message, kind);
}
+ @override
String prefixMessage(String message, Diagnostic kind) {
return message;
}
+ @override
int fatalCount;
+ @override
int throwOnErrorCount;
}
diff --git a/tests/compiler/dart2js/end_to_end/exit_code_test.dart b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
index c891f34..aea5404 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -32,6 +32,7 @@
final String testMarker;
final String testType;
final Function onTest;
+ @override
TestDiagnosticReporter reporter;
TestCompiler(
@@ -54,6 +55,7 @@
return new TestBackend(this);
}
+ @override
Future<bool> run(Uri uri) {
test('Compiler.run');
return super.run(uri);
@@ -98,6 +100,7 @@
}
class TestBackend extends JavaScriptBackend {
+ @override
final TestCompiler compiler;
TestBackend(TestCompiler compiler)
: this.compiler = compiler,
@@ -116,6 +119,7 @@
class TestDiagnosticReporter extends DiagnosticReporterWrapper {
TestCompiler compiler;
+ @override
DiagnosticReporter reporter;
@override
diff --git a/tests/compiler/dart2js/end_to_end/library_env_test.dart b/tests/compiler/dart2js/end_to_end/library_env_test.dart
index e215c89..45421c4 100644
--- a/tests/compiler/dart2js/end_to_end/library_env_test.dart
+++ b/tests/compiler/dart2js/end_to_end/library_env_test.dart
@@ -49,6 +49,7 @@
class DummyCompilerInput implements CompilerInput {
const DummyCompilerInput();
+ @override
Future<Input> readFromUri(Uri uri,
{InputKind inputKind: InputKind.UTF8}) async {
if (uri.path.endsWith("libraries.json")) {
@@ -62,6 +63,7 @@
class DummyCompilerDiagnostics implements CompilerDiagnostics {
const DummyCompilerDiagnostics();
+ @override
report(code, uri, begin, end, text, kind) {
throw "should not be needed";
}
diff --git a/tests/compiler/dart2js/end_to_end/user_crash_test.dart b/tests/compiler/dart2js/end_to_end/user_crash_test.dart
index a17fbf2..1f21642 100644
--- a/tests/compiler/dart2js/end_to_end/user_crash_test.dart
+++ b/tests/compiler/dart2js/end_to_end/user_crash_test.dart
@@ -96,7 +96,9 @@
}
class CrashingMap implements Map<String, String> {
+ @override
operator [](_) => throw EXCEPTION;
+ @override
noSuchMethod(_) => null;
}
diff --git a/tests/compiler/dart2js/equivalence/check_helpers.dart b/tests/compiler/dart2js/equivalence/check_helpers.dart
index cef161e..2465a58 100644
--- a/tests/compiler/dart2js/equivalence/check_helpers.dart
+++ b/tests/compiler/dart2js/equivalence/check_helpers.dart
@@ -53,6 +53,7 @@
return ' $indent';
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
printOn(sb, '');
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence.dart b/tests/compiler/dart2js/equivalence/id_equivalence.dart
index 4d76541..d664020 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence.dart
@@ -34,14 +34,17 @@
const IdValue(this.id, this.value);
+ @override
int get hashCode => id.hashCode * 13 + value.hashCode * 17;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! IdValue) return false;
return id == other.id && value == other.value;
}
+ @override
String toString() => idToString(id, value);
static String idToString(Id id, String value) {
@@ -131,6 +134,7 @@
class ElementId implements Id {
final String className;
final String memberName;
+ @override
final bool isGlobal;
factory ElementId(String text, {bool isGlobal: false}) {
@@ -145,44 +149,55 @@
ElementId.internal(this.memberName, {this.className, this.isGlobal: false});
+ @override
int get hashCode => className.hashCode * 13 + memberName.hashCode * 17;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! ElementId) return false;
return className == other.className && memberName == other.memberName;
}
+ @override
IdKind get kind => IdKind.element;
String get name => className != null ? '$className.$memberName' : memberName;
+ @override
String get descriptor => 'member $name';
+ @override
String toString() => 'element:$name';
}
/// Id for a class.
class ClassId implements Id {
final String className;
+ @override
final bool isGlobal;
ClassId(this.className, {this.isGlobal: false});
+ @override
int get hashCode => className.hashCode * 13;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! ClassId) return false;
return className == other.className;
}
+ @override
IdKind get kind => IdKind.cls;
String get name => className;
+ @override
String get descriptor => 'class $name';
+ @override
String toString() => 'class:$name';
}
@@ -190,22 +205,28 @@
// TODO(johnniwinther): Create an [NodeId]-based equivalence with the kernel IR.
class NodeId implements Id {
final int value;
+ @override
final IdKind kind;
const NodeId(this.value, this.kind);
+ @override
bool get isGlobal => false;
+ @override
int get hashCode => value.hashCode * 13 + kind.hashCode * 17;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! NodeId) return false;
return value == other.value && kind == other.kind;
}
+ @override
String get descriptor => 'offset $value ($kind)';
+ @override
String toString() => '$kind:$value';
}
@@ -230,6 +251,7 @@
return 'object `${'$object'.replaceAll('\n', '')}` (${object.runtimeType})';
}
+ @override
String toString() =>
'ActualData(id=$id,value=$value,sourceSpan=$sourceSpan,object=$objectText)';
}
@@ -272,7 +294,9 @@
/// Abstract IR visitor for computing data corresponding to a node or element,
/// and record it with a generic [Id]
abstract class IrDataExtractor<T> extends ir.Visitor with DataRegistry<T> {
+ @override
final DiagnosticReporter reporter;
+ @override
final Map<Id, ActualData<T>> actualMap;
/// Implement this to compute the data corresponding to [member].
@@ -352,15 +376,18 @@
root.accept(this);
}
+ @override
defaultNode(ir.Node node) {
node.visitChildren(this);
}
+ @override
defaultMember(ir.Member node) {
computeForMember(node);
super.defaultMember(node);
}
+ @override
visitMethodInvocation(ir.MethodInvocation node) {
ir.TreeNode receiver = node.receiver;
if (receiver is ir.VariableGet &&
@@ -384,15 +411,18 @@
}
}
+ @override
visitLoadLibrary(ir.LoadLibrary node) {
computeForNode(node, createInvokeId(node));
}
+ @override
visitPropertyGet(ir.PropertyGet node) {
computeForNode(node, computeDefaultNodeId(node));
super.visitPropertyGet(node);
}
+ @override
visitVariableDeclaration(ir.VariableDeclaration node) {
if (node.name != null && node.parent is! ir.FunctionDeclaration) {
// Skip synthetic variables and function declaration variables.
@@ -401,16 +431,19 @@
super.visitVariableDeclaration(node);
}
+ @override
visitFunctionDeclaration(ir.FunctionDeclaration node) {
computeForNode(node, computeDefaultNodeId(node));
super.visitFunctionDeclaration(node);
}
+ @override
visitFunctionExpression(ir.FunctionExpression node) {
computeForNode(node, computeDefaultNodeId(node));
super.visitFunctionExpression(node);
}
+ @override
visitVariableGet(ir.VariableGet node) {
if (node.variable.name != null && !node.variable.isFieldFormal) {
// Skip use of synthetic variables.
@@ -419,11 +452,13 @@
super.visitVariableGet(node);
}
+ @override
visitPropertySet(ir.PropertySet node) {
computeForNode(node, createUpdateId(node));
super.visitPropertySet(node);
}
+ @override
visitVariableSet(ir.VariableSet node) {
if (node.variable.name != null) {
// Skip use of synthetic variables.
@@ -432,16 +467,19 @@
super.visitVariableSet(node);
}
+ @override
visitDoStatement(ir.DoStatement node) {
computeForNode(node, createLoopId(node));
super.visitDoStatement(node);
}
+ @override
visitForStatement(ir.ForStatement node) {
computeForNode(node, createLoopId(node));
super.visitForStatement(node);
}
+ @override
visitForInStatement(ir.ForInStatement node) {
computeForNode(node, createLoopId(node));
computeForNode(node, createIteratorId(node));
@@ -450,11 +488,13 @@
super.visitForInStatement(node);
}
+ @override
visitWhileStatement(ir.WhileStatement node) {
computeForNode(node, createLoopId(node));
super.visitWhileStatement(node);
}
+ @override
visitLabeledStatement(ir.LabeledStatement node) {
if (!JumpVisitor.canBeBreakTarget(node.body) &&
!JumpVisitor.canBeContinueTarget(node.parent)) {
@@ -463,16 +503,19 @@
super.visitLabeledStatement(node);
}
+ @override
visitBreakStatement(ir.BreakStatement node) {
computeForNode(node, createGotoId(node));
super.visitBreakStatement(node);
}
+ @override
visitSwitchStatement(ir.SwitchStatement node) {
computeForNode(node, createSwitchId(node));
super.visitSwitchStatement(node);
}
+ @override
visitSwitchCase(ir.SwitchCase node) {
if (node.expressionOffsets.isNotEmpty) {
computeForNode(node, createSwitchCaseId(node));
@@ -480,6 +523,7 @@
super.visitSwitchCase(node);
}
+ @override
visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
computeForNode(node, createGotoId(node));
super.visitContinueSwitchStatement(node);
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index ba46e61..ba5118a 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -476,6 +476,7 @@
return _computedDataForEachFile[file];
}
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('MemberAnnotations(');
diff --git a/tests/compiler/dart2js/field_analysis/jdata/regress_36222.dart b/tests/compiler/dart2js/field_analysis/jdata/regress_36222.dart
new file mode 100644
index 0000000..d798780
--- /dev/null
+++ b/tests/compiler/dart2js/field_analysis/jdata/regress_36222.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, 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 BinaryFunc(int x, int y);
+
+class A {
+ const A({this.foo = A.defaultFoo});
+
+ static int defaultFoo(int x, int y) {
+ return x + y;
+ }
+
+ /*element: A.foo:constant=FunctionConstant(A.defaultFoo)*/
+ final BinaryFunc foo;
+}
+
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+test(dynamic a) => a.foo(1, 2);
+
+main() {
+ test(new A());
+}
diff --git a/tests/compiler/dart2js/field_analysis/jdata/static_initializers.dart b/tests/compiler/dart2js/field_analysis/jdata/static_initializers.dart
index 967f63c..4e0c97f 100644
--- a/tests/compiler/dart2js/field_analysis/jdata/static_initializers.dart
+++ b/tests/compiler/dart2js/field_analysis/jdata/static_initializers.dart
@@ -17,6 +17,56 @@
print(field3b);
field3c = null;
print(field3c);
+ print(field3d);
+ print(field3e);
+ print(field3f);
+ print(field3g);
+ print(field3h);
+
+ print(field4a);
+ print(field4b);
+ print(field4c);
+
+ print(field5a);
+ print(field5b);
+ print(field5c);
+
+ print(field6a);
+ print(field6b);
+ print(field6c);
+
+ print(field7a);
+ print(field7b);
+ print(field7c);
+ print(field7d);
+ print(field7e);
+
+ print(field8a);
+ print(field8b);
+ print(field8c);
+ print(field8d);
+
+ print(field9a);
+ print(field9b);
+ print(field9c);
+ print(field9d);
+ field9e = null;
+ print(field9e);
+ print(field9f);
+ print(field9g);
+ print(field9h);
+ print(field9i);
+
+ print(field10a);
+ print(field10b);
+}
+
+method() {}
+
+class Class {
+ const Class.generative();
+
+ const factory Class.fact() = Class.generative;
}
/*element: field1a:constant=IntConstant(0)*/
@@ -37,11 +87,133 @@
/*element: field2c:initial=ListConstant([])*/
var field2c = const [];
-/*element: field3a:*/
+/*element: field3a:eager,final*/
final field3a = [];
-/*element: field3b:*/
+/*element: field3b:eager,final*/
var field3b = [];
-/*element: field3c:*/
+/*element: field3c:eager*/
var field3c = [];
+
+/*element: field3d:eager,final*/
+var field3d = [1, 2, 3];
+
+/*element: field3e:eager,final*/
+var field3e = [
+ 1,
+ 2,
+ [
+ 3,
+ 4,
+ [5, 6, method]
+ ]
+];
+
+/*element: field3f:final,lazy*/
+var field3f = [
+ 1,
+ 2,
+ [
+ 3,
+ 4,
+ [5, 6, method()]
+ ]
+];
+
+/*element: field3g:final,lazy*/
+var field3g = [method()];
+
+// TODO(johnniwinther): Recognize this as of eager complexity.
+/*element: field3h:final,lazy*/
+var field3h = [1 + 3];
+
+/*element: field4a:constant=IntConstant(5)*/
+final field4a = 2 + 3;
+
+/*element: field4b:constant=IntConstant(5)*/
+var field4b = 2 + 3;
+
+/*element: field4c:constant=IntConstant(5)*/
+const field4c = 2 + 3;
+
+/*element: field5a:constant=FunctionConstant(method)*/
+final field5a = method;
+
+/*element: field5b:constant=FunctionConstant(method)*/
+var field5b = method;
+
+/*element: field5c:constant=FunctionConstant(method)*/
+const field5c = method;
+
+/*element: field6a:constant=ConstructedConstant(Class())*/
+var field6a = const Class.generative();
+
+/*element: field6b:constant=ConstructedConstant(Class())*/
+var field6b = const Class.fact();
+
+/*element: field6c:final,lazy*/
+var field6c = method();
+
+/*element: field7a:eager,final*/
+var field7a = {};
+
+/*element: field7b:eager,final*/
+var field7b = {0: 1};
+
+/*element: field7c:eager,final*/
+var field7c = {0: method};
+
+/*element: field7d:final,lazy*/
+var field7d = {0: method()};
+
+/*element: field7e:final,lazy*/
+var field7e = {method(): 0};
+
+/*element: field8a:eager,final*/
+var field8a = {};
+
+/*element: field8b:eager,final*/
+var field8b = {0};
+
+/*element: field8c:eager,final*/
+var field8c = {method};
+
+/*element: field8d:final,lazy*/
+var field8d = {method()};
+
+/*element: field9g:eager=[field9d],final,index=1*/
+var field9g = field9d;
+
+/*element: field9a:eager,final*/
+var field9a = [];
+
+/*element: field9c:eager=[field9b],final,index=3*/
+var field9c = [field9b];
+
+/*element: field9b:eager=[field9a],final,index=2*/
+var field9b = field9a;
+
+// Because [field9g] is declared first and it depends upon [field9d], [field9d]
+// must be created before [field9g] and thus has a lower index than, say,
+// [field9b].
+/*element: field9d:eager=[field9a],final,index=0*/
+var field9d = [field9a];
+
+/*element: field9e:eager*/
+var field9e = [];
+
+/*element: field9f:final,lazy*/
+var field9f = field9e;
+
+/*element: field9h:constant=ListConstant([])*/
+var field9h = const [];
+
+/*element: field9i:eager,final*/
+var field9i = [field9h];
+
+/*element: field10a:final,lazy*/
+int field10a = field10b;
+
+/*element: field10b:final,lazy*/
+int field10b = field10a;
diff --git a/tests/compiler/dart2js/field_analysis/jfield_analysis_test.dart b/tests/compiler/dart2js/field_analysis/jfield_analysis_test.dart
index 1e9dfb7..09870a6 100644
--- a/tests/compiler/dart2js/field_analysis/jfield_analysis_test.dart
+++ b/tests/compiler/dart2js/field_analysis/jfield_analysis_test.dart
@@ -26,6 +26,10 @@
static const String isInitializedInAllocator = 'allocator';
static const String initialValue = 'initial';
static const String constantValue = 'constant';
+ static const String isEager = 'eager';
+ static const String eagerCreationIndex = 'index';
+ static const String isLazy = 'lazy';
+ static const String isEffectivelyFinal = 'final';
}
class JAllocatorAnalysisDataComputer extends DataComputer<Features> {
@@ -41,14 +45,33 @@
ir.Member node = closedWorld.elementMap.getMemberDefinition(member).node;
Features features = new Features();
FieldAnalysisData fieldData = fieldAnalysis.getFieldData(member);
+ if (fieldData.isInitializedInAllocator) {
+ features.add(Tags.isInitializedInAllocator);
+ }
if (fieldData.isEffectivelyConstant) {
features[Tags.constantValue] =
fieldData.constantValue.toStructuredText();
} else if (fieldData.initialValue != null) {
features[Tags.initialValue] = fieldData.initialValue.toStructuredText();
+ } else if (fieldData.isEager) {
+ if (fieldData.eagerCreationIndex != null) {
+ features[Tags.eagerCreationIndex] =
+ fieldData.eagerCreationIndex.toString();
+ }
+ if (fieldData.eagerFieldDependenciesForTesting != null) {
+ for (FieldEntity field
+ in fieldData.eagerFieldDependenciesForTesting) {
+ features.addElement(Tags.isEager, field.name);
+ }
+ } else {
+ features.add(Tags.isEager);
+ }
}
- if (fieldData.isInitializedInAllocator) {
- features.add(Tags.isInitializedInAllocator);
+ if (!member.isInstanceMember && fieldData.isLazy) {
+ features.add(Tags.isLazy);
+ }
+ if (fieldData.isEffectivelyFinal && !fieldData.isEffectivelyConstant) {
+ features.add(Tags.isEffectivelyFinal);
}
Id id = computeEntityId(node);
actualMap[id] = new ActualData<Features>(
diff --git a/tests/compiler/dart2js/field_analysis/kdata/regress_36222.dart b/tests/compiler/dart2js/field_analysis/kdata/regress_36222.dart
new file mode 100644
index 0000000..6794ac8
--- /dev/null
+++ b/tests/compiler/dart2js/field_analysis/kdata/regress_36222.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, 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 BinaryFunc(int x, int y);
+
+class A {
+ const A({this.foo = A.defaultFoo});
+
+ static int defaultFoo(int x, int y) {
+ return x + y;
+ }
+
+ /*element: A.foo:A.=foo:FunctionConstant(A.defaultFoo),initial=NullConstant*/
+ final BinaryFunc foo;
+}
+
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+test(dynamic a) => a.foo(1, 2);
+
+main() {
+ test(new A());
+}
diff --git a/tests/compiler/dart2js/field_analysis/kdata/static_initializers.dart b/tests/compiler/dart2js/field_analysis/kdata/static_initializers.dart
index fc87293..6f393ef 100644
--- a/tests/compiler/dart2js/field_analysis/kdata/static_initializers.dart
+++ b/tests/compiler/dart2js/field_analysis/kdata/static_initializers.dart
@@ -14,10 +14,49 @@
print(field3a);
print(field3b);
print(field3c);
+ print(field3d);
+ print(field3e);
+ print(field3f);
+ print(field3g);
+ print(field3h);
print(field4a);
print(field4b);
print(field4c);
+
+ print(field5a);
+ print(field5b);
+ print(field5c);
+
+ print(field6a);
+ print(field6b);
+ print(field6c);
+
+ print(field7a);
+ print(field7b);
+ print(field7c);
+ print(field7d);
+ print(field7e);
+
+ print(field8a);
+ print(field8b);
+ print(field8c);
+ print(field8d);
+
+ print(field9a);
+ print(field9b);
+ print(field9c);
+
+ print(field10a);
+ print(field10b);
+}
+
+method() {}
+
+class Class {
+ const Class.generative();
+
+ const factory Class.fact() = Class.generative;
}
/*element: field1a:complexity=constant,initial=IntConstant(0)*/
@@ -38,16 +77,48 @@
/*element: field2c:complexity=constant,initial=ListConstant([])*/
const field2c = const [];
-/*element: field3a:complexity=lazy*/
+/*element: field3a:complexity=eager*/
final field3a = [];
-/*element: field3b:complexity=lazy*/
+/*element: field3b:complexity=eager*/
var field3b = [];
-/*element: field3c:complexity=lazy*/
+/*element: field3c:complexity=eager*/
var field3c = [];
-// TODO(johnniwinther): Recognize these as of constant complexity.
+/*element: field3d:complexity=eager*/
+var field3d = [1, 2, 3];
+
+/*element: field3e:complexity=eager*/
+var field3e = [
+ 1,
+ 2,
+ [
+ 3,
+ 4,
+ [5, 6, method]
+ ]
+];
+
+/*element: field3f:complexity=lazy*/
+var field3f = [
+ 1,
+ 2,
+ [
+ 3,
+ 4,
+ [5, 6, method()]
+ ]
+];
+
+/*element: field3g:complexity=lazy*/
+var field3g = [method()];
+
+// TODO(johnniwinther): Recognize this as of eager complexity.
+/*element: field3h:complexity=lazy*/
+var field3h = [1 + 3];
+
+// TODO(johnniwinther): Recognize `field4*` as of constant complexity.
/*element: field4a:complexity=lazy,initial=IntConstant(5)*/
final field4a = 2 + 3;
@@ -56,3 +127,63 @@
/*element: field4c:complexity=lazy,initial=IntConstant(5)*/
const field4c = 2 + 3;
+
+/*element: field5a:complexity=constant,initial=FunctionConstant(method)*/
+final field5a = method;
+
+/*element: field5b:complexity=constant,initial=FunctionConstant(method)*/
+var field5b = method;
+
+/*element: field5c:complexity=constant,initial=FunctionConstant(method)*/
+const field5c = method;
+
+/*element: field6a:complexity=constant,initial=ConstructedConstant(Class())*/
+var field6a = const Class.generative();
+
+/*element: field6b:complexity=constant,initial=ConstructedConstant(Class())*/
+var field6b = const Class.fact();
+
+/*element: field6c:complexity=lazy*/
+var field6c = method();
+
+/*element: field7a:complexity=eager*/
+var field7a = {};
+
+/*element: field7b:complexity=eager*/
+var field7b = {0: 1};
+
+/*element: field7c:complexity=eager*/
+var field7c = {0: method};
+
+/*element: field7d:complexity=lazy*/
+var field7d = {0: method()};
+
+/*element: field7e:complexity=lazy*/
+var field7e = {method(): 0};
+
+/*element: field8a:complexity=eager*/
+var field8a = {};
+
+/*element: field8b:complexity=eager*/
+var field8b = {0};
+
+/*element: field8c:complexity=eager*/
+var field8c = {method};
+
+/*element: field8d:complexity=lazy*/
+var field8d = {method()};
+
+/*element: field9a:complexity=eager*/
+var field9a = [];
+
+/*element: field9b:complexity=eager&fields=[field9a]*/
+var field9b = field9a;
+
+/*element: field9c:complexity=eager&fields=[field9b]*/
+var field9c = [field9b];
+
+/*element: field10a:complexity=eager&fields=[field10b]*/
+int field10a = field10b;
+
+/*element: field10b:complexity=eager&fields=[field10a]*/
+int field10b = field10a;
diff --git a/tests/compiler/dart2js/helpers/diagnostic_helper.dart b/tests/compiler/dart2js/helpers/diagnostic_helper.dart
index e5d433d..d45306a 100644
--- a/tests/compiler/dart2js/helpers/diagnostic_helper.dart
+++ b/tests/compiler/dart2js/helpers/diagnostic_helper.dart
@@ -25,6 +25,7 @@
MessageKind get messageKind => message?.kind;
+ @override
String toString() {
return '${message != null ? message.kind : ''}'
':$uri:$begin:$end:$text:$kind';
diff --git a/tests/compiler/dart2js/helpers/output_collector.dart b/tests/compiler/dart2js/helpers/output_collector.dart
index e9ff37b..30b62be 100644
--- a/tests/compiler/dart2js/helpers/output_collector.dart
+++ b/tests/compiler/dart2js/helpers/output_collector.dart
@@ -12,15 +12,18 @@
StringBuffer sb = new StringBuffer();
String text;
+ @override
void add(String event) {
sb.write(event);
}
+ @override
void close() {
text = sb.toString();
sb = null;
}
+ @override
String toString() {
return text ?? sb.toString();
}
@@ -33,12 +36,15 @@
BufferedBinaryOutputSink(this.uri);
+ @override
void write(List<int> buffer, [int start = 0, int end]) {
list.addAll(buffer.sublist(start, end));
}
+ @override
void close() {}
+ @override
String toString() {
return 'BufferedBinaryOutputSink($uri)';
}
@@ -79,6 +85,7 @@
}
}
+ @override
BinaryOutputSink createBinarySink(Uri uri) {
return binaryOutputMap.putIfAbsent(
uri, () => new BufferedBinaryOutputSink(uri));
diff --git a/tests/compiler/dart2js/helpers/program_lookup.dart b/tests/compiler/dart2js/helpers/program_lookup.dart
index ccbf049..18d8e84 100644
--- a/tests/compiler/dart2js/helpers/program_lookup.dart
+++ b/tests/compiler/dart2js/helpers/program_lookup.dart
@@ -176,6 +176,7 @@
return _staticFieldMap[field];
}
+ @override
String toString() => 'LibraryData(library=$library,_classMap=$_classMap,'
'_methodMap=$_methodMap,_fieldMap=$_fieldMap)';
}
@@ -220,6 +221,7 @@
return _checkedSetterMap[field];
}
+ @override
String toString() => 'ClassData(cls=$cls,'
'_methodMap=$_methodMap,_fieldMap=$_fieldMap)';
}
diff --git a/tests/compiler/dart2js/helpers/stats_test.dart b/tests/compiler/dart2js/helpers/stats_test.dart
index 5271e12..9254ee9 100644
--- a/tests/compiler/dart2js/helpers/stats_test.dart
+++ b/tests/compiler/dart2js/helpers/stats_test.dart
@@ -8,10 +8,12 @@
class CollectingOutput implements StatsOutput {
final StringBuffer sb = new StringBuffer();
+ @override
void println(String text) {
sb.write('$text\n');
}
+ @override
String toString() => sb.toString();
}
diff --git a/tests/compiler/dart2js/helpers/type_test_helper.dart b/tests/compiler/dart2js/helpers/type_test_helper.dart
index c4304da..cda6070 100644
--- a/tests/compiler/dart2js/helpers/type_test_helper.dart
+++ b/tests/compiler/dart2js/helpers/type_test_helper.dart
@@ -190,6 +190,7 @@
const FunctionTypeData(this.returnType, this.name, this.parameters);
+ @override
String toString() => '$returnType $name$parameters';
}
diff --git a/tests/compiler/dart2js/impact/data/injected_cast.dart b/tests/compiler/dart2js/impact/data/injected_cast.dart
new file mode 100644
index 0000000..526414c
--- /dev/null
+++ b/tests/compiler/dart2js/impact/data/injected_cast.dart
@@ -0,0 +1,220 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {}
+
+class B {}
+
+class C {}
+
+class D {}
+
+class E {}
+
+/*element: Class1.:static=[Object.(0)]*/
+class Class1 {
+ /*element: Class1.field1:type=[inst:JSBool,inst:JSNull,param:A]*/
+ A field1;
+}
+
+/*element: method1:
+ dynamic=[Class1.field1=],
+ type=[
+ impl:A,
+ inst:JSBool,
+ is:Class1]
+*/
+method1(dynamic o, dynamic value) {
+ if (o is! Class1) return;
+ o.field1 = value;
+}
+
+/*element: Class2.:static=[Object.(0)]*/
+class Class2<T> {
+ /*element: Class2.field2:
+ static=*,
+ type=[inst:*,param:Class2.T]
+ */
+ T field2;
+}
+
+/*element: method2:
+ dynamic=[Class2.field2=],
+ static=*,
+ type=[
+ impl:A,
+ inst:*,
+ is:Class2<A>]
+*/
+method2(dynamic o, dynamic value) {
+ if (o is! Class2<A>) return;
+ o.field2 = value;
+}
+
+/*element: Class3.:static=[Object.(0)]*/
+class Class3 {
+ /*element: Class3.method3:type=[inst:JSBool,inst:JSNull,param:A,param:B,param:C]*/
+ method3(A a, [B b, C c]) {}
+}
+
+/*element: method3:
+ dynamic=[Class3.method3(3)],
+ type=[
+ impl:A,
+ impl:C,
+ inst:JSBool,
+ is:Class3,
+ param:B]
+*/
+method3(dynamic o, dynamic a, B b, dynamic c) {
+ if (o is! Class3) return;
+ o.method3(a, b, c);
+}
+
+/*element: Class4.:static=[Object.(0)]*/
+class Class4 {
+ /*element: Class4.method4:
+ type=[inst:JSBool,inst:JSNull,param:A,param:B,param:C]
+ */
+ method4(A a, {B b, C c}) {}
+}
+
+/*element: method4:
+ dynamic=[Class4.method4(1,b,c)],
+ type=[
+ impl:A,
+ impl:C,
+ inst:JSBool,
+ is:Class4,
+ param:B]
+*/
+method4(dynamic o, dynamic a, B b, dynamic c) {
+ if (o is! Class4) return;
+ o.method4(a, c: c, b: b);
+}
+
+/*element: Class5.:static=[Object.(0)]*/
+class Class5<T1, T2> {
+ /*element: Class5.method5:
+ static=*,
+ type=[
+ inst:*,
+ param:C,
+ param:Class5.T1,
+ param:Class5.T2,
+ param:Object,
+ param:method5.S1,
+ param:method5.S2]
+ */
+ method5<S1, S2>(T1 a, [T2 b, C c, S1 d, S2 e]) {}
+}
+
+/*element: method5:
+ dynamic=[Class5.method5<D,E>(5)],
+ static=*,
+ type=[
+ impl:A,
+ impl:D,
+ inst:*,
+ is:Class5<A,B>,
+ param:B,
+ param:C,
+ param:E]
+*/
+method5(dynamic o, dynamic a, B b, C c, dynamic d, E e) {
+ if (o is! Class5<A, B>) return;
+ o.method5<D, E>(a, b, c, d, e);
+}
+
+/*element: Class6.:static=[Object.(0)]*/
+class Class6<T1, T2> {
+ /*element: Class6.method6:
+ static=*,
+ type=[
+ inst:*,
+ param:C,
+ param:Class6.T1,
+ param:Class6.T2,
+ param:Object,
+ param:method6.S1,
+ param:method6.S2]
+ */
+ method6<S1, S2>(T1 a, {T2 b, C c, S1 d, S2 e}) {}
+}
+
+/*element: method6:
+ dynamic=[Class6.method6<D,E>(1,b,c,d,e)],
+ static=*,
+ type=[
+ impl:A,
+ impl:D,
+ inst:*,
+ is:Class6<A,B>,
+ param:B,
+ param:C,
+ param:E]
+*/
+method6(dynamic o, dynamic a, B b, C c, dynamic d, E e) {
+ if (o is! Class6<A, B>) return;
+ o.method6<D, E>(a, d: d, b: b, e: e, c: c);
+}
+
+/*element: Class7.:static=[Object.(0)]*/
+class Class7 {
+ /*element: Class7.f:type=[inst:JSNull]*/
+ A Function(A) get f => null;
+}
+
+/*element: method7:
+ dynamic=[Class7.f(1),call(1)],
+ type=[impl:A,inst:JSBool,is:Class7]
+*/
+method7(dynamic o, dynamic a) {
+ if (o is! Class7) return;
+ o.f(a);
+}
+
+/*element: F.:static=[Object.(0)]*/
+class F<T> {
+ /*element: F.method:static=*,type=[inst:*,param:List<F.T>]*/
+ T method(List<T> list) => null;
+
+ /*element: F.field:static=*,type=[inst:*,param:F.T]*/
+ T field;
+}
+
+/*element: G.:static=[F.(0)]*/
+class G extends F<int> {}
+
+/*element: method8:
+ dynamic=[G.method(1)],
+ static=*,
+ type=[impl:List<int>,inst:*,is:G,param:Iterable<int>]
+*/
+method8(dynamic g, Iterable<int> iterable) {
+ if (g is! G) return null;
+ return g.method(iterable);
+}
+
+/*element: method9:
+ dynamic=[G.field=],
+ type=[impl:int,inst:JSBool,inst:JSNull,is:G,param:num]
+*/
+method9(dynamic g, num value) {
+ if (g is! G) return null;
+ return g.field = value;
+}
+
+/*element: main:**/
+main() {
+ method1(new Class1(), null);
+ method2(new Class2<A>(), null);
+ method3(new Class3(), null, null, null);
+ method4(new Class4(), null, null, null);
+ method5(new Class5<A, B>(), null, null, null, null, null);
+ method6(new Class6<A, B>(), null, null, null, null, null);
+ method7(new Class7(), null);
+ method8(new G(), null);
+ method9(new G(), null);
+}
diff --git a/tests/compiler/dart2js/impact/impact_test.dart b/tests/compiler/dart2js/impact/impact_test.dart
index 2dc7d40..1237e4c 100644
--- a/tests/compiler/dart2js/impact/impact_test.dart
+++ b/tests/compiler/dart2js/impact/impact_test.dart
@@ -9,7 +9,6 @@
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/ir/util.dart';
import 'package:compiler/src/kernel/kernel_strategy.dart';
-import 'package:compiler/src/kernel/element_map_impl.dart';
import 'package:compiler/src/universe/feature.dart';
import 'package:compiler/src/universe/use.dart';
import 'package:compiler/src/universe/world_impact.dart';
diff --git a/tests/compiler/dart2js/inference/data/map_tracer_keys.dart b/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
index af96537..576a02a 100644
--- a/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
+++ b/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
@@ -58,16 +58,16 @@
test2() {
dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
theMap
- /*update: Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+ /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble])*/
[aList2] = 5.5;
/*iterator: [exact=LinkedHashMapKeyIterable]*/
/*current: [exact=LinkedHashMapKeyIterator]*/
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
for (var key in theMap.
- /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+ /*Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble])*/
keys) {
aDouble2 = theMap
- /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+ /*Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble])*/
[key];
}
// We have to reference it somewhere, so that it always gets resolved.
diff --git a/tests/compiler/dart2js/inference/libs/mixin_constructor_default_parameter_values_lib.dart b/tests/compiler/dart2js/inference/libs/mixin_constructor_default_parameter_values_lib.dart
index a105fa0..8ae50e9 100644
--- a/tests/compiler/dart2js/inference/libs/mixin_constructor_default_parameter_values_lib.dart
+++ b/tests/compiler/dart2js/inference/libs/mixin_constructor_default_parameter_values_lib.dart
@@ -6,6 +6,7 @@
/*element: _SECRET.:[exact=_SECRET]*/
const _SECRET();
/*element: _SECRET.toString:Value([exact=JSString], value: "SECRET!")*/
+ @override
String toString() => "SECRET!";
}
@@ -29,5 +30,6 @@
this.y = b;
/*element: C.toString:[exact=JSString]*/
+ @override
String toString() => "C(${/*[exact=D]*/ x},${/*[exact=D]*/ y})";
}
diff --git a/tests/compiler/dart2js/inference/type_combination_test.dart b/tests/compiler/dart2js/inference/type_combination_test.dart
index cddae20..cc65647 100644
--- a/tests/compiler/dart2js/inference/type_combination_test.dart
+++ b/tests/compiler/dart2js/inference/type_combination_test.dart
@@ -54,7 +54,9 @@
final first;
final second;
Pair(this.first, this.second);
+ @override
int get hashCode => first.hashCode * 47 + second.hashCode;
+ @override
bool operator ==(other) =>
other is Pair &&
identical(first, other.first) &&
diff --git a/tests/compiler/dart2js/js/js_spec_string_test.dart b/tests/compiler/dart2js/js/js_spec_string_test.dart
index 0dc8344..193a39f 100644
--- a/tests/compiler/dart2js/js/js_spec_string_test.dart
+++ b/tests/compiler/dart2js/js/js_spec_string_test.dart
@@ -15,11 +15,13 @@
class Listener extends DiagnosticReporter {
String errorMessage;
+ @override
internalError(spannable, message) {
errorMessage = message;
throw "error";
}
+ @override
reportError(message, [infos = const <DiagnosticMessage>[]]) {
errorMessage =
'${message.message.arguments}'; // E.g. "{text: Duplicate tag 'new'.}"
@@ -33,6 +35,7 @@
MessageTemplate.TEMPLATES[messageKind].message(arguments));
}
+ @override
noSuchMethod(_) => null;
}
diff --git a/tests/compiler/dart2js/jumps/jump_test.dart b/tests/compiler/dart2js/jumps/jump_test.dart
index 4d954d7..5ea39a1 100644
--- a/tests/compiler/dart2js/jumps/jump_test.dart
+++ b/tests/compiler/dart2js/jumps/jump_test.dart
@@ -56,6 +56,7 @@
TargetData(this.index, this.id, this.sourceSpan, this.target);
+ @override
String toString() => 'TargetData(index=$index,id=$id,'
'sourceSpan=$sourceSpan,target=$target)';
}
@@ -67,6 +68,7 @@
GotoData(this.id, this.sourceSpan, this.target);
+ @override
String toString() => 'GotoData(id=$id,sourceSpan=$sourceSpan,target=$target)';
}
@@ -113,6 +115,7 @@
});
}
+ @override
void run(ir.Node root) {
super.run(root);
processData();
@@ -136,30 +139,35 @@
}
}
+ @override
visitForStatement(ir.ForStatement node) {
addTargetData(
node, createLoopId(node), _localsMap.getJumpTargetForFor(node));
super.visitForStatement(node);
}
+ @override
visitForInStatement(ir.ForInStatement node) {
addTargetData(
node, createLoopId(node), _localsMap.getJumpTargetForForIn(node));
super.visitForInStatement(node);
}
+ @override
visitWhileStatement(ir.WhileStatement node) {
addTargetData(
node, createLoopId(node), _localsMap.getJumpTargetForWhile(node));
super.visitWhileStatement(node);
}
+ @override
visitDoStatement(ir.DoStatement node) {
addTargetData(
node, createLoopId(node), _localsMap.getJumpTargetForDo(node));
super.visitDoStatement(node);
}
+ @override
visitBreakStatement(ir.BreakStatement node) {
JumpTarget target = _localsMap.getJumpTargetForBreak(node);
assert(target != null, 'No target for $node.');
@@ -180,18 +188,21 @@
super.visitLabeledStatement(node);
}
+ @override
visitSwitchStatement(ir.SwitchStatement node) {
addTargetData(
node, createSwitchId(node), _localsMap.getJumpTargetForSwitch(node));
super.visitSwitchStatement(node);
}
+ @override
visitSwitchCase(ir.SwitchCase node) {
addTargetData(node, createSwitchCaseId(node),
_localsMap.getJumpTargetForSwitchCase(node));
super.visitSwitchCase(node);
}
+ @override
visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
JumpTarget target = _localsMap.getJumpTargetForContinueSwitch(node);
assert(target != null, 'No target for $node.');
diff --git a/tests/compiler/dart2js/model/cfe_annotations_test.dart b/tests/compiler/dart2js/model/cfe_annotations_test.dart
index b6eed0b..4f8c619 100644
--- a/tests/compiler/dart2js/model/cfe_annotations_test.dart
+++ b/tests/compiler/dart2js/model/cfe_annotations_test.dart
@@ -24,11 +24,36 @@
library lib;
+import 'package:meta/dart2js.dart';
+
import 'jslib1.dart';
import 'jslib2.dart';
import 'nativelib.dart';
+@pragma('dart2js:noInline')
+method1() {}
+
+@noInline
+method2() {}
+
+@pragma('dart2js:tryInline')
+method3() {}
+
+@tryInline
+method4() {}
+
main() {
+ method1();
+ method2();
+ method3();
+ method4();
+ new JsClass1()..jsMethod1()..jsMethod2();
+ new JsClass2();
+ jsMethod3();
+ new NativeClass1()..nativeMethod()..nativeField;
+ new NativeClass2()..nativeField;
+ new NativeClass3()..nativeMethod()..nativeGetter;
+ nativeMethod();
}
''',
'$pathPrefix/jslib1.dart': '''
@@ -39,11 +64,11 @@
import 'package:js/js.dart';
@JS('JsInteropClass1')
-class Class1 {
+class JsClass1 {
@JS('jsInteropMethod1')
- external method1();
+ external jsMethod1();
- external method2();
+ external jsMethod2();
}
''',
@@ -56,35 +81,68 @@
@JS()
@anonymous
-class Class2 {
+class JsClass2 {
}
@JS('jsInteropMethod3')
-external method3();
+external jsMethod3();
''',
'$pathPrefix/nativelib.dart': '''
+library lib3;
+
import 'dart:_js_helper';
-@Native('NativeClass1')
-class Class1 {
+@Native('Class1')
+class NativeClass1 {
+ @JSName('field1')
+ var nativeField;
+
+ @JSName('method1')
+ nativeMethod() native;
}
-@Native('NativeClass2,!nonleaf')
-class Class2 {
+@Native('Class2,!nonleaf')
+class NativeClass2 {
+ @JSName('field2')
+ var nativeField;
}
-@Native('NativeClass3a,NativeClass3b')
-class Class3 {
+@Native('Class3a,Class3b')
+class NativeClass3 {
+
+ @JSName('method2')
+ get nativeGetter native;
+
+ @Creates('String')
+ @Returns('int')
+ nativeMethod() native;
}
-
+@JSName('method3')
+nativeMethod() native;
''',
};
const Map<String, String> expectedNativeClassNames = {
- '$pathPrefix/nativelib.dart::Class1': 'NativeClass1',
- '$pathPrefix/nativelib.dart::Class2': 'NativeClass2,!nonleaf',
- '$pathPrefix/nativelib.dart::Class3': 'NativeClass3a,NativeClass3b',
+ '$pathPrefix/nativelib.dart::NativeClass1': 'Class1',
+ '$pathPrefix/nativelib.dart::NativeClass2': 'Class2,!nonleaf',
+ '$pathPrefix/nativelib.dart::NativeClass3': 'Class3a,Class3b',
+};
+
+const Map<String, String> expectedNativeMemberNames = {
+ '$pathPrefix/nativelib.dart::NativeClass1::nativeField': 'field1',
+ '$pathPrefix/nativelib.dart::NativeClass1::nativeMethod': 'method1',
+ '$pathPrefix/nativelib.dart::NativeClass2::nativeField': 'field2',
+ '$pathPrefix/nativelib.dart::NativeClass3::nativeGetter': 'method2',
+ '$pathPrefix/nativelib.dart::nativeMethod': 'method3',
+};
+
+const Map<String, String> expectedCreates = {
+ '$pathPrefix/nativelib.dart::NativeClass3::nativeMethod': 'String',
+};
+
+const Map<String, String> expectedReturns = {
+ '$pathPrefix/nativelib.dart::NativeClass3::nativeMethod': 'int',
};
const Map<String, String> expectedJsInteropLibraryNames = {
@@ -93,17 +151,27 @@
};
const Map<String, String> expectedJsInteropClassNames = {
- '$pathPrefix/jslib1.dart::Class1': 'JsInteropClass1',
- '$pathPrefix/jslib2.dart::Class2': '',
+ '$pathPrefix/jslib1.dart::JsClass1': 'JsInteropClass1',
+ '$pathPrefix/jslib2.dart::JsClass2': '',
};
const Map<String, String> expectedJsInteropMemberNames = {
- '$pathPrefix/jslib1.dart::Class1::method1': 'jsInteropMethod1',
- '$pathPrefix/jslib2.dart::method3': 'jsInteropMethod3',
+ '$pathPrefix/jslib1.dart::JsClass1::jsMethod1': 'jsInteropMethod1',
+ '$pathPrefix/jslib2.dart::jsMethod3': 'jsInteropMethod3',
};
const Set<String> expectedAnonymousJsInteropClasses = {
- '$pathPrefix/jslib2.dart::Class2',
+ '$pathPrefix/jslib2.dart::JsClass2',
+};
+
+const Set<String> expectedNoInlineMethods = {
+ '$pathPrefix/main.dart::method1',
+ '$pathPrefix/main.dart::method2',
+};
+
+const Set<String> expectedTryInlineMethods = {
+ '$pathPrefix/main.dart::method3',
+ '$pathPrefix/main.dart::method4',
};
main(List<String> args) {
@@ -116,6 +184,7 @@
List<String> options = getOptions(argResults);
runTest({bool useIr}) async {
+ useIrAnnotationsDataForTesting = useIr;
CompilationResult result = await runCompiler(
entryPoint: Uri.parse('memory:$pathPrefix/main.dart'),
memorySourceFiles: source,
@@ -132,23 +201,63 @@
NativeData nativeData =
compiler.resolutionWorldBuilder.closedWorldForTesting.nativeData;
ir.Component component = elementMap.env.mainComponent;
- IrAnnotationData annotationData;
- if (useIr) {
- annotationData = processAnnotations(component);
- }
+ IrAnnotationData annotationData =
+ frontendStrategy.irAnnotationDataForTesting;
void testMember(String idPrefix, ir.Member member,
- {bool implicitJsInteropMember}) {
+ {bool implicitJsInteropMember, bool implicitNativeMember}) {
String memberId = '$idPrefix::${member.name.name}';
MemberEntity memberEntity = elementMap.getMember(member);
String expectedJsInteropMemberName =
expectedJsInteropMemberNames[memberId];
+ String expectedNativeMemberName = expectedNativeMemberNames[memberId];
+ Set<String> expectedPragmaNames = {};
+ if (expectedNoInlineMethods.contains(memberId)) {
+ expectedPragmaNames.add('dart2js:noInline');
+ }
+ if (expectedTryInlineMethods.contains(memberId)) {
+ expectedPragmaNames.add('dart2js:tryInline');
+ }
+
+ String expectedCreatesText = expectedCreates[memberId];
+ String expectedReturnsText = expectedReturns[memberId];
+
if (useIr) {
Expect.equals(
expectedJsInteropMemberName,
annotationData.getJsInteropMemberName(member),
- "Unexpected js interop member name from IR for $member");
+ "Unexpected js interop member name from IR for $member, "
+ "id: $memberId");
+
+ Expect.equals(
+ expectedNativeMemberName,
+ annotationData.getNativeMemberName(member),
+ "Unexpected js interop member name from IR for $member, "
+ "id: $memberId");
+
+ List<PragmaAnnotationData> pragmaAnnotations =
+ annotationData.getMemberPragmaAnnotationData(member);
+ Set<String> pragmaNames =
+ pragmaAnnotations.map((d) => d.name).toSet();
+ Expect.setEquals(expectedPragmaNames, pragmaNames,
+ "Unexpected pragmas from IR for $member, " "id: $memberId");
+
+ List<String> createsAnnotations =
+ annotationData.getCreatesAnnotations(member);
+ Expect.equals(
+ expectedCreatesText,
+ createsAnnotations.isEmpty ? null : createsAnnotations.join(','),
+ "Unexpected create annotations from IR for $member, "
+ "id: $memberId");
+
+ List<String> returnsAnnotations =
+ annotationData.getReturnsAnnotations(member);
+ Expect.equals(
+ expectedReturnsText,
+ returnsAnnotations.isEmpty ? null : returnsAnnotations.join(','),
+ "Unexpected returns annotations from IR for $member, "
+ "id: $memberId");
}
bool isJsInteropMember =
(implicitJsInteropMember && member.isExternal) ||
@@ -156,13 +265,82 @@
Expect.equals(
isJsInteropMember,
nativeData.isJsInteropMember(memberEntity),
- "Unexpected js interop member result from native data for $member");
+ "Unexpected js interop member result from native data for $member, "
+ "id: $memberId");
Expect.equals(
isJsInteropMember
? expectedJsInteropMemberName ?? memberEntity.name
: null,
nativeData.getJsInteropMemberName(memberEntity),
- "Unexpected js interop member name from native data for $member");
+ "Unexpected js interop member name from native data for $member, "
+ "id: $memberId");
+
+ bool isNativeMember =
+ implicitNativeMember || expectedNativeMemberName != null;
+ Expect.equals(
+ isNativeMember || isJsInteropMember,
+ nativeData.isNativeMember(memberEntity),
+ "Unexpected native member result from native data for $member, "
+ "id: $memberId");
+ Expect.equals(
+ isNativeMember
+ ? expectedNativeMemberName ?? memberEntity.name
+ : (isJsInteropMember
+ ? expectedJsInteropMemberName ?? memberEntity.name
+ : null),
+ nativeData.getFixedBackendName(memberEntity),
+ "Unexpected fixed backend name from native data for $member, "
+ "id: $memberId");
+
+ if (expectedCreatesText != null) {
+ String createsText;
+ if (memberEntity.isField) {
+ createsText = nativeData
+ .getNativeFieldLoadBehavior(memberEntity)
+ .typesInstantiated
+ .join(',');
+ } else {
+ createsText = nativeData
+ .getNativeMethodBehavior(memberEntity)
+ .typesInstantiated
+ .join(',');
+ }
+ Expect.equals(
+ expectedCreatesText,
+ createsText,
+ "Unexpected create annotations from native data for $member, "
+ "id: $memberId");
+ }
+
+ if (expectedReturnsText != null) {
+ String returnsText;
+ if (memberEntity.isField) {
+ returnsText = nativeData
+ .getNativeFieldLoadBehavior(memberEntity)
+ .typesReturned
+ .join(',');
+ } else {
+ returnsText = nativeData
+ .getNativeMethodBehavior(memberEntity)
+ .typesReturned
+ .join(',');
+ }
+ Expect.equals(
+ expectedReturnsText,
+ returnsText,
+ "Unexpected returns annotations from native data for $member, "
+ "id: $memberId");
+ }
+
+ List<PragmaAnnotationData> pragmaAnnotations = frontendStrategy
+ .modularStrategyForTesting
+ .getPragmaAnnotationData(member);
+ Set<String> pragmaNames = pragmaAnnotations.map((d) => d.name).toSet();
+ Expect.setEquals(
+ expectedPragmaNames,
+ pragmaNames,
+ "Unexpected pragmas from modular strategy for $member, "
+ "id: $memberId");
}
for (ir.Library library in component.libraries) {
@@ -248,20 +426,24 @@
for (ir.Member member in cls.members) {
testMember(clsId, member,
implicitJsInteropMember:
- nativeData.isJsInteropClass(classEntity));
+ nativeData.isJsInteropClass(classEntity),
+ implicitNativeMember: member is! ir.Constructor &&
+ nativeData.isNativeClass(classEntity) &&
+ !nativeData.isJsInteropClass(classEntity));
}
}
for (ir.Member member in library.members) {
- testMember(libraryId, member, implicitJsInteropMember: false);
+ testMember(libraryId, member,
+ implicitJsInteropMember: false, implicitNativeMember: false);
}
}
}
}
- print('test annotations from IR');
- await runTest(useIr: true);
-
print('test annotations from K-model');
await runTest(useIr: false);
+
+ print('test annotations from IR');
+ await runTest(useIr: true);
});
}
diff --git a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
index c5c9d5b..fafdcbb 100644
--- a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
+++ b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
@@ -64,6 +64,7 @@
MemoryEnvironment(this._environment, [this.env = const <String, String>{}]);
+ @override
bool get checkCasts => true;
@override
diff --git a/tests/compiler/dart2js/model/enqueuer_test.dart b/tests/compiler/dart2js/model/enqueuer_test.dart
index 8a8a6a6..3417206 100644
--- a/tests/compiler/dart2js/model/enqueuer_test.dart
+++ b/tests/compiler/dart2js/model/enqueuer_test.dart
@@ -71,6 +71,7 @@
const Impact.invoke(this.clsName, this.memberName)
: this.kind = ImpactKind.invoke;
+ @override
String toString() =>
'Impact(kind=$kind,clsName=$clsName,memberName=$memberName)';
}
diff --git a/tests/compiler/dart2js/model/native_test.dart b/tests/compiler/dart2js/model/native_test.dart
index 3e7284b..c281c63f 100644
--- a/tests/compiler/dart2js/model/native_test.dart
+++ b/tests/compiler/dart2js/model/native_test.dart
@@ -290,6 +290,7 @@
return sb.toString();
}
+ @override
String toString() {
return lines.values.join('\n');
}
diff --git a/tests/compiler/dart2js/model/strong_mode_impact_test.dart b/tests/compiler/dart2js/model/strong_mode_impact_test.dart
index 1b2f5ad..eec9e9d 100644
--- a/tests/compiler/dart2js/model/strong_mode_impact_test.dart
+++ b/tests/compiler/dart2js/model/strong_mode_impact_test.dart
@@ -136,6 +136,7 @@
this.implicitCasts: const <String>[],
this.parameterChecks: const <String>[]});
+ @override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('Impact(');
diff --git a/tests/compiler/dart2js/optimization/data/index.dart b/tests/compiler/dart2js/optimization/data/index.dart
index 12586ad..b6dd480 100644
--- a/tests/compiler/dart2js/optimization/data/index.dart
+++ b/tests/compiler/dart2js/optimization/data/index.dart
@@ -40,6 +40,7 @@
/*strong.element: mutableDynamicListDynamicIndex:Specializer=[!Index]*/
/*omit.element: mutableDynamicListDynamicIndex:Specializer=[Index]*/
@pragma('dart2js:noInline')
+@pragma('dart2js:disableFinal')
mutableDynamicListDynamicIndex(dynamic index) {
dynamic list = [0];
return list[index];
diff --git a/tests/compiler/dart2js/rti/emission/function_typed_arguments.dart b/tests/compiler/dart2js/rti/emission/function_typed_arguments.dart
new file mode 100644
index 0000000..a434694
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/function_typed_arguments.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+/*class: A:checkedInstance,checks=[],instance*/
+class A<T> {}
+
+main() {
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+}
+
+/*class: B1:checkedTypeArgument,checks=[],typeArgument*/
+class B1<T> {}
+
+/*class: C1:checkedTypeArgument,checks=[$asB1],typeArgument*/
+class C1 extends B1<int> {}
+
+@pragma('dart2js:noInline')
+test1() {
+ Expect.isTrue(_test1(new A<void Function(C1)>()));
+ Expect.isTrue(_test1(new A<void Function(B1<int>)>()));
+ Expect.isFalse(_test1(new A<void Function(B1<String>)>()));
+}
+
+@pragma('dart2js:noInline')
+_test1(f) => f is A<void Function(C1)>;
+
+/*class: B2:checks=[],typeArgument*/
+class B2<T> {}
+
+/*class: C2:checkedTypeArgument,checks=[],typeArgument*/
+class C2 extends B2<int> {}
+
+@pragma('dart2js:noInline')
+test2() {
+ Expect.isTrue(_test2(new A<C2 Function()>()));
+ Expect.isFalse(_test2(new A<B2<int> Function()>()));
+ Expect.isFalse(_test2(new A<B2<String> Function()>()));
+}
+
+@pragma('dart2js:noInline')
+_test2(f) => f is A<C2 Function()>;
+
+/*class: B3:checkedTypeArgument,checks=[],typeArgument*/
+class B3<T> {}
+
+/*class: C3:checkedTypeArgument,checks=[$asB3],typeArgument*/
+class C3 extends B3<int> {}
+
+@pragma('dart2js:noInline')
+test3() {
+ Expect.isFalse(_test3(new A<void Function(C3)>()));
+ Expect.isTrue(_test3(new A<void Function(B3<int>)>()));
+ Expect.isFalse(_test3(new A<void Function(B3<String>)>()));
+}
+
+@pragma('dart2js:noInline')
+_test3(f) => f is A<void Function(B3<int>)>;
+
+/*class: B4:checkedTypeArgument,checks=[],typeArgument*/
+class B4<T> {}
+
+/*class: C4:checks=[$asB4],typeArgument*/
+class C4 extends B4<int> {}
+
+@pragma('dart4js:noInline')
+test4() {
+ Expect.isTrue(_test4(new A<C4 Function()>()));
+ Expect.isTrue(_test4(new A<B4<int> Function()>()));
+ Expect.isFalse(_test4(new A<B4<String> Function()>()));
+}
+
+@pragma('dart4js:noInline')
+_test4(f) => f is A<B4<int> Function()>;
+
+/*class: B5:checkedTypeArgument,checks=[],typeArgument*/
+class B5<T> {}
+
+/*class: C5:checkedTypeArgument,checks=[$asB5],typeArgument*/
+class C5 extends B5<int> {}
+
+@pragma('dart2js:noInline')
+test5() {
+ Expect.isTrue(_test5(new A<void Function(C5 Function())>()));
+ Expect.isTrue(_test5(new A<void Function(B5<int> Function())>()));
+ Expect.isFalse(_test5(new A<void Function(B5<String> Function())>()));
+}
+
+@pragma('dart2js:noInline')
+_test5(f) => f is A<void Function(C5 Function())>;
+
+/*class: B6:checks=[],typeArgument*/
+class B6<T> {}
+
+/*class: C6:checkedTypeArgument,checks=[],typeArgument*/
+class C6 extends B6<int> {}
+
+@pragma('dart2js:noInline')
+test6() {
+ Expect.isTrue(_test6(new A<void Function(void Function(C6))>()));
+ Expect.isFalse(_test6(new A<void Function(void Function(B6<int>))>()));
+ Expect.isFalse(_test6(new A<void Function(void Function(B6<String>))>()));
+}
+
+@pragma('dart2js:noInline')
+_test6(f) => f is A<void Function(void Function(C6))>;
diff --git a/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02.dart b/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02.dart
index e091714..947dcca 100644
--- a/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02.dart
+++ b/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02.dart
@@ -20,6 +20,7 @@
List<T> bar<T>(Iterable<T> t) => <T>[t.first];
}
+@pragma('dart2js:disableFinal')
main() {
B b = new B();
C c = new C();
diff --git a/tests/compiler/dart2js/rti/emission/tear_off_types.dart b/tests/compiler/dart2js/rti/emission/tear_off_types.dart
new file mode 100644
index 0000000..86d41eb
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/tear_off_types.dart
@@ -0,0 +1,159 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+main() {
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
+}
+
+/*class: A1:checkedTypeArgument,checks=[],typeArgument*/
+class A1<T> {}
+
+/*class: B1:checks=[$asA1],typeArgument*/
+class B1 extends A1<int> {}
+
+@pragma('dart2js:noInline')
+test1() {
+ Expect.isTrue(_test1(method1a));
+ Expect.isTrue(_test1(method1b));
+ Expect.isFalse(_test1(method1c));
+}
+
+B1 method1a() => null;
+A1<int> method1b() => null;
+A1<String> method1c() => null;
+
+@pragma('dart2js:noInline')
+bool _test1(f) => f is A1<int> Function();
+
+/*strong.class: A2:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+/*omit.class: A2:checkedTypeArgument,checks=[],typeArgument*/
+class A2<T> {}
+
+/*strong.class: B2:checkedInstance,checkedTypeArgument,checks=[$asA2],typeArgument*/
+/*omit.class: B2:checkedTypeArgument,checks=[$asA2],typeArgument*/
+class B2 extends A2<int> {}
+
+@pragma('dart2js:noInline')
+test2() {
+ Expect.isFalse(_test2(method2a));
+ Expect.isTrue(_test2(method2b));
+ Expect.isFalse(_test2(method2c));
+}
+
+void method2a(B2 b) {}
+void method2b(A2<int> a) {}
+void method2c(A2<String> a) {}
+
+@pragma('dart2js:noInline')
+bool _test2(f) => f is void Function(A2<int>);
+
+/*strong.class: A3:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+/*omit.class: A3:checkedTypeArgument,checks=[],typeArgument*/
+class A3<T> {}
+
+/*strong.class: B3:checkedInstance,checkedTypeArgument,checks=[$asA3],typeArgument*/
+/*omit.class: B3:checkedTypeArgument,checks=[$asA3],typeArgument*/
+class B3 extends A3<int> {}
+
+@pragma('dart3js:noInline')
+test3() {
+ Expect.isTrue(_test3(method3a));
+ Expect.isTrue(_test3(method3b));
+ Expect.isFalse(_test3(method3c));
+}
+
+void method3a(B3 b) {}
+void method3b(A3<int> a) {}
+void method3c(A3<String> a) {}
+
+@pragma('dart3js:noInline')
+_test3(f) => f is void Function(B3);
+
+/*class: A4:checks=[],typeArgument*/
+class A4<T> {}
+
+/*class: B4:checkedTypeArgument,checks=[],typeArgument*/
+class B4 extends A4<int> {}
+
+@pragma('dart4js:noInline')
+test4() {
+ Expect.isTrue(_test4(method4a));
+ Expect.isFalse(_test4(method4b));
+ Expect.isFalse(_test4(method4c));
+}
+
+B4 method4a() => null;
+A4<int> method4b() => null;
+A4<String> method4c() => null;
+
+@pragma('dart4js:noInline')
+_test4(f) => f is B4 Function();
+
+/*class: A5:checkedTypeArgument,checks=[],typeArgument*/
+class A5<T> {}
+
+/*class: B5:checks=[$asA5],typeArgument*/
+class B5 extends A5<int> {}
+
+@pragma('dart2js:noInline')
+test5() {
+ Expect.isTrue(_test5(method5a));
+ Expect.isTrue(_test5(method5b));
+ Expect.isFalse(_test5(method5c));
+}
+
+void method5a(void Function(B5) f) => null;
+void method5b(void Function(A5<int>) f) => null;
+void method5c(void Function(A5<String>) f) => null;
+
+@pragma('dart2js:noInline')
+bool _test5(f) => f is void Function(void Function(A5<int>));
+
+/*class: A6:checkedTypeArgument,checks=[],typeArgument*/
+class A6<T> {}
+
+/*class: B6:checkedTypeArgument,checks=[$asA6],typeArgument*/
+class B6 extends A6<int> {}
+
+@pragma('dart6js:noInline')
+test6() {
+ Expect.isTrue(_test6(method6a));
+ Expect.isTrue(_test6(method6b));
+ Expect.isFalse(_test6(method6c));
+}
+
+void Function(B6) method6a() => null;
+void Function(A6<int>) method6b() => null;
+void Function(A6<String>) method6c() => null;
+
+@pragma('dart6js:noInline')
+_test6(f) => f is void Function(B6) Function();
+
+/*class: A7:checks=[],typeArgument*/
+class A7<T> {}
+
+/*class: B7:checkedTypeArgument,checks=[],typeArgument*/
+class B7 extends A7<int> {}
+
+@pragma('dart7js:noInline')
+test7() {
+ Expect.isTrue(_test7(method7a));
+ Expect.isFalse(_test7(method7b));
+ Expect.isFalse(_test7(method7c));
+}
+
+void method7a(void Function(B7) f) => null;
+void method7b(void Function(A7<int>) f) => null;
+void method7c(void Function(A7<String>) f) => null;
+
+@pragma('dart7js:noInline')
+_test7(f) => f is void Function(void Function(B7));
diff --git a/tests/compiler/dart2js/rti/rti_emission_test.dart b/tests/compiler/dart2js/rti/rti_emission_test.dart
index 5b7e145..0e580ca 100644
--- a/tests/compiler/dart2js/rti/rti_emission_test.dart
+++ b/tests/compiler/dart2js/rti/rti_emission_test.dart
@@ -125,12 +125,15 @@
class RtiClassEmissionIrComputer extends DataRegistry<String>
with ComputeValueMixin {
+ @override
final Compiler compiler;
final JsToElementMap _elementMap;
+ @override
final Map<Id, ActualData<String>> actualMap;
RtiClassEmissionIrComputer(this.compiler, this._elementMap, this.actualMap);
+ @override
DiagnosticReporter get reporter => compiler.reporter;
void computeClassValue(ClassEntity cls) {
@@ -145,6 +148,7 @@
with ComputeValueMixin {
final JsToElementMap _elementMap;
final ClosureData _closureDataLookup;
+ @override
final Compiler compiler;
RtiMemberEmissionIrComputer(
diff --git a/tests/compiler/dart2js/rti/rti_need_test_helper.dart b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
index f601ebc..4c54942 100644
--- a/tests/compiler/dart2js/rti/rti_need_test_helper.dart
+++ b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
@@ -318,12 +318,15 @@
class RtiClassNeedIrComputer extends DataRegistry<String>
with ComputeValueMixin, IrMixin {
+ @override
final Compiler compiler;
final JsToElementMap _elementMap;
+ @override
final Map<Id, ActualData<String>> actualMap;
RtiClassNeedIrComputer(this.compiler, this._elementMap, this.actualMap);
+ @override
DiagnosticReporter get reporter => compiler.reporter;
void computeClassValue(ClassEntity cls) {
@@ -339,6 +342,7 @@
with ComputeValueMixin, IrMixin {
final JsToElementMap _elementMap;
final ClosureData _closureDataLookup;
+ @override
final Compiler compiler;
RtiMemberNeedIrComputer(
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/colors.dart b/tests/compiler/dart2js/sourcemaps/helpers/colors.dart
index 4595382..f3d435d 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/colors.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/colors.dart
@@ -22,6 +22,7 @@
/// all in range 0..1.
const RGB(this.r, this.g, this.b);
+ @override
String get toCss {
StringBuffer sb = new StringBuffer();
sb.write('#');
@@ -41,6 +42,7 @@
return sb.toString();
}
+ @override
String toString() => 'rgb($r,$g,$b)';
}
@@ -49,6 +51,7 @@
const RGBA(double r, double g, double b, this.a) : super(r, g, b);
+ @override
String get toCss {
StringBuffer sb = new StringBuffer();
@@ -84,6 +87,7 @@
/// saturation [s] in range 0..1, and value [v] in range 0..1.
const HSV(this.h, this.s, this.v);
+ @override
String get toCss => toRGB(this).toCss;
static RGB toRGB(HSV hsv) {
@@ -116,5 +120,6 @@
}
}
+ @override
String toString() => 'hsv($h,$s,$v)';
}
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/diff.dart b/tests/compiler/dart2js/sourcemaps/helpers/diff.dart
index 7be8f761..012679e 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/diff.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/diff.dart
@@ -24,14 +24,17 @@
const DiffColumn(this.type, [this.index]);
+ @override
int get hashCode => type.hashCode * 19 + index.hashCode * 23;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! DiffColumn) return false;
return type == other.type && index == other.index;
}
+ @override
String toString() => '$type${index != null ? index : ''}';
}
@@ -46,6 +49,7 @@
PartsColumnBlock(this.parts);
+ @override
void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
if (parts.isNotEmpty) {
for (HtmlPart part in parts) {
@@ -62,6 +66,7 @@
CodeLinesColumnBlock(this.jsCodeLines, this.jsToDartMap);
+ @override
void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
if (jsCodeLines.isNotEmpty) {
htmlBuffer.write('<table style="width:100%">');
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/html_parts.dart b/tests/compiler/dart2js/sourcemaps/helpers/html_parts.dart
index 77dd7cf..ad951bc 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/html_parts.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/html_parts.dart
@@ -36,8 +36,10 @@
const AnnotationData(
{this.tag: 'a', this.properties: const <String, String>{}});
+ @override
int get hashCode => tag.hashCode * 13 + properties.hashCode * 19;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! AnnotationData) return false;
@@ -171,6 +173,7 @@
const ConstHtmlPart(this.html);
+ @override
HtmlPartKind get kind => HtmlPartKind.CONST;
@override
@@ -178,6 +181,7 @@
buffer.write(html);
}
+ @override
toJson(JsonStrategy strategy) {
return {'kind': kind.index, 'html': html};
}
@@ -190,8 +194,10 @@
class NewLine implements HtmlPart {
const NewLine();
+ @override
HtmlPartKind get kind => HtmlPartKind.NEWLINE;
+ @override
void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
if (context.usePre) {
buffer.write('\n');
@@ -200,6 +206,7 @@
}
}
+ @override
toJson(JsonStrategy strategy) {
return {'kind': kind.index};
}
@@ -210,13 +217,16 @@
const HtmlText(this.text);
+ @override
HtmlPartKind get kind => HtmlPartKind.TEXT;
+ @override
void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
String escaped = escape(text);
buffer.write(escaped);
}
+ @override
toJson(JsonStrategy strategy) {
return {'kind': kind.index, 'text': text};
}
@@ -235,6 +245,7 @@
{this.properties: const <String, String>{},
this.content: const <HtmlPart>[]});
+ @override
HtmlPartKind get kind => HtmlPartKind.TAG;
@override
@@ -252,6 +263,7 @@
buffer.write('</$tag>');
}
+ @override
toJson(JsonStrategy strategy) {
return {
'kind': kind.index,
@@ -271,6 +283,7 @@
class HtmlLine implements HtmlPart {
final List<HtmlPart> htmlParts = <HtmlPart>[];
+ @override
HtmlPartKind get kind => HtmlPartKind.LINE;
@override
@@ -280,6 +293,7 @@
}
}
+ @override
Map toJson(JsonStrategy strategy) {
return {
'kind': kind.index,
@@ -370,6 +384,7 @@
LineNumber(this.lineNo, this.lineAnnotation);
+ @override
HtmlPartKind get kind => HtmlPartKind.LINE_NUMBER;
@override
@@ -407,6 +422,7 @@
CodeLine(this.lineNo, this.offset, {this.uri});
+ @override
HtmlPartKind get kind => HtmlPartKind.CODE;
String get code {
@@ -432,6 +448,7 @@
}
}
+ @override
Map toJson(JsonStrategy strategy) {
return {
'kind': kind.index,
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart b/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
index bc504c76..aa234a1 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
@@ -33,6 +33,7 @@
StepTraceListener(this.graph);
+ @override
SourceInformationReader get reader => const SourceInformationReader();
@override
@@ -114,6 +115,7 @@
steppableMap[node] = step;
}
+ @override
void pushBranch(BranchKind kind, [value]) {
var branch;
switch (kind) {
@@ -136,6 +138,7 @@
graph.pushBranch(branch);
}
+ @override
void popBranch() {
graph.popBranch();
}
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart b/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart
index f12212a..ddfd8c9 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart
@@ -86,40 +86,50 @@
abstract class BaseOutputVisitor<R, A> extends OutputVisitor<R, A> {
R visitEntity(OutputEntity entity, A arg) => null;
+ @override
R visitStructure(OutputStructure entity, A arg) => visitEntity(entity, arg);
+ @override
R visitLibrary(LibraryBlock entity, A arg) => visitEntity(entity, arg);
+ @override
R visitClass(LibraryClass entity, A arg) => visitEntity(entity, arg);
R visitMember(BasicEntity entity, A arg) => visitEntity(entity, arg);
R visitTopLevelMember(BasicEntity entity, A arg) => visitMember(entity, arg);
+ @override
R visitTopLevelFunction(TopLevelFunction entity, A arg) {
return visitTopLevelMember(entity, arg);
}
+ @override
R visitTopLevelValue(TopLevelValue entity, A arg) {
return visitTopLevelMember(entity, arg);
}
R visitClassMember(BasicEntity entity, A arg) => visitMember(entity, arg);
+ @override
R visitMemberObject(MemberObject entity, A arg) {
return visitClassMember(entity, arg);
}
+ @override
R visitMemberFunction(MemberFunction entity, A arg) {
return visitClassMember(entity, arg);
}
+ @override
R visitMemberValue(MemberValue entity, A arg) {
return visitClassMember(entity, arg);
}
+ @override
R visitStatics(Statics entity, A arg) {
return visitClassMember(entity, arg);
}
+ @override
R visitStaticFunction(StaticFunction entity, A arg) {
return visitClassMember(entity, arg);
}
@@ -130,6 +140,7 @@
final List<CodeLine> lines;
final int headerEnd;
final int footerStart;
+ @override
final List<LibraryBlock> children;
OutputStructure(this.lines, this.headerEnd, this.footerStart, this.children);
@@ -137,14 +148,19 @@
@override
EntityKind get kind => EntityKind.STRUCTURE;
+ @override
Interval get interval => new Interval(0, lines.length);
+ @override
Interval get header => new Interval(0, headerEnd);
+ @override
Interval get footer => new Interval(footerStart, lines.length);
+ @override
bool get canHaveChildren => true;
+ @override
OutputEntity getEntityForLine(int line) {
if (line < headerEnd || line >= footerStart) {
return this;
@@ -221,6 +237,7 @@
return new OutputStructure(lines, headerEnd, footerStart, libraryBlocks);
}
+ @override
accept(OutputVisitor visitor, arg) => visitor.visitStructure(this, arg);
@override
@@ -252,6 +269,7 @@
AbstractEntity(this.name, this.from);
+ @override
Interval get interval => new Interval(from, to);
@override
@@ -328,6 +346,7 @@
/// A block defining the content of a Dart library.
class LibraryBlock extends AbstractEntity {
+ @override
List<BasicEntity> children = <BasicEntity>[];
int get headerEnd => from + 2;
int get footerStart => to /* - 1*/;
@@ -337,10 +356,13 @@
@override
EntityKind get kind => EntityKind.LIBRARY;
+ @override
Interval get header => new Interval(from, headerEnd);
+ @override
Interval get footer => new Interval(footerStart, to);
+ @override
bool get canHaveChildren => true;
void preprocess(List<CodeLine> lines) {
@@ -383,8 +405,10 @@
}
}
+ @override
accept(OutputVisitor visitor, arg) => visitor.visitLibrary(this, arg);
+ @override
OutputEntity getEntityForLine(int line) {
if (line < headerEnd || line >= footerStart) {
return this;
@@ -402,10 +426,13 @@
abstract class BasicEntity extends AbstractEntity {
BasicEntity(String name, int from) : super(name, from);
+ @override
Interval get header => new Interval(from, to);
+ @override
Interval get footer => new Interval(to, to);
+ @override
List<OutputEntity> get children => const <OutputEntity>[];
void preprocess(List<CodeLine> lines) {}
@@ -425,6 +452,7 @@
@override
EntityKind get kind => EntityKind.TOP_LEVEL_FUNCTION;
+ @override
accept(OutputVisitor visitor, arg) {
return visitor.visitTopLevelFunction(this, arg);
}
@@ -436,6 +464,7 @@
@override
EntityKind get kind => EntityKind.TOP_LEVEL_VALUE;
+ @override
accept(OutputVisitor visitor, arg) {
return visitor.visitTopLevelValue(this, arg);
}
@@ -443,6 +472,7 @@
/// A block defining a Dart class.
class LibraryClass extends BasicEntity {
+ @override
List<BasicEntity> children = <BasicEntity>[];
int get headerEnd => from + 1;
int get footerStart => to - 1;
@@ -452,12 +482,16 @@
@override
EntityKind get kind => EntityKind.CLASS;
+ @override
Interval get header => new Interval(from, headerEnd);
+ @override
Interval get footer => new Interval(footerStart, to);
+ @override
bool get canHaveChildren => true;
+ @override
void preprocess(List<CodeLine> lines) {
int index = headerEnd;
BasicEntity current;
@@ -503,8 +537,10 @@
}
}
+ @override
accept(OutputVisitor visitor, arg) => visitor.visitClass(this, arg);
+ @override
OutputEntity getEntityForLine(int line) {
if (line < headerEnd || line >= footerStart) {
return this;
@@ -520,6 +556,7 @@
/// A block defining static members of a Dart class.
class Statics extends BasicEntity {
+ @override
List<BasicEntity> children = <BasicEntity>[];
int get headerEnd => from + 1;
int get footerStart => to - 1;
@@ -529,12 +566,16 @@
@override
EntityKind get kind => EntityKind.STATICS;
+ @override
Interval get header => new Interval(from, headerEnd);
+ @override
Interval get footer => new Interval(footerStart, to);
+ @override
bool get canHaveChildren => true;
+ @override
void preprocess(List<CodeLine> lines) {
int index = headerEnd;
BasicEntity current;
@@ -561,8 +602,10 @@
}
}
+ @override
accept(OutputVisitor visitor, arg) => visitor.visitStatics(this, arg);
+ @override
OutputEntity getEntityForLine(int line) {
if (line < headerEnd || line >= footerStart) {
return this;
@@ -582,6 +625,7 @@
@override
EntityKind get kind => EntityKind.MEMBER_FUNCTION;
+ @override
accept(OutputVisitor visitor, arg) => visitor.visitMemberFunction(this, arg);
}
@@ -591,6 +635,7 @@
@override
EntityKind get kind => EntityKind.MEMBER_OBJECT;
+ @override
accept(OutputVisitor visitor, arg) => visitor.visitMemberObject(this, arg);
}
@@ -600,6 +645,7 @@
@override
EntityKind get kind => EntityKind.MEMBER_VALUE;
+ @override
accept(OutputVisitor visitor, arg) => visitor.visitMemberValue(this, arg);
}
@@ -609,6 +655,7 @@
@override
EntityKind get kind => EntityKind.STATIC_FUNCTION;
+ @override
accept(OutputVisitor visitor, arg) => visitor.visitStaticFunction(this, arg);
}
@@ -634,6 +681,7 @@
return from - windowSize <= index && index < to + windowSize;
}
+ @override
String toString() => '[$from,$to[';
}
@@ -652,6 +700,7 @@
assert(uri != null);
}
+ @override
String toString() => '$uri:$name:$offset';
Map toJson(JsonStrategy strategy) {
@@ -681,6 +730,7 @@
CodeSource(this.kind, this.uri, this.name, this.begin, this.end);
+ @override
int get hashCode {
return kind.hashCode * 13 +
uri.hashCode * 17 +
@@ -688,6 +738,7 @@
begin.hashCode * 23;
}
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! CodeSource) return false;
@@ -697,6 +748,7 @@
begin == other.begin;
}
+ @override
String toString() => '${toJson()}';
Map toJson() {
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart
index a0b6a5a..aab0969 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart
@@ -304,6 +304,7 @@
return line < other.line || line == other.line && column <= other.column;
}
+ @override
String toString() => '[${line + 1},${column + 1}]';
}
@@ -317,5 +318,6 @@
return begin <= other && other <= end;
}
+ @override
String toString() => '$begin-$end';
}
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
index 8826468..f38c7a6 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
@@ -277,6 +277,7 @@
FindVisitor(this.soughtNode);
+ @override
visitNode(js.Node node) {
if (node == soughtNode) {
found = true;
@@ -437,6 +438,7 @@
element != null ? computeElementNameForSourceMaps(element) : '',
this.element = element;
+ @override
String toString() {
return '$name:$element';
}
@@ -473,8 +475,10 @@
@override
void registerPop(int codeOffset, {bool isEmpty: false}) {}
+ @override
Iterable<js.Node> get nodes => _nodeMap.keys;
+ @override
Map<int, List<SourceLocation>> operator [](js.Node node) {
return _nodeMap[node];
}
@@ -486,8 +490,10 @@
_FilteredLocationMap(this._nodes, this.map);
+ @override
Iterable<js.Node> get nodes => map.nodes.where((n) => _nodes.contains(n));
+ @override
Map<int, List<SourceLocation>> operator [](js.Node node) {
return map[node];
}
@@ -522,6 +528,7 @@
/// Called when [node] defines a step of the given [kind] at the given
/// [offset] when the generated JavaScript code.
+ @override
void onStep(js.Node node, Offset offset, StepKind kind) {
if (kind == StepKind.ACCESS) return;
register(kind, node);
@@ -588,6 +595,7 @@
this.dartCode,
{this.isMissing: false});
+ @override
String toString() {
return 'CodePoint[kind=$kind,js=$jsCode,dart=$dartCode,'
'location=$sourceLocation]';
@@ -601,6 +609,7 @@
IOSourceFileManager(this.base);
+ @override
SourceFile getSourceFile(var uri) {
Uri absoluteUri;
if (uri is Uri) {
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_html_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_html_helper.dart
index e4b8c95..57869ca 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_html_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_html_helper.dart
@@ -80,6 +80,7 @@
SourceMapHtmlInfo(
this.sourceMapInfo, this.codeProcessor, this.sourceLocationCollection);
+ @override
String toString() {
return sourceMapInfo.toString();
}
@@ -117,6 +118,7 @@
}
class CustomColorScheme implements CssColorScheme {
+ @override
final bool showLocationAsSpan;
final Function single;
final Function multi;
@@ -126,8 +128,10 @@
String this.single(int id),
String this.multi(List<int> ids)});
+ @override
String singleLocationToCssColor(int id) => single != null ? single(id) : null;
+ @override
String multiLocationToCssColor(List<int> ids) =>
multi != null ? multi(ids) : null;
}
@@ -135,12 +139,15 @@
class PatternCssColorScheme implements CssColorScheme {
const PatternCssColorScheme();
+ @override
bool get showLocationAsSpan => true;
+ @override
String singleLocationToCssColor(int index) {
return "background:${toPattern(index)};";
}
+ @override
String multiLocationToCssColor(List<int> indices) {
StringBuffer sb = new StringBuffer();
double delta = 100.0 / (indices.length);
@@ -163,12 +170,15 @@
class SingleColorScheme implements CssColorScheme {
const SingleColorScheme();
+ @override
bool get showLocationAsSpan => false;
+ @override
String singleLocationToCssColor(int index) {
return "background:${toColorCss(index)};";
}
+ @override
String multiLocationToCssColor(List<int> indices) {
StringBuffer sb = new StringBuffer();
double delta = 100.0 / (indices.length);
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/trace_graph.dart b/tests/compiler/dart2js/sourcemaps/helpers/trace_graph.dart
index feceab2..d4481f8 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/trace_graph.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/trace_graph.dart
@@ -62,5 +62,6 @@
TraceStep(this.kind, this.id, this.node, this.offset, this.text,
[this.sourceLocation]);
+ @override
String toString() => '<span style="background:${toColorCss(id)}">$id</span>';
}
diff --git a/tests/compiler/dart2js/sourcemaps/mapping_test.dart b/tests/compiler/dart2js/sourcemaps/mapping_test.dart
index ed5d544..6c933ee 100644
--- a/tests/compiler/dart2js/sourcemaps/mapping_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/mapping_test.dart
@@ -171,9 +171,11 @@
SourceLocation(this.methodName, this.lineNo, this.columnNo);
+ @override
int get hashCode =>
methodName.hashCode * 13 + lineNo.hashCode * 17 + columnNo.hashCode * 19;
+ @override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! SourceLocation) return false;
@@ -182,5 +184,6 @@
columnNo == other.columnNo;
}
+ @override
String toString() => '$methodName:$lineNo:$columnNo';
}
diff --git a/tests/compiler/dart2js/sourcemaps/minified/no_such_method.dart b/tests/compiler/dart2js/sourcemaps/minified/no_such_method.dart
index 6fcd2aa..88383df 100644
--- a/tests/compiler/dart2js/sourcemaps/minified/no_such_method.dart
+++ b/tests/compiler/dart2js/sourcemaps/minified/no_such_method.dart
@@ -17,6 +17,7 @@
confuse(x) => x;
class A {
+ @override
noSuchMethod(i) => null;
}
diff --git a/tests/compiler/dart2js/sourcemaps/minified/no_such_method2.dart b/tests/compiler/dart2js/sourcemaps/minified/no_such_method2.dart
index 98e56b9..c169326 100644
--- a/tests/compiler/dart2js/sourcemaps/minified/no_such_method2.dart
+++ b/tests/compiler/dart2js/sourcemaps/minified/no_such_method2.dart
@@ -17,6 +17,7 @@
confuse(x) => x;
class A {
+ @override
noSuchMethod(i) => null;
}
diff --git a/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart b/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart
index ea6456b..2701c10 100644
--- a/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart
+++ b/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart
@@ -124,6 +124,7 @@
class CodeLineAnnotationJsonStrategy implements JsonStrategy {
const CodeLineAnnotationJsonStrategy();
+ @override
Map encodeAnnotation(Annotation annotation) {
CodeLineAnnotation data = annotation.data;
return {
@@ -134,6 +135,7 @@
};
}
+ @override
Annotation decodeAnnotation(Map json) {
return new Annotation(json['id'], json['codeOffset'], json['title'],
data: CodeLineAnnotation.fromJson(json['data'], this));
diff --git a/tests/compiler/dart2js/sourcemaps/tools/source_mapping_test_viewer.dart b/tests/compiler/dart2js/sourcemaps/tools/source_mapping_test_viewer.dart
index f6e7687..ac18b0b 100644
--- a/tests/compiler/dart2js/sourcemaps/tools/source_mapping_test_viewer.dart
+++ b/tests/compiler/dart2js/sourcemaps/tools/source_mapping_test_viewer.dart
@@ -92,7 +92,9 @@
}
class OutputConfigurations implements Configurations {
+ @override
final Iterable<String> configs;
+ @override
final Iterable<String> files;
final Map<Pair, String> pathMap = {};
final Map<Pair, Uri> uriMap = {};
@@ -156,6 +158,7 @@
Measurement(this.config, this.filename, this.missing, this.count);
+ @override
String toString() {
double percentage = 100 * missing / count;
return "Config '${config}', file: '${filename}': "
diff --git a/tests/compiler/dart2js_extra/constant_folding_test.dart b/tests/compiler/dart2js_extra/constant_folding_test.dart
new file mode 100644
index 0000000..cc88f68
--- /dev/null
+++ b/tests/compiler/dart2js_extra/constant_folding_test.dart
@@ -0,0 +1,1241 @@
+// Copyright (c) 2019, 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";
+
+void main() {
+ const BitNot(42, 4294967253).check();
+ const BitNot(4294967253, 42).check();
+ const BitNot(-42, 41).check();
+ const BitNot(-1, 0).check();
+ const BitNot(0, 0xFFFFFFFF).check();
+ const BitNot(4294967295, 0).check();
+ const BitNot(0x12121212121212, 0xEDEDEDED).check();
+
+ const Negate(0, -0).check();
+ const Negate(-0, 0).check();
+ const Negate(0.0, -0.0).check();
+ const Negate(-0.0, 0.0).check();
+ const Negate(-0.0, 0).check();
+ const Negate(-0, 0.0).check();
+ const Negate(0, -0.0).check();
+ const Negate(0.0, -0).check();
+ const Negate(1, -1).check();
+ const Negate(-1, 1).check();
+ const Negate(1.0, -1.0).check();
+ const Negate(-1.0, 1.0).check();
+ const Negate(3.14, -3.14).check();
+ const Negate(-3.14, 3.14).check();
+ const Negate(4294967295, -4294967295).check();
+ const Negate(-4294967295, 4294967295).check();
+ const Negate(4294967295.5, -4294967295.5).check();
+ const Negate(-4294967295.5, 4294967295.5).check();
+ const Negate(4294967296, -4294967296).check();
+ const Negate(-4294967296, 4294967296).check();
+ const Negate(4294967296.5, -4294967296.5).check();
+ const Negate(-4294967296.5, 4294967296.5).check();
+ const Negate(9007199254740991, -9007199254740991).check();
+ const Negate(-9007199254740991, 9007199254740991).check();
+ const Negate(9007199254740991.5, -9007199254740991.5).check();
+ const Negate(-9007199254740991.5, 9007199254740991.5).check();
+ const Negate(9007199254740992, -9007199254740992).check();
+ const Negate(-9007199254740992, 9007199254740992).check();
+ const Negate(9007199254740992.5, -9007199254740992.5).check();
+ const Negate(-9007199254740992.5, 9007199254740992.5).check();
+ const Negate(double.infinity, double.negativeInfinity).check();
+ const Negate(double.negativeInfinity, double.infinity).check();
+ const Negate(double.maxFinite, -double.maxFinite).check();
+ const Negate(-double.maxFinite, double.maxFinite).check();
+ const Negate(double.minPositive, -double.minPositive).check();
+ const Negate(-double.minPositive, double.minPositive).check();
+ const Negate(double.nan, double.nan).check();
+
+ const Not(true, false).check();
+ const Not(false, true).check();
+
+ const BitAnd(314159, 271828, 262404).check();
+ const BitAnd(271828, 314159, 262404).check();
+ const BitAnd(0, 0, 0).check();
+ const BitAnd(-1, 0, 0).check();
+ const BitAnd(-1, 314159, 314159).check();
+ const BitAnd(-1, 0xFFFFFFFF, 0xFFFFFFFF).check();
+ const BitAnd(0xff, -4, 0xfc).check();
+ const BitAnd(0, 0xFFFFFFFF, 0).check();
+ const BitAnd(0xFFFFFFFF, 0, 0).check();
+ const BitAnd(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF).check();
+ const BitAnd(0x123456789ABC, 0xEEEEEEEEEEEE, 0x46688AAC).check();
+
+ const BitOr(314159, 271828, 323583).check();
+ const BitOr(271828, 314159, 323583).check();
+ const BitOr(0, 0, 0).check();
+ const BitOr(-8, 0, 0xFFFFFFF8).check();
+ const BitOr(-8, 271828, 0xFFFFFFFC).check();
+ const BitOr(-8, 0xFFFFFFFF, 0xFFFFFFFF).check();
+ const BitOr(0x1, -4, 0xFFFFFFFD).check();
+ const BitOr(0, 0xFFFFFFFF, 0xFFFFFFFF).check();
+ const BitOr(0xFFFFFFFF, 0, 0xFFFFFFFF).check();
+ const BitOr(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF).check();
+ const BitOr(0x123456789ABC, 0x111111111111, 0x57799BBD).check();
+
+ const BitXor(314159, 271828, 61179).check();
+ const BitXor(271828, 314159, 61179).check();
+ const BitXor(0, 0, 0).check();
+ const BitXor(-1, 0, 0xFFFFFFFF).check();
+ const BitXor(-256, 1, 0xFFFFFF01).check();
+ const BitXor(-256, -255, 1).check();
+ const BitXor(0, 0xFFFFFFFF, 0xFFFFFFFF).check();
+ const BitXor(0xFFFFFFFF, 0, 0xFFFFFFFF).check();
+ const BitXor(0xFFFFFFFF, 0xFFFFFFFF, 0).check();
+ const BitXor(0x123456789ABC, 0x111111111111, 0x47698BAD).check();
+
+ const ShiftLeft(42, 0, 42).check();
+ const ShiftLeft(42, 5, 1344).check();
+ const ShiftLeft(1, 31, 0x80000000).check();
+ const ShiftLeft(1, 32, 0).check();
+ const ShiftLeft(1, 100, 0).check();
+ const ShiftLeft(0, 0, 0).check();
+ const ShiftLeft(0, 5, 0).check();
+ const ShiftLeft(0, 31, 0).check();
+ const ShiftLeft(0, 32, 0).check();
+ const ShiftLeft(0, 100, 0).check();
+ const ShiftLeft(-1, 0, 0xFFFFFFFF).check();
+ const ShiftLeft(-1, 5, 0xFFFFFFE0).check();
+ const ShiftLeft(-1, 31, 0x80000000).check();
+ const ShiftLeft(-1, 32, 0).check();
+ const ShiftLeft(-1, 100, 0).check();
+
+ const ShiftRight(8675309, 0, 8675309).check();
+ const ShiftRight(8675309, 5, 271103).check();
+ const ShiftRight(0xFEDCBA98, 0, 0xFEDCBA98).check();
+ const ShiftRight(0xFEDCBA98, 5, 0x07F6E5D4).check();
+ const ShiftRight(0xFEDCBA98, 31, 1).check();
+ const ShiftRight(0xFEDCBA98, 32, 0).check();
+ const ShiftRight(0xFEDCBA98, 100, 0).check();
+ const ShiftRight(0xFFFFFEDCBA98, 0, 0xFEDCBA98).check();
+ const ShiftRight(0xFFFFFEDCBA98, 5, 0x07F6E5D4).check();
+ const ShiftRight(0xFFFFFEDCBA98, 31, 1).check();
+ const ShiftRight(0xFFFFFEDCBA98, 32, 0).check();
+ const ShiftRight(0xFFFFFEDCBA98, 100, 0).check();
+ const ShiftRight(-1, 0, 0xFFFFFFFF).check();
+ const ShiftRight(-1, 5, 0xFFFFFFFF).check();
+ const ShiftRight(-1, 31, 0xFFFFFFFF).check();
+ const ShiftRight(-1, 32, 0xFFFFFFFF).check();
+ const ShiftRight(-1, 100, 0xFFFFFFFF).check();
+ const ShiftRight(-1073741824, 0, 0xC0000000).check();
+ const ShiftRight(-1073741824, 5, 0xFE000000).check();
+ const ShiftRight(-1073741824, 31, 0xFFFFFFFF).check();
+ const ShiftRight(-1073741824, 32, 0xFFFFFFFF).check();
+ const ShiftRight(-1073741824, 100, 0xFFFFFFFF).check();
+
+ const BooleanAnd(true, true, true).check();
+ const BooleanAnd(true, false, false).check();
+ const BooleanAnd(false, true, false).check();
+ const BooleanAnd(false, false, false).check();
+ const BooleanAnd(false, null, false).check();
+
+ const BooleanOr(true, true, true).check();
+ const BooleanOr(true, false, true).check();
+ const BooleanOr(false, true, true).check();
+ const BooleanOr(false, false, false).check();
+ const BooleanOr(true, null, true).check();
+
+ const Subtract(314159, 271828, 42331).check();
+ const Subtract(271828, 314159, -42331).check();
+ const Subtract(0, 0, 0).check();
+ const Subtract(0, 42, -42).check();
+ const Subtract(0, -42, 42).check();
+ const Subtract(42, 0, 42).check();
+ const Subtract(42, 42, 0).check();
+ const Subtract(42, -42, 84).check();
+ const Subtract(-42, 0, -42).check();
+ const Subtract(-42, 42, -84).check();
+ const Subtract(-42, -42, 0).check();
+ const Subtract(4294967295, -1, 4294967296).check();
+ const Subtract(4294967296, -1, 4294967297).check();
+ const Subtract(9007199254740991, -1, 9007199254740992).check();
+ const Subtract(9007199254740992, -1, 9007199254740992).check();
+ const Subtract(9007199254740992, -100, 9007199254741092).check();
+ const Subtract(-4294967295, 1, -4294967296).check();
+ const Subtract(-4294967296, 1, -4294967297).check();
+ const Subtract(-9007199254740991, 1, -9007199254740992).check();
+ const Subtract(-9007199254740992, 1, -9007199254740992).check();
+ const Subtract(-9007199254740992, 100, -9007199254741092).check();
+ const Subtract(
+ 0x7fffffff00000000, -0x7fffffff00000000, 2 * 0x7fffffff00000000)
+ .check();
+ const Subtract(4.2, 1.5, 2.7).check();
+ const Subtract(1.5, 4.2, -2.7).check();
+ const Subtract(1.5, 0, 1.5).check();
+ const Subtract(0, 1.5, -1.5).check();
+ const Subtract(1.5, 1.5, 0.0).check();
+ const Subtract(-1.5, -1.5, 0.0).check();
+ const Subtract(0.0, 0.0, 0.0).check();
+ const Subtract(0.0, -0.0, 0.0).check();
+ const Subtract(-0.0, 0.0, -0.0).check();
+ const Subtract(-0.0, -0.0, 0.0).check();
+ const Subtract(double.maxFinite, -double.maxFinite, double.infinity).check();
+ const Subtract(-double.maxFinite, double.maxFinite, double.negativeInfinity)
+ .check();
+ const Subtract(1.5, double.nan, double.nan).check();
+ const Subtract(double.nan, 1.5, double.nan).check();
+ const Subtract(double.nan, double.nan, double.nan).check();
+ const Subtract(double.nan, double.infinity, double.nan).check();
+ const Subtract(double.nan, double.negativeInfinity, double.nan).check();
+ const Subtract(double.infinity, double.nan, double.nan).check();
+ const Subtract(double.negativeInfinity, double.nan, double.nan).check();
+ const Subtract(double.infinity, double.maxFinite, double.infinity).check();
+ const Subtract(double.infinity, -double.maxFinite, double.infinity).check();
+ const Subtract(
+ double.negativeInfinity, double.maxFinite, double.negativeInfinity)
+ .check();
+ const Subtract(
+ double.negativeInfinity, -double.maxFinite, double.negativeInfinity)
+ .check();
+ const Subtract(1.5, double.infinity, double.negativeInfinity).check();
+ const Subtract(1.5, double.negativeInfinity, double.infinity).check();
+ const Subtract(double.infinity, double.infinity, double.nan).check();
+ const Subtract(double.infinity, double.negativeInfinity, double.infinity)
+ .check();
+ const Subtract(
+ double.negativeInfinity, double.infinity, double.negativeInfinity)
+ .check();
+ const Subtract(double.negativeInfinity, double.negativeInfinity, double.nan)
+ .check();
+ const Subtract(double.minPositive, double.minPositive, 0.0).check();
+ const Subtract(-double.minPositive, -double.minPositive, 0.0).check();
+
+ const Multiply(6, 7, 42).check();
+ const Multiply(-6, 7, -42).check();
+ const Multiply(6, -7, -42).check();
+ const Multiply(-6, -7, 42).check();
+ const Multiply(0, 0, 0).check();
+ const Multiply(0, 7, 0).check();
+ const Multiply(6, 0, 0).check();
+ const Multiply(65536, 65536, 4294967296).check();
+ const Multiply(4294967296, -1, -4294967296).check();
+ const Multiply(-1, 4294967296, -4294967296).check();
+ const Multiply(134217728, 134217728, 18014398509481984).check();
+ const Multiply(18014398509481984, -1, -18014398509481984).check();
+ const Multiply(-1, 18014398509481984, -18014398509481984).check();
+ const Multiply(9000000000000000, 9000000000000000, 8.1e31).check();
+ const Multiply(0x7fff000000000000, 0x8000000000000000, 8.506799558180535e37)
+ .check();
+ const Multiply(0x8000000000000000, 1.2, 11068046444225730000.0).check();
+ const Multiply(3.14, 2.72, 8.5408).check();
+ const Multiply(-3.14, 2.72, -8.5408).check();
+ const Multiply(3.14, -2.72, -8.5408).check();
+ const Multiply(-3.14, -2.72, 8.5408).check();
+ const Multiply(3.14, 0, 0.0).check();
+ const Multiply(0, 2.72, 0.0).check();
+ const Multiply(0.0, 0.0, 0.0).check();
+ const Multiply(0.0, -0.0, -0.0).check();
+ const Multiply(-0.0, 0.0, -0.0).check();
+ const Multiply(-0.0, -0.0, 0.0).check();
+ const Multiply(double.maxFinite, double.maxFinite, double.infinity).check();
+ const Multiply(double.maxFinite, -double.maxFinite, double.negativeInfinity)
+ .check();
+ const Multiply(-double.maxFinite, double.maxFinite, double.negativeInfinity)
+ .check();
+ const Multiply(-double.maxFinite, -double.maxFinite, double.infinity).check();
+ const Multiply(0, double.nan, double.nan).check();
+ const Multiply(double.nan, 0, double.nan).check();
+ const Multiply(double.nan, double.nan, double.nan).check();
+ const Multiply(0, double.infinity, double.nan).check();
+ const Multiply(double.infinity, 0, double.nan).check();
+ const Multiply(0, double.negativeInfinity, double.nan).check();
+ const Multiply(double.negativeInfinity, 0, double.nan).check();
+ const Multiply(-0.0, double.infinity, double.nan).check();
+ const Multiply(double.infinity, -0.0, double.nan).check();
+ const Multiply(-0.0, double.negativeInfinity, double.nan).check();
+ const Multiply(double.negativeInfinity, -0.0, double.nan).check();
+ const Multiply(double.infinity, double.infinity, double.infinity).check();
+ const Multiply(
+ double.infinity, double.negativeInfinity, double.negativeInfinity)
+ .check();
+ const Multiply(
+ double.negativeInfinity, double.infinity, double.negativeInfinity)
+ .check();
+ const Multiply(
+ double.negativeInfinity, double.negativeInfinity, double.infinity)
+ .check();
+ const Multiply(double.minPositive, 0.5, 0.0).check();
+ const Multiply(double.minPositive, -0.5, -0.0).check();
+ const Multiply(-double.minPositive, 0.5, -0.0).check();
+ const Multiply(-double.minPositive, -0.5, 0.0).check();
+ const Multiply(1e-300, -1e-300, -0.0).check();
+ const Multiply(double.minPositive, double.infinity, double.infinity).check();
+ const Multiply(
+ double.minPositive, double.negativeInfinity, double.negativeInfinity)
+ .check();
+ const Multiply(double.minPositive, double.maxFinite, 8.881784197001251e-16)
+ .check();
+
+ const Modulo(27, 314159, 27).check();
+ const Modulo(27, 1, 0).check();
+ const Modulo(27, -1, 0).check();
+ const Modulo(-27, 1, 0).check();
+ const Modulo(-27, -1, 0).check();
+ const Modulo(314159, 27, 14).check();
+ const Modulo(314159, -27, 14).check();
+ const Modulo(-314159, 27, 13).check();
+ const Modulo(-314159, -27, 13).check();
+ const Modulo(4294967295, 4294967296, 4294967295).check();
+ const Modulo(4294967295, -4294967296, 4294967295).check();
+ const Modulo(-4294967295, 4294967296, 1).check();
+ const Modulo(-4294967295, -4294967296, 1).check();
+ const Modulo(9007199254740991, 9007199254740992, 9007199254740991).check();
+ const Modulo(9007199254740991, -9007199254740992, 9007199254740991).check();
+ const Modulo(-9007199254740991, 9007199254740992, 1).check();
+ const Modulo(-9007199254740991, -9007199254740992, 1).check();
+ const Modulo(2.71828, 3.14159, 2.71828).check();
+ const Modulo(2.71828, 1, 0.71828).check();
+ const Modulo(2.71828, -1, 0.71828).check();
+ const Modulo(-2.71828, 1, 0.28171999999999997).check();
+ const Modulo(-2.71828, -1, 0.28171999999999997).check();
+ const Modulo(27.1828, 3.14159, 2.0500800000000012).check();
+ const Modulo(27.1828, -3.14159, 2.0500800000000012).check();
+ const Modulo(-27.1828, 3.14159, 1.0915099999999986).check();
+ const Modulo(-27.1828, -3.14159, 1.0915099999999986).check();
+ const Modulo(42, double.nan, double.nan).check();
+ const Modulo(double.nan, 42, double.nan).check();
+ const Modulo(0, double.nan, double.nan).check();
+ const Modulo(double.nan, double.nan, double.nan).check();
+ const Modulo(double.infinity, double.nan, double.nan).check();
+ const Modulo(double.nan, double.infinity, double.nan).check();
+ const Modulo(0.0, double.infinity, 0).check();
+ const Modulo(-0.0, double.infinity, 0).check();
+ const Modulo(0.0, double.negativeInfinity, 0).check();
+ const Modulo(-0.0, double.negativeInfinity, 0).check();
+ const Modulo(42, double.infinity, 42).check();
+ const Modulo(-42, double.infinity, double.infinity).check();
+ const Modulo(42, double.negativeInfinity, 42).check();
+ const Modulo(-42, double.negativeInfinity, double.infinity).check();
+ const Modulo(double.infinity, 42, double.nan).check();
+ const Modulo(double.infinity, -42, double.nan).check();
+ const Modulo(double.negativeInfinity, 42, double.nan).check();
+ const Modulo(double.negativeInfinity, -42, double.nan).check();
+ const Modulo(double.infinity, double.infinity, double.nan).check();
+ const Modulo(double.negativeInfinity, double.infinity, double.nan).check();
+ const Modulo(double.infinity, double.negativeInfinity, double.nan).check();
+ const Modulo(double.negativeInfinity, double.negativeInfinity, double.nan)
+ .check();
+
+ const TruncatingDivide(27, 314159, 0).check();
+ const TruncatingDivide(27, 1, 27).check();
+ const TruncatingDivide(27, -1, -27).check();
+ const TruncatingDivide(-27, 1, -27).check();
+ const TruncatingDivide(-27, -1, 27).check();
+ const TruncatingDivide(314159, 27, 11635).check();
+ const TruncatingDivide(314159, -27, -11635).check();
+ const TruncatingDivide(-314159, 27, -11635).check();
+ const TruncatingDivide(-314159, -27, 11635).check();
+ const TruncatingDivide(4294967295, 4294967296, 0).check();
+ const TruncatingDivide(4294967295, -4294967296, 0).check();
+ const TruncatingDivide(-4294967295, 4294967296, 0).check();
+ const TruncatingDivide(-4294967295, -4294967296, 0).check();
+ const TruncatingDivide(9007199254740991, 9007199254740992, 0).check();
+ const TruncatingDivide(9007199254740991, -9007199254740992, 0).check();
+ const TruncatingDivide(-9007199254740991, 9007199254740992, 0).check();
+ const TruncatingDivide(-9007199254740991, -9007199254740992, 0).check();
+ const TruncatingDivide(4294967295, 0.5, 8589934590).check();
+ const TruncatingDivide(4294967295, -0.5, -8589934590).check();
+ const TruncatingDivide(-4294967295, 0.5, -8589934590).check();
+ const TruncatingDivide(-4294967295, -0.5, 8589934590).check();
+ const TruncatingDivide(9007199254740991, 0.5, 18014398509481982).check();
+ const TruncatingDivide(9007199254740991, -0.5, -18014398509481982).check();
+ const TruncatingDivide(-9007199254740991, 0.5, -18014398509481982).check();
+ const TruncatingDivide(-9007199254740991, -0.5, 18014398509481982).check();
+ const TruncatingDivide(
+ 0x80000000 * 0x100000000, -1, -0x80000000 * 0x100000000)
+ .check();
+ const TruncatingDivide(2.71828, 3.14159, 0).check();
+ const TruncatingDivide(2.71828, 1, 2).check();
+ const TruncatingDivide(2.71828, -1, -2).check();
+ const TruncatingDivide(-2.71828, 1, -2).check();
+ const TruncatingDivide(-2.71828, -1, 2).check();
+ const TruncatingDivide(27.1828, 3.14159, 8).check();
+ const TruncatingDivide(27.1828, -3.14159, -8).check();
+ const TruncatingDivide(-27.1828, 3.14159, -8).check();
+ const TruncatingDivide(-27.1828, -3.14159, 8).check();
+ const TruncatingDivide(0.0, double.infinity, 0).check();
+ const TruncatingDivide(-0.0, double.infinity, 0).check();
+ const TruncatingDivide(0.0, double.negativeInfinity, 0).check();
+ const TruncatingDivide(-0.0, double.negativeInfinity, 0).check();
+ const TruncatingDivide(42, double.infinity, 0).check();
+ const TruncatingDivide(-42, double.infinity, 0).check();
+ const TruncatingDivide(42, double.negativeInfinity, 0).check();
+ const TruncatingDivide(-42, double.negativeInfinity, 0).check();
+
+ const Divide(27, 3, 9).check();
+ const Divide(27, 1, 27).check();
+ const Divide(27, -1, -27).check();
+ const Divide(-27, 1, -27).check();
+ const Divide(-27, -1, 27).check();
+ const Divide(0, 1, 0).check();
+ const Divide(0, -1, -0.0).check();
+ const Divide(-0.0, 1, -0.0).check();
+ const Divide(-0.0, -1, 0).check();
+ const Divide(314159, 27, 11635.518518518518).check();
+ const Divide(314159, -27, -11635.518518518518).check();
+ const Divide(-314159, 27, -11635.518518518518).check();
+ const Divide(-314159, -27, 11635.518518518518).check();
+ const Divide(4294967295, 4294967296, 0.9999999997671694).check();
+ const Divide(4294967295, -4294967296, -0.9999999997671694).check();
+ const Divide(-4294967295, 4294967296, -0.9999999997671694).check();
+ const Divide(-4294967295, -4294967296, 0.9999999997671694).check();
+ const Divide(9007199254740991, 9007199254740992, 0.9999999999999999).check();
+ const Divide(9007199254740991, -9007199254740992, -0.9999999999999999)
+ .check();
+ const Divide(-9007199254740991, 9007199254740992, -0.9999999999999999)
+ .check();
+ const Divide(-9007199254740991, -9007199254740992, 0.9999999999999999)
+ .check();
+ const Divide(4294967296, 4294967295, 1.0000000002328306).check();
+ const Divide(4294967296, -4294967295, -1.0000000002328306).check();
+ const Divide(-4294967296, 4294967295, -1.0000000002328306).check();
+ const Divide(-4294967296, -4294967295, 1.0000000002328306).check();
+ const Divide(9007199254740992, 9007199254740991, 1.0000000000000002).check();
+ const Divide(9007199254740992, -9007199254740991, -1.0000000000000002)
+ .check();
+ const Divide(-9007199254740992, 9007199254740991, -1.0000000000000002)
+ .check();
+ const Divide(-9007199254740992, -9007199254740991, 1.0000000000000002)
+ .check();
+ const Divide(4294967295, 0.5, 8589934590).check();
+ const Divide(4294967295, -0.5, -8589934590).check();
+ const Divide(-4294967295, 0.5, -8589934590).check();
+ const Divide(-4294967295, -0.5, 8589934590).check();
+ const Divide(9007199254740991, 0.5, 18014398509481982).check();
+ const Divide(9007199254740991, -0.5, -18014398509481982).check();
+ const Divide(-9007199254740991, 0.5, -18014398509481982).check();
+ const Divide(-9007199254740991, -0.5, 18014398509481982).check();
+ const Divide(2.71828, 3.14159, 0.8652561282662601).check();
+ const Divide(2.71828, 1, 2.71828).check();
+ const Divide(2.71828, -1, -2.71828).check();
+ const Divide(-2.71828, 1, -2.71828).check();
+ const Divide(-2.71828, -1, 2.71828).check();
+ const Divide(27.1828, 3.14159, 8.652561282662601).check();
+ const Divide(27.1828, -3.14159, -8.652561282662601).check();
+ const Divide(-27.1828, 3.14159, -8.652561282662601).check();
+ const Divide(-27.1828, -3.14159, 8.652561282662601).check();
+ const Divide(1, 0, double.infinity).check();
+ const Divide(1, -0.0, double.negativeInfinity).check();
+ const Divide(-1, 0, double.negativeInfinity).check();
+ const Divide(-1, -0.0, double.infinity).check();
+ const Divide(0, 0, double.nan).check();
+ const Divide(0, -0.0, double.nan).check();
+ const Divide(-0.0, 0, double.nan).check();
+ const Divide(-0.0, -0.0, double.nan).check();
+ const Divide(double.infinity, 0, double.infinity).check();
+ const Divide(double.infinity, -0.0, double.negativeInfinity).check();
+ const Divide(double.negativeInfinity, 0, double.negativeInfinity).check();
+ const Divide(double.negativeInfinity, -0.0, double.infinity).check();
+ const Divide(double.nan, 0, double.nan).check();
+ const Divide(double.nan, -0.0, double.nan).check();
+ const Divide(double.nan, 1, double.nan).check();
+ const Divide(1, double.nan, double.nan).check();
+ const Divide(0, double.nan, double.nan).check();
+ const Divide(double.nan, double.nan, double.nan).check();
+ const Divide(double.nan, double.infinity, double.nan).check();
+ const Divide(double.infinity, double.nan, double.nan).check();
+ const Divide(double.negativeInfinity, double.nan, double.nan).check();
+ const Divide(double.infinity, 1, double.infinity).check();
+ const Divide(double.infinity, -1, double.negativeInfinity).check();
+ const Divide(double.negativeInfinity, 1, double.negativeInfinity).check();
+ const Divide(double.negativeInfinity, -1, double.infinity).check();
+ const Divide(0, double.infinity, 0).check();
+ const Divide(0, double.negativeInfinity, -0.0).check();
+ const Divide(-0.0, double.infinity, -0.0).check();
+ const Divide(-0.0, double.negativeInfinity, 0).check();
+ const Divide(1, double.infinity, 0).check();
+ const Divide(1, double.negativeInfinity, -0.0).check();
+ const Divide(-1, double.infinity, -0.0).check();
+ const Divide(-1, double.negativeInfinity, 0).check();
+ const Divide(double.infinity, double.infinity, double.nan).check();
+ const Divide(double.minPositive, double.maxFinite, 0).check();
+ const Divide(double.minPositive, -double.maxFinite, -0.0).check();
+ const Divide(-double.minPositive, double.maxFinite, -0.0).check();
+ const Divide(-double.minPositive, -double.maxFinite, 0).check();
+ const Divide(double.maxFinite, double.minPositive, double.infinity).check();
+ const Divide(double.maxFinite, -double.minPositive, double.negativeInfinity)
+ .check();
+ const Divide(-double.maxFinite, double.minPositive, double.negativeInfinity)
+ .check();
+ const Divide(-double.maxFinite, -double.minPositive, double.infinity).check();
+
+ const Add("", "", "").check();
+ const Add("foo", "", "foo").check();
+ const Add("", "bar", "bar").check();
+ const Add("foo", "bar", "foobar").check();
+ const Add(314159, 271828, 585987).check();
+ const Add(314159, -271828, 42331).check();
+ const Add(-314159, 271828, -42331).check();
+ const Add(-314159, -271828, -585987).check();
+ const Add(0, 0, 0).check();
+ const Add(0, 42, 42).check();
+ const Add(0, -42, -42).check();
+ const Add(42, 0, 42).check();
+ const Add(42, 42, 84).check();
+ const Add(42, -42, 0).check();
+ const Add(-42, 0, -42).check();
+ const Add(-42, 42, 0).check();
+ const Add(-42, -42, -84).check();
+ const Add(4294967295, 1, 4294967296).check();
+ const Add(4294967296, 1, 4294967297).check();
+ const Add(9007199254740991, 1, 9007199254740992).check();
+ const Add(9007199254740992, 1, 9007199254740992).check();
+ const Add(9007199254740992, 100, 9007199254741092).check();
+ const Add(-4294967295, -1, -4294967296).check();
+ const Add(-4294967296, -1, -4294967297).check();
+ const Add(-9007199254740991, -1, -9007199254740992).check();
+ const Add(-9007199254740992, -1, -9007199254740992).check();
+ const Add(-9007199254740992, -100, -9007199254741092).check();
+ const Add(4.2, 1.5, 5.7).check();
+ const Add(4.2, -1.5, 2.7).check();
+ const Add(-4.2, 1.5, -2.7).check();
+ const Add(-4.2, -1.5, -5.7).check();
+ const Add(1.5, 0, 1.5).check();
+ const Add(0, 1.5, 1.5).check();
+ const Add(1.5, -1.5, 0.0).check();
+ const Add(-1.5, 1.5, 0.0).check();
+ const Add(0.0, 0.0, 0.0).check();
+ const Add(0.0, -0.0, 0.0).check();
+ const Add(-0.0, 0.0, 0.0).check();
+ const Add(-0.0, -0.0, -0.0).check();
+ const Add(double.maxFinite, double.maxFinite, double.infinity).check();
+ const Add(-double.maxFinite, -double.maxFinite, double.negativeInfinity)
+ .check();
+ const Add(1.5, double.nan, double.nan).check();
+ const Add(double.nan, 1.5, double.nan).check();
+ const Add(double.nan, double.nan, double.nan).check();
+ const Add(double.nan, double.infinity, double.nan).check();
+ const Add(double.nan, double.negativeInfinity, double.nan).check();
+ const Add(double.infinity, double.nan, double.nan).check();
+ const Add(double.negativeInfinity, double.nan, double.nan).check();
+ const Add(double.infinity, -double.maxFinite, double.infinity).check();
+ const Add(double.infinity, double.maxFinite, double.infinity).check();
+ const Add(double.negativeInfinity, -double.maxFinite, double.negativeInfinity)
+ .check();
+ const Add(double.negativeInfinity, double.maxFinite, double.negativeInfinity)
+ .check();
+ const Add(1.5, double.negativeInfinity, double.negativeInfinity).check();
+ const Add(1.5, double.infinity, double.infinity).check();
+ const Add(double.infinity, double.infinity, double.infinity).check();
+ const Add(double.infinity, double.negativeInfinity, double.nan).check();
+ const Add(double.negativeInfinity, double.infinity, double.nan).check();
+ const Add(double.negativeInfinity, double.negativeInfinity,
+ double.negativeInfinity)
+ .check();
+ const Add(double.minPositive, -double.minPositive, 0.0).check();
+ const Add(-double.minPositive, double.minPositive, 0.0).check();
+
+ const Less(double.nan, double.nan, false).check();
+ const Less(double.nan, double.infinity, false).check();
+ const Less(double.infinity, double.nan, false).check();
+ const Less(double.nan, double.maxFinite, false).check();
+ const Less(double.maxFinite, double.nan, false).check();
+ const Less(double.nan, -double.maxFinite, false).check();
+ const Less(-double.maxFinite, double.nan, false).check();
+ const Less(double.nan, double.negativeInfinity, false).check();
+ const Less(double.negativeInfinity, double.nan, false).check();
+ const Less(double.negativeInfinity, double.negativeInfinity, false).check();
+ const Less(double.negativeInfinity, -double.maxFinite, true).check();
+ const Less(-double.maxFinite, double.negativeInfinity, false).check();
+ const Less(-double.maxFinite, -double.maxFinite, false).check();
+ const Less(-double.maxFinite, -9007199254740992, true).check();
+ const Less(-9007199254740992, -double.maxFinite, false).check();
+ const Less(-9007199254740992, -9007199254740992, false).check();
+ const Less(-9007199254740992, -4294967296, true).check();
+ const Less(-4294967296, -9007199254740992, false).check();
+ const Less(-4294967296, -4294967296, false).check();
+ const Less(-4294967296, -42, true).check();
+ const Less(-42, -4294967296, false).check();
+ const Less(-42, -42, false).check();
+ const Less(-42, -42.0, false).check();
+ const Less(-42.0, -42, false).check();
+ const Less(-42.0, -42.0, false).check();
+ const Less(-42, -3.14, true).check();
+ const Less(-3.14, -42, false).check();
+ const Less(-3.14, -3.14, false).check();
+ const Less(-3.14, -double.minPositive, true).check();
+ const Less(-double.minPositive, -3.14, false).check();
+ const Less(-double.minPositive, -double.minPositive, false).check();
+ const Less(-double.minPositive, -0.0, true).check();
+ const Less(-0.0, -double.minPositive, false).check();
+ const Less(-0.0, -0.0, false).check();
+ const Less(0, 0, false).check();
+ const Less(0.0, 0.0, false).check();
+ const Less(-0.0, 0, false).check();
+ const Less(0, -0.0, false).check();
+ const Less(-0.0, 0.0, false).check();
+ const Less(0.0, -0.0, false).check();
+ const Less(0, 0.0, false).check();
+ const Less(0.0, 0, false).check();
+ const Less(0.0, double.minPositive, true).check();
+ const Less(double.minPositive, 0.0, false).check();
+ const Less(double.minPositive, double.minPositive, false).check();
+ const Less(double.minPositive, 3.14, true).check();
+ const Less(3.14, double.minPositive, false).check();
+ const Less(3.14, 3.14, false).check();
+ const Less(3.14, 42, true).check();
+ const Less(42, 3.14, false).check();
+ const Less(42.0, 42.0, false).check();
+ const Less(42, 42.0, false).check();
+ const Less(42.0, 42, false).check();
+ const Less(42, 42, false).check();
+ const Less(42, 4294967296, true).check();
+ const Less(4294967296, 42, false).check();
+ const Less(4294967296, 4294967296, false).check();
+ const Less(4294967296, 9007199254740992, true).check();
+ const Less(9007199254740992, 4294967296, false).check();
+ const Less(9007199254740992, 9007199254740992, false).check();
+ const Less(9007199254740992, double.maxFinite, true).check();
+ const Less(double.maxFinite, 9007199254740992, false).check();
+ const Less(double.maxFinite, double.maxFinite, false).check();
+ const Less(double.maxFinite, double.infinity, true).check();
+ const Less(double.infinity, double.maxFinite, false).check();
+ const Less(double.infinity, double.infinity, false).check();
+ const Less(0x7fffffff00000000, 0x8000000000000000, true).check();
+ const Less(0x8000000000000000, 0x7fffffff00000000, false).check();
+
+ const LessEqual(double.nan, double.nan, false).check();
+ const LessEqual(double.nan, double.infinity, false).check();
+ const LessEqual(double.infinity, double.nan, false).check();
+ const LessEqual(double.nan, double.maxFinite, false).check();
+ const LessEqual(double.maxFinite, double.nan, false).check();
+ const LessEqual(double.nan, -double.maxFinite, false).check();
+ const LessEqual(-double.maxFinite, double.nan, false).check();
+ const LessEqual(double.nan, double.negativeInfinity, false).check();
+ const LessEqual(double.negativeInfinity, double.nan, false).check();
+ const LessEqual(double.negativeInfinity, double.negativeInfinity, true)
+ .check();
+ const LessEqual(double.negativeInfinity, -double.maxFinite, true).check();
+ const LessEqual(-double.maxFinite, double.negativeInfinity, false).check();
+ const LessEqual(-double.maxFinite, -double.maxFinite, true).check();
+ const LessEqual(-double.maxFinite, -9007199254740992, true).check();
+ const LessEqual(-9007199254740992, -double.maxFinite, false).check();
+ const LessEqual(-9007199254740992, -9007199254740992, true).check();
+ const LessEqual(-9007199254740992, -4294967296, true).check();
+ const LessEqual(-4294967296, -9007199254740992, false).check();
+ const LessEqual(-4294967296, -4294967296, true).check();
+ const LessEqual(-4294967296, -42, true).check();
+ const LessEqual(-42, -4294967296, false).check();
+ const LessEqual(-42, -42, true).check();
+ const LessEqual(-42, -42.0, true).check();
+ const LessEqual(-42.0, -42, true).check();
+ const LessEqual(-42.0, -42.0, true).check();
+ const LessEqual(-42, -3.14, true).check();
+ const LessEqual(-3.14, -42, false).check();
+ const LessEqual(-3.14, -3.14, true).check();
+ const LessEqual(-3.14, -double.minPositive, true).check();
+ const LessEqual(-double.minPositive, -3.14, false).check();
+ const LessEqual(-double.minPositive, -double.minPositive, true).check();
+ const LessEqual(-double.minPositive, -0.0, true).check();
+ const LessEqual(-0.0, -double.minPositive, false).check();
+ const LessEqual(-0.0, -0.0, true).check();
+ const LessEqual(0, 0, true).check();
+ const LessEqual(0.0, 0.0, true).check();
+ const LessEqual(-0.0, 0, true).check();
+ const LessEqual(0, -0.0, true).check();
+ const LessEqual(-0.0, 0.0, true).check();
+ const LessEqual(0.0, -0.0, true).check();
+ const LessEqual(0, 0.0, true).check();
+ const LessEqual(0.0, 0, true).check();
+ const LessEqual(0.0, double.minPositive, true).check();
+ const LessEqual(double.minPositive, 0.0, false).check();
+ const LessEqual(double.minPositive, double.minPositive, true).check();
+ const LessEqual(double.minPositive, 3.14, true).check();
+ const LessEqual(3.14, double.minPositive, false).check();
+ const LessEqual(3.14, 3.14, true).check();
+ const LessEqual(3.14, 42, true).check();
+ const LessEqual(42, 3.14, false).check();
+ const LessEqual(42.0, 42.0, true).check();
+ const LessEqual(42, 42.0, true).check();
+ const LessEqual(42.0, 42, true).check();
+ const LessEqual(42, 42, true).check();
+ const LessEqual(42, 4294967296, true).check();
+ const LessEqual(4294967296, 42, false).check();
+ const LessEqual(4294967296, 4294967296, true).check();
+ const LessEqual(4294967296, 9007199254740992, true).check();
+ const LessEqual(9007199254740992, 4294967296, false).check();
+ const LessEqual(9007199254740992, 9007199254740992, true).check();
+ const LessEqual(9007199254740992, double.maxFinite, true).check();
+ const LessEqual(double.maxFinite, 9007199254740992, false).check();
+ const LessEqual(double.maxFinite, double.maxFinite, true).check();
+ const LessEqual(double.maxFinite, double.infinity, true).check();
+ const LessEqual(double.infinity, double.maxFinite, false).check();
+ const LessEqual(double.infinity, double.infinity, true).check();
+ const LessEqual(0x7fffffff00000000, 0x8000000000000000, true).check();
+ const LessEqual(0x8000000000000000, 0x7fffffff00000000, false).check();
+
+ const Greater(double.nan, double.nan, false).check();
+ const Greater(double.nan, double.infinity, false).check();
+ const Greater(double.infinity, double.nan, false).check();
+ const Greater(double.nan, double.maxFinite, false).check();
+ const Greater(double.maxFinite, double.nan, false).check();
+ const Greater(double.nan, -double.maxFinite, false).check();
+ const Greater(-double.maxFinite, double.nan, false).check();
+ const Greater(double.nan, double.negativeInfinity, false).check();
+ const Greater(double.negativeInfinity, double.nan, false).check();
+ const Greater(double.negativeInfinity, double.negativeInfinity, false)
+ .check();
+ const Greater(double.negativeInfinity, -double.maxFinite, false).check();
+ const Greater(-double.maxFinite, double.negativeInfinity, true).check();
+ const Greater(-double.maxFinite, -double.maxFinite, false).check();
+ const Greater(-double.maxFinite, -9007199254740992, false).check();
+ const Greater(-9007199254740992, -double.maxFinite, true).check();
+ const Greater(-9007199254740992, -9007199254740992, false).check();
+ const Greater(-9007199254740992, -4294967296, false).check();
+ const Greater(-4294967296, -9007199254740992, true).check();
+ const Greater(-4294967296, -4294967296, false).check();
+ const Greater(-4294967296, -42, false).check();
+ const Greater(-42, -4294967296, true).check();
+ const Greater(-42, -42, false).check();
+ const Greater(-42, -42.0, false).check();
+ const Greater(-42.0, -42, false).check();
+ const Greater(-42.0, -42.0, false).check();
+ const Greater(-42, -3.14, false).check();
+ const Greater(-3.14, -42, true).check();
+ const Greater(-3.14, -3.14, false).check();
+ const Greater(-3.14, -double.minPositive, false).check();
+ const Greater(-double.minPositive, -3.14, true).check();
+ const Greater(-double.minPositive, -double.minPositive, false).check();
+ const Greater(-double.minPositive, -0.0, false).check();
+ const Greater(-0.0, -double.minPositive, true).check();
+ const Greater(-0.0, -0.0, false).check();
+ const Greater(0, 0, false).check();
+ const Greater(0.0, 0.0, false).check();
+ const Greater(-0.0, 0, false).check();
+ const Greater(0, -0.0, false).check();
+ const Greater(-0.0, 0.0, false).check();
+ const Greater(0.0, -0.0, false).check();
+ const Greater(0, 0.0, false).check();
+ const Greater(0.0, 0, false).check();
+ const Greater(0.0, double.minPositive, false).check();
+ const Greater(double.minPositive, 0.0, true).check();
+ const Greater(double.minPositive, double.minPositive, false).check();
+ const Greater(double.minPositive, 3.14, false).check();
+ const Greater(3.14, double.minPositive, true).check();
+ const Greater(3.14, 3.14, false).check();
+ const Greater(3.14, 42, false).check();
+ const Greater(42, 3.14, true).check();
+ const Greater(42.0, 42.0, false).check();
+ const Greater(42, 42.0, false).check();
+ const Greater(42.0, 42, false).check();
+ const Greater(42, 42, false).check();
+ const Greater(42, 4294967296, false).check();
+ const Greater(4294967296, 42, true).check();
+ const Greater(4294967296, 4294967296, false).check();
+ const Greater(4294967296, 9007199254740992, false).check();
+ const Greater(9007199254740992, 4294967296, true).check();
+ const Greater(9007199254740992, 9007199254740992, false).check();
+ const Greater(9007199254740992, double.maxFinite, false).check();
+ const Greater(double.maxFinite, 9007199254740992, true).check();
+ const Greater(double.maxFinite, double.maxFinite, false).check();
+ const Greater(double.maxFinite, double.infinity, false).check();
+ const Greater(double.infinity, double.maxFinite, true).check();
+ const Greater(double.infinity, double.infinity, false).check();
+ const Greater(0x7fffffff00000000, 0x8000000000000000, false).check();
+ const Greater(0x8000000000000000, 0x7fffffff00000000, true).check();
+
+ const GreaterEqual(double.nan, double.nan, false).check();
+ const GreaterEqual(double.nan, double.infinity, false).check();
+ const GreaterEqual(double.infinity, double.nan, false).check();
+ const GreaterEqual(double.nan, double.maxFinite, false).check();
+ const GreaterEqual(double.maxFinite, double.nan, false).check();
+ const GreaterEqual(double.nan, -double.maxFinite, false).check();
+ const GreaterEqual(-double.maxFinite, double.nan, false).check();
+ const GreaterEqual(double.nan, double.negativeInfinity, false).check();
+ const GreaterEqual(double.negativeInfinity, double.nan, false).check();
+ const GreaterEqual(double.negativeInfinity, double.negativeInfinity, true)
+ .check();
+ const GreaterEqual(double.negativeInfinity, -double.maxFinite, false).check();
+ const GreaterEqual(-double.maxFinite, double.negativeInfinity, true).check();
+ const GreaterEqual(-double.maxFinite, -double.maxFinite, true).check();
+ const GreaterEqual(-double.maxFinite, -9007199254740992, false).check();
+ const GreaterEqual(-9007199254740992, -double.maxFinite, true).check();
+ const GreaterEqual(-9007199254740992, -9007199254740992, true).check();
+ const GreaterEqual(-9007199254740992, -4294967296, false).check();
+ const GreaterEqual(-4294967296, -9007199254740992, true).check();
+ const GreaterEqual(-4294967296, -4294967296, true).check();
+ const GreaterEqual(-4294967296, -42, false).check();
+ const GreaterEqual(-42, -4294967296, true).check();
+ const GreaterEqual(-42, -42, true).check();
+ const GreaterEqual(-42, -42.0, true).check();
+ const GreaterEqual(-42.0, -42, true).check();
+ const GreaterEqual(-42.0, -42.0, true).check();
+ const GreaterEqual(-42, -3.14, false).check();
+ const GreaterEqual(-3.14, -42, true).check();
+ const GreaterEqual(-3.14, -3.14, true).check();
+ const GreaterEqual(-3.14, -double.minPositive, false).check();
+ const GreaterEqual(-double.minPositive, -3.14, true).check();
+ const GreaterEqual(-double.minPositive, -double.minPositive, true).check();
+ const GreaterEqual(-double.minPositive, -0.0, false).check();
+ const GreaterEqual(-0.0, -double.minPositive, true).check();
+ const GreaterEqual(-0.0, -0.0, true).check();
+ const GreaterEqual(0, 0, true).check();
+ const GreaterEqual(0.0, 0.0, true).check();
+ const GreaterEqual(-0.0, 0, true).check();
+ const GreaterEqual(0, -0.0, true).check();
+ const GreaterEqual(-0.0, 0.0, true).check();
+ const GreaterEqual(0.0, -0.0, true).check();
+ const GreaterEqual(0, 0.0, true).check();
+ const GreaterEqual(0.0, 0, true).check();
+ const GreaterEqual(0.0, double.minPositive, false).check();
+ const GreaterEqual(double.minPositive, 0.0, true).check();
+ const GreaterEqual(double.minPositive, double.minPositive, true).check();
+ const GreaterEqual(double.minPositive, 3.14, false).check();
+ const GreaterEqual(3.14, double.minPositive, true).check();
+ const GreaterEqual(3.14, 3.14, true).check();
+ const GreaterEqual(3.14, 42, false).check();
+ const GreaterEqual(42, 3.14, true).check();
+ const GreaterEqual(42.0, 42.0, true).check();
+ const GreaterEqual(42, 42.0, true).check();
+ const GreaterEqual(42.0, 42, true).check();
+ const GreaterEqual(42, 42, true).check();
+ const GreaterEqual(42, 4294967296, false).check();
+ const GreaterEqual(4294967296, 42, true).check();
+ const GreaterEqual(4294967296, 4294967296, true).check();
+ const GreaterEqual(4294967296, 9007199254740992, false).check();
+ const GreaterEqual(9007199254740992, 4294967296, true).check();
+ const GreaterEqual(9007199254740992, 9007199254740992, true).check();
+ const GreaterEqual(9007199254740992, double.maxFinite, false).check();
+ const GreaterEqual(double.maxFinite, 9007199254740992, true).check();
+ const GreaterEqual(double.maxFinite, double.maxFinite, true).check();
+ const GreaterEqual(double.maxFinite, double.infinity, false).check();
+ const GreaterEqual(double.infinity, double.maxFinite, true).check();
+ const GreaterEqual(double.infinity, double.infinity, true).check();
+ const GreaterEqual(0x7fffffff00000000, 0x8000000000000000, false).check();
+ const GreaterEqual(0x8000000000000000, 0x7fffffff00000000, true).check();
+
+ const Equals(null, null, true).check();
+ const Equals(null, "", false).check();
+ const Equals("", null, false).check();
+ const Equals("", "", true).check();
+ const Equals(true, true, true).check();
+ const Equals(false, false, true).check();
+ const Equals(true, false, false).check();
+ const Equals(false, true, false).check();
+ const Equals(0, false, false).check();
+ const Equals(true, 1, false).check();
+ const Equals(double.nan, double.nan, false).check();
+ const Equals(0, 0, true).check();
+ const Equals(0.0, 0.0, true).check();
+ const Equals(-0.0, -0.0, true).check();
+ const Equals(0, 0.0, true).check();
+ const Equals(0.0, 0, true).check();
+ const Equals(0, -0.0, true).check();
+ const Equals(-0.0, 0, true).check();
+ const Equals(0.0, -0.0, true).check();
+ const Equals(-0.0, 0.0, true).check();
+ const Equals(1, 1, true).check();
+ const Equals(1.0, 1.0, true).check();
+ const Equals(1, 1.0, true).check();
+ const Equals(1.0, 1, true).check();
+ const Equals(double.infinity, double.infinity, true).check();
+ const Equals(double.infinity, double.negativeInfinity, false).check();
+ const Equals(double.negativeInfinity, double.infinity, false).check();
+ const Equals(double.negativeInfinity, double.negativeInfinity, true).check();
+
+ const Identity(null, null, true).check();
+ const Identity(null, "", false).check();
+ const Identity("", null, false).check();
+ const Identity("", "", true).check();
+ const Identity(true, true, true).check();
+ const Identity(false, false, true).check();
+ const Identity(true, false, false).check();
+ const Identity(false, true, false).check();
+ const Identity(0, false, false).check();
+ const Identity(true, 1, false).check();
+ // TODO(36194)
+ //const Identity(double.nan, double.nan, false).check();
+ const Identity(0, 0, true).check();
+ const Identity(0.0, 0.0, true).check();
+ const Identity(-0.0, -0.0, true).check();
+ const Identity(0, 0.0, true).check();
+ const Identity(0.0, 0, true).check();
+ const Identity(0, -0.0, true).check();
+ const Identity(-0.0, 0, true).check();
+ const Identity(0.0, -0.0, true).check();
+ const Identity(-0.0, 0.0, true).check();
+ const Identity(1, 1, true).check();
+ const Identity(1.0, 1.0, true).check();
+ const Identity(1, 1.0, true).check();
+ const Identity(1.0, 1, true).check();
+ const Identity(double.infinity, double.infinity, true).check();
+ const Identity(double.infinity, double.negativeInfinity, false).check();
+ const Identity(double.negativeInfinity, double.infinity, false).check();
+ const Identity(double.negativeInfinity, double.negativeInfinity, true)
+ .check();
+
+ const IfNull(null, null, null).check();
+ const IfNull(null, 1, 1).check();
+ const IfNull("foo", 1, "foo").check();
+ const IfNull("foo", null, "foo").check();
+}
+
+/// Wraps [Expect.equals] to accommodate JS equality semantics.
+///
+/// Naively using [Expect.equals] causes JS values to be compared with `===`.
+/// This can yield some unintended results:
+///
+/// * Since `NaN === NaN` is `false`, [Expect.equals] will throw even if both
+/// values are `NaN`. Therefore, we check for `NaN` specifically.
+/// * Since `0.0 === -0.0` is `true`, [Expect.equals] will fail to throw if one
+/// constant evaluation results in `0` or `0.0` and the other results in
+/// `-0.0`. Therefore, we additionally check that both values have the same
+/// sign in this case.
+void jsEquals(expected, actual, [String reason = null]) {
+ if (expected is num && actual is num) {
+ if (expected.isNaN && actual.isNaN) return;
+ }
+
+ Expect.equals(expected, actual, reason);
+
+ if (expected == 0 && actual == 0) {
+ Expect.equals(
+ expected.isNegative,
+ actual.isNegative,
+ (reason == null ? "" : "$reason ") +
+ "${expected.toString()} and "
+ "${actual.toString()} have different signs.");
+ }
+}
+
+abstract class TestOp {
+ final expected;
+ final result;
+
+ const TestOp(this.expected, this.result);
+
+ @pragma('dart2js:noInline')
+ checkAll(evalResult) {
+ jsEquals(expected, result,
+ "Frontend constant evaluation does not yield expected value.");
+ jsEquals(expected, evalResult,
+ "Backend constant evaluation does not yield expected value.");
+ jsEquals(expected, eval(), "eval() does not yield expected value.");
+ }
+
+ eval();
+}
+
+class BitNot extends TestOp {
+ final arg;
+
+ const BitNot(this.arg, expected) : super(expected, ~arg);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => ~arg;
+}
+
+class Negate extends TestOp {
+ final arg;
+
+ const Negate(this.arg, expected) : super(expected, -arg);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => -arg;
+}
+
+class Not extends TestOp {
+ final arg;
+
+ const Not(this.arg, expected) : super(expected, !arg);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => !arg;
+}
+
+class BitAnd extends TestOp {
+ final arg1;
+ final arg2;
+
+ const BitAnd(this.arg1, this.arg2, expected) : super(expected, arg1 & arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 & arg2;
+}
+
+class BitOr extends TestOp {
+ final arg1;
+ final arg2;
+
+ const BitOr(this.arg1, this.arg2, expected) : super(expected, arg1 | arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 | arg2;
+}
+
+class BitXor extends TestOp {
+ final arg1;
+ final arg2;
+
+ const BitXor(this.arg1, this.arg2, expected) : super(expected, arg1 ^ arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 ^ arg2;
+}
+
+class ShiftLeft extends TestOp {
+ final arg1;
+ final arg2;
+
+ const ShiftLeft(this.arg1, this.arg2, expected)
+ : super(expected, arg1 << arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 << arg2;
+}
+
+class ShiftRight extends TestOp {
+ final arg1;
+ final arg2;
+
+ const ShiftRight(this.arg1, this.arg2, expected)
+ : super(expected, arg1 >> arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 >> arg2;
+}
+
+class BooleanAnd extends TestOp {
+ final arg1;
+ final arg2;
+
+ const BooleanAnd(this.arg1, this.arg2, expected)
+ : super(expected, arg1 && arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 && arg2;
+}
+
+class BooleanOr extends TestOp {
+ final arg1;
+ final arg2;
+
+ const BooleanOr(this.arg1, this.arg2, expected)
+ : super(expected, arg1 || arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 || arg2;
+}
+
+class Subtract extends TestOp {
+ final arg1;
+ final arg2;
+
+ const Subtract(this.arg1, this.arg2, expected) : super(expected, arg1 - arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 - arg2;
+}
+
+class Multiply extends TestOp {
+ final arg1;
+ final arg2;
+
+ const Multiply(this.arg1, this.arg2, expected) : super(expected, arg1 * arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 * arg2;
+}
+
+class Modulo extends TestOp {
+ final arg1;
+ final arg2;
+
+ const Modulo(this.arg1, this.arg2, expected) : super(expected, arg1 % arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 % arg2;
+}
+
+class TruncatingDivide extends TestOp {
+ final arg1;
+ final arg2;
+
+ const TruncatingDivide(this.arg1, this.arg2, expected)
+ : super(expected, arg1 ~/ arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 ~/ arg2;
+}
+
+class Divide extends TestOp {
+ final arg1;
+ final arg2;
+
+ const Divide(this.arg1, this.arg2, expected) : super(expected, arg1 / arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @override
+ @pragma('dart2js:tryInline')
+ eval() => arg1 / arg2;
+}
+
+class Add extends TestOp {
+ final arg1;
+ final arg2;
+
+ const Add(this.arg1, this.arg2, expected) : super(expected, arg1 + arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @pragma('dart2js:tryInline')
+ eval() => arg1 + arg2;
+}
+
+class Less extends TestOp {
+ final arg1;
+ final arg2;
+
+ const Less(this.arg1, this.arg2, expected) : super(expected, arg1 < arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @pragma('dart2js:tryInline')
+ eval() => arg1 < arg2;
+}
+
+class LessEqual extends TestOp {
+ final arg1;
+ final arg2;
+
+ const LessEqual(this.arg1, this.arg2, expected)
+ : super(expected, arg1 <= arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @pragma('dart2js:tryInline')
+ eval() => arg1 <= arg2;
+}
+
+class Greater extends TestOp {
+ final arg1;
+ final arg2;
+
+ const Greater(this.arg1, this.arg2, expected) : super(expected, arg1 > arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @pragma('dart2js:tryInline')
+ eval() => arg1 > arg2;
+}
+
+class GreaterEqual extends TestOp {
+ final arg1;
+ final arg2;
+
+ const GreaterEqual(this.arg1, this.arg2, expected)
+ : super(expected, arg1 >= arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @pragma('dart2js:tryInline')
+ eval() => arg1 >= arg2;
+}
+
+class Equals extends TestOp {
+ final arg1;
+ final arg2;
+
+ const Equals(this.arg1, this.arg2, expected) : super(expected, arg1 == arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @pragma('dart2js:tryInline')
+ eval() => arg1 == arg2;
+}
+
+class Identity extends TestOp {
+ final arg1;
+ final arg2;
+
+ const Identity(this.arg1, this.arg2, expected)
+ : super(expected, identical(arg1, arg2));
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @pragma('dart2js:tryInline')
+ eval() => identical(arg1, arg2);
+}
+
+class IfNull extends TestOp {
+ final arg1;
+ final arg2;
+
+ const IfNull(this.arg1, this.arg2, expected) : super(expected, arg1 ?? arg2);
+
+ @pragma('dart2js:tryInline')
+ check() => checkAll(eval());
+
+ @pragma('dart2js:tryInline')
+ eval() => arg1 ?? arg2;
+}
diff --git a/tests/compiler/dart2js_extra/effectively_constant_instance_field_test.dart b/tests/compiler/dart2js_extra/effectively_constant_instance_field_test.dart
new file mode 100644
index 0000000..94020a2
--- /dev/null
+++ b/tests/compiler/dart2js_extra/effectively_constant_instance_field_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+// dart2jsOptions=--omit-implicit-checks
+
+import 'package:expect/expect.dart';
+
+class C {
+ const C();
+}
+
+class A {
+ var field = const C();
+}
+
+class B {
+ var field;
+}
+
+@pragma('dart2js:noInline')
+test(o) => o.field;
+
+main() {
+ Expect.isNotNull(test(new A()));
+ Expect.isNull(test(new B()));
+}
diff --git a/tests/compiler/dart2js_extra/function_typed_arguments_test.dart b/tests/compiler/dart2js_extra/function_typed_arguments_test.dart
new file mode 100644
index 0000000..f18daee
--- /dev/null
+++ b/tests/compiler/dart2js_extra/function_typed_arguments_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2019, 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.
+
+// dart2jsOptions=--omit-implicit-checks
+
+// Test type tests of function types used a type argument.
+
+import 'package:expect/expect.dart';
+
+class A<T> {}
+
+main() {
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+}
+
+class B1<T> {}
+
+class C1 extends B1<int> {}
+
+@pragma('dart2js:noInline')
+test1() {
+ Expect.isTrue(_test1(new A<void Function(C1)>()));
+ Expect.isTrue(_test1(new A<void Function(B1<int>)>())); //# 01: ok
+ Expect.isFalse(_test1(new A<void Function(B1<String>)>()));
+}
+
+@pragma('dart2js:noInline')
+_test1(f) => f is A<void Function(C1)>;
+
+class B2<T> {}
+
+class C2 extends B2<int> {}
+
+@pragma('dart2js:noInline')
+test2() {
+ Expect.isTrue(_test2(new A<C2 Function()>()));
+ Expect.isFalse(_test2(new A<B2<int> Function()>()));
+ Expect.isFalse(_test2(new A<B2<String> Function()>()));
+}
+
+@pragma('dart2js:noInline')
+_test2(f) => f is A<C2 Function()>;
+
+class B3<T> {}
+
+class C3 extends B3<int> {}
+
+@pragma('dart2js:noInline')
+test3() {
+ Expect.isFalse(_test3(new A<void Function(C3)>()));
+ Expect.isTrue(_test3(new A<void Function(B3<int>)>()));
+ Expect.isFalse(_test3(new A<void Function(B3<String>)>()));
+}
+
+@pragma('dart2js:noInline')
+_test3(f) => f is A<void Function(B3<int>)>;
+
+class B4<T> {}
+
+class C4 extends B4<int> {}
+
+@pragma('dart4js:noInline')
+test4() {
+ Expect.isTrue(_test4(new A<C4 Function()>()));
+ Expect.isTrue(_test4(new A<B4<int> Function()>()));
+ Expect.isFalse(_test4(new A<B4<String> Function()>()));
+}
+
+@pragma('dart4js:noInline')
+_test4(f) => f is A<B4<int> Function()>;
+
+class B5<T> {}
+
+class C5 extends B5<int> {}
+
+@pragma('dart2js:noInline')
+test5() {
+ Expect.isTrue(_test5(new A<void Function(C5 Function())>()));
+ Expect.isTrue(_test5(new A<void Function(B5<int> Function())>())); //# 02: ok
+ Expect.isFalse(_test5(new A<void Function(B5<String> Function())>()));
+}
+
+@pragma('dart2js:noInline')
+_test5(f) => f is A<void Function(C5 Function())>;
+
+class B6<T> {}
+
+class C6 extends B6<int> {}
+
+@pragma('dart2js:noInline')
+test6() {
+ Expect.isTrue(_test6(new A<void Function(void Function(C6))>()));
+ Expect.isFalse(_test6(new A<void Function(void Function(B6<int>))>()));
+ Expect.isFalse(_test6(new A<void Function(void Function(B6<String>))>()));
+}
+
+@pragma('dart2js:noInline')
+_test6(f) => f is A<void Function(void Function(C6))>;
diff --git a/tests/compiler/dart2js_extra/injected_cast_test.dart b/tests/compiler/dart2js_extra/injected_cast_test.dart
new file mode 100644
index 0000000..3ab671c
--- /dev/null
+++ b/tests/compiler/dart2js_extra/injected_cast_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+var field;
+
+class Class {
+ @pragma('dart2js:noInline')
+ method(int i, int j, int k) {}
+}
+
+@pragma('dart2js:noInline')
+test1(dynamic c, num n) {
+ if (c is Class) {
+ c.method(field = 41, n, field = 42);
+ }
+}
+
+@pragma('dart2js:noInline')
+test2(dynamic c, num n) {
+ if (c is! Class) return;
+ c.method(field = 86, n, field = 87);
+}
+
+main() {
+ try {
+ test1(new Class(), 0.5);
+ field = 123;
+ field = 123;
+ } catch (e) {}
+ // CFE inserts the implicit cast directly on the argument expression, making
+ // it fail before later arguments are evaluated.
+ Expect.equals(41, field);
+
+ try {
+ test2(new Class(), 0.5);
+ field = 321;
+ field = 321;
+ } catch (e) {}
+ // dart2js inserts implicit casts, but does so after evaluating all arguments
+ // to ensure semantics match what it would be like to check the types when
+ // entering the callee.
+ Expect.equals(87, field);
+}
diff --git a/tests/compiler/dart2js_extra/regress_36222_test.dart b/tests/compiler/dart2js_extra/regress_36222_test.dart
new file mode 100644
index 0000000..f030833
--- /dev/null
+++ b/tests/compiler/dart2js_extra/regress_36222_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, 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 BinaryFunc(int x, int y);
+
+class A {
+ const A({this.foo = A.defaultFoo});
+
+ static int defaultFoo(int x, int y) {
+ return x + y;
+ }
+
+ final BinaryFunc foo;
+}
+
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+test(dynamic a) => a.foo(1, 2);
+
+main() {
+ test(new A());
+}
diff --git a/tests/compiler/dart2js_extra/tear_off_types_test.dart b/tests/compiler/dart2js_extra/tear_off_types_test.dart
new file mode 100644
index 0000000..d7f6c41
--- /dev/null
+++ b/tests/compiler/dart2js_extra/tear_off_types_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2019, 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.
+
+// dart2jsOptions=--omit-implicit-checks
+
+import 'package:expect/expect.dart';
+
+main() {
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
+}
+
+class A1<T> {}
+
+class B1 extends A1<int> {}
+
+@pragma('dart2js:noInline')
+test1() {
+ Expect.isTrue(_test1(method1a));
+ Expect.isTrue(_test1(method1b));
+ Expect.isFalse(_test1(method1c));
+}
+
+B1 method1a() => null;
+A1<int> method1b() => null;
+A1<String> method1c() => null;
+
+@pragma('dart2js:noInline')
+bool _test1(f) => f is A1<int> Function();
+
+class A2<T> {}
+
+class B2 extends A2<int> {}
+
+@pragma('dart2js:noInline')
+test2() {
+ Expect.isFalse(_test2(method2a));
+ Expect.isTrue(_test2(method2b));
+ Expect.isFalse(_test2(method2c));
+}
+
+void method2a(B2 b) {}
+void method2b(A2<int> a) {}
+void method2c(A2<String> a) {}
+
+@pragma('dart2js:noInline')
+bool _test2(f) => f is void Function(A2<int>);
+
+class A3<T> {}
+
+class B3 extends A3<int> {}
+
+@pragma('dart3js:noInline')
+test3() {
+ Expect.isTrue(_test3(method3a));
+ Expect.isTrue(_test3(method3b));
+ Expect.isFalse(_test3(method3c));
+}
+
+void method3a(B3 b) {}
+void method3b(A3<int> a) {}
+void method3c(A3<String> a) {}
+
+@pragma('dart3js:noInline')
+_test3(f) => f is void Function(B3);
+
+class A4<T> {}
+
+class B4 extends A4<int> {}
+
+@pragma('dart4js:noInline')
+test4() {
+ Expect.isTrue(_test4(method4a));
+ Expect.isFalse(_test4(method4b));
+ Expect.isFalse(_test4(method4c));
+}
+
+B4 method4a() => null;
+A4<int> method4b() => null;
+A4<String> method4c() => null;
+
+@pragma('dart4js:noInline')
+_test4(f) => f is B4 Function();
+
+class A5<T> {}
+
+class B5 extends A5<int> {}
+
+@pragma('dart2js:noInline')
+test5() {
+ Expect.isTrue(_test5(method5a));
+ Expect.isTrue(_test5(method5b));
+ Expect.isFalse(_test5(method5c));
+}
+
+void method5a(void Function(B5) f) => null;
+void method5b(void Function(A5<int>) f) => null;
+void method5c(void Function(A5<String>) f) => null;
+
+@pragma('dart2js:noInline')
+bool _test5(f) => f is void Function(void Function(A5<int>));
+
+class A6<T> {}
+
+class B6 extends A6<int> {}
+
+@pragma('dart6js:noInline')
+test6() {
+ Expect.isTrue(_test6(method6a));
+ Expect.isTrue(_test6(method6b));
+ Expect.isFalse(_test6(method6c));
+}
+
+void Function(B6) method6a() => null;
+void Function(A6<int>) method6b() => null;
+void Function(A6<String>) method6c() => null;
+
+@pragma('dart6js:noInline')
+_test6(f) => f is void Function(B6) Function();
+
+class A7<T> {}
+
+class B7 extends A7<int> {}
+
+@pragma('dart7js:noInline')
+test7() {
+ Expect.isTrue(_test7(method7a));
+ Expect.isFalse(_test7(method7b));
+ Expect.isFalse(_test7(method7c));
+}
+
+void method7a(void Function(B7) f) => null;
+void method7b(void Function(A7<int>) f) => null;
+void method7c(void Function(A7<String>) f) => null;
+
+@pragma('dart7js:noInline')
+_test7(f) => f is void Function(void Function(B7));
diff --git a/tests/corelib_2/bigint_test.dart b/tests/corelib_2/bigint_test.dart
index 46b69e1..01dea1f 100644
--- a/tests/corelib_2/bigint_test.dart
+++ b/tests/corelib_2/bigint_test.dart
@@ -1065,5 +1065,9 @@
var b = BigInt.parse("10000000000000000001"); /// 27: ok
Expect.equals(false, a.hashCode == b.hashCode); /// 27: ok
Expect.equals(true, a.hashCode == (b - BigInt.one).hashCode); /// 27: ok
+
+ // Regression test for http://dartbug.com/36105
+ var overbig = -BigInt.from(10).pow(309);
+ Expect.equals(overbig.toDouble(), double.negativeInfinity);
}
}
diff --git a/tests/corelib_2/regexp/lookbehind_test.dart b/tests/corelib_2/regexp/lookbehind_test.dart
new file mode 100644
index 0000000..5ccdcdb
--- /dev/null
+++ b/tests/corelib_2/regexp/lookbehind_test.dart
@@ -0,0 +1,440 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+ // Tests captures in positive and negative look-behind in regular expressions.
+
+ void testRE(RegExp re, String input, bool expectedResult) {
+ if (expectedResult) {
+ assertTrue(re.hasMatch(input));
+ } else {
+ assertFalse(re.hasMatch(input));
+ }
+ }
+
+ void execRE(RegExp re, String input, List<String> expectedResult) {
+ assertTrue(re.hasMatch(input));
+ shouldBe(re.firstMatch(input), expectedResult);
+ }
+
+ void multiRE(RegExp re, String input, List<List<String>> expectedResult) {
+ assertTrue(re.hasMatch(input));
+ final matches = re.allMatches(input);
+ assertEquals(matches.length, expectedResult.length);
+ for (var i = 0; i < matches.length; i++) {
+ shouldBe(matches.elementAt(i), expectedResult[i]);
+ }
+ }
+
+ // Simple fixed-length matches.
+
+ var re = new RegExp(r"^.(?<=a)");
+ execRE(re, "a", ["a"]);
+ testRE(re, "b", false);
+
+ re = new RegExp(r"^f..(?<=.oo)");
+ execRE(re, "foo1", ["foo"]);
+
+ re = new RegExp(r"^f\w\w(?<=\woo)");
+ execRE(re, "foo2", ["foo"]);
+ testRE(re, "boo", false);
+ testRE(re, "fao", false);
+ testRE(re, "foa", false);
+
+ re = new RegExp(r"(?<=abc)\w\w\w");
+ execRE(re, "abcdef", ["def"]);
+
+ re = new RegExp(r"(?<=a.c)\w\w\w");
+ execRE(re, "abcdef", ["def"]);
+
+ re = new RegExp(r"(?<=a\wc)\w\w\w");
+ execRE(re, "abcdef", ["def"]);
+
+ re = new RegExp(r"(?<=a[a-z])\w\w\w");
+ execRE(re, "abcdef", ["cde"]);
+
+ re = new RegExp(r"(?<=a[a-z][a-z])\w\w\w");
+ execRE(re, "abcdef", ["def"]);
+
+ re = new RegExp(r"(?<=a[a-z]{2})\w\w\w");
+ execRE(re, "abcdef", ["def"]);
+
+ re = new RegExp(r"(?<=a{1})\w\w\w");
+ execRE(re, "abcdef", ["bcd"]);
+
+ re = new RegExp(r"(?<=a{1}b{1})\w\w\w");
+ execRE(re, "abcdef", ["cde"]);
+
+ re = new RegExp(r"(?<=a{1}[a-z]{2})\w\w\w");
+ execRE(re, "abcdef", ["def"]);
+
+ // Variable-length matches.
+
+ re = new RegExp(r"(?<=[a|b|c]*)[^a|b|c]{3}");
+ execRE(re, "abcdef", ["def"]);
+
+ re = new RegExp(r"(?<=\w*)[^a|b|c]{3}");
+ execRE(re, "abcdef", ["def"]);
+
+ re = new RegExp(r"(?<=b|c)\w");
+ multiRE(re, "abcdef", [
+ ["c"],
+ ["d"]
+ ]);
+
+ re = new RegExp(r"(?<=[b-e])\w{2}");
+ multiRE(re, "abcdef", [
+ ["cd"],
+ ["ef"]
+ ]);
+
+ // Start of line matches.
+
+ re = new RegExp(r"(?<=^abc)def");
+ execRE(re, "abcdef", ["def"]);
+
+ re = new RegExp(r"(?<=^[a-c]{3})def");
+ execRE(re, "abcdef", ["def"]);
+
+ re = new RegExp(r"(?<=^[a-c]{3})def", multiLine: true);
+ execRE(re, "xyz\nabcdef", ["def"]);
+
+ re = new RegExp(r"(?<=^)\w+", multiLine: true);
+ multiRE(re, "ab\ncd\nefg", [
+ ["ab"],
+ ["cd"],
+ ["efg"]
+ ]);
+
+ re = new RegExp(r"\w+(?<=$)", multiLine: true);
+ multiRE(re, "ab\ncd\nefg", [
+ ["ab"],
+ ["cd"],
+ ["efg"]
+ ]);
+
+ re = new RegExp(r"(?<=^)\w+(?<=$)", multiLine: true);
+ multiRE(re, "ab\ncd\nefg", [
+ ["ab"],
+ ["cd"],
+ ["efg"]
+ ]);
+
+ re = new RegExp(r"(?<=^[^a-c]{3})def");
+ testRE(re, "abcdef", false);
+
+ re = new RegExp(r"^foooo(?<=^o+)$");
+ testRE(re, "foooo", false);
+
+ re = new RegExp(r"^foooo(?<=^o*)$");
+ testRE(re, "foooo", false);
+
+ re = new RegExp(r"^foo(?<=^fo+)$");
+ execRE(re, "foo", ["foo"]);
+
+ re = new RegExp(r"^foooo(?<=^fo*)");
+ execRE(re, "foooo", ["foooo"]);
+
+ re = new RegExp(r"^(f)oo(?<=^\1o+)$");
+ testRE(re, "foo", true);
+ execRE(re, "foo", ["foo", "f"]);
+
+ re = new RegExp(r"^(f)oo(?<=^\1o+)$", caseSensitive: false);
+ execRE(re, "foo", ["foo", "f"]);
+
+ re = new RegExp(r"^(f)oo(?<=^\1o+).$", caseSensitive: false);
+ execRE(re, "foo\u1234", ["foo\u1234", "f"]);
+
+ re = new RegExp(r"(?<=^\w+)def");
+ execRE(re, "abcdefdef", ["def"]);
+ multiRE(re, "abcdefdef", [
+ ["def"],
+ ["def"]
+ ]);
+
+ // Word boundary matches.
+
+ re = new RegExp(r"(?<=\b)[d-f]{3}");
+ execRE(re, "abc def", ["def"]);
+
+ re = new RegExp(r"(?<=\B)\w{3}");
+ execRE(re, "ab cdef", ["def"]);
+
+ re = new RegExp(r"(?<=\B)(?<=c(?<=\w))\w{3}");
+ execRE(re, "ab cdef", ["def"]);
+
+ re = new RegExp(r"(?<=\b)[d-f]{3}");
+ testRE(re, "abcdef", false);
+
+ // Negative lookbehind.
+
+ re = new RegExp(r"(?<!abc)\w\w\w");
+ execRE(re, "abcdef", ["abc"]);
+
+ re = new RegExp(r"(?<!a.c)\w\w\w");
+ execRE(re, "abcdef", ["abc"]);
+
+ re = new RegExp(r"(?<!a\wc)\w\w\w");
+ execRE(re, "abcdef", ["abc"]);
+
+ re = new RegExp(r"(?<!a[a-z])\w\w\w");
+ execRE(re, "abcdef", ["abc"]);
+
+ re = new RegExp(r"(?<!a[a-z]{2})\w\w\w");
+ execRE(re, "abcdef", ["abc"]);
+
+ re = new RegExp(r"(?<!abc)def");
+ testRE(re, "abcdef", false);
+
+ re = new RegExp(r"(?<!a.c)def");
+ testRE(re, "abcdef", false);
+
+ re = new RegExp(r"(?<!a\wc)def");
+ testRE(re, "abcdef", false);
+
+ re = new RegExp(r"(?<!a[a-z][a-z])def");
+ testRE(re, "abcdef", false);
+
+ re = new RegExp(r"(?<!a[a-z]{2})def");
+ testRE(re, "abcdef", false);
+
+ re = new RegExp(r"(?<!a{1}b{1})cde");
+ testRE(re, "abcdef", false);
+
+ re = new RegExp(r"(?<!a{1}[a-z]{2})def");
+ testRE(re, "abcdef", false);
+
+ // Capturing matches.
+ re = new RegExp(r"(?<=(c))def");
+ execRE(re, "abcdef", ["def", "c"]);
+
+ re = new RegExp(r"(?<=(\w{2}))def");
+ execRE(re, "abcdef", ["def", "bc"]);
+
+ re = new RegExp(r"(?<=(\w(\w)))def");
+ execRE(re, "abcdef", ["def", "bc", "c"]);
+
+ re = new RegExp(r"(?<=(\w){3})def");
+ execRE(re, "abcdef", ["def", "a"]);
+
+ re = new RegExp(r"(?<=(bc)|(cd)).");
+ execRE(re, "abcdef", ["d", "bc", null]);
+
+ re = new RegExp(r"(?<=([ab]{1,2})\D|(abc))\w");
+ execRE(re, "abcdef", ["c", "a", null]);
+
+ re = new RegExp(r"\D(?<=([ab]+))(\w)");
+ execRE(re, "abcdef", ["ab", "a", "b"]);
+
+ // Captures inside negative lookbehind. (They never capture.)
+ re = new RegExp(r"(?<!(^|[ab]))\w{2}");
+ execRE(re, "abcdef", ["de", null]);
+
+ // Nested lookaround.
+ re = new RegExp(r"(?<=ab(?=c)\wd)\w\w");
+ execRE(re, "abcdef", ["ef"]);
+
+ re = new RegExp(r"(?<=a(?=([^a]{2})d)\w{3})\w\w");
+ execRE(re, "abcdef", ["ef", "bc"]);
+
+ re = new RegExp(r"(?<=a(?=([bc]{2}(?<!a{2}))d)\w{3})\w\w");
+ execRE(re, "abcdef", ["ef", "bc"]);
+
+ re = new RegExp(r"(?<=a(?=([bc]{2}(?<!a*))d)\w{3})\w\w/");
+ testRE(re, "abcdef", false);
+
+ re = new RegExp(r"^faaao?(?<=^f[oa]+(?=o))");
+ execRE(re, "faaao", ["faaa"]);
+
+ // Back references.
+ re = new RegExp(r"(.)(?<=(\1\1))");
+ execRE(re, "abb", ["b", "b", "bb"]);
+
+ re = new RegExp(r"(.)(?<=(\1\1))", caseSensitive: false);
+ execRE(re, "abB", ["B", "B", "bB"]);
+
+ re = new RegExp(r"((\w)\w)(?<=\1\2\1)", caseSensitive: false);
+ execRE(re, "aabAaBa", ["aB", "aB", "a"]);
+
+ re = new RegExp(r"(\w(\w))(?<=\1\2\1)", caseSensitive: false);
+ execRE(re, "aabAaBa", ["Ba", "Ba", "a"]);
+
+ re = new RegExp(r"(?=(\w))(?<=(\1)).", caseSensitive: false);
+ execRE(re, "abaBbAa", ["b", "b", "B"]);
+
+ re = new RegExp(r"(?<=(.))(\w+)(?=\1)");
+ execRE(re, " 'foo' ", ["foo", "'", "foo"]);
+ execRE(re, " \"foo\" ", ["foo", "\"", "foo"]);
+ testRE(re, " .foo\" ", false);
+
+ re = new RegExp(r"(.)(?<=\1\1\1)");
+ testRE(re, "ab", false);
+ testRE(re, "abb", false);
+ execRE(re, "abbb", ["b", "b"]);
+
+ re = new RegExp(r"(..)(?<=\1\1\1)");
+ testRE(re, "ab", false);
+ testRE(re, "abb", false);
+ testRE(re, "aabb", false);
+ testRE(re, "abab", false);
+ testRE(re, "fabxbab", false);
+ testRE(re, "faxabab", false);
+ execRE(re, "fababab", ["ab", "ab"]);
+
+ // Back references to captures inside the lookbehind.
+ re = new RegExp(r"(?<=\1(\w))d", caseSensitive: false);
+ execRE(re, "abcCd", ["d", "C"]);
+
+ re = new RegExp(r"(?<=\1([abx]))d");
+ execRE(re, "abxxd", ["d", "x"]);
+
+ re = new RegExp(r"(?<=\1(\w+))c");
+ execRE(re, "ababc", ["c", "ab"]);
+ execRE(re, "ababbc", ["c", "b"]);
+ testRE(re, "ababdc", false);
+
+ re = new RegExp(r"(?<=(\w+)\1)c");
+ execRE(re, "ababc", ["c", "abab"]);
+
+ // Alternations are tried left to right,
+ // and we do not backtrack into a lookbehind.
+ re = new RegExp(r".*(?<=(..|...|....))(.*)");
+ execRE(re, "xabcd", ["xabcd", "cd", ""]);
+
+ re = new RegExp(r".*(?<=(xx|...|....))(.*)");
+ execRE(re, "xabcd", ["xabcd", "bcd", ""]);
+
+ re = new RegExp(r".*(?<=(xx|...))(.*)");
+ execRE(re, "xxabcd", ["xxabcd", "bcd", ""]);
+
+ re = new RegExp(r".*(?<=(xx|xxx))(.*)");
+ execRE(re, "xxabcd", ["xxabcd", "xx", "abcd"]);
+
+ // We do not backtrack into a lookbehind.
+ // The lookbehind captures "abc" so that \1 does not match. We do not backtrack
+ // to capture only "bc" in the lookbehind.
+ re = new RegExp(r"(?<=([abc]+)).\1");
+ testRE(re, "abcdbc", false);
+
+ // Greedy loop.
+ re = new RegExp(r"(?<=(b+))c");
+ execRE(re, "abbbbbbc", ["c", "bbbbbb"]);
+
+ re = new RegExp(r"(?<=(b\d+))c");
+ execRE(re, "ab1234c", ["c", "b1234"]);
+
+ re = new RegExp(r"(?<=((?:b\d{2})+))c");
+ execRE(re, "ab12b23b34c", ["c", "b12b23b34"]);
+
+ // Sticky
+ re = new RegExp(r"(?<=^(\w+))def");
+ multiRE(re, "abcdefdef", [
+ ["def", "abc"],
+ ["def", "abcdef"]
+ ]);
+
+ re = new RegExp(r"\Bdef");
+ multiRE(re, "abcdefdef", [
+ ["def"],
+ ["def"]
+ ]);
+
+ // Misc
+ re = new RegExp(r"(?<=$abc)def");
+ testRE(re, "abcdef", false);
+
+ re = new RegExp(r"^foo(?<=foo)$");
+ execRE(re, "foo", ["foo"]);
+
+ re = new RegExp(r"^f.o(?<=foo)$");
+ execRE(re, "foo", ["foo"]);
+
+ re = new RegExp(r"^f.o(?<=foo)$");
+ testRE(re, "fno", false);
+
+ re = new RegExp(r"^foo(?<!foo)$");
+ testRE(re, "foo", false);
+
+ re = new RegExp(r"^f.o(?<!foo)$");
+ testRE(re, "foo", false);
+ execRE(re, "fno", ["fno"]);
+
+ re = new RegExp(r"^foooo(?<=fo+)$");
+ execRE(re, "foooo", ["foooo"]);
+
+ re = new RegExp(r"^foooo(?<=fo*)$");
+ execRE(re, "foooo", ["foooo"]);
+
+ re = new RegExp(r"(abc\1)");
+ execRE(re, "abc", ["abc", "abc"]);
+ execRE(re, "abc\u1234", ["abc", "abc"]);
+
+ re = new RegExp(r"(abc\1)", caseSensitive: false);
+ execRE(re, "abc", ["abc", "abc"]);
+ execRE(re, "abc\u1234", ["abc", "abc"]);
+
+ final oob_subject = "abcdefghijklmnabcdefghijklmn".substring(14);
+ re = new RegExp(r"(?=(abcdefghijklmn))(?<=\1)a", caseSensitive: false);
+ testRE(re, oob_subject, false);
+
+ re = new RegExp(r"(?=(abcdefghijklmn))(?<=\1)a");
+ testRE(re, oob_subject, false);
+
+ re = new RegExp(r"(?=(abcdefg))(?<=\1)");
+ testRE(re, "abcdefgabcdefg".substring(1), false);
+
+ // Mutual recursive capture/back references
+ re = new RegExp(r"(?<=a(.\2)b(\1)).{4}");
+ execRE(re, "aabcacbc", ["cacb", "a", ""]);
+
+ re = new RegExp(r"(?<=a(\2)b(..\1))b");
+ execRE(re, "aacbacb", ["b", "ac", "ac"]);
+
+ re = new RegExp(r"(?<=(?:\1b)(aa)).");
+ execRE(re, "aabaax", ["x", "aa"]);
+
+ re = new RegExp(r"(?<=(?:\1|b)(aa)).");
+ execRE(re, "aaaax", ["x", "aa"]);
+
+ // Restricted syntax in Annex B 1.4.
+ // The check for quantifiers on lookbehinds was added later than the
+ // original feature in v8, so we may need to approve failures here
+ // separately from the rest of the file.
+ assertThrows(() => new RegExp(r"(?<=.)*")); //# 01: ok
+ assertThrows(() => new RegExp(r"(?<=.)?")); //# 01: ok
+ assertThrows(() => new RegExp(r"(?<=.)+")); //# 01: ok
+
+ // No unicode flag (yet), so can't test these.
+ // See https://github.com/dart-lang/sdk/issues/36170.
+ // assertThrows("/(?<=.)*/u", SyntaxError);
+ // assertThrows("/(?<=.){1,2}/u", SyntaxError);
+}
diff --git a/tests/corelib_2/string_replace_all_2_test.dart b/tests/corelib_2/string_replace_all_2_test.dart
new file mode 100644
index 0000000..39d196a
--- /dev/null
+++ b/tests/corelib_2/string_replace_all_2_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// dart2jsOptions=-Ddart2js.testing.String.replaceAll.force.regexp=true
+
+import "string_replace_all_test.dart" as base;
+
+main() {
+ base.main();
+}
diff --git a/tests/language_2/cascaded_forwarding_stubs_test.dart b/tests/language_2/cascaded_forwarding_stubs_test.dart
index 1af182b..a10cc2e 100644
--- a/tests/language_2/cascaded_forwarding_stubs_test.dart
+++ b/tests/language_2/cascaded_forwarding_stubs_test.dart
@@ -24,7 +24,9 @@
}
// E contains a forwarding stub for f which ensures that `y` is type checked.
-class E extends D implements I2 {}
+class E extends D implements I2 {
+ void f(B x, B y);
+}
main() {
E e = new E();
diff --git a/tests/language_2/control_flow_collections/experimental_flag_test.dart b/tests/language_2/control_flow_collections/experimental_flag_test.dart
index aa3d8a1..a044a01 100644
--- a/tests/language_2/control_flow_collections/experimental_flag_test.dart
+++ b/tests/language_2/control_flow_collections/experimental_flag_test.dart
@@ -4,9 +4,6 @@
// Check that control flow is not enabled without the experimental flag.
-// Do enable set literals, just not the new syntax in them.
-// SharedOptions=--enable-experiment=set-literals
-
// TODO(rnystrom): Remove this test when the feature is enabled without a flag.
void main() {
diff --git a/tests/language_2/control_flow_collections/for_const_test.dart b/tests/language_2/control_flow_collections/for_const_test.dart
index 022ec24..3ba2d91 100644
--- a/tests/language_2/control_flow_collections/for_const_test.dart
+++ b/tests/language_2/control_flow_collections/for_const_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections
+// SharedOptions=--enable-experiment=control-flow-collections
void main() {
// For cannot be used in a const collection.
diff --git a/tests/language_2/control_flow_collections/for_inference_test.dart b/tests/language_2/control_flow_collections/for_inference_test.dart
index 3d9773b..9c462262 100644
--- a/tests/language_2/control_flow_collections/for_inference_test.dart
+++ b/tests/language_2/control_flow_collections/for_inference_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
// Test how control flow interacts with inference.
import 'package:expect/expect.dart';
diff --git a/tests/language_2/control_flow_collections/for_test.dart b/tests/language_2/control_flow_collections/for_test.dart
index 6add35f..f9aee00 100644
--- a/tests/language_2/control_flow_collections/for_test.dart
+++ b/tests/language_2/control_flow_collections/for_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
import 'package:expect/expect.dart';
@@ -118,7 +118,7 @@
// Else inside for.
Expect.mapEquals(map,
- <int, int>{for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i else i: i});
+ <int, int>{for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i: -i else i: i});
// For inside for.
Expect.mapEquals(map, <int, int>{
@@ -230,9 +230,9 @@
void testRuntimeErrors() {
// Non-bool condition expression.
dynamic nonBool = 3;
- Expect.throwsCastError(() => <int>[for (; nonBool;) 1]);
- Expect.throwsCastError(() => <int, int>{for (; nonBool;) 1: 1});
- Expect.throwsCastError(() => <int>{for (; nonBool;) 1});
+ Expect.throwsTypeError(() => <int>[for (; nonBool;) 1]);
+ Expect.throwsTypeError(() => <int, int>{for (; nonBool;) 1: 1});
+ Expect.throwsTypeError(() => <int>{for (; nonBool;) 1});
// Null condition expression.
bool nullBool = null;
@@ -242,15 +242,15 @@
// Cast for variable.
dynamic nonInt = "string";
- Expect.throwsCastError(() => <int>[for (int i = nonInt; false;) 1]);
- Expect.throwsCastError(() => <int, int>{for (int i = nonInt; false;) 1: 1});
- Expect.throwsCastError(() => <int>{for (int i = nonInt; false;) 1});
+ Expect.throwsTypeError(() => <int>[for (int i = nonInt; false;) 1]);
+ Expect.throwsTypeError(() => <int, int>{for (int i = nonInt; false;) 1: 1});
+ Expect.throwsTypeError(() => <int>{for (int i = nonInt; false;) 1});
// Cast for-in variable.
dynamic nonIterable = 3;
- Expect.throwsCastError(() => <int>[for (int i in nonIterable) 1]);
- Expect.throwsCastError(() => <int, int>{for (int i in nonIterable) 1: 1});
- Expect.throwsCastError(() => <int>{for (int i in nonIterable) 1});
+ Expect.throwsTypeError(() => <int>[for (int i in nonIterable) 1]);
+ Expect.throwsTypeError(() => <int, int>{for (int i in nonIterable) 1: 1});
+ Expect.throwsTypeError(() => <int>{for (int i in nonIterable) 1});
// Null iterable.
Iterable<int> nullIterable = null;
@@ -260,10 +260,10 @@
Expect.throwsNoSuchMethodError(() => <int>{for (var i in nullIterable) 1});
// Wrong element type.
- Expect.throwsCastError(() => <int>[for (var i = 0; i < 1; i++) nonInt]);
- Expect.throwsCastError(
+ Expect.throwsTypeError(() => <int>[for (var i = 0; i < 1; i++) nonInt]);
+ Expect.throwsTypeError(
() => <int, int>{for (var i = 0; i < 1; i++) nonInt: 1});
- Expect.throwsCastError(
+ Expect.throwsTypeError(
() => <int, int>{for (var i = 0; i < 1; i++) 1: nonInt});
- Expect.throwsCastError(() => <int>{for (var i = 0; i < 1; i++) nonInt});
+ Expect.throwsTypeError(() => <int>{for (var i = 0; i < 1; i++) nonInt});
}
diff --git a/tests/language_2/control_flow_collections/for_variable_test.dart b/tests/language_2/control_flow_collections/for_variable_test.dart
index b7b4307..f866daf 100644
--- a/tests/language_2/control_flow_collections/for_variable_test.dart
+++ b/tests/language_2/control_flow_collections/for_variable_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
/// Tests for how variables and scoping work with for elements.
import 'package:expect/expect.dart';
diff --git a/tests/language_2/control_flow_collections/if_const_error_test.dart b/tests/language_2/control_flow_collections/if_const_error_test.dart
index 4e100a6..8f6acf9 100644
--- a/tests/language_2/control_flow_collections/if_const_error_test.dart
+++ b/tests/language_2/control_flow_collections/if_const_error_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections
+// SharedOptions=--enable-experiment=control-flow-collections
import 'dart:collection';
diff --git a/tests/language_2/control_flow_collections/if_const_test.dart b/tests/language_2/control_flow_collections/if_const_test.dart
index e30939cb..258a889 100644
--- a/tests/language_2/control_flow_collections/if_const_test.dart
+++ b/tests/language_2/control_flow_collections/if_const_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
import 'package:expect/expect.dart';
@@ -70,12 +70,6 @@
// Nested if in else.
Expect.identical(const [1], const <int>[if (false) 9 else if (true) 1]);
-
- // Nested for in then.
- Expect.identical(list, const <int>[if (true) for (var i in list) i]);
-
- // Nested for in else.
- Expect.identical(list, const <int>[if (false) 9 else for (var i in list) i]);
}
void testMap() {
@@ -122,13 +116,6 @@
// Nested if in else.
Expect.identical(const {1: 1},
const <int, int>{if (false) 9: 9 else if (true) 1: 1});
-
- // Nested for in then.
- Expect.identical(map, const <int, int>{if (true) for (var i in list) i: i});
-
- // Nested for in else.
- Expect.identical(map,
- const <int, int>{if (false) 9: 9 else for (var i in list) i: i});
}
void testSet() {
@@ -142,7 +129,7 @@
Expect.identical(set, const <int>{1, if (false) 9 else 2, 3});
// Only if.
- Expect.identical({1}, const <int>{if (true) 1});
+ Expect.identical(const <int>{1}, const <int>{if (true) 1});
// If at beginning.
Expect.identical(set, const <int>{if (true) 1, 2, 3});
@@ -177,12 +164,6 @@
// Nested if in else.
Expect.identical(const <int>{1}, const <int>{if (false) 9 else if (true) 1});
-
- // Nested for in then.
- Expect.identical(set, const <int>{if (true) for (var i in list) i});
-
- // Nested for in else.
- Expect.identical(set, const <int>{if (false) 9 else for (var i in list) i});
}
void testShortCircuit() {
@@ -220,7 +201,7 @@
Expect.identical(const <int>[1, 2],
const <int>[if (true) 1 else nonInt, if (false) nonInt else 2]);
- Expect.identical(const <int>{1: 1}, const <int, int>{
+ Expect.identical(const <int, int>{1: 1}, const <int, int>{
if (true) 1: 1,
if (false) nonInt: 9,
if (false) 9: nonInt
diff --git a/tests/language_2/control_flow_collections/if_inference_test.dart b/tests/language_2/control_flow_collections/if_inference_test.dart
index adc6e65..0c73618 100644
--- a/tests/language_2/control_flow_collections/if_inference_test.dart
+++ b/tests/language_2/control_flow_collections/if_inference_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
// Test how control flow interacts with inference.
import 'package:expect/expect.dart';
diff --git a/tests/language_2/control_flow_collections/if_test.dart b/tests/language_2/control_flow_collections/if_test.dart
index d420e16..4ffd515 100644
--- a/tests/language_2/control_flow_collections/if_test.dart
+++ b/tests/language_2/control_flow_collections/if_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
import 'package:expect/expect.dart';
@@ -232,9 +232,9 @@
void testRuntimeFailures() {
dynamic nonBool = 3;
- Expect.throwsCastError(() => <int>[if (nonBool) 1]);
- Expect.throwsCastError(() => <int, int>{if (nonBool) 1: 1});
- Expect.throwsCastError(() => <int>{if (nonBool) 1});
+ Expect.throwsTypeError(() => <int>[if (nonBool) 1]);
+ Expect.throwsTypeError(() => <int, int>{if (nonBool) 1: 1});
+ Expect.throwsTypeError(() => <int>{if (nonBool) 1});
bool nullBool = null;
Expect.throwsAssertionError(() => <int>[if (nullBool) 1]);
diff --git a/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart b/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart
index 5296956..452ac9b 100644
--- a/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart
+++ b/tests/language_2/control_flow_collections/map_set_ambiguity_error_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
// Test cases where the syntax is ambiguous between maps and sets when control
// flow elements contain spreads.
diff --git a/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart b/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
index abd6f58..271bb09 100644
--- a/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
+++ b/tests/language_2/control_flow_collections/map_set_ambiguity_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
// Test cases where the syntax is ambiguous between maps and sets because of
// spreads inside control flow.
diff --git a/tests/language_2/control_flow_collections/syntax_test.dart b/tests/language_2/control_flow_collections/syntax_test.dart
index c6de2d8..0810aec 100644
--- a/tests/language_2/control_flow_collections/syntax_test.dart
+++ b/tests/language_2/control_flow_collections/syntax_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections
+// SharedOptions=--enable-experiment=control-flow-collections
// Tests syntax edge cases.
import 'package:expect/expect.dart';
diff --git a/tests/language_2/control_flow_collections/type_error_test.dart b/tests/language_2/control_flow_collections/type_error_test.dart
index ace6588..2656b7f 100644
--- a/tests/language_2/control_flow_collections/type_error_test.dart
+++ b/tests/language_2/control_flow_collections/type_error_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.
-// SharedOptions=--enable-experiment=set-literals,control-flow-collections
+// SharedOptions=--enable-experiment=control-flow-collections
void main() {
Object obj = true;
diff --git a/tests/language_2/generic_methods_generic_function_result_test.dart b/tests/language_2/generic_methods_generic_function_result_test.dart
index cc583fe9..3a391ec 100644
--- a/tests/language_2/generic_methods_generic_function_result_test.dart
+++ b/tests/language_2/generic_methods_generic_function_result_test.dart
@@ -2,8 +2,6 @@
// 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
-
// Verify that function type parameter S can be resolved in bar's result type.
// Verify that generic function types are not allowed as type arguments.
diff --git a/tests/language_2/hello_dart_test.dart b/tests/language_2/hello_dart_test.dart
index 0af0005..d53705b 100644
--- a/tests/language_2/hello_dart_test.dart
+++ b/tests/language_2/hello_dart_test.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// Simple test program invoked with an option to eagerly
// compile all code that is loaded in the isolate.
-// VMOptions=--compile_all --error-on-bad-type
+// VMOptions=--compile_all
class HelloDartTest {
static testMain() {
diff --git a/tests/language_2/issue21957_test.dart b/tests/language_2/issue21957_double_test.dart
similarity index 100%
rename from tests/language_2/issue21957_test.dart
rename to tests/language_2/issue21957_double_test.dart
diff --git a/tests/language_2/issue21957_float32x4_test.dart b/tests/language_2/issue21957_float32x4_test.dart
new file mode 100644
index 0000000..f364261
--- /dev/null
+++ b/tests/language_2/issue21957_float32x4_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+// Check slow path for PotentialUnboxedStore.
+// VMOptions=--optimization_counter_threshold=-1
+
+import "dart:typed_data";
+
+main() {
+ for (int i = 0; i < 1000000; i++) {
+ new A();
+ }
+}
+
+class A {
+ var a = new Float32x4(1.0, 2.0, 3.0, 4.0);
+}
diff --git a/tests/language_2/issue21957_float64x2_test.dart b/tests/language_2/issue21957_float64x2_test.dart
new file mode 100644
index 0000000..5b51722
--- /dev/null
+++ b/tests/language_2/issue21957_float64x2_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+// Check slow path for PotentialUnboxedStore.
+// VMOptions=--optimization_counter_threshold=-1
+
+import "dart:typed_data";
+
+main() {
+ for (int i = 0; i < 1000000; i++) {
+ new A();
+ }
+}
+
+class A {
+ var a = new Float64x2(1.0, 2.0);
+}
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 88da305..23788e5 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -53,6 +53,12 @@
stacktrace_demangle_ctors_test: SkipByDesign # Names are not scrubbed.
type_checks_in_factory_method_test: SkipByDesign # Requires checked mode.
+[ $runtime == vm ]
+spread_collections/const_error_test/05: Crash
+spread_collections/const_error_test/06: Crash
+spread_collections/const_error_test/07: Crash
+spread_collections/const_error_test/08: Crash
+
[ $fasta ]
partial_instantiation_static_bounds_check_test/01: MissingCompileTimeError # Issue 34327
partial_instantiation_static_bounds_check_test/02: MissingCompileTimeError # Issue 34327
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 9bfaf74..804ad39 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -22,6 +22,7 @@
config_import_test: RuntimeError # Test flag is not passed to the compiler.
const_constructor_nonconst_param_test/01: MissingCompileTimeError
const_dynamic_type_literal_test/03: Pass # but it shouldn't until we fix issue 17207
+control_flow_collections/*: Skip
deopt_inlined_function_lazy_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
deopt_smi_op_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in dart2js; bug #11551.
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index b678948..b3372d6 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -184,6 +184,7 @@
const_optional_args_test/01: MissingCompileTimeError
const_syntax_test/05: MissingCompileTimeError
constants_test/05: MissingCompileTimeError
+control_flow_collections/*: Skip
covariant_subtyping_test: RuntimeError
deferred_load_library_wrong_args_test/01: CompileTimeError
double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in ddk
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index bff609c..d20e287 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -37,18 +37,7 @@
const_nested_test: RuntimeError
const_string_test: RuntimeError
constructor12_test: RuntimeError
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: DartkCrash
-control_flow_collections/for_test: DartkCrash
-control_flow_collections/for_variable_test: DartkCrash
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: DartkCrash
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: DartkCrash
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_error_test/09: DartkCrash
-control_flow_collections/syntax_error_test/10: DartkCrash
-control_flow_collections/syntax_test: CompileTimeError
+control_flow_collections/*: Skip
covariant_subtyping_test: RuntimeError
ct_const_test: RuntimeError
cyclic_type2_test: CompileTimeError
@@ -166,17 +155,11 @@
mixin_method_override_test/G5: Skip # Issue 34354
private_method_tearoff_test: RuntimeError
+[ $compiler == dartk ]
+control_flow_collections/*: Skip
+
[ $compiler == dartkp ]
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: CompileTimeError
-control_flow_collections/for_test: CompileTimeError
-control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: CompileTimeError
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: CompileTimeError
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_test: CompileTimeError
+control_flow_collections/*: Skip
covariant_subtyping_test: RuntimeError
generic_no_such_method_dispatcher_test: RuntimeError # Issue 31424
spread_collections/await_test: CompileTimeError
@@ -221,14 +204,43 @@
control_flow_collections/for_inference_test: CompileTimeError
control_flow_collections/for_test: CompileTimeError
control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
+control_flow_collections/if_const_error_test/02: MissingCompileTimeError
+control_flow_collections/if_const_error_test/07: MissingCompileTimeError
+control_flow_collections/if_const_error_test/08: MissingCompileTimeError
+control_flow_collections/if_const_error_test/10: MissingCompileTimeError
+control_flow_collections/if_const_error_test/19: MissingCompileTimeError
+control_flow_collections/if_const_error_test/20: MissingCompileTimeError
+control_flow_collections/if_const_error_test/21: MissingCompileTimeError
+control_flow_collections/if_const_error_test/22: MissingCompileTimeError
+control_flow_collections/if_const_error_test/26: MissingCompileTimeError
+control_flow_collections/if_const_error_test/28: MissingCompileTimeError
+control_flow_collections/if_const_error_test/33: MissingCompileTimeError
+control_flow_collections/if_const_error_test/34: MissingCompileTimeError
+control_flow_collections/if_const_error_test/38: MissingCompileTimeError
+control_flow_collections/if_const_error_test/39: MissingCompileTimeError
control_flow_collections/if_const_test: CompileTimeError
control_flow_collections/if_inference_test: CompileTimeError
+control_flow_collections/if_promotion_test/04: MissingCompileTimeError
+control_flow_collections/if_promotion_test/05: MissingCompileTimeError
+control_flow_collections/if_promotion_test/06: MissingCompileTimeError
+control_flow_collections/if_promotion_test/07: MissingCompileTimeError
+control_flow_collections/if_promotion_test/08: MissingCompileTimeError
control_flow_collections/if_test: CompileTimeError
control_flow_collections/map_set_ambiguity_test: CompileTimeError
control_flow_collections/syntax_error_test/09: Crash
control_flow_collections/syntax_error_test/10: Crash
control_flow_collections/syntax_test: CompileTimeError
+control_flow_collections/type_error_test/00: MissingCompileTimeError
+control_flow_collections/type_error_test/01: MissingCompileTimeError
+control_flow_collections/type_error_test/02: MissingCompileTimeError
+control_flow_collections/type_error_test/06: MissingCompileTimeError
+control_flow_collections/type_error_test/07: MissingCompileTimeError
+control_flow_collections/type_error_test/08: MissingCompileTimeError
+control_flow_collections/type_error_test/09: MissingCompileTimeError
+control_flow_collections/type_error_test/10: MissingCompileTimeError
+control_flow_collections/type_error_test/11: MissingCompileTimeError
+control_flow_collections/type_error_test/12: MissingCompileTimeError
+control_flow_collections/type_error_test/13: MissingCompileTimeError
implicit_creation/implicit_const_not_default_values_test/e1: MissingCompileTimeError
implicit_creation/implicit_const_not_default_values_test/e10: MissingCompileTimeError
implicit_creation/implicit_const_not_default_values_test/e11: MissingCompileTimeError
@@ -260,26 +272,10 @@
spread_collections/const_error_test/10: MissingCompileTimeError
spread_collections/const_error_test/11: MissingCompileTimeError
spread_collections/const_error_test/12: MissingCompileTimeError
-spread_collections/const_error_test/13: MissingCompileTimeError
+spread_collections/const_error_test/13: Crash
spread_collections/const_error_test/14: MissingCompileTimeError
spread_collections/const_error_test/15: MissingCompileTimeError
spread_collections/const_error_test/16: MissingCompileTimeError
-spread_collections/const_test: CompileTimeError
-spread_collections/map_set_ambiguity_error_test/00: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/01: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/02: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/03: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/04: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/05: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/06: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/07: MissingCompileTimeError
-spread_collections/map_set_ambiguity_test: CompileTimeError
-spread_collections/spread_test: CompileTimeError
-spread_collections/syntax_test: CompileTimeError
-spread_collections/type_error_test/01: MissingCompileTimeError
-spread_collections/type_error_test/04: MissingCompileTimeError
-spread_collections/type_error_test/07: MissingCompileTimeError
-spread_collections/type_error_test/08: MissingCompileTimeError
vm/regress_33469_test/01: MissingCompileTimeError
vm/regress_33469_test/02: MissingCompileTimeError
vm/regress_33469_test/03: MissingCompileTimeError
@@ -293,9 +289,6 @@
async_return_types_test/nestedFuture: MissingCompileTimeError # Issue 33068
const_cast2_test/01: CompileTimeError # Issue 32517
const_cast2_test/none: CompileTimeError # Issue 32517
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_promotion_test/none: CompileTimeError
deferred_inheritance_constraints_test/extends: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
deferred_inheritance_constraints_test/implements: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
deferred_inheritance_constraints_test/mixin: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
@@ -340,18 +333,6 @@
vm/regress_27201_test: CompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
[ $arch != simarm && $arch != simarm64 && $arch != simdbc64 && $compiler == dartk ]
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: DartkCrash
-control_flow_collections/for_test: DartkCrash
-control_flow_collections/for_variable_test: DartkCrash
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: DartkCrash
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: DartkCrash
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_error_test/09: DartkCrash
-control_flow_collections/syntax_error_test/10: DartkCrash
-control_flow_collections/syntax_test: CompileTimeError
spread_collections/await_test: CompileTimeError
spread_collections/const_test: CompileTimeError
spread_collections/inference_test: CompileTimeError
@@ -360,16 +341,6 @@
spread_collections/syntax_test: CompileTimeError
[ $arch == simdbc64 && $compiler == dartk ]
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: CompileTimeError
-control_flow_collections/for_test: CompileTimeError
-control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: CompileTimeError
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: CompileTimeError
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_test: CompileTimeError
spread_collections/await_test: CompileTimeError
spread_collections/const_test: CompileTimeError
spread_collections/inference_test: CompileTimeError
@@ -470,18 +441,6 @@
assertion_initializer_const_error2_test/cc10: MissingCompileTimeError # Not reporting failed assert() at compile time.
[ $compiler == dartk && ($arch == simarm || $arch == simarm64) ]
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: CompileTimeError
-control_flow_collections/for_test: CompileTimeError
-control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: CompileTimeError
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: CompileTimeError
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_error_test/09: Pass
-control_flow_collections/syntax_error_test/10: Pass
-control_flow_collections/syntax_test: CompileTimeError
spread_collections/await_test: CompileTimeError
spread_collections/const_test: CompileTimeError
spread_collections/inference_test: CompileTimeError
@@ -495,16 +454,7 @@
compile_time_constant_o_test/01: Pass
compile_time_constant_o_test/02: Pass
const_dynamic_type_literal_test/02: Pass
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: CompileTimeError
-control_flow_collections/for_test: CompileTimeError
-control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: CompileTimeError
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: CompileTimeError
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_test: CompileTimeError
+control_flow_collections/*: Skip
map_literal3_test/01: Pass
map_literal3_test/02: Pass
spread_collections/await_test: CompileTimeError
diff --git a/tests/language_2/regress_25389_test.dart b/tests/language_2/regress_25389_test.dart
index f15bb0c..ad76eda 100644
--- a/tests/language_2/regress_25389_test.dart
+++ b/tests/language_2/regress_25389_test.dart
@@ -1,7 +1,6 @@
// 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
library regress_25389;
diff --git a/tests/language_2/regress_25609_test.dart b/tests/language_2/regress_25609_test.dart
index 67b783c..2cd030a 100644
--- a/tests/language_2/regress_25609_test.dart
+++ b/tests/language_2/regress_25609_test.dart
@@ -2,8 +2,6 @@
// 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
-
import 'regress_25609_lib1.dart';
Foo baz() => null;
diff --git a/tests/language_2/set_literals/const_set_literal_test.dart b/tests/language_2/set_literals/const_set_literal_test.dart
index 0e59037..7b3cce2 100644
--- a/tests/language_2/set_literals/const_set_literal_test.dart
+++ b/tests/language_2/set_literals/const_set_literal_test.dart
@@ -2,8 +2,6 @@
// 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.
-// SharedOptions=--enable-experiment=set-literals
-
import 'dart:async';
import "package:expect/expect.dart";
diff --git a/tests/language_2/set_literals/invalid_set_literal_test.dart b/tests/language_2/set_literals/invalid_set_literal_test.dart
index 2b6a790..912e65e 100644
--- a/tests/language_2/set_literals/invalid_set_literal_test.dart
+++ b/tests/language_2/set_literals/invalid_set_literal_test.dart
@@ -2,8 +2,6 @@
// 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.
-// SharedOptions=--enable-experiment=set-literals
-
import "dart:collection" show HashSet, LinkedHashSet;
import "package:expect/expect.dart";
diff --git a/tests/language_2/set_literals/set_literal_test.dart b/tests/language_2/set_literals/set_literal_test.dart
index cc17fae..3cb57c0 100644
--- a/tests/language_2/set_literals/set_literal_test.dart
+++ b/tests/language_2/set_literals/set_literal_test.dart
@@ -2,8 +2,6 @@
// 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.
-// SharedOptions=--enable-experiment=set-literals
-
import 'dart:async';
import "dart:collection" show LinkedHashSet;
diff --git a/tests/language_2/spread_collections/const_test.dart b/tests/language_2/spread_collections/const_test.dart
index 994e904..b36dff9 100644
--- a/tests/language_2/spread_collections/const_test.dart
+++ b/tests/language_2/spread_collections/const_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.
-// SharedOptions=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
import 'package:expect/expect.dart';
diff --git a/tests/language_2/spread_collections/experimental_flag_test.dart b/tests/language_2/spread_collections/experimental_flag_test.dart
index a1c8bf7..84135f1 100644
--- a/tests/language_2/spread_collections/experimental_flag_test.dart
+++ b/tests/language_2/spread_collections/experimental_flag_test.dart
@@ -4,9 +4,6 @@
// Check that spread collections are not enabled without the experimental flag.
-// Do enable sets, just not spread inside them.
-// SharedOptions=--enable-experiment=set-literals
-
// TODO(rnystrom): Remove this test when the feature is enabled without a flag.
void main() {
diff --git a/tests/language_2/spread_collections/inference_test.dart b/tests/language_2/spread_collections/inference_test.dart
index 0b3d4e5..42e5686 100644
--- a/tests/language_2/spread_collections/inference_test.dart
+++ b/tests/language_2/spread_collections/inference_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.
-// SharedOptions=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
// Test how spread interacts with inference.
import 'package:expect/expect.dart';
@@ -113,5 +113,5 @@
Expect.setEquals(<int>{}, <int>{...expectIntSet()});
// Bottom up-inference from elements is not pushed back down into spread.
- Expect.setEquals(<int>{}, {1, ...expectDynamicSet()});
+ Expect.setEquals(<int>{1}, {1, ...expectDynamicSet()});
}
diff --git a/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart b/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
index ab9b822..5f6576d 100644
--- a/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
+++ b/tests/language_2/spread_collections/map_set_ambiguity_error_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.
-// SharedOptions=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
// Test cases where the syntax is ambiguous between maps and sets.
import 'dart:collection';
diff --git a/tests/language_2/spread_collections/map_set_ambiguity_test.dart b/tests/language_2/spread_collections/map_set_ambiguity_test.dart
index 48ce5a7..9b3d537 100644
--- a/tests/language_2/spread_collections/map_set_ambiguity_test.dart
+++ b/tests/language_2/spread_collections/map_set_ambiguity_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.
-// SharedOptions=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
// Test cases where the syntax is ambiguous between maps and sets.
import 'dart:collection';
@@ -19,7 +19,8 @@
void testBottomUpInference() {
Map<int, int> map = {};
Set<int> set = Set();
- dynamic dyn = map;
+ dynamic dynMap = map;
+ dynamic dynSet = set;
Iterable<int> iterable = [];
CustomSet customSet = CustomSet();
CustomMap customMap = CustomMap();
@@ -31,25 +32,25 @@
// Expect.type<...>({...dyn});
Expect.type<Set<int>>({...iterable});
Expect.type<Set<int>>({...customSet});
- Expect.type<Map<int, int>>({...customMap});
+ Expect.type<Map<int, String>>({...customMap});
Expect.type<Map<int, int>>({...map, ...map});
// Expect.type<...>({...map, ...set});
- Expect.type<Map<dynamic, dynamic>>({...map, ...dyn});
+ Expect.type<Map<dynamic, dynamic>>({...map, ...dynMap});
// Expect.type<...>({...map, ...iterable});
// Expect.type<...>({...map, ...customSet});
- Expect.type<Map<int, int>>({...map, ...customMap});
+ Expect.type<Map<int, Object>>({...map, ...customMap});
Expect.type<Set<int>>({...set, ...set});
- Expect.type<Set<dynamic>>({...set, ...dyn});
+ Expect.type<Set<dynamic>>({...set, ...dynSet});
Expect.type<Set<int>>({...set, ...iterable});
Expect.type<Set<int>>({...set, ...customSet});
// Expect.type<...>({...set, ...customMap});
// Expect.type<...>({...dyn, ...dyn});
- Expect.type<Set<dynamic>>({...dyn, ...iterable});
- Expect.type<Set<dynamic>>({...dyn, ...customSet});
- Expect.type<Map<dynamic, dynamic>>({...dyn, ...customMap});
+ Expect.type<Set<dynamic>>({...dynSet, ...iterable});
+ Expect.type<Set<dynamic>>({...dynSet, ...customSet});
+ Expect.type<Map<dynamic, dynamic>>({...dynMap, ...customMap});
Expect.type<Set<int>>({...iterable, ...iterable});
Expect.type<Set<int>>({...iterable, ...customSet});
@@ -58,7 +59,7 @@
Expect.type<Set<int>>({...customSet, ...customSet});
// Expect.type<...>({...customSet, ...customMap});
- Expect.type<Map<int, int>>({...customMap, ...customMap});
+ Expect.type<Map<int, String>>({...customMap, ...customMap});
}
void testTopDownInference() {
diff --git a/tests/language_2/spread_collections/spread_test.dart b/tests/language_2/spread_collections/spread_test.dart
index 8b23a48..bd88880 100644
--- a/tests/language_2/spread_collections/spread_test.dart
+++ b/tests/language_2/spread_collections/spread_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.
-// SharedOptions=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
import 'package:expect/expect.dart';
@@ -200,24 +200,24 @@
void testCastFailures() {
dynamic nonIterable = 3;
- Expect.throwsCastError(() => <int>[...nonIterable]);
- Expect.throwsCastError(() => <int>{...nonIterable});
+ Expect.throwsTypeError(() => <int>[...nonIterable]);
+ Expect.throwsTypeError(() => <int>{...nonIterable});
dynamic nonMap = 3;
- Expect.throwsCastError(() => <int, int>{...nonMap});
+ Expect.throwsTypeError(() => <int, int>{...nonMap});
dynamic wrongIterableType = <String>["s"];
- Expect.throwsCastError(() => <int>[...wrongIterableType]);
- Expect.throwsCastError(() => <int>{...wrongIterableType});
+ Expect.throwsTypeError(() => <int>[...wrongIterableType]);
+ Expect.throwsTypeError(() => <int>{...wrongIterableType});
dynamic wrongKeyType = <String, int>{"s": 1};
dynamic wrongValueType = <int, String>{1: "s"};
- Expect.throwsCastError(() => <int, int>{...wrongKeyType});
- Expect.throwsCastError(() => <int, int>{...wrongValueType});
+ Expect.throwsTypeError(() => <int, int>{...wrongKeyType});
+ Expect.throwsTypeError(() => <int, int>{...wrongValueType});
// Mismatched collection types.
- Expect.throwsCastError(() => <int>[...map]);
- Expect.throwsCastError(() => <int, int>{...list});
- Expect.throwsCastError(() => <int, int>{...set});
- Expect.throwsCastError(() => <int>{...map});
+ Expect.throwsTypeError(() => <int>[...map]);
+ Expect.throwsTypeError(() => <int, int>{...list});
+ Expect.throwsTypeError(() => <int, int>{...set});
+ Expect.throwsTypeError(() => <int>{...map});
}
diff --git a/tests/language_2/spread_collections/syntax_error_test.dart b/tests/language_2/spread_collections/syntax_error_test.dart
index 9f38d74..1ccea11 100644
--- a/tests/language_2/spread_collections/syntax_error_test.dart
+++ b/tests/language_2/spread_collections/syntax_error_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.
-// SharedOptions=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
void main() {
// Spread nothing.
diff --git a/tests/language_2/spread_collections/syntax_test.dart b/tests/language_2/spread_collections/syntax_test.dart
index c46b589..7100394 100644
--- a/tests/language_2/spread_collections/syntax_test.dart
+++ b/tests/language_2/spread_collections/syntax_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.
-// SharedOptions=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
// Tests syntax edge cases.
import 'package:expect/expect.dart';
diff --git a/tests/language_2/spread_collections/type_error_test.dart b/tests/language_2/spread_collections/type_error_test.dart
index 06f1cab..68cf98c 100644
--- a/tests/language_2/spread_collections/type_error_test.dart
+++ b/tests/language_2/spread_collections/type_error_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.
-// SharedOptions=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
void main() {
// Spread non-iterable or non-map.
diff --git a/tests/lib_2/math/random_secure_unsupported_test.dart b/tests/lib_2/math/random_secure_unsupported_test.dart
new file mode 100644
index 0000000..7e8744c
--- /dev/null
+++ b/tests/lib_2/math/random_secure_unsupported_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that `Random.secure()` throws `UnsupportedError` each time it fails.
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+main() {
+ var result1 = getRandom();
+ var result2 = getRandom();
+
+ Expect.isNotNull(result1);
+ Expect.isNotNull(result2); // This fired for http://dartbug.com/36206
+
+ Expect.equals(result1 is Random, result2 is Random);
+ Expect.equals(result1 is UnsupportedError, result2 is UnsupportedError);
+}
+
+dynamic getRandom() {
+ try {
+ return Random.secure();
+ } catch (e) {
+ return e;
+ }
+}
diff --git a/tests/standalone/io/process_environment_lib.dart b/tests/standalone/io/process_environment_lib.dart
new file mode 100644
index 0000000..7446236
--- /dev/null
+++ b/tests/standalone/io/process_environment_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, 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:io';
+
+void main() {
+ print(Platform.environment);
+}
diff --git a/tests/standalone/io/process_environment_test.dart b/tests/standalone/io/process_environment_test.dart
new file mode 100644
index 0000000..1a6767d
--- /dev/null
+++ b/tests/standalone/io/process_environment_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, 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:convert';
+import 'dart:io';
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as path;
+
+const String childFile = 'process_environment_lib.dart';
+const String fakeKey = 'Artificial';
+const String fakeValue = 'fakepath';
+
+void main() async {
+ Map<String, String> environ = Platform.environment;
+ String baseDirectory = path.dirname(Platform.script.path);
+ //DETACHED PROCESS WITHOUT includeParentEnvironment
+ var WithoutEnviron = await Process.start(
+ Platform.executable, [path.join(baseDirectory, childFile)],
+ mode: ProcessStartMode.detachedWithStdio,
+ includeParentEnvironment: false,
+ environment: <String, String>{fakeKey: fakeValue});
+
+ Map<String, String> notInclude = new Map();
+ await for (final line in WithoutEnviron.stdout
+ .transform(systemEncoding.decoder)
+ .transform(LineSplitter())) {
+ notInclude = RestoreToMap(line);
+ }
+
+ //Ensure the child process has the passed environment
+ Expect.isTrue(notInclude.length >= 1);
+ Expect.isTrue(notInclude.keys.contains(fakeKey));
+
+ //DETACHED PROCESS WITH includeParentEnvironment
+ var WithEnviron = await Process.start(
+ Platform.executable, [path.join(baseDirectory, childFile)],
+ mode: ProcessStartMode.detachedWithStdio,
+ includeParentEnvironment: true,
+ environment: <String, String>{fakeKey: fakeValue});
+
+ Map<String, String> include = new Map();
+ await for (final line in WithEnviron.stdout
+ .transform(systemEncoding.decoder)
+ .transform(LineSplitter())) {
+ include = RestoreToMap(line);
+ }
+
+ //Parent environment and one fake path
+ Expect.isTrue(include.length == environ.length + 1);
+ Expect.isTrue(include[fakeKey] == fakeValue);
+}
+
+Map<String, String> RestoreToMap(String s) {
+ s = s.substring(1, s.length - 1);
+ Map<String, String> result = new Map();
+ for (String line in s.split(", ")) {
+ var i = line.indexOf(": ");
+ result.putIfAbsent(line.substring(0, i), () => line.substring(i + 2));
+ }
+ return result;
+}
diff --git a/tests/standalone_2/ffi/dylib_utils.dart b/tests/standalone_2/ffi/dylib_utils.dart
index 1929961..1c924d4 100644
--- a/tests/standalone_2/ffi/dylib_utils.dart
+++ b/tests/standalone_2/ffi/dylib_utils.dart
@@ -9,6 +9,7 @@
if (path == null) path = "";
if (Platform.isLinux) return path + "lib" + name + ".so";
if (Platform.isMacOS) return path + "lib" + name + ".dylib";
+ if (Platform.isWindows) return path + name + ".dll";
throw Exception("Platform not implemented");
}
diff --git a/tests/standalone_2/ffi/function_stress_test.dart b/tests/standalone_2/ffi/function_stress_test.dart
index 2f5f02c..fd3f0ec 100644
--- a/tests/standalone_2/ffi/function_stress_test.dart
+++ b/tests/standalone_2/ffi/function_stress_test.dart
@@ -2,10 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
-// Dart test program for stress-testing boxing and GC.
// VMOptions=--deterministic --optimization-counter-threshold=500 --verbose-gc
// VMOptions=--deterministic --optimization-counter-threshold=-1 --verbose-gc
//
+// Dart test program for stress-testing boxing and GC in return paths from FFI
+// trampolines.
+//
// NOTE: This test does not produce useful stderr when it fails because the
// stderr is redirected to a file for reflection.
@@ -32,14 +34,15 @@
}
main() async {
- final watcher = GCWatcher();
+ final watcher = GCWatcher.ifAvailable();
try {
await test(watcher, testBoxInt64);
// On 64-bit platforms this won't trigger GC because the result fits into a
// Smi.
await test(watcher, testBoxInt32, mustTriggerGC: false);
await test(watcher, testBoxDouble);
- await test(watcher, testBoxPointer);
+ await test(watcher, testBoxSmallPointer);
+ await test(watcher, testBoxLargePointer);
} finally {
watcher.dispose();
}
@@ -56,9 +59,12 @@
typedef NullaryOpDbl = double Function();
typedef NullaryOpPtr = ffi.Pointer<ffi.Void> Function();
+//// These functions return values that require boxing into different types.
+
final minInt64 =
ffiTestFunctions.lookupFunction<NativeNullaryOp64, NullaryOp>("MinInt64");
+// Forces boxing into Mint on all platforms.
void testBoxInt64() {
Expect.equals(0x8000000000000000, minInt64());
}
@@ -66,13 +72,15 @@
NullaryOp minInt32 =
ffiTestFunctions.lookupFunction<NativeNullaryOp32, NullaryOp>("MinInt32");
+// Forces boxing into Mint on 32-bit platforms only.
void testBoxInt32() {
- Expect.equals(0x80000000, minInt32());
+ Expect.equals(-0x80000000, minInt32());
}
final smallDouble = ffiTestFunctions
.lookupFunction<NativeNullaryOpDouble, NullaryOpDbl>("SmallDouble");
+// Forces boxing into Double.
void testBoxDouble() {
Expect.equals(0x80000000 * -1.0, smallDouble());
}
@@ -80,6 +88,16 @@
final smallPointer = ffiTestFunctions
.lookupFunction<NativeNullaryOpPtr, NullaryOpPtr>("SmallPointer");
-void testBoxPointer() {
+// Forces boxing into ffi.Pointer. On 32-bit platforms, also forces boxing into
+// Mint inside of ffi.Pointer.
+void testBoxSmallPointer() {
Expect.equals(-0x80000000, smallPointer().address);
}
+
+final largePointer = ffiTestFunctions
+ .lookupFunction<NativeNullaryOpPtr, NullaryOpPtr>("LargePointer");
+
+// Forces boxing into ffi.Pointer and ffi.Mint on all platforms.
+void testBoxLargePointer() {
+ Expect.equals(-0x8000000000000000, largePointer().address);
+}
diff --git a/tests/standalone_2/ffi/function_test.dart b/tests/standalone_2/ffi/function_test.dart
index c2019f7..d22f771 100644
--- a/tests/standalone_2/ffi/function_test.dart
+++ b/tests/standalone_2/ffi/function_test.dart
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
//
// Dart test program for testing dart:ffi function pointers.
+//
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=10
library FfiTest;
@@ -13,23 +16,26 @@
import "package:expect/expect.dart";
void main() {
- testNativeFunctionFromCast();
- testNativeFunctionFromLookup();
- test64bitInterpretations();
- testTruncation();
- testNativeFunctionDoubles();
- testNativeFunctionFloats();
- testNativeFunctionManyArguments1();
- testNativeFunctionManyArguments2();
- testNativeFunctionManyArguments3();
- testNativeFunctionPointer();
- testNullInt();
- testNullDouble();
- testNullManyArgs();
- testNullPointers();
- testFloatRounding();
- testVoidReturn();
- testNoArgs();
+ for (int i = 0; i < 100; ++i) {
+ testNativeFunctionFromCast();
+ testNativeFunctionFromLookup();
+ test64bitInterpretations();
+ testExtension();
+ testTruncation();
+ testNativeFunctionDoubles();
+ testNativeFunctionFloats();
+ testNativeFunctionManyArguments1();
+ testNativeFunctionManyArguments2();
+ testNativeFunctionManyArguments3();
+ testNativeFunctionPointer();
+ testNullInt();
+ testNullDouble();
+ testNullManyArgs();
+ testNullPointers();
+ testFloatRounding();
+ testVoidReturn();
+ testNoArgs();
+ }
}
ffi.DynamicLibrary ffiTestFunctions =
@@ -43,8 +49,8 @@
void testNativeFunctionFromCast() {
ffi.Pointer<ffi.IntPtr> p1 = ffi.allocate();
ffi.Pointer<ffi.NativeFunction<NativeBinaryOp>> p2 = p1.cast();
- BinaryOp f = p2.asFunction<BinaryOp>();
- BinaryOp f2 = p2.asFunction<GenericBinaryOp<int>>();
+ p2.asFunction<BinaryOp>();
+ p2.asFunction<GenericBinaryOp<int>>();
p1.free();
}
@@ -54,13 +60,15 @@
typedef NativeQuadOpUnsigned = ffi.Uint64 Function(
ffi.Uint64, ffi.Uint32, ffi.Uint16, ffi.Uint8);
+BinaryOp sumPlus42 =
+ ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
+
+QuadOp intComputation = ffiTestFunctions
+ .lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
+
void testNativeFunctionFromLookup() {
- BinaryOp sumPlus42 =
- ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
Expect.equals(49, sumPlus42(3, 4));
- QuadOp intComputation = ffiTestFunctions
- .lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
Expect.equals(625, intComputation(125, 250, 500, 1000));
Expect.equals(
@@ -69,10 +77,29 @@
-0x8000000000000000, intComputation(0, 0, 0, -0x8000000000000000));
}
-void test64bitInterpretations() {
- QuadOp uintComputation = ffiTestFunctions
- .lookupFunction<NativeQuadOpUnsigned, QuadOp>("UintComputation");
+typedef NativeNullaryOpSigned = ffi.Int32 Function();
+typedef NativeNullaryOpUnsigned = ffi.Uint32 Function();
+int Function() unsignedOp = ffiTestFunctions
+ .lookup("TestExtension")
+ .cast<ffi.Pointer<ffi.NativeFunction<NativeNullaryOpUnsigned>>>()
+ .asFunction();
+
+int Function() signedOp = ffiTestFunctions
+ .lookup("TestExtension")
+ .cast<ffi.Pointer<ffi.NativeFunction<NativeNullaryOpSigned>>>()
+ .asFunction();
+
+// Test 32-bit (int32_t) -> 64-bit (Dart int) sign extension and truncation.
+void testExtension() {
+ Expect.equals(unsignedOp(), 0x80000000);
+ Expect.equals(signedOp(), 0xffffffff80000000);
+}
+
+QuadOp uintComputation = ffiTestFunctions
+ .lookupFunction<NativeQuadOpUnsigned, QuadOp>("UintComputation");
+
+void test64bitInterpretations() {
// 2 ^ 63 - 1
Expect.equals(
0x7FFFFFFFFFFFFFFF, uintComputation(0, 0, 0, 0x7FFFFFFFFFFFFFFF));
@@ -87,10 +114,10 @@
ffi.Int8, ffi.Int16, ffi.Int32, ffi.Uint8, ffi.Uint16, ffi.Uint32);
typedef SenaryOp = int Function(int, int, int, int, int, int);
-void testTruncation() {
- SenaryOp sumSmallNumbers = ffiTestFunctions
- .lookupFunction<NativeSenaryOp, SenaryOp>("SumSmallNumbers");
+SenaryOp sumSmallNumbers = ffiTestFunctions
+ .lookupFunction<NativeSenaryOp, SenaryOp>("SumSmallNumbers");
+void testTruncation() {
// TODO(dacoharkes): implement truncation and sign extension in trampolines
// for values smaller than 32 bits.
sumSmallNumbers(128, 0, 0, 0, 0, 0);
@@ -113,17 +140,19 @@
typedef NativeDoubleUnaryOp = ffi.Double Function(ffi.Double);
typedef DoubleUnaryOp = double Function(double);
+DoubleUnaryOp times1_337Double = ffiTestFunctions
+ .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
+
void testNativeFunctionDoubles() {
- DoubleUnaryOp times1_337Double = ffiTestFunctions
- .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
Expect.approxEquals(2.0 * 1.337, times1_337Double(2.0));
}
typedef NativeFloatUnaryOp = ffi.Float Function(ffi.Float);
+DoubleUnaryOp times1_337Float = ffiTestFunctions
+ .lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
+
void testNativeFunctionFloats() {
- DoubleUnaryOp times1_337Float = ffiTestFunctions
- .lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
Expect.approxEquals(1337.0, times1_337Float(1000.0));
}
@@ -141,9 +170,10 @@
typedef OctenaryOp = int Function(
int, int, int, int, int, int, int, int, int, int);
+OctenaryOp sumManyInts = ffiTestFunctions
+ .lookupFunction<NativeOctenaryOp, OctenaryOp>("SumManyInts");
+
void testNativeFunctionManyArguments1() {
- OctenaryOp sumManyInts = ffiTestFunctions
- .lookupFunction<NativeOctenaryOp, OctenaryOp>("SumManyInts");
Expect.equals(55, sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
}
@@ -161,10 +191,10 @@
typedef DoubleOctenaryOp = double Function(double, double, double, double,
double, double, double, double, double, double);
+DoubleOctenaryOp sumManyDoubles = ffiTestFunctions
+ .lookupFunction<NativeDoubleOctenaryOp, DoubleOctenaryOp>("SumManyDoubles");
+
void testNativeFunctionManyArguments2() {
- DoubleOctenaryOp sumManyDoubles =
- ffiTestFunctions.lookupFunction<NativeDoubleOctenaryOp, DoubleOctenaryOp>(
- "SumManyDoubles");
Expect.approxEquals(
55.0, sumManyDoubles(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0));
}
@@ -212,9 +242,10 @@
int,
double);
+VigesimalOp sumManyNumbers = ffiTestFunctions
+ .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
+
void testNativeFunctionManyArguments3() {
- VigesimalOp sumManyNumbers = ffiTestFunctions
- .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
Expect.approxEquals(
210.0,
sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13,
@@ -224,9 +255,10 @@
typedef Int64PointerUnOp = ffi.Pointer<ffi.Int64> Function(
ffi.Pointer<ffi.Int64>);
+Int64PointerUnOp assign1337Index1 = ffiTestFunctions
+ .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
+
void testNativeFunctionPointer() {
- Int64PointerUnOp assign1337Index1 = ffiTestFunctions
- .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
ffi.Pointer<ffi.Int64> p2 = ffi.allocate(count: 2);
p2.store(42);
p2.elementAt(1).store(1000);
@@ -245,23 +277,18 @@
}
void testNullDouble() {
- DoubleUnaryOp times1_337Double = ffiTestFunctions
- .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
Expect.throws(() => times1_337Double(null));
}
void testNullManyArgs() {
- VigesimalOp sumManyNumbers = ffiTestFunctions
- .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
Expect.throws(() => sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0,
11, 12.0, 13, 14.0, 15, 16.0, 17, 18.0, null, 20.0));
}
-void testNullPointers() {
- Int64PointerUnOp nullableInt64ElemAt1 =
- ffiTestFunctions.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>(
- "NullableInt64ElemAt1");
+Int64PointerUnOp nullableInt64ElemAt1 = ffiTestFunctions
+ .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("NullableInt64ElemAt1");
+void testNullPointers() {
ffi.Pointer<ffi.Int64> result = nullableInt64ElemAt1(null);
Expect.isNull(result);
@@ -274,10 +301,10 @@
typedef NativeFloatPointerToBool = ffi.Uint8 Function(ffi.Pointer<ffi.Float>);
typedef FloatPointerToBool = int Function(ffi.Pointer<ffi.Float>);
-void testFloatRounding() {
- FloatPointerToBool isRoughly1337 = ffiTestFunctions.lookupFunction<
- NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
+FloatPointerToBool isRoughly1337 = ffiTestFunctions.lookupFunction<
+ NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
+void testFloatRounding() {
ffi.Pointer<ffi.Float> p2 = ffi.allocate();
p2.store(1337.0);
@@ -290,10 +317,10 @@
typedef NativeFloatToVoid = ffi.Void Function(ffi.Float);
typedef DoubleToVoid = void Function(double);
-void testVoidReturn() {
- DoubleToVoid devNullFloat = ffiTestFunctions
- .lookupFunction<NativeFloatToVoid, DoubleToVoid>("DevNullFloat");
+DoubleToVoid devNullFloat = ffiTestFunctions
+ .lookupFunction<NativeFloatToVoid, DoubleToVoid>("DevNullFloat");
+void testVoidReturn() {
devNullFloat(1337.0);
dynamic loseSignature = devNullFloat;
@@ -304,10 +331,10 @@
typedef NativeVoidToFloat = ffi.Float Function();
typedef VoidToDouble = double Function();
-void testNoArgs() {
- VoidToDouble inventFloatValue = ffiTestFunctions
- .lookupFunction<NativeVoidToFloat, VoidToDouble>("InventFloatValue");
+VoidToDouble inventFloatValue = ffiTestFunctions
+ .lookupFunction<NativeVoidToFloat, VoidToDouble>("InventFloatValue");
+void testNoArgs() {
double result = inventFloatValue();
Expect.approxEquals(1337.0, result);
}
diff --git a/tests/standalone_2/ffi/gc_helper.dart b/tests/standalone_2/ffi/gc_helper.dart
index 084a0ce..5e9431d 100644
--- a/tests/standalone_2/ffi/gc_helper.dart
+++ b/tests/standalone_2/ffi/gc_helper.dart
@@ -3,25 +3,48 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
-import 'dart:convert';
import 'dylib_utils.dart';
import 'dart:ffi';
+import 'dart:io' show Platform;
DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+abstract class GCWatcher {
+ factory GCWatcher() => _GCWatcherImpl();
+ factory GCWatcher.dummy() => _MockGCWatcher();
+ factory GCWatcher.ifAvailable() =>
+ Platform.isWindows ? GCWatcher.dummy() : GCWatcher();
+
+ Future<int> size();
+ void dispose();
+}
+
// Requires --verbose-gc.
-class GCWatcher {
+class _GCWatcherImpl implements GCWatcher {
int _suffix;
Future<int> size() async {
return await File("/tmp/captured_stderr_$_suffix").length();
}
- GCWatcher() {
+ _GCWatcherImpl() {
print("Starting...");
_suffix = ffiTestFunctions
.lookupFunction<Int32 Function(), int Function()>("RedirectStderr")();
}
- dispose() => File("/tmp/captured_stderr_$_suffix").deleteSync();
+ dispose() {
+ try {
+ File("/tmp/captured_stderr_$_suffix").deleteSync();
+ } catch (e) {
+ print("deleting file failed");
+ }
+ }
+}
+
+class _MockGCWatcher implements GCWatcher {
+ int _ctr = 0;
+
+ Future<int> size() async => ++_ctr;
+ dispose() {}
}
diff --git a/tests/standalone_2/ffi/negative_function_test.dart b/tests/standalone_2/ffi/negative_function_test.dart
index f716ca5..a529d67 100644
--- a/tests/standalone_2/ffi/negative_function_test.dart
+++ b/tests/standalone_2/ffi/negative_function_test.dart
@@ -19,8 +19,8 @@
typedef NativeBinaryOp = ffi.Int32 Function(ffi.Int32, ffi.Int32);
typedef BinaryOp = int Function(int, int);
-typedef NativeUnaryOp = ffi.Int64 Function(ffi.Int64);
-typedef UnaryOp = int Function(int);
+typedef NativeUnaryOp = ffi.Int64 Function(ffi.Pointer<ffi.Int64>);
+typedef UnaryOp = int Function(ffi.Pointer<ffi.Int64>);
void testWrongArity() {
{
@@ -44,18 +44,18 @@
{
dynamic sumPlus42 =
ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
- Expect.throwsNoSuchMethodError(() => sumPlus42("abc", "def"));
+ Expect.throwsTypeError(() => sumPlus42("abc", "def"));
}
{
Function sumPlus42 =
ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
- Expect.throwsNoSuchMethodError(() => sumPlus42("abc", "def"));
+ Expect.throwsTypeError(() => sumPlus42("abc", "def"));
}
{
dynamic pointerOp = ffiTestFunctions
.lookupFunction<NativeUnaryOp, UnaryOp>("Assign1337Index1");
- Expect.throwsNoSuchMethodError(() => pointerOp(0));
+ Expect.throwsTypeError(() => pointerOp(0));
}
}
diff --git a/tests/standalone_2/ffi/subtype_test.dart b/tests/standalone_2/ffi/subtype_test.dart
index dd466ae..22dbe13 100644
--- a/tests/standalone_2/ffi/subtype_test.dart
+++ b/tests/standalone_2/ffi/subtype_test.dart
@@ -39,7 +39,7 @@
CString cs = ffi.fromAddress<CString>(11);
bar = cs;
foo = "";
- final watcher = GCWatcher();
+ final watcher = GCWatcher.ifAvailable();
int counts = await watcher.size();
for (int i = 0; i < 1000000; ++i) {
foo = new X(i);
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index a68bdd7..2e1dc6a 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -8,6 +8,7 @@
io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
[ $builder_tag == asan ]
+ffi/data_not_asan_test: Skip # this test tries to allocate too much memory on purpose
io/file_test: Fail # Issue 34724
io/http_server_response_test: Fail # Issue 34724
io/process_sync_test: Pass, Fail # https://github.com/dart-lang/sdk/issues/34724
@@ -15,6 +16,11 @@
io/test_extension_fail_test: Fail # Issue 32187
[ $compiler == app_jitk ]
+ffi/dynamic_library_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/function_callbacks_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/function_structs_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/function_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/negative_function_test: Skip # https://github.com/dart-lang/sdk/issues/35934
io/file_error_test: RuntimeError
io/file_test: RuntimeError
io/http_auth_digest_test: RuntimeError
@@ -42,6 +48,9 @@
io/arguments_test: Fail # Test harness passes runtime arguments to the compiler
io/test_runner_test: SkipByDesign # Is not relevant for AOT.
+[ $runtime == dart_precompiled ]
+ffi: Skip # https://github.com/dart-lang/sdk/issues/35765
+
[ $system == android ]
entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
@@ -157,6 +166,9 @@
[ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
io/web_socket_ping_test: Crash, Pass
+[ $runtime != dart_precompiled && $runtime != vm ]
+ffi: SkipByDesign # ffi is only supported on vm
+
[ $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
io/http_client_request_test: Pass, Timeout
io/secure_builtin_roots_test: Pass, Timeout
@@ -229,12 +241,12 @@
io/web_socket_compression_test: Skip # Timeout
io/web_socket_test: Skip # Timeout
-[ $arch != x64 || $compiler != dartk || $mode == product || $system != linux && $system != macos]
+[ $arch != x64 || $compiler != dartk || $mode == product || $system != linux && $system != macos && $system != windows ]
ffi/function_stress_test: SkipByDesign # FFI must be supported. Also requires --verbose-gc, which isn't included in product.
ffi/subtype_test: SkipByDesign # FFI must be supported. Also requires --verbose-gc, which isn't included in product.
-[ $mode == product || $mode != product ]
-ffi/negative_function_test: Skip # Issues 36033, 36034
+[ $arch != x64 || $system != linux && $system != macos && $system != windows ]
+ffi: Skip # ffi not yet supported on other systems than linux/macos/windows x64
[ $compiler != dartk && $compiler != dartkb && $compiler != dartkp || $compiler == dartkp && $system == windows ]
entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe.
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index 49b61dc..bc23a30 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -6,9 +6,6 @@
link_natives_lazily_test: SkipByDesign # Not supported.
no_allow_absolute_addresses_test: SkipByDesign # Not supported.
-[ $builder_tag == asan ]
-ffi/data_not_asan_test: Skip # this test tries to allocate too much memory on purpose
-
[ $compiler == app_jit ]
full_coverage_test: Skip # Platform.executable
io/code_collection_test: Skip # Platform.executable
@@ -25,15 +22,6 @@
io/test_runner_test: RuntimeError # Issue 33168
regress_26031_test: Skip # Platform.resolvedExecutable
-[ $compiler == app_jitk ]
-ffi/dynamic_library_test: Skip # https://github.com/dart-lang/sdk/issues/35934
-ffi/function_callbacks_test: Skip # https://github.com/dart-lang/sdk/issues/35934
-ffi/function_structs_test: Skip # https://github.com/dart-lang/sdk/issues/35934
-ffi/function_test: Skip # https://github.com/dart-lang/sdk/issues/35934
-
-[ $runtime == dart_precompiled ]
-ffi: Skip # https://github.com/dart-lang/sdk/issues/35765
-
[ $runtime == vm ]
io/test_runner_test: Skip # Spawns a process which runs in Dart2 mode.
@@ -85,15 +73,9 @@
[ $arch == x64 && $compiler == dartkb && $runtime == vm && $system == linux ]
io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
-[ $arch == x64 && $mode == debug && $system == linux && $hot_reload ]
-ffi/subtype_test: Skip # https://github.com/dart-lang/sdk/issues/35933
-
[ $compiler != dart2analyzer && $system == windows ]
io/platform_resolved_executable_test/06: RuntimeError # Issue 23641
-[ $compiler == dartkb && $mode == debug ]
-ffi/subtype_test: Skip # https://github.com/dart-lang/sdk/issues/35935
-
[ $mode == release && $runtime == vm && $system == linux && ($arch == simdbc64 || $arch == x64) ]
io/http_bind_test: Pass, Timeout # Issue 35192
@@ -107,9 +89,6 @@
[ $runtime == dart_precompiled && $system == linux && ($arch == simarm || $arch == simarm64 || $arch == x64) ]
io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
-[ $runtime != dart_precompiled && $runtime != vm ]
-ffi: SkipByDesign # ffi is only supported on vm
-
[ $runtime == vm && !$checked && !$strong ]
io/file_constructor_test: RuntimeError
@@ -132,6 +111,3 @@
full_coverage_test: Skip # TODO(vegorov) SIMDBC interpreter doesn't support coverage yet.
link_natives_lazily_test: SkipByDesign # SIMDBC interpreter doesn't support lazy linking of natives.
no_lazy_dispatchers_test: SkipByDesign # SIMDBC interpreter doesn't support --no_lazy_dispatchers
-
-[ $arch != x64 || $system != linux && $system != macos ]
-ffi: Skip # ffi not yet supported on other systems than linux/macos 64
diff --git a/tools/VERSION b/tools/VERSION
index 6ba184f..2096130 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
MAJOR 2
MINOR 2
PATCH 1
-PRERELEASE 1
-PRERELEASE_PATCH 1
+PRERELEASE 2
+PRERELEASE_PATCH 0
ABI_VERSION 0
OLDEST_SUPPORTED_ABI_VERSION 0
diff --git a/tools/abiversions/.gitignore b/tools/abiversions/.gitignore
new file mode 100644
index 0000000..3e2c1ba
--- /dev/null
+++ b/tools/abiversions/.gitignore
@@ -0,0 +1,4 @@
+# This directory is populated by gclient sync. But we still need the directory
+# to be checked in, and git doesn't track empty directories, hence this file.
+*
+!.gitignore
diff --git a/tools/approve_results.dart b/tools/approve_results.dart
index 2279db2..9d11f48 100755
--- a/tools/approve_results.dart
+++ b/tools/approve_results.dart
@@ -8,6 +8,7 @@
/// green.
import 'dart:async';
+import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
@@ -73,25 +74,45 @@
? loadResultsMap(path)
: <String, Map<String, dynamic>>{};
+/// Exception for when the results for a builder can't be found.
+class NoResultsException implements Exception {
+ final String message;
+ final String buildUrl;
+
+ NoResultsException(this.message, this.buildUrl);
+
+ String toString() => message;
+}
+
/// Loads a log from logdog.
Future<String> loadLog(String id, String step) async {
+ final buildUrl = "https://ci.chromium.org/b/$id";
final logUrl = Uri.parse("https://logs.chromium.org/"
"logs/dart/buildbucket/cr-buildbucket.appspot.com/"
"$id/+/steps/$step?format=raw");
final client = new HttpClient();
- final request =
- await client.getUrl(logUrl).timeout(const Duration(seconds: 60));
- final response = await request.close().timeout(const Duration(seconds: 60));
- if (response.statusCode != HttpStatus.ok) {
- throw new Exception("The log at $logUrl doesn't exist");
+ try {
+ final request =
+ await client.getUrl(logUrl).timeout(const Duration(seconds: 60));
+ final response = await request.close().timeout(const Duration(seconds: 60));
+ if (response.statusCode == HttpStatus.notFound) {
+ await response.drain();
+ throw new NoResultsException(
+ "The log at $logUrl doesn't exist: ${response.statusCode}", buildUrl);
+ }
+ if (response.statusCode != HttpStatus.ok) {
+ await response.drain();
+ throw new Exception("Failed to download $logUrl: ${response.statusCode}");
+ }
+ final contents = (await response
+ .transform(new Utf8Decoder())
+ .timeout(const Duration(seconds: 60))
+ .toList())
+ .join("");
+ return contents;
+ } finally {
+ client.close();
}
- final contents = (await response
- .transform(new Utf8Decoder())
- .timeout(const Duration(seconds: 60))
- .toList())
- .join("");
- client.close();
- return contents;
}
/// TODO(https://github.com/dart-lang/sdk/issues/36015): The step name changed
@@ -305,6 +326,12 @@
return;
}
+ if (options.rest.isNotEmpty) {
+ stderr.writeln("Unexpected extra argument: ${options.rest.first}");
+ exitCode = 1;
+ return;
+ }
+
// Locate gsutil.py.
gsutilPy =
Platform.script.resolve("../third_party/gsutil/gsutil.py").toFilePath();
@@ -487,10 +514,19 @@
// Load all the latest results for the selected bots, as well as flakiness
// data, and the set of currently approved results. Each bot's latest build
// is downloaded in parallel to make this phase faster.
- final testListFutures = <Future>[];
+ final testListFutures = <Future<List<Test>>>[];
+ final noResultsBuilds = new SplayTreeMap<String, String>();
for (final String bot in bots) {
- testListFutures
- .add(loadResultsFromBot(bot, options, changelistBuilds[bot]));
+ testListFutures.add(new Future(() async {
+ try {
+ return await loadResultsFromBot(bot, options, changelistBuilds[bot]);
+ } on NoResultsException catch (e) {
+ print(
+ "Error: Failed to find results for $bot build <${e.buildUrl}>: $e");
+ noResultsBuilds[bot] = e.buildUrl;
+ return <Test>[];
+ }
+ }));
}
// Collect all the tests from the synchronous downloads.
@@ -625,6 +661,17 @@
statistic(brokenTests.length, tests.length,
"tests were broken since last approval");
+ // Warn about any builders where results weren't available.
+ if (noResultsBuilds.isNotEmpty) {
+ print("");
+ noResultsBuilds.forEach((String builder, String buildUrl) {
+ print("Warning: No results were found for $builder: <$buildUrl>");
+ });
+ print("Warning: Builders without results are usually due to infrastructure "
+ "issues, please have a closer look at the affected builders and try "
+ "the build again.");
+ }
+
// Stop if there's nothing to do.
if (unapprovedBots.isEmpty) {
print("\nEvery test result has already been approved.");
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 0dc5fc2..bcf66e7 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -195,7 +195,7 @@
"timeout": 240,
"use-sdk": true
}},
- "unittest-asserts-(release|debug)-(linux|mac|win)": {
+ "unittest-asserts-(debug|product|release)-(linux|mac|win)": {
"options": {
"compiler": "dartk",
"enable-asserts": true,
@@ -211,7 +211,7 @@
"runtime": "vm",
"timeout": 240
}},
- "unittest-analyzer_use_fasta-linux": {
+ "unittest-analyzer_use_fasta-(linux|mac|win)": {
"options": {
"compiler": "none",
"runtime": "vm",
@@ -220,7 +220,7 @@
"vm-options": ["-DuseFastaParser=true"],
"builder-tag": "analyzer_use_fasta"
}},
- "dartk-asan-linux-release-(ia32|x64)": {
+ "dartk-asan-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"builder-tag": "asan",
"timeout": 240
@@ -241,96 +241,103 @@
"options": {
"use-sdk": true
}},
- "dart2js-minified-csp-linux-chrome": {
+ "dart2js-minified-csp-(linux|mac|win)-chrome": {
"options": {
"minified": true,
"csp": true,
"use-sdk": true
}},
- "dart2js-minified-linux-d8": {
+ "dart2js-minified-(linux|mac|win)-d8": {
"options": {
"minified": true,
"use-sdk": true
}},
- "dart2js-hostasserts-linux-ia32-d8": {
+ "dart2js-production-(linux|mac|win)-d8": {
+ "options": {
+ "use-sdk": true,
+ "dart2js-options": ["-O3"]
+ }},
+ "dart2js-hostasserts-(linux|mac|win)-(ia32|x64)-d8": {
"options": {
"host-checked": true
}},
- "dartkp-android-release-arm": {
+ "dartkp-android-(debug|product|release)-arm": {
"options": {
"use-blobs": true
}},
- "dartkp-linux-release-(simarm|simarm64)": {
+ "dartkp-linux-(debug|product|release)-(simarm|simarm64)": {
"options": {
"use-blobs": true
}},
- "dartkp-(win|mac)-release-simarm64": {
+ "dartkp-(win|mac)-(debug|product|release)-(simarm|simarm64)": {
"options": {
"use-blobs": true
}},
- "dartkp-win-release-x64": {
+ "dartkp-win-(product|release)-x64": {
"options": {
"use-blobs": true
}},
- "dartkp-linux-(product|release)-x64": { },
- "dartkp-obfuscate-linux-release-x64": {
+ "dartkp-win-debug-x64": {
+ "options": {
+ "use-blobs": true,
+ "vm-options": ["--no-enable-malloc-hooks"]
+ }},
+ "dartkp-(linux|mac)-(product|release)-x64": { },
+ "dartkp-obfuscate-(linux|mac|win)-(debug|product|release)-x64": {
"options": {
"builder-tag": "obfuscated",
"vm-options": ["--obfuscate"]
}},
- "dartkp-linux-debug-x64": {
+ "dartkp-(linux|mac)-debug-x64": {
"options": {
"vm-options": ["--no-enable-malloc-hooks"]
}},
- "dartkp-no-bare-linux-(debug|release)-x64": {
+ "dartkp-no-bare-(linux|mac|win)-(debug|product|release)-x64": {
"options": {
"vm-options": ["--no-enable-malloc-hooks", "--no-use-bare-instructions"]
}},
- "dartkp-no-bare-linux-(debug|release)-(simarm|simarm64)": {
+ "dartkp-no-bare-(linux|mac|win)-(debug|product|release)-(simarm|simarm64)": {
"options": {
"vm-options": ["--no-enable-malloc-hooks", "--no-use-bare-instructions"],
"use-blobs": true
}},
- "dartk-(linux|mac)-(debug|release)-(ia32|x64)": { },
- "dartk-checked-linux-release-x64": {
+ "dartk-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { },
+ "dartk-checked-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"checked": true
}},
- "dartk-win-(debug|release)-(ia32|x64)": { },
- "dartk-(linux|mac|win)-product-x64": { },
- "dartk-(linux|mac)-(debug|release)-simdbc64": { },
- "dartk-linux-release-(arm64|simarm|simarm64)": { },
- "dartk-optcounter-linux-release-(ia32|x64)": {
+ "dartk-(linux|mac|win)-(debug|product|release)-(arm64|simarm|simarm64|simdbc64)": { },
+ "dartk-optcounter-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"builder-tag": "optimization_counter_threshold",
"vm-options": ["--optimization-counter-threshold=5"]
}},
- "dartk-reload-linux-(debug|release)-x64": {
+ "dartk-reload-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"hot-reload": true
}},
- "dartk-reload-mac-(debug|release)-simdbc64": {
+ "dartk-reload-mac-(debug|product|release)-simdbc64": {
"options": {
"hot-reload": true
}},
- "dartk-reload-rollback-linux-(debug|release)-x64": {
+ "dartk-reload-rollback-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"hot-reload-rollback": true
}},
- "app_jitk-linux-(debug|product|release)-x64": { },
- "dartkb-interpret-linux-(debug|release)-x64": {
+ "app_jitk-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { },
+ "dartkb-interpret-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"vm-options": ["--enable_interpreter", "--compilation-counter-threshold=-1"]
}},
- "dartkb-mixed-linux-(debug|release)-x64": {
+ "dartkb-mixed-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"vm-options": ["--enable_interpreter"]
}},
- "dartkb-compile-linux-(debug|release)-x64": {
+ "dartkb-compile-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"vm-options": ["--use_bytecode_compiler"]
}},
- "(dartdevc|dartdevk)-checked-(linux|mac|win)-release-chrome": {
+ "(dartdevc|dartdevk)-checked-(linux|mac|win)-(debug|product|release)-chrome": {
"options": {
"checked": true,
"use-sdk": true
@@ -614,7 +621,7 @@
"arguments": [
"-ndartk-asan-linux-release-${arch}"],
"environment": {
- "ASAN_OPTIONS": "handle_segv=0:detect_stack_use_after_return=0",
+ "ASAN_OPTIONS": "handle_segv=0:detect_stack_use_after_return=0:disable_coredump=0",
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
}
@@ -1181,6 +1188,25 @@
"dart2js_extra",
"dart2js_native"
]
+ },
+ {
+ "name": "dart2js production tests",
+ "arguments": [
+ "-ndart2js-production-linux-d8",
+ "--dart2js-batch",
+ "--exclude_suite=observatory_ui"
+ ],
+ "shards": 6,
+ "fileset": "dart2js"
+ },
+ {
+ "name": "dart2js production extra tests",
+ "arguments": [
+ "-ndart2js-production-linux-d8",
+ "--dart2js-batch",
+ "dart2js_extra",
+ "dart2js_native"
+ ]
}
]
},
@@ -1385,7 +1411,7 @@
{
"name": "analyze tests co19_2",
"arguments": [
- "-nanalyzer-${system}",
+ "-nanalyzer-asserts-${system}",
"co19_2"
]
}
diff --git a/tools/download_abi_dills.py b/tools/download_abi_dills.py
index e45b2ce..fb77a55 100644
--- a/tools/download_abi_dills.py
+++ b/tools/download_abi_dills.py
@@ -1,5 +1,6 @@
# Downloads dill files from CIPD for each supported ABI version.
+import os
import subprocess
import sys
import utils
@@ -8,12 +9,19 @@
def main():
abi_version = int(utils.GetAbiVersion())
oldest_abi_version = int(utils.GetOldestSupportedAbiVersion())
+ cmd = ['cipd', 'ensure', '-root', 'tools/abiversions', '-ensure-file', '-']
+ ensure_file = ''
for i in xrange(oldest_abi_version, abi_version):
- cmd = ['cipd', 'install', 'dart/abiversions/%d' % i, 'latest']
- result = subprocess.call(cmd)
- if result != 0:
- return 1
- return 0
+ ensure_file += '@Subdir %d\ndart/abiversions/%d latest\n\n' % (i, i)
+ if not ensure_file:
+ return 0
+ p = subprocess.Popen(cmd,
+ stdin = subprocess.PIPE,
+ shell = utils.IsWindows(),
+ cwd = utils.DART_DIR)
+ p.communicate(ensure_file)
+ p.stdin.close()
+ return p.wait()
if __name__ == '__main__':
diff --git a/tools/gardening/bin/results_list.dart b/tools/gardening/bin/results_list.dart
index 2e9322c..e0baa1b 100644
--- a/tools/gardening/bin/results_list.dart
+++ b/tools/gardening/bin/results_list.dart
@@ -17,9 +17,6 @@
argParser.addOption("compiler", allowed: Compiler.names);
argParser.addFlag("csp", negatable: false);
argParser.addFlag("fasta", negatable: false);
- argParser.addFlag("dart2js-with-kernel", negatable: false);
- argParser.addFlag("dart2js-old-frontend", negatable: false);
- argParser.addFlag("dart2js-with-kernel-in-ssa", negatable: false);
argParser.addFlag("enable-asserts", negatable: false);
argParser.addFlag("fast-startup", negatable: false);
argParser.addFlag("host-checked", negatable: false);
@@ -54,8 +51,6 @@
argResults["builder-tag"],
argResults["fast-startup"],
0,
- argResults["dart2js-with-kernel"],
- argResults["dart2js-old-frontend"],
argResults["enable-asserts"],
argResults["hot-reload"],
argResults["hot-reload-rollback"],
diff --git a/tools/gardening/lib/src/results/configuration_environment.dart b/tools/gardening/lib/src/results/configuration_environment.dart
index 53da74d..9f35774 100644
--- a/tools/gardening/lib/src/results/configuration_environment.dart
+++ b/tools/gardening/lib/src/results/configuration_environment.dart
@@ -27,8 +27,6 @@
"checked": new _Variable.bool((c) => c.checked),
"compiler": new _Variable((c) => c.compiler, Compiler.names),
"csp": new _Variable.bool((c) => c.csp),
- "dart2js_with_kernel": new _Variable.bool((c) => c.dart2JsWithKernel),
- "dart2js_old_frontend": new _Variable.bool((c) => c.dart2JsOldFrontend),
"fasta": new _Variable.bool((c) => c.fasta),
"fast_startup": new _Variable.bool((c) => c.fastStartup),
"enable_asserts": new _Variable.bool((c) => c.enableAsserts),
diff --git a/tools/gardening/lib/src/results/result_json_models.dart b/tools/gardening/lib/src/results/result_json_models.dart
index 954b1c52..7a55a89 100644
--- a/tools/gardening/lib/src/results/result_json_models.dart
+++ b/tools/gardening/lib/src/results/result_json_models.dart
@@ -23,8 +23,6 @@
final String builderTag;
final bool fastStartup;
final int timeout;
- final bool dart2JsWithKernel;
- final bool dart2JsOldFrontend;
final bool enableAsserts;
final bool hotReload;
final bool hotReloadRollback;
@@ -48,8 +46,6 @@
this.builderTag,
this.fastStartup,
this.timeout,
- this.dart2JsWithKernel,
- this.dart2JsOldFrontend,
this.enableAsserts,
this.hotReload,
this.hotReloadRollback,
@@ -75,8 +71,6 @@
json["builder_tag"],
json["fast_startup"],
json["timeout"],
- json["dart2js_with_kernel"] ?? false,
- json["dart2js_old_frontend"] ?? false,
json["enable_asserts"] ?? false,
json["hot_reload"] ?? false,
json["hot_reload_rollback"] ?? false,
@@ -103,8 +97,6 @@
_boolToArg("use-sdk", useSdk),
_stringToArg("builder-tag", builderTag),
_boolToArg("fast-startup", fastStartup),
- _boolToArg("dart2js-with-kernel", dart2JsWithKernel),
- _boolToArg("dart2js-old-frontend", dart2JsOldFrontend),
_boolToArg("enable-asserts", enableAsserts),
_boolToArg("hot-reload", hotReload),
_boolToArg("hot-reload-rollback", hotReloadRollback),
@@ -119,7 +111,7 @@
String toCsvString() {
return "$mode;$arch;$compiler;$runtime;$checked;$strong;$hostChecked;"
"$minified;$csp;$fasta;$system;$vmOptions;$useSdk;$builderTag;$fastStartup;"
- "$dart2JsWithKernel;$dart2JsOldFrontend;$enableAsserts;$hotReload;"
+ "$enableAsserts;$hotReload;"
"$hotReloadRollback;$noPreviewDart2;$selectors";
}
diff --git a/tools/patches/flutter-engine/7418238239f885ba92093c44a1768f8ec93b121f.patch b/tools/patches/flutter-engine/7418238239f885ba92093c44a1768f8ec93b121f.patch
new file mode 100644
index 0000000..69336e8
--- /dev/null
+++ b/tools/patches/flutter-engine/7418238239f885ba92093c44a1768f8ec93b121f.patch
@@ -0,0 +1,31 @@
+diff --git a/DEPS b/DEPS
+index 442e2d912..cb079bde9 100644
+--- a/DEPS
++++ b/DEPS
+@@ -37,7 +37,7 @@ vars = {
+ # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py
+ 'dart_args_tag': '1.4.4',
+ 'dart_async_tag': '2.0.8',
+- 'dart_bazel_worker_tag': '0.1.14',
++ 'dart_bazel_worker_tag': 'bazel_worker-v0.1.20',
+ 'dart_boolean_selector_tag': '1.0.4',
+ 'dart_boringssl_gen_rev': 'bbf52f18f425e29b1185f2f6753bec02ed8c5880',
+ 'dart_boringssl_rev': '702e2b6d3831486535e958f262a05c75a5cb312e',
+@@ -48,7 +48,7 @@ vars = {
+ 'dart_crypto_tag': '2.0.6',
+ 'dart_csslib_tag': '0.14.4+1',
+ 'dart_dart2js_info_tag': '0.6.0',
+- 'dart_dart_style_tag': '1.2.2',
++ 'dart_dart_style_tag': '1.2.4',
+ 'dart_dartdoc_tag': 'v0.28.2',
+ 'dart_fixnum_tag': '0.10.9',
+ 'dart_glob_tag': '1.1.7',
+@@ -74,7 +74,7 @@ vars = {
+ 'dart_path_tag': '1.6.2',
+ 'dart_plugin_tag': 'f5b4b0e32d1406d62daccea030ba6457d14b1c47',
+ 'dart_pool_tag': '1.3.6',
+- 'dart_protobuf_tag': '0.9.0',
++ 'dart_protobuf_tag': '0c77167b16d00b561a6055bfe26690af7f26ae88',
+ 'dart_pub_rev': '3c060aae47985e9a248b850f1d0450304a5c97e3',
+ 'dart_pub_semver_tag': '1.4.2',
+ 'dart_quiver_tag': '2.0.0+1',
diff --git a/tools/patches/flutter-engine/apply.sh b/tools/patches/flutter-engine/apply.sh
index d1105a5..9c2bd33 100755
--- a/tools/patches/flutter-engine/apply.sh
+++ b/tools/patches/flutter-engine/apply.sh
@@ -53,7 +53,7 @@
# DEPS file might have been patched with new version of packages that
# Dart SDK depends on. Get information about dependencies from the
# DEPS file and forcefully update checkouts of those dependencies.
- gclient revinfo | grep 'src/third_party/dart/' | while read -r line; do
+ gclient.py revinfo | grep 'src/third_party/dart/' | while read -r line; do
# revinfo would produce lines in the following format:
# path: git-url@tag-or-hash
# Where no spaces occur inside path, git-url or tag-or-hash.
@@ -82,5 +82,5 @@
fi
popd > /dev/null
done
- gclient runhooks
+ gclient.py runhooks
fi
diff --git a/tools/patches/flutter-engine/c92d5ca288da15b54b04c0a40ffe5d94a8883d77.patch b/tools/patches/flutter-engine/c92d5ca288da15b54b04c0a40ffe5d94a8883d77.patch
deleted file mode 100644
index dc6194c..0000000
--- a/tools/patches/flutter-engine/c92d5ca288da15b54b04c0a40ffe5d94a8883d77.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/DEPS b/DEPS
-index 2af26b012..cd98d79f0 100644
---- a/DEPS
-+++ b/DEPS
-@@ -47,7 +47,7 @@ vars = {
- 'dart_convert_tag': '2.0.2',
- 'dart_crypto_tag': '2.0.6',
- 'dart_csslib_tag': '0.14.4+1',
-- 'dart_dart2js_info_tag': '0.5.15',
-+ 'dart_dart2js_info_tag': '0.6.0',
- 'dart_dart_style_tag': '1.2.2',
- 'dart_dartdoc_tag': 'v0.28.1+2',
- 'dart_fixnum_tag': '0.10.9',
diff --git a/tools/patches/flutter-flutter/502c9c4002a6b456f829f79bfbd2ff61d075d1d7.patch b/tools/patches/flutter-flutter/502c9c4002a6b456f829f79bfbd2ff61d075d1d7.patch
deleted file mode 100644
index 50eb1f4ea..0000000
--- a/tools/patches/flutter-flutter/502c9c4002a6b456f829f79bfbd2ff61d075d1d7.patch
+++ /dev/null
@@ -1,166 +0,0 @@
-diff --git a/packages/flutter_tools/lib/src/base/build.dart b/packages/flutter_tools/lib/src/base/build.dart
-index 7be3b8c20..8e6012042 100644
---- a/packages/flutter_tools/lib/src/base/build.dart
-+++ b/packages/flutter_tools/lib/src/base/build.dart
-@@ -46,13 +46,11 @@ class GenSnapshot {
-
- Future<int> run({
- @required SnapshotType snapshotType,
-- @required String packagesPath,
- IOSArch iosArch,
- Iterable<String> additionalArgs = const <String>[],
- }) {
- final List<String> args = <String>[
- '--causal_async_stacks',
-- '--packages=$packagesPath',
- ]..addAll(additionalArgs);
-
- final String snapshotterPath = getSnapshotterPath(snapshotType);
-@@ -193,7 +191,6 @@ class AOTSnapshotter {
- final SnapshotType snapshotType = SnapshotType(platform, buildMode);
- final int genSnapshotExitCode = await genSnapshot.run(
- snapshotType: snapshotType,
-- packagesPath: packageMap.packagesPath,
- additionalArgs: genSnapshotArgs,
- iosArch: iosArch,
- );
-@@ -537,7 +534,6 @@ class JITSnapshotter {
- final SnapshotType snapshotType = SnapshotType(platform, buildMode);
- final int genSnapshotExitCode = await genSnapshot.run(
- snapshotType: snapshotType,
-- packagesPath: packagesPath,
- additionalArgs: genSnapshotArgs,
- );
- if (genSnapshotExitCode != 0) {
-diff --git a/packages/flutter_tools/test/base/build_test.dart b/packages/flutter_tools/test/base/build_test.dart
-index 81653aded..4d245a33d 100644
---- a/packages/flutter_tools/test/base/build_test.dart
-+++ b/packages/flutter_tools/test/base/build_test.dart
-@@ -190,7 +190,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.ios);
- expect(genSnapshot.snapshotType.mode, BuildMode.profile);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-aot-assembly',
-@@ -229,7 +228,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.ios);
- expect(genSnapshot.snapshotType.mode, BuildMode.profile);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-aot-assembly',
-@@ -268,7 +266,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
- expect(genSnapshot.snapshotType.mode, BuildMode.profile);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-aot-blobs',
-@@ -312,7 +309,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
- expect(genSnapshot.snapshotType.mode, BuildMode.profile);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-aot-blobs',
-@@ -352,7 +348,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.ios);
- expect(genSnapshot.snapshotType.mode, BuildMode.release);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-aot-assembly',
-@@ -391,7 +386,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.ios);
- expect(genSnapshot.snapshotType.mode, BuildMode.release);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-aot-assembly',
-@@ -448,7 +442,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
- expect(genSnapshot.snapshotType.mode, BuildMode.release);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-aot-blobs',
-@@ -492,7 +485,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
- expect(genSnapshot.snapshotType.mode, BuildMode.release);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-aot-blobs',
-@@ -581,7 +573,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
- expect(genSnapshot.snapshotType.mode, BuildMode.debug);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--enable_asserts',
-@@ -622,7 +613,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
- expect(genSnapshot.snapshotType.mode, BuildMode.debug);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--enable_asserts',
-@@ -674,7 +664,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
- expect(genSnapshot.snapshotType.mode, BuildMode.profile);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-jit',
-@@ -714,7 +703,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
- expect(genSnapshot.snapshotType.mode, BuildMode.profile);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-jit',
-@@ -765,7 +753,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
- expect(genSnapshot.snapshotType.mode, BuildMode.release);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-jit',
-@@ -805,7 +792,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
- expect(genSnapshot.snapshotType.mode, BuildMode.release);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-jit',
-@@ -860,7 +846,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
- expect(genSnapshot.snapshotType.mode, BuildMode.release);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-jit',
-@@ -917,7 +902,6 @@ void main() {
- expect(genSnapshot.callCount, 1);
- expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
- expect(genSnapshot.snapshotType.mode, BuildMode.release);
-- expect(genSnapshot.packagesPath, '.packages');
- expect(genSnapshot.additionalArgs, <String>[
- '--deterministic',
- '--snapshot_kind=app-jit',
diff --git a/tools/patches/flutter-flutter/cad97fe7467c60de645d47acffd0e00cd83178ab.patch b/tools/patches/flutter-flutter/cad97fe7467c60de645d47acffd0e00cd83178ab.patch
new file mode 100644
index 0000000..6cc2a6b
--- /dev/null
+++ b/tools/patches/flutter-flutter/cad97fe7467c60de645d47acffd0e00cd83178ab.patch
@@ -0,0 +1,190 @@
+diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
+index 12c0770ab..7787bd4ca 100644
+--- a/packages/flutter_tools/lib/src/compile.dart
++++ b/packages/flutter_tools/lib/src/compile.dart
+@@ -57,12 +57,15 @@ class TargetModel {
+ }
+
+ class CompilerOutput {
+- const CompilerOutput(this.outputFilename, this.errorCount);
++ const CompilerOutput(this.outputFilename, this.errorCount, this.sources);
+
+ final String outputFilename;
+ final int errorCount;
++ final List<Uri> sources;
+ }
+
++enum StdoutState { CollectDiagnostic, CollectDependencies }
++
+ /// Handles stdin/stdout communication with the frontend server.
+ class StdoutHandler {
+ StdoutHandler({this.consumer = printError}) {
+@@ -72,30 +75,54 @@ class StdoutHandler {
+ bool compilerMessageReceived = false;
+ final CompilerMessageConsumer consumer;
+ String boundaryKey;
++ StdoutState state = StdoutState.CollectDiagnostic;
+ Completer<CompilerOutput> compilerOutput;
++ final List<Uri> sources = <Uri>[];
+
+ bool _suppressCompilerMessages;
+
+ void handler(String message) {
++ printTrace('-> $message');
+ const String kResultPrefix = 'result ';
+ if (boundaryKey == null && message.startsWith(kResultPrefix)) {
+ boundaryKey = message.substring(kResultPrefix.length);
+ } else if (message.startsWith(boundaryKey)) {
+- if (message.length <= boundaryKey.length) {
+- compilerOutput.complete(null);
+- return;
++ if (state == StdoutState.CollectDiagnostic) {
++ state = StdoutState.CollectDependencies;
++ } else {
++ if (message.length <= boundaryKey.length) {
++ compilerOutput.complete(null);
++ return;
++ }
++ final int spaceDelimiter = message.lastIndexOf(' ');
++ compilerOutput.complete(
++ CompilerOutput(
++ message.substring(boundaryKey.length + 1, spaceDelimiter),
++ int.parse(message.substring(spaceDelimiter + 1).trim()),
++ sources));
+ }
+- final int spaceDelimiter = message.lastIndexOf(' ');
+- compilerOutput.complete(
+- CompilerOutput(
+- message.substring(boundaryKey.length + 1, spaceDelimiter),
+- int.parse(message.substring(spaceDelimiter + 1).trim())));
+- } else if (!_suppressCompilerMessages) {
+- if (compilerMessageReceived == false) {
+- consumer('\nCompiler message:');
+- compilerMessageReceived = true;
++ } else {
++ if (state == StdoutState.CollectDiagnostic) {
++ if (!_suppressCompilerMessages) {
++ if (compilerMessageReceived == false) {
++ consumer('\nCompiler message:');
++ compilerMessageReceived = true;
++ }
++ consumer(message);
++ }
++ } else {
++ assert(state == StdoutState.CollectDependencies);
++ switch (message[0]) {
++ case '+':
++ sources.add(Uri.parse(message.substring(1)));
++ break;
++ case '-':
++ sources.remove(Uri.parse(message.substring(1)));
++ break;
++ default:
++ printTrace('Unexpected prefix for $message uri - ignoring');
++ }
+ }
+- consumer(message);
+ }
+ }
+
+@@ -106,6 +133,7 @@ class StdoutHandler {
+ compilerMessageReceived = false;
+ compilerOutput = Completer<CompilerOutput>();
+ _suppressCompilerMessages = suppressCompilerMessages;
++ state = StdoutState.CollectDiagnostic;
+ }
+ }
+
+@@ -200,7 +228,7 @@ class KernelCompiler {
+
+ if (await fingerprinter.doesFingerprintMatch()) {
+ printTrace('Skipping kernel compilation. Fingerprint match.');
+- return CompilerOutput(outputFilePath, 0);
++ return CompilerOutput(outputFilePath, 0, /* sources */ null);
+ }
+ }
+
+@@ -453,10 +481,13 @@ class ResidentCompiler {
+ ? _mapFilename(request.mainPath, packageUriMapper) + ' '
+ : '';
+ _server.stdin.writeln('recompile $mainUri$inputKey');
++ printTrace('<- recompile $mainUri$inputKey');
+ for (String fileUri in request.invalidatedFiles) {
+ _server.stdin.writeln(_mapFileUri(fileUri, packageUriMapper));
++ printTrace('<- ${_mapFileUri(fileUri, packageUriMapper)}');
+ }
+ _server.stdin.writeln(inputKey);
++ printTrace('<- $inputKey');
+
+ return _stdoutHandler.compilerOutput.future;
+ }
+@@ -545,6 +576,7 @@ class ResidentCompiler {
+ .listen((String message) { printError(message); });
+
+ _server.stdin.writeln('compile $scriptUri');
++ printTrace('<- compile $scriptUri');
+
+ return _stdoutHandler.compilerOutput.future;
+ }
+@@ -597,6 +629,7 @@ class ResidentCompiler {
+ void accept() {
+ if (_compileRequestNeedsConfirmation) {
+ _server.stdin.writeln('accept');
++ printTrace('<- accept');
+ }
+ _compileRequestNeedsConfirmation = false;
+ }
+@@ -620,6 +653,7 @@ class ResidentCompiler {
+ }
+ _stdoutHandler.reset();
+ _server.stdin.writeln('reject');
++ printTrace('<- reject');
+ _compileRequestNeedsConfirmation = false;
+ return _stdoutHandler.compilerOutput.future;
+ }
+@@ -629,6 +663,7 @@ class ResidentCompiler {
+ /// kernel file.
+ void reset() {
+ _server?.stdin?.writeln('reset');
++ printTrace('<- reset');
+ }
+
+ String _mapFilename(String filename, PackageUriMapper packageUriMapper) {
+diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
+index 7940e8bb0..9e8b9bd45 100644
+--- a/packages/flutter_tools/lib/src/devfs.dart
++++ b/packages/flutter_tools/lib/src/devfs.dart
+@@ -557,6 +557,8 @@ class DevFS {
+ outputPath: dillOutputPath ?? getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
+ packagesFilePath : _packagesFilePath,
+ );
++ // list of sources that needs to be monitored are in [compilerOutput.sources]
++ //
+ // Don't send full kernel file that would overwrite what VM already
+ // started loading from.
+ if (!bundleFirstUpload) {
+diff --git a/packages/flutter_tools/test/src/mocks.dart b/packages/flutter_tools/test/src/mocks.dart
+index 52c5fc907..36d63f2d5 100644
+--- a/packages/flutter_tools/test/src/mocks.dart
++++ b/packages/flutter_tools/test/src/mocks.dart
+@@ -496,6 +496,6 @@ class MockResidentCompiler extends BasicMock implements ResidentCompiler {
+ Future<CompilerOutput> recompile(String mainPath, List<String> invalidatedFiles, { String outputPath, String packagesFilePath }) async {
+ fs.file(outputPath).createSync(recursive: true);
+ fs.file(outputPath).writeAsStringSync('compiled_kernel_output');
+- return CompilerOutput(outputPath, 0);
++ return CompilerOutput(outputPath, 0, <Uri>[]);
+ }
+ }
+diff --git a/packages/flutter_tools/test/tester/flutter_tester_test.dart b/packages/flutter_tools/test/tester/flutter_tester_test.dart
+index a78f70f4f..b6524bd5d 100644
+--- a/packages/flutter_tools/test/tester/flutter_tester_test.dart
++++ b/packages/flutter_tools/test/tester/flutter_tester_test.dart
+@@ -177,7 +177,7 @@ Hello!
+ packagesPath: anyNamed('packagesPath'),
+ )).thenAnswer((_) async {
+ fs.file('$mainPath.dill').createSync(recursive: true);
+- return CompilerOutput('$mainPath.dill', 0);
++ return CompilerOutput('$mainPath.dill', 0, <Uri>[]);
+ });
+
+ final LaunchResult result = await device.startApp(null,
diff --git a/tools/test.dart b/tools/test.dart
index 9842a06..ae5213c 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -205,11 +205,6 @@
"named configuration $requestedNamedConfiguration");
return false;
}
- if (requestedNamedConfiguration != null && outputNamedConfiguration.isEmpty) {
- stderr.writeln("error: The named configuration "
- "$requestedNamedConfiguration doesn't exist");
- return false;
- }
if (requestedNamedConfiguration != null && outputBuilders.isEmpty) {
stderr.writeln("error: The named configuration "
"$requestedNamedConfiguration isn't tested on any builders");
@@ -236,9 +231,26 @@
return LineSplitter.split(result.stdout).first;
}
+/// Exception thrown when looking up the build for a commit failed.
+class CommitNotBuiltException implements Exception {
+ final String reason;
+
+ CommitNotBuiltException(this.reason);
+
+ String toString() => reason;
+}
+
+/// The result after searching for a build of a commit.
+class BuildSearchResult {
+ final int build;
+ final String commit;
+
+ BuildSearchResult(this.build, this.commit);
+}
+
/// Locates the build number of the [commit] on the [builder], or throws an
/// exception if the builder hasn't built the commit.
-Future<int> buildNumberOfCommit(String builder, String commit) async {
+Future<BuildSearchResult> searchForBuild(String builder, String commit) async {
final requestUrl = Uri.parse(
"https://cr-buildbucket.appspot.com/_ah/api/buildbucket/v1/search"
"?bucket=luci.dart.ci.sandbox"
@@ -255,7 +267,8 @@
client.close();
final builds = object["builds"];
if (builds == null || builds.isEmpty) {
- throw new Exception("Builder $builder hasn't built commit $commit");
+ throw new CommitNotBuiltException(
+ "Builder $builder hasn't built commit $commit");
}
final build = builds.last;
final tags = (build["tags"] as List).cast<String>();
@@ -263,9 +276,44 @@
tags.firstWhere((tag) => tag.startsWith("build_address:"));
final buildAddress = buildAddressTag.substring("build_address:".length);
if (build["status"] != "COMPLETED") {
- throw new Exception("Build $buildAddress isn't completed yet");
+ throw new CommitNotBuiltException(
+ "Build $buildAddress isn't completed yet");
}
- return int.parse(buildAddress.split("/").last);
+ return new BuildSearchResult(int.parse(buildAddress.split("/").last), commit);
+}
+
+Future<BuildSearchResult> searchForApproximateBuild(
+ String builder, String commit) async {
+ try {
+ return await searchForBuild(builder, commit);
+ } on CommitNotBuiltException catch (e) {
+ print("Warning: $e, searching for an inexact previous build...");
+ final int limit = 25;
+ final arguments = [
+ "rev-list",
+ "$commit~$limit..$commit~1",
+ "--first-parent",
+ "--topo-order"
+ ];
+ final processResult = await Process.run("git", arguments, runInShell: true);
+ if (processResult.exitCode != 0) {
+ throw new Exception("Failed to list potential commits: git $arguments\n"
+ "exitCode: ${processResult.exitCode}\n"
+ "stdout: ${processResult.stdout}\n"
+ "stdout: ${processResult.stderr}\n");
+ }
+ for (final fallbackCommit in LineSplitter.split(processResult.stdout)) {
+ try {
+ return await searchForBuild(builder, fallbackCommit);
+ } catch (e) {
+ print(
+ "Warning: Searching for inexact baseline build: $e, continuing...");
+ }
+ }
+ throw new CommitNotBuiltException(
+ "Failed to locate approximate baseline results for "
+ "$commit in past $limit commits");
+ }
}
void main(List<String> args) async {
@@ -277,10 +325,18 @@
help: "Select the builders building this branch",
defaultsTo: "master");
parser.addOption("commit", abbr: "C", help: "Compare with this commit");
+ parser.addFlag("list-configurations",
+ help: "Output list of configurations.", negatable: false);
parser.addOption("named-configuration",
abbr: "n",
help: "The named test configuration that supplies the\nvalues for all "
"test options, specifying how tests\nshould be run.");
+ parser.addOption("local-configuration",
+ abbr: "N",
+ help: "Use a different named configuration for local\ntesting than the "
+ "named configuration the baseline\nresults were downloaded for. The "
+ "results may be\ninexact if the baseline configuration is "
+ "different.");
parser.addOption("remote",
abbr: "R",
help: "Compare with this remote and git branch",
@@ -289,7 +345,9 @@
final options = parser.parse(args);
if (options["help"] ||
- (options["builder"] == null && options["named-configuration"] == null)) {
+ (options["builder"] == null &&
+ options["named-configuration"] == null &&
+ !options["list-configurations"])) {
print("""
Usage: test.dart -b [BUILDER] -n [CONFIGURATION] [OPTION]... [--]
[TEST.PY OPTION]... [SELECTOR]...
@@ -309,6 +367,14 @@
return;
}
+ if (options["list-configurations"]) {
+ final process = await Process.start(
+ "python", ["tools/test.py", "--list-configurations"],
+ mode: ProcessStartMode.inheritStdio, runInShell: Platform.isWindows);
+ exitCode = await process.exitCode;
+ return;
+ }
+
// Locate gsutil.py.
gsutilPy =
Platform.script.resolve("../third_party/gsutil/gsutil.py").toFilePath();
@@ -351,9 +417,16 @@
return;
}
final namedConfiguration = namedConfigurations.single;
+ final localConfiguration =
+ options["local-configuration"] ?? namedConfiguration;
for (final builder in builders) {
- print("Testing the named configuration $namedConfiguration "
- "compared with builder $builder");
+ if (localConfiguration != namedConfiguration) {
+ print("Testing the named configuration $localConfiguration "
+ "compared with builder $builder's configuration $namedConfiguration");
+ } else {
+ print("Testing the named configuration $localConfiguration "
+ "compared with builder $builder");
+ }
}
// Find out where the current HEAD branched.
@@ -368,10 +441,18 @@
final mergedFlaky = <String, Map<String, dynamic>>{};
// Use the buildbucket API to search for builds of the right commit.
+ final inexactBuilds = new SplayTreeMap<String, String>();
for (final builder in builders) {
// Download the previous results and flakiness info from cloud storage.
print("Finding build on builder $builder to compare with...");
- final buildNumber = await buildNumberOfCommit(builder, commit);
+ final buildSearchResult =
+ await searchForApproximateBuild(builder, commit);
+ if (buildSearchResult.commit != commit) {
+ print("Warning: Using commit ${buildSearchResult.commit} "
+ "as baseline instead of $commit for $builder");
+ inexactBuilds[builder] = buildSearchResult.commit;
+ }
+ final buildNumber = buildSearchResult.build;
print("Downloading results from builder $builder build $buildNumber...");
await cpGsutil(
buildFileCloudPath(builder, buildNumber.toString(), "results.json"),
@@ -391,16 +472,31 @@
// Write out the merged results for the builders.
if (2 <= builders.length) {
- print("Merging downloaded results from the builders...");
await new File("${outDirectory.path}/previous.json").writeAsString(
mergedResults.values.map((data) => jsonEncode(data) + "\n").join(""));
await new File("${outDirectory.path}/flaky.json").writeAsString(
mergedFlaky.values.map((data) => jsonEncode(data) + "\n").join(""));
}
+ // Override the named configuration in the baseline data if needed.
+ if (namedConfiguration != localConfiguration) {
+ for (final path in [
+ "${outDirectory.path}/previous.json",
+ "${outDirectory.path}/flaky.json"
+ ]) {
+ final results = await loadResultsMap(path);
+ final records = results.values
+ .where((r) => r["configuration"] == namedConfiguration)
+ .toList()
+ ..forEach((r) => r["configuration"] = localConfiguration);
+ await new File(path).writeAsString(
+ records.map((data) => jsonEncode(data) + "\n").join(""));
+ }
+ }
+
// Run the tests.
final arguments = [
- "--named-configuration=$namedConfiguration",
+ "--named-configuration=$localConfiguration",
"--output-directory=${outDirectory.path}",
"--clean-exit",
"--silent-failures",
@@ -438,7 +534,7 @@
final deflakeDirectory = new Directory("${outDirectory.path}/$i");
await deflakeDirectory.create();
final deflakeArguments = <String>[
- "--named-configuration=$namedConfiguration",
+ "--named-configuration=$localConfiguration",
"--output-directory=${deflakeDirectory.path}",
"--clean-exit",
"--silent-failures",
@@ -483,6 +579,12 @@
} else {
stdout.write(compareOutput.stdout);
}
+ if (inexactBuilds.isNotEmpty) {
+ print("");
+ inexactBuilds.forEach((String builder, String inexactCommit) => print(
+ "Warning: Results may be inexact because commit ${inexactCommit} "
+ "was used as the baseline for $builder instead of $commit"));
+ }
} finally {
await outDirectory.delete(recursive: true);
}
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index 89ba917..59399f3a 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -59,7 +59,6 @@
this.testDriverErrorPort,
this.localIP,
this.keepGeneratedFiles,
- this.dart2jsOptions,
this.sharedOptions,
String packages,
this.packageRoot,
@@ -117,8 +116,6 @@
bool get useBlobs => configuration.useBlobs;
bool get useSdk => configuration.useSdk;
bool get useEnableAsserts => configuration.enableAsserts;
- bool get useDart2JSWithKernel => configuration.useDart2JSWithKernel;
- bool get useDart2JSOldFrontend => configuration.useDart2JSOldFrontEnd;
// Various file paths.
@@ -143,7 +140,7 @@
final bool keepGeneratedFiles;
/// Extra dart2js options passed to the testing script.
- final List<String> dart2jsOptions;
+ List<String> get dart2jsOptions => configuration.dart2jsOptions;
/// Extra VM options passed to the testing script.
List<String> get vmOptions => configuration.vmOptions;
@@ -187,9 +184,9 @@
Compiler.dartkb,
Compiler.dartkp,
Compiler.fasta,
+ Compiler.dart2js,
];
- return fastaCompilers.contains(compiler) ||
- (compiler == Compiler.dart2js && !useDart2JSOldFrontend);
+ return fastaCompilers.contains(compiler);
}
/// The base directory named for this configuration, like:
@@ -236,19 +233,12 @@
return const ["--ignore-unrecognized-flags"];
}
- var args = ['--generate-code-with-compile-time-errors', '--test-mode'];
+ var args = ['--test-mode'];
if (isChecked) args.add('--enable-checked-mode');
- if (!runtime.isBrowser) {
- args.add("--allow-mock-compilation");
- args.add("--categories=all");
- }
-
if (isMinified) args.add("--minify");
if (isCsp) args.add("--csp");
if (useEnableAsserts) args.add("--enable-asserts");
- if (useDart2JSWithKernel) args.add("--use-kernel");
- if (useDart2JSOldFrontend) args.add("--use-old-frontend");
return args;
}
@@ -446,6 +436,7 @@
'csp': isCsp,
'system': system.name,
'vm_options': vmOptions,
+ 'dart2js_options': dart2jsOptions,
'fasta': usesFasta,
'use_sdk': useSdk,
'builder_tag': builderTag,
@@ -453,8 +444,6 @@
'no_preview_dart_2': noPreviewDart2,
'use_cfe': useAnalyzerCfe,
'analyzer_use_fasta_parser': useAnalyzerFastaParser,
- 'dart2js_with_kernel': useDart2JSWithKernel,
- 'dart2js_old_frontend': useDart2JSOldFrontend,
'enable_asserts': useEnableAsserts,
'hot_reload': hotReload,
'hot_reload_rollback': hotReloadRollback,
diff --git a/tools/testing/dart/environment.dart b/tools/testing/dart/environment.dart
index 720c72d..5245977 100644
--- a/tools/testing/dart/environment.dart
+++ b/tools/testing/dart/environment.dart
@@ -21,8 +21,6 @@
"checked": new _Variable.bool((c) => c.isChecked),
"compiler": new _Variable((c) => c.compiler.name, Compiler.names),
"csp": new _Variable.bool((c) => c.isCsp),
- "dart2js_with_kernel": new _Variable.bool((c) => c.useDart2JSWithKernel),
- "dart2js_old_frontend": new _Variable.bool((c) => c.useDart2JSOldFrontend),
"enable_asserts": new _Variable.bool((c) => c.useEnableAsserts),
"fasta": new _Variable.bool((c) => c.usesFasta),
"host_checked": new _Variable.bool((c) => c.isHostChecked),
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index 258ed6d..c0c6d7d 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -201,9 +201,11 @@
TestUtils.mkdirRecursive(targetDir, importDir);
}
- // Copy file.
- futureCopies.add(TestUtils.copyFile(
- sourceDir.join(importPath), targetDir.join(importPath)));
+ // Copy file. Because some test suites may be read-only, we don't
+ // want to copy the permissions, so we create the copy by writing.
+ final source = File(sourceDir.join(importPath).toNativePath()).openRead();
+ final target = File(targetDir.join(importPath).toNativePath()).openWrite();
+ futureCopies.add(source.pipe(target));
}
// Wait until all imports are copied before scheduling test cases.
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index e462b42..cafab24 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -174,13 +174,6 @@
'Pass the --use-fasta-parser flag to analyzer',
hide: true),
- // TODO(sigmund): replace dart2js_with_kernel with preview-dart-2.
- new _Option.bool(
- 'dart2js_with_kernel', 'Pass the --use-kernel flag to dart2js.',
- hide: true),
- new _Option.bool(
- 'dart2js_old_frontend', 'Pass the --use-old-frontend flag to dart2js.',
- hide: true),
new _Option.bool('hot_reload', 'Run hot reload stress tests.', hide: true),
new _Option.bool(
'hot_reload_rollback', 'Run hot reload rollback stress tests.',
@@ -219,6 +212,7 @@
new _Option.bool('no-tree-shake', 'Disable kernel IR tree shaking.',
hide: true),
new _Option.bool('list', 'List tests only, do not run them.'),
+ new _Option.bool('list-configurations', 'Output list of configurations.'),
new _Option.bool('list_status_files',
'List status files for test-suites. Do not run any test suites.',
hide: true),
@@ -383,6 +377,17 @@
verbose: arguments.contains("--verbose") || arguments.contains("-v"));
return null;
}
+ if (arguments.contains("--list-configurations")) {
+ final testMatrixFile = "tools/bots/test_matrix.json";
+ TestMatrix testMatrix = TestMatrix.fromPath(testMatrixFile);
+ for (final configuration in testMatrix.configurations
+ .map((configuration) => configuration.name)
+ .toList()
+ ..sort()) {
+ print(configuration);
+ }
+ return null;
+ }
// Dart1 mode has been deprecated.
if (arguments.contains("--no-preview-dart-2")) {
return null;
@@ -683,8 +688,6 @@
data["analyzer_use_fasta_parser"] as bool,
useBlobs: data["use_blobs"] as bool,
useSdk: data["use_sdk"] as bool,
- useDart2JSWithKernel: data["dart2js_with_kernel"] as bool,
- useDart2JSOldFrontEnd: data["dart2js_old_frontend"] as bool,
useHotReload: data["hot_reload"] as bool,
useHotReloadRollback: data["hot_reload_rollback"] as bool,
isChecked: data["checked"] as bool,
@@ -692,6 +695,7 @@
isCsp: data["csp"] as bool,
isMinified: data["minified"] as bool,
vmOptions: vmOptions,
+ dart2jsOptions: dart2jsOptions,
builderTag: data["builder_tag"] as String,
previewDart2: true);
var configuration = new TestConfiguration(
@@ -734,7 +738,6 @@
data['test_server_cross_origin_port'] as int,
testDriverErrorPort: data["test_driver_error_port"] as int,
localIP: data["local_ip"] as String,
- dart2jsOptions: dart2jsOptions,
sharedOptions: sharedOptions,
packages: data["packages"] as String,
packageRoot: data["package_root"] as String,
diff --git a/tools/utils.py b/tools/utils.py
index a6db548..a3657f2 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -880,11 +880,11 @@
missing.append(crash)
if self._output_directory is not None and self._is_shard():
print (
- "INFO: Copying collected dumps and binaries into output directory\n"
+ "INFO: Moving collected dumps and binaries into output directory\n"
"INFO: They will be uploaded to isolate server. Look for \"isolated"
" out\" under the failed step on the build page.\n"
"INFO: For more information see runtime/docs/infra/coredumps.md")
- self._copy(files)
+ self._move(files)
else:
print (
"INFO: Uploading collected dumps and binaries into Cloud Storage\n"
@@ -910,13 +910,7 @@
if throw:
raise Exception('Missing crash dumps for: %s' % missing_as_string)
- def _copy(self, files):
- for file in files:
- tarname = self._tar(file)
- print '+++ Copying %s to output_directory (%s)' % (tarname, self._output_directory)
- shutil.copy(tarname, self._output_directory)
-
- def _tar(self, file):
+ def _get_file_name(self, file):
# Sanitize the name: actual cores follow 'core.%d' pattern, crashed
# binaries are copied next to cores and named
# 'binary.<mode>_<arch>_<binary_name>'.
@@ -927,7 +921,21 @@
if is_binary:
(mode, arch, binary_name) = suffix.split('_', 2)
name = binary_name
+ return (name, is_binary)
+ def _move(self, files):
+ for file in files:
+ print '+++ Moving %s to output_directory (%s)' % (file, self._output_directory)
+ (name, is_binary) = self._get_file_name(file)
+ destination = os.path.join(self._output_directory, name)
+ shutil.move(file, destination)
+ if is_binary and os.path.exists(file + '.pdb'):
+ # Also move a PDB file if there is one.
+ pdb = os.path.join(self._output_directory, name + '.pdb')
+ shutil.move(file + '.pdb', pdb)
+
+ def _tar(self, file):
+ (name, is_binary) = self._get_file_name(file)
tarname = '%s.tar.gz' % name
# Compress the file.
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index a9a0145..86a2eb8 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -15,10 +15,12 @@
import 'package:args/args.dart';
import 'package:bazel_worker/bazel_worker.dart';
import 'package:build_integration/file_system/multi_root.dart';
+import 'package:dev_compiler/src/kernel/target.dart';
import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
import 'package:kernel/ast.dart' show Component, Library;
import 'package:kernel/target/targets.dart';
import 'package:vm/target/vm.dart';
+import 'package:compiler/src/kernel/dart2js_target.dart';
main(List<String> args) async {
args = preprocessArgs(args);
@@ -83,7 +85,7 @@
/// An [ArgParser] for generating kernel summaries.
final summaryArgsParser = new ArgParser()
- ..addFlag('help', negatable: false)
+ ..addFlag('help', negatable: false, abbr: 'h')
..addFlag('exclude-non-sources',
negatable: false,
help: 'Whether source files loaded implicitly should be included as '
@@ -92,11 +94,15 @@
defaultsTo: true,
negatable: true,
help: 'Whether to only build summary files.')
+ ..addOption('target',
+ allowed: const ['vm', 'dart2js', 'devcompiler'],
+ help: 'Build kernel for the vm, dart2js, or devcompiler')
..addOption('dart-sdk-summary')
..addMultiOption('input-summary')
..addMultiOption('input-linked')
..addMultiOption('multi-root')
..addOption('multi-root-scheme', defaultsTo: 'org-dartlang-multi-root')
+ ..addOption('libraries-file')
..addOption('packages-file')
..addMultiOption('source')
..addOption('output');
@@ -128,20 +134,54 @@
if (multiRoots.isEmpty) multiRoots.add(Uri.base);
var fileSystem = new MultiRootFileSystem(parsedArgs['multi-root-scheme'],
multiRoots, fe.StandardFileSystem.instance);
- var sources = (parsedArgs['source'] as List<String>).map(Uri.parse).toList();
- Target target;
- var summaryOnly = parsedArgs['summary-only'] as bool;
+ var sources =
+ (parsedArgs['source'] as List<String>).map(Uri.base.resolve).toList();
var excludeNonSources = parsedArgs['exclude-non-sources'] as bool;
+
+ var summaryOnly = parsedArgs['summary-only'] as bool;
+ // TODO(sigmund,jakemac): make target mandatory. We allow null to be backwards
+ // compatible while we migrate existing clients of this tool.
+ var targetName =
+ (parsedArgs['target'] as String) ?? (summaryOnly ? 'devcompiler' : 'vm');
var targetFlags = new TargetFlags();
- if (summaryOnly) {
- target = new SummaryTarget(sources, excludeNonSources, targetFlags);
- } else {
- target = new VmTarget(targetFlags);
+ Target target;
+ switch (targetName) {
+ case 'vm':
+ target = new VmTarget(targetFlags);
+ if (summaryOnly) {
+ out.writeln('error: --summary-only not supported for the vm target');
+ }
+ break;
+ case 'dart2js':
+ target = new Dart2jsTarget('dart2js', targetFlags);
+ if (summaryOnly) {
+ out.writeln(
+ 'error: --summary-only not supported for the dart2js target');
+ }
+ break;
+ case 'devcompiler':
+ // TODO(jakemac):If `generateKernel` changes to return a summary
+ // component, process the component instead.
+ target = new DevCompilerSummaryTarget(sources, excludeNonSources);
+ if (!summaryOnly) {
+ out.writeln('error: --no-summary-only not supported for the '
+ 'devcompiler target');
+ }
+ break;
+ default:
+ out.writeln('error: unsupported target: $targetName');
}
+
+ // TODO(sigmund,jakemac): make it mandatory. We allow null while we migrate
+ // existing clients of this tool.
+ var librariesSpec = parsedArgs['libraries-file'] == null
+ ? null
+ : Uri.base.resolve(parsedArgs['libraries-file']);
var state = await fe.initializeCompiler(
// TODO(sigmund): pass an old state once we can make use of it.
null,
Uri.base.resolve(parsedArgs['dart-sdk-summary']),
+ librariesSpec,
Uri.base.resolve(parsedArgs['packages-file']),
(parsedArgs['input-summary'] as List<String>)
.map(Uri.base.resolve)
@@ -171,8 +211,8 @@
return succeeded;
}
-/// A target that transforms outlines to meet the requirements of summaries in
-/// bazel and package-build.
+/// Extends the DevCompilerTarget to transform outlines to meet the requirements
+/// of summaries in bazel and package-build.
///
/// Build systems like package-build may provide the same input file twice to
/// the summary worker, but only intends to have it in one output summary. The
@@ -183,15 +223,15 @@
///
/// Note: this transformation is destructive and is only intended to be used
/// when generating summaries.
-class SummaryTarget extends NoneTarget {
+class DevCompilerSummaryTarget extends DevCompilerTarget {
final List<Uri> sources;
final bool excludeNonSources;
- SummaryTarget(this.sources, this.excludeNonSources, TargetFlags flags)
- : super(flags);
+ DevCompilerSummaryTarget(this.sources, this.excludeNonSources);
@override
void performOutlineTransformations(Component component) {
+ super.performOutlineTransformations(component);
if (!excludeNonSources) return;
List<Library> libraries = new List.from(component.libraries);