Version 2.19.0-0.0.dev
Merge commit '939134338742c86e8aff177cd1703d3261684398' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b8f7c1..55f8cdd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,71 +1,15 @@
## 2.19.0
-#### Dart command line
-
-- **Breaking change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
- The standalone `dartanalyzer` tool has been removed as previously
- announced. `dartanalyzer` is replaced by the `dart analyze` command.
-
### Language
-- **Breaking Change** [#48167](https://github.com/dart-lang/sdk/issues/48167):
- Mixin of classes that don't extend `Object` is no longer supported:
- ```dart
- class Base {}
- class Mixin extends Base {}
- class C extends Base with Mixin {}
- ```
- This should instead be written using a mixin declaration of `Mixin`:
- ```dart
- class Base {}
- mixin Mixin on Base {}
- class C extends Base with Mixin {}
- ```
- This feature has not been supported in most compilation targets for some
- time but is now completely removed.
-
### Libraries
-#### `dart:async`
-
-- The `Stream.fromIterable` stream can now be listened to more than once.
-
-### `dart:collection`
-
-- Deprecates `BidirectionalIterator`.
-
### `dart:developer`
- Deprecates `UserTag.MAX_USER_TAGS` in favor of `UserTag.maxUserTags`.
-### Dart VM
-
-Implementation of `async`/`async*`/`sync*` is revamped in Dart VM,
-both in JIT and AOT modes. This also affects Flutter except Flutter Web.
-
-Besides smaller code size and better performance of async methods,
-the new implementation carries a few subtle changes in behavior:
-
-- If `async` method returns before reaching the first `await`, it now returns a completed Future.
- Previously `async` methods completed resulting Future in separate microtasks.
-
-- Stack traces no longer have duplicate entries for `async` methods.
-
-- New implementation now correctly throws an error if `null` occurs as
- an argument of a logical expression (`&&` and `||`) which also contains
- an `await`.
-
-- New implementation avoids unnecessary extending the liveness of local
- variables in `async`/`async*`/`sync*` methods, which means that unused
- objects stored in local variables in such methods might be garbage
- collected earlier than they were before
- (see issue [#36983](https://github.com/dart-lang/sdk/issues/36983) for details).
-
-
### Tools
-#### Dart command line
-
#### Linter
Updated the Linter to `1.26.0`, which includes changes that
@@ -131,8 +75,32 @@
}
```
+- **Breaking Change** [#48167](https://github.com/dart-lang/sdk/issues/48167):
+ Mixin of classes that don't extend `Object` is no longer supported:
+ ```dart
+ class Base {}
+ class Mixin extends Base {}
+ class C extends Base with Mixin {}
+ ```
+ This should instead be written using a mixin declaration of `Mixin`:
+ ```dart
+ class Base {}
+ mixin Mixin on Base {}
+ class C extends Base with Mixin {}
+ ```
+ This feature has not been supported in most compilation targets for some
+ time but is now completely removed.
+
### Core libraries
+#### `dart:async`
+
+- The `Stream.fromIterable` stream can now be listened to more than once.
+
+### `dart:collection`
+
+- Deprecates `BidirectionalIterator`.
+
#### `dart:html`
- Add `connectionState` attribute and `connectionstatechange` listener to
@@ -202,6 +170,29 @@
- Allow omitting the `unencodedPath` positional argument to `Uri.http` and
`Uri.https` to default to an empty path.
+### Dart VM
+
+Implementation of `async`/`async*`/`sync*` is revamped in Dart VM,
+both in JIT and AOT modes. This also affects Flutter except Flutter Web.
+
+Besides smaller code size and better performance of async methods,
+the new implementation carries a few subtle changes in behavior:
+
+- If `async` method returns before reaching the first `await`, it now returns a completed Future.
+ Previously `async` methods completed resulting Future in separate microtasks.
+
+- Stack traces no longer have duplicate entries for `async` methods.
+
+- New implementation now correctly throws an error if `null` occurs as
+ an argument of a logical expression (`&&` and `||`) which also contains
+ an `await`.
+
+- New implementation avoids unnecessary extending the liveness of local
+ variables in `async`/`async*`/`sync*` methods, which means that unused
+ objects stored in local variables in such methods might be garbage
+ collected earlier than they were before
+ (see issue [#36983](https://github.com/dart-lang/sdk/issues/36983) for details).
+
### Tools
#### Dart command line
@@ -211,6 +202,10 @@
announced. `dart2js` is replaced by the `dart compile js` command, `dartdevc`
is no longer exposed as a command-line tool.
+- **Breaking change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+ The standalone `dartanalyzer` tool has been removed as previously
+ announced. `dartanalyzer` is replaced by the `dart analyze` command.
+
#### Linter
Updated the Linter to `1.25.0`, which includes changes that
diff --git a/pkg/analysis_server/lib/src/computer/computer_call_hierarchy.dart b/pkg/analysis_server/lib/src/computer/computer_call_hierarchy.dart
index 82a4176..188f29b 100644
--- a/pkg/analysis_server/lib/src/computer/computer_call_hierarchy.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_call_hierarchy.dart
@@ -35,6 +35,17 @@
(ancestor) => containerKinds.contains(ancestor.kind));
}
+/// Gets a user-friendly display name for [element].
+String _getDisplayName(Element element) {
+ return element is CompilationUnitElement
+ ? element.source.shortName
+ : element is PropertyAccessorElement
+ ? element.isGetter
+ ? 'get ${element.displayName}'
+ : 'set ${element.displayName}'
+ : element.displayName;
+}
+
/// A [CallHierarchyItem] and a set of ranges that call to or from it.
class CallHierarchyCalls {
final CallHierarchyItem item;
@@ -109,16 +120,6 @@
return SourceRange(elementImpl.codeOffset!, elementImpl.codeLength!);
}
- static String _getDisplayName(Element element) {
- return element is CompilationUnitElement
- ? element.source.shortName
- : element is PropertyAccessorElement
- ? element.isGetter
- ? 'get ${element.displayName}'
- : 'set ${element.displayName}'
- : element.displayName;
- }
-
/// Returns the [SourceRange] of the name for [element].
static SourceRange _nameRangeForElement(Element element) {
// For synthetic items (like implicit constructors), use the nonSynthetic
@@ -185,6 +186,9 @@
/// Finds incoming calls to [target], returning the elements that call them
/// and ranges of those calls within.
+ ///
+ /// Returns an empty list if [target] is not valid, including if source code
+ /// has changed and its offset is no longer correct.
Future<List<CallHierarchyCalls>> findIncomingCalls(
CallHierarchyItem target,
SearchEngine searchEngine,
@@ -192,7 +196,7 @@
assert(target.file == _result.path);
final node = _findTargetNode(target.nameRange.offset);
var element = _getElementOfNode(node);
- if (element == null) {
+ if (element == null || !_isMatchingElement(element, target)) {
return [];
}
@@ -242,12 +246,18 @@
/// Finds outgoing calls from [target], returning the elements that are called
/// and the ranges that call them.
+ ///
+ /// Returns an empty list if [target] is not valid, including if source code
+ /// has changed and its offset is no longer correct.
Future<List<CallHierarchyCalls>> findOutgoingCalls(
CallHierarchyItem target,
) async {
assert(target.file == _result.path);
final node = _findTargetNode(target.nameRange.offset);
- if (node == null) {
+ final element = _getElementOfNode(node);
+ if (node == null ||
+ element == null ||
+ !_isMatchingElement(element, target)) {
return [];
}
@@ -359,6 +369,15 @@
return element;
}
+ /// Checks whether [element] is a match for [target].
+ ///
+ /// This is used to ensure calls are only returned for the expected target
+ /// if source code has changed since the earlier request that provided
+ /// [target] to the client.
+ bool _isMatchingElement(Element element, CallHierarchyItem target) {
+ return _getDisplayName(element) == target.displayName;
+ }
+
/// Returns the [SourceRange] to use for [node].
///
/// The returned range covers only the name of the target and does not include
diff --git a/pkg/analysis_server/test/src/computer/call_hierarchy_computer_test.dart b/pkg/analysis_server/test/src/computer/call_hierarchy_computer_test.dart
index d0d5519..486abe6 100644
--- a/pkg/analysis_server/test/src/computer/call_hierarchy_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/call_hierarchy_computer_test.dart
@@ -69,6 +69,19 @@
SourceRange entireRange(String code) =>
SourceRange(0, withoutMarkers(code).length);
+ Future<CallHierarchyItem?> findTarget(String code) async {
+ final marker = code.indexOf('^');
+ expect(marker, greaterThanOrEqualTo(0));
+ addTestSource(withoutMarkers(code));
+
+ final result = await getResolvedUnit(testFile);
+
+ return DartCallHierarchyComputer(result).findTarget(marker);
+ }
+
+ Future<ResolvedUnitResult> getResolvedUnit(String file) async =>
+ await (await session).getResolvedUnit(file) as ResolvedUnitResult;
+
// Gets the expected range that follows the string [prefix] in [code] with a
// length of [match.length].
SourceRange rangeAfterPrefix(String prefix, String code, String match) =>
@@ -111,16 +124,6 @@
expect(target, matcher);
}
- Future<CallHierarchyItem?> findTarget(String code) async {
- final marker = code.indexOf('^');
- expect(marker, greaterThanOrEqualTo(0));
- addTestSource(withoutMarkers(code));
- final result =
- await (await session).getResolvedUnit(testFile) as ResolvedUnitResult;
-
- return DartCallHierarchyComputer(result).findTarget(marker);
- }
-
@override
void setUp() {
super.setUp();
@@ -128,7 +131,7 @@
}
Future<void> test_args() async {
- await expectNoTarget('main(int ^a) {}');
+ await expectNoTarget('f(int ^a) {}');
}
Future<void> test_block() async {
@@ -580,25 +583,18 @@
late SearchEngine searchEngine;
Future<List<CallHierarchyCalls>> findIncomingCalls(String code) async {
- final marker = code.indexOf('^');
- expect(marker, greaterThanOrEqualTo(0));
- addTestSource(withoutMarkers(code));
- final session_ = await session;
+ final target = (await findTarget(code))!;
+ return findIncomingCallsForTarget(target);
+ }
- var result = await session_.getResolvedUnit(testFile) as ResolvedUnitResult;
+ Future<List<CallHierarchyCalls>> findIncomingCallsForTarget(
+ CallHierarchyItem target,
+ ) async {
+ final result = await getResolvedUnit(target.file);
expect(result.errors, isEmpty);
- var computer = DartCallHierarchyComputer(result);
- // It's possible that the target is in a different file (because we were
- // invoked on a call and not a declaration), so fetch the resolved unit
- // for the target.
- final target = computer.findTarget(marker)!;
- if (target.file != testFile) {
- result =
- await session_.getResolvedUnit(target.file) as ResolvedUnitResult;
- expect(result.errors, isEmpty);
- computer = DartCallHierarchyComputer(result);
- }
- return computer.findIncomingCalls(target, searchEngine);
+
+ return DartCallHierarchyComputer(result)
+ .findIncomingCalls(target, searchEngine);
}
@override
@@ -718,6 +714,28 @@
);
}
+ Future<void> test_fileModifications() async {
+ final contents = '''
+void o^ne() {}
+void two() {
+ one();
+}
+ ''';
+
+ final target = (await findTarget(contents))!;
+
+ // Ensure there are some results before modification.
+ var calls = await findIncomingCallsForTarget(target);
+ expect(calls, isNotEmpty);
+
+ // Modify the file so that the target offset is no longer the original item.
+ addTestSource(testCode.replaceAll('one()', 'three()'));
+
+ // Ensure there are now no results for the original target.
+ calls = await findIncomingCallsForTarget(target);
+ expect(calls, isEmpty);
+ }
+
Future<void> test_function() async {
final contents = '''
String myFun^ction() => '';
@@ -1068,25 +1086,17 @@
late String otherFile;
Future<List<CallHierarchyCalls>> findOutgoingCalls(String code) async {
- final marker = code.indexOf('^');
- expect(marker, greaterThanOrEqualTo(0));
- addTestSource(withoutMarkers(code));
- final session_ = await session;
+ final target = (await findTarget(code))!;
+ return findOutgoingCallsForTarget(target);
+ }
- var result = await session_.getResolvedUnit(testFile) as ResolvedUnitResult;
+ Future<List<CallHierarchyCalls>> findOutgoingCallsForTarget(
+ CallHierarchyItem target,
+ ) async {
+ final result = await getResolvedUnit(target.file);
expect(result.errors, isEmpty);
- var computer = DartCallHierarchyComputer(result);
- // It's possible that the target is in a different file (because we were
- // invoked on a call and not a declaration), so fetch the resolved unit
- // for the target.
- final target = computer.findTarget(marker)!;
- if (target.file != testFile) {
- result =
- await session_.getResolvedUnit(target.file) as ResolvedUnitResult;
- expect(result.errors, isEmpty);
- computer = DartCallHierarchyComputer(result);
- }
- return computer.findOutgoingCalls(target);
+
+ return DartCallHierarchyComputer(result).findOutgoingCalls(target);
}
@override
@@ -1180,6 +1190,28 @@
);
}
+ Future<void> test_fileModifications() async {
+ final contents = '''
+void o^ne() {
+ two();
+}
+void two() {}
+ ''';
+
+ final target = (await findTarget(contents))!;
+
+ // Ensure there are some results before modification.
+ var calls = await findOutgoingCallsForTarget(target);
+ expect(calls, isNotEmpty);
+
+ // Modify the file so that the target offset is no longer the original item.
+ addTestSource(testCode.replaceAll('one()', 'three()'));
+
+ // Ensure there are now no results for the original target.
+ calls = await findOutgoingCallsForTarget(target);
+ expect(calls, isEmpty);
+ }
+
Future<void> test_function() async {
final contents = '''
// ignore_for_file: unused_local_variable
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index 616f487..291d453 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -8,7 +8,7 @@
/// The current version of the Dart language (or, for non-stable releases, the
/// version of the language currently in the process of being developed).
-const _currentVersion = '2.18.0';
+const _currentVersion = '2.19.0';
/// A map containing information about all known experimental flags.
final _knownFeatures = <String, ExperimentalFeature>{
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_language_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_language_override_test.dart
index 020ebfb..156e6d2 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_language_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_language_override_test.dart
@@ -24,12 +24,12 @@
]);
}
- test_correct_2_19() async {
+ test_correct_2_190() async {
await assertErrorsInCode(r'''
-// @dart = 2.19
+// @dart = 2.190
int i = 0;
''', [
- error(HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER, 0, 15),
+ error(HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER, 0, 16),
]);
}
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index 99be7f5..d4e4585 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.11.1
+- Call `analyzeFiles` from `handleAffectedFiles` only for files that are
+ analyzed in this analysis context.
+
## 0.11.0
- Using `AnalysisContextCollection` and `AnalysisContext` for analysis.
diff --git a/pkg/analyzer_plugin/lib/plugin/plugin.dart b/pkg/analyzer_plugin/lib/plugin/plugin.dart
index fe76e56..3f7bb5d 100644
--- a/pkg/analyzer_plugin/lib/plugin/plugin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/plugin.dart
@@ -198,14 +198,19 @@
/// one or more files. The implementation may check if these files should
/// be analyzed, do such analysis, and send diagnostics.
///
- /// By default invokes [analyzeFiles].
+ /// By default invokes [analyzeFiles] only for files that are analyzed in
+ /// this [analysisContext].
Future<void> handleAffectedFiles({
required AnalysisContext analysisContext,
required List<String> paths,
}) async {
+ final analyzedPaths = paths
+ .where(analysisContext.contextRoot.isAnalyzed)
+ .toList(growable: false);
+
await analyzeFiles(
analysisContext: analysisContext,
- paths: paths,
+ paths: analyzedPaths,
);
}
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 2b61963..ad43abd 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,6 +1,6 @@
name: analyzer_plugin
description: A framework and support code for building plugins for the analysis server.
-version: 0.11.0
+version: 0.11.1
repository: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer_plugin
environment:
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index 71d843e..04e84d6 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -55,17 +55,17 @@
name: 'alternative-invalidation-strategy',
isEnabledByDefault: false,
isExpired: false,
- enabledVersion: const Version(2, 18),
- experimentEnabledVersion: const Version(2, 18),
- experimentReleasedVersion: const Version(2, 18));
+ enabledVersion: const Version(2, 19),
+ experimentEnabledVersion: const Version(2, 19),
+ experimentReleasedVersion: const Version(2, 19));
static const ExperimentalFlag constFunctions = const ExperimentalFlag(
name: 'const-functions',
isEnabledByDefault: false,
isExpired: false,
- enabledVersion: const Version(2, 18),
- experimentEnabledVersion: const Version(2, 18),
- experimentReleasedVersion: const Version(2, 18));
+ enabledVersion: const Version(2, 19),
+ experimentEnabledVersion: const Version(2, 19),
+ experimentReleasedVersion: const Version(2, 19));
static const ExperimentalFlag constantUpdate2018 = const ExperimentalFlag(
name: 'constant-update-2018',
@@ -111,9 +111,9 @@
name: 'extension-types',
isEnabledByDefault: false,
isExpired: false,
- enabledVersion: const Version(2, 18),
- experimentEnabledVersion: const Version(2, 18),
- experimentReleasedVersion: const Version(2, 18));
+ enabledVersion: const Version(2, 19),
+ experimentEnabledVersion: const Version(2, 19),
+ experimentReleasedVersion: const Version(2, 19));
static const ExperimentalFlag genericMetadata = const ExperimentalFlag(
name: 'generic-metadata',
@@ -135,17 +135,17 @@
name: 'inference-update-2',
isEnabledByDefault: false,
isExpired: false,
- enabledVersion: const Version(2, 18),
- experimentEnabledVersion: const Version(2, 18),
- experimentReleasedVersion: const Version(2, 18));
+ enabledVersion: const Version(2, 19),
+ experimentEnabledVersion: const Version(2, 19),
+ experimentReleasedVersion: const Version(2, 19));
static const ExperimentalFlag macros = const ExperimentalFlag(
name: 'macros',
isEnabledByDefault: false,
isExpired: false,
- enabledVersion: const Version(2, 18),
- experimentEnabledVersion: const Version(2, 18),
- experimentReleasedVersion: const Version(2, 18));
+ enabledVersion: const Version(2, 19),
+ experimentEnabledVersion: const Version(2, 19),
+ experimentReleasedVersion: const Version(2, 19));
static const ExperimentalFlag namedArgumentsAnywhere = const ExperimentalFlag(
name: 'named-arguments-anywhere',
@@ -199,9 +199,9 @@
name: 'test-experiment',
isEnabledByDefault: false,
isExpired: false,
- enabledVersion: const Version(2, 18),
- experimentEnabledVersion: const Version(2, 18),
- experimentReleasedVersion: const Version(2, 18));
+ enabledVersion: const Version(2, 19),
+ experimentEnabledVersion: const Version(2, 19),
+ experimentReleasedVersion: const Version(2, 19));
static const ExperimentalFlag tripleShift = const ExperimentalFlag(
name: 'triple-shift',
@@ -215,17 +215,17 @@
name: 'value-class',
isEnabledByDefault: false,
isExpired: false,
- enabledVersion: const Version(2, 18),
- experimentEnabledVersion: const Version(2, 18),
- experimentReleasedVersion: const Version(2, 18));
+ enabledVersion: const Version(2, 19),
+ experimentEnabledVersion: const Version(2, 19),
+ experimentReleasedVersion: const Version(2, 19));
static const ExperimentalFlag variance = const ExperimentalFlag(
name: 'variance',
isEnabledByDefault: false,
isExpired: false,
- enabledVersion: const Version(2, 18),
- experimentEnabledVersion: const Version(2, 18),
- experimentReleasedVersion: const Version(2, 18));
+ enabledVersion: const Version(2, 19),
+ experimentEnabledVersion: const Version(2, 19),
+ experimentReleasedVersion: const Version(2, 19));
}
/// Interface for accessing the global state of experimental features.
diff --git a/pkg/front_end/test/incremental_suite.dart b/pkg/front_end/test/incremental_suite.dart
index 3481e23..db71521 100644
--- a/pkg/front_end/test/incremental_suite.dart
+++ b/pkg/front_end/test/incremental_suite.dart
@@ -110,11 +110,6 @@
final ExpectationSet staticExpectationSet =
new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
-class Flags {
- /// The expected result of the advanced invalidation.
- static const String advancedInvalidation = 'advancedInvalidation';
-}
-
const String EXPECTATIONS = '''
[
{
@@ -370,18 +365,18 @@
"incrementalSerialization",
"nnbdMode",
]);
- result = await new NewWorldTest().newWorldTest(
- data,
- context,
- map["worlds"],
- map["modules"],
- map["omitPlatform"],
- map["target"],
- map["forceLateLoweringForTesting"] ?? false,
- map["trackWidgetCreation"] ?? false,
- map["incrementalSerialization"],
- map["nnbdMode"] == "strong" ? NnbdMode.Strong : NnbdMode.Weak,
- );
+ result = await new NewWorldTest(
+ data: data,
+ context: context,
+ omitPlatform: map["omitPlatform"] != false,
+ forceLateLoweringForTesting:
+ map["forceLateLoweringForTesting"] ?? false,
+ trackWidgetCreation: map["trackWidgetCreation"] ?? false,
+ incrementalSerialization: map["incrementalSerialization"] ?? false,
+ nnbdMode:
+ map["nnbdMode"] == "strong" ? NnbdMode.Strong : NnbdMode.Weak,
+ targetName: map["target"],
+ ).newWorldTest();
break;
default:
throw "Unexpected type: ${map['type']}";
@@ -532,7 +527,404 @@
return moduleResult;
}
+String doStringReplacements(String input) {
+ Version enableNonNullableVersion =
+ ExperimentalFlag.nonNullable.experimentEnabledVersion;
+ String output = input.replaceAll("%NNBD_VERSION_MARKER%",
+ "${enableNonNullableVersion.major}.${enableNonNullableVersion.minor}");
+ return output;
+}
+
+class ExpressionCompilation {
+ final bool errors;
+ final bool warnings;
+ final String uri;
+ final String expression;
+
+ ExpressionCompilation(
+ {required this.errors,
+ required this.warnings,
+ required this.uri,
+ required this.expression});
+
+ static ExpressionCompilation create(Map yaml) {
+ Set<String> keys = new Set<String>.from(yaml.keys);
+
+ bool errors = checkTypeOrNull<bool>(yaml, keys, "errors") ?? false;
+ bool warnings = checkTypeOrNull<bool>(yaml, keys, "warnings") ?? false;
+ String uri = checkType<String>(yaml, keys, "uri");
+ String expression = checkType<String>(yaml, keys, "expression");
+
+ if (keys.isNotEmpty) {
+ throw "Unknown key(s) for ExpressionCompilation: $keys";
+ }
+ return new ExpressionCompilation(
+ errors: errors, warnings: warnings, uri: uri, expression: expression);
+ }
+}
+
+T checkType<T>(Map world, Set<String> keys, String key, {Set<T>? options}) {
+ dynamic data = world[key];
+ keys.remove(key);
+ if (data == null) throw "Expected '$key' to have non-null value.";
+ if (data is! T) throw "Expected '$key' to be a '$T'.";
+ if (options != null) {
+ if (!options.contains(data)) {
+ throw "Got '$data' for '$key' but expected one of $options";
+ }
+ }
+ return data;
+}
+
+T? checkTypeOrNull<T>(Map world, Set<String> keys, String key,
+ {Set<T>? options}) {
+ dynamic data = world[key];
+ keys.remove(key);
+ if (data == null) return null;
+ if (data is! T) {
+ throw "Expected '$key' to be a '$T' but was '${data.runtimeType}'";
+ }
+ if (options != null) {
+ if (!options.contains(data)) {
+ throw "Got '$data' for '$key' but expected one of $options";
+ }
+ }
+ return data;
+}
+
+T? checkTypeEnumOrNull<T extends Enum>(
+ Map world, Set<String> keys, String key, List<T> enums) {
+ String? enumValue = checkTypeOrNull<String>(world, keys, key,
+ options: new Set<String>.from(enums.map((e) => e.name)));
+ if (enumValue == null) return null;
+ return enums.where((element) => element.name == enumValue).single;
+}
+
+List<T>? checkTypeListOrNull<T>(Map world, Set<String> keys, String key) {
+ List? list = checkTypeOrNull<List>(world, keys, key);
+ if (list == null) return null;
+ try {
+ return new List<T>.from(list);
+ } catch (e) {
+ throw "Expected the list to contain '$T' for '$key' but failed: $e";
+ }
+}
+
+Map<K, V>? checkTypeMapOrNull<K, V>(Map world, Set<String> keys, String key) {
+ Map? map = checkTypeOrNull<Map>(world, keys, key);
+ if (map == null) return null;
+ try {
+ return new Map<K, V>.from(map);
+ } catch (e) {
+ throw "Expected the map to contain '<$K, $V>' for '$key' but failed: $e";
+ }
+}
+
+Map<K, List<V>>? checkTypeMapListOrNull<K, V>(
+ Map world, Set<String> keys, String key) {
+ Map? map = checkTypeOrNull<Map>(world, keys, key);
+ if (map == null) return null;
+ try {
+ Map<K, List<V>> result = {};
+ for (var entry in map.entries) {
+ result[entry.key] = new List<V>.from(entry.value);
+ }
+ return result;
+ } catch (e) {
+ throw "Expected the map to contain '<$K, $V>' for '$key' but failed: $e";
+ }
+}
+
+List<T>? checkTypeSingletonOrListOrNull<T>(
+ Map world, Set<String> keys, String key) {
+ dynamic data = world[key];
+ keys.remove(key);
+
+ if (data == null) return null;
+ if (data is T) return [data];
+ if (data is List) {
+ try {
+ return new List<T>.from(data);
+ } catch (e) {
+ throw "Expected the list to contain '$T' for '$key' but failed: $e";
+ }
+ }
+ throw "Expected '$key' to be a '$T' or List<$T>";
+}
+
+List<T> checkTypeSingletonOrList<T>(Map world, Set<String> keys, String key) {
+ List<T>? data = checkTypeSingletonOrListOrNull(world, keys, key);
+ if (data == null) throw "Expected non-null value for '$key'";
+ return data;
+}
+
+class World {
+ final List<String>? modules;
+ final bool updateWorldType;
+ final bool noFullComponent;
+ final bool? expectInitializeFromDill;
+ final Map<String, String?> sources;
+ final bool useBadSdk;
+ final bool enableStringReplacement;
+ final String? packageConfigFile;
+ final String? experiments;
+ final String? nnbdModeString;
+ final List<String> entries;
+ final bool outlineOnly;
+ final bool skipOutlineBodyCheck;
+ final bool fromComponent;
+ final List<String>? invalidate;
+ final bool simulateTransformer;
+ final bool? expectInitializationError;
+ final bool compareToPrevious;
+ final List<String>? uriToSourcesDoesntInclude;
+ final List<String>? uriToSourcesOnlyIncludes;
+ final bool skipClassHierarchyTest;
+ final bool expectsPlatform;
+ final int? expectedLibraryCount;
+ final int? expectedSyntheticLibraryCount;
+ final bool warnings;
+ final bool errors;
+ final List<String>? neededDillLibraries;
+ final Map<String, List<String>>? expectedContent;
+ final bool incrementalSerializationDoesWork;
+
+ /// The expected result of the advanced invalidation.
+ final AdvancedInvalidationResult? advancedInvalidation;
+
+ final bool checkEntries;
+ final bool checkInvalidatedFiles;
+ final List<String>? expectedInvalidatedUri;
+ final int? expectSameErrorsAsWorld;
+ final List<ExpressionCompilation>? expressionCompilation;
+ final bool compareWithFromScratch;
+
+ /// Don't check for equality when we allow it to be different
+ /// (e.g. when the old one contains more, and the new one doesn't).
+ final bool brandNewIncrementalSerializationAllowDifferent;
+
+ final List<String>? serializationShouldNotInclude;
+
+ World({
+ required this.modules,
+ required this.updateWorldType,
+ required this.noFullComponent,
+ required this.expectInitializeFromDill,
+ required this.sources,
+ required this.useBadSdk,
+ required this.enableStringReplacement,
+ required this.packageConfigFile,
+ required this.experiments,
+ required this.nnbdModeString,
+ required this.entries,
+ required this.outlineOnly,
+ required this.skipOutlineBodyCheck,
+ required this.fromComponent,
+ required this.invalidate,
+ required this.simulateTransformer,
+ required this.expectInitializationError,
+ required this.compareToPrevious,
+ required this.uriToSourcesDoesntInclude,
+ required this.uriToSourcesOnlyIncludes,
+ required this.skipClassHierarchyTest,
+ required this.expectsPlatform,
+ required this.expectedLibraryCount,
+ required this.expectedSyntheticLibraryCount,
+ required this.advancedInvalidation,
+ required this.checkEntries,
+ required this.checkInvalidatedFiles,
+ required this.expectedInvalidatedUri,
+ required this.expectSameErrorsAsWorld,
+ required this.expressionCompilation,
+ required this.compareWithFromScratch,
+ required this.brandNewIncrementalSerializationAllowDifferent,
+ required this.warnings,
+ required this.errors,
+ required this.neededDillLibraries,
+ required this.expectedContent,
+ required this.incrementalSerializationDoesWork,
+ required this.serializationShouldNotInclude,
+ });
+
+ static World create(Map world) {
+ Set<String> keys = new Set<String>.from(world.keys);
+
+ List<String>? modules = checkTypeListOrNull<String>(world, keys, "modules");
+
+ String? worldType =
+ checkTypeOrNull(world, keys, "worldType", options: {"updated"});
+ bool updateWorldType = worldType == "updated";
+
+ bool noFullComponent =
+ checkTypeOrNull<bool>(world, keys, "noFullComponent") ?? false;
+
+ bool? expectInitializeFromDill =
+ checkTypeOrNull<bool>(world, keys, "expectInitializeFromDill");
+
+ Map<String, String?> sources =
+ checkTypeMapOrNull<String, String?>(world, keys, "sources") ?? {};
+
+ bool useBadSdk = checkTypeOrNull<bool>(world, keys, "badSdk") ?? false;
+
+ bool enableStringReplacement =
+ checkTypeOrNull<bool>(world, keys, "enableStringReplacement") ?? false;
+
+ String? packageConfigFile =
+ checkTypeOrNull<String>(world, keys, "packageConfigFile");
+
+ String? experiments = checkTypeOrNull<String>(world, keys, "experiments");
+
+ String? nnbdModeString =
+ checkTypeOrNull<String>(world, keys, "nnbdMode", options: {"strong"});
+
+ List<String> entries =
+ checkTypeSingletonOrList<String>(world, keys, "entry");
+
+ bool outlineOnly =
+ checkTypeOrNull<bool>(world, keys, "outlineOnly") ?? false;
+
+ bool skipOutlineBodyCheck =
+ checkTypeOrNull<bool>(world, keys, "skipOutlineBodyCheck") ?? false;
+
+ bool fromComponent =
+ checkTypeOrNull<bool>(world, keys, "fromComponent") ?? false;
+
+ List<String>? invalidate =
+ checkTypeListOrNull<String>(world, keys, "invalidate");
+
+ bool simulateTransformer =
+ checkTypeOrNull<bool>(world, keys, "simulateTransformer") ?? false;
+
+ bool? expectInitializationError =
+ checkTypeOrNull<bool>(world, keys, "expectInitializationError");
+
+ bool compareToPrevious =
+ checkTypeOrNull<bool>(world, keys, "compareToPrevious") ?? false;
+
+ List<String>? uriToSourcesDoesntInclude =
+ checkTypeListOrNull<String>(world, keys, "uriToSourcesDoesntInclude");
+
+ List<String>? uriToSourcesOnlyIncludes =
+ checkTypeListOrNull<String>(world, keys, "uriToSourcesOnlyIncludes");
+
+ bool skipClassHierarchyTest =
+ checkTypeOrNull<bool>(world, keys, "skipClassHierarchyTest") ?? false;
+
+ bool expectsPlatform =
+ checkTypeOrNull<bool>(world, keys, "expectsPlatform") ?? false;
+
+ int? expectedLibraryCount =
+ checkTypeOrNull<int>(world, keys, "expectedLibraryCount");
+
+ int? expectedSyntheticLibraryCount =
+ checkTypeOrNull<int>(world, keys, "expectedSyntheticLibraryCount");
+
+ /// The expected result of the advanced invalidation.
+ AdvancedInvalidationResult? advancedInvalidation =
+ checkTypeEnumOrNull<AdvancedInvalidationResult>(world, keys,
+ "advancedInvalidation", AdvancedInvalidationResult.values);
+
+ bool checkEntries =
+ checkTypeOrNull<bool>(world, keys, "checkEntries") ?? true;
+
+ bool checkInvalidatedFiles =
+ checkTypeOrNull<bool>(world, keys, "checkInvalidatedFiles") ?? true;
+
+ List<String>? expectedInvalidatedUri =
+ checkTypeListOrNull<String>(world, keys, "expectedInvalidatedUri");
+
+ int? expectSameErrorsAsWorld =
+ checkTypeOrNull<int>(world, keys, "expectSameErrorsAsWorld");
+
+ List<Map>? expressionCompilationRaw = checkTypeSingletonOrListOrNull<Map>(
+ world, keys, "expressionCompilation");
+ List<ExpressionCompilation>? expressionCompilation =
+ expressionCompilationRaw
+ ?.map((e) => ExpressionCompilation.create(e))
+ .toList();
+
+ bool compareWithFromScratch =
+ checkTypeOrNull<bool>(world, keys, "compareWithFromScratch") ?? false;
+
+ bool brandNewIncrementalSerializationAllowDifferent = checkTypeOrNull<bool>(
+ world, keys, "brandNewIncrementalSerializationAllowDifferent") ??
+ false;
+
+ bool warnings = checkTypeOrNull<bool>(world, keys, "warnings") ?? false;
+
+ bool errors = checkTypeOrNull<bool>(world, keys, "errors") ?? false;
+
+ List<String>? neededDillLibraries =
+ checkTypeListOrNull<String>(world, keys, "neededDillLibraries");
+
+ Map<String, List<String>>? expectedContent =
+ checkTypeMapListOrNull<String, String>(world, keys, "expectedContent");
+
+ bool incrementalSerializationDoesWork = checkTypeOrNull<bool>(
+ world, keys, "incrementalSerializationDoesWork") ??
+ false;
+
+ List<String>? serializationShouldNotInclude = checkTypeListOrNull<String>(
+ world, keys, "serializationShouldNotInclude");
+
+ if (keys.isNotEmpty) {
+ throw "Unknown key(s) for World: $keys";
+ }
+
+ return new World(
+ modules: modules,
+ updateWorldType: updateWorldType,
+ noFullComponent: noFullComponent,
+ expectInitializeFromDill: expectInitializeFromDill,
+ sources: sources,
+ useBadSdk: useBadSdk,
+ enableStringReplacement: enableStringReplacement,
+ packageConfigFile: packageConfigFile,
+ experiments: experiments,
+ nnbdModeString: nnbdModeString,
+ entries: entries,
+ outlineOnly: outlineOnly,
+ skipOutlineBodyCheck: skipOutlineBodyCheck,
+ fromComponent: fromComponent,
+ invalidate: invalidate,
+ simulateTransformer: simulateTransformer,
+ expectInitializationError: expectInitializationError,
+ compareToPrevious: compareToPrevious,
+ uriToSourcesDoesntInclude: uriToSourcesDoesntInclude,
+ uriToSourcesOnlyIncludes: uriToSourcesOnlyIncludes,
+ skipClassHierarchyTest: skipClassHierarchyTest,
+ expectsPlatform: expectsPlatform,
+ expectedLibraryCount: expectedLibraryCount,
+ expectedSyntheticLibraryCount: expectedSyntheticLibraryCount,
+ advancedInvalidation: advancedInvalidation,
+ checkEntries: checkEntries,
+ checkInvalidatedFiles: checkInvalidatedFiles,
+ expectedInvalidatedUri: expectedInvalidatedUri,
+ expectSameErrorsAsWorld: expectSameErrorsAsWorld,
+ expressionCompilation: expressionCompilation,
+ compareWithFromScratch: compareWithFromScratch,
+ brandNewIncrementalSerializationAllowDifferent:
+ brandNewIncrementalSerializationAllowDifferent,
+ warnings: warnings,
+ errors: errors,
+ neededDillLibraries: neededDillLibraries,
+ expectedContent: expectedContent,
+ incrementalSerializationDoesWork: incrementalSerializationDoesWork,
+ serializationShouldNotInclude: serializationShouldNotInclude,
+ );
+ }
+}
+
class NewWorldTest {
+ final TestData data;
+ final Context context;
+ final bool omitPlatform;
+ final bool forceLateLoweringForTesting;
+ final bool trackWidgetCreation;
+ final bool incrementalSerialization;
+ final NnbdMode nnbdMode;
+ final String? targetName;
+
// These are fields in a class to make it easier to track down memory leaks
// via the leak detector test.
Component? newestWholeComponent;
@@ -541,25 +933,22 @@
Component? component2;
Component? component3;
- String doStringReplacements(String input) {
- Version enableNonNullableVersion =
- ExperimentalFlag.nonNullable.experimentEnabledVersion;
- String output = input.replaceAll("%NNBD_VERSION_MARKER%",
- "${enableNonNullableVersion.major}.${enableNonNullableVersion.minor}");
- return output;
- }
+ NewWorldTest({
+ required this.data,
+ required this.context,
+ required this.omitPlatform,
+ required this.forceLateLoweringForTesting,
+ required this.trackWidgetCreation,
+ required this.incrementalSerialization,
+ required this.nnbdMode,
+ required this.targetName,
+ });
- Future<Result<TestData>> newWorldTest(
- TestData data,
- Context context,
- List worlds,
- Map? modules,
- bool? omitPlatform,
- String? targetName,
- bool forceLateLoweringForTesting,
- bool trackWidgetCreation,
- bool? incrementalSerialization,
- NnbdMode nnbdMode) async {
+ List<World> get worlds =>
+ (data.map["worlds"] as List).map((e) => World.create(e)).toList();
+ Map? get modules => data.map["modules"];
+
+ Future<Result<TestData>> newWorldTest() async {
final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
TestTargetFlags targetFlags = new TestTargetFlags(
@@ -608,7 +997,7 @@
if (modules != null) {
moduleData = await createModules(
- modules, sdkSummaryData, target, originalTarget, sdkSummary,
+ modules!, sdkSummaryData, target, originalTarget, sdkSummary,
trackNeededDillLibraries: false);
sdk = newestWholeComponent = new Component();
new BinaryBuilder(sdkSummaryData,
@@ -619,13 +1008,13 @@
int worldNum = 0;
// TODO: When needed, we can do this for warnings too.
List<Set<String>> worldErrors = [];
- for (YamlMap world in worlds) {
+ for (World world in worlds) {
worldNum++;
print("----------------");
print("World #$worldNum");
print("----------------");
List<Component>? modulesToUse;
- if (world["modules"] != null) {
+ if (world.modules != null) {
moduleComponents ??= new Map<String, Component>();
sdk!.adoptChildren();
@@ -634,13 +1023,13 @@
}
modulesToUse = <Component>[];
- for (String moduleName in world["modules"]) {
+ for (String moduleName in world.modules!) {
Component? moduleComponent = moduleComponents[moduleName];
if (moduleComponent != null) {
modulesToUse.add(moduleComponent);
}
}
- for (String moduleName in world["modules"]) {
+ for (String moduleName in world.modules!) {
Component? moduleComponent = moduleComponents[moduleName];
if (moduleComponent == null) {
moduleComponent = new Component(nameRoot: sdk!.root);
@@ -655,16 +1044,7 @@
}
}
- bool brandNewWorld = true;
- if (world["worldType"] == "updated") {
- brandNewWorld = false;
- }
- bool noFullComponent = false;
- if (world["noFullComponent"] == true) {
- noFullComponent = true;
- }
-
- if (brandNewWorld) {
+ if (!world.updateWorldType) {
fs = new TestMemoryFileSystem(base);
}
fs!.entityForUri(sdkSummaryUri).writeAsBytesSync(sdkSummaryData);
@@ -676,14 +1056,13 @@
.writeAsBytesSync(newestWholeComponentData);
expectInitializeFromDill = true;
}
- if (world["expectInitializeFromDill"] != null) {
- expectInitializeFromDill = world["expectInitializeFromDill"];
+ if (world.expectInitializeFromDill != null) {
+ expectInitializeFromDill = world.expectInitializeFromDill!;
}
- if (brandNewWorld) {
- sourceFiles = new Map<String, String?>.from(world["sources"]);
+ if (!world.updateWorldType) {
+ sourceFiles = new Map<String, String?>.from(world.sources);
} else {
- sourceFiles!.addAll(new Map<String, String?>.from(
- world["sources"] ?? <String, String?>{}));
+ sourceFiles!.addAll(new Map<String, String?>.from(world.sources));
}
Uri? packagesUri;
for (String filename in sourceFiles.keys) {
@@ -692,28 +1071,28 @@
if (filename == ".dart_tool/package_config.json") {
packagesUri = uri;
}
- if (world["enableStringReplacement"] == true) {
+ if (world.enableStringReplacement) {
data = doStringReplacements(data);
}
fs.entityForUri(uri).writeAsStringSync(data);
}
- if (world["packageConfigFile"] != null) {
- packagesUri = base.resolve(world["packageConfigFile"]);
+ if (world.packageConfigFile != null) {
+ packagesUri = base.resolve(world.packageConfigFile!);
}
- if (brandNewWorld) {
+ if (!world.updateWorldType) {
options = getOptions(target: target, sdkSummary: sdkSummary);
options.nnbdMode = nnbdMode;
options.fileSystem = fs;
options.sdkRoot = null;
options.sdkSummary = sdkSummaryUri;
- if (world["badSdk"] == true) {
+ if (world.useBadSdk) {
options.sdkSummary = sdkSummaryUri.resolve("nonexisting.dill");
}
- options.omitPlatform = omitPlatform != false;
- if (world["experiments"] != null) {
+ options.omitPlatform = omitPlatform;
+ if (world.experiments != null) {
Map<String, bool> flagsFromOptions =
- parseExperimentalArguments([world["experiments"]]);
+ parseExperimentalArguments([world.experiments!]);
// Ensure that we run with non-nullable turned off even when the
// flag is on by default.
Map<ExperimentalFlag, bool> explicitExperimentalFlags =
@@ -726,8 +1105,8 @@
}
// A separate "world" can also change nnbd mode ---
// notice that the platform is not updated though!
- if (world["nnbdMode"] != null) {
- String nnbdMode = world["nnbdMode"];
+ if (world.nnbdModeString != null) {
+ String nnbdMode = world.nnbdModeString!;
switch (nnbdMode) {
case "strong":
options.nnbdMode = NnbdMode.Strong;
@@ -769,32 +1148,21 @@
}
};
- List<Uri> entries;
- if (world["entry"] is String) {
- entries = [base.resolve(world["entry"])];
- } else {
- entries = <Uri>[];
- List<dynamic> entryList = world["entry"];
- for (String entry in entryList) {
- entries.add(base.resolve(entry));
- }
- }
- bool outlineOnly = world["outlineOnly"] == true;
- bool skipOutlineBodyCheck = world["skipOutlineBodyCheck"] == true;
- if (brandNewWorld) {
+ List<Uri> entries = world.entries.map((e) => base.resolve(e)).toList();
+ if (!world.updateWorldType) {
if (incrementalSerialization == true) {
incrementalSerializer = new IncrementalSerializer();
}
- if (world["fromComponent"] == true) {
+ if (world.fromComponent) {
compiler = new TestIncrementalCompiler.fromComponent(
options,
entries.first,
(modulesToUse != null) ? sdk : newestWholeComponent,
- outlineOnly,
+ world.outlineOnly,
incrementalSerializer);
} else {
compiler = new TestIncrementalCompiler(options, entries.first,
- initializeFrom, outlineOnly, incrementalSerializer);
+ initializeFrom, world.outlineOnly, incrementalSerializer);
if (modulesToUse != null) {
throw "You probably shouldn't do this! "
@@ -804,8 +1172,8 @@
}
List<Uri> invalidated = <Uri>[];
- if (world["invalidate"] != null) {
- for (String filename in world["invalidate"]) {
+ if (world.invalidate != null) {
+ for (String filename in world.invalidate!) {
Uri uri = base.resolve(filename);
invalidated.add(uri);
compiler!.invalidate(uri);
@@ -820,14 +1188,15 @@
Stopwatch stopwatch = new Stopwatch()..start();
IncrementalCompilerResult? compilerResult = await compiler!.computeDelta(
entryPoints: entries,
- fullComponent:
- brandNewWorld ? false : (noFullComponent ? false : true),
+ fullComponent: !world.updateWorldType
+ ? false
+ : (world.noFullComponent ? false : true),
trackNeededDillLibraries: modulesToUse != null,
- simulateTransformer: world["simulateTransformer"]);
+ simulateTransformer: world.simulateTransformer);
component = compilerResult.component;
// compilerResult is null'ed out at the end to avoid any
// "artificial memory leak" on that account.
- if (outlineOnly && !skipOutlineBodyCheck) {
+ if (world.outlineOnly && !world.skipOutlineBodyCheck) {
for (Library lib in component!.libraries) {
for (Class c in lib.classes) {
for (Procedure p in c.procedures) {
@@ -847,19 +1216,20 @@
Result<TestData>? result = performErrorAndWarningCheck(world, data,
gotError, formattedErrors, gotWarning, formattedWarnings);
if (result != null) return result;
- if (world["expectInitializationError"] != null) {
+ bool? expectInitializationError = world.expectInitializationError;
+ if (expectInitializationError != null) {
Set<String> seenInitializationError = seenDiagnosticCodes.intersection({
"InitializeFromDillNotSelfContainedNoDump",
"InitializeFromDillNotSelfContained",
"InitializeFromDillUnknownProblem",
"InitializeFromDillUnknownProblemNoDump",
});
- if (world["expectInitializationError"] == true) {
+ if (expectInitializationError) {
if (seenInitializationError.isEmpty) {
return new Result<TestData>(data, MissingInitializationError,
"Expected to see an initialization error but didn't.");
}
- } else if (world["expectInitializationError"] == false) {
+ } else {
if (seenInitializationError.isNotEmpty) {
return new Result<TestData>(
data,
@@ -867,9 +1237,6 @@
"Expected not to see an initialization error but did: "
"$seenInitializationError.");
}
- } else {
- throw "Unsupported value for 'expectInitializationError': "
- "${world["expectInitializationError"]}";
}
}
util.throwOnEmptyMixinBodies(component!);
@@ -886,7 +1253,7 @@
Result? nnbdCheck = checkNNBDSettings(component!);
if (nnbdCheck != null) return nnbdCheck.copyWithOutput(data);
- if (!noFullComponent) {
+ if (!world.noFullComponent) {
Set<Library> allLibraries = new Set<Library>();
for (Library lib in component!.libraries) {
computeAllReachableLibrariesFor(lib, allLibraries);
@@ -917,7 +1284,7 @@
result = checkExpectFile(data, worldNum, "", context, actualSerialized);
if (result != null) return result;
- if (world["compareToPrevious"] == true && newestWholeComponent != null) {
+ if (world.compareToPrevious && newestWholeComponent != null) {
EquivalenceResult result = checkEquivalence(
newestWholeComponent!, component!,
strategy: const Strategy());
@@ -930,8 +1297,8 @@
newestWholeComponentData = util.postProcess(component!);
newestWholeComponent = component;
- if (world["uriToSourcesDoesntInclude"] != null) {
- for (String filename in world["uriToSourcesDoesntInclude"]) {
+ if (world.uriToSourcesDoesntInclude != null) {
+ for (String filename in world.uriToSourcesDoesntInclude!) {
Uri uri = base.resolve(filename);
if (component!.uriToSource[uri] != null) {
return new Result<TestData>(
@@ -942,9 +1309,9 @@
}
}
}
- if (world["uriToSourcesOnlyIncludes"] != null) {
+ if (world.uriToSourcesOnlyIncludes != null) {
Set<Uri> allowed = {};
- for (String filename in world["uriToSourcesOnlyIncludes"]) {
+ for (String filename in world.uriToSourcesOnlyIncludes!) {
Uri uri = base.resolve(filename);
allowed.add(uri);
}
@@ -963,7 +1330,7 @@
}
}
- if (world["skipClassHierarchyTest"] != true) {
+ if (!world.skipClassHierarchyTest) {
result = checkClassHierarchy(compilerResult, data, worldNum, context);
if (result != null) return result;
}
@@ -972,7 +1339,7 @@
int nonSyntheticPlatformLibraries =
countNonSyntheticPlatformLibraries(component!);
int syntheticLibraries = countSyntheticLibraries(component!);
- if (world["expectsPlatform"] == true) {
+ if (world.expectsPlatform) {
if (nonSyntheticPlatformLibraries < 5) {
return new Result<TestData>(
data,
@@ -990,45 +1357,44 @@
"but got $nonSyntheticPlatformLibraries.");
}
}
- if (world["expectedLibraryCount"] != null) {
+ if (world.expectedLibraryCount != null) {
if (nonSyntheticLibraries - nonSyntheticPlatformLibraries !=
- world["expectedLibraryCount"]) {
+ world.expectedLibraryCount!) {
return new Result<TestData>(
data,
LibraryCountMismatch,
- "Expected ${world["expectedLibraryCount"]} non-synthetic "
+ "Expected ${world.expectedLibraryCount} non-synthetic "
"libraries, got "
"${nonSyntheticLibraries - nonSyntheticPlatformLibraries} "
"(not counting platform libraries)");
}
}
- if (world["expectedSyntheticLibraryCount"] != null) {
- if (syntheticLibraries != world["expectedSyntheticLibraryCount"]) {
+ if (world.expectedSyntheticLibraryCount != null) {
+ if (syntheticLibraries != world.expectedSyntheticLibraryCount!) {
return new Result<TestData>(
data,
LibraryCountMismatch,
- "Expected ${world["expectedSyntheticLibraryCount"]} synthetic "
+ "Expected ${world.expectedSyntheticLibraryCount} synthetic "
"libraries, got ${syntheticLibraries}");
}
}
- String? expectedAdvancedInvalidation = world[Flags.advancedInvalidation];
- if (expectedAdvancedInvalidation != null) {
+ if (world.advancedInvalidation != null) {
AdvancedInvalidationResult? actualAdvancedInvalidation =
compiler.recorderForTesting.advancedInvalidationResult;
- if (expectedAdvancedInvalidation != actualAdvancedInvalidation?.name) {
+ if (world.advancedInvalidation != actualAdvancedInvalidation) {
return new Result<TestData>(
data,
UnexpectedAdvancedInvalidation,
- "Expected ${Flags.advancedInvalidation}: "
- "$expectedAdvancedInvalidation, "
- "${Flags.advancedInvalidation}: "
- "${actualAdvancedInvalidation?.name}.");
+ "Expected advancedInvalidation: "
+ "${world.advancedInvalidation}, "
+ "advancedInvalidation: "
+ "${actualAdvancedInvalidation}.");
}
}
- if (!noFullComponent) {
- if (world["checkEntries"] != false) {
+ if (!world.noFullComponent) {
+ if (world.checkEntries) {
List<Library> entryLib = component!.libraries
.where((Library lib) =>
entries.contains(lib.importUri) ||
@@ -1060,20 +1426,20 @@
Expect.isFalse(compiler.initializedIncrementalSerializerForTesting);
}
- if (world["checkInvalidatedFiles"] != false) {
+ if (world.checkInvalidatedFiles) {
Set<Uri>? filteredInvalidated =
compiler.getFilteredInvalidatedImportUrisForTesting(invalidated);
- if (world["invalidate"] != null) {
+ if (world.invalidate != null) {
Expect.equals(
- world["invalidate"].length, filteredInvalidated?.length ?? 0);
- List? expectedInvalidatedUri = world["expectedInvalidatedUri"];
- if (expectedInvalidatedUri != null) {
- Expect.setEquals(expectedInvalidatedUri.map((s) => base.resolve(s)),
+ world.invalidate!.length, filteredInvalidated?.length ?? 0);
+ if (world.expectedInvalidatedUri != null) {
+ Expect.setEquals(
+ world.expectedInvalidatedUri!.map((s) => base.resolve(s)),
filteredInvalidated!);
}
} else {
Expect.isNull(filteredInvalidated);
- Expect.isNull(world["expectedInvalidatedUri"]);
+ Expect.isNull(world.expectedInvalidatedUri);
}
}
Result<List<int>?> serializationResult = checkIncrementalSerialization(
@@ -1085,10 +1451,9 @@
worldErrors.add(formattedErrors.toSet());
assert(worldErrors.length == worldNum);
- if (world["expectSameErrorsAsWorld"] != null) {
- int expectSameErrorsAsWorld = world["expectSameErrorsAsWorld"];
+ if (world.expectSameErrorsAsWorld != null) {
checkErrorsAndWarnings(
- worldErrors[expectSameErrorsAsWorld - 1],
+ worldErrors[world.expectSameErrorsAsWorld! - 1],
formattedErrors,
{},
{},
@@ -1105,13 +1470,13 @@
formattedWarnings.clear();
}
- if (!noFullComponent) {
+ if (!world.noFullComponent) {
clearPrevErrorsEtc();
IncrementalCompilerResult? compilerResult2 =
await compiler.computeDelta(
entryPoints: entries,
fullComponent: true,
- simulateTransformer: world["simulateTransformer"]);
+ simulateTransformer: world.simulateTransformer);
component2 = compilerResult2.component;
compilerResult2 = null;
Result<TestData>? result = performErrorAndWarningCheck(world, data,
@@ -1152,37 +1517,29 @@
}
}
- if (world["expressionCompilation"] != null) {
- List compilations;
- if (world["expressionCompilation"] is List) {
- compilations = world["expressionCompilation"];
- } else {
- compilations = [world["expressionCompilation"]];
- }
+ if (world.expressionCompilation != null) {
int expressionCompilationNum = 0;
- for (Map compilation in compilations) {
+ for (ExpressionCompilation compilation
+ in world.expressionCompilation!) {
expressionCompilationNum++;
clearPrevErrorsEtc();
- bool expectErrors = compilation["errors"] ?? false;
- bool expectWarnings = compilation["warnings"] ?? false;
- Uri uri = base.resolve(compilation["uri"]);
- String expression = compilation["expression"];
+ Uri uri = base.resolve(compilation.uri);
Procedure procedure = (await compiler.compileExpression(
- expression, {}, [], "debugExpr", uri))!;
- if (gotError && !expectErrors) {
+ compilation.expression, {}, [], "debugExpr", uri))!;
+ if (gotError && !compilation.errors) {
return new Result<TestData>(data, UnexpectedErrors,
"Got error(s) on expression compilation: ${formattedErrors}.");
- } else if (!gotError && expectErrors) {
+ } else if (!gotError && compilation.errors) {
return new Result<TestData>(
data, MissingErrors, "Didn't get any errors.");
}
- if (gotWarning && !expectWarnings) {
+ if (gotWarning && !compilation.warnings) {
return new Result<TestData>(
data,
UnexpectedWarnings,
"Got warning(s) on expression compilation: "
"${formattedWarnings}.");
- } else if (!gotWarning && expectWarnings) {
+ } else if (!gotWarning && compilation.warnings) {
return new Result<TestData>(
data, MissingWarnings, "Didn't get any warnings.");
}
@@ -1196,9 +1553,8 @@
}
}
- if (!noFullComponent &&
- (incrementalSerialization == true ||
- world["compareWithFromScratch"] == true)) {
+ if (!world.noFullComponent &&
+ (incrementalSerialization == true || world.compareWithFromScratch)) {
// Do compile from scratch and compare.
clearPrevErrorsEtc();
TestIncrementalCompiler? compilerFromScratch;
@@ -1208,12 +1564,16 @@
incrementalSerializer2 = new IncrementalSerializer();
}
- if (world["fromComponent"] == true || modulesToUse != null) {
+ if (world.fromComponent || modulesToUse != null) {
compilerFromScratch = new TestIncrementalCompiler.fromComponent(
- options, entries.first, sdk, outlineOnly, incrementalSerializer2);
+ options,
+ entries.first,
+ sdk,
+ world.outlineOnly,
+ incrementalSerializer2);
} else {
compilerFromScratch = new TestIncrementalCompiler(options,
- entries.first, null, outlineOnly, incrementalSerializer2);
+ entries.first, null, world.outlineOnly, incrementalSerializer2);
}
if (modulesToUse != null) {
@@ -1226,7 +1586,7 @@
await compilerFromScratch.computeDelta(
entryPoints: entries,
trackNeededDillLibraries: modulesToUse != null,
- simulateTransformer: world["simulateTransformer"]);
+ simulateTransformer: world.simulateTransformer);
component3 = compilerResult3.component;
compilerResult3 = null;
compilerFromScratch = null;
@@ -1240,7 +1600,7 @@
List<int> thisWholeComponent = util.postProcess(component3!);
print("*****\n\ncomponent3:\n"
"${componentToStringSdkFiltered(component3!)}\n\n\n");
- if (world["compareWithFromScratch"] == true) {
+ if (world.compareWithFromScratch) {
checkIsEqual(newestWholeComponentData, thisWholeComponent);
}
checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
@@ -1268,7 +1628,7 @@
}
if (incrementalSerializationBytes != null) {
- if (world["brandNewIncrementalSerializationAllowDifferent"] == true) {
+ if (world.brandNewIncrementalSerializationAllowDifferent) {
// Don't check for equality when we allow it to be different
// (e.g. when the old one contains more, and the new one doesn't).
} else {
@@ -1606,7 +1966,7 @@
bool? incrementalSerialization,
Component component,
IncrementalSerializer? incrementalSerializer,
- YamlMap world) {
+ World world) {
if (incrementalSerialization == true) {
Component c = new Component(nameRoot: component.root)
..setMainMethodAndMode(null, false, component.mode);
@@ -1622,7 +1982,7 @@
"Incremental serialization added libraries!");
}
if (librariesBefore == librariesAfter &&
- world["incrementalSerializationDoesWork"] == true) {
+ world.incrementalSerializationDoesWork) {
return new Result<List<int>>(null, IncrementalSerializationError,
"Incremental serialization didn't remove any libraries!");
}
@@ -1650,12 +2010,10 @@
new BinaryBuilder(bytes, filename: null).readComponent(loadedComponent);
// Check that it doesn't contain anything we said it shouldn't.
- if (world["serializationShouldNotInclude"] is List) {
- List serializationShouldNotInclude =
- world["serializationShouldNotInclude"];
+ if (world.serializationShouldNotInclude != null) {
Set<Uri> includedImportUris =
loadedComponent.libraries.map((l) => l.importUri).toSet();
- for (String uriString in serializationShouldNotInclude) {
+ for (String uriString in world.serializationShouldNotInclude!) {
Uri uri = Uri.parse(uriString);
if (includedImportUris.contains(uri)) {
return new Result<List<int>>(
@@ -1730,17 +2088,16 @@
}
}
-Result? checkExpectedContent(YamlMap world, Component component) {
- if (world["expectedContent"] != null) {
+Result? checkExpectedContent(World world, Component component) {
+ if (world.expectedContent != null) {
Map<String, Set<String>> actualContent = buildMapOfContent(component);
- Map expectedContent = world["expectedContent"];
- return checkExpectedContentData(actualContent, expectedContent);
+ return checkExpectedContentData(actualContent, world.expectedContent!);
}
return null;
}
-Result? checkExpectedContentData(
- Map<String, Set<String>> actualContent, Map expectedContent) {
+Result? checkExpectedContentData(Map<String, Set<String>> actualContent,
+ Map<String, Iterable<String>> expectedContent) {
Result<TestData> createFailureResult() {
return new Result(
null,
@@ -1758,9 +2115,9 @@
if (missingKeys.isNotEmpty) {
return createFailureResult();
}
- for (String key in expectedContent.keys) {
- Set<String> expected = new Set<String>.from(expectedContent[key]);
- Set<String> actual = actualContent[key]!.toSet();
+ for (MapEntry<String, Iterable<String>> entry in expectedContent.entries) {
+ Set<String> expected = new Set<String>.from(entry.value);
+ Set<String> actual = actualContent[entry.key]!.toSet();
if (expected.length != actual.length) {
return createFailureResult();
}
@@ -1791,8 +2148,8 @@
}
Result<TestData>? checkNeededDillLibraries(
- YamlMap world, TestData data, Set<Library>? neededDillLibraries, Uri base) {
- if (world["neededDillLibraries"] != null) {
+ World world, TestData data, Set<Library>? neededDillLibraries, Uri base) {
+ if (world.neededDillLibraries != null) {
List<Uri> actualContent = <Uri>[];
for (Library lib in neededDillLibraries!) {
if (lib.importUri.isScheme("dart")) continue;
@@ -1800,7 +2157,7 @@
}
List<Uri> expectedContent = <Uri>[];
- for (String entry in world["neededDillLibraries"]) {
+ for (String entry in world.neededDillLibraries!) {
expectedContent.add(base.resolve(entry));
}
@@ -1891,23 +2248,23 @@
}
Result<TestData>? performErrorAndWarningCheck(
- YamlMap world,
+ World world,
TestData data,
bool gotError,
Set<String> formattedErrors,
bool gotWarning,
Set<String> formattedWarnings) {
- if (world["errors"] == true && !gotError) {
+ if (world.errors && !gotError) {
return new Result<TestData>(
data, MissingErrors, "Expected error, but didn't get any.");
- } else if (world["errors"] != true && gotError) {
+ } else if (!world.errors && gotError) {
return new Result<TestData>(
data, UnexpectedErrors, "Got unexpected error(s): $formattedErrors.");
}
- if (world["warnings"] == true && !gotWarning) {
+ if (world.warnings && !gotWarning) {
return new Result<TestData>(
data, MissingWarnings, "Expected warning, but didn't get any.");
- } else if (world["warnings"] != true && gotWarning) {
+ } else if (!world.warnings && gotWarning) {
return new Result<TestData>(data, UnexpectedWarnings,
"Got unexpected warnings(s): $formattedWarnings.");
}
diff --git a/pkg/front_end/testcases/incremental/regress_35215.yaml b/pkg/front_end/testcases/incremental/regress_35215.yaml
index 92e35f0..522b5c8 100644
--- a/pkg/front_end/testcases/incremental/regress_35215.yaml
+++ b/pkg/front_end/testcases/incremental/regress_35215.yaml
@@ -22,7 +22,6 @@
expectedLibraryCount: 2
errors: true
- entry: main.dart
- worldTypex: updated
invalidate:
- b.dart
sources:
diff --git a/pkg/kernel/lib/default_language_version.dart b/pkg/kernel/lib/default_language_version.dart
index fcae847..b959db4 100644
--- a/pkg/kernel/lib/default_language_version.dart
+++ b/pkg/kernel/lib/default_language_version.dart
@@ -9,4 +9,4 @@
import "ast.dart";
-Version defaultLanguageVersion = const Version(2, 18);
+Version defaultLanguageVersion = const Version(2, 19);
diff --git a/runtime/vm/experimental_features.cc b/runtime/vm/experimental_features.cc
index c776db0f..ad7117f 100644
--- a/runtime/vm/experimental_features.cc
+++ b/runtime/vm/experimental_features.cc
@@ -6,7 +6,7 @@
// Instead modify 'tools/experimental_features.yaml' and run
// 'dart tools/generate_experimental_flags.dart' to update.
//
-// Current version: 2.18.0
+// Current version: 2.19.0
#include "vm/experimental_features.h"
diff --git a/runtime/vm/experimental_features.h b/runtime/vm/experimental_features.h
index be9be59..773062c 100644
--- a/runtime/vm/experimental_features.h
+++ b/runtime/vm/experimental_features.h
@@ -6,7 +6,7 @@
// Instead modify 'tools/experimental_features.yaml' and run
// 'dart tools/generate_experimental_flags.dart' to update.
//
-// Current version: 2.18.0
+// Current version: 2.19.0
#ifndef RUNTIME_VM_EXPERIMENTAL_FEATURES_H_
#define RUNTIME_VM_EXPERIMENTAL_FEATURES_H_
diff --git a/tools/VERSION b/tools/VERSION
index 005f402..e3f65ac 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -25,7 +25,7 @@
#
CHANNEL dev
MAJOR 2
-MINOR 18
+MINOR 19
PATCH 0
-PRERELEASE 286
+PRERELEASE 0
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index 7ac7dbb..2ddf600 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -103,7 +103,7 @@
# default 'language' "category" with code generated for both CFE and Analyzer,
# while other categories can be tailored more specifically.
-current-version: '2.18.0'
+current-version: '2.19.0'
features:
variance: