Version 2.12.0-7.0.dev
Merge commit '77f2019f00858ac60dbca006ed93f11576b757b4' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 051ed07..041bc3f 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -229,12 +229,6 @@
"languageVersion": "2.10"
},
{
- "name": "dartfix",
- "rootUri": "../pkg/dartfix",
- "packageUri": "lib/",
- "languageVersion": "2.8"
- },
- {
"name": "dds",
"rootUri": "../pkg/dds",
"packageUri": "lib/",
diff --git a/.packages b/.packages
index 831d0f3..22dab41 100644
--- a/.packages
+++ b/.packages
@@ -35,7 +35,6 @@
dart_style:third_party/pkg_tested/dart_style/lib
dartdev:pkg/dartdev/lib
dartdoc:third_party/pkg/dartdoc/lib
-dartfix:pkg/dartfix/lib
dds:pkg/dds/lib
dev_compiler:pkg/dev_compiler/lib
diagnostic:pkg/diagnostic/lib
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index ea398ea..ce3c063 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -626,10 +626,6 @@
/// generally used in specific SDKs (like the internal google3 one).
SdkConfiguration configurationOverrides;
- /// The list of the names of the experiments that should be enabled by
- /// default, unless the analysis options file of a context overrides it.
- List<String> enabledExperiments = const <String>[];
-
/// Whether to use the Language Server Protocol.
bool useLanguageServerProtocol = false;
@@ -659,9 +655,8 @@
analysisServer.notificationManager;
@override
- nd.AnalysisDriver addAnalysisDriver(
- Folder folder, ContextRoot contextRoot, AnalysisOptions options) {
- var builder = createContextBuilder(folder, options);
+ nd.AnalysisDriver addAnalysisDriver(Folder folder, ContextRoot contextRoot) {
+ var builder = createContextBuilder(folder);
var analysisDriver = builder.buildDriver(contextRoot);
analysisDriver.results.listen((result) {
var notificationManager = analysisServer.notificationManager;
@@ -814,9 +809,8 @@
}
@override
- ContextBuilder createContextBuilder(Folder folder, AnalysisOptions options) {
+ ContextBuilder createContextBuilder(Folder folder) {
var builderOptions = ContextBuilderOptions();
- builderOptions.defaultOptions = options;
var builder = ContextBuilder(
resourceProvider, analysisServer.sdkManager, null,
options: builderOptions);
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index bb545e4..f0db479 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -22,7 +22,6 @@
import 'package:analysis_server/src/utilities/null_string_sink.dart';
import 'package:analysis_server/src/utilities/request_statistics.dart';
import 'package:analysis_server/src/utilities/tee_string_sink.dart';
-import 'package:analyzer/dart/analysis/features.dart' as analyzer_features;
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
@@ -34,8 +33,6 @@
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
-import 'package:analyzer/src/dart/analysis/experiments.dart'
- as analyzer_features;
import 'package:analyzer/src/dart/analysis/file_byte_store.dart'
show EvictingFileByteStore;
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
@@ -60,10 +57,6 @@
/// context directories.
ContextManager contextManager;
- /// The default options used to create new analysis contexts. This object is
- /// also referenced by the ContextManager.
- final AnalysisOptionsImpl defaultContextOptions = AnalysisOptionsImpl();
-
/// The object used to manage sending a subset of notifications to the client.
/// The subset of notifications are those to which plugins may contribute.
/// This field is `null` when the new plugin support is disabled.
@@ -155,12 +148,6 @@
instrumentationService);
var pluginWatcher = PluginWatcher(resourceProvider, pluginManager);
- defaultContextOptions.contextFeatures =
- analyzer_features.FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: analyzer_features.ExperimentStatus.currentVersion,
- flags: options.enabledExperiments,
- );
-
{
var name = options.newAnalysisDriverLog;
StringSink sink = NullStringSink();
@@ -192,7 +179,7 @@
}
contextManager = ContextManagerImpl(resourceProvider, sdkManager,
- analyzedFilesGlobs, instrumentationService, defaultContextOptions);
+ analyzedFilesGlobs, instrumentationService);
searchEngine = SearchEngineImpl(driverMap.values);
}
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 19725d0..5c09be3 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -294,10 +294,8 @@
/// Return the notification manager associated with the server.
AbstractNotificationManager get notificationManager;
- /// Create and return a new analysis driver rooted at the given [folder], with
- /// the given analysis [options].
- AnalysisDriver addAnalysisDriver(
- Folder folder, ContextRoot contextRoot, AnalysisOptions options);
+ /// Create and return a new analysis driver rooted at the given [folder].
+ AnalysisDriver addAnalysisDriver(Folder folder, ContextRoot contextRoot);
/// An [event] was processed, so analysis state might be different now.
void afterWatchEvent(WatchEvent event);
@@ -318,9 +316,8 @@
void broadcastWatchEvent(WatchEvent event);
/// Create and return a context builder that can be used to create a context
- /// for the files in the given [folder] when analyzed using the given
- /// [options].
- ContextBuilder createContextBuilder(Folder folder, AnalysisOptions options);
+ /// for the files in the given [folder].
+ ContextBuilder createContextBuilder(Folder folder);
/// Remove the context associated with the given [folder]. [flushedFiles] is
/// a list of the files which will be "orphaned" by removing this context
@@ -377,9 +374,6 @@
/// A list of the globs used to determine which files should be analyzed.
final List<Glob> analyzedFilesGlobs;
- /// The default options used to create new analysis contexts.
- final AnalysisOptionsImpl defaultContextOptions;
-
/// The instrumentation service used to report instrumentation data.
final InstrumentationService _instrumentationService;
@@ -400,11 +394,11 @@
<Folder, StreamSubscription<WatchEvent>>{};
ContextManagerImpl(
- this.resourceProvider,
- this.sdkManager,
- this.analyzedFilesGlobs,
- this._instrumentationService,
- this.defaultContextOptions) {
+ this.resourceProvider,
+ this.sdkManager,
+ this.analyzedFilesGlobs,
+ this._instrumentationService,
+ ) {
pathContext = resourceProvider.pathContext;
}
@@ -1006,7 +1000,7 @@
} catch (_) {
// Parse errors are reported elsewhere.
}
- AnalysisOptions options = AnalysisOptionsImpl.from(defaultContextOptions);
+ var options = AnalysisOptionsImpl();
applyToAnalysisOptions(options, optionMap);
info.setDependencies(dependencies);
@@ -1021,8 +1015,7 @@
if (optionsFile != null) {
contextRoot.optionsFilePath = optionsFile.path;
}
- info.analysisDriver =
- callbacks.addAnalysisDriver(folder, contextRoot, options);
+ info.analysisDriver = callbacks.addAnalysisDriver(folder, contextRoot);
if (optionsFile != null) {
_analyzeAnalysisOptionsFile(info.analysisDriver, optionsFile.path);
}
@@ -1115,8 +1108,8 @@
/// Set up a [SourceFactory] that resolves packages as appropriate for the
/// given [folder].
- SourceFactory _createSourceFactory(AnalysisOptions options, Folder folder) {
- var builder = callbacks.createContextBuilder(folder, options);
+ SourceFactory _createSourceFactory(Folder folder) {
+ var builder = callbacks.createContextBuilder(folder);
return builder.createSourceFactory(folder.path);
}
@@ -1481,8 +1474,7 @@
void _updateAnalysisOptions(ContextInfo info) {
var driver = info.analysisDriver;
var contextRoot = info.folder.path;
- var builder =
- callbacks.createContextBuilder(info.folder, defaultContextOptions);
+ var builder = callbacks.createContextBuilder(info.folder);
var options = builder.getAnalysisOptions(contextRoot,
contextRoot: driver.contextRoot);
var factory = builder.createSourceFactory(contextRoot);
@@ -1493,8 +1485,7 @@
void _updateContextPackageUriResolver(Folder contextFolder) {
var info = getContextInfoFor(contextFolder);
var driver = info.analysisDriver;
- var sourceFactory =
- _createSourceFactory(driver.analysisOptions, contextFolder);
+ var sourceFactory = _createSourceFactory(contextFolder);
driver.configure(sourceFactory: sourceFactory);
}
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index 4e53670..c8acbe8 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -43,7 +43,6 @@
import 'package:analyzer/src/context/context_root.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
import 'package:analyzer/src/dart/analysis/status.dart' as nd;
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
@@ -741,9 +740,8 @@
analysisServer.notificationManager;
@override
- nd.AnalysisDriver addAnalysisDriver(
- Folder folder, ContextRoot contextRoot, AnalysisOptions options) {
- var builder = createContextBuilder(folder, options);
+ nd.AnalysisDriver addAnalysisDriver(Folder folder, ContextRoot contextRoot) {
+ var builder = createContextBuilder(folder);
var analysisDriver = builder.buildDriver(contextRoot);
final textDocumentCapabilities =
analysisServer.clientCapabilities?.textDocument;
@@ -838,9 +836,8 @@
}
@override
- ContextBuilder createContextBuilder(Folder folder, AnalysisOptions options) {
+ ContextBuilder createContextBuilder(Folder folder) {
var builderOptions = ContextBuilderOptions();
- builderOptions.defaultOptions = options;
var builder = ContextBuilder(
resourceProvider, analysisServer.sdkManager, null,
options: builderOptions);
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 298fd30..18b8438 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -234,9 +234,6 @@
static const String DISABLE_SERVER_FEATURE_SEARCH =
'disable-server-feature-search';
- /// The name of the option used to enable experiments.
- static const String ENABLE_EXPERIMENT_OPTION = 'enable-experiment';
-
/// The name of the option used to enable instrumentation.
static const String ENABLE_INSTRUMENTATION_OPTION = 'enable-instrumentation';
@@ -336,10 +333,6 @@
analysisServerOptions.clientVersion = results[CLIENT_VERSION];
analysisServerOptions.cacheFolder = results[CACHE_FOLDER];
- if (results.wasParsed(ENABLE_EXPERIMENT_OPTION)) {
- analysisServerOptions.enabledExperiments =
- (results[ENABLE_EXPERIMENT_OPTION] as List).cast<String>().toList();
- }
analysisServerOptions.useNewRelevance = results[USE_NEW_RELEVANCE];
// Read in any per-SDK overrides specified in <sdk>/config/settings.json.
@@ -769,11 +762,6 @@
help: 'disable all completion features', defaultsTo: false, hide: true);
parser.addFlag(DISABLE_SERVER_FEATURE_SEARCH,
help: 'disable all search features', defaultsTo: false, hide: true);
- parser.addMultiOption(ENABLE_EXPERIMENT_OPTION,
- help: 'Enable one or more experimental features. If multiple features '
- 'are being added, they should be comma separated.',
- hide: true,
- splitCommas: true);
parser.addFlag(ENABLE_INSTRUMENTATION_OPTION,
help: 'enable sending instrumentation information to a server',
defaultsTo: false,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
index f00f631..e7b8a24 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -405,8 +405,9 @@
Change _translateChange(YamlNode node, ErrorContext context) {
assert(node != null);
if (node is YamlMap) {
- var kind = _translateString(node.valueAt(_kindKey),
- ErrorContext(key: _kindKey, parentNode: node));
+ var kindNode = node.valueAt(_kindKey);
+ var kindContext = ErrorContext(key: _kindKey, parentNode: node);
+ var kind = _translateString(kindNode, kindContext);
if (kind == null) {
return null;
} else if (kind == _addParameterKind) {
@@ -420,7 +421,7 @@
} else if (kind == _renameKind) {
return _translateRenameChange(node);
}
- return _reportInvalidValueOneOf(node, context, [
+ return _reportInvalidValueOneOf(kindNode, kindContext, [
_addParameterKind,
_addTypeParameterKind,
_removeParameterKind,
@@ -879,8 +880,9 @@
/// error.
ValueGenerator _translateValueGenerator(YamlNode node, ErrorContext context) {
if (node is YamlMap) {
- var kind = _translateString(node.valueAt(_kindKey),
- ErrorContext(key: _kindKey, parentNode: node));
+ var kindNode = node.valueAt(_kindKey);
+ var kindContext = ErrorContext(key: _kindKey, parentNode: node);
+ var kind = _translateString(kindNode, kindContext);
if (kind == null) {
return null;
} else if (kind == _fragmentKind) {
@@ -888,7 +890,7 @@
} else if (kind == _importKind) {
return _translateImportValue(node);
}
- return _reportInvalidValueOneOf(node, context, [
+ return _reportInvalidValueOneOf(kindNode, kindContext, [
_fragmentKind,
_importKind,
]);
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 0669678..28ba464 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -1591,11 +1591,11 @@
MockSdk(resourceProvider: resourceProvider);
var sdkManager = DartSdkManager(convertPath(sdkRoot));
manager = ContextManagerImpl(
- resourceProvider,
- sdkManager,
- analysisFilesGlobs,
- InstrumentationService.NULL_SERVICE,
- AnalysisOptionsImpl());
+ resourceProvider,
+ sdkManager,
+ analysisFilesGlobs,
+ InstrumentationService.NULL_SERVICE,
+ );
var logger = PerformanceLog(NullStringSink());
var scheduler = AnalysisDriverScheduler(logger);
callbacks = TestContextManagerCallbacks(
@@ -2280,15 +2280,14 @@
SourceFactory get sourceFactory => currentDriver?.sourceFactory;
@override
- AnalysisDriver addAnalysisDriver(
- Folder folder, ContextRoot contextRoot, AnalysisOptions options) {
+ AnalysisDriver addAnalysisDriver(Folder folder, ContextRoot contextRoot) {
var path = folder.path;
expect(currentContextRoots, isNot(contains(path)));
expect(contextRoot, isNotNull);
expect(contextRoot.root, path);
currentContextTimestamps[path] = now;
- var builder = createContextBuilder(folder, options);
+ var builder = createContextBuilder(folder);
builder.analysisDriverScheduler = scheduler;
builder.byteStore = MemoryByteStore();
builder.performanceLog = logger;
@@ -2345,9 +2344,8 @@
}
@override
- ContextBuilder createContextBuilder(Folder folder, AnalysisOptions options) {
+ ContextBuilder createContextBuilder(Folder folder) {
var builderOptions = ContextBuilderOptions();
- builderOptions.defaultOptions = options;
var builder = ContextBuilder(resourceProvider, sdkManager, null,
options: builderOptions);
return builder;
diff --git a/pkg/analysis_server/test/lsp/signature_help_test.dart b/pkg/analysis_server/test/lsp/signature_help_test.dart
index 64d902d..2e6094e 100644
--- a/pkg/analysis_server/test/lsp/signature_help_test.dart
+++ b/pkg/analysis_server/test/lsp/signature_help_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
-import 'package:analysis_server/src/analysis_server.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -449,10 +448,6 @@
class SignatureHelpWithNullSafetyTest extends AbstractLspAnalysisServerTest
with SignatureHelpMixin {
@override
- AnalysisServerOptions get serverOptions =>
- AnalysisServerOptions()..enabledExperiments = ['non-nullable'];
-
- @override
String get testPackageLanguageVersion => latestLanguageVersion;
Future<void> test_params_requiredNamed() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart b/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart
index 9a363e9..643fec4 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart
@@ -9,12 +9,9 @@
import '../../../../client/completion_driver_test.dart';
class CompletionRelevanceTest extends AbstractCompletionDriverTest {
- List<String> get enabledExperiments => [];
-
@override
- AnalysisServerOptions get serverOptions => AnalysisServerOptions()
- ..enabledExperiments = enabledExperiments
- ..useNewRelevance = true;
+ AnalysisServerOptions get serverOptions =>
+ AnalysisServerOptions()..useNewRelevance = true;
@override
bool get supportsAvailableSuggestions => true;
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_relevance_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_relevance_test.dart
index baaf538..ffe4112 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_relevance_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_relevance_test.dart
@@ -46,9 +46,6 @@
@reflectiveTest
class NamedArgumentRelevanceWithNullSafetyTest
extends NamedArgumentRelevanceTest {
- @override
- List<String> get enabledExperiments => ['non-nullable'];
-
Future<void> test_required() async {
await addTestFile('''
void f({int a = 0, required int b}) {}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart
index 2e606bb..fa9beb5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart
@@ -27,7 +27,7 @@
changes:
- kind: 'invalid'
''', [
- error(TransformSetErrorCode.invalidValueOneOf, 129, 16),
+ error(TransformSetErrorCode.invalidValueOneOf, 135, 9),
]);
}
@@ -50,7 +50,7 @@
x:
kind: 'invalid'
''', [
- error(TransformSetErrorCode.invalidValueOneOf, 274, 16),
+ error(TransformSetErrorCode.invalidValueOneOf, 280, 9),
]);
}
}
diff --git a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
index 8705915..f3c9a79 100644
--- a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
+++ b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
@@ -12,7 +12,6 @@
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/analysis/session.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
@@ -217,7 +216,7 @@
var unit = result.unit as CompilationUnitImpl;
unit.languageVersion = LibraryLanguageVersion(
- package: ExperimentStatus.currentVersion,
+ package: languageVersion,
override: null,
);
diff --git a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
index 16a57bd..32b5d0f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/packages.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/util/uri.dart';
@@ -85,7 +84,7 @@
/// be either lower, or higher than the package language version.
Version getLanguageVersion(String path, Uri uri) {
if (uri.isScheme('dart')) {
- return ExperimentStatus.currentVersion;
+ return _sdkLanguageVersion;
}
var package = _findPackage(uri, path);
if (package != null) {
@@ -93,7 +92,7 @@
if (languageVersion != null) {
return languageVersion;
}
- return ExperimentStatus.currentVersion;
+ return _sdkLanguageVersion;
}
return _nonPackageDefaultLanguageVersion;
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 720c0e4..3688028 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -2030,17 +2030,17 @@
/**
* No parameters.
*/
- /* // #### Description
+ // #### Description
//
// The analyzer produces this diagnostic when a reference to the class `Never`
// is found in code that has an SDK constraint whose lower bound is less than
- // 2.X.0. This class wasn't defined in earlier versions, so this code won't be
- // able to run against earlier versions of the SDK.
+ // 2.12.0. This class wasn't defined in earlier versions, so this code won't
+ // be able to run against earlier versions of the SDK.
//
// #### Examples
//
// Here's an example of a pubspec that defines an SDK constraint with a lower
- // bound of less than 2.X.0:
+ // bound of less than 2.12.0:
//
// ```yaml
// %uri="pubspec.yaml"
@@ -2062,7 +2062,7 @@
//
// ```yaml
// environment:
- // sdk: '>=2.X.0 <2.7.0'
+ // sdk: '>=2.12.0 <2.13.0'
// ```
//
// If you need to support older versions of the SDK, then rewrite the code to
@@ -2070,14 +2070,12 @@
//
// ```dart
// dynamic x;
- // ``` */
+ // ```
static const HintCode SDK_VERSION_NEVER = HintCode(
- // TODO(brianwilkerson) Replace the message with the following when we know
- // when this feature will ship:
- // The type 'Never' wasn't supported until version 2.X.0, but this code
- // is required to be able to run on earlier versions.
'SDK_VERSION_NEVER',
- "The type Never isn't yet supported.");
+ "The type 'Never' wasn't supported until version 2.X.0, but this code is "
+ "required to be able to run on earlier versions.",
+ correction: "Try updating the SDK constraints.");
/**
* No parameters.
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 6489ae9..e901de2 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -11073,8 +11073,7 @@
// `isEven` if `s` is `null`. In other words, if `s` is `null`, then neither
// `length` nor `isEven` will be invoked, and if `s` is non-`null`, then
// `length` can't return a `null` value. Either way, `isEven` can't be invoked
- // on a `null` value, so the null-aware operator is neither necessary nor
- // allowed. See
+ // on a `null` value, so the null-aware operator is not necessary. See
// [Understanding null safety](/null-safety/understanding-null-safety#smarter-null-aware-methods)
// for more details.
//
@@ -11095,8 +11094,8 @@
static const StaticWarningCode INVALID_NULL_AWARE_OPERATOR =
StaticWarningCode(
'INVALID_NULL_AWARE_OPERATOR',
- "The receiver can't be null, so the null-aware operator '{0}' can't "
- "be used.",
+ "The receiver can't be null, so the null-aware operator '{0}' is "
+ "unnecessary.",
correction: "Try replacing the operator '{0}' with '{1}'.",
hasPublishedDocs: true);
diff --git a/pkg/analyzer/lib/src/error/deprecated_member_use_verifier.dart b/pkg/analyzer/lib/src/error/deprecated_member_use_verifier.dart
index 25c7280..6bcabc9 100644
--- a/pkg/analyzer/lib/src/error/deprecated_member_use_verifier.dart
+++ b/pkg/analyzer/lib/src/error/deprecated_member_use_verifier.dart
@@ -279,21 +279,21 @@
static bool _isLocalParameter(Element element, AstNode node) {
if (element is ParameterElement) {
ExecutableElement definingFunction = element.enclosingElement;
- FunctionBody body = node.thisOrAncestorOfType<FunctionBody>();
- while (body != null) {
- ExecutableElement enclosingFunction;
- AstNode parent = body.parent;
- if (parent is ConstructorDeclaration) {
- enclosingFunction = parent.declaredElement;
- } else if (parent is FunctionExpression) {
- enclosingFunction = parent.declaredElement;
- } else if (parent is MethodDeclaration) {
- enclosingFunction = parent.declaredElement;
+
+ for (; node != null; node = node.parent) {
+ if (node is ConstructorDeclaration) {
+ if (node.declaredElement == definingFunction) {
+ return true;
+ }
+ } else if (node is FunctionExpression) {
+ if (node.declaredElement == definingFunction) {
+ return true;
+ }
+ } else if (node is MethodDeclaration) {
+ if (node.declaredElement == definingFunction) {
+ return true;
+ }
}
- if (enclosingFunction == definingFunction) {
- return true;
- }
- body = parent?.thisOrAncestorOfType<FunctionBody>();
}
}
return false;
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 4fd12b4..ccfec81 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -3677,7 +3677,7 @@
handleRecoverableError(
templateExperimentNotEnabled.withArguments(
feature.enableString,
- _versionAsString(ExperimentStatus.currentVersion),
+ _versionAsString(feature.releaseVersion),
),
questionMark,
questionMark,
@@ -3699,7 +3699,7 @@
handleRecoverableError(
templateExperimentNotEnabled.withArguments(
feature.enableString,
- _versionAsString(ExperimentStatus.currentVersion),
+ _versionAsString(feature.releaseVersion),
),
modifierToken,
modifierToken,
@@ -3712,7 +3712,7 @@
handleRecoverableError(
templateExperimentNotEnabled.withArguments(
feature.enableString,
- _versionAsString(ExperimentStatus.currentVersion),
+ _versionAsString(feature.releaseVersion),
),
bang,
bang,
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 6b23228..440043d 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -1103,7 +1103,7 @@
_versionFile = resourceProvider
.getFolder(resourceProvider.convertPath(sdkRoot))
.getChildAssumingFile('version');
- _versionFile.writeAsStringSync('2.10.0');
+ _versionFile.writeAsStringSync('2.12.0');
for (MockSdkLibrary library in _LIBRARIES) {
var convertedLibrary = library._toProvider(resourceProvider);
diff --git a/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart b/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
index b304d11..37172b1 100644
--- a/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
@@ -7,6 +7,7 @@
import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/context/source.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/dart/analysis/experiments_impl.dart';
import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
@@ -260,40 +261,65 @@
}
test_sdk_allowedExperiments_default() {
+ var feature_a = ExperimentalFeature(
+ index: 0,
+ enableString: 'a',
+ isEnabledByDefault: false,
+ isExpired: false,
+ documentation: 'a',
+ experimentalReleaseVersion: null,
+ releaseVersion: null,
+ );
+
_newSdkExperimentsFile(r'''
{
"version": 1,
"experimentSets": {
- "nullSafety": ["non-nullable"]
+ "with_a": ["a"]
},
"sdk": {
"default": {
- "experimentSet": "nullSafety"
+ "experimentSet": "with_a"
}
}
}
''');
- provider = FeatureSetProvider.build(
- sourceFactory: sourceFactory,
- resourceProvider: resourceProvider,
- packages: findPackagesFrom(resourceProvider, getFolder('/test')),
- packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- );
+ overrideKnownFeatures({'a': feature_a}, () {
+ provider = FeatureSetProvider.build(
+ sourceFactory: sourceFactory,
+ resourceProvider: resourceProvider,
+ packages: findPackagesFrom(resourceProvider, getFolder('/test')),
+ packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+ nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
+ nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+ );
- var featureSet = _getSdkFeatureSet('dart:math');
- expect(featureSet.isEnabled(Feature.non_nullable), isTrue);
+ var core_featureSet = _getSdkFeatureSet('dart:core');
+ expect(core_featureSet.isEnabled(feature_a), isTrue);
+
+ var math_featureSet = _getSdkFeatureSet('dart:math');
+ expect(math_featureSet.isEnabled(feature_a), isTrue);
+ });
}
test_sdk_allowedExperiments_library() {
+ var feature_a = ExperimentalFeature(
+ index: 0,
+ enableString: 'a',
+ isEnabledByDefault: false,
+ isExpired: false,
+ documentation: 'a',
+ experimentalReleaseVersion: null,
+ releaseVersion: null,
+ );
+
_newSdkExperimentsFile(r'''
{
"version": 1,
"experimentSets": {
"none": [],
- "nullSafety": ["non-nullable"]
+ "with_a": ["a"]
},
"sdk": {
"default": {
@@ -301,26 +327,29 @@
},
"libraries": {
"math": {
- "experimentSet": "nullSafety"
+ "experimentSet": "with_a"
}
}
}
}
''');
- provider = FeatureSetProvider.build(
- sourceFactory: sourceFactory,
- resourceProvider: resourceProvider,
- packages: findPackagesFrom(resourceProvider, getFolder('/test')),
- packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- );
- var core_featureSet = _getSdkFeatureSet('dart:core');
- expect(core_featureSet.isEnabled(Feature.non_nullable), isFalse);
+ overrideKnownFeatures({'a': feature_a}, () {
+ provider = FeatureSetProvider.build(
+ sourceFactory: sourceFactory,
+ resourceProvider: resourceProvider,
+ packages: findPackagesFrom(resourceProvider, getFolder('/test')),
+ packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+ nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
+ nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+ );
- var math_featureSet = _getSdkFeatureSet('dart:math');
- expect(math_featureSet.isEnabled(Feature.non_nullable), isTrue);
+ var core_featureSet = _getSdkFeatureSet('dart:core');
+ expect(core_featureSet.isEnabled(feature_a), isFalse);
+
+ var math_featureSet = _getSdkFeatureSet('dart:math');
+ expect(math_featureSet.isEnabled(feature_a), isTrue);
+ });
}
test_sdk_allowedExperiments_mockDefault() {
diff --git a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
index 854de9d..a2d3d19 100644
--- a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
@@ -864,6 +864,48 @@
]);
}
+ test_parameter_named_inDefiningConstructor_asFieldFormalParameter() async {
+ await assertNoErrorsInCode(r'''
+class C {
+ int x;
+ C({@deprecated this.x});
+}
+''');
+ }
+
+ test_parameter_named_inDefiningConstructor_assertInitializer() async {
+ await assertNoErrorsInCode(r'''
+class C {
+ C({@deprecated int y}) : assert(y > 0);
+}
+''');
+ }
+
+ test_parameter_named_inDefiningConstructor_fieldInitializer() async {
+ await assertNoErrorsInCode(r'''
+class C {
+ int x;
+ C({@deprecated int y}) : x = y;
+}
+''');
+ }
+
+ test_parameter_named_inDefiningConstructor_inFieldFormalParameter_notName() async {
+ await assertErrorsInCode(r'''
+class A {}
+
+@deprecated
+class B extends A {}
+
+class C {
+ A a;
+ C({B this.a});
+}
+''', [
+ error(HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE, 68, 1),
+ ]);
+ }
+
test_parameter_named_inDefiningFunction() async {
await assertNoErrorsInCode(r'''
f({@deprecated int x}) => x;
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index ef05f7e..7b12549 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -3884,7 +3884,7 @@
_The receiver can't be null because of short-circuiting, so the null-aware
operator '{0}' can't be used._
-_The receiver can't be null, so the null-aware operator '{0}' can't be used._
+_The receiver can't be null, so the null-aware operator '{0}' is unnecessary._
#### Description
@@ -3923,8 +3923,7 @@
`isEven` if `s` is `null`. In other words, if `s` is `null`, then neither
`length` nor `isEven` will be invoked, and if `s` is non-`null`, then
`length` can't return a `null` value. Either way, `isEven` can't be invoked
-on a `null` value, so the null-aware operator is neither necessary nor
-allowed. See
+on a `null` value, so the null-aware operator is not necessary. See
[Understanding null safety](/null-safety/understanding-null-safety#smarter-null-aware-methods)
for more details.
@@ -7122,6 +7121,52 @@
var y = x is int ? 0 : 1;
{% endprettify %}
+### sdk_version_never
+
+_The type 'Never' wasn't supported until version 2.X.0, but this code is
+required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when a reference to the class `Never`
+is found in code that has an SDK constraint whose lower bound is less than
+2.12.0. This class wasn't defined in earlier versions, so this code won't
+be able to run against earlier versions of the SDK.
+
+#### Examples
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.12.0:
+
+```yaml
+environment:
+ sdk: '>=2.5.0 <2.6.0'
+```
+
+In the package that has that pubspec, code like the following produces this
+diagnostic:
+
+{% prettify dart tag=pre+code %}
+[!Never!] n;
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the type to be used:
+
+```yaml
+environment:
+ sdk: '>=2.12.0 <2.13.0'
+```
+
+If you need to support older versions of the SDK, then rewrite the code to
+not reference this class:
+
+{% prettify dart tag=pre+code %}
+dynamic x;
+{% endprettify %}
+
### sdk_version_set_literal
_Set literals weren't supported until version 2.2, but this code is required to
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index 0dfcc55..cedc8b2 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -201,9 +201,10 @@
@override
final ir.StaticTypeContext staticTypeContext;
- ImpactBuilderBase(this.staticTypeContext, ir.ClassHierarchy classHierarchy,
- this.variableScopeModel)
- : super(staticTypeContext.typeEnvironment, classHierarchy);
+ ImpactBuilderBase(this.staticTypeContext, StaticTypeCacheImpl staticTypeCache,
+ ir.ClassHierarchy classHierarchy, this.variableScopeModel)
+ : super(
+ staticTypeContext.typeEnvironment, classHierarchy, staticTypeCache);
@override
void handleIntLiteral(ir.IntLiteral node) {
@@ -642,10 +643,15 @@
@override
final inferEffectivelyFinalVariableTypes;
- ImpactBuilder(ir.StaticTypeContext staticTypeContext,
- ir.ClassHierarchy classHierarchy, VariableScopeModel variableScopeModel,
- {this.useAsserts: false, this.inferEffectivelyFinalVariableTypes: true})
- : super(staticTypeContext, classHierarchy, variableScopeModel);
+ ImpactBuilder(
+ ir.StaticTypeContext staticTypeContext,
+ StaticTypeCacheImpl staticTypeCache,
+ ir.ClassHierarchy classHierarchy,
+ VariableScopeModel variableScopeModel,
+ {this.useAsserts: false,
+ this.inferEffectivelyFinalVariableTypes: true})
+ : super(staticTypeContext, staticTypeCache, classHierarchy,
+ variableScopeModel);
ImpactBuilderData computeImpact(ir.Member node) {
if (retainDataForTesting) {
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 4472ff8..13b7967 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -39,6 +39,29 @@
}
}
+class StaticTypeCacheImpl implements ir.StaticTypeCache {
+ final Map<ir.Expression, ir.DartType> _expressionTypes = {};
+ final Map<ir.ForInStatement, ir.DartType> _forInIteratorTypes = {};
+
+ @override
+ ir.DartType getExpressionType(
+ ir.Expression node, ir.StaticTypeContext context) {
+ return _expressionTypes[node] ??= node.getStaticTypeInternal(context);
+ }
+
+ @override
+ ir.DartType getForInIteratorType(
+ ir.ForInStatement node, ir.StaticTypeContext context) {
+ return _forInIteratorTypes[node] ??= node.getElementTypeInternal(context);
+ }
+
+ @override
+ ir.DartType getForInElementType(
+ ir.ForInStatement node, ir.StaticTypeContext context) {
+ throw UnsupportedError('StaticTypeCacheImpl.getForInElementType');
+ }
+}
+
/// Visitor that computes and caches the static type of expression while
/// visiting the full tree at expression level.
///
@@ -47,8 +70,7 @@
/// adds 'handleX' hooks for subclasses to handle individual expressions using
/// the readily compute static types of subexpressions.
abstract class StaticTypeVisitor extends StaticTypeBase {
- final Map<ir.Expression, ir.DartType> _expressionTypeCache = {};
- Map<ir.ForInStatement, ir.DartType> _forInIteratorTypeCache;
+ final StaticTypeCacheImpl _staticTypeCache;
Map<ir.Expression, TypeMap> typeMapsForTesting;
Map<ir.PropertyGet, RuntimeTypeUseData> _pendingRuntimeTypeUseData = {};
@@ -57,11 +79,13 @@
ThisInterfaceType _thisType;
ir.Library _currentLibrary;
- StaticTypeVisitor(ir.TypeEnvironment typeEnvironment, this.hierarchy)
+ StaticTypeVisitor(
+ ir.TypeEnvironment typeEnvironment, this.hierarchy, this._staticTypeCache)
: super(typeEnvironment);
StaticTypeCache getStaticTypeCache() {
- return new StaticTypeCache(_expressionTypeCache, _forInIteratorTypeCache);
+ return new StaticTypeCache(_staticTypeCache._expressionTypes,
+ _staticTypeCache._forInIteratorTypes);
}
/// If `true`, the effect of executing assert statements is taken into account
@@ -252,7 +276,7 @@
@override
ir.DartType visitPropertyGet(ir.PropertyGet node) {
ir.DartType receiverType = visitNode(node.receiver);
- ir.DartType resultType = _expressionTypeCache[node] =
+ ir.DartType resultType = _staticTypeCache._expressionTypes[node] =
_computePropertyGetType(node, receiverType);
receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
handlePropertyGet(node, receiverType, resultType);
@@ -490,7 +514,7 @@
ir.VariableGet get = new ir.VariableGet(variable)..parent = parent;
// Visit the newly created variable get.
handleVariableGet(get, argumentType);
- _expressionTypeCache[get] = argumentType;
+ _staticTypeCache._expressionTypes[get] = argumentType;
if (checkedParameterType == null) {
return get;
@@ -672,7 +696,7 @@
.promote(right.variable, right.variable.type, isTrue: true);
}
}
- _expressionTypeCache[node] = returnType;
+ _staticTypeCache._expressionTypes[node] = returnType;
handleMethodInvocation(node, receiverType, argumentTypes, returnType);
return returnType;
}
@@ -693,7 +717,7 @@
ir.SubtypeCheckMode.ignoringNullabilities),
"Unexpected promotion of ${node.variable} in ${node.parent}. "
"Expected ${node.promotedType}, found $promotedType");
- _expressionTypeCache[node] = promotedType;
+ _staticTypeCache._expressionTypes[node] = promotedType;
handleVariableGet(node, promotedType);
return promotedType;
}
@@ -740,7 +764,7 @@
ir.DartType returnType = ir.Substitution.fromPairs(
node.target.function.typeParameters, node.arguments.types)
.substituteType(node.target.function.returnType);
- _expressionTypeCache[node] = returnType;
+ _staticTypeCache._expressionTypes[node] = returnType;
handleStaticInvocation(node, argumentTypes, returnType);
return returnType;
}
@@ -756,7 +780,7 @@
.nonNullableRawType(node.target.enclosingClass))
: new ExactInterfaceType(node.target.enclosingClass,
ir.Nullability.nonNullable, node.arguments.types);
- _expressionTypeCache[node] = resultType;
+ _staticTypeCache._expressionTypes[node] = resultType;
handleConstructorInvocation(node, argumentTypes, resultType);
return resultType;
}
@@ -781,7 +805,7 @@
.substituteType(node.interfaceTarget.getterType);
}
}
- _expressionTypeCache[node] = resultType;
+ _staticTypeCache._expressionTypes[node] = resultType;
handleSuperPropertyGet(node, resultType);
return resultType;
}
@@ -817,7 +841,7 @@
node.arguments.types)
.substituteType(returnType);
}
- _expressionTypeCache[node] = returnType;
+ _staticTypeCache._expressionTypes[node] = returnType;
handleSuperMethodInvocation(node, argumentTypes, returnType);
return returnType;
}
@@ -936,7 +960,7 @@
ir.DartType visitInstantiation(ir.Instantiation node) {
ir.FunctionType expressionType = visitNode(node.expression);
ir.DartType resultType = _computeInstantiationType(node, expressionType);
- _expressionTypeCache[node] = resultType;
+ _staticTypeCache._expressionTypes[node] = resultType;
handleInstantiation(node, expressionType, resultType);
return resultType;
}
@@ -982,7 +1006,7 @@
ir.DartType resultType = operandType == typeEnvironment.nullType
? const ir.NeverType(ir.Nullability.nonNullable)
: operandType.withDeclaredNullability(ir.Nullability.nonNullable);
- _expressionTypeCache[node] = resultType;
+ _staticTypeCache._expressionTypes[node] = resultType;
return resultType;
}
@@ -1221,8 +1245,7 @@
.substituteType(member.getterType);
}
}
- _forInIteratorTypeCache ??= {};
- _forInIteratorTypeCache[node] = iteratorType;
+ _staticTypeCache._forInIteratorTypes[node] = iteratorType;
TypeMap beforeLoop = typeMap =
typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
visitNode(node.variable);
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index b176c21..05e5686 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -1429,12 +1429,15 @@
new ir.StaticTypeContext(node, typeEnvironment));
return converter.convert(impactData);
} else {
+ StaticTypeCacheImpl staticTypeCache = new StaticTypeCacheImpl();
KernelImpactBuilder builder = new KernelImpactBuilder(
this,
member,
reporter,
options,
- new ir.StaticTypeContext(node, typeEnvironment),
+ new ir.StaticTypeContext(node, typeEnvironment,
+ cache: staticTypeCache),
+ staticTypeCache,
variableScopeModel,
annotations,
_constantValuefier);
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 94d96a6..ad10c22 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -55,12 +55,14 @@
this.reporter,
this._options,
ir.StaticTypeContext staticTypeContext,
+ StaticTypeCacheImpl staticTypeCache,
VariableScopeModel variableScopeModel,
this._annotations,
this._constantValuefier)
: this.impactBuilder = new ResolutionWorldImpactBuilder(
elementMap.commonElements.dartTypes, currentMember),
- super(staticTypeContext, elementMap.classHierarchy, variableScopeModel);
+ super(staticTypeContext, staticTypeCache, elementMap.classHierarchy,
+ variableScopeModel);
@override
CommonElements get commonElements => elementMap.commonElements;
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 2bc723d..eb961d7 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -25,6 +25,7 @@
import '../ir/impact.dart';
import '../ir/modular.dart';
import '../ir/scope.dart' show ScopeModel;
+import '../ir/static_type.dart';
import '../js_backend/annotations.dart';
import '../js_backend/backend_impact.dart';
import '../js_backend/backend_usage.dart';
@@ -439,8 +440,11 @@
// depend on metadata, so these parts of the impact data need to be
// computed during conversion to [ResolutionImpact].
impactBuilderData = _compilerTask.measureSubtask('worldImpact', () {
+ StaticTypeCacheImpl staticTypeCache = StaticTypeCacheImpl();
ImpactBuilder builder = ImpactBuilder(
- ir.StaticTypeContext(node, _elementMap.typeEnvironment),
+ ir.StaticTypeContext(node, _elementMap.typeEnvironment,
+ cache: staticTypeCache),
+ staticTypeCache,
_elementMap.classHierarchy,
scopeModel.variableScopeModel,
useAsserts: _elementMap.options.enableUserAssertions,
diff --git a/pkg/compiler/test/analyses/analysis_helper.dart b/pkg/compiler/test/analyses/analysis_helper.dart
index eee894d..3261133 100644
--- a/pkg/compiler/test/analyses/analysis_helper.dart
+++ b/pkg/compiler/test/analyses/analysis_helper.dart
@@ -86,7 +86,8 @@
: assert(evaluationMode != null),
super(
new ir.TypeEnvironment(new ir.CoreTypes(component), classHierarchy),
- classHierarchy) {
+ classHierarchy,
+ new StaticTypeCacheImpl()) {
_constantEvaluator = new Dart2jsConstantEvaluator(
typeEnvironment, const ir.SimpleErrorReporter().report,
evaluationMode: evaluationMode);
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index c31877f..275c2ad 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -89,14 +89,16 @@
args = List.from(args)..remove('--disable-dartdev-analytics');
}
- // These flags have a format that can't be handled by package:args, so while
- // they are valid flags we'll assume the VM has verified them by this point.
- args = args
- .where(
- (element) => !(element.contains('--observe') ||
- element.contains('--enable-vm-service')),
- )
- .toList();
+ if (args.contains('run')) {
+ // These flags have a format that can't be handled by package:args, so while
+ // they are valid flags we'll assume the VM has verified them by this point.
+ args = args
+ .where(
+ (element) => !(element.contains('--observe') ||
+ element.contains('--enable-vm-service')),
+ )
+ .toList();
+ }
// If ... help pub ... is in the args list, remove 'help', and add '--help'
// to the end of the list. This will make it possible to use the help
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index c380bcd..f33cb83 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -221,4 +221,18 @@
expect(result.stderr, contains('Unhandled exception'));
expect(result.exitCode, 255);
});
+
+ test('does not interpret VM flags provided after script', () async {
+ p = project(mainSrc: 'void main() { assert(false); }');
+
+ // Any VM flags passed after the script shouldn't be interpreted by the VM.
+ ProcessResult result = p.runSync('run', [
+ p.relativeFilePath,
+ '--enable-asserts',
+ ]);
+
+ expect(result.stdout, isEmpty);
+ expect(result.stderr, isEmpty);
+ expect(result.exitCode, 0);
+ });
}
diff --git a/pkg/dartfix/.gitignore b/pkg/dartfix/.gitignore
deleted file mode 100644
index 113d783..0000000
--- a/pkg/dartfix/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-*.iml
-.dart_tool
-.packages
-pubspec.lock
diff --git a/pkg/dartfix/CHANGELOG.md b/pkg/dartfix/CHANGELOG.md
deleted file mode 100644
index fb292fa..0000000
--- a/pkg/dartfix/CHANGELOG.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# 0.1.8
-* The dartfix package has been deprecated. The functionality has been moved to
- the new `dart fix` command that's included in the SDK.
-
-# 0.1.7
-* Improve experimental non-nullable migration support.
-* Extract some nnbd migration implementation components from the dartfix
- package.
-
-# 0.1.6
-* Improve experimental non-nullable migration support.
-
-# 0.1.5
-* Add command line options for selecting/excluding fixes to apply (`--fix`,
- `--excludeFix`, and `--required`). Call with `--help` for more details.
-* Add a `--color` option for printing messages with ANSI colors. This defaults
- to true if the terminal supports ANSI colors.
-* Add a `--pedantic` option for specifying fixes relating to the [pedantic]
- lints.
-* Add experimental non-nullable migration support.
-
-[pedantic]: https://pub.dev/packages/pedantic
-
-# 0.1.4
- * update protocol version constraints
-
-# 0.1.3
- * update SDK constraints
-
-# 0.1.2
- * update SDK constraints
- * add example.dart showing what can be "fixed"
-
-# 0.1.1
- * Remove reading dartfix version from pubspec
-
-# 0.1.0
- * Initial version
diff --git a/pkg/dartfix/LICENSE b/pkg/dartfix/LICENSE
deleted file mode 100644
index a9ab5f8..0000000
--- a/pkg/dartfix/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2018, the Dart 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.
\ No newline at end of file
diff --git a/pkg/dartfix/README.md b/pkg/dartfix/README.md
deleted file mode 100644
index a3f0493..0000000
--- a/pkg/dartfix/README.md
+++ /dev/null
@@ -1,82 +0,0 @@
-`dartfix` is a command-line tool for migrating your Dart code
-to use newer syntax styles.
-
-## Usage
-
-> **Important:**
-> Save a copy of your source code before making changes with `dartfix`.
-> Unlike [dartfmt][], which makes only safe changes (usually to whitespace),
-> `dartfix` can make changes that you might need to undo or modify.
-
-Before you can use the `dartfix` tool, you need to
-[install it](#installing-and-updating-dartfix), as described below.
-Then invoke it with the name of the directory that you want to update.
-When you're ready to make the suggested changes,
-add the `--overwrite` option.
-
-```terminal
-$ dartfix examples/misc
-... summary of recommended changes ...
-$ dartfix examples/misc --overwrite
-```
-
-## Features
-`dartfix` applies different types of "fixes" to migrate your Dart code.
-By default, all fixes are applied, but you can select only the specific fixes you
-want. See `dartfix --help` for more about the available command line options.
-
-Some of the fixes that you can apply are "required" in that the Dart language
-is changing and at some point the old syntax will no longer be supported.
-To only apply these changes, pass the `--required` option on the command line.
-The required fixes include:
-
-* Find classes used as mixins, and convert them to use the `mixin` keyword
- instead of `class`.
- Mixin support is one of the [features added to Dart in 2.1][].
- At some point in the future, the Dart team plans
- to disallow using classes as mixins.
-
-* Move named constructor type arguments from the name to the type. <br>
- For example, given `class A<T> { A.from(Object obj) { } }`,
- `dartfix` changes constructor invocations in the following way:
-
- ```
- Original code:
- A.from<String>(anObject) // Invokes the `A.from` named constructor.
-
- Code produced by dartfix:
- A<String>.from(anObject) // Same, but the type is directly after `A`.
- ```
-
-Other changes are recommended but not required. These include:
-
-* Find `double` literals that end in `.0`, and remove the `.0`.
- Language support for this was [added in Dart in 2.1][].
-
-## Installing and updating dartfix
-
-The easiest way to use `dartfix` is to [globally install][] it,
-so that it can be [in your path][PATH]:
-
-```terminal
-$ pub global activate dartfix
-```
-
-Use the same command to update `dartfix`.
-We recommend updating `dartfix` whenever you update your Dart SDK
-or when a new feature is released.
-
-## Filing issues
-
-If you want a new fix, first look at [dartfix issues][]
-and star the fixes you want.
-If no issue exists for the fix, [create a GitHub issue.][new issue]
-
-[dartfix]: https://pub.dev/packages/dartfix
-[dartfmt]: https://dart.dev/tools/dartfmt
-[added in Dart in 2.1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#210---2018-11-15
-[features added to Dart in 2.1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#210---2018-11-15
-[globally install]: https://dart.dev/tools/pub/cmd/pub-global
-[new issue]: https://github.com/dart-lang/sdk/issues/new?title=dartfix%20request%3A%20%3CSUMMARIZE%20REQUEST%20HERE%3E
-[dartfix issues]: https://github.com/dart-lang/sdk/issues?q=is%3Aissue+is%3Aopen+label%3Aanalyzer-dartfix
-[PATH]: https://dart.dev/tools/pub/cmd/pub-global#running-a-script-from-your-path
diff --git a/pkg/dartfix/analysis_options.yaml b/pkg/dartfix/analysis_options.yaml
deleted file mode 100644
index 4be2194..0000000
--- a/pkg/dartfix/analysis_options.yaml
+++ /dev/null
@@ -1,42 +0,0 @@
-include: package:pedantic/analysis_options.1.8.0.yaml
-
-analyzer:
- strong-mode:
- implicit-casts: false
- errors:
- # Increase the severity of the unused_import hint.
- unused_import: warning
- unnecessary_brace_in_string_interps: warning
- # There are many pre-existing violations; this lint may not work well with
- # the Analyzer team's style.
- omit_local_variable_types: ignore
- # Turn off the prefer_is_empty lint so that it can be used in the example tests
- # and not be reported during normal package analysis.
- prefer_is_empty: ignore
-
-linter:
- rules:
- - await_only_futures
- - directives_ordering
- - empty_statements
- - unnecessary_brace_in_string_interps
- #
- # Delta from pedantic 1.8.0 to 1.9.0
- #
- #- always_declare_return_types # 17
- - always_require_non_null_named_parameters
- - annotate_overrides
- - avoid_null_checks_in_equality_operators
- - camel_case_extensions
- #- omit_local_variable_types # 44
- - prefer_adjacent_string_concatenation
- - prefer_collection_literals
- - prefer_conditional_assignment
- #- prefer_final_fields # 1
- - prefer_for_elements_to_map_fromIterable
- - prefer_generic_function_type_aliases
- #- prefer_if_null_operators # 2
- - prefer_single_quotes
- - prefer_spread_collections
- - unnecessary_this
- - use_function_type_syntax_for_parameters
diff --git a/pkg/dartfix/bin/dartfix.dart b/pkg/dartfix/bin/dartfix.dart
deleted file mode 100644
index d611474..0000000
--- a/pkg/dartfix/bin/dartfix.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env dart
-// 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:dartfix/src/driver.dart';
-
-/// The entry point for dartfix.
-void main(List<String> args) async {
- Driver starter = Driver();
-
- // Wait for the starter to complete.
- await starter.start(args);
-}
diff --git a/pkg/dartfix/example/example.dart b/pkg/dartfix/example/example.dart
deleted file mode 100644
index 6093104..0000000
--- a/pkg/dartfix/example/example.dart
+++ /dev/null
@@ -1,25 +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.
-
-// This file contains code that is modified by running dartfix.
-// After running dartfix, this content matches a file in the "fixed" directory.
-
-// Dart will automatically convert int literals to doubles.
-// Running dartfix converts this double literal to an int
-// if --double-to-int is specified on the command line.
-const double myDouble = 4.0;
-
-// This class is used as a mixin but does not use the new mixin syntax.
-// Running dartfix converts this class to use the new syntax.
-class MyMixin {
- final someValue = myDouble;
-}
-
-class MyClass with MyMixin {}
-
-void main(List<String> args) {
- if (args.length == 0) {
- print('myDouble = ${MyClass().someValue}');
- }
-}
diff --git a/pkg/dartfix/fixed/example_default.dart b/pkg/dartfix/fixed/example_default.dart
deleted file mode 100644
index 10bd52c..0000000
--- a/pkg/dartfix/fixed/example_default.dart
+++ /dev/null
@@ -1,25 +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.
-
-// This file contains code that has been modified by running dartfix.
-// See example.dart for the original unmodified code.
-
-// Dart will automatically convert int literals to doubles.
-// Running dartfix converts this double literal to an int
-// if --double-to-int is specified on the command line.
-const double myDouble = 4;
-
-// This class is used as a mixin but does not use the new mixin syntax.
-// Running dartfix converts this class to use the new syntax.
-mixin MyMixin {
- final someValue = myDouble;
-}
-
-class MyClass with MyMixin {}
-
-void main(List<String> args) {
- if (args.length == 0) {
- print('myDouble = ${MyClass().someValue}');
- }
-}
diff --git a/pkg/dartfix/fixed/example_pedantic.dart b/pkg/dartfix/fixed/example_pedantic.dart
deleted file mode 100644
index 5337a5b..0000000
--- a/pkg/dartfix/fixed/example_pedantic.dart
+++ /dev/null
@@ -1,25 +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.
-
-// This file contains code that has been modified by running dartfix.
-// See example.dart for the original unmodified code.
-
-// Dart will automatically convert int literals to doubles.
-// Running dartfix converts this double literal to an int
-// if --double-to-int is specified on the command line.
-const double myDouble = 4.0;
-
-// This class is used as a mixin but does not use the new mixin syntax.
-// Running dartfix converts this class to use the new syntax.
-class MyMixin {
- final someValue = myDouble;
-}
-
-class MyClass with MyMixin {}
-
-void main(List<String> args) {
- if (args.isEmpty) {
- print('myDouble = ${MyClass().someValue}');
- }
-}
diff --git a/pkg/dartfix/fixed/example_prefer_is_empty.dart b/pkg/dartfix/fixed/example_prefer_is_empty.dart
deleted file mode 100644
index 5337a5b..0000000
--- a/pkg/dartfix/fixed/example_prefer_is_empty.dart
+++ /dev/null
@@ -1,25 +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.
-
-// This file contains code that has been modified by running dartfix.
-// See example.dart for the original unmodified code.
-
-// Dart will automatically convert int literals to doubles.
-// Running dartfix converts this double literal to an int
-// if --double-to-int is specified on the command line.
-const double myDouble = 4.0;
-
-// This class is used as a mixin but does not use the new mixin syntax.
-// Running dartfix converts this class to use the new syntax.
-class MyMixin {
- final someValue = myDouble;
-}
-
-class MyClass with MyMixin {}
-
-void main(List<String> args) {
- if (args.isEmpty) {
- print('myDouble = ${MyClass().someValue}');
- }
-}
diff --git a/pkg/dartfix/fixed/example_required.dart b/pkg/dartfix/fixed/example_required.dart
deleted file mode 100644
index 9324f22..0000000
--- a/pkg/dartfix/fixed/example_required.dart
+++ /dev/null
@@ -1,25 +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.
-
-// This file contains code that has been modified by running dartfix.
-// See example.dart for the original unmodified code.
-
-// Dart will automatically convert int literals to doubles.
-// Running dartfix converts this double literal to an int
-// if --double-to-int is specified on the command line.
-const double myDouble = 4.0;
-
-// This class is used as a mixin but does not use the new mixin syntax.
-// Running dartfix converts this class to use the new syntax.
-mixin MyMixin {
- final someValue = myDouble;
-}
-
-class MyClass with MyMixin {}
-
-void main(List<String> args) {
- if (args.length == 0) {
- print('myDouble = ${MyClass().someValue}');
- }
-}
diff --git a/pkg/dartfix/lib/handler/analysis_complete_handler.dart b/pkg/dartfix/lib/handler/analysis_complete_handler.dart
deleted file mode 100644
index e45b8a8..0000000
--- a/pkg/dartfix/lib/handler/analysis_complete_handler.dart
+++ /dev/null
@@ -1,31 +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.
-//
-// This file has been automatically generated. Please do not edit it manually.
-// To regenerate the file, use the script
-// "pkg/analysis_server/tool/spec/generate_files".
-
-import 'dart:async';
-
-import 'package:analysis_server_client/handler/notification_handler.dart';
-import 'package:analysis_server_client/protocol.dart';
-
-/// [AnalysisCompleteHandler] listens to analysis server notifications
-/// and detects when analysis has finished.
-mixin AnalysisCompleteHandler on NotificationHandler {
- Completer<void> _analysisComplete;
-
- @override
- void onServerStatus(ServerStatusParams params) {
- if (params.analysis != null && !params.analysis.isAnalyzing) {
- _analysisComplete?.complete();
- _analysisComplete = null;
- }
- }
-
- Future<void> analysisComplete() {
- _analysisComplete ??= Completer<void>();
- return _analysisComplete.future;
- }
-}
diff --git a/pkg/dartfix/lib/listener/bad_message_listener.dart b/pkg/dartfix/lib/listener/bad_message_listener.dart
deleted file mode 100644
index 03cb102..0000000
--- a/pkg/dartfix/lib/listener/bad_message_listener.dart
+++ /dev/null
@@ -1,53 +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.
-
-import 'package:analysis_server_client/listener/server_listener.dart';
-
-/// [BadMessageListener] throws an exception if the [Client] receives bad data.
-mixin BadMessageListener on ServerListener {
- /// True if we've received bad data from the server.
- bool _receivedBadDataFromServer = false;
-
- void throwDelayedException(String prefix, String details) {
- if (!_receivedBadDataFromServer) {
- _receivedBadDataFromServer = true;
- // Give the server 1 second to continue outputting bad data
- // such as outputting a stacktrace.
- Future.delayed(Duration(seconds: 1), () {
- throw '$prefix $details';
- });
- }
- }
-
- @override
- void badMessage(String trimmedLine, exception) {
- super.badMessage(trimmedLine, exception);
- throwDelayedException('JSON decode failure', '$exception');
- }
-
- @override
- void errorMessage(String line) {
- super.errorMessage(line);
- throwDelayedException('ERR:', line);
- }
-
- @override
- void unexpectedMessage(Map<String, dynamic> message) {
- super.unexpectedMessage(message);
- throwDelayedException(
- 'BAD DATA FROM SERVER:', 'Unexpected message from server');
- }
-
- @override
- void unexpectedResponse(Map<String, dynamic> message, id) {
- super.unexpectedResponse(message, id);
- throw 'Unexpected response from server: id=$id';
- }
-
- @override
- void unexpectedStop(int exitCode) {
- super.unexpectedStop(exitCode);
- throwDelayedException('Server terminated with exit code', '$exitCode');
- }
-}
diff --git a/pkg/dartfix/lib/listener/recording_listener.dart b/pkg/dartfix/lib/listener/recording_listener.dart
deleted file mode 100644
index a97120c..0000000
--- a/pkg/dartfix/lib/listener/recording_listener.dart
+++ /dev/null
@@ -1,58 +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.
-
-import 'package:analysis_server_client/listener/server_listener.dart';
-import 'package:analysis_server_client/server.dart';
-import 'package:dartfix/listener/bad_message_listener.dart';
-import 'package:dartfix/listener/timed_listener.dart';
-
-/// [RecordingListener] caches all messages exchanged with the server
-/// and print them if a problem occurs.
-///
-/// This is primarily used when testing and debugging the analysis server.
-class RecordingListener with ServerListener, BadMessageListener, TimedListener {
- /// True if we are currently printing out messages exchanged with the server.
- bool _echoMessages = false;
-
- /// Messages which have been exchanged with the server; we buffer these
- /// up until the test finishes, so that they can be examined in the debugger
- /// or printed out in response to a call to [echoMessages].
- final _messages = <String>[];
-
- /// Print out any messages exchanged with the server. If some messages have
- /// already been exchanged with the server, they are printed out immediately.
- void echoMessages() {
- if (_echoMessages) {
- return;
- }
- _echoMessages = true;
- for (String line in _messages) {
- print(line);
- }
- }
-
- /// Called when the [Server] is terminating the server process
- /// rather than requesting that the server stop itself.
- @override
- void killingServerProcess(String reason) {
- echoMessages();
- super.killingServerProcess(reason);
- }
-
- /// Log a timed message about interaction with the server.
- @override
- void logTimed(double elapseTime, String prefix, String details) {
- String line = '$elapseTime: $prefix $details';
- if (_echoMessages) {
- print(line);
- }
- _messages.add(line);
- }
-
- @override
- void throwDelayedException(String prefix, String details) {
- echoMessages();
- super.throwDelayedException(prefix, details);
- }
-}
diff --git a/pkg/dartfix/lib/listener/timed_listener.dart b/pkg/dartfix/lib/listener/timed_listener.dart
deleted file mode 100644
index ab41744..0000000
--- a/pkg/dartfix/lib/listener/timed_listener.dart
+++ /dev/null
@@ -1,39 +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.
-
-import 'package:analysis_server_client/listener/server_listener.dart';
-
-/// [TimedListener] appends a timestamp (seconds since server startup)
-/// to each logged interaction with the server.
-mixin TimedListener on ServerListener {
- /// Stopwatch that we use to generate timing information for debug output.
- final Stopwatch _time = Stopwatch();
-
- /// The [currentElapseTime] at which the last communication was received from
- /// the server or `null` if no communication has been received.
- double lastCommunicationTime;
-
- /// The current elapse time (seconds) since the server was started.
- double get currentElapseTime => _time.elapsedTicks / _time.frequency;
-
- @override
- void log(String prefix, String details) {
- logTimed(currentElapseTime, prefix, details);
- }
-
- /// Log a timed message about interaction with the server.
- void logTimed(double elapseTime, String prefix, String details);
-
- @override
- void messageReceived(String json) {
- lastCommunicationTime = currentElapseTime;
- super.messageReceived(json);
- }
-
- @override
- void startingServer(String dartBinary, List<String> arguments) {
- _time.start();
- super.startingServer(dartBinary, arguments);
- }
-}
diff --git a/pkg/dartfix/lib/src/context.dart b/pkg/dartfix/lib/src/context.dart
deleted file mode 100644
index dd28a47..0000000
--- a/pkg/dartfix/lib/src/context.dart
+++ /dev/null
@@ -1,24 +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.
-
-import 'dart:io' as io;
-
-/// The context for dartfix.
-class Context {
- String get workingDir => io.Directory.current.path;
-
- bool exists(String filePath) {
- return io.FileSystemEntity.typeSync(filePath) !=
- io.FileSystemEntityType.notFound;
- }
-
- void exit(int code) {
- io.exit(code);
- }
-
- bool isDirectory(String filePath) {
- return io.FileSystemEntity.typeSync(filePath) ==
- io.FileSystemEntityType.directory;
- }
-}
diff --git a/pkg/dartfix/lib/src/driver.dart b/pkg/dartfix/lib/src/driver.dart
deleted file mode 100644
index 26f7ce93..0000000
--- a/pkg/dartfix/lib/src/driver.dart
+++ /dev/null
@@ -1,508 +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.
-
-import 'dart:io' show File, Platform;
-
-import 'package:analysis_server_client/handler/connection_handler.dart';
-import 'package:analysis_server_client/handler/notification_handler.dart';
-import 'package:analysis_server_client/listener/server_listener.dart';
-import 'package:analysis_server_client/protocol.dart';
-import 'package:analysis_server_client/server.dart';
-import 'package:cli_util/cli_logging.dart';
-import 'package:dartfix/handler/analysis_complete_handler.dart';
-import 'package:dartfix/listener/bad_message_listener.dart';
-import 'package:dartfix/src/context.dart';
-import 'package:dartfix/src/options.dart';
-import 'package:dartfix/src/util.dart';
-import 'package:path/path.dart' as path;
-import 'package:pub_semver/pub_semver.dart';
-
-import 'migrate/display.dart';
-import 'util.dart';
-
-class Driver {
- Context context;
- _Handler handler;
- Logger logger;
- Server server;
-
- bool force;
- bool overwrite;
- List<String> targets;
- EditDartfixResult result;
-
- Ansi get ansi => logger.ansi;
-
- /// Apply the fixes that were computed.
- void applyFixes() {
- for (SourceFileEdit fileEdit in result.edits) {
- final file = File(fileEdit.file);
- String code = file.existsSync() ? file.readAsStringSync() : '';
- code = SourceEdit.applySequence(code, fileEdit.edits);
- file.writeAsStringSync(code);
- }
- }
-
- bool checkIfChangesShouldBeApplied(EditDartfixResult result) {
- logger.stdout('');
- if (result.hasErrors) {
- logger.stdout('WARNING: The analyzed source contains errors'
- ' that might affect the accuracy of these changes.');
- logger.stdout('');
- if (!force) {
- logger.stdout('Rerun with --$forceOption to apply these changes.');
- return false;
- }
- } else if (!overwrite && !force) {
- logger.stdout('Rerun with --$overwriteOption to apply these changes.');
- return false;
- }
- return true;
- }
-
- /// Check if the specified options is supported by the version of analysis
- /// server being run and return `true` if they are.
- /// Display an error message and return `false` if not.
- bool checkIfSelectedOptionsAreSupported(Options options) {
- if (handler.serverProtocolVersion.compareTo(Version(1, 27, 2)) >= 0) {
- return true;
- }
- if (options.pedanticFixes) {
- _unsupportedOption(pedanticOption);
- return false;
- }
- if (handler.serverProtocolVersion.compareTo(Version(1, 22, 2)) >= 0) {
- return true;
- }
- if (options.excludeFixes.isNotEmpty) {
- _unsupportedOption(excludeFixOption);
- return false;
- }
- if (options.includeFixes.isNotEmpty) {
- _unsupportedOption(includeFixOption);
- return false;
- }
- if (options.showHelp) {
- return false;
- }
- return true;
- }
-
- void printAndApplyFixes() {
- showDescriptions('Recommended changes that cannot be automatically applied',
- result.otherSuggestions);
- showDetails(result.details);
- if (result.edits.isEmpty) {
- logger.stdout('');
- logger.stdout(result.otherSuggestions.isNotEmpty
- ? 'None of the recommended changes can be automatically applied.'
- : 'No recommended changes.');
- return;
- }
- logger.stdout('');
- logger.stdout(ansi.emphasized('Files to be changed:'));
- for (SourceFileEdit fileEdit in result.edits) {
- logger.stdout(' ${_relativePath(fileEdit.file)}');
- }
- if (checkIfChangesShouldBeApplied(result)) {
- applyFixes();
- logger.stdout(ansi.emphasized('Changes have been applied.'));
- }
- }
-
- Future<EditDartfixResult> requestFixes(
- Options options, {
- Progress progress,
- }) async {
- Future isAnalysisComplete = handler.analysisComplete();
-
- final params = EditDartfixParams(options.targets);
- if (options.excludeFixes.isNotEmpty) {
- params.excludedFixes = options.excludeFixes;
- }
- if (options.includeFixes.isNotEmpty) {
- params.includedFixes = options.includeFixes;
- }
- if (options.pedanticFixes) {
- params.includePedanticFixes = true;
- }
- Map<String, dynamic> json =
- await server.send(EDIT_REQUEST_DARTFIX, params.toJson());
-
- // TODO(danrubel): This is imprecise signal for determining when all
- // analysis error notifications have been received. Consider adding a new
- // notification indicating that the server is idle (all requests processed,
- // all analysis complete, all notifications sent).
- await isAnalysisComplete;
-
- progress.finish(showTiming: true);
- ResponseDecoder decoder = ResponseDecoder(null);
- return EditDartfixResult.fromJson(decoder, 'result', json);
- }
-
- /// Return `true` if the changes should be applied.
- bool shouldApplyFixes(EditDartfixResult result) {
- return overwrite || force;
- }
-
- void showDescriptions(String title, List<DartFixSuggestion> suggestions) {
- if (suggestions.isNotEmpty) {
- logger.stdout('');
- logger.stdout(ansi.emphasized('$title:'));
- List<DartFixSuggestion> sorted = List.from(suggestions)
- ..sort(compareSuggestions);
- for (DartFixSuggestion suggestion in sorted) {
- final msg = StringBuffer();
- msg.write(' ${toSentenceFragment(suggestion.description)}');
- final loc = suggestion.location;
- if (loc != null) {
- msg.write(' • ${_relativePath(loc.file)}');
- msg.write(' • ${loc.startLine}:${loc.startColumn}');
- }
- logger.stdout(msg.toString());
- }
- }
- }
-
- void showDetails(List<String> details) {
- if (details == null || details.isEmpty) {
- return;
- }
- logger.stdout('''
-
-Analysis Details:
-''');
- for (String detail in details) {
- logger.stdout('''
- • $detail
-''');
- }
- }
-
- void showFix(DartFix fix) {
- logger.stdout('''
-
-• ${ansi.emphasized(fix.name)}''');
- if (fix.description != null) {
- for (String line in _indentAndWrapDescription(fix.description)) {
- logger.stdout(line);
- }
- }
- }
-
- Future<EditGetDartfixInfoResult> showFixes({Progress progress}) async {
- Map<String, dynamic> json = await server.send(
- EDIT_REQUEST_GET_DARTFIX_INFO, EditGetDartfixInfoParams().toJson());
- progress?.finish(showTiming: true);
- ResponseDecoder decoder = ResponseDecoder(null);
- final result = EditGetDartfixInfoResult.fromJson(decoder, 'result', json);
-
- final fixes = List<DartFix>.from(result.fixes)
- ..sort((f1, f2) => f1.name.compareTo(f2.name));
-
- logger.stdout('''
-
-These fixes can be enabled using --$includeFixOption:''');
-
- fixes
- ..sort(compareFixes)
- ..forEach(showFix);
-
- return result;
- }
-
- Future start(
- List<String> args, {
- Context testContext,
- Logger testLogger,
- }) async {
- final Options options = Options.parse(args, testContext, testLogger);
-
- force = options.force;
- overwrite = options.overwrite;
- targets = options.targets;
- context = testContext ?? options.context;
- logger = testLogger ?? options.logger;
- server = Server(listener: _Listener(logger));
- handler = _Handler(this, context);
-
- // Start showing progress before we start the analysis server.
- Progress progress;
- if (options.showHelp) {
- progress = logger.progress('${ansi.emphasized('Listing fixes')}');
- } else {
- progress = logger.progress('${ansi.emphasized('Calculating fixes')}');
- }
-
- if (!await startServer(options)) {
- context.exit(16);
- }
-
- if (!checkIfSelectedOptionsAreSupported(options)) {
- await server.stop();
- context.exit(1);
- }
-
- if (options.showHelp) {
- try {
- await showFixes(progress: progress);
- } finally {
- await server.stop();
- }
- context.exit(0);
- }
-
- if (options.includeFixes.isEmpty && !options.pedanticFixes) {
- logger.stdout('No fixes specified.');
- context.exit(1);
- }
-
- Future serverStopped;
- try {
- await startServerAnalysis(options);
- result = await requestFixes(options, progress: progress);
- var fileEdits = result.edits;
- var editCount = 0;
- for (SourceFileEdit fileEdit in fileEdits) {
- editCount += fileEdit.edits.length;
- }
- logger.stdout('Found $editCount changes in ${fileEdits.length} files.');
-
- previewFixes(logger, result);
-
- //
- // Stop the server.
- //
- serverStopped = server.stop();
-
- logger.stdout('');
-
- // Check if we should apply fixes.
- if (result.edits.isEmpty) {
- logger.stdout(result.otherSuggestions.isNotEmpty
- ? 'None of the recommended changes can be automatically applied.'
- : 'There are no recommended changes.');
- } else if (shouldApplyFixes(result)) {
- applyFixes();
- logger.stdout('Changes have been applied.');
- } else {
- logger.stdout('Re-run with --overwrite to apply the above changes.');
- }
- await serverStopped;
- } finally {
- // If we didn't already try to stop the server, then stop it now.
- if (serverStopped == null) {
- await server.stop();
- }
- }
- }
-
- Future<bool> startServer(Options options) async {
- // Automatically run analysis server from source
- // if this command line tool is being run from source within the SDK repo.
- String serverPath = options.serverSnapshot ?? findServerPath();
- if (options.verbose) {
- logger.trace('''
-Dart SDK version ${Platform.version}
- ${Platform.resolvedExecutable}
-dartfix
- ${Platform.script.toFilePath()}
-analysis server
- $serverPath
-''');
- }
- await server.start(
- clientId: 'dartfix',
- clientVersion: 'unspecified',
- sdkPath: options.sdkPath,
- serverPath: serverPath,
- );
- server.listenToOutput(notificationProcessor: handler.handleEvent);
- return handler.serverConnected(timeLimit: const Duration(seconds: 30));
- }
-
- Future<Progress> startServerAnalysis(
- Options options, {
- Progress progress,
- }) async {
- logger.trace('');
- logger.trace('Setup analysis');
- await server.send(SERVER_REQUEST_SET_SUBSCRIPTIONS,
- ServerSetSubscriptionsParams([ServerService.STATUS]).toJson());
- await server.send(
- ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS,
- AnalysisSetAnalysisRootsParams(
- options.targets,
- const [],
- ).toJson());
- return progress;
- }
-
- List<String> _indentAndWrapDescription(String description) =>
- description.split('\n').map((line) => ' $line').toList();
-
- String _relativePath(String filePath) {
- for (String target in targets) {
- if (filePath.startsWith(target)) {
- return filePath.substring(target.length + 1);
- }
- }
- return filePath;
- }
-
- void _unsupportedOption(String option) {
- final version = handler.serverProtocolVersion.toString();
- logger.stderr('''
-The --$option option is not supported by analysis server version $version.
-Please upgrade to a newer version of the Dart SDK to use this option.''');
- }
-
- void previewFixes(
- Logger logger,
- EditDartfixResult results,
- ) {
- final Ansi ansi = logger.ansi;
-
- Map<String, List<DartFixSuggestion>> fileSuggestions = {};
- for (DartFixSuggestion suggestion in results.suggestions) {
- String file = suggestion.location.file;
- fileSuggestions.putIfAbsent(file, () => <DartFixSuggestion>[]);
- fileSuggestions[file].add(suggestion);
- }
-
- // present a diff-like view
- for (SourceFileEdit sourceFileEdit in results.edits) {
- String file = sourceFileEdit.file;
- String relPath = path.relative(file);
- int count = sourceFileEdit.edits.length;
-
- logger.stdout('');
- logger.stdout('${ansi.emphasized(relPath)} '
- '($count ${pluralize('change', count)}):');
-
- String source;
- try {
- source = File(file).readAsStringSync();
- } catch (_) {}
-
- if (source == null) {
- logger.stdout(' (unable to retrieve source for file)');
- } else {
- SourcePrinter sourcePrinter = SourcePrinter(source);
-
- List<SourceEdit> edits = sortEdits(sourceFileEdit);
-
- // Apply edits.
- sourcePrinter.applyEdits(edits);
-
- // Render the changed lines.
- sourcePrinter.processChangedLines((lineNumber, lineText) {
- String prefix = ' line ${lineNumber.toString().padRight(3)} •';
- logger.stdout('$prefix ${lineText.trim()}');
- });
- }
- }
- }
-}
-
-class _Handler
- with NotificationHandler, ConnectionHandler, AnalysisCompleteHandler {
- final Driver driver;
- final Logger logger;
- final Context context;
-
- @override
- final Server server;
- Version serverProtocolVersion;
-
- _Handler(this.driver, this.context)
- : logger = driver.logger,
- server = driver.server;
-
- @override
- bool checkServerProtocolVersion(Version version) {
- serverProtocolVersion = version;
- return super.checkServerProtocolVersion(version);
- }
-
- @override
- void onAnalysisErrors(AnalysisErrorsParams params) {
- List<AnalysisError> errors = params.errors;
- bool foundAtLeastOneError = false;
- for (AnalysisError error in errors) {
- if (shouldShowError(error)) {
- if (!foundAtLeastOneError) {
- foundAtLeastOneError = true;
- logger.stdout('${driver._relativePath(params.file)}:');
- }
- Location loc = error.location;
- logger.stdout(' ${toSentenceFragment(error.message)}'
- ' • ${loc.startLine}:${loc.startColumn}');
- }
- }
- super.onAnalysisErrors(params);
- // Analysis errors are non-fatal; no need to exit.
- }
-
- @override
- void onFailedToConnect() {
- logger.stderr('Failed to connect to server');
- super.onFailedToConnect();
- // Exiting on connection failure is already handled by [Driver.start].
- }
-
- @override
- void onProtocolNotSupported(Version version) {
- logger.stderr('Expected protocol version $PROTOCOL_VERSION,'
- ' but found $version');
- final expectedVersion = Version.parse(PROTOCOL_VERSION);
- if (version > expectedVersion) {
- logger.stdout('''
-This version of dartfix is incompatible with the current Dart SDK.
-Try installing a newer version of dartfix by running:
-
- pub global activate dartfix
-''');
- } else {
- logger.stdout('''
-This version of dartfix is too new to be used with the current Dart SDK. Try
-upgrading the Dart SDK to a newer version or installing an older version of
-dartfix using:
-
- pub global activate dartfix <version>
-''');
- }
- super.onProtocolNotSupported(version);
- // This is handled by the connection failure case; no need to exit here.
- }
-
- @override
- void onServerError(ServerErrorParams params) {
- if (params.isFatal) {
- logger.stderr('Fatal Server Error: ${params.message}');
- } else {
- logger.stderr('Server Error: ${params.message}');
- }
- if (params.stackTrace != null) {
- logger.stderr(params.stackTrace);
- }
- super.onServerError(params);
- // Server is stopped by super method, so we can safely exit here.
- context.exit(16);
- }
-}
-
-class _Listener with ServerListener, BadMessageListener {
- final Logger logger;
- final bool verbose;
-
- _Listener(this.logger) : verbose = logger.isVerbose;
-
- @override
- void log(String prefix, String details) {
- if (verbose) {
- logger.trace('$prefix $details');
- }
- }
-}
diff --git a/pkg/dartfix/lib/src/migrate/apply.dart b/pkg/dartfix/lib/src/migrate/apply.dart
deleted file mode 100644
index b4c7ab2..0000000
--- a/pkg/dartfix/lib/src/migrate/apply.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2020, 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_client/protocol.dart';
-
-import '../util.dart';
-
-// TODO(devoncarew): This is only referenced from tests.
-
-/// Perform the indicated source edits to the given source, returning the
-/// resulting transformed text.
-String applyEdits(SourceFileEdit sourceFileEdit, String source) {
- List<SourceEdit> edits = sortEdits(sourceFileEdit);
- return SourceEdit.applySequence(source, edits);
-}
diff --git a/pkg/dartfix/lib/src/migrate/display.dart b/pkg/dartfix/lib/src/migrate/display.dart
deleted file mode 100644
index 68561fb..0000000
--- a/pkg/dartfix/lib/src/migrate/display.dart
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2020, 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_client/protocol.dart';
-import 'package:cli_util/cli_logging.dart';
-import 'package:path/path.dart' as path;
-
-// TODO(devoncarew): This is only referenced from tests.
-
-/// Given a Logger and an analysis issue, render the issue to the logger.
-class IssueRenderer {
- final Logger logger;
- final String rootDirectory;
-
- IssueRenderer(this.logger, this.rootDirectory);
-
- void render(AnalysisError issue) {
- // severity • Message ... at foo/bar.dart:6:1 • (error_code)
-
- final Ansi ansi = logger.ansi;
-
- logger.stdout(
- ' ${ansi.error(issue.severity.name.toLowerCase())} • '
- '${ansi.emphasized(_removePeriod(issue.message))} '
- 'at ${path.relative(issue.location.file, from: rootDirectory)}'
- ':${issue.location.startLine}:'
- '${issue.location.startColumn} '
- '• (${issue.code})',
- );
- }
-}
-
-typedef LineProcessor = void Function(int lineNumber, String lineText);
-
-class SourcePrinter {
- static final String red = '\u001b[31m';
- static final String bold = '\u001b[1m';
- static final String reversed = '\u001b[7m';
- static final String none = '\u001b[0m';
-
- String source;
-
- SourcePrinter(this.source);
-
- void applyEdits(List<SourceEdit> edits) {
- for (SourceEdit edit in edits) {
- if (edit.replacement.isNotEmpty) {
- // an addition
- insertText(edit.offset + edit.length, edit.replacement);
- }
-
- if (edit.length != 0) {
- // a removal
- deleteRange(edit.offset, edit.length);
- }
- }
- }
-
- void deleteRange(int offset, int length) {
- source = source.substring(0, offset) +
- red +
- reversed +
- source.substring(offset, offset + length) +
- none +
- source.substring(offset + length);
- }
-
- void insertText(int offset, String text) {
- text = '$reversed$text$none';
- source = source.substring(0, offset) + text + source.substring(offset);
- }
-
- void processChangedLines(LineProcessor callback) {
- List<String> lines = source.split('\n');
- for (int i = 0; i < lines.length; i++) {
- String line = lines[i];
-
- if (line.contains(none)) {
- callback(i + 1, line);
- }
- }
- }
-}
-
-String _removePeriod(String value) {
- return value.endsWith('.') ? value.substring(0, value.length - 1) : value;
-}
diff --git a/pkg/dartfix/lib/src/migrate/options.dart b/pkg/dartfix/lib/src/migrate/options.dart
deleted file mode 100644
index e3c565e..0000000
--- a/pkg/dartfix/lib/src/migrate/options.dart
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2020, 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:args/args.dart';
-import 'package:args/src/arg_parser.dart';
-import 'package:path/path.dart' as path;
-
-// TODO(devoncarew): This class is unused.
-
-class MigrateOptions {
- static const applyChangesOption = 'apply-changes';
- static const debugOption = 'debug';
- static const ignoreErrorsOption = 'ignore-errors';
- static const previewPortOption = 'preview-port';
- static const sdkPathOption = 'sdk-path';
- static const serverPathOption = 'server-path';
- static const webPreviewOption = 'web-preview';
-
- final bool applyChanges;
- final bool debug;
- final String directory;
- final bool ignoreErrors;
- final int previewPort;
- final String serverPath;
- final String sdkPath;
- final bool webPreview;
-
- MigrateOptions(ArgResults argResults, this.directory)
- : applyChanges = argResults[applyChangesOption] as bool,
- debug = argResults[debugOption] as bool,
- ignoreErrors = argResults[ignoreErrorsOption] as bool,
- previewPort =
- int.tryParse(argResults[previewPortOption] as String) ?? 0,
- sdkPath = argResults[sdkPathOption] as String,
- serverPath = argResults[serverPathOption] as String,
- webPreview = argResults['web-preview'] as bool;
-
- String get directoryAbsolute => Directory(path.canonicalize(directory)).path;
-
- @override
- String toString() {
- return '[$directory]';
- }
-
- static void defineOptions(ArgParser argParser) {
- argParser.addFlag(
- applyChangesOption,
- defaultsTo: false,
- negatable: false,
- help: 'Apply the proposed null safety changes to the files on disk.',
- );
- argParser.addFlag(
- debugOption,
- defaultsTo: false,
- hide: true,
- negatable: true,
- help: 'Show (very verbose) debugging information to stdout during '
- 'migration',
- );
- argParser.addFlag(
- ignoreErrorsOption,
- defaultsTo: false,
- negatable: false,
- help: 'Attempt to perform null safety analysis even if the package has '
- 'analysis errors.',
- );
- argParser.addOption(
- sdkPathOption,
- hide: true,
- help: 'Override the SDK path used for migration.',
- );
- argParser.addOption(
- previewPortOption,
- defaultsTo: '0',
- help: 'Run the preview server on the specified port. If not specified '
- 'or invalid, dynamically allocate a port.',
- );
- argParser.addOption(
- serverPathOption,
- hide: true,
- help: 'Override the analysis server path used for migration.',
- );
- argParser.addFlag(
- webPreviewOption,
- defaultsTo: true,
- negatable: true,
- help: 'Show an interactive preview of the proposed null safety changes '
- 'in a browser window.\n'
- 'With --no-web-preview, the proposed changes are instead printed to '
- 'the console.',
- );
- }
-}
diff --git a/pkg/dartfix/lib/src/options.dart b/pkg/dartfix/lib/src/options.dart
deleted file mode 100644
index b6d2cbb..0000000
--- a/pkg/dartfix/lib/src/options.dart
+++ /dev/null
@@ -1,210 +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.
-
-import 'dart:io';
-
-import 'package:args/args.dart';
-import 'package:cli_util/cli_logging.dart';
-import 'package:dartfix/src/context.dart';
-import 'package:path/path.dart' as path;
-
-// TODO(brianwilkerson) Deprecate 'excludeFix' and replace it with 'exclude-fix'
-const excludeFixOption = 'excludeFix';
-const forceOption = 'force';
-const includeFixOption = 'fix';
-const overwriteOption = 'overwrite';
-const pedanticOption = 'pedantic';
-const previewDirOption = 'preview-dir';
-const previewPortOption = 'preview-port';
-const sdkOption = 'sdk';
-
-const _binaryName = 'dartfix';
-const _colorOption = 'color';
-
-// options only supported by server 1.22.2 and greater
-const _helpOption = 'help';
-const _serverSnapshot = 'server';
-
-// options not supported yet by any server
-const _verboseOption = 'verbose';
-
-/// Command line options for `dartfix`.
-class Options {
- final Context context;
- Logger logger;
-
- List<String> targets;
- final String sdkPath;
- final String serverSnapshot;
-
- final bool pedanticFixes;
- final List<String> includeFixes;
- final List<String> excludeFixes;
-
- final bool force;
- final bool showHelp;
- bool overwrite;
- final bool useColor;
- final bool verbose;
-
- Options._fromArgs(this.context, ArgResults results)
- : force = results[forceOption] as bool,
- includeFixes = (results[includeFixOption] as List ?? []).cast<String>(),
- excludeFixes = (results[excludeFixOption] as List ?? []).cast<String>(),
- overwrite = results[overwriteOption] as bool,
- pedanticFixes = results[pedanticOption] as bool,
- sdkPath = results[sdkOption] as String ?? _getSdkPath(),
- serverSnapshot = results[_serverSnapshot] as String,
- showHelp = results[_helpOption] as bool || results.arguments.isEmpty,
- targets = results.rest,
- useColor = results.wasParsed(_colorOption)
- ? results[_colorOption] as bool
- : null,
- verbose = results[_verboseOption] as bool;
-
- String makeAbsoluteAndNormalize(String target) {
- if (!path.isAbsolute(target)) {
- target = path.join(context.workingDir, target);
- }
- return path.normalize(target);
- }
-
- static Options parse(List<String> args, Context context, Logger logger) {
- final parser = ArgParser(allowTrailingOptions: true)
- ..addSeparator('Choosing fixes to be applied:')
- ..addMultiOption(includeFixOption,
- help: 'Include a specific fix.', valueHelp: 'name-of-fix')
- ..addMultiOption(excludeFixOption,
- help: 'Exclude a specific fix.', valueHelp: 'name-of-fix')
- ..addFlag(pedanticOption,
- help: 'Apply pedantic fixes.', defaultsTo: false, negatable: false)
- ..addSeparator('Modifying files:')
- ..addFlag(overwriteOption,
- abbr: 'w',
- help: 'Overwrite files with the changes.',
- defaultsTo: false,
- negatable: false)
- ..addFlag(forceOption,
- abbr: 'f',
- help: 'Overwrite files even if there are errors.',
- defaultsTo: false,
- negatable: false)
- ..addSeparator('Miscellaneous:')
- ..addFlag(_helpOption,
- abbr: 'h',
- help: 'Display this help message.',
- defaultsTo: false,
- negatable: false)
- ..addOption(sdkOption,
- help: 'Path to the SDK to analyze against.',
- valueHelp: 'path',
- hide: true)
- ..addOption(_serverSnapshot,
- help: 'Path to the analysis server snapshot file.',
- valueHelp: 'path',
- hide: true)
- ..addFlag(_verboseOption,
- abbr: 'v',
- help: 'Verbose output.',
- defaultsTo: false,
- negatable: false)
- ..addFlag(_colorOption,
- help: 'Use ansi colors when printing messages.',
- defaultsTo: Ansi.terminalSupportsAnsi);
-
- context ??= Context();
-
- ArgResults results;
- try {
- results = parser.parse(args);
- } on FormatException catch (e) {
- logger ??= Logger.standard(ansi: Ansi(Ansi.terminalSupportsAnsi));
- logger.stderr(e.message);
- _showUsage(parser, logger);
- context.exit(17);
- }
-
- Options options = Options._fromArgs(context, results);
-
- if (logger == null) {
- if (options.verbose) {
- logger = Logger.verbose();
- } else {
- logger = Logger.standard(
- ansi: Ansi(
- options.useColor ?? Ansi.terminalSupportsAnsi,
- ));
- }
- }
- options.logger = logger;
-
- // For '--help', we short circuit the logic to validate the sdk and project.
- if (options.showHelp) {
- _showUsage(parser, logger, showHelpHint: false);
- return options;
- }
-
- // Validate the Dart SDK location
- String sdkPath = options.sdkPath;
- if (sdkPath == null) {
- logger.stderr('No Dart SDK found.');
- context.exit(18);
- }
-
- if (!context.exists(sdkPath)) {
- logger.stderr('Invalid Dart SDK path: $sdkPath');
- context.exit(19);
- }
-
- // Check for files and/or directories to analyze.
- if (options.targets == null || options.targets.isEmpty) {
- logger.stderr('Expected at least one file or directory to analyze.');
- context.exit(20);
- }
-
- // Normalize and verify paths
- options.targets =
- options.targets.map<String>(options.makeAbsoluteAndNormalize).toList();
- for (String target in options.targets) {
- if (!context.isDirectory(target)) {
- if (!context.exists(target)) {
- logger.stderr('Target does not exist: $target');
- } else {
- logger.stderr('Expected directory, but found: $target');
- }
- context.exit(21);
- }
- }
-
- if (options.verbose) {
- logger.trace('Targets:');
- for (String target in options.targets) {
- logger.trace(' $target');
- }
- }
-
- return options;
- }
-
- static String _getSdkPath() {
- return Platform.environment['DART_SDK'] ??
- path.dirname(path.dirname(Platform.resolvedExecutable));
- }
-
- static void _showUsage(ArgParser parser, Logger logger,
- {bool showHelpHint = true}) {
- Function(String message) out = showHelpHint ? logger.stderr : logger.stdout;
- // show help on stdout when showHelp is true and showHelpHint is false
- out('''
-Usage: $_binaryName [options...] <directory paths>
-''');
- out(parser.usage);
- out(showHelpHint
- ? '''
-
-Use --$_helpOption to display the fixes that can be specified using either
---$includeFixOption or --$excludeFixOption.'''
- : '');
- }
-}
diff --git a/pkg/dartfix/lib/src/util.dart b/pkg/dartfix/lib/src/util.dart
deleted file mode 100644
index 07ad858..0000000
--- a/pkg/dartfix/lib/src/util.dart
+++ /dev/null
@@ -1,69 +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.
-
-import 'dart:io' show File, Platform;
-
-import 'package:analysis_server_client/protocol.dart';
-import 'package:path/path.dart' as path;
-
-int compareSuggestions(DartFixSuggestion s1, DartFixSuggestion s2) {
- int result = s1.description.compareTo(s2.description);
- if (result != 0) {
- return result;
- }
- return (s2.location?.offset ?? 0) - (s1.location?.offset ?? 0);
-}
-
-int compareFixes(DartFix s1, DartFix s2) {
- return s1.name.compareTo(s2.name);
-}
-
-/// Return the analysis_server executable by proceeding upward until finding the
-/// Dart SDK repository root, then returning the analysis_server executable
-/// within the repository.
-///
-/// Return `null` if it cannot be found.
-String findServerPath() {
- String pathname = Platform.script.toFilePath();
- while (true) {
- String parent = path.dirname(pathname);
- if (parent.length >= pathname.length) {
- return null;
- }
- String serverPath =
- path.join(parent, 'pkg', 'analysis_server', 'bin', 'server.dart');
- if (File(serverPath).existsSync()) {
- return serverPath;
- }
- pathname = parent;
- }
-}
-
-bool shouldShowError(AnalysisError error) {
- // Only show diagnostics that will affect the fixes.
- return error.type.name != 'HINT' &&
- error.type.name != 'LINT' &&
- error.type.name != 'TODO' &&
- // TODO(danrubel): Rather than checking the error.code with
- // specific strings, add something to the error indicating that
- // it will be automatically fixed by edit.dartfix.
- error.code != 'wrong_number_of_type_arguments_constructor';
-}
-
-String toSentenceFragment(String message) {
- return message.endsWith('.')
- ? message.substring(0, message.length - 1)
- : message;
-}
-
-String pluralize(String word, int count) => count == 1 ? word : '${word}s';
-
-List<SourceEdit> sortEdits(SourceFileEdit sourceFileEdit) {
- // Sort edits in reverse offset order.
- List<SourceEdit> edits = sourceFileEdit.edits.toList();
- edits.sort((a, b) {
- return b.offset - a.offset;
- });
- return edits;
-}
diff --git a/pkg/dartfix/pubspec.yaml b/pkg/dartfix/pubspec.yaml
deleted file mode 100644
index 10dcae8..0000000
--- a/pkg/dartfix/pubspec.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-name: dartfix
-version: 0.1.8
-description:
- A tool for migrating Dart source to newer versions of the Dart SDK
- and fixing common issues.
-homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dartfix
-environment:
- sdk: '>=2.8.0 <3.0.0'
-
-# Add the bin/dartfix.dart script to the scripts pub installs.
-executables:
- dartfix:
-
-dependencies:
- # Pin to an exact version of analysis_server_client because the edit.dartfix
- # protocol is experimental and will continue to evolve.
- analysis_server_client: '>=1.1.3 <1.1.4'
- args: ^1.4.0
- cli_util: ^0.2.0
- path: ^1.7.0
- pub_semver: ^1.4.4
-
-dev_dependencies:
- analyzer: ^0.40.0
- pedantic: ^1.8.0
- test: ^1.14.2
diff --git a/pkg/dartfix/test/src/driver_example_test.dart b/pkg/dartfix/test/src/driver_example_test.dart
deleted file mode 100644
index 4cbb06b..0000000
--- a/pkg/dartfix/test/src/driver_example_test.dart
+++ /dev/null
@@ -1,28 +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 'dart:io';
-
-import 'package:test/test.dart';
-
-import 'test_context.dart';
-
-void main() {
- test('run original example', () async {
- File exampleFile = findFile('pkg/dartfix/example/example.dart');
-
- print('--- launching original example');
- final futureResult1 =
- Process.run(Platform.resolvedExecutable, [exampleFile.path]);
-
- print('--- waiting for original example');
- final result = await futureResult1;
-
- print('--- original example output');
- var text = result.stdout as String;
- print(text);
-
- expect(text.trim(), 'myDouble = 4.0');
- });
-}
diff --git a/pkg/dartfix/test/src/driver_exclude_test.dart b/pkg/dartfix/test/src/driver_exclude_test.dart
deleted file mode 100644
index 3236efa..0000000
--- a/pkg/dartfix/test/src/driver_exclude_test.dart
+++ /dev/null
@@ -1,48 +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 'dart:io';
-
-import 'package:dartfix/src/driver.dart';
-import 'package:test/test.dart';
-
-import 'test_context.dart';
-
-void main() {
- File exampleFile;
- Directory exampleDir;
-
- test('exclude fix', () async {
- exampleFile = findFile('pkg/dartfix/example/example.dart');
- exampleDir = exampleFile.parent;
-
- final driver = Driver();
- final testContext = TestContext();
- final testLogger = TestLogger(debug: _debug);
- String exampleSource = await exampleFile.readAsString();
-
- try {
- await driver.start([
- if (_debug) '-v',
- '--fix',
- 'convert_class_to_mixin',
- '--excludeFix',
- 'convert_class_to_mixin',
- exampleDir.path,
- ], testContext: testContext, testLogger: testLogger);
- } finally {
- if (_debug) {
- print(testLogger.stderrBuffer.toString());
- print(testLogger.stdoutBuffer.toString());
- print('--- original example');
- print(exampleSource);
- }
- }
-
- final suggestions = driver.result.suggestions;
- expect(suggestions, hasLength(0));
- }, timeout: const Timeout(Duration(minutes: 3)));
-}
-
-const _debug = true;
diff --git a/pkg/dartfix/test/src/driver_help_test.dart b/pkg/dartfix/test/src/driver_help_test.dart
deleted file mode 100644
index d8a6330..0000000
--- a/pkg/dartfix/test/src/driver_help_test.dart
+++ /dev/null
@@ -1,55 +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:dartfix/src/driver.dart';
-import 'package:dartfix/src/options.dart';
-import 'package:test/test.dart';
-
-import 'test_context.dart';
-
-void main() {
- test('help explicit', () async {
- final driver = Driver();
- final testContext = TestContext();
- final testLogger = TestLogger();
- try {
- await driver.start(
- ['--help'], // display help and list fixes
- testContext: testContext,
- testLogger: testLogger,
- );
- fail('expected exception');
- } on TestExit catch (e) {
- expect(e.code, 0);
- }
- final errText = testLogger.stderrBuffer.toString();
- final outText = testLogger.stdoutBuffer.toString();
- expect(errText, isEmpty);
- expect(outText, contains('--$excludeFixOption'));
- expect(outText, isNot(contains('Use --help to display the fixes')));
- });
-
- test('help implicit', () async {
- final driver = Driver();
- final testContext = TestContext();
- final testLogger = TestLogger();
- try {
- await driver.start(
- [], // no options or arguments should display help and list fixes
- testContext: testContext,
- testLogger: testLogger,
- );
- fail('expected exception');
- } on TestExit catch (e) {
- expect(e.code, 0);
- }
- final errText = testLogger.stderrBuffer.toString();
- final outText = testLogger.stdoutBuffer.toString();
- print(errText);
- print(outText);
- expect(errText, isEmpty);
- expect(outText, contains('--$excludeFixOption'));
- expect(outText, isNot(contains('Use --help to display the fixes')));
- });
-}
diff --git a/pkg/dartfix/test/src/driver_include_test.dart b/pkg/dartfix/test/src/driver_include_test.dart
deleted file mode 100644
index 7079d5d..0000000
--- a/pkg/dartfix/test/src/driver_include_test.dart
+++ /dev/null
@@ -1,47 +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 'dart:io';
-
-import 'package:dartfix/src/driver.dart';
-import 'package:test/test.dart';
-
-import 'test_context.dart';
-
-void main() {
- File exampleFile;
- Directory exampleDir;
-
- test('include fix', () async {
- exampleFile = findFile('pkg/dartfix/example/example.dart');
- exampleDir = exampleFile.parent;
-
- final driver = Driver();
- final testContext = TestContext();
- final testLogger = TestLogger(debug: _debug);
- String exampleSource = await exampleFile.readAsString();
-
- try {
- await driver.start([
- if (_debug) '-v',
- '--fix',
- 'prefer_int_literals',
- exampleDir.path,
- ], testContext: testContext, testLogger: testLogger);
- } finally {
- if (_debug) {
- print(testLogger.stderrBuffer.toString());
- print(testLogger.stdoutBuffer.toString());
- print('--- original example');
- print(exampleSource);
- }
- }
-
- final suggestions = driver.result.suggestions;
- expect(suggestions, hasLength(1));
- expectHasSuggestion(suggestions, 'Convert to an int literal');
- }, timeout: const Timeout(Duration(minutes: 3)));
-}
-
-const _debug = true;
diff --git a/pkg/dartfix/test/src/driver_pedantic_test.dart b/pkg/dartfix/test/src/driver_pedantic_test.dart
deleted file mode 100644
index 6d4b99c6..0000000
--- a/pkg/dartfix/test/src/driver_pedantic_test.dart
+++ /dev/null
@@ -1,13 +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 'driver_test.dart' show defineDriverTests;
-
-void main() {
- defineDriverTests(
- name: 'pedantic',
- options: ['--pedantic'],
- expectedSuggestions: ["Replace with 'isEmpty'"],
- );
-}
diff --git a/pkg/dartfix/test/src/driver_prefer_is_empty_test.dart b/pkg/dartfix/test/src/driver_prefer_is_empty_test.dart
deleted file mode 100644
index db8b4ad..0000000
--- a/pkg/dartfix/test/src/driver_prefer_is_empty_test.dart
+++ /dev/null
@@ -1,13 +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 'driver_test.dart' show defineDriverTests;
-
-void main() {
- defineDriverTests(
- name: 'prefer_is_empty',
- options: ['--fix', 'prefer_is_empty'],
- expectedSuggestions: ["Replace with 'isEmpty'"],
- );
-}
diff --git a/pkg/dartfix/test/src/driver_test.dart b/pkg/dartfix/test/src/driver_test.dart
deleted file mode 100644
index 667b723..0000000
--- a/pkg/dartfix/test/src/driver_test.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.
-
-import 'dart:io';
-
-import 'package:analysis_server_client/protocol.dart';
-import 'package:dartfix/src/driver.dart';
-import 'package:test/test.dart';
-
-import 'test_context.dart';
-
-void main() {
- defineDriverTests(
- name: 'default',
- options: [
- '--fix',
- 'prefer_int_literals',
- '--fix',
- 'convert_class_to_mixin'
- ],
- expectedSuggestions: [
- 'Convert MyMixin to a mixin',
- 'Convert to an int literal',
- ],
- );
-}
-
-void defineDriverTests({
- String name,
- List<String> options,
- List<String> expectedSuggestions,
- bool debug = false,
- bool updateExample = false,
-}) {
- var fixFileName = 'example_$name.dart';
-
- File exampleFile;
- File exampleFixedFile;
- Directory exampleDir;
-
- setUp(() {
- exampleFile = findFile('pkg/dartfix/example/example.dart');
- exampleFixedFile = findFile('pkg/dartfix/fixed/$fixFileName');
- exampleDir = exampleFile.parent;
- });
-
- test('fix example - $name', () async {
- final driver = Driver();
- final testContext = TestContext();
- final testLogger = TestLogger(debug: debug);
- String exampleSource = await exampleFile.readAsString();
-
- await driver.start([if (debug) '-v', ...options, exampleDir.path],
- testContext: testContext, testLogger: testLogger);
- if (debug) {
- print(testLogger.stderrBuffer.toString());
- print(testLogger.stdoutBuffer.toString());
- print('--- original example');
- print(exampleSource);
- }
-
- expect(driver.result.edits, hasLength(1));
- for (SourceEdit edit in driver.result.edits[0].edits) {
- exampleSource = edit.apply(exampleSource);
- }
- if (debug) {
- print('--- fixed example');
- print(exampleSource);
- }
-
- final suggestions = driver.result.suggestions;
- for (var expectedSuggestion in expectedSuggestions) {
- expectHasSuggestion(suggestions, expectedSuggestion);
- }
- expect(suggestions, hasLength(expectedSuggestions.length));
-
- exampleSource = replaceLeadingComment(exampleSource);
- if (updateExample) {
- await exampleFixedFile.writeAsString(exampleSource);
- } else {
- final expectedSource = await exampleFixedFile.readAsString();
- expect(exampleSource, expectedSource);
- }
- }, timeout: const Timeout(Duration(minutes: 3)));
-
- test('run example - $name', () async {
- if (debug) print('--- launching original example');
- final futureResult1 =
- Process.run(Platform.resolvedExecutable, [exampleFile.path]);
-
- if (debug) print('--- launching fixed example');
- final futureResult2 =
- Process.run(Platform.resolvedExecutable, [exampleFixedFile.path]);
-
- if (debug) print('--- waiting for original example');
- final result1 = await futureResult1;
-
- if (debug) print('--- waiting for fixed example');
- final result2 = await futureResult2;
-
- final stdout1 = result1.stdout;
- final stdout2 = result2.stdout;
- if (debug) {
- print('--- original example output');
- print(stdout1);
- print('--- fixed example output');
- print(stdout2);
- }
- expect(stdout1, stdout2);
- });
-}
-
-String replaceLeadingComment(String source) => source.replaceAll(
- '''
-// This file contains code that is modified by running dartfix.
-// After running dartfix, this content matches a file in the "fixed" directory.
-'''
- .trim(),
- '''
-// This file contains code that has been modified by running dartfix.
-// See example.dart for the original unmodified code.
- '''
- .trim());
diff --git a/pkg/dartfix/test/src/migrate_command_test.dart b/pkg/dartfix/test/src/migrate_command_test.dart
deleted file mode 100644
index a2fcf89..0000000
--- a/pkg/dartfix/test/src/migrate_command_test.dart
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright (c) 2020, 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:analysis_server_client/protocol.dart';
-import 'package:cli_util/cli_logging.dart';
-import 'package:dartfix/src/migrate/apply.dart';
-import 'package:dartfix/src/migrate/display.dart';
-import 'package:test/test.dart';
-
-void main() {
- defineMigrateTests();
-}
-
-void defineMigrateTests() {
- group('issue render', defineIssueRenderTests);
- group('SourcePrinter', defineSourcePrinterTests);
- group('applyEdits', defineApplyEditsTests);
-}
-
-void defineIssueRenderTests() {
- IssueRenderer renderer;
- TestLogger logger;
-
- setUp(() {
- logger = TestLogger();
- renderer = IssueRenderer(logger, '.');
- });
-
- test('issue1', () {
- AnalysisError issue = AnalysisError(
- AnalysisErrorSeverity.ERROR,
- AnalysisErrorType.COMPILE_TIME_ERROR,
- Location('foo/bar/baz.dart', 1, 2, 3, 4),
- 'My message.',
- 'my_error_code',
- );
-
- renderer.render(issue);
-
- expect(
- logger.stdoutText.trim(),
- contains(platformPath(
- 'error • My message at foo/bar/baz.dart:3:4 • (my_error_code)')),
- );
- expect(logger.stderrText, isEmpty);
- });
-
- test('issue2', () {
- AnalysisError issue = AnalysisError(
- AnalysisErrorSeverity.INFO,
- AnalysisErrorType.TODO,
- Location('foo/bar/qux.dart', 1, 2, 3, 4),
- 'todo: My message.',
- 'todo',
- );
-
- renderer.render(issue);
-
- expect(
- logger.stdoutText,
- contains(platformPath(
- 'info • todo: My message at foo/bar/qux.dart:3:4 • (todo)')));
-
- expect(logger.stderrText, isEmpty);
- });
-}
-
-void defineSourcePrinterTests() {
- SourcePrinter printer;
-
- setUp(() {
- printer = SourcePrinter('''
-void main() {
- Cat one = Cat('Tabby');
- print(one);
-}
-
-class Cat {
- final String name;
- String color;
-
- Cat(this.name);
-
- String toString() {
- return name?.toString() + ' is ' + color.toString();
- }
-}
-''');
- });
-
- test('add and remove', () {
- printer.insertText(192, '?');
- printer.deleteRange(164, 1);
- printer.insertText(98, '?');
-
- StringBuffer buf = StringBuffer();
- printer.processChangedLines((lineNumber, lineText) {
- buf.writeln('$lineNumber ${lineText.trim()}');
- });
-
- expect(buf.toString().trim(), '''
-8 String\x1B[7m?\x1B[0m color;
-13 return name?\x1B[31m\x1B[7m.\x1B[0mtoString() + \' is \' + color\x1B[7m?\x1B[0m.toString();''');
- });
-}
-
-void defineApplyEditsTests() {
- test('insert', () {
- String source = 'one two\nthree four';
- SourceFileEdit edit = SourceFileEdit('foo.dart', 0, edits: [
- SourceEdit(0, 0, 'five '),
- ]);
-
- String result = applyEdits(edit, source);
- expect(result, 'five one two\nthree four');
- });
-
- test('delete', () {
- String source = 'one two\nthree four';
- SourceFileEdit edit = SourceFileEdit('foo.dart', 0, edits: [
- SourceEdit(0, 4, ''),
- SourceEdit(8, 6, ''),
- ]);
-
- String result = applyEdits(edit, source);
- expect(result, 'two\nfour');
- });
-
- test('insert and delete', () {
- String source = 'one two\nthree four';
- SourceFileEdit edit = SourceFileEdit('foo.dart', 0, edits: [
- SourceEdit(13, 5, ''),
- SourceEdit(8, 0, 'six '),
- SourceEdit(7, 1, ' '),
- ]);
-
- String result = applyEdits(edit, source);
- expect(result, 'one two six three');
- });
-}
-
-class TestLogger implements Logger {
- final bool debug;
-
- @override
- final Ansi ansi;
- final stdoutBuffer = StringBuffer();
- final stderrBuffer = StringBuffer();
-
- TestLogger({this.debug = false}) : ansi = Ansi(false);
-
- @override
- void flush() {}
-
- @override
- bool get isVerbose => debug;
-
- @override
- Progress progress(String message) {
- return SimpleProgress(this, message);
- }
-
- @override
- void stdout(String message) {
- stdoutBuffer.writeln(message);
- }
-
- @override
- void write(String message) {
- stdoutBuffer.write(message);
- }
-
- @override
- void writeCharCode(int charCode) {
- stdoutBuffer.writeCharCode(charCode);
- }
-
- @override
- void stderr(String message) {
- stderrBuffer.writeln(message);
- }
-
- @override
- void trace(String message) {
- if (debug) {
- stdoutBuffer.writeln(message);
- }
- }
-
- String get stdoutText => stdoutBuffer.toString();
-
- String get stderrText => stderrBuffer.toString();
-}
-
-String platformPath(String path) {
- return path.replaceAll('/', Platform.pathSeparator);
-}
diff --git a/pkg/dartfix/test/src/options_test.dart b/pkg/dartfix/test/src/options_test.dart
deleted file mode 100644
index 9843fab..0000000
--- a/pkg/dartfix/test/src/options_test.dart
+++ /dev/null
@@ -1,151 +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.
-
-import 'package:dartfix/src/options.dart';
-import 'package:path/path.dart' as path;
-import 'package:test/test.dart';
-
-import 'test_context.dart';
-
-void main() {
- TestContext context;
- TestLogger logger;
-
- setUp(() {
- context = TestContext();
- logger = TestLogger();
- });
-
- String p(String filePath) => context.convertPath(filePath);
-
- Options parse(
- List<String> args, {
- String errorOut,
- int exitCode,
- bool force = false,
- List<String> includeFixes = const <String>[],
- List<String> excludeFixes = const <String>[],
- bool showHelp = false,
- String normalOut,
- bool dependencies = false,
- bool pedanticFixes = false,
- bool requiredFixes = false,
- bool overwrite = false,
- String serverSnapshot,
- List<String> targetSuffixes,
- bool verbose = false,
- }) {
- Options options;
- int actualExitCode;
- try {
- options = Options.parse(args, context, logger);
- } on TestExit catch (e) {
- actualExitCode = e.code;
- }
- expect(logger.stderrBuffer.toString(),
- errorOut != null ? contains(errorOut) : isEmpty);
- expect(logger.stdoutBuffer.toString(),
- normalOut != null ? contains(normalOut) : isEmpty);
- if (exitCode != null) {
- expect(actualExitCode, exitCode, reason: 'exit code');
- return null;
- } else {
- expect(actualExitCode, isNull, reason: 'exit code');
- }
- expect(options.force, force);
- expect(options.pedanticFixes, pedanticFixes);
- expect(options.overwrite, overwrite);
- expect(options.serverSnapshot, serverSnapshot);
- expect(options.showHelp, showHelp);
- expect(options.includeFixes, includeFixes);
- expect(options.excludeFixes, excludeFixes);
- expect(options.verbose, verbose);
- expect(path.isAbsolute(options.sdkPath), isTrue, reason: options.sdkPath);
- for (String target in options.targets) {
- expect(target, isNotNull);
- expect(path.isAbsolute(target), isTrue, reason: '$target');
- }
- if (targetSuffixes != null) {
- for (String suffix in targetSuffixes) {
- expectContains(options.targets, suffix);
- }
- }
- return options;
- }
-
- test('exclude fix', () {
- parse(['--excludeFix', 'c', '--excludeFix', 'd', 'foo'],
- excludeFixes: ['c', 'd'], targetSuffixes: ['foo']);
- });
-
- test('force', () {
- parse(['--force', 'foo'], force: true, targetSuffixes: ['foo']);
- });
-
- test('help explicit', () {
- parse(['--help'], normalOut: 'Display this help message', showHelp: true);
- });
-
- test('help implicit', () {
- parse([], normalOut: 'Display this help message', showHelp: true);
- });
-
- test('include fix', () {
- parse(['--fix', 'a', '--fix', 'b', 'foo'],
- includeFixes: ['a', 'b'], targetSuffixes: ['foo']);
- });
-
- test('invalid option', () {
- parse(['--foo'],
- errorOut: 'Could not find an option named "foo"', exitCode: 17);
- });
-
- test('invalid option no logger', () {
- try {
- Options.parse(['--foo'], context, null);
- fail('Expected exception');
- } on TestExit catch (e) {
- expect(e.code, 17, reason: 'exit code');
- }
- });
-
- test('invalid target', () {
- parse(['foo.dart'],
- errorOut: 'Expected directory, but found', exitCode: 21);
- });
-
- test('overwrite', () {
- parse(['--overwrite', 'foo'], overwrite: true, targetSuffixes: ['foo']);
- });
-
- test('pedantic fixes', () {
- parse(['--pedantic', 'foo'], pedanticFixes: true);
- });
-
- test('server snapshot', () {
- parse(['--server', 'some/path', 'foo'], serverSnapshot: 'some/path');
- });
-
- test('simple', () {
- parse(['foo'], targetSuffixes: ['foo']);
- });
-
- test('two targets', () {
- parse([p('one/foo'), p('two/bar')],
- targetSuffixes: [p('one/foo'), p('two/bar')]);
- });
-
- test('verbose', () {
- parse(['--verbose', 'foo'], verbose: true);
- });
-}
-
-void expectContains(Iterable<String> collection, String suffix) {
- for (String elem in collection) {
- if (elem.endsWith(suffix)) {
- return;
- }
- }
- fail('Expected one of $collection\n to end with "$suffix"');
-}
diff --git a/pkg/dartfix/test/src/test_context.dart b/pkg/dartfix/test/src/test_context.dart
deleted file mode 100644
index 9e55c3f..0000000
--- a/pkg/dartfix/test/src/test_context.dart
+++ /dev/null
@@ -1,130 +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.
-
-import 'dart:io';
-
-import 'package:analysis_server_client/protocol.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:cli_util/cli_logging.dart';
-import 'package:dartfix/src/context.dart';
-import 'package:test/test.dart';
-
-class TestContext with ResourceProviderMixin implements Context {
- @override
- String get workingDir => convertPath('/usr/some/non/existing/directory');
-
- @override
- bool exists(String filePath) => true;
-
- @override
- void exit(int code) {
- throw TestExit(code);
- }
-
- @override
- bool isDirectory(String filePath) => !filePath.endsWith('.dart');
-}
-
-class TestExit {
- final int code;
-
- TestExit(this.code);
-
- @override
- String toString() => 'TestExit($code)';
-}
-
-class TestLogger implements Logger {
- final bool debug;
-
- @override
- final Ansi ansi;
- final stdoutBuffer = StringBuffer();
- final stderrBuffer = StringBuffer();
-
- TestLogger({this.debug = false}) : ansi = Ansi(false);
-
- @override
- void flush() {}
-
- @override
- bool get isVerbose => debug;
-
- @override
- Progress progress(String message) {
- return SimpleProgress(this, message);
- }
-
- @override
- void stderr(String message) {
- stderrBuffer.writeln(message);
- }
-
- @override
- void stdout(String message) {
- stdoutBuffer.writeln(message);
- }
-
- @override
- void write(String message) {
- stdoutBuffer.write(message);
- }
-
- @override
- void writeCharCode(int charCode) {
- stdoutBuffer.writeCharCode(charCode);
- }
-
- @override
- void trace(String message) {
- if (debug) {
- stdoutBuffer.writeln(message);
- }
- }
-}
-
-void expectHasSuggestion(
- List<DartFixSuggestion> suggestions, String expectedText) {
- for (DartFixSuggestion suggestion in suggestions) {
- if (suggestion.description.contains(expectedText)) {
- return;
- }
- }
- fail('Failed to find suggestion containing: $expectedText\n'
- 'in ${suggestions.map((s) => s.description).toList()}');
-}
-
-void expectDoesNotHaveSuggestion(
- List<DartFixSuggestion> suggestions, String expectedText) {
- for (DartFixSuggestion suggestion in suggestions) {
- if (suggestion.description.contains(expectedText)) {
- fail('Did not expect to find suggestion containing: $expectedText');
- }
- }
-}
-
-File findFile(String relPath) {
- Directory dir = Directory.current;
- while (true) {
- final file = File.fromUri(dir.uri.resolve(relPath));
- if (file.existsSync()) {
- return file;
- }
- final parent = dir.parent;
- if (parent.path == dir.path) {
- fail('Failed to find $relPath');
- }
- dir = parent;
- }
-}
-
-String findValue(File pubspec, String key) {
- List<String> lines = pubspec.readAsLinesSync();
- for (String line in lines) {
- if (line.trim().startsWith('$key:')) {
- return line.split(':')[1].trim();
- }
- }
- fail('Failed to find $key in ${pubspec.path}');
-}
diff --git a/pkg/dartfix/test/test_all.dart b/pkg/dartfix/test/test_all.dart
deleted file mode 100644
index 0b1908e..0000000
--- a/pkg/dartfix/test/test_all.dart
+++ /dev/null
@@ -1,27 +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.
-
-import 'package:test/test.dart';
-
-import 'src/driver_example_test.dart' as driver_example;
-import 'src/driver_exclude_test.dart' as driver_exclude;
-import 'src/driver_help_test.dart' as driver_help;
-import 'src/driver_include_test.dart' as driver_include;
-import 'src/driver_pedantic_test.dart' as driver_pedantic;
-import 'src/driver_prefer_is_empty_test.dart' as driver_prefer_is_empty;
-import 'src/driver_test.dart' as driver;
-import 'src/migrate_command_test.dart' as migrate_command_test;
-import 'src/options_test.dart' as options_test;
-
-void main() {
- group('driver', driver_example.main);
- group('driver', driver_exclude.main);
- group('driver', driver_help.main);
- group('driver', driver_include.main);
- group('driver', driver_pedantic.main);
- group('driver', driver_prefer_is_empty.main);
- group('driver', driver.main);
- group('migrate', migrate_command_test.main);
- group('options', options_test.main);
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/collections.dart b/pkg/front_end/lib/src/fasta/kernel/collections.dart
index 0a26c3a..79b99c0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/collections.dart
@@ -53,6 +53,11 @@
}
@override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
+ return unsupported("getStaticTypeInternal", fileOffset, getFileUri(this));
+ }
+
+ @override
R accept<R>(ExpressionVisitor<R> v) => v.defaultExpression(this);
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 5fdaeb3..dc9dfa1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -24,6 +24,7 @@
import 'package:kernel/text/ast_to_text.dart' show Precedence, Printer;
import 'package:kernel/src/printer.dart';
import 'package:kernel/core_types.dart';
+import 'package:kernel/type_environment.dart';
import '../builder/type_alias_builder.dart';
@@ -439,7 +440,11 @@
unsupported("${runtimeType}.accept1", -1, null);
@override
- DartType getStaticType(types) =>
+ DartType getStaticType(StaticTypeContext context) =>
+ unsupported("${runtimeType}.getStaticType", -1, null);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
unsupported("${runtimeType}.getStaticType", -1, null);
ExpressionInferenceResult acceptInference(
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 09193dc..ec80b02 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -2964,7 +2964,19 @@
abstract class Expression extends TreeNode {
/// Returns the static type of the expression.
- DartType getStaticType(StaticTypeContext context);
+ ///
+ /// This calls `StaticTypeContext.getExpressionType` which calls
+ /// [getStaticTypeInternal] to compute the type of not already cached in
+ /// [context].
+ DartType getStaticType(StaticTypeContext context) {
+ return context.getExpressionType(this);
+ }
+
+ /// Computes the static type of this expression.
+ ///
+ /// This is called by `StaticTypeContext.getExpressionType` if the static
+ /// type of this expression is not already cached in [context].
+ DartType getStaticTypeInternal(StaticTypeContext context);
/// Returns the static type of the expression as an instantiation of
/// [superclass].
@@ -3066,14 +3078,26 @@
InvalidExpression(this.message);
- DartType getStaticType(StaticTypeContext context) => const BottomType();
+ @override
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
+ const BottomType();
+
+ @override
R accept<R>(ExpressionVisitor<R> v) => v.visitInvalidExpression(this);
+
+ @override
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
v.visitInvalidExpression(this, arg);
- visitChildren(Visitor v) {}
- transformChildren(Transformer v) {}
+ @override
+ void visitChildren(Visitor v) {}
+
+ @override
+ void transformChildren(Transformer v) {}
@override
String toString() {
@@ -3095,7 +3119,11 @@
VariableGet(this.variable, [this.promotedType]) : assert(variable != null);
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return promotedType ?? variable.type;
}
@@ -3141,6 +3169,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitVariableSet(this);
@@ -3194,7 +3226,8 @@
interfaceTargetReference = getMemberReference(member);
}
- DartType getStaticType(StaticTypeContext context) {
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
var interfaceTarget = this.interfaceTarget;
if (interfaceTarget != null) {
Class superclass = interfaceTarget.enclosingClass;
@@ -3274,6 +3307,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitPropertySet(this);
@@ -3333,7 +3370,7 @@
interfaceTargetReference = getMemberReference(member);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticTypeInternal(StaticTypeContext context) {
if (interfaceTarget == null) {
// TODO(johnniwinther): SuperPropertyGet without a target should be
// replaced by invalid expressions.
@@ -3399,6 +3436,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitSuperPropertySet(this);
@@ -3447,7 +3488,12 @@
targetReference = getMemberReference(target);
}
- DartType getStaticType(StaticTypeContext context) => target.getterType;
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
+ target.getterType;
R accept<R>(ExpressionVisitor<R> v) => v.visitStaticGet(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3492,6 +3538,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitStaticSet(this);
@@ -3686,7 +3736,7 @@
interfaceTargetReference = getMemberReference(target);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticTypeInternal(StaticTypeContext context) {
var interfaceTarget = this.interfaceTarget;
if (interfaceTarget != null) {
if (interfaceTarget is Procedure &&
@@ -3816,7 +3866,7 @@
interfaceTargetReference = getMemberReference(target);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticTypeInternal(StaticTypeContext context) {
if (interfaceTarget == null) return const DynamicType();
Class superclass = interfaceTarget.enclosingClass;
List<DartType> receiverTypeArguments = context.typeEnvironment
@@ -3887,7 +3937,7 @@
targetReference = getMemberReference(target);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return Substitution.fromPairs(
target.function.typeParameters, arguments.types)
.substituteType(target.function.returnType);
@@ -3951,7 +4001,7 @@
targetReference = getMemberReference(target);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return arguments.types.isEmpty
? context.typeEnvironment.coreTypes
.rawType(target.enclosingClass, context.nonNullable)
@@ -4018,7 +4068,7 @@
expression?.parent = this;
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticTypeInternal(StaticTypeContext context) {
FunctionType type = expression.getStaticType(context);
return Substitution.fromPairs(type.typeParameters, typeArguments)
.substituteType(type.withoutTypeParameters);
@@ -4065,6 +4115,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitNot(this);
@@ -4118,6 +4172,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitLogicalExpression(this);
@@ -4170,7 +4228,11 @@
otherwise?.parent = this;
}
- DartType getStaticType(StaticTypeContext context) => staticType;
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) => staticType;
R accept<R>(ExpressionVisitor<R> v) => v.visitConditionalExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4238,6 +4300,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.stringRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitStringConcatenation(this);
@@ -4288,7 +4354,11 @@
setParents(lists, this);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return context.typeEnvironment.listType(typeArgument, context.nonNullable);
}
@@ -4342,7 +4412,11 @@
setParents(sets, this);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return context.typeEnvironment.setType(typeArgument, context.nonNullable);
}
@@ -4399,7 +4473,11 @@
setParents(maps, this);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return context.typeEnvironment
.mapType(keyType, valueType, context.nonNullable);
}
@@ -4460,7 +4538,11 @@
Class get classNode => classReference.asClass;
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return typeArguments.isEmpty
? context.typeEnvironment.coreTypes
.rawType(classNode, context.nonNullable)
@@ -4558,6 +4640,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
expression.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitFileUriExpression(this);
@@ -4619,6 +4705,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitIsExpression(this);
@@ -4728,7 +4818,11 @@
: (flags & ~FlagForNonNullableByDefault);
}
- DartType getStaticType(StaticTypeContext context) => type;
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) => type;
R accept<R>(ExpressionVisitor<R> v) => v.visitAsExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4791,7 +4885,7 @@
operand?.parent = this;
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticTypeInternal(StaticTypeContext context) {
DartType operandType = operand.getStaticType(context);
return operandType == context.typeEnvironment.nullType
? const NeverType(Nullability.nonNullable)
@@ -4840,6 +4934,10 @@
StringLiteral(this.value);
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.stringRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitStringLiteral(this);
@@ -4869,6 +4967,10 @@
IntLiteral(this.value);
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitIntLiteral(this);
@@ -4892,6 +4994,10 @@
DoubleLiteral(this.value);
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.doubleRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitDoubleLiteral(this);
@@ -4915,6 +5021,10 @@
BoolLiteral(this.value);
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitBoolLiteral(this);
@@ -4936,6 +5046,10 @@
Object get value => null;
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.nullType;
R accept<R>(ExpressionVisitor<R> v) => v.visitNullLiteral(this);
@@ -4959,6 +5073,10 @@
SymbolLiteral(this.value);
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.symbolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitSymbolLiteral(this);
@@ -4986,6 +5104,10 @@
TypeLiteral(this.type);
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.typeRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitTypeLiteral(this);
@@ -5012,7 +5134,11 @@
}
class ThisExpression extends Expression {
- DartType getStaticType(StaticTypeContext context) => context.thisType;
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) => context.thisType;
R accept<R>(ExpressionVisitor<R> v) => v.visitThisExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -5034,6 +5160,10 @@
class Rethrow extends Expression {
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.isNonNullableByDefault
? const NeverType(Nullability.nonNullable)
: const BottomType();
@@ -5064,6 +5194,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
context.isNonNullableByDefault
? const NeverType(Nullability.nonNullable)
: const BottomType();
@@ -5105,7 +5239,11 @@
setParents(expressions, this);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return context.typeEnvironment.listType(typeArgument, context.nonNullable);
}
@@ -5152,7 +5290,11 @@
setParents(expressions, this);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return context.typeEnvironment.setType(typeArgument, context.nonNullable);
}
@@ -5203,7 +5345,11 @@
setParents(entries, this);
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return context.typeEnvironment
.mapType(keyType, valueType, context.nonNullable);
}
@@ -5302,7 +5448,7 @@
operand?.parent = this;
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return context.typeEnvironment.flatten(operand.getStaticType(context));
}
@@ -5348,7 +5494,7 @@
function?.parent = this;
}
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return function.computeFunctionType(context.nonNullable);
}
@@ -5386,7 +5532,11 @@
assert(constant != null);
}
- DartType getStaticType(StaticTypeContext context) => type;
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) => type;
R accept<R>(ExpressionVisitor<R> v) => v.visitConstantExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -5424,6 +5574,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
body.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitLet(this);
@@ -5469,6 +5623,10 @@
}
DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) =>
value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitBlockExpression(this);
@@ -5523,7 +5681,11 @@
LoadLibrary(this.import);
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return context.typeEnvironment
.futureType(const DynamicType(), context.nonNullable);
}
@@ -5554,7 +5716,11 @@
CheckLibraryIsLoaded(this.import);
- DartType getStaticType(StaticTypeContext context) {
+ DartType getStaticType(StaticTypeContext context) =>
+ getStaticTypeInternal(context);
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
return context.typeEnvironment.coreTypes.objectRawType(context.nonNullable);
}
@@ -6069,6 +6235,76 @@
}
}
+ /// Returns the type of the iterator in this for-in statement.
+ ///
+ /// This calls `StaticTypeContext.getForInIteratorType` which calls
+ /// [getStaticTypeInternal] to compute the type of not already cached in
+ /// [context].
+ DartType getIteratorType(StaticTypeContext context) =>
+ context.getForInIteratorType(this);
+
+ /// Computes the type of the iterator in this for-in statement.
+ ///
+ /// This is called by `StaticTypeContext.getForInIteratorType` if the iterator
+ /// type of this for-in statement is not already cached in [context].
+ DartType getIteratorTypeInternal(StaticTypeContext context) {
+ DartType iteratorType;
+ if (isAsync) {
+ InterfaceType streamType = iterable.getStaticTypeAsInstanceOf(
+ context.typeEnvironment.coreTypes.streamClass, context);
+ if (streamType != null) {
+ iteratorType = new InterfaceType(
+ context.typeEnvironment.coreTypes.streamIteratorClass,
+ context.nonNullable,
+ streamType.typeArguments);
+ }
+ } else {
+ InterfaceType iterableType = iterable.getStaticTypeAsInstanceOf(
+ context.typeEnvironment.coreTypes.iterableClass, context);
+ Member member = context.typeEnvironment.hierarchy
+ .getInterfaceMember(iterableType.classNode, new Name('iterator'));
+ if (member != null) {
+ iteratorType = Substitution.fromInterfaceType(iterableType)
+ .substituteType(member.getterType);
+ }
+ }
+ return iteratorType ??= const DynamicType();
+ }
+
+ /// Returns the type of the element in this for-in statement.
+ ///
+ /// This calls `StaticTypeContext.getForInElementType` which calls
+ /// [getStaticTypeInternal] to compute the type of not already cached in
+ /// [context].
+ DartType getElementType(StaticTypeContext context) =>
+ context.getForInElementType(this);
+
+ /// Computes the type of the element in this for-in statement.
+ ///
+ /// This is called by `StaticTypeContext.getForInElementType` if the element
+ /// type of this for-in statement is not already cached in [context].
+ DartType getElementTypeInternal(StaticTypeContext context) {
+ DartType iterableType = iterable.getStaticType(context);
+ // TODO(johnniwinther): Update this to use the type of
+ // `iterable.iterator.current` if inference is updated accordingly.
+ while (iterableType is TypeParameterType) {
+ TypeParameterType typeParameterType = iterableType;
+ iterableType =
+ typeParameterType.promotedBound ?? typeParameterType.parameter.bound;
+ }
+ if (isAsync) {
+ List<DartType> typeArguments = context.typeEnvironment
+ .getTypeArgumentsAsInstanceOf(
+ iterableType, context.typeEnvironment.coreTypes.streamClass);
+ return typeArguments.single;
+ } else {
+ List<DartType> typeArguments = context.typeEnvironment
+ .getTypeArgumentsAsInstanceOf(
+ iterableType, context.typeEnvironment.coreTypes.iterableClass);
+ return typeArguments.single;
+ }
+ }
+
@override
String toString() {
return "ForInStatement(${toStringInternal()})";
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index 076f46e..8967df1 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -530,13 +530,89 @@
ignoringNullabilities,
}
+abstract class StaticTypeCache {
+ DartType getExpressionType(Expression node, StaticTypeContext context);
+
+ DartType getForInIteratorType(ForInStatement node, StaticTypeContext context);
+
+ DartType getForInElementType(ForInStatement node, StaticTypeContext context);
+}
+
+class StaticTypeCacheImpl implements StaticTypeCache {
+ Map<Expression, DartType> _expressionTypes;
+ Map<ForInStatement, DartType> _forInIteratorTypes;
+ Map<ForInStatement, DartType> _forInElementTypes;
+
+ DartType getExpressionType(Expression node, StaticTypeContext context) {
+ _expressionTypes ??= <Expression, DartType>{};
+ return _expressionTypes[node] ??= node.getStaticTypeInternal(context);
+ }
+
+ DartType getForInIteratorType(
+ ForInStatement node, StaticTypeContext context) {
+ _forInIteratorTypes ??= <ForInStatement, DartType>{};
+ return _forInIteratorTypes[node] ??= node.getIteratorTypeInternal(context);
+ }
+
+ DartType getForInElementType(ForInStatement node, StaticTypeContext context) {
+ _forInElementTypes ??= <ForInStatement, DartType>{};
+ return _forInElementTypes[node] ??= node.getElementTypeInternal(context);
+ }
+}
+
/// Context object needed for computing `Expression.getStaticType`.
///
/// The [StaticTypeContext] provides access to the [TypeEnvironment] and the
/// current 'this type' as well as determining the nullability state of the
/// enclosing library.
-// TODO(johnniwinther): Support static type caching through [StaticTypeContext].
-class StaticTypeContext {
+abstract class StaticTypeContext {
+ /// The [TypeEnvironment] used for the static type computation.
+ ///
+ /// This provides access to the core types and the class hierarchy.
+ TypeEnvironment get typeEnvironment;
+
+ /// The static type of a `this` expression.
+ InterfaceType get thisType;
+
+ /// Creates a static type context for computing static types in the body
+ /// of [member].
+ factory StaticTypeContext(Member member, TypeEnvironment typeEnvironment,
+ {StaticTypeCache cache}) = StaticTypeContextImpl;
+
+ /// Creates a static type context for computing static types of annotations
+ /// in [library].
+ factory StaticTypeContext.forAnnotations(
+ Library library, TypeEnvironment typeEnvironment,
+ {StaticTypeCache cache}) = StaticTypeContextImpl.forAnnotations;
+
+ /// The [Nullability] used for non-nullable types.
+ ///
+ /// For opt out libraries this is [Nullability.legacy].
+ Nullability get nonNullable;
+
+ /// The [Nullability] used for nullable types.
+ ///
+ /// For opt out libraries this is [Nullability.legacy].
+ Nullability get nullable;
+
+ /// Return `true` if the current library is opted in to non-nullable by
+ /// default.
+ bool get isNonNullableByDefault;
+
+ /// Returns the mode under which the current library was compiled.
+ NonNullableByDefaultCompiledMode get nonNullableByDefaultCompiledMode;
+
+ /// Returns the static type of [node].
+ DartType getExpressionType(Expression node);
+
+ /// Returns the static type of the iterator in for-in statement [node].
+ DartType getForInIteratorType(ForInStatement node);
+
+ /// Returns the static type of the element in for-in statement [node].
+ DartType getForInElementType(ForInStatement node);
+}
+
+class StaticTypeContextImpl implements StaticTypeContext {
/// The [TypeEnvironment] used for the static type computation.
///
/// This provides access to the core types and the class hierarchy.
@@ -551,17 +627,23 @@
/// The static type of a `this` expression.
final InterfaceType thisType;
+ final StaticTypeCache _cache;
+
/// Creates a static type context for computing static types in the body
/// of [member].
- StaticTypeContext(Member member, this.typeEnvironment)
+ StaticTypeContextImpl(Member member, this.typeEnvironment,
+ {StaticTypeCache cache})
: _library = member.enclosingLibrary,
thisType = member.enclosingClass?.getThisType(
- typeEnvironment.coreTypes, member.enclosingLibrary.nonNullable);
+ typeEnvironment.coreTypes, member.enclosingLibrary.nonNullable),
+ _cache = cache;
/// Creates a static type context for computing static types of annotations
/// in [library].
- StaticTypeContext.forAnnotations(this._library, this.typeEnvironment)
- : thisType = null;
+ StaticTypeContextImpl.forAnnotations(this._library, this.typeEnvironment,
+ {StaticTypeCache cache})
+ : thisType = null,
+ _cache = cache;
/// The [Nullability] used for non-nullable types.
///
@@ -580,6 +662,30 @@
/// Returns the mode under which the current library was compiled.
NonNullableByDefaultCompiledMode get nonNullableByDefaultCompiledMode =>
_library.nonNullableByDefaultCompiledMode;
+
+ DartType getExpressionType(Expression node) {
+ if (_cache != null) {
+ return _cache.getExpressionType(node, this);
+ } else {
+ return node.getStaticTypeInternal(this);
+ }
+ }
+
+ DartType getForInIteratorType(ForInStatement node) {
+ if (_cache != null) {
+ return _cache.getForInIteratorType(node, this);
+ } else {
+ return node.getIteratorTypeInternal(this);
+ }
+ }
+
+ DartType getForInElementType(ForInStatement node) {
+ if (_cache != null) {
+ return _cache.getForInElementType(node, this);
+ } else {
+ return node.getElementTypeInternal(this);
+ }
+ }
}
/// Implementation of [StaticTypeContext] that update its state when entering
@@ -636,7 +742,6 @@
_FlatStatefulStaticTypeContext(TypeEnvironment typeEnvironment)
: super._internal(typeEnvironment);
- @override
Library get _library {
Library library = _currentLibrary ?? _currentMember?.enclosingLibrary;
assert(library != null,
@@ -718,6 +823,18 @@
"Trying to leave $node but current is ${_currentLibrary}.");
_currentLibrary = null;
}
+
+ @override
+ DartType getExpressionType(Expression node) =>
+ node.getStaticTypeInternal(this);
+
+ @override
+ DartType getForInIteratorType(ForInStatement node) =>
+ node.getIteratorTypeInternal(this);
+
+ @override
+ DartType getForInElementType(ForInStatement node) =>
+ node.getElementTypeInternal(this);
}
/// Implementation of [StatefulStaticTypeContext] that use a stack to change
@@ -729,7 +846,6 @@
_StackedStatefulStaticTypeContext(TypeEnvironment typeEnvironment)
: super._internal(typeEnvironment);
- @override
Library get _library {
assert(_contextStack.isNotEmpty,
"No library currently associated with StaticTypeContext.");
@@ -805,6 +921,18 @@
"Inconsistent static type context stack: "
"Trying to leave $node but current is ${state._node}.");
}
+
+ @override
+ DartType getExpressionType(Expression node) =>
+ node.getStaticTypeInternal(this);
+
+ @override
+ DartType getForInIteratorType(ForInStatement node) =>
+ node.getIteratorTypeInternal(this);
+
+ @override
+ DartType getForInElementType(ForInStatement node) =>
+ node.getElementTypeInternal(this);
}
class _StaticTypeContextState {
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 16d0fb1..e644202 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -599,7 +599,18 @@
// dartdev command (e.g., --enable-vm-service, --observe, etc).
if (!run_script) {
int tmp_i = i;
+ // We only run the CLI implicitly if the service is enabled and the user
+ // didn't run with the 'run' command. If they did provide a command, we need
+ // to skip it here to continue parsing VM flags.
+ if (!implicitly_use_dart_dev) {
+ tmp_i++;
+ }
while (tmp_i < argc) {
+ // Check if this flag is a potentially valid VM flag. If not, we've likely
+ // hit a script name and are done parsing VM flags.
+ if (!OptionProcessor::IsValidFlag(argv[tmp_i], kPrefix, kPrefixLen)) {
+ break;
+ }
OptionProcessor::TryProcess(argv[tmp_i], vm_options);
tmp_i++;
}
diff --git a/runtime/tests/vm/dart/il_round_trip_deserialization_test.dart b/runtime/tests/vm/dart/il_round_trip_deserialization_test.dart
deleted file mode 100644
index 0a6f667..0000000
--- a/runtime/tests/vm/dart/il_round_trip_deserialization_test.dart
+++ /dev/null
@@ -1,20 +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.
-
-// VMOptions=
-// VMOptions=--early-round-trip-serialization
-// VMOptions=--late-round-trip-serialization
-// VMOptions=--early-round-trip-serialization --late-round-trip-serialization
-// VMOptions=--deterministic
-// VMOptions=--deterministic --early-round-trip-serialization
-// VMOptions=--deterministic --late-round-trip-serialization
-// VMOptions=--deterministic --early-round-trip-serialization --late-round-trip-serialization
-
-// Just use the existing hello world test for now.
-// TODO(36882): Add more interesting code as the deserializer grows.
-import 'hello_world_test.dart' as test;
-
-main(args) {
- test.main();
-}
diff --git a/runtime/tests/vm/dart_2/il_round_trip_deserialization_test.dart b/runtime/tests/vm/dart_2/il_round_trip_deserialization_test.dart
deleted file mode 100644
index 0a6f667..0000000
--- a/runtime/tests/vm/dart_2/il_round_trip_deserialization_test.dart
+++ /dev/null
@@ -1,20 +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.
-
-// VMOptions=
-// VMOptions=--early-round-trip-serialization
-// VMOptions=--late-round-trip-serialization
-// VMOptions=--early-round-trip-serialization --late-round-trip-serialization
-// VMOptions=--deterministic
-// VMOptions=--deterministic --early-round-trip-serialization
-// VMOptions=--deterministic --late-round-trip-serialization
-// VMOptions=--deterministic --early-round-trip-serialization --late-round-trip-serialization
-
-// Just use the existing hello world test for now.
-// TODO(36882): Add more interesting code as the deserializer grows.
-import 'hello_world_test.dart' as test;
-
-main(args) {
- test.main();
-}
diff --git a/runtime/vm/heap/compactor.cc b/runtime/vm/heap/compactor.cc
index a4c5370..cd6e83f 100644
--- a/runtime/vm/heap/compactor.cc
+++ b/runtime/vm/heap/compactor.cc
@@ -296,6 +296,8 @@
ForwardStackPointers();
}
+ heap_->old_space()->VisitRoots(this);
+
{
MutexLocker ml(pages_lock);
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index d7f1455..a1d5866 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -58,9 +58,11 @@
};
Heap::Heap(IsolateGroup* isolate_group,
+ bool is_vm_isolate,
intptr_t max_new_gen_semi_words,
intptr_t max_old_gen_words)
: isolate_group_(isolate_group),
+ is_vm_isolate_(is_vm_isolate),
new_space_(this, max_new_gen_semi_words),
old_space_(this, max_old_gen_words),
barrier_(),
@@ -150,6 +152,9 @@
if (addr != 0) {
return addr;
}
+
+ old_space_.TryReleaseReservation();
+
// Give up allocating this object.
OS::PrintErr("Exhausted heap space, trying to allocate %" Pd " bytes.\n",
size);
@@ -678,11 +683,12 @@
}
void Heap::Init(IsolateGroup* isolate_group,
+ bool is_vm_isolate,
intptr_t max_new_gen_words,
intptr_t max_old_gen_words) {
ASSERT(isolate_group->heap() == nullptr);
- std::unique_ptr<Heap> heap(
- new Heap(isolate_group, max_new_gen_words, max_old_gen_words));
+ std::unique_ptr<Heap> heap(new Heap(isolate_group, is_vm_isolate,
+ max_new_gen_words, max_old_gen_words));
isolate_group->set_heap(std::move(heap));
}
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 7e42b75..026d793 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -167,6 +167,7 @@
// Initialize the heap and register it with the isolate.
static void Init(IsolateGroup* isolate_group,
+ bool is_vm_isolate,
intptr_t max_new_gen_words,
intptr_t max_old_gen_words);
@@ -305,6 +306,7 @@
#endif // PRODUCT
IsolateGroup* isolate_group() const { return isolate_group_; }
+ bool is_vm_isolate() const { return is_vm_isolate_; }
Monitor* barrier() const { return &barrier_; }
Monitor* barrier_done() const { return &barrier_done_; }
@@ -354,6 +356,7 @@
};
Heap(IsolateGroup* isolate_group,
+ bool is_vm_isolate,
intptr_t max_new_gen_semi_words, // Max capacity of new semi-space.
intptr_t max_old_gen_words);
@@ -391,6 +394,7 @@
void CollectForDebugging();
IsolateGroup* isolate_group_;
+ bool is_vm_isolate_;
// The different spaces used for allocation.
Scavenger new_space_;
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 3c73952..d3b62fa 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -249,6 +249,8 @@
for (intptr_t i = 0; i < num_freelists_; i++) {
freelists_[i].Reset();
}
+
+ TryReserveForOOM();
}
PageSpace::~PageSpace() {
@@ -366,7 +368,7 @@
page->set_object_end(page->memory_->end());
if ((type != OldPage::kExecutable) && (heap_ != nullptr) &&
- (heap_->isolate_group() != Dart::vm_isolate()->group())) {
+ (!heap_->is_vm_isolate())) {
page->AllocateForwardingPage();
}
return page;
@@ -1020,6 +1022,47 @@
return estimated_mark_compact_completion <= deadline;
}
+void PageSpace::TryReleaseReservation() {
+ if (oom_reservation_ == nullptr) return;
+ uword addr = reinterpret_cast<uword>(oom_reservation_);
+ intptr_t size = oom_reservation_->HeapSize();
+ oom_reservation_ = nullptr;
+ freelists_[OldPage::kData].Free(addr, size);
+}
+
+bool PageSpace::MarkReservation() {
+ if (oom_reservation_ == nullptr) {
+ return false;
+ }
+ ObjectLayout* ptr = reinterpret_cast<ObjectLayout*>(oom_reservation_);
+ if (!ptr->IsMarked()) {
+ ptr->SetMarkBit();
+ }
+ return true;
+}
+
+void PageSpace::TryReserveForOOM() {
+ if (oom_reservation_ == nullptr) {
+ uword addr = TryAllocate(kOOMReservationSize, OldPage::kData,
+ kForceGrowth /* Don't re-enter GC */);
+ if (addr != 0) {
+ oom_reservation_ = FreeListElement::AsElement(addr, kOOMReservationSize);
+ }
+ }
+}
+
+void PageSpace::VisitRoots(ObjectPointerVisitor* visitor) {
+ if (oom_reservation_ != nullptr) {
+ // FreeListElements are generally held untagged, but ObjectPointerVisitors
+ // expect tagged pointers.
+ ObjectPtr ptr =
+ ObjectLayout::FromAddr(reinterpret_cast<uword>(oom_reservation_));
+ visitor->VisitPointer(&ptr);
+ oom_reservation_ =
+ reinterpret_cast<FreeListElement*>(ObjectLayout::ToAddr(ptr));
+ }
+}
+
void PageSpace::CollectGarbage(bool compact, bool finalize) {
ASSERT(GrowthControlState());
@@ -1186,11 +1229,13 @@
mid3 = OS::GetCurrentMonotonicMicros();
}
+ bool has_reservation = MarkReservation();
+
if (compact) {
SweepLarge();
Compact(thread);
set_phase(kDone);
- } else if (FLAG_concurrent_sweep) {
+ } else if (FLAG_concurrent_sweep && has_reservation) {
ConcurrentSweep(isolate_group);
} else {
SweepLarge();
@@ -1198,6 +1243,8 @@
set_phase(kDone);
}
+ TryReserveForOOM();
+
// Make code pages read-only.
if (finalize) WriteProtectCode(true);
@@ -1551,9 +1598,10 @@
before.CombinedUsedInWords() - last_usage_.CombinedUsedInWords();
intptr_t grow_heap;
if (allocated_since_previous_gc > 0) {
- const intptr_t garbage =
+ intptr_t garbage =
before.CombinedUsedInWords() - after.CombinedUsedInWords();
- ASSERT(garbage >= 0);
+ // Garbage may be negative if when the OOM reservation is refilled.
+ garbage = Utils::Maximum(static_cast<intptr_t>(0), garbage);
// It makes no sense to expect that each kb allocated will cause more than
// one kb of garbage, so we clamp k at 1.0.
const double k = Utils::Minimum(
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 83c5488..a786f78 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -307,6 +307,11 @@
is_protected, is_locked);
}
+ void TryReleaseReservation();
+ bool MarkReservation();
+ void TryReserveForOOM();
+ void VisitRoots(ObjectPointerVisitor* visitor);
+
bool ReachedHardThreshold() const {
return page_space_controller_.ReachedHardThreshold(usage_);
}
@@ -569,6 +574,8 @@
// page freelists without locking.
const intptr_t num_freelists_;
FreeList* freelists_;
+ static constexpr intptr_t kOOMReservationSize = 32 * KB;
+ FreeListElement* oom_reservation_ = nullptr;
// Use ExclusivePageIterator for safe access to these.
mutable Mutex pages_lock_;
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 41f1f99..e45ebd5 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -1512,6 +1512,10 @@
if (abort_) {
ReverseScavenge(&from);
bytes_promoted = 0;
+ } else if ((CapacityInWords() - UsedInWords()) < KBInWords) {
+ // Don't scavenge again until the next old-space GC has occurred. Prevents
+ // performing one scavenge per allocation as the heap limit is approached.
+ heap_->assume_scavenge_will_fail_ = true;
}
ASSERT(promotion_stack_.IsEmpty());
MournWeakHandles();
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 7a1c69e..0667421 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -448,7 +448,7 @@
void IsolateGroup::CreateHeap(bool is_vm_isolate,
bool is_service_or_kernel_isolate) {
- Heap::Init(this,
+ Heap::Init(this, is_vm_isolate,
is_vm_isolate
? 0 // New gen size 0; VM isolate should only allocate in old.
: FLAG_new_gen_semi_max_size * MBInWords,
diff --git a/tests/language/deferred/split_constants_canonicalization_a.dart b/tests/language/deferred/split_constants_canonicalization_a.dart
new file mode 100644
index 0000000..3e3ada7
--- /dev/null
+++ b/tests/language/deferred/split_constants_canonicalization_a.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_a_1.dart" deferred as a_1;
+import "split_constants_canonicalization_a_2.dart" deferred as a_2;
+
+loadChildren() async {
+ await a_1.loadLibrary();
+ await a_2.loadLibrary();
+}
+
+a_1_mint() => a_1.mint();
+a_1_string() => a_1.string();
+a_1_list() => a_1.list();
+a_1_map() => a_1.map();
+a_1_box() => a_1.box();
+a_1_enum() => a_1.enumm();
+a_1_type() => a_1.type();
+a_1_closure() => a_1.closure();
+
+a_2_mint() => a_2.mint();
+a_2_string() => a_2.string();
+a_2_list() => a_2.list();
+a_2_map() => a_2.map();
+a_2_box() => a_2.box();
+a_2_enum() => a_2.enumm();
+a_2_type() => a_2.type();
+a_2_closure() => a_2.closure();
diff --git a/tests/language/deferred/split_constants_canonicalization_a_1.dart b/tests/language/deferred/split_constants_canonicalization_a_1.dart
new file mode 100644
index 0000000..ea054f5
--- /dev/null
+++ b/tests/language/deferred/split_constants_canonicalization_a_1.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_test.dart";
+
+@pragma("vm:never-inline")
+mint() => 0x7FFFFFFFFFFFFFFF;
+
+@pragma("vm:never-inline")
+string() => "We all have identical strings";
+
+@pragma("vm:never-inline")
+list() => const <String>["We all have identical lists"];
+
+@pragma("vm:never-inline")
+map() => const <String, String>{"We all have": "identical maps"};
+
+@pragma("vm:never-inline")
+box() => const Box("We all have identical boxes");
+
+@pragma("vm:never-inline")
+enumm() => Enum.GREEN;
+
+@pragma("vm:never-inline")
+type() => Box;
+
+@pragma("vm:never-inline")
+closure() => commonClosure;
diff --git a/tests/language/deferred/split_constants_canonicalization_a_2.dart b/tests/language/deferred/split_constants_canonicalization_a_2.dart
new file mode 100644
index 0000000..ea054f5
--- /dev/null
+++ b/tests/language/deferred/split_constants_canonicalization_a_2.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_test.dart";
+
+@pragma("vm:never-inline")
+mint() => 0x7FFFFFFFFFFFFFFF;
+
+@pragma("vm:never-inline")
+string() => "We all have identical strings";
+
+@pragma("vm:never-inline")
+list() => const <String>["We all have identical lists"];
+
+@pragma("vm:never-inline")
+map() => const <String, String>{"We all have": "identical maps"};
+
+@pragma("vm:never-inline")
+box() => const Box("We all have identical boxes");
+
+@pragma("vm:never-inline")
+enumm() => Enum.GREEN;
+
+@pragma("vm:never-inline")
+type() => Box;
+
+@pragma("vm:never-inline")
+closure() => commonClosure;
diff --git a/tests/language/deferred/split_constants_canonicalization_b.dart b/tests/language/deferred/split_constants_canonicalization_b.dart
new file mode 100644
index 0000000..f27900d
--- /dev/null
+++ b/tests/language/deferred/split_constants_canonicalization_b.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_b_1.dart" deferred as b_1;
+import "split_constants_canonicalization_b_2.dart" deferred as b_2;
+
+loadChildren() async {
+ await b_1.loadLibrary();
+ await b_2.loadLibrary();
+}
+
+b_1_mint() => b_1.mint();
+b_1_string() => b_1.string();
+b_1_list() => b_1.list();
+b_1_map() => b_1.map();
+b_1_box() => b_1.box();
+b_1_enum() => b_1.enumm();
+b_1_type() => b_1.type();
+b_1_closure() => b_1.closure();
+
+b_2_mint() => b_2.mint();
+b_2_string() => b_2.string();
+b_2_list() => b_2.list();
+b_2_map() => b_2.map();
+b_2_box() => b_2.box();
+b_2_enum() => b_2.enumm();
+b_2_type() => b_2.type();
+b_2_closure() => b_2.closure();
diff --git a/tests/language/deferred/split_constants_canonicalization_b_1.dart b/tests/language/deferred/split_constants_canonicalization_b_1.dart
new file mode 100644
index 0000000..ea054f5
--- /dev/null
+++ b/tests/language/deferred/split_constants_canonicalization_b_1.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_test.dart";
+
+@pragma("vm:never-inline")
+mint() => 0x7FFFFFFFFFFFFFFF;
+
+@pragma("vm:never-inline")
+string() => "We all have identical strings";
+
+@pragma("vm:never-inline")
+list() => const <String>["We all have identical lists"];
+
+@pragma("vm:never-inline")
+map() => const <String, String>{"We all have": "identical maps"};
+
+@pragma("vm:never-inline")
+box() => const Box("We all have identical boxes");
+
+@pragma("vm:never-inline")
+enumm() => Enum.GREEN;
+
+@pragma("vm:never-inline")
+type() => Box;
+
+@pragma("vm:never-inline")
+closure() => commonClosure;
diff --git a/tests/language/deferred/split_constants_canonicalization_b_2.dart b/tests/language/deferred/split_constants_canonicalization_b_2.dart
new file mode 100644
index 0000000..ea054f5
--- /dev/null
+++ b/tests/language/deferred/split_constants_canonicalization_b_2.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_test.dart";
+
+@pragma("vm:never-inline")
+mint() => 0x7FFFFFFFFFFFFFFF;
+
+@pragma("vm:never-inline")
+string() => "We all have identical strings";
+
+@pragma("vm:never-inline")
+list() => const <String>["We all have identical lists"];
+
+@pragma("vm:never-inline")
+map() => const <String, String>{"We all have": "identical maps"};
+
+@pragma("vm:never-inline")
+box() => const Box("We all have identical boxes");
+
+@pragma("vm:never-inline")
+enumm() => Enum.GREEN;
+
+@pragma("vm:never-inline")
+type() => Box;
+
+@pragma("vm:never-inline")
+closure() => commonClosure;
diff --git a/tests/language/deferred/split_constants_canonicalization_test.dart b/tests/language/deferred/split_constants_canonicalization_test.dart
new file mode 100644
index 0000000..02d5c6e
--- /dev/null
+++ b/tests/language/deferred/split_constants_canonicalization_test.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2020, 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=--use_bare_instructions=false
+// VMOptions=--use_bare_instructions=true
+
+import "package:expect/expect.dart";
+import "split_constants_canonicalization_a.dart" deferred as a;
+import "split_constants_canonicalization_b.dart" deferred as b;
+
+class Box {
+ final contents;
+ const Box(this.contents);
+}
+
+enum Enum {
+ RED,
+ GREEN,
+ BLUE,
+}
+
+commonClosure() {}
+
+main() async {
+ await a.loadLibrary();
+ await a.loadChildren();
+ await b.loadLibrary();
+ await b.loadChildren();
+
+ var a_1_mint = await a.a_1_mint();
+ var a_2_mint = await a.a_2_mint();
+ var b_1_mint = await b.b_1_mint();
+ var b_2_mint = await b.b_2_mint();
+ Expect.isTrue(identical(a_1_mint, a_2_mint));
+ Expect.isTrue(identical(a_1_mint, b_1_mint));
+ Expect.isTrue(identical(a_1_mint, b_2_mint));
+
+ var a_1_string = await a.a_1_string();
+ var a_2_string = await a.a_2_string();
+ var b_1_string = await b.b_1_string();
+ var b_2_string = await b.b_2_string();
+ Expect.isTrue(identical(a_1_string, a_2_string));
+ Expect.isTrue(identical(a_1_string, b_1_string));
+ Expect.isTrue(identical(a_1_string, b_2_string));
+
+ var a_1_list = await a.a_1_list();
+ var a_2_list = await a.a_2_list();
+ var b_1_list = await b.b_1_list();
+ var b_2_list = await b.b_2_list();
+ Expect.isTrue(identical(a_1_list, a_2_list));
+ Expect.isTrue(identical(a_1_list, b_1_list));
+ Expect.isTrue(identical(a_1_list, b_2_list));
+
+ var a_1_map = await a.a_1_map();
+ var a_2_map = await a.a_2_map();
+ var b_1_map = await b.b_1_map();
+ var b_2_map = await b.b_2_map();
+ Expect.isTrue(identical(a_1_map, a_2_map));
+ Expect.isTrue(identical(a_1_map, b_1_map));
+ Expect.isTrue(identical(a_1_map, b_2_map));
+
+ var a_1_box = await a.a_1_box();
+ var a_2_box = await a.a_2_box();
+ var b_1_box = await b.b_1_box();
+ var b_2_box = await b.b_2_box();
+ Expect.isTrue(identical(a_1_box, a_2_box));
+ Expect.isTrue(identical(a_1_box, b_1_box));
+ Expect.isTrue(identical(a_1_box, b_2_box));
+
+ var a_1_enum = await a.a_1_enum();
+ var a_2_enum = await a.a_2_enum();
+ var b_1_enum = await b.b_1_enum();
+ var b_2_enum = await b.b_2_enum();
+ Expect.isTrue(identical(a_1_enum, a_2_enum));
+ Expect.isTrue(identical(a_1_enum, b_1_enum));
+ Expect.isTrue(identical(a_1_enum, b_2_enum));
+
+ var a_1_type = await a.a_1_type();
+ var a_2_type = await a.a_2_type();
+ var b_1_type = await b.b_1_type();
+ var b_2_type = await b.b_2_type();
+ Expect.isTrue(identical(a_1_type, a_2_type));
+ Expect.isTrue(identical(a_1_type, b_1_type));
+ Expect.isTrue(identical(a_1_type, b_2_type));
+
+ var a_1_closure = await a.a_1_closure();
+ var a_2_closure = await a.a_2_closure();
+ var b_1_closure = await b.b_1_closure();
+ var b_2_closure = await b.b_2_closure();
+ Expect.isTrue(identical(a_1_closure, a_2_closure));
+ Expect.isTrue(identical(a_1_closure, b_1_closure));
+ Expect.isTrue(identical(a_1_closure, b_2_closure));
+}
diff --git a/tests/language_2/deferred/split_constants_canonicalization_a.dart b/tests/language_2/deferred/split_constants_canonicalization_a.dart
new file mode 100644
index 0000000..3e3ada7
--- /dev/null
+++ b/tests/language_2/deferred/split_constants_canonicalization_a.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_a_1.dart" deferred as a_1;
+import "split_constants_canonicalization_a_2.dart" deferred as a_2;
+
+loadChildren() async {
+ await a_1.loadLibrary();
+ await a_2.loadLibrary();
+}
+
+a_1_mint() => a_1.mint();
+a_1_string() => a_1.string();
+a_1_list() => a_1.list();
+a_1_map() => a_1.map();
+a_1_box() => a_1.box();
+a_1_enum() => a_1.enumm();
+a_1_type() => a_1.type();
+a_1_closure() => a_1.closure();
+
+a_2_mint() => a_2.mint();
+a_2_string() => a_2.string();
+a_2_list() => a_2.list();
+a_2_map() => a_2.map();
+a_2_box() => a_2.box();
+a_2_enum() => a_2.enumm();
+a_2_type() => a_2.type();
+a_2_closure() => a_2.closure();
diff --git a/tests/language_2/deferred/split_constants_canonicalization_a_1.dart b/tests/language_2/deferred/split_constants_canonicalization_a_1.dart
new file mode 100644
index 0000000..ea054f5
--- /dev/null
+++ b/tests/language_2/deferred/split_constants_canonicalization_a_1.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_test.dart";
+
+@pragma("vm:never-inline")
+mint() => 0x7FFFFFFFFFFFFFFF;
+
+@pragma("vm:never-inline")
+string() => "We all have identical strings";
+
+@pragma("vm:never-inline")
+list() => const <String>["We all have identical lists"];
+
+@pragma("vm:never-inline")
+map() => const <String, String>{"We all have": "identical maps"};
+
+@pragma("vm:never-inline")
+box() => const Box("We all have identical boxes");
+
+@pragma("vm:never-inline")
+enumm() => Enum.GREEN;
+
+@pragma("vm:never-inline")
+type() => Box;
+
+@pragma("vm:never-inline")
+closure() => commonClosure;
diff --git a/tests/language_2/deferred/split_constants_canonicalization_a_2.dart b/tests/language_2/deferred/split_constants_canonicalization_a_2.dart
new file mode 100644
index 0000000..ea054f5
--- /dev/null
+++ b/tests/language_2/deferred/split_constants_canonicalization_a_2.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_test.dart";
+
+@pragma("vm:never-inline")
+mint() => 0x7FFFFFFFFFFFFFFF;
+
+@pragma("vm:never-inline")
+string() => "We all have identical strings";
+
+@pragma("vm:never-inline")
+list() => const <String>["We all have identical lists"];
+
+@pragma("vm:never-inline")
+map() => const <String, String>{"We all have": "identical maps"};
+
+@pragma("vm:never-inline")
+box() => const Box("We all have identical boxes");
+
+@pragma("vm:never-inline")
+enumm() => Enum.GREEN;
+
+@pragma("vm:never-inline")
+type() => Box;
+
+@pragma("vm:never-inline")
+closure() => commonClosure;
diff --git a/tests/language_2/deferred/split_constants_canonicalization_b.dart b/tests/language_2/deferred/split_constants_canonicalization_b.dart
new file mode 100644
index 0000000..f27900d
--- /dev/null
+++ b/tests/language_2/deferred/split_constants_canonicalization_b.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_b_1.dart" deferred as b_1;
+import "split_constants_canonicalization_b_2.dart" deferred as b_2;
+
+loadChildren() async {
+ await b_1.loadLibrary();
+ await b_2.loadLibrary();
+}
+
+b_1_mint() => b_1.mint();
+b_1_string() => b_1.string();
+b_1_list() => b_1.list();
+b_1_map() => b_1.map();
+b_1_box() => b_1.box();
+b_1_enum() => b_1.enumm();
+b_1_type() => b_1.type();
+b_1_closure() => b_1.closure();
+
+b_2_mint() => b_2.mint();
+b_2_string() => b_2.string();
+b_2_list() => b_2.list();
+b_2_map() => b_2.map();
+b_2_box() => b_2.box();
+b_2_enum() => b_2.enumm();
+b_2_type() => b_2.type();
+b_2_closure() => b_2.closure();
diff --git a/tests/language_2/deferred/split_constants_canonicalization_b_1.dart b/tests/language_2/deferred/split_constants_canonicalization_b_1.dart
new file mode 100644
index 0000000..ea054f5
--- /dev/null
+++ b/tests/language_2/deferred/split_constants_canonicalization_b_1.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_test.dart";
+
+@pragma("vm:never-inline")
+mint() => 0x7FFFFFFFFFFFFFFF;
+
+@pragma("vm:never-inline")
+string() => "We all have identical strings";
+
+@pragma("vm:never-inline")
+list() => const <String>["We all have identical lists"];
+
+@pragma("vm:never-inline")
+map() => const <String, String>{"We all have": "identical maps"};
+
+@pragma("vm:never-inline")
+box() => const Box("We all have identical boxes");
+
+@pragma("vm:never-inline")
+enumm() => Enum.GREEN;
+
+@pragma("vm:never-inline")
+type() => Box;
+
+@pragma("vm:never-inline")
+closure() => commonClosure;
diff --git a/tests/language_2/deferred/split_constants_canonicalization_b_2.dart b/tests/language_2/deferred/split_constants_canonicalization_b_2.dart
new file mode 100644
index 0000000..ea054f5
--- /dev/null
+++ b/tests/language_2/deferred/split_constants_canonicalization_b_2.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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 "split_constants_canonicalization_test.dart";
+
+@pragma("vm:never-inline")
+mint() => 0x7FFFFFFFFFFFFFFF;
+
+@pragma("vm:never-inline")
+string() => "We all have identical strings";
+
+@pragma("vm:never-inline")
+list() => const <String>["We all have identical lists"];
+
+@pragma("vm:never-inline")
+map() => const <String, String>{"We all have": "identical maps"};
+
+@pragma("vm:never-inline")
+box() => const Box("We all have identical boxes");
+
+@pragma("vm:never-inline")
+enumm() => Enum.GREEN;
+
+@pragma("vm:never-inline")
+type() => Box;
+
+@pragma("vm:never-inline")
+closure() => commonClosure;
diff --git a/tests/language_2/deferred/split_constants_canonicalization_test.dart b/tests/language_2/deferred/split_constants_canonicalization_test.dart
new file mode 100644
index 0000000..02d5c6e
--- /dev/null
+++ b/tests/language_2/deferred/split_constants_canonicalization_test.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2020, 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=--use_bare_instructions=false
+// VMOptions=--use_bare_instructions=true
+
+import "package:expect/expect.dart";
+import "split_constants_canonicalization_a.dart" deferred as a;
+import "split_constants_canonicalization_b.dart" deferred as b;
+
+class Box {
+ final contents;
+ const Box(this.contents);
+}
+
+enum Enum {
+ RED,
+ GREEN,
+ BLUE,
+}
+
+commonClosure() {}
+
+main() async {
+ await a.loadLibrary();
+ await a.loadChildren();
+ await b.loadLibrary();
+ await b.loadChildren();
+
+ var a_1_mint = await a.a_1_mint();
+ var a_2_mint = await a.a_2_mint();
+ var b_1_mint = await b.b_1_mint();
+ var b_2_mint = await b.b_2_mint();
+ Expect.isTrue(identical(a_1_mint, a_2_mint));
+ Expect.isTrue(identical(a_1_mint, b_1_mint));
+ Expect.isTrue(identical(a_1_mint, b_2_mint));
+
+ var a_1_string = await a.a_1_string();
+ var a_2_string = await a.a_2_string();
+ var b_1_string = await b.b_1_string();
+ var b_2_string = await b.b_2_string();
+ Expect.isTrue(identical(a_1_string, a_2_string));
+ Expect.isTrue(identical(a_1_string, b_1_string));
+ Expect.isTrue(identical(a_1_string, b_2_string));
+
+ var a_1_list = await a.a_1_list();
+ var a_2_list = await a.a_2_list();
+ var b_1_list = await b.b_1_list();
+ var b_2_list = await b.b_2_list();
+ Expect.isTrue(identical(a_1_list, a_2_list));
+ Expect.isTrue(identical(a_1_list, b_1_list));
+ Expect.isTrue(identical(a_1_list, b_2_list));
+
+ var a_1_map = await a.a_1_map();
+ var a_2_map = await a.a_2_map();
+ var b_1_map = await b.b_1_map();
+ var b_2_map = await b.b_2_map();
+ Expect.isTrue(identical(a_1_map, a_2_map));
+ Expect.isTrue(identical(a_1_map, b_1_map));
+ Expect.isTrue(identical(a_1_map, b_2_map));
+
+ var a_1_box = await a.a_1_box();
+ var a_2_box = await a.a_2_box();
+ var b_1_box = await b.b_1_box();
+ var b_2_box = await b.b_2_box();
+ Expect.isTrue(identical(a_1_box, a_2_box));
+ Expect.isTrue(identical(a_1_box, b_1_box));
+ Expect.isTrue(identical(a_1_box, b_2_box));
+
+ var a_1_enum = await a.a_1_enum();
+ var a_2_enum = await a.a_2_enum();
+ var b_1_enum = await b.b_1_enum();
+ var b_2_enum = await b.b_2_enum();
+ Expect.isTrue(identical(a_1_enum, a_2_enum));
+ Expect.isTrue(identical(a_1_enum, b_1_enum));
+ Expect.isTrue(identical(a_1_enum, b_2_enum));
+
+ var a_1_type = await a.a_1_type();
+ var a_2_type = await a.a_2_type();
+ var b_1_type = await b.b_1_type();
+ var b_2_type = await b.b_2_type();
+ Expect.isTrue(identical(a_1_type, a_2_type));
+ Expect.isTrue(identical(a_1_type, b_1_type));
+ Expect.isTrue(identical(a_1_type, b_2_type));
+
+ var a_1_closure = await a.a_1_closure();
+ var a_2_closure = await a.a_2_closure();
+ var b_1_closure = await b.b_1_closure();
+ var b_2_closure = await b.b_2_closure();
+ Expect.isTrue(identical(a_1_closure, a_2_closure));
+ Expect.isTrue(identical(a_1_closure, b_1_closure));
+ Expect.isTrue(identical(a_1_closure, b_2_closure));
+}
diff --git a/tests/standalone/out_of_memory_recovery_synchronous_test.dart b/tests/standalone/out_of_memory_recovery_synchronous_test.dart
new file mode 100644
index 0000000..2157fa7
--- /dev/null
+++ b/tests/standalone/out_of_memory_recovery_synchronous_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2020, 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=--old_gen_heap_size=20
+
+import "package:expect/expect.dart";
+
+main() {
+ var leak;
+ var exceptionThrown = false;
+ try {
+ leak = [];
+ while (true) {
+ leak = [leak];
+ }
+ } on OutOfMemoryError catch (exception) {
+ leak = null;
+ exceptionThrown = true;
+ print("Okay");
+ }
+ Expect.isTrue(exceptionThrown);
+
+ exceptionThrown = false;
+ try {
+ leak = [];
+ while (true) {
+ leak = [leak];
+ }
+ } on OutOfMemoryError catch (exception) {
+ leak = null;
+ exceptionThrown = true;
+ print("Okay");
+ }
+ Expect.isTrue(exceptionThrown);
+
+ exceptionThrown = false;
+ try {
+ leak = [];
+ while (true) {
+ leak = [leak];
+ }
+ } on OutOfMemoryError catch (exception) {
+ leak = null;
+ exceptionThrown = true;
+ print("Okay");
+ }
+ Expect.isTrue(exceptionThrown);
+}
diff --git a/tests/standalone/out_of_memory_recovery_test.dart b/tests/standalone/out_of_memory_recovery_test.dart
new file mode 100644
index 0000000..05aa4db
--- /dev/null
+++ b/tests/standalone/out_of_memory_recovery_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, 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=--old_gen_heap_size=20
+
+import "dart:io";
+import "dart:isolate";
+
+import "package:expect/expect.dart";
+
+handleRequest(request) {
+ if (request % 2 == 0) {
+ var leak = [];
+ while (true) {
+ leak = [leak];
+ }
+ }
+ return "Okay";
+}
+
+handleMessage(message) {
+ print(">> $message");
+ var responsePort = message[0];
+ var request = message[1];
+ try {
+ responsePort.send(<dynamic>[request, handleRequest(request)]);
+ } catch (e, st) {
+ responsePort.send(<dynamic>[request, "Failed: $e\n$st"]);
+ }
+}
+
+main(args) async {
+ var child = new RawReceivePort(handleMessage);
+
+ var parent;
+ parent = new RawReceivePort((message) {
+ print("<< $message");
+ var request = message[0];
+ var response = message[1];
+ if (request % 2 == 0) {
+ Expect.isTrue(response.contains("Out of Memory"));
+ } else {
+ Expect.equals("Okay", response);
+ }
+ if (request == 5) {
+ child.close();
+ parent.close();
+ } else {
+ child.sendPort.send(<dynamic>[parent.sendPort, request + 1]);
+ }
+ });
+
+ child.sendPort.send(<dynamic>[parent.sendPort, 1]);
+}
diff --git a/tests/standalone/standalone_kernel.status b/tests/standalone/standalone_kernel.status
index 1da02b7..63813b2 100644
--- a/tests/standalone/standalone_kernel.status
+++ b/tests/standalone/standalone_kernel.status
@@ -6,7 +6,6 @@
fragmentation_typed_data_test: Pass, Slow # GC heavy
io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
-out_of_memory_unhandled_exception_test: Pass, Slow
[ $system == android ]
entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
diff --git a/tests/standalone_2/out_of_memory_recovery_synchronous_test.dart b/tests/standalone_2/out_of_memory_recovery_synchronous_test.dart
new file mode 100644
index 0000000..2157fa7
--- /dev/null
+++ b/tests/standalone_2/out_of_memory_recovery_synchronous_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2020, 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=--old_gen_heap_size=20
+
+import "package:expect/expect.dart";
+
+main() {
+ var leak;
+ var exceptionThrown = false;
+ try {
+ leak = [];
+ while (true) {
+ leak = [leak];
+ }
+ } on OutOfMemoryError catch (exception) {
+ leak = null;
+ exceptionThrown = true;
+ print("Okay");
+ }
+ Expect.isTrue(exceptionThrown);
+
+ exceptionThrown = false;
+ try {
+ leak = [];
+ while (true) {
+ leak = [leak];
+ }
+ } on OutOfMemoryError catch (exception) {
+ leak = null;
+ exceptionThrown = true;
+ print("Okay");
+ }
+ Expect.isTrue(exceptionThrown);
+
+ exceptionThrown = false;
+ try {
+ leak = [];
+ while (true) {
+ leak = [leak];
+ }
+ } on OutOfMemoryError catch (exception) {
+ leak = null;
+ exceptionThrown = true;
+ print("Okay");
+ }
+ Expect.isTrue(exceptionThrown);
+}
diff --git a/tests/standalone_2/out_of_memory_recovery_test.dart b/tests/standalone_2/out_of_memory_recovery_test.dart
new file mode 100644
index 0000000..05aa4db
--- /dev/null
+++ b/tests/standalone_2/out_of_memory_recovery_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, 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=--old_gen_heap_size=20
+
+import "dart:io";
+import "dart:isolate";
+
+import "package:expect/expect.dart";
+
+handleRequest(request) {
+ if (request % 2 == 0) {
+ var leak = [];
+ while (true) {
+ leak = [leak];
+ }
+ }
+ return "Okay";
+}
+
+handleMessage(message) {
+ print(">> $message");
+ var responsePort = message[0];
+ var request = message[1];
+ try {
+ responsePort.send(<dynamic>[request, handleRequest(request)]);
+ } catch (e, st) {
+ responsePort.send(<dynamic>[request, "Failed: $e\n$st"]);
+ }
+}
+
+main(args) async {
+ var child = new RawReceivePort(handleMessage);
+
+ var parent;
+ parent = new RawReceivePort((message) {
+ print("<< $message");
+ var request = message[0];
+ var response = message[1];
+ if (request % 2 == 0) {
+ Expect.isTrue(response.contains("Out of Memory"));
+ } else {
+ Expect.equals("Okay", response);
+ }
+ if (request == 5) {
+ child.close();
+ parent.close();
+ } else {
+ child.sendPort.send(<dynamic>[parent.sendPort, request + 1]);
+ }
+ });
+
+ child.sendPort.send(<dynamic>[parent.sendPort, 1]);
+}
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 939b834..52e78e2 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -7,7 +7,6 @@
fragmentation_test: Pass, Slow # GC heavy
fragmentation_typed_data_test: Pass, Slow # GC heavy
io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
-out_of_memory_unhandled_exception_test: Pass, Slow
[ $system == android ]
entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
diff --git a/tools/VERSION b/tools/VERSION
index 2ba0f39..dcc999f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 6
+PRERELEASE 7
PRERELEASE_PATCH 0
\ No newline at end of file