Version 2.17.0-262.0.dev
Merge commit 'bdf81502206a4da1975dfc2cecbf0d9ec0bb1628' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
index af3bf0f..e94c61e 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
@@ -69,15 +69,27 @@
/// Entrypoint to be spawned with [Isolate.spawnUri] or [Process.start].
///
/// Supports the client side of the macro expansion protocol.
-void main(_, [SendPort? sendPort]) {
+void main(List<String> arguments, [SendPort? sendPort]) {
// Function that sends the result of a [Serializer] using either [sendPort]
// or [stdout].
void Function(Serializer) sendResult;
- // The stream for incoming messages, could be either a ReceivePort or stdin.
+ // The stream for incoming messages, could be either a ReceivePort, stdin, or
+ // a socket.
Stream<Object?> messageStream;
- withSerializationMode($_modeMarker, () {
+ String? socketAddress;
+ int? socketPort;
+ if (arguments.isNotEmpty) {
+ if (arguments.length != 2) {
+ throw new ArgumentError(
+ 'Expected exactly two or zero arguments, got \$arguments.');
+ }
+ socketAddress = arguments.first;
+ socketPort = int.parse(arguments[1]);
+ }
+
+ withSerializationMode($_modeMarker, () async {
if (sendPort != null) {
ReceivePort receivePort = new ReceivePort();
messageStream = receivePort;
@@ -87,12 +99,20 @@
// isolate.
sendPort.send(receivePort.sendPort);
} else {
- sendResult = _sendStdoutResult;
+ late Stream<List<int>> inputStream;
+ if (socketAddress != null && socketPort != null) {
+ var socket = await Socket.connect(socketAddress, socketPort);
+ sendResult = _sendIOSinkResultFactory(socket);
+ inputStream = socket;
+ } else {
+ sendResult = _sendIOSinkResultFactory(stdout);
+ inputStream = stdin;
+ }
if (serializationMode == SerializationMode.byteDataClient) {
- messageStream = MessageGrouper(stdin).messageStream;
+ messageStream = MessageGrouper(inputStream).messageStream;
} else if (serializationMode == SerializationMode.jsonClient) {
- messageStream = stdin
- .transform(const Utf8Decoder())
+ messageStream = const Utf8Decoder()
+ .bind(inputStream)
.transform(const LineSplitter())
.map((line) => jsonDecode(line)!);
} else {
@@ -339,26 +359,28 @@
}
}
-/// Sends [serializer.result] to [stdout].
+/// Returns a function which takes a [Serializer] and sends its result to
+/// [sink].
///
/// Serializes the result to a string if using JSON.
-void _sendStdoutResult(Serializer serializer) {
- if (serializationMode == SerializationMode.jsonClient) {
- stdout.writeln(jsonEncode(serializer.result));
- } else if (serializationMode == SerializationMode.byteDataClient) {
- Uint8List result = (serializer as ByteDataSerializer).result;
- int length = result.lengthInBytes;
- stdout.add([
- length >> 24 & 0xff,
- length >> 16 & 0xff,
- length >> 8 & 0xff,
- length & 0xff,
- ]);
- stdout.add(result);
- } else {
- throw new UnsupportedError(
- 'Unsupported serialization mode \$serializationMode for '
- 'ProcessExecutor');
- }
-}
+void Function(Serializer) _sendIOSinkResultFactory(IOSink sink) =>
+ (Serializer serializer) {
+ if (serializationMode == SerializationMode.jsonClient) {
+ sink.writeln(jsonEncode(serializer.result));
+ } else if (serializationMode == SerializationMode.byteDataClient) {
+ Uint8List result = (serializer as ByteDataSerializer).result;
+ int length = result.lengthInBytes;
+ sink.add([
+ length >> 24 & 0xff,
+ length >> 16 & 0xff,
+ length >> 8 & 0xff,
+ length & 0xff,
+ ]);
+ sink.add(result);
+ } else {
+ throw new UnsupportedError(
+ 'Unsupported serialization mode \$serializationMode for '
+ 'ProcessExecutor');
+ }
+ };
''';
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
index ed67219..07b02f0 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
@@ -23,19 +23,25 @@
/// programs spawned must use the corresponding `client` variant.
///
/// This is the only public api exposed by this library.
-Future<MacroExecutor> start(SerializationMode serializationMode) async =>
+Future<MacroExecutor> start(SerializationMode serializationMode,
+ CommunicationChannel communicationChannel) async =>
new MultiMacroExecutor((Uri library, String name,
{Uri? precompiledKernelUri}) {
+ // TODO: We actually assume this is a full precompiled AOT binary, and
+ // not a kernel file. We launch it directly using `Process.start`.
if (precompiledKernelUri == null) {
throw new UnsupportedError(
'This environment requires a non-null `precompiledKernelUri` to be '
'passed when loading macros.');
}
-
- // TODO: We actually assume this is a full precompiled AOT binary, and not
- // a kernel file. We launch it directly using `Process.start`.
- return _SingleProcessMacroExecutor.start(
- library, name, serializationMode, precompiledKernelUri.toFilePath());
+ switch (communicationChannel) {
+ case CommunicationChannel.stdio:
+ return _SingleProcessMacroExecutor.startWithStdio(library, name,
+ serializationMode, precompiledKernelUri.toFilePath());
+ case CommunicationChannel.socket:
+ return _SingleProcessMacroExecutor.startWithSocket(library, name,
+ serializationMode, precompiledKernelUri.toFilePath());
+ }
});
/// Actual implementation of the separate process based macro executor.
@@ -55,8 +61,65 @@
: super(
messageStream: messageStream, serializationMode: serializationMode);
- static Future<_SingleProcessMacroExecutor> start(Uri library, String name,
- SerializationMode serializationMode, String programPath) async {
+ static Future<_SingleProcessMacroExecutor> startWithSocket(
+ Uri library,
+ String name,
+ SerializationMode serializationMode,
+ String programPath) async {
+ late ServerSocket serverSocket;
+ // Try an ipv6 address loopback first, and fall back on ipv4.
+ try {
+ serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv6, 0);
+ } on SocketException catch (_) {
+ serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
+ }
+ Process process = await Process.start(programPath, [
+ serverSocket.address.address,
+ serverSocket.port.toString(),
+ ]);
+ process.stderr
+ .transform(const Utf8Decoder())
+ .listen((content) => throw new RemoteException(content));
+ process.stdout.transform(const Utf8Decoder()).listen(
+ (event) => print('Stdout from MacroExecutor at $programPath:\n$event'));
+
+ Completer<Socket> clientCompleter = new Completer();
+ serverSocket.listen((client) {
+ clientCompleter.complete(client);
+ });
+ Socket client = await clientCompleter.future;
+
+ Stream<Object> messageStream;
+
+ if (serializationMode == SerializationMode.byteDataServer) {
+ messageStream = new MessageGrouper(client).messageStream;
+ } else if (serializationMode == SerializationMode.jsonServer) {
+ messageStream = const Utf8Decoder()
+ .bind(client)
+ .transform(const LineSplitter())
+ .map((line) => jsonDecode(line)!);
+ } else {
+ throw new UnsupportedError(
+ 'Unsupported serialization mode \$serializationMode for '
+ 'ProcessExecutor');
+ }
+
+ return new _SingleProcessMacroExecutor(
+ onClose: () {
+ client.close();
+ serverSocket.close();
+ process.kill();
+ },
+ messageStream: messageStream,
+ outSink: client,
+ serializationMode: serializationMode);
+ }
+
+ static Future<_SingleProcessMacroExecutor> startWithStdio(
+ Uri library,
+ String name,
+ SerializationMode serializationMode,
+ String programPath) async {
Process process = await Process.start(programPath, []);
process.stderr
.transform(const Utf8Decoder())
@@ -115,3 +178,8 @@
}
}
}
+
+enum CommunicationChannel {
+ socket,
+ stdio,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 36be330..a9f8bfa 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -5642,6 +5642,33 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ String
+ name)> templateInstanceAndSynthesizedStaticConflict = const Template<
+ Message Function(String name)>(
+ problemMessageTemplate:
+ r"""This instance member conflicts with the synthesized static member called '#name'.""",
+ withArguments: _withArgumentsInstanceAndSynthesizedStaticConflict);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+ codeInstanceAndSynthesizedStaticConflict =
+ const Code<Message Function(String name)>(
+ "InstanceAndSynthesizedStaticConflict",
+ analyzerCodes: <String>["CONFLICTING_STATIC_AND_INSTANCE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInstanceAndSynthesizedStaticConflict(String name) {
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
+ return new Message(codeInstanceAndSynthesizedStaticConflict,
+ problemMessage:
+ """This instance member conflicts with the synthesized static member called '${name}'.""",
+ arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(int count, int count2)>
templateInstantiationTooFewArguments =
const Template<Message Function(int count, int count2)>(
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart
index e6cf230..c70ad25 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart
@@ -11,7 +11,9 @@
import 'package:_fe_analyzer_shared/src/macros/executor/isolated_executor.dart'
as isolatedExecutor;
import 'package:_fe_analyzer_shared/src/macros/executor/process_executor.dart'
- as processExecutor;
+ as processExecutor show start;
+import 'package:_fe_analyzer_shared/src/macros/executor/process_executor.dart'
+ hide start;
import 'package:test/test.dart';
@@ -26,11 +28,15 @@
late File simpleMacroFile;
late Directory tmpDir;
- for (var executorKind in ['Isolated', 'Process']) {
+ for (var executorKind in [
+ 'Isolated',
+ 'ProcessSocket',
+ 'ProcessStdio',
+ ]) {
group('$executorKind executor', () {
for (var mode in [
SerializationMode.byteDataServer,
- SerializationMode.jsonServer
+ SerializationMode.jsonServer,
]) {
final clientMode = mode == SerializationMode.byteDataServer
? SerializationMode.byteDataClient
@@ -42,7 +48,12 @@
File(Platform.script.resolve('simple_macro.dart').toFilePath());
executor = executorKind == 'Isolated'
? await isolatedExecutor.start(mode)
- : await processExecutor.start(mode);
+ : executorKind == 'ProcessSocket'
+ ? await processExecutor.start(
+ mode, CommunicationChannel.socket)
+ : await processExecutor.start(
+ mode, CommunicationChannel.stdio);
+
tmpDir = Directory.systemTemp.createTempSync('executor_test');
macroUri = simpleMacroFile.absolute.uri;
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 57f98ce..3db8862 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -256,7 +256,10 @@
var lengthRestricted =
suggestionBuilders.take(params.maxResults).toList();
- completionPerformance.suggestionCount = lengthRestricted.length;
+ completionPerformance.computedSuggestionCount =
+ suggestionBuilders.length;
+ completionPerformance.transmittedSuggestionCount =
+ lengthRestricted.length;
var suggestions = lengthRestricted.map((e) => e.build()).toList();
@@ -477,7 +480,10 @@
);
});
- completionPerformance.suggestionCount = suggestionBuilders.length;
+ completionPerformance.computedSuggestionCount =
+ suggestionBuilders.length;
+ completionPerformance.transmittedSuggestionCount =
+ suggestionBuilders.length;
} finally {
ifMatchesRequestClear(completionRequest);
}
diff --git a/pkg/analysis_server/lib/src/lsp/client_configuration.dart b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
index 6a97756..a5ef8f7 100644
--- a/pkg/analysis_server/lib/src/lsp/client_configuration.dart
+++ b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
@@ -151,6 +151,14 @@
/// known editors allow per-file configuration and it allows us to keep the
/// settings cached, invalidated only when WorkspaceFolders change.
class LspResourceClientConfiguration {
+ /// The maximum number of completions to return for completion requests by
+ /// default.
+ ///
+ /// This has been set fairly high initially to avoid changing behaviour too
+ /// much. The Dart-Code extension will override this default with its own
+ /// to gather feedback and then this can be adjusted accordingly.
+ static const defaultMaxCompletions = 2000;
+
final Map<String, Object?> _settings;
final LspResourceClientConfiguration? _fallback;
@@ -187,6 +195,15 @@
int? get lineLength =>
_settings['lineLength'] as int? ?? _fallback?.lineLength;
+ /// Maximum number of CompletionItems per completion request.
+ ///
+ /// If more than this are available, the list is truncated and isIncomplete
+ /// is set to true.
+ int get maxCompletionItems =>
+ _settings['maxCompletionItems'] as int? ??
+ _fallback?.maxCompletionItems ??
+ defaultMaxCompletions;
+
/// Whether to rename files when renaming classes inside them where the file
/// and class name match.
///
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index f385bd1..fed7a76 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -78,13 +78,31 @@
final pathContext = server.resourceProvider.pathContext;
final fileExtension = pathContext.extension(path.result);
+ final maxResults = server.clientConfiguration
+ .forResource(path.result)
+ .maxCompletionItems;
+
+ CompletionPerformance? completionPerformance;
if (fileExtension == '.dart' && !unit.isError) {
+ final result = unit.result;
+ var performanceOperation = OperationPerformanceImpl('<root>');
+ completionPerformance = CompletionPerformance(
+ operation: performanceOperation,
+ path: result.path,
+ content: result.content,
+ offset: offset,
+ );
+ server.performanceStats.completion.add(completionPerformance);
+
serverResultsFuture = _getServerDartItems(
clientCapabilities,
- unit.result,
+ result,
+ completionPerformance,
+ performanceOperation,
offset,
triggerCharacter,
token,
+ maxResults: maxResults,
);
} else if (fileExtension == '.yaml') {
YamlCompletionGenerator? generator;
@@ -124,14 +142,25 @@
if (serverResults.isError) return serverResults;
if (pluginResults.isError) return pluginResults;
+ final untruncatedItems = serverResults.result.items
+ .followedBy(pluginResults.result.items)
+ .toList();
+
+ final truncatedItems = untruncatedItems.length > maxResults
+ ? (untruncatedItems..sort(sortTextComparer)).sublist(0, maxResults)
+ : untruncatedItems;
+
+ // If we're tracing performance (only Dart), record the number of results
+ // after truncation.
+ completionPerformance?.transmittedSuggestionCount = truncatedItems.length;
+
return success(CompletionList(
// If any set of the results is incomplete, the whole batch must be
// marked as such.
isIncomplete: serverResults.result.isIncomplete ||
- pluginResults.result.isIncomplete,
- items: serverResults.result.items
- .followedBy(pluginResults.result.items)
- .toList(),
+ pluginResults.result.isIncomplete ||
+ truncatedItems.length != untruncatedItems.length,
+ items: truncatedItems,
));
});
}
@@ -232,25 +261,19 @@
Future<ErrorOr<CompletionList>> _getServerDartItems(
LspClientCapabilities capabilities,
ResolvedUnitResult unit,
+ CompletionPerformance completionPerformance,
+ OperationPerformanceImpl operationPerformance,
int offset,
String? triggerCharacter,
- CancellationToken token,
- ) async {
+ CancellationToken token, {
+ required int maxResults,
+ }) async {
final useSuggestionSets =
suggestFromUnimportedLibraries && capabilities.applyEdit;
- var performance = OperationPerformanceImpl('<root>');
- return await performance.runAsync(
+ return await operationPerformance.runAsync(
'request',
(performance) async {
- final completionPerformance = CompletionPerformance(
- operation: performance,
- path: unit.path,
- content: unit.content,
- offset: offset,
- );
- server.performanceStats.completion.add(completionPerformance);
-
final completionRequest = DartCompletionRequest.forResolvedUnit(
resolvedUnit: unit,
offset: offset,
@@ -474,7 +497,9 @@
.where((e) => fuzzyMatcher.score(e.filterText ?? e.label) > 0)
.toList();
- completionPerformance.suggestionCount = results.length;
+ // Transmitted count will be set after combining with plugins.
+ completionPerformance.computedSuggestionCount =
+ matchingResults.length;
return success(
CompletionList(isIncomplete: false, items: matchingResults));
@@ -620,4 +645,37 @@
return true; // Any other trigger character can be handled always.
}
+
+ /// Compares [CompletionItem]s by the `sortText` field, which is derived from
+ /// relevance.
+ ///
+ /// For items with the same relevance, shorter items are sorted first so that
+ /// truncation always removes longer items first (which can be included by
+ /// typing more of their characters).
+ static int sortTextComparer(CompletionItem item1, CompletionItem item2) {
+ // Note: It should never be the case that we produce items without sortText
+ // but if they're null, fall back to label which is what the client would do
+ // when sorting.
+ final item1Text = item1.sortText ?? item1.label;
+ final item2Text = item2.sortText ?? item2.label;
+
+ // If both items have the same text, this means they had the same relevance.
+ // In this case, sort by the length of the name ascending, so that shorter
+ // items are first. This is because longer items can be obtained by typing
+ // additional characters where shorter ones may not.
+ //
+ // For example, with:
+ // - String aaa1;
+ // - String aaa2;
+ // - ...
+ // - String aaa(N); // up to past the truncation amount
+ // - String aaa; // declared last, same prefix
+ //
+ // Typing 'aaa' should not allow 'aaa' to be truncated before 'aaa1'.
+ if (item1Text == item2Text) {
+ return item1.label.length.compareTo(item2.label.length);
+ }
+
+ return item1Text.compareTo(item2Text);
+ }
}
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
index 7815def..c41731b 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
@@ -38,7 +38,8 @@
final OperationPerformance operation;
final String path;
final String snippet;
- int suggestionCount = -1;
+ int computedSuggestionCount = -1;
+ int transmittedSuggestionCount = -1;
CompletionPerformance({
required this.operation,
@@ -47,12 +48,17 @@
required int offset,
}) : snippet = _computeCompletionSnippet(content, offset);
+ String get computedSuggestionCountStr {
+ if (computedSuggestionCount < 1) return '';
+ return '$computedSuggestionCount';
+ }
+
int get elapsedInMilliseconds {
return operation.elapsed.inMilliseconds;
}
- String get suggestionCountStr {
- if (suggestionCount < 1) return '';
- return '$suggestionCount';
+ String get transmittedSuggestionCountStr {
+ if (transmittedSuggestionCount < 1) return '';
+ return '$transmittedSuggestionCount';
}
}
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 68863ac..dfaacc9 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -205,12 +205,13 @@
// emit the data as a table
buf.writeln('<table>');
buf.writeln(
- '<tr><th>Time</th><th>Results</th><th>Source</th><th>Snippet</th></tr>');
+ '<tr><th>Time</th><th>Computed Results</th><th>Transmitted Results</th><th>Source</th><th>Snippet</th></tr>');
for (var completion in completions) {
var shortName = pathContext.basename(completion.path);
buf.writeln('<tr>'
'<td class="pre right">${printMilliseconds(completion.elapsedInMilliseconds)}</td>'
- '<td class="right">${completion.suggestionCountStr}</td>'
+ '<td class="right">${completion.computedSuggestionCountStr}</td>'
+ '<td class="right">${completion.transmittedSuggestionCountStr}</td>'
'<td>${escape(shortName)}</td>'
'<td><code>${escape(completion.snippet)}</code></td>'
'</tr>');
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index 92744a4..2387349 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -973,6 +973,80 @@
expect(item.detail, isNot(contains('deprecated')));
}
+ Future<void> test_isIncomplete_falseIfAllIncluded() async {
+ final content = '''
+import 'a.dart';
+void f() {
+ A a = A();
+ a.^
+}
+ ''';
+
+ // Create a class with fields aaa1 to aaa500 in the other file.
+ newFile2(
+ join(projectFolderPath, 'lib', 'a.dart'),
+ [
+ 'class A {',
+ for (var i = 1; i <= 500; i++) 'String get aaa$i => "";',
+ '}',
+ ].join('\n'),
+ );
+
+ final initialAnalysis = waitForAnalysisComplete();
+ await initialize(
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
+ await openFile(mainFileUri, withoutMarkers(content));
+ await initialAnalysis;
+ final res =
+ await getCompletionList(mainFileUri, positionFromMarker(content));
+
+ // Expect everything (hashCode etc. will take it over 500).
+ expect(res.items, hasLength(greaterThanOrEqualTo(500)));
+ expect(res.isIncomplete, isFalse);
+ }
+
+ Future<void> test_isIncomplete_trueIfNotAllIncluded() async {
+ final content = '''
+import 'a.dart';
+void f() {
+ A a = A();
+ a.^
+}
+ ''';
+
+ // Create a class with fields aaa1 to aaa500 in the other file.
+ newFile2(
+ join(projectFolderPath, 'lib', 'a.dart'),
+ [
+ 'class A {',
+ for (var i = 1; i <= 500; i++) ' String get aaa$i => "";',
+ ' String get aaa => "";',
+ '}',
+ ].join('\n'),
+ );
+
+ final initialAnalysis = waitForAnalysisComplete();
+ await provideConfig(
+ () => initialize(
+ workspaceCapabilities: withApplyEditSupport(
+ withConfigurationSupport(emptyWorkspaceClientCapabilities))),
+ {'maxCompletionItems': 200},
+ );
+ await openFile(mainFileUri, withoutMarkers(content));
+ await initialAnalysis;
+ final res =
+ await getCompletionList(mainFileUri, positionFromMarker(content));
+
+ // Should be capped at 200 and marked as incomplete.
+ expect(res.items, hasLength(200));
+ expect(res.isIncomplete, isTrue);
+
+ // Also ensure 'aaa' is included, since relevance sorting should have
+ // put it at the top.
+ expect(res.items.map((item) => item.label).contains('aaa'), isTrue);
+ }
+
Future<void> test_namedArg_insertReplaceRanges() async {
/// Helper to check multiple completions in the same template file.
Future<void> check(
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index b843ceb..e2f886f 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -227,33 +227,37 @@
if (buffer.isNotEmpty) {
errors.sort((first, second) => first.offset.compareTo(second.offset));
buffer.writeln();
- buffer.writeln('To accept the current state, expect:');
- for (AnalysisError actual in errors) {
- List<DiagnosticMessage> contextMessages = actual.contextMessages;
- buffer.write(' error(');
- buffer.write(actual.errorCode);
- buffer.write(', ');
- buffer.write(actual.offset);
- buffer.write(', ');
- buffer.write(actual.length);
- if (contextMessages.isNotEmpty) {
- buffer.write(', contextMessages: [');
- for (int i = 0; i < contextMessages.length; i++) {
- DiagnosticMessage message = contextMessages[i];
- if (i > 0) {
+ if (errors.isEmpty) {
+ buffer.writeln('To accept the current state, expect no errors.');
+ } else {
+ buffer.writeln('To accept the current state, expect:');
+ for (AnalysisError actual in errors) {
+ List<DiagnosticMessage> contextMessages = actual.contextMessages;
+ buffer.write(' error(');
+ buffer.write(actual.errorCode);
+ buffer.write(', ');
+ buffer.write(actual.offset);
+ buffer.write(', ');
+ buffer.write(actual.length);
+ if (contextMessages.isNotEmpty) {
+ buffer.write(', contextMessages: [');
+ for (int i = 0; i < contextMessages.length; i++) {
+ DiagnosticMessage message = contextMessages[i];
+ if (i > 0) {
+ buffer.write(', ');
+ }
+ buffer.write('message(\'');
+ buffer.write(message.filePath);
+ buffer.write('\', ');
+ buffer.write(message.offset);
buffer.write(', ');
+ buffer.write(message.length);
+ buffer.write(')');
}
- buffer.write('message(\'');
- buffer.write(message.filePath);
- buffer.write('\', ');
- buffer.write(message.offset);
- buffer.write(', ');
- buffer.write(message.length);
- buffer.write(')');
+ buffer.write(']');
}
- buffer.write(']');
+ buffer.writeln('),');
}
- buffer.writeln('),');
}
fail(buffer.toString());
}
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index f323ee3..3c936c66 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -171,14 +171,15 @@
void setOutput(Iterator<String> arguments) {
outputSpecified = true;
+ String option = arguments.current;
String path;
- if (arguments.current == '-o') {
+ if (option == '-o' || option == '--out' || option == '--output') {
if (!arguments.moveNext()) {
- helpAndFail('Error: Missing file after -o option.');
+ helpAndFail("Missing file after '$option' option.");
}
path = arguments.current;
} else {
- path = extractParameter(arguments.current);
+ path = extractParameter(option);
}
out = Uri.base.resolve(fe.nativeToUriPath(path));
}
@@ -186,7 +187,7 @@
void setOptimizationLevel(String argument) {
int value = int.tryParse(extractParameter(argument));
if (value == null || value < 0 || value > 4) {
- helpAndFail("Error: Unsupported optimization level '$argument', "
+ helpAndFail("Unsupported optimization level '$argument', "
"supported levels are: 0, 1, 2, 3, 4");
return;
}
@@ -474,14 +475,14 @@
passThrough(argument);
return;
}
- helpAndFail("Error: Unsupported dump-info format '$argument', "
+ helpAndFail("Unsupported dump-info format '$argument', "
"supported formats are: json or binary");
}
String nullSafetyMode = null;
void setNullSafetyMode(String argument) {
if (nullSafetyMode != null && nullSafetyMode != argument) {
- helpAndFail("Error: cannot specify both $nullSafetyMode and $argument.");
+ helpAndFail("Cannot specify both $nullSafetyMode and $argument.");
}
nullSafetyMode = argument;
passThrough(argument);
@@ -573,7 +574,8 @@
OptionHandler('${Flags.codegenShards}=.+', setCodegenShards),
OptionHandler(Flags.cfeOnly, setCfeOnly),
OptionHandler(Flags.debugGlobalInference, passThrough),
- OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
+ OptionHandler('--output(?:=.+)?|--out(?:=.+)?|-o.*', setOutput,
+ multipleArguments: true),
OptionHandler('-O.*', setOptimizationLevel),
OptionHandler(Flags.allowMockCompilation, ignoreOption),
OptionHandler(Flags.fastStartup, ignoreOption),
@@ -1171,7 +1173,7 @@
-h, /h, /?, --help
Print this usage information (add -v for information about all options).
- -o <file name>, --out=<file name>
+ -o <file name>, --output=<file name>
Write the output to <file name>.
-m, --minify
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index a35a348..8358202 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
// TODO(sigmund): rename universe => world
/// Describes individual features that may be seen in a program. Most features
/// can be described only by name using the [Feature] enum, some features are
diff --git a/pkg/compiler/lib/src/util/sink_adapter.dart b/pkg/compiler/lib/src/util/sink_adapter.dart
index bcb9b33..1b093a4 100644
--- a/pkg/compiler/lib/src/util/sink_adapter.dart
+++ b/pkg/compiler/lib/src/util/sink_adapter.dart
@@ -1,3 +1,7 @@
+// 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 '../../compiler.dart' as api;
class BinaryOutputSinkAdapter implements Sink<List<int>> {
diff --git a/pkg/compiler/test/end_to_end/data/exit_code_helper.dart b/pkg/compiler/test/end_to_end/data/exit_code_helper.dart
index ab73b3a..4ce6da8 100644
--- a/pkg/compiler/test/end_to_end/data/exit_code_helper.dart
+++ b/pkg/compiler/test/end_to_end/data/exit_code_helper.dart
@@ -1 +1,5 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
void main() {}
diff --git a/pkg/compiler/test/sourcemaps/stacktrace/extension_method.dart b/pkg/compiler/test/sourcemaps/stacktrace/extension_method.dart
index 5c8302a..9a5ddf5 100644
--- a/pkg/compiler/test/sourcemaps/stacktrace/extension_method.dart
+++ b/pkg/compiler/test/sourcemaps/stacktrace/extension_method.dart
@@ -1,3 +1,7 @@
+// 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.
+
// @dart = 2.7
class MyClass {
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 71c417b..450b24b 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -22,16 +22,13 @@
import 'experimental_flags.dart'
show
AllowedExperimentalFlags,
- defaultExperimentalFlags,
ExperimentalFlag,
- expiredExperimentalFlags,
+ GlobalFeatures,
parseExperimentalFlag;
import 'experimental_flags.dart' as flags
show
getExperimentEnabledVersionInLibrary,
- isExperimentEnabled,
- isExperimentEnabledInLibrary,
isExperimentEnabledInLibraryByVersion;
import 'file_system.dart' show FileSystem;
@@ -275,29 +272,14 @@
/// Verbosity level used for filtering emitted messages.
Verbosity verbosity = Verbosity.all;
- /// Returns `true` if the experiment with the given [flag] is enabled, either
- /// explicitly or implicitly.
- ///
- /// Note that libraries can still opt out of the experiment by having a lower
- /// language version than required for the experiment.
- bool isExperimentEnabled(ExperimentalFlag flag) {
- return flags.isExperimentEnabled(flag,
- explicitExperimentalFlags: explicitExperimentalFlags,
- defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting);
- }
+ GlobalFeatures? _globalFeatures;
- /// Returns `true` if the experiment with the given [flag] is enabled either
- /// explicitly or implicitly for the library with the given [importUri].
- ///
- /// Note that the library can still opt out of the experiment by having a
- /// lower language version than required for the experiment. See
- /// [getExperimentEnabledVersionInLibrary].
- bool isExperimentEnabledInLibrary(ExperimentalFlag flag, Uri importUri) {
- return flags.isExperimentEnabledInLibrary(flag, importUri,
- defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
- explicitExperimentalFlags: explicitExperimentalFlags,
- allowedExperimentalFlags: allowedExperimentalFlagsForTesting);
- }
+ GlobalFeatures get globalFeatures => _globalFeatures ??= new GlobalFeatures(
+ explicitExperimentalFlags,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ experimentEnabledVersionForTesting: experimentEnabledVersionForTesting,
+ experimentReleasedVersionForTesting: experimentReleasedVersionForTesting,
+ allowedExperimentalFlags: allowedExperimentalFlagsForTesting);
/// Returns the minimum language version needed for a library with the given
/// [importUri] to opt in to the experiment with the given [flag].
@@ -443,8 +425,8 @@
"Experiment specified with conflicting values: " + experiment);
}
} else {
- if (expiredExperimentalFlags[flag]!) {
- if (value != defaultExperimentalFlags[flag]) {
+ if (flag.isExpired) {
+ if (value != flag.isEnabledByDefault) {
/// Produce an error when the value is not the default value.
if (value) {
onError("Enabling experiment " +
@@ -455,7 +437,7 @@
experiment +
" is no longer supported.");
}
- value = defaultExperimentalFlags[flag]!;
+ value = flag.isEnabledByDefault;
} else if (onWarning != null) {
/// Produce a warning when the value is the default value.
if (value) {
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index aa49e7b..340761c 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -4,6 +4,8 @@
import 'package:kernel/kernel.dart' show Version;
+import '../fasta/fasta_codes.dart';
+
part 'experimental_flags_generated.dart';
/// The set of experiments enabled for SDK and packages.
@@ -50,8 +52,6 @@
bool isExperimentEnabled(ExperimentalFlag flag,
{Map<ExperimentalFlag, bool>? explicitExperimentalFlags,
Map<ExperimentalFlag, bool>? defaultExperimentFlagsForTesting}) {
- assert(defaultExperimentalFlags.containsKey(flag),
- "No default value for $flag.");
bool? enabled;
if (explicitExperimentalFlags != null) {
enabled = explicitExperimentalFlags[flag];
@@ -59,8 +59,8 @@
if (defaultExperimentFlagsForTesting != null) {
enabled ??= defaultExperimentFlagsForTesting[flag];
}
- enabled ??= defaultExperimentalFlags[flag];
- return enabled!;
+ enabled ??= flag.isEnabledByDefault;
+ return enabled;
}
/// Returns `true` if [flag] is enabled in the library with the [canonicalUri]
@@ -80,8 +80,6 @@
{Map<ExperimentalFlag, bool>? defaultExperimentFlagsForTesting,
Map<ExperimentalFlag, bool>? explicitExperimentalFlags,
AllowedExperimentalFlags? allowedExperimentalFlags}) {
- assert(defaultExperimentalFlags.containsKey(flag),
- "No default value for $flag.");
bool? enabled;
if (explicitExperimentalFlags != null) {
enabled = explicitExperimentalFlags[flag];
@@ -89,8 +87,8 @@
if (defaultExperimentFlagsForTesting != null) {
enabled ??= defaultExperimentFlagsForTesting[flag];
}
- enabled ??= defaultExperimentalFlags[flag];
- if (!enabled!) {
+ enabled ??= flag.isEnabledByDefault;
+ if (!enabled) {
allowedExperimentalFlags ??= defaultAllowedExperimentalFlags;
Set<ExperimentalFlag>? allowedFlags;
if (canonicalUri.isScheme('dart')) {
@@ -140,11 +138,11 @@
if (defaultExperimentFlagsForTesting != null) {
enabledByDefault = defaultExperimentFlagsForTesting[flag];
}
- enabledByDefault ??= defaultExperimentalFlags[flag];
+ enabledByDefault ??= flag.isEnabledByDefault;
bool enabledExplicitly = explicitExperimentalFlags[flag] ?? false;
- if (!enabledByDefault! ||
+ if (!enabledByDefault ||
enabledExplicitly ||
(allowedFlags != null && allowedFlags.contains(flag))) {
// If the feature is not enabled by default or is enabled by the allowed
@@ -152,17 +150,18 @@
if (experimentReleasedVersionForTesting != null) {
version = experimentReleasedVersionForTesting[flag];
}
- version ??= experimentReleasedVersion[flag];
+ version ??= flag.experimentReleasedVersion;
} else {
// If the feature is enabled by default and is not enabled by the allowed
// list use the enabled version.
if (experimentEnabledVersionForTesting != null) {
version = experimentEnabledVersionForTesting[flag];
}
- version ??= experimentEnabledVersion[flag];
+ version ??= flag.experimentEnabledVersion;
}
+ // ignore: unnecessary_null_comparison
assert(version != null, "No version for enabling $flag in $canonicalUri.");
- return version!;
+ return version;
}
bool isExperimentEnabledInLibraryByVersion(
@@ -172,14 +171,11 @@
AllowedExperimentalFlags? allowedExperimentalFlags,
Map<ExperimentalFlag, Version>? experimentEnabledVersionForTesting,
Map<ExperimentalFlag, Version>? experimentReleasedVersionForTesting}) {
- assert(defaultExperimentalFlags.containsKey(flag),
- "No default value for $flag.");
-
bool? enabledByDefault;
if (defaultExperimentFlagsForTesting != null) {
enabledByDefault = defaultExperimentFlagsForTesting[flag];
}
- enabledByDefault ??= defaultExperimentalFlags[flag];
+ enabledByDefault ??= flag.isEnabledByDefault;
bool enabledExplicitly = explicitExperimentalFlags[flag] ?? false;
@@ -203,7 +199,7 @@
enabledByAllowed = allowedFlags.contains(flag);
}
- if (enabledByDefault! || enabledExplicitly || enabledByAllowed) {
+ if (enabledByDefault || enabledExplicitly || enabledByAllowed) {
// The feature is enabled depending on the library language version.
Version? enabledVersion;
if (!enabledByDefault || enabledExplicitly || enabledByAllowed) {
@@ -212,18 +208,65 @@
if (experimentReleasedVersionForTesting != null) {
enabledVersion = experimentReleasedVersionForTesting[flag]!;
}
- enabledVersion ??= experimentReleasedVersion[flag];
+ enabledVersion ??= flag.experimentReleasedVersion;
} else {
// If the feature is enabled by default and is not enabled by the allowed
// list use the enabled version.
if (experimentEnabledVersionForTesting != null) {
enabledVersion = experimentEnabledVersionForTesting[flag];
}
- enabledVersion ??= experimentEnabledVersion[flag];
+ enabledVersion ??= flag.experimentEnabledVersion;
}
- return version >= enabledVersion!;
+ return version >= enabledVersion;
} else {
// The feature is not enabled, regardless of library language version.
return false;
}
}
+
+/// Common interface for the state of an experimental feature.
+abstract class ExperimentalFeature {
+ /// The flag for the experimental feature.
+ final ExperimentalFlag flag;
+
+ ExperimentalFeature(this.flag);
+
+ /// `true` if this feature is enabled.
+ bool get isEnabled;
+}
+
+/// The global state of an experimental feature.
+class GlobalFeature extends ExperimentalFeature {
+ @override
+ final bool isEnabled;
+
+ GlobalFeature(ExperimentalFlag flag, this.isEnabled) : super(flag);
+}
+
+/// The state of an experimental feature within a specific library.
+class LibraryFeature extends ExperimentalFeature {
+ /// `true` if this feature is supported in the library as defined by the
+ /// default language version for its containing package/sdk.
+ ///
+ /// The feature might still not be enabled if the language version of the
+ /// library itself is below the [enabledVersion] for the feature in the
+ /// containing package/sdk.
+ final bool isSupported;
+
+ @override
+ final bool isEnabled;
+
+ /// The minimum language version for enabling this feature in this library.
+ final Version enabledVersion;
+
+ LibraryFeature(ExperimentalFlag flag, this.isSupported, this.enabledVersion,
+ this.isEnabled)
+ : super(flag);
+
+ // TODO(johnniwinther): We should emit a different message when the
+ // experiment is not released yet. The current message indicates that
+ // changing the sdk version can solve the problem.
+ /// Returns a [Message] for reporting that this feature is not enabled.
+ Message get notEnabledMessage => templateExperimentNotEnabled.withArguments(
+ flag.name, enabledVersion.toText());
+}
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 e6a113c..4d56950 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
@@ -9,52 +9,471 @@
part of 'experimental_flags.dart';
-enum ExperimentalFlag {
- alternativeInvalidationStrategy,
- constFunctions,
- constantUpdate2018,
- constructorTearoffs,
- controlFlowCollections,
- enhancedEnums,
- extensionMethods,
- extensionTypes,
- genericMetadata,
- inferenceUpdate1,
- macros,
- namedArgumentsAnywhere,
- nonNullable,
- nonfunctionTypeAliases,
- setLiterals,
- spreadCollections,
- superParameters,
- testExperiment,
- tripleShift,
- valueClass,
- variance,
+/// An experiment flag including its fixed properties.
+class ExperimentalFlag {
+ /// The name of this flag as used in the --enable-experiment option.
+ final String name;
+
+ /// `true` if this experimental feature is enabled by default.
+ ///
+ /// When `true`, the feature can still be disabled in individual libraries
+ /// with a language version below the [experimentEnabledVersion], and if not
+ /// [isExpired], the feature can also be disabled by using a 'no-' prefix
+ /// in the --enable-experiment option.
+ final bool isEnabledByDefault;
+
+ /// `true` if this feature can no longer be changed using the
+ /// --enable-experiment option.
+ ///
+ /// Libraries can still opt out of the feature by using a language version
+ /// below the [experimentEnabledVersion].
+ final bool isExpired;
+ final Version enabledVersion;
+
+ /// The minimum version that supports this feature.
+ ///
+ /// If the feature is not enabled by default, this is the current language
+ /// version.
+ final Version experimentEnabledVersion;
+
+ /// The minimum version that supports this feature in allowed libraries.
+ ///
+ /// Allowed libraries are specified in
+ ///
+ /// sdk/lib/_internal/allowed_experiments.json
+ final Version experimentReleasedVersion;
+
+ const ExperimentalFlag(
+ {required this.name,
+ required this.isEnabledByDefault,
+ required this.isExpired,
+ required this.enabledVersion,
+ required this.experimentEnabledVersion,
+ required this.experimentReleasedVersion});
+ static const ExperimentalFlag alternativeInvalidationStrategy =
+ const ExperimentalFlag(
+ name: 'alternative-invalidation-strategy',
+ isEnabledByDefault: false,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag constFunctions = const ExperimentalFlag(
+ name: 'const-functions',
+ isEnabledByDefault: false,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag constantUpdate2018 = const ExperimentalFlag(
+ name: 'constant-update-2018',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 0),
+ experimentEnabledVersion: const Version(2, 0),
+ experimentReleasedVersion: const Version(2, 0));
+
+ static const ExperimentalFlag constructorTearoffs = const ExperimentalFlag(
+ name: 'constructor-tearoffs',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 15),
+ experimentEnabledVersion: const Version(2, 15),
+ experimentReleasedVersion: const Version(2, 15));
+
+ static const ExperimentalFlag controlFlowCollections = const ExperimentalFlag(
+ name: 'control-flow-collections',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 0),
+ experimentEnabledVersion: const Version(2, 0),
+ experimentReleasedVersion: const Version(2, 0));
+
+ static const ExperimentalFlag enhancedEnums = const ExperimentalFlag(
+ name: 'enhanced-enums',
+ isEnabledByDefault: true,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag extensionMethods = const ExperimentalFlag(
+ name: 'extension-methods',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 6),
+ experimentEnabledVersion: const Version(2, 6),
+ experimentReleasedVersion: const Version(2, 6));
+
+ static const ExperimentalFlag extensionTypes = const ExperimentalFlag(
+ name: 'extension-types',
+ isEnabledByDefault: false,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag genericMetadata = const ExperimentalFlag(
+ name: 'generic-metadata',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 14),
+ experimentEnabledVersion: const Version(2, 14),
+ experimentReleasedVersion: const Version(2, 14));
+
+ static const ExperimentalFlag inferenceUpdate1 = const ExperimentalFlag(
+ name: 'inference-update-1',
+ isEnabledByDefault: false,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag macros = const ExperimentalFlag(
+ name: 'macros',
+ isEnabledByDefault: false,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag namedArgumentsAnywhere = const ExperimentalFlag(
+ name: 'named-arguments-anywhere',
+ isEnabledByDefault: true,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag nonNullable = const ExperimentalFlag(
+ name: 'non-nullable',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 12),
+ experimentEnabledVersion: const Version(2, 12),
+ experimentReleasedVersion: const Version(2, 10));
+
+ static const ExperimentalFlag nonfunctionTypeAliases = const ExperimentalFlag(
+ name: 'nonfunction-type-aliases',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 13),
+ experimentEnabledVersion: const Version(2, 13),
+ experimentReleasedVersion: const Version(2, 13));
+
+ static const ExperimentalFlag setLiterals = const ExperimentalFlag(
+ name: 'set-literals',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 0),
+ experimentEnabledVersion: const Version(2, 0),
+ experimentReleasedVersion: const Version(2, 0));
+
+ static const ExperimentalFlag spreadCollections = const ExperimentalFlag(
+ name: 'spread-collections',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 0),
+ experimentEnabledVersion: const Version(2, 0),
+ experimentReleasedVersion: const Version(2, 0));
+
+ static const ExperimentalFlag superParameters = const ExperimentalFlag(
+ name: 'super-parameters',
+ isEnabledByDefault: true,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag testExperiment = const ExperimentalFlag(
+ name: 'test-experiment',
+ isEnabledByDefault: false,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag tripleShift = const ExperimentalFlag(
+ name: 'triple-shift',
+ isEnabledByDefault: true,
+ isExpired: true,
+ enabledVersion: const Version(2, 14),
+ experimentEnabledVersion: const Version(2, 14),
+ experimentReleasedVersion: const Version(2, 14));
+
+ static const ExperimentalFlag valueClass = const ExperimentalFlag(
+ name: 'value-class',
+ isEnabledByDefault: false,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
+
+ static const ExperimentalFlag variance = const ExperimentalFlag(
+ name: 'variance',
+ isEnabledByDefault: false,
+ isExpired: false,
+ enabledVersion: const Version(2, 17),
+ experimentEnabledVersion: const Version(2, 17),
+ experimentReleasedVersion: const Version(2, 17));
}
-const Version enableAlternativeInvalidationStrategyVersion =
- const Version(2, 17);
-const Version enableConstFunctionsVersion = const Version(2, 17);
-const Version enableConstantUpdate2018Version = const Version(2, 0);
-const Version enableConstructorTearoffsVersion = const Version(2, 15);
-const Version enableControlFlowCollectionsVersion = const Version(2, 0);
-const Version enableEnhancedEnumsVersion = const Version(2, 17);
-const Version enableExtensionMethodsVersion = const Version(2, 6);
-const Version enableExtensionTypesVersion = const Version(2, 17);
-const Version enableGenericMetadataVersion = const Version(2, 14);
-const Version enableInferenceUpdate1Version = const Version(2, 17);
-const Version enableMacrosVersion = const Version(2, 17);
-const Version enableNamedArgumentsAnywhereVersion = const Version(2, 17);
-const Version enableNonNullableVersion = const Version(2, 12);
-const Version enableNonfunctionTypeAliasesVersion = const Version(2, 13);
-const Version enableSetLiteralsVersion = const Version(2, 0);
-const Version enableSpreadCollectionsVersion = const Version(2, 0);
-const Version enableSuperParametersVersion = const Version(2, 17);
-const Version enableTestExperimentVersion = const Version(2, 17);
-const Version enableTripleShiftVersion = const Version(2, 14);
-const Version enableValueClassVersion = const Version(2, 17);
-const Version enableVarianceVersion = const Version(2, 17);
+/// Interface for accessing the global state of experimental features.
+class GlobalFeatures {
+ final Map<ExperimentalFlag, bool> explicitExperimentalFlags;
+ final AllowedExperimentalFlags? allowedExperimentalFlags;
+ final Map<ExperimentalFlag, bool>? defaultExperimentFlagsForTesting;
+ final Map<ExperimentalFlag, Version>? experimentEnabledVersionForTesting;
+ final Map<ExperimentalFlag, Version>? experimentReleasedVersionForTesting;
+
+ GlobalFeatures(this.explicitExperimentalFlags,
+ {this.allowedExperimentalFlags,
+ this.defaultExperimentFlagsForTesting,
+ this.experimentEnabledVersionForTesting,
+ this.experimentReleasedVersionForTesting});
+
+ GlobalFeature _computeGlobalFeature(ExperimentalFlag flag) {
+ return new GlobalFeature(
+ flag,
+ isExperimentEnabled(flag,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ explicitExperimentalFlags: explicitExperimentalFlags));
+ }
+
+ LibraryFeature _computeLibraryFeature(
+ ExperimentalFlag flag, Uri canonicalUri, Version libraryVersion) {
+ return new LibraryFeature(
+ flag,
+ isExperimentEnabledInLibrary(flag, canonicalUri,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ explicitExperimentalFlags: explicitExperimentalFlags,
+ allowedExperimentalFlags: allowedExperimentalFlags),
+ getExperimentEnabledVersionInLibrary(
+ flag, canonicalUri, explicitExperimentalFlags,
+ allowedExperimentalFlags: allowedExperimentalFlags,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ experimentEnabledVersionForTesting:
+ experimentEnabledVersionForTesting,
+ experimentReleasedVersionForTesting:
+ experimentReleasedVersionForTesting),
+ isExperimentEnabledInLibraryByVersion(
+ flag, canonicalUri, libraryVersion,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ explicitExperimentalFlags: explicitExperimentalFlags,
+ allowedExperimentalFlags: allowedExperimentalFlags));
+ }
+
+ GlobalFeature? _alternativeInvalidationStrategy;
+ GlobalFeature get alternativeInvalidationStrategy =>
+ _alternativeInvalidationStrategy ??= _computeGlobalFeature(
+ ExperimentalFlag.alternativeInvalidationStrategy);
+
+ GlobalFeature? _constFunctions;
+ GlobalFeature get constFunctions => _constFunctions ??=
+ _computeGlobalFeature(ExperimentalFlag.constFunctions);
+
+ GlobalFeature? _constantUpdate2018;
+ GlobalFeature get constantUpdate2018 => _constantUpdate2018 ??=
+ _computeGlobalFeature(ExperimentalFlag.constantUpdate2018);
+
+ GlobalFeature? _constructorTearoffs;
+ GlobalFeature get constructorTearoffs => _constructorTearoffs ??=
+ _computeGlobalFeature(ExperimentalFlag.constructorTearoffs);
+
+ GlobalFeature? _controlFlowCollections;
+ GlobalFeature get controlFlowCollections => _controlFlowCollections ??=
+ _computeGlobalFeature(ExperimentalFlag.controlFlowCollections);
+
+ GlobalFeature? _enhancedEnums;
+ GlobalFeature get enhancedEnums =>
+ _enhancedEnums ??= _computeGlobalFeature(ExperimentalFlag.enhancedEnums);
+
+ GlobalFeature? _extensionMethods;
+ GlobalFeature get extensionMethods => _extensionMethods ??=
+ _computeGlobalFeature(ExperimentalFlag.extensionMethods);
+
+ GlobalFeature? _extensionTypes;
+ GlobalFeature get extensionTypes => _extensionTypes ??=
+ _computeGlobalFeature(ExperimentalFlag.extensionTypes);
+
+ GlobalFeature? _genericMetadata;
+ GlobalFeature get genericMetadata => _genericMetadata ??=
+ _computeGlobalFeature(ExperimentalFlag.genericMetadata);
+
+ GlobalFeature? _inferenceUpdate1;
+ GlobalFeature get inferenceUpdate1 => _inferenceUpdate1 ??=
+ _computeGlobalFeature(ExperimentalFlag.inferenceUpdate1);
+
+ GlobalFeature? _macros;
+ GlobalFeature get macros =>
+ _macros ??= _computeGlobalFeature(ExperimentalFlag.macros);
+
+ GlobalFeature? _namedArgumentsAnywhere;
+ GlobalFeature get namedArgumentsAnywhere => _namedArgumentsAnywhere ??=
+ _computeGlobalFeature(ExperimentalFlag.namedArgumentsAnywhere);
+
+ GlobalFeature? _nonNullable;
+ GlobalFeature get nonNullable =>
+ _nonNullable ??= _computeGlobalFeature(ExperimentalFlag.nonNullable);
+
+ GlobalFeature? _nonfunctionTypeAliases;
+ GlobalFeature get nonfunctionTypeAliases => _nonfunctionTypeAliases ??=
+ _computeGlobalFeature(ExperimentalFlag.nonfunctionTypeAliases);
+
+ GlobalFeature? _setLiterals;
+ GlobalFeature get setLiterals =>
+ _setLiterals ??= _computeGlobalFeature(ExperimentalFlag.setLiterals);
+
+ GlobalFeature? _spreadCollections;
+ GlobalFeature get spreadCollections => _spreadCollections ??=
+ _computeGlobalFeature(ExperimentalFlag.spreadCollections);
+
+ GlobalFeature? _superParameters;
+ GlobalFeature get superParameters => _superParameters ??=
+ _computeGlobalFeature(ExperimentalFlag.superParameters);
+
+ GlobalFeature? _testExperiment;
+ GlobalFeature get testExperiment => _testExperiment ??=
+ _computeGlobalFeature(ExperimentalFlag.testExperiment);
+
+ GlobalFeature? _tripleShift;
+ GlobalFeature get tripleShift =>
+ _tripleShift ??= _computeGlobalFeature(ExperimentalFlag.tripleShift);
+
+ GlobalFeature? _valueClass;
+ GlobalFeature get valueClass =>
+ _valueClass ??= _computeGlobalFeature(ExperimentalFlag.valueClass);
+
+ GlobalFeature? _variance;
+ GlobalFeature get variance =>
+ _variance ??= _computeGlobalFeature(ExperimentalFlag.variance);
+}
+
+/// Interface for accessing the state of experimental features within a
+/// specific library.
+class LibraryFeatures {
+ final GlobalFeatures globalFeatures;
+ final Uri canonicalUri;
+ final Version libraryVersion;
+
+ LibraryFeatures(this.globalFeatures, this.canonicalUri, this.libraryVersion);
+
+ LibraryFeature? _alternativeInvalidationStrategy;
+ LibraryFeature get alternativeInvalidationStrategy =>
+ _alternativeInvalidationStrategy ??=
+ globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.alternativeInvalidationStrategy,
+ canonicalUri,
+ libraryVersion);
+
+ LibraryFeature? _constFunctions;
+ LibraryFeature get constFunctions =>
+ _constFunctions ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.constFunctions, canonicalUri, libraryVersion);
+
+ LibraryFeature? _constantUpdate2018;
+ LibraryFeature get constantUpdate2018 =>
+ _constantUpdate2018 ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.constantUpdate2018, canonicalUri, libraryVersion);
+
+ LibraryFeature? _constructorTearoffs;
+ LibraryFeature get constructorTearoffs =>
+ _constructorTearoffs ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.constructorTearoffs, canonicalUri, libraryVersion);
+
+ LibraryFeature? _controlFlowCollections;
+ LibraryFeature get controlFlowCollections =>
+ _controlFlowCollections ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.controlFlowCollections,
+ canonicalUri,
+ libraryVersion);
+
+ LibraryFeature? _enhancedEnums;
+ LibraryFeature get enhancedEnums =>
+ _enhancedEnums ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.enhancedEnums, canonicalUri, libraryVersion);
+
+ LibraryFeature? _extensionMethods;
+ LibraryFeature get extensionMethods =>
+ _extensionMethods ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.extensionMethods, canonicalUri, libraryVersion);
+
+ LibraryFeature? _extensionTypes;
+ LibraryFeature get extensionTypes =>
+ _extensionTypes ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.extensionTypes, canonicalUri, libraryVersion);
+
+ LibraryFeature? _genericMetadata;
+ LibraryFeature get genericMetadata =>
+ _genericMetadata ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.genericMetadata, canonicalUri, libraryVersion);
+
+ LibraryFeature? _inferenceUpdate1;
+ LibraryFeature get inferenceUpdate1 =>
+ _inferenceUpdate1 ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.inferenceUpdate1, canonicalUri, libraryVersion);
+
+ LibraryFeature? _macros;
+ LibraryFeature get macros =>
+ _macros ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.macros, canonicalUri, libraryVersion);
+
+ LibraryFeature? _namedArgumentsAnywhere;
+ LibraryFeature get namedArgumentsAnywhere =>
+ _namedArgumentsAnywhere ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.namedArgumentsAnywhere,
+ canonicalUri,
+ libraryVersion);
+
+ LibraryFeature? _nonNullable;
+ LibraryFeature get nonNullable =>
+ _nonNullable ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.nonNullable, canonicalUri, libraryVersion);
+
+ LibraryFeature? _nonfunctionTypeAliases;
+ LibraryFeature get nonfunctionTypeAliases =>
+ _nonfunctionTypeAliases ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.nonfunctionTypeAliases,
+ canonicalUri,
+ libraryVersion);
+
+ LibraryFeature? _setLiterals;
+ LibraryFeature get setLiterals =>
+ _setLiterals ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.setLiterals, canonicalUri, libraryVersion);
+
+ LibraryFeature? _spreadCollections;
+ LibraryFeature get spreadCollections =>
+ _spreadCollections ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.spreadCollections, canonicalUri, libraryVersion);
+
+ LibraryFeature? _superParameters;
+ LibraryFeature get superParameters =>
+ _superParameters ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.superParameters, canonicalUri, libraryVersion);
+
+ LibraryFeature? _testExperiment;
+ LibraryFeature get testExperiment =>
+ _testExperiment ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.testExperiment, canonicalUri, libraryVersion);
+
+ LibraryFeature? _tripleShift;
+ LibraryFeature get tripleShift =>
+ _tripleShift ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.tripleShift, canonicalUri, libraryVersion);
+
+ LibraryFeature? _valueClass;
+ LibraryFeature get valueClass =>
+ _valueClass ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.valueClass, canonicalUri, libraryVersion);
+
+ LibraryFeature? _variance;
+ LibraryFeature get variance =>
+ _variance ??= globalFeatures._computeLibraryFeature(
+ ExperimentalFlag.variance, canonicalUri, libraryVersion);
+}
ExperimentalFlag? parseExperimentalFlag(String flag) {
switch (flag) {
@@ -104,102 +523,44 @@
return null;
}
-const Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
- ExperimentalFlag.alternativeInvalidationStrategy: false,
- ExperimentalFlag.constFunctions: false,
- ExperimentalFlag.constantUpdate2018: true,
- ExperimentalFlag.constructorTearoffs: true,
- ExperimentalFlag.controlFlowCollections: true,
- ExperimentalFlag.enhancedEnums: true,
- ExperimentalFlag.extensionMethods: true,
- ExperimentalFlag.extensionTypes: false,
- ExperimentalFlag.genericMetadata: true,
- ExperimentalFlag.inferenceUpdate1: false,
- ExperimentalFlag.macros: false,
- ExperimentalFlag.namedArgumentsAnywhere: true,
- ExperimentalFlag.nonNullable: true,
- ExperimentalFlag.nonfunctionTypeAliases: true,
- ExperimentalFlag.setLiterals: true,
- ExperimentalFlag.spreadCollections: true,
- ExperimentalFlag.superParameters: true,
- ExperimentalFlag.testExperiment: false,
- ExperimentalFlag.tripleShift: true,
- ExperimentalFlag.valueClass: false,
- ExperimentalFlag.variance: false,
+final Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
+ ExperimentalFlag.alternativeInvalidationStrategy:
+ ExperimentalFlag.alternativeInvalidationStrategy.isEnabledByDefault,
+ ExperimentalFlag.constFunctions:
+ ExperimentalFlag.constFunctions.isEnabledByDefault,
+ ExperimentalFlag.constantUpdate2018:
+ ExperimentalFlag.constantUpdate2018.isEnabledByDefault,
+ ExperimentalFlag.constructorTearoffs:
+ ExperimentalFlag.constructorTearoffs.isEnabledByDefault,
+ ExperimentalFlag.controlFlowCollections:
+ ExperimentalFlag.controlFlowCollections.isEnabledByDefault,
+ ExperimentalFlag.enhancedEnums:
+ ExperimentalFlag.enhancedEnums.isEnabledByDefault,
+ ExperimentalFlag.extensionMethods:
+ ExperimentalFlag.extensionMethods.isEnabledByDefault,
+ ExperimentalFlag.extensionTypes:
+ ExperimentalFlag.extensionTypes.isEnabledByDefault,
+ ExperimentalFlag.genericMetadata:
+ ExperimentalFlag.genericMetadata.isEnabledByDefault,
+ ExperimentalFlag.inferenceUpdate1:
+ ExperimentalFlag.inferenceUpdate1.isEnabledByDefault,
+ ExperimentalFlag.macros: ExperimentalFlag.macros.isEnabledByDefault,
+ ExperimentalFlag.namedArgumentsAnywhere:
+ ExperimentalFlag.namedArgumentsAnywhere.isEnabledByDefault,
+ ExperimentalFlag.nonNullable: ExperimentalFlag.nonNullable.isEnabledByDefault,
+ ExperimentalFlag.nonfunctionTypeAliases:
+ ExperimentalFlag.nonfunctionTypeAliases.isEnabledByDefault,
+ ExperimentalFlag.setLiterals: ExperimentalFlag.setLiterals.isEnabledByDefault,
+ ExperimentalFlag.spreadCollections:
+ ExperimentalFlag.spreadCollections.isEnabledByDefault,
+ ExperimentalFlag.superParameters:
+ ExperimentalFlag.superParameters.isEnabledByDefault,
+ ExperimentalFlag.testExperiment:
+ ExperimentalFlag.testExperiment.isEnabledByDefault,
+ ExperimentalFlag.tripleShift: ExperimentalFlag.tripleShift.isEnabledByDefault,
+ ExperimentalFlag.valueClass: ExperimentalFlag.valueClass.isEnabledByDefault,
+ ExperimentalFlag.variance: ExperimentalFlag.variance.isEnabledByDefault,
};
-
-const Map<ExperimentalFlag, bool> expiredExperimentalFlags = {
- ExperimentalFlag.alternativeInvalidationStrategy: false,
- ExperimentalFlag.constFunctions: false,
- ExperimentalFlag.constantUpdate2018: true,
- ExperimentalFlag.constructorTearoffs: true,
- ExperimentalFlag.controlFlowCollections: true,
- ExperimentalFlag.enhancedEnums: false,
- ExperimentalFlag.extensionMethods: true,
- ExperimentalFlag.extensionTypes: false,
- ExperimentalFlag.genericMetadata: true,
- ExperimentalFlag.inferenceUpdate1: false,
- ExperimentalFlag.macros: false,
- ExperimentalFlag.namedArgumentsAnywhere: false,
- ExperimentalFlag.nonNullable: true,
- ExperimentalFlag.nonfunctionTypeAliases: true,
- ExperimentalFlag.setLiterals: true,
- ExperimentalFlag.spreadCollections: true,
- ExperimentalFlag.superParameters: false,
- ExperimentalFlag.testExperiment: false,
- ExperimentalFlag.tripleShift: true,
- ExperimentalFlag.valueClass: false,
- ExperimentalFlag.variance: false,
-};
-
-const Map<ExperimentalFlag, Version> experimentEnabledVersion = {
- ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 17),
- ExperimentalFlag.constFunctions: const Version(2, 17),
- ExperimentalFlag.constantUpdate2018: const Version(2, 0),
- ExperimentalFlag.constructorTearoffs: const Version(2, 15),
- ExperimentalFlag.controlFlowCollections: const Version(2, 0),
- ExperimentalFlag.enhancedEnums: const Version(2, 17),
- ExperimentalFlag.extensionMethods: const Version(2, 6),
- ExperimentalFlag.extensionTypes: const Version(2, 17),
- ExperimentalFlag.genericMetadata: const Version(2, 14),
- ExperimentalFlag.inferenceUpdate1: const Version(2, 17),
- ExperimentalFlag.macros: const Version(2, 17),
- ExperimentalFlag.namedArgumentsAnywhere: const Version(2, 17),
- ExperimentalFlag.nonNullable: const Version(2, 12),
- ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 13),
- ExperimentalFlag.setLiterals: const Version(2, 0),
- ExperimentalFlag.spreadCollections: const Version(2, 0),
- ExperimentalFlag.superParameters: const Version(2, 17),
- ExperimentalFlag.testExperiment: const Version(2, 17),
- ExperimentalFlag.tripleShift: const Version(2, 14),
- ExperimentalFlag.valueClass: const Version(2, 17),
- ExperimentalFlag.variance: const Version(2, 17),
-};
-
-const Map<ExperimentalFlag, Version> experimentReleasedVersion = {
- ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 17),
- ExperimentalFlag.constFunctions: const Version(2, 17),
- ExperimentalFlag.constantUpdate2018: const Version(2, 0),
- ExperimentalFlag.constructorTearoffs: const Version(2, 15),
- ExperimentalFlag.controlFlowCollections: const Version(2, 0),
- ExperimentalFlag.enhancedEnums: const Version(2, 17),
- ExperimentalFlag.extensionMethods: const Version(2, 6),
- ExperimentalFlag.extensionTypes: const Version(2, 17),
- ExperimentalFlag.genericMetadata: const Version(2, 14),
- ExperimentalFlag.inferenceUpdate1: const Version(2, 17),
- ExperimentalFlag.macros: const Version(2, 17),
- ExperimentalFlag.namedArgumentsAnywhere: const Version(2, 17),
- ExperimentalFlag.nonNullable: const Version(2, 10),
- ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 13),
- ExperimentalFlag.setLiterals: const Version(2, 0),
- ExperimentalFlag.spreadCollections: const Version(2, 0),
- ExperimentalFlag.superParameters: const Version(2, 17),
- ExperimentalFlag.testExperiment: const Version(2, 17),
- ExperimentalFlag.tripleShift: const Version(2, 14),
- ExperimentalFlag.valueClass: const Version(2, 17),
- ExperimentalFlag.variance: const Version(2, 17),
-};
-
const AllowedExperimentalFlags defaultAllowedExperimentalFlags =
const AllowedExperimentalFlags(
sdkDefaultExperiments: {},
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index d129e23..959eb38 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -364,35 +364,8 @@
Target get target =>
_target ??= _raw.target ?? new NoneTarget(new TargetFlags());
- /// Returns `true` if the [flag] is enabled globally by default.
- bool isExperimentEnabledByDefault(flags.ExperimentalFlag flag) {
- return flags.isExperimentEnabled(flag,
- defaultExperimentFlagsForTesting:
- _raw.defaultExperimentFlagsForTesting);
- }
-
- /// Returns `true` if the [flag] is enabled globally.
- ///
- /// This is `true` either if the [flag] is passed through an explicit
- /// `--enable-experiment` option or if the [flag] is expired and on by
- /// default.
- bool isExperimentEnabledGlobally(flags.ExperimentalFlag flag) {
- return flags.isExperimentEnabled(flag,
- explicitExperimentalFlags: _raw.explicitExperimentalFlags,
- defaultExperimentFlagsForTesting:
- _raw.defaultExperimentFlagsForTesting);
- }
-
- /// Returns `true` if the experiment with the given [flag] is enabled either
- /// explicitly or implicitly for the library with the given [importUri].
- ///
- /// Note that the library can still opt out of the experiment by having a
- /// lower language version than required for the experiment. See
- /// [getExperimentEnabledVersionInLibrary].
- bool isExperimentEnabledInLibrary(
- flags.ExperimentalFlag flag, Uri importUri) {
- return _raw.isExperimentEnabledInLibrary(flag, importUri);
- }
+ /// Returns the global state of the experimental features.
+ flags.GlobalFeatures get globalFeatures => _raw.globalFeatures;
/// Returns the minimum language version needed for a library with the given
/// [importUri] to opt in to the experiment with the given [flag].
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
index 93079f4..f0deb80 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -75,7 +75,7 @@
DartType buildType(LibraryBuilder library,
NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments) {
if (library is SourceLibraryBuilder &&
- library.enableExtensionTypesInLibrary) {
+ library.libraryFeatures.extensionTypes.isEnabled) {
return buildTypeWithBuiltArguments(
library,
nullabilityBuilder.build(library),
@@ -90,7 +90,7 @@
DartType buildTypeWithBuiltArguments(LibraryBuilder library,
Nullability nullability, List<DartType> arguments) {
if (library is SourceLibraryBuilder &&
- library.enableExtensionTypesInLibrary) {
+ library.libraryFeatures.extensionTypes.isEnabled) {
return new ExtensionType(extension, nullability, arguments);
} else {
throw new UnsupportedError(
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index d885de8..6855fda 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -16,7 +16,6 @@
messageTypeVariableInStaticContext,
messageTypedefCause,
noLength,
- templateExperimentNotEnabled,
templateExtendingRestricted,
templateNotAType,
templateSupertypeIsIllegal,
@@ -269,10 +268,9 @@
}
if (_declaration!.isExtension &&
library is SourceLibraryBuilder &&
- !library.enableExtensionTypesInLibrary) {
- Message message = templateExperimentNotEnabled.withArguments(
- 'extension-types',
- library.enableExtensionTypesVersionInLibrary.toText());
+ !library.libraryFeatures.extensionTypes.isEnabled) {
+ Message message =
+ library.libraryFeatures.extensionTypes.notEnabledMessage;
int typeNameLength = nameLength;
int typeNameOffset = nameOffset;
library.addProblem(message, typeNameOffset, typeNameLength, fileUri);
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 5dc9c13..410e9b1 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -62,8 +62,6 @@
import '../api_prototype/compiler_options.dart' show CompilerOptions;
-import '../api_prototype/experimental_flags.dart';
-
import '../api_prototype/file_system.dart' show FileSystem, FileSystemEntity;
import '../api_prototype/incremental_kernel_generator.dart'
@@ -983,7 +981,7 @@
}
// Check compilation mode up against what we've seen here and set
// `hasInvalidNnbdModeLibrary` accordingly.
- if (c.options.isExperimentEnabledGlobally(ExperimentalFlag.nonNullable)) {
+ if (c.options.globalFeatures.nonNullable.isEnabled) {
switch (c.options.nnbdMode) {
case NnbdMode.Weak:
// Don't expect strong or invalid.
@@ -1150,8 +1148,10 @@
Set<LibraryBuilder> originalNotReusedLibraries;
Set<Uri>? missingSources;
- if (!context.options.isExperimentEnabledGlobally(
- ExperimentalFlag.alternativeInvalidationStrategy)) return null;
+ if (!context
+ .options.globalFeatures.alternativeInvalidationStrategy.isEnabled) {
+ return null;
+ }
if (_modulesToLoad != null) return null;
if (reusedResult.directlyInvalidated.isEmpty) return null;
if (reusedResult.invalidatedBecauseOfPackageUpdate) return null;
@@ -1199,8 +1199,7 @@
enableTripleShift:
/* should this be on the library? */
/* this is effectively what the constant evaluator does */
- context.options
- .isExperimentEnabledGlobally(ExperimentalFlag.tripleShift));
+ context.options.globalFeatures.tripleShift.isEnabled);
String? before = textualOutline(previousSource, scannerConfiguration,
performModelling: true);
if (before == null) {
@@ -2603,8 +2602,7 @@
// Compute "output nnbd mode".
NonNullableByDefaultCompiledMode compiledMode;
- if (context.options
- .isExperimentEnabledGlobally(ExperimentalFlag.nonNullable)) {
+ if (context.options.globalFeatures.nonNullable.isEnabled) {
switch (context.options.nnbdMode) {
case NnbdMode.Weak:
compiledMode = NonNullableByDefaultCompiledMode.Weak;
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index e4866f3..b9b2813 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -33,6 +33,7 @@
import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart'
show isBinaryOperator, isMinusOperator, isUserDefinableOperator;
import 'package:_fe_analyzer_shared/src/util/link.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/fasta/kernel/benchmarker.dart' show Benchmarker;
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
@@ -67,13 +68,7 @@
import '../constant_context.dart' show ConstantContext;
import '../dill/dill_library_builder.dart' show DillLibraryBuilder;
import '../fasta_codes.dart' as fasta;
-import '../fasta_codes.dart'
- show
- LocatedMessage,
- Message,
- Template,
- noLength,
- templateExperimentNotEnabled;
+import '../fasta_codes.dart' show LocatedMessage, Message, Template, noLength;
import '../identifiers.dart'
show Identifier, InitializedIdentifier, QualifiedName, flattenName;
import '../messages.dart' as messages show getLocationFromUri;
@@ -601,24 +596,7 @@
DartType get implicitTypeArgument => const ImplicitTypeArgument();
@override
- bool get enableExtensionTypesInLibrary {
- return libraryBuilder.enableExtensionTypesInLibrary;
- }
-
- @override
- bool get enableConstFunctionsInLibrary {
- return libraryBuilder.enableConstFunctionsInLibrary;
- }
-
- @override
- bool get enableConstructorTearOffsInLibrary {
- return libraryBuilder.enableConstructorTearOffsInLibrary;
- }
-
- @override
- bool get enableNamedArgumentsAnywhereInLibrary {
- return libraryBuilder.enableNamedArgumentsAnywhereInLibrary;
- }
+ LibraryFeatures get libraryFeatures => libraryBuilder.libraryFeatures;
void _enterLocalState({bool inLateLocalInitializer: false}) {
_localInitializerState =
@@ -1893,7 +1871,7 @@
buildProblem(fasta.messageEnumConstructorSuperInitializer,
superInitializer.fileOffset, noLength))
..parent = constructor;
- } else if (libraryBuilder.enableSuperParametersInLibrary) {
+ } else if (libraryFeatures.superParameters.isEnabled) {
ArgumentsImpl arguments = superInitializer.arguments as ArgumentsImpl;
if (positionalSuperParametersAsArguments != null) {
@@ -1926,7 +1904,7 @@
RedirectingInitializer redirectingInitializer =
initializers.last as RedirectingInitializer;
if (sourceClassBuilder is SourceEnumBuilder &&
- libraryBuilder.enableEnhancedEnumsInLibrary) {
+ libraryFeatures.enhancedEnums.isEnabled) {
ArgumentsImpl arguments =
redirectingInitializer.arguments as ArgumentsImpl;
List<Expression> enumSyntheticArguments = [
@@ -1971,7 +1949,7 @@
ArgumentsImpl arguments;
List<Expression>? positionalArguments;
List<NamedExpression>? namedArguments;
- if (libraryBuilder.enableSuperParametersInLibrary) {
+ if (libraryFeatures.superParameters.isEnabled) {
positionalArguments = positionalSuperParametersAsArguments;
namedArguments = namedSuperParametersAsArguments;
}
@@ -2020,7 +1998,7 @@
initializer = buildSuperInitializer(
true, superTarget, arguments, builder.charOffset);
}
- if (libraryBuilder.enableSuperParametersInLibrary) {
+ if (libraryFeatures.superParameters.isEnabled) {
InitializerInferenceResult inferenceResult =
typeInferrer.inferInitializer(this, initializer);
builder.addInitializer(initializer, this,
@@ -2066,7 +2044,7 @@
return;
}
List<Object?>? argumentsOriginalOrder;
- if (libraryBuilder.enableNamedArgumentsAnywhereInLibrary) {
+ if (libraryFeatures.namedArgumentsAnywhere.isEnabled) {
argumentsOriginalOrder = new List<Object?>.of(arguments);
}
int firstNamedArgumentIndex = arguments.length;
@@ -2084,7 +2062,7 @@
argumentsOriginalOrder?[i] = argument;
if (i > firstNamedArgumentIndex) {
hasNamedBeforePositional = true;
- if (!libraryBuilder.enableNamedArgumentsAnywhereInLibrary) {
+ if (!libraryFeatures.namedArgumentsAnywhere.isEnabled) {
arguments[i] = new NamedExpression(
"#$i",
buildProblem(fasta.messageExpectedNamedArgument,
@@ -2100,7 +2078,7 @@
if (firstNamedArgumentIndex < arguments.length) {
List<Expression> positional;
List<NamedExpression> named;
- if (libraryBuilder.enableNamedArgumentsAnywhereInLibrary) {
+ if (libraryFeatures.namedArgumentsAnywhere.isEnabled) {
positional = new List<Expression>.filled(
positionalCount, dummyExpression,
growable: true);
@@ -2905,7 +2883,7 @@
if (constantContext != ConstantContext.none &&
!variableBuilder.isConst &&
!member.isConstructor &&
- !enableConstFunctionsInLibrary) {
+ !libraryFeatures.constFunctions.isEnabled) {
return new IncompleteErrorGenerator(
this, token, fasta.messageNotAConstantExpression);
}
@@ -4120,7 +4098,7 @@
if (name is Generator) {
bool allowPotentiallyConstantType;
if (libraryBuilder.isNonNullableByDefault) {
- if (enableConstructorTearOffsInLibrary) {
+ if (libraryFeatures.constructorTearoffs.isEnabled) {
allowPotentiallyConstantType = true;
} else {
allowPotentiallyConstantType = inIsOrAsOperatorType;
@@ -4188,7 +4166,7 @@
if (typeVariables != null) {
for (TypeVariableBuilder builder in typeVariables) {
if (builder.parameter.annotations.isNotEmpty) {
- if (!libraryBuilder.enableGenericMetadataInLibrary) {
+ if (!libraryFeatures.genericMetadata.isEnabled) {
addProblem(fasta.messageAnnotationOnFunctionTypeTypeVariable,
builder.charOffset, builder.name.length);
}
@@ -4385,7 +4363,9 @@
buildDartType(type, allowPotentiallyConstantType: false);
}
Token? varOrFinalOrConst = pop(NullValue.Token) as Token?;
- if (superKeyword != null && varOrFinalOrConst != null) {
+ if (superKeyword != null &&
+ varOrFinalOrConst != null &&
+ optional('var', varOrFinalOrConst)) {
handleRecoverableError(
fasta.templateExtraneousModifier.withArguments(varOrFinalOrConst),
varOrFinalOrConst,
@@ -5239,7 +5219,7 @@
String name = pop() as String;
List<TypeBuilder>? typeArguments = pop() as List<TypeBuilder>?;
if (inMetadata && typeArguments != null) {
- if (!libraryBuilder.enableGenericMetadataInLibrary) {
+ if (!libraryFeatures.genericMetadata.isEnabled) {
handleRecoverableError(fasta.messageMetadataTypeArguments,
nameLastToken.next!, nameLastToken.next!);
}
@@ -5291,7 +5271,8 @@
{required int instantiationOffset,
required int invocationOffset,
required bool inImplicitCreationContext}) {
- if (enableConstructorTearOffsInLibrary && inImplicitCreationContext) {
+ if (libraryFeatures.constructorTearoffs.isEnabled &&
+ inImplicitCreationContext) {
Expression receiver = receiverFunction();
if (typeArguments != null) {
if (receiver is StaticTearOff &&
@@ -5565,7 +5546,7 @@
target = b.member;
}
if (type.isEnum &&
- !(libraryBuilder.enableEnhancedEnumsInLibrary &&
+ !(libraryFeatures.enhancedEnums.isEnabled &&
target is Procedure &&
target.kind == ProcedureKind.Factory)) {
return buildProblem(fasta.messageEnumInstantiation,
@@ -5610,7 +5591,7 @@
@override
void handleConstFactory(Token constKeyword) {
debugEvent("ConstFactory");
- if (!libraryBuilder.enableConstFunctionsInLibrary) {
+ if (!libraryFeatures.constFunctions.isEnabled) {
handleRecoverableError(
fasta.messageConstFactory, constKeyword, constKeyword);
}
@@ -6837,7 +6818,7 @@
TypeVariableBuilder variable = typeVariables[index];
variable.bound = bound;
if (variance != null) {
- if (!libraryBuilder.enableVarianceInLibrary) {
+ if (!libraryFeatures.variance.isEnabled) {
reportVarianceModifierNotEnabled(variance);
}
variable.variance = Variance.fromString(variance.lexeme);
@@ -7198,7 +7179,7 @@
]));
List<TypeBuilder>? typeArguments =
pop() as List<TypeBuilder>?; // typeArguments
- if (libraryBuilder.enableConstructorTearOffsInLibrary) {
+ if (libraryFeatures.constructorTearoffs.isEnabled) {
Object? operand = pop();
if (operand is Generator) {
push(operand.applyTypeArguments(
@@ -7217,13 +7198,8 @@
..fileOffset = openAngleBracket.charOffset);
}
} else {
- addProblem(
- templateExperimentNotEnabled.withArguments(
- 'constructor-tearoffs',
- libraryBuilder.enableConstructorTearOffsVersionInLibrary
- .toText()),
- openAngleBracket.charOffset,
- noLength);
+ addProblem(libraryFeatures.constructorTearoffs.notEnabledMessage,
+ openAngleBracket.charOffset, noLength);
}
}
@@ -7308,7 +7284,7 @@
{bool isConstantExpression: false, bool isNullAware: false}) {
if (constantContext != ConstantContext.none &&
!isConstantExpression &&
- !enableConstFunctionsInLibrary) {
+ !libraryFeatures.constFunctions.isEnabled) {
return buildProblem(
fasta.templateNotConstantExpression
.withArguments('Method invocation'),
@@ -7338,7 +7314,7 @@
bool isImplicitCall: false}) {
if (constantContext != ConstantContext.none &&
!isConstantExpression &&
- !enableConstFunctionsInLibrary) {
+ !libraryFeatures.constFunctions.isEnabled) {
return buildProblem(
fasta.templateNotConstantExpression
.withArguments('Method invocation'),
@@ -7480,15 +7456,8 @@
@override
void handleNewAsIdentifier(Token token) {
- if (!libraryBuilder.enableConstructorTearOffsInLibrary) {
- addProblem(
- templateExperimentNotEnabled.withArguments(
- 'constructor-tearoffs',
- libraryBuilder.enableConstructorTearOffsVersionInLibrary
- .toText()),
- token.charOffset,
- token.length);
- }
+ reportIfNotEnabled(
+ libraryFeatures.constructorTearoffs, token.charOffset, token.length);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 4c64564..927fca16 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -1503,7 +1503,7 @@
{bool isTypeArgumentsInForest = false}) {
if (_helper.constantContext != ConstantContext.none &&
!_helper.isIdentical(readTarget) &&
- !_helper.enableConstFunctionsInLibrary) {
+ !_helper.libraryFeatures.constFunctions.isEnabled) {
return _helper.buildProblem(
templateNotConstantExpression.withArguments('Method invocation'),
offset,
@@ -3085,7 +3085,7 @@
_helper.libraryBuilder.nonNullableBuilder, typeArguments,
allowPotentiallyConstantType: true, forTypeLiteral: true),
allowPotentiallyConstantType:
- _helper.enableConstructorTearOffsInLibrary));
+ _helper.libraryFeatures.constructorTearoffs.isEnabled));
}
}
return _expression!;
@@ -3110,7 +3110,7 @@
usedAsClassFileUri: _uri);
bool isConstructorTearOff = send is PropertySelector &&
- _helper.enableConstructorTearOffsInLibrary &&
+ _helper.libraryFeatures.constructorTearoffs.isEnabled &&
declarationBuilder is ClassBuilder;
List<TypeBuilder>? aliasedTypeArguments = typeArguments
?.map((unknownType) => _helper.validateTypeVariableUse(unknownType,
@@ -3173,7 +3173,7 @@
"Unexpected non-null typeArguments of "
"an IncompletePropertyAccessGenerator object: "
"'${send.typeArguments.runtimeType}'.");
- if (_helper.enableConstructorTearOffsInLibrary &&
+ if (_helper.libraryFeatures.constructorTearoffs.isEnabled &&
declarationBuilder is ClassBuilder) {
MemberBuilder? constructor =
declarationBuilder.findConstructorOrFactory(
@@ -4786,7 +4786,8 @@
/// Report an error if the selector name "new" when the constructor-tearoff
/// feature is enabled.
void reportNewAsSelector() {
- if (name.text == 'new' && _helper.enableConstructorTearOffsInLibrary) {
+ if (name.text == 'new' &&
+ _helper.libraryFeatures.constructorTearoffs.isEnabled) {
_helper.addProblem(messageNewAsSelector, fileOffset, name.text.length);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index a141e17..41ab864 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -9,20 +9,19 @@
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
+import '../../api_prototype/experimental_flags.dart';
import '../builder/builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/prefix_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_declaration_builder.dart';
-
import '../constant_context.dart' show ConstantContext;
import '../fasta_codes.dart' show LocatedMessage;
import '../messages.dart' show Message;
import '../scope.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
import '../type_inference/inference_helper.dart' show InferenceHelper;
-
import 'constness.dart' show Constness;
import 'forest.dart' show Forest;
import 'internal_ast.dart';
@@ -57,13 +56,7 @@
Member? lookupSuperMember(Name name, {bool isSetter});
- bool get enableExtensionTypesInLibrary;
-
- bool get enableConstFunctionsInLibrary;
-
- bool get enableConstructorTearOffsInLibrary;
-
- bool get enableNamedArgumentsAnywhereInLibrary;
+ LibraryFeatures get libraryFeatures;
Expression_Generator_Builder scopeLookup(
Scope scope, String name, Token token,
diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart
index 1657161..8672ea7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart
@@ -37,6 +37,7 @@
templateCantInferTypeDueToNoCombinedSignature,
templateDuplicatedDeclaration,
templateDuplicatedDeclarationCause,
+ templateInstanceAndSynthesizedStaticConflict,
templateMissingImplementationCause,
templateMissingImplementationNotAbstract;
import '../../names.dart' show noSuchMethodName;
@@ -531,12 +532,23 @@
staticMember = b;
instanceMember = a;
}
- classBuilder.libraryBuilder.addProblem(messageStaticAndInstanceConflict,
- staticMember.charOffset, name.length, staticMember.fileUri,
- context: <LocatedMessage>[
- messageStaticAndInstanceConflictCause.withLocation(
- instanceMember.fileUri, instanceMember.charOffset, name.length)
- ]);
+ if (!staticMember.isSynthesized) {
+ classBuilder.libraryBuilder.addProblem(messageStaticAndInstanceConflict,
+ staticMember.charOffset, name.length, staticMember.fileUri,
+ context: <LocatedMessage>[
+ messageStaticAndInstanceConflictCause.withLocation(
+ instanceMember.fileUri,
+ instanceMember.charOffset,
+ name.length)
+ ]);
+ } else {
+ classBuilder.libraryBuilder.addProblem(
+ templateInstanceAndSynthesizedStaticConflict
+ .withArguments(staticMember.name.text),
+ instanceMember.charOffset,
+ name.length,
+ instanceMember.fileUri);
+ }
} else {
// This message can be reported twice (when merging localMembers with
// classSetters, or localSetters with classMembers). By ensuring that
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 07ea5fb..f7b6898 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -6461,7 +6461,7 @@
TypeLiteral node, DartType typeContext) {
DartType inferredType =
inferrer.coreTypes.typeRawType(inferrer.libraryBuilder.nonNullable);
- if (inferrer.libraryBuilder.enableConstructorTearOffsInLibrary) {
+ if (inferrer.libraryFeatures.constructorTearoffs.isEnabled) {
inferrer.libraryBuilder.checkBoundsInType(
node.type,
inferrer.typeSchemaEnvironment,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 7912ac66..176a1b9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -17,7 +17,8 @@
import 'package:kernel/type_environment.dart' show TypeEnvironment;
import 'package:package_config/package_config.dart' hide LanguageVersion;
-import '../../api_prototype/experimental_flags.dart' show ExperimentalFlag;
+import '../../api_prototype/experimental_flags.dart'
+ show ExperimentalFlag, GlobalFeatures;
import '../../api_prototype/file_system.dart' show FileSystem;
import '../../base/nnbd_mode.dart';
import '../../base/processed_options.dart' show ProcessedOptions;
@@ -171,9 +172,7 @@
loader = createLoader();
}
- bool isExperimentEnabledInLibrary(ExperimentalFlag flag, Uri importUri) {
- return _options.isExperimentEnabledInLibrary(flag, importUri);
- }
+ GlobalFeatures get globalFeatures => _options.globalFeatures;
Version getExperimentEnabledVersionInLibrary(
ExperimentalFlag flag, Uri importUri) {
@@ -186,20 +185,6 @@
flag, importUri, version);
}
- /// Returns `true` if the [flag] is enabled by default.
- bool isExperimentEnabledByDefault(ExperimentalFlag flag) {
- return _options.isExperimentEnabledByDefault(flag);
- }
-
- /// Returns `true` if the [flag] is enabled globally.
- ///
- /// This is `true` either if the [flag] is passed through an explicit
- /// `--enable-experiment` option or if the [flag] is expired and on by
- /// default.
- bool isExperimentEnabledGlobally(ExperimentalFlag flag) {
- return _options.isExperimentEnabledGlobally(flag);
- }
-
Uri? translateUri(Uri uri) => uriTranslator.translate(uri);
/// Returns a reference to the constructor of
@@ -704,7 +689,7 @@
nameRoot: nameRoot, libraries: libraries, uriToSource: uriToSource));
NonNullableByDefaultCompiledMode? compiledMode = null;
- if (isExperimentEnabledGlobally(ExperimentalFlag.nonNullable)) {
+ if (globalFeatures.nonNullable.isEnabled) {
switch (loader.nnbdMode) {
case NnbdMode.Weak:
compiledMode = NonNullableByDefaultCompiledMode.Weak;
@@ -1595,12 +1580,10 @@
new KernelConstantErrorReporter(loader),
evaluationMode,
evaluateAnnotations: true,
- enableTripleShift:
- isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
- enableConstFunctions:
- isExperimentEnabledGlobally(ExperimentalFlag.constFunctions),
- enableConstructorTearOff: isExperimentEnabledGlobally(
- ExperimentalFlag.constructorTearoffs),
+ enableTripleShift: globalFeatures.tripleShift.isEnabled,
+ enableConstFunctions: globalFeatures.constFunctions.isEnabled,
+ enableConstructorTearOff:
+ globalFeatures.constructorTearoffs.isEnabled,
errorOnUnevaluatedConstant: errorOnUnevaluatedConstant);
ticker.logMs("Evaluated constants");
@@ -1617,8 +1600,7 @@
});
ticker.logMs("Added constant coverage");
- if (loader.target.context.options
- .isExperimentEnabledGlobally(ExperimentalFlag.valueClass)) {
+ if (loader.target.context.options.globalFeatures.valueClass.isEnabled) {
valueClass.transformComponent(component!, loader.coreTypes,
loader.hierarchy, loader.referenceFromIndex, environment);
ticker.logMs("Lowered value classes");
@@ -1652,12 +1634,9 @@
new KernelConstantErrorReporter(loader),
evaluationMode,
evaluateAnnotations: true,
- enableTripleShift:
- isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
- enableConstFunctions:
- isExperimentEnabledGlobally(ExperimentalFlag.constFunctions),
- enableConstructorTearOff:
- isExperimentEnabledGlobally(ExperimentalFlag.constructorTearoffs),
+ enableTripleShift: globalFeatures.tripleShift.isEnabled,
+ enableConstFunctions: globalFeatures.constFunctions.isEnabled,
+ enableConstructorTearOff: globalFeatures.constructorTearoffs.isEnabled,
errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
);
ticker.logMs("Evaluated constants");
@@ -1676,7 +1655,7 @@
// because the SDK might be agnostic and therefore needs to be weakened
// for legacy mode.
assert(
- isExperimentEnabledGlobally(ExperimentalFlag.nonNullable) ||
+ globalFeatures.nonNullable.isEnabled ||
loader.nnbdMode == NnbdMode.Weak,
"Non-weak nnbd mode found without experiment enabled: "
"${loader.nnbdMode}.");
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 2d46643..05e5c4f 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -1132,7 +1132,7 @@
? ""
: nameOrQualified as String;
}
- if (libraryBuilder.enableConstructorTearOffsInLibrary) {
+ if (libraryFeatures.constructorTearoffs.isEnabled) {
suffix = suffix == "new" ? "" : suffix;
}
declaration = currentClass!.constructorScope.local[suffix];
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index c9b3083..3793ca5 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -591,16 +591,9 @@
checkEmpty(importKeyword.charOffset);
if (prefix is ParserRecovery) return;
- if (!libraryBuilder.enableMacrosInLibrary) {
- if (augmentToken != null) {
- // TODO(johnniwinther): We should emit a different message when the
- // experiment is not released yet. The current message indicates that
- // changing the sdk version can solve the problem.
- addProblem(
- templateExperimentNotEnabled.withArguments(
- 'macros', libraryBuilder.enableMacrosVersionInLibrary.toText()),
- augmentToken.charOffset,
- augmentToken.length);
+ if (augmentToken != null) {
+ if (reportIfNotEnabled(libraryFeatures.macros, augmentToken.charOffset,
+ augmentToken.length)) {
augmentToken = null;
}
}
@@ -875,16 +868,9 @@
libraryBuilder.setCurrentClassName(name.lexeme);
inAbstractClass = abstractToken != null;
push(abstractToken != null ? abstractMask : 0);
- if (!libraryBuilder.enableMacrosInLibrary) {
- if (macroToken != null) {
- // TODO(johnniwinther): We should emit a different message when the
- // experiment is not released yet. The current message indicates that
- // changing the sdk version can solve the problem.
- addProblem(
- templateExperimentNotEnabled.withArguments(
- 'macros', libraryBuilder.enableMacrosVersionInLibrary.toText()),
- macroToken.charOffset,
- macroToken.length);
+ if (macroToken != null) {
+ if (reportIfNotEnabled(
+ libraryFeatures.macros, macroToken.charOffset, macroToken.length)) {
macroToken = null;
}
}
@@ -975,13 +961,9 @@
libraryBuilder.currentTypeParameterScopeBuilder.markAsNamedMixinApplication(
name.lexeme, name.charOffset, typeVariables);
push(abstractToken != null ? abstractMask : 0);
- if (!libraryBuilder.enableMacrosInLibrary) {
- if (macroToken != null) {
- addProblem(
- templateExperimentNotEnabled.withArguments(
- 'macros', libraryBuilder.enableMacrosVersionInLibrary.toText()),
- macroToken.next!.charOffset,
- macroToken.next!.length);
+ if (macroToken != null) {
+ if (reportIfNotEnabled(libraryFeatures.macros,
+ macroToken.next!.charOffset, macroToken.next!.length)) {
macroToken = null;
}
}
@@ -996,14 +978,10 @@
.popNonNullable(stack, interfacesCount, dummyTypeBuilder) ??
NullValue.TypeBuilderList);
- if (!libraryBuilder.enableEnhancedEnumsInLibrary &&
- implementsKeyword != null &&
+ if (implementsKeyword != null &&
declarationContext == DeclarationContext.Enum) {
- addProblem(
- templateExperimentNotEnabled.withArguments('enhanced-enums',
- libraryBuilder.enableEnhancedEnumsVersionInLibrary.toText()),
- implementsKeyword.charOffset,
- -1);
+ reportIfNotEnabled(libraryFeatures.enhancedEnums,
+ implementsKeyword.charOffset, implementsKeyword.length);
}
}
@@ -1403,11 +1381,8 @@
hiddenMembersOrTypes: hiddenMembersOrTypes ?? const <String>[],
hiddenOperators: hiddenOperators ?? const <Operator>[]);
- if (showKeyword != null && !libraryBuilder.enableExtensionTypesInLibrary) {
- addProblem(
- templateExperimentNotEnabled.withArguments('extension-types',
- libraryBuilder.enableExtensionTypesVersionInLibrary.toText()),
- showKeyword.charOffset,
+ if (showKeyword != null) {
+ reportIfNotEnabled(libraryFeatures.extensionTypes, showKeyword.charOffset,
showKeyword.length);
}
Object? onType = pop();
@@ -1431,13 +1406,9 @@
? extensionKeyword.charOffset
: metadata.first.charOffset;
bool isExtensionTypeDeclaration = typeKeyword != null;
- if (!libraryBuilder.enableExtensionTypesInLibrary &&
- isExtensionTypeDeclaration) {
- addProblem(
- templateExperimentNotEnabled.withArguments('extension-types',
- libraryBuilder.enableExtensionTypesVersionInLibrary.toText()),
- extensionKeyword.next!.charOffset,
- extensionKeyword.next!.length);
+ if (isExtensionTypeDeclaration) {
+ reportIfNotEnabled(libraryFeatures.extensionTypes,
+ extensionKeyword.next!.charOffset, extensionKeyword.next!.length);
}
libraryBuilder.addExtensionDeclaration(
metadata,
@@ -1939,7 +1910,7 @@
if (constructorName != null) {
if (isConst &&
bodyKind != MethodBody.Abstract &&
- !libraryBuilder.enableConstFunctionsInLibrary) {
+ !libraryFeatures.constFunctions.isEnabled) {
addProblem(messageConstConstructorWithBody, varFinalOrConstOffset, 5);
modifiers &= ~constMask;
}
@@ -2272,13 +2243,9 @@
MemberKind memberKind) {
debugEvent("FormalParameter");
- if (superKeyword != null &&
- !libraryBuilder.enableSuperParametersInLibrary) {
- addProblem(
- templateExperimentNotEnabled.withArguments('super-parameters',
- libraryBuilder.enableSuperParametersVersionInLibrary.toText()),
- superKeyword.charOffset,
- superKeyword.length);
+ if (superKeyword != null) {
+ reportIfNotEnabled(libraryFeatures.superParameters,
+ superKeyword.charOffset, superKeyword.length);
}
int charOffset = popCharOffset();
@@ -2692,7 +2659,7 @@
return;
}
if (type is FunctionTypeBuilder &&
- !libraryBuilder.enableNonfunctionTypeAliasesInLibrary) {
+ !libraryFeatures.nonfunctionTypeAliases.isEnabled) {
if (type.nullabilityBuilder.build(libraryBuilder) ==
Nullability.nullable &&
libraryBuilder.isNonNullableByDefault) {
@@ -2717,7 +2684,7 @@
// of a generic function).
aliasedType = type;
}
- } else if (libraryBuilder.enableNonfunctionTypeAliasesInLibrary) {
+ } else if (libraryFeatures.nonfunctionTypeAliases.isEnabled) {
if (type is TypeBuilder) {
aliasedType = type;
} else {
@@ -2977,7 +2944,7 @@
if (typeParameters != null) {
typeParameters[index].bound = bound;
if (variance != null) {
- if (!libraryBuilder.enableVarianceInLibrary) {
+ if (!libraryFeatures.variance.isEnabled) {
reportVarianceModifierNotEnabled(variance);
}
typeParameters[index].variance = Variance.fromString(variance.lexeme);
@@ -2989,13 +2956,9 @@
void endTypeVariables(Token beginToken, Token endToken) {
debugEvent("endTypeVariables");
- if (!libraryBuilder.enableEnhancedEnumsInLibrary &&
- declarationContext == DeclarationContext.Enum) {
- addProblem(
- templateExperimentNotEnabled.withArguments('enhanced-enums',
- libraryBuilder.enableEnhancedEnumsVersionInLibrary.toText()),
- beginToken.charOffset,
- -1);
+ if (declarationContext == DeclarationContext.Enum) {
+ reportIfNotEnabled(
+ libraryFeatures.enhancedEnums, beginToken.charOffset, noLength);
}
// Peek to leave type parameters on top of stack.
@@ -3103,7 +3066,7 @@
// omitted only within an enum element declaration.
if (libraryBuilder.currentTypeParameterScopeBuilder.kind ==
TypeParameterScopeKind.enumDeclaration) {
- if (libraryBuilder.enableEnhancedEnumsInLibrary) {
+ if (libraryFeatures.enhancedEnums.isEnabled) {
push(libraryBuilder.addConstructorReference(
libraryBuilder.currentTypeParameterScopeBuilder.name,
typeArguments,
@@ -3113,13 +3076,8 @@
// For entries that consist of their name only, all of the elements
// of the constructor reference should be null.
if (typeArguments != null || suffix != null) {
- addProblem(
- templateExperimentNotEnabled.withArguments(
- 'enhanced-enums',
- libraryBuilder.enableEnhancedEnumsVersionInLibrary
- .toText()),
- charOffset,
- -1);
+ addProblem(libraryFeatures.enhancedEnums.notEnabledMessage,
+ charOffset, noLength);
}
push(NullValue.ConstructorReference);
}
@@ -3228,13 +3186,8 @@
void endEnumFactoryMethod(
Token beginToken, Token factoryKeyword, Token endToken) {
debugEvent("EnumFactoryMethod");
- if (!libraryBuilder.enableEnhancedEnumsInLibrary) {
- addProblem(
- templateExperimentNotEnabled.withArguments('enhanced-enums',
- libraryBuilder.enableEnhancedEnumsVersionInLibrary.toText()),
- beginToken.charOffset,
- -1);
- }
+ reportIfNotEnabled(
+ libraryFeatures.enhancedEnums, beginToken.charOffset, noLength);
_endFactoryMethod(beginToken, factoryKeyword, endToken);
}
@@ -3242,13 +3195,8 @@
@override
void endEnumMethod(Token? getOrSet, Token beginToken, Token beginParam,
Token? beginInitializers, Token endToken) {
- if (!libraryBuilder.enableEnhancedEnumsInLibrary) {
- addProblem(
- templateExperimentNotEnabled.withArguments('enhanced-enums',
- libraryBuilder.enableEnhancedEnumsVersionInLibrary.toText()),
- beginToken.charOffset,
- -1);
- }
+ reportIfNotEnabled(
+ libraryFeatures.enhancedEnums, beginToken.charOffset, noLength);
_endClassMethod(getOrSet, beginToken, beginParam, beginInitializers,
endToken, _MethodKind.enumMethod);
@@ -3266,13 +3214,9 @@
int count,
Token beginToken,
Token endToken) {
- if (!libraryBuilder.enableEnhancedEnumsInLibrary) {
- addProblem(
- templateExperimentNotEnabled.withArguments('enhanced-enums',
- libraryBuilder.enableEnhancedEnumsVersionInLibrary.toText()),
- beginToken.charOffset,
- -1);
- }
+ reportIfNotEnabled(
+ libraryFeatures.enhancedEnums, beginToken.charOffset, noLength);
+
endClassFields(
abstractToken,
augmentToken,
@@ -3289,13 +3233,8 @@
@override
void endEnumConstructor(Token? getOrSet, Token beginToken, Token beginParam,
Token? beginInitializers, Token endToken) {
- if (!libraryBuilder.enableEnhancedEnumsInLibrary) {
- addProblem(
- templateExperimentNotEnabled.withArguments('enhanced-enums',
- libraryBuilder.enableEnhancedEnumsVersionInLibrary.toText()),
- beginToken.charOffset,
- -1);
- }
+ reportIfNotEnabled(
+ libraryFeatures.enhancedEnums, beginToken.charOffset, noLength);
_endClassMethod(getOrSet, beginToken, beginParam, beginInitializers,
endToken, _MethodKind.enumConstructor);
@@ -3310,7 +3249,7 @@
@override
void handleConstFactory(Token constKeyword) {
debugEvent("ConstFactory");
- if (!libraryBuilder.enableConstFunctionsInLibrary) {
+ if (!libraryFeatures.constFunctions.isEnabled) {
handleRecoverableError(messageConstFactory, constKeyword, constKeyword);
}
}
@@ -3438,13 +3377,8 @@
]),
]));
- if (!libraryBuilder.enableEnhancedEnumsInLibrary) {
- addProblem(
- templateExperimentNotEnabled.withArguments('enhanced-enums',
- libraryBuilder.enableEnhancedEnumsVersionInLibrary.toText()),
- withKeyword.charOffset,
- -1);
- }
+ reportIfNotEnabled(libraryFeatures.enhancedEnums, withKeyword.charOffset,
+ withKeyword.length);
Object? mixins = pop();
if (mixins is ParserRecovery) {
@@ -3512,15 +3446,8 @@
@override
void handleNewAsIdentifier(Token token) {
- if (!libraryBuilder.enableConstructorTearOffsInLibrary) {
- addProblem(
- templateExperimentNotEnabled.withArguments(
- 'constructor-tearoffs',
- libraryBuilder.enableConstructorTearOffsVersionInLibrary
- .toText()),
- token.charOffset,
- token.length);
- }
+ reportIfNotEnabled(
+ libraryFeatures.constructorTearoffs, token.charOffset, token.length);
}
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 3cfb2bf..d914a49 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -727,7 +727,7 @@
// Moreover, it checks that `FutureOr` and `void` are not among the
// supertypes and that `Enum` is not implemented by non-abstract classes.
- if (libraryBuilder.enableEnhancedEnumsInLibrary && !isEnum) {
+ if (libraryBuilder.libraryFeatures.enhancedEnums.isEnabled && !isEnum) {
bool hasEnumSuperinterface = false;
List<Supertype> interfaces =
hierarchyBuilder.getNodeFromClass(cls).superclasses;
@@ -1322,29 +1322,28 @@
void checkBoundsInSupertype(
Supertype supertype, TypeEnvironment typeEnvironment) {
- SourceLibraryBuilder libraryBuilder2 = this.libraryBuilder;
- Library library = libraryBuilder2.library;
+ Library library = libraryBuilder.library;
List<TypeArgumentIssue> issues = findTypeArgumentIssues(
new InterfaceType(
supertype.classNode, library.nonNullable, supertype.typeArguments),
typeEnvironment,
- libraryBuilder2.isNonNullableByDefault
+ libraryBuilder.isNonNullableByDefault
? SubtypeCheckMode.withNullabilities
: SubtypeCheckMode.ignoringNullabilities,
allowSuperBounded: false,
isNonNullableByDefault: library.isNonNullableByDefault,
areGenericArgumentsAllowed:
- libraryBuilder2.enableGenericMetadataInLibrary);
+ libraryBuilder.libraryFeatures.genericMetadata.isEnabled);
for (TypeArgumentIssue issue in issues) {
DartType argument = issue.argument;
TypeParameter typeParameter = issue.typeParameter;
- bool inferred = libraryBuilder2.inferredTypes.contains(argument);
+ bool inferred = libraryBuilder.inferredTypes.contains(argument);
if (issue.isGenericTypeAsArgumentIssue) {
if (inferred) {
// Supertype can't be or contain super-bounded types, so null is
// passed for super-bounded hint here.
- libraryBuilder2.reportTypeArgumentIssue(
+ libraryBuilder.reportTypeArgumentIssue(
templateGenericFunctionTypeInferredAsActualTypeArgument
.withArguments(argument, library.isNonNullableByDefault),
fileUri,
@@ -1355,7 +1354,7 @@
} else {
// Supertype can't be or contain super-bounded types, so null is
// passed for super-bounded hint here.
- libraryBuilder2.reportTypeArgumentIssue(
+ libraryBuilder.reportTypeArgumentIssue(
messageGenericFunctionTypeUsedAsActualTypeArgument,
fileUri,
charOffset,
@@ -1371,7 +1370,7 @@
template) {
// Supertype can't be or contain super-bounded types, so null is
// passed for super-bounded hint here.
- libraryBuilder2.reportTypeArgumentIssue(
+ libraryBuilder.reportTypeArgumentIssue(
template.withArguments(
argument,
typeParameter.bound,
diff --git a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
index 4d57b10..10a8838 100644
--- a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -284,7 +284,8 @@
staticFieldNameScheme,
fieldReference: valuesFieldReference,
fieldGetterReference: valuesGetterReference,
- fieldSetterReference: valuesSetterReference);
+ fieldSetterReference: valuesSetterReference,
+ isSynthesized: true);
members["values"] = valuesBuilder;
DeclaredSourceConstructorBuilder? synthesizedDefaultConstructorBuilder;
@@ -676,7 +677,7 @@
typeArguments.add(typeBuilder.build(libraryBuilder));
}
}
- if (libraryBuilder.enableEnhancedEnumsInLibrary) {
+ if (libraryBuilder.libraryFeatures.enhancedEnums.isEnabled) {
// We need to create a BodyBuilder to solve the following: 1) if
// the arguments token is provided, we'll use the BodyBuilder to
// parse them and perform inference, 2) if the type arguments
diff --git a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
index 346eda3..e5d89e8 100644
--- a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
@@ -70,6 +70,8 @@
@override
final bool isTopLevel;
+ final bool isSynthesized;
+
SourceFieldBuilder(
this.metadata,
this.type,
@@ -88,7 +90,8 @@
Reference? lateIsSetSetterReference,
Reference? lateGetterReference,
Reference? lateSetterReference,
- Token? constInitializerToken})
+ Token? constInitializerToken,
+ this.isSynthesized = false})
: _constInitializerToken = constInitializerToken,
super(libraryBuilder, charOffset) {
bool isInstanceMember = fieldNameScheme.isInstanceMember;
@@ -758,6 +761,9 @@
bool get isProperty => true;
@override
+ bool get isSynthesized => memberBuilder.isSynthesized;
+
+ @override
bool isSameDeclaration(ClassMember other) {
return other is SourceFieldMember && memberBuilder == other.memberBuilder;
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 72c27c2..177d445 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -310,143 +310,13 @@
TypeParameterScopeBuilder get libraryTypeParameterScopeBuilderForTesting =>
_libraryTypeParameterScopeBuilder;
- bool? _enableConstFunctionsInLibrary;
- bool? _enableVarianceInLibrary;
- bool? _enableNonfunctionTypeAliasesInLibrary;
- bool? _enableNonNullableInLibrary;
- Version? _enableNonNullableVersionInLibrary;
- Version? _enableConstructorTearoffsVersionInLibrary;
- Version? _enableExtensionTypesVersionInLibrary;
- Version? _enableNamedArgumentsAnywhereVersionInLibrary;
- Version? _enableSuperParametersVersionInLibrary;
- Version? _enableEnhancedEnumsVersionInLibrary;
- Version? _enableMacrosVersionInLibrary;
- bool? _enableTripleShiftInLibrary;
- bool? _enableExtensionMethodsInLibrary;
- bool? _enableGenericMetadataInLibrary;
- bool? _enableExtensionTypesInLibrary;
- bool? _enableEnhancedEnumsInLibrary;
- bool? _enableConstructorTearOffsInLibrary;
- bool? _enableNamedArgumentsAnywhereInLibrary;
- bool? _enableSuperParametersInLibrary;
- bool? _enableMacrosInLibrary;
+ LibraryFeatures? _libraryFeatures;
- bool get enableConstFunctionsInLibrary => _enableConstFunctionsInLibrary ??=
- loader.target.isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.constFunctions,
- _packageUri ?? importUri,
- languageVersion.version);
-
- bool get enableVarianceInLibrary => _enableVarianceInLibrary ??= loader.target
- .isExperimentEnabledInLibraryByVersion(ExperimentalFlag.variance,
+ /// Returns the state of the experimental features within this library.
+ LibraryFeatures get libraryFeatures =>
+ _libraryFeatures ??= new LibraryFeatures(loader.target.globalFeatures,
_packageUri ?? importUri, languageVersion.version);
- bool get enableNonfunctionTypeAliasesInLibrary =>
- _enableNonfunctionTypeAliasesInLibrary ??= loader.target
- .isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.nonfunctionTypeAliases,
- _packageUri ?? importUri,
- languageVersion.version);
-
- /// Returns `true` if the 'non-nullable' experiment is enabled for this
- /// library.
- ///
- /// Note that the library might still opt out of the experiment by having
- /// a version that is too low for opting in to the experiment.
- bool get enableNonNullableInLibrary => _enableNonNullableInLibrary ??=
- loader.target.isExperimentEnabledInLibrary(
- ExperimentalFlag.nonNullable, _packageUri ?? importUri);
-
- Version get enableNonNullableVersionInLibrary =>
- _enableNonNullableVersionInLibrary ??= loader.target
- .getExperimentEnabledVersionInLibrary(
- ExperimentalFlag.nonNullable, _packageUri ?? importUri);
-
- bool get enableConstructorTearOffsInLibrary =>
- _enableConstructorTearOffsInLibrary ??= loader.target
- .isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.constructorTearoffs,
- _packageUri ?? importUri,
- languageVersion.version);
-
- Version get enableConstructorTearOffsVersionInLibrary =>
- _enableConstructorTearoffsVersionInLibrary ??= loader.target
- .getExperimentEnabledVersionInLibrary(
- ExperimentalFlag.constructorTearoffs, _packageUri ?? importUri);
-
- bool get enableTripleShiftInLibrary => _enableTripleShiftInLibrary ??=
- loader.target.isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.tripleShift,
- _packageUri ?? importUri,
- languageVersion.version);
-
- bool get enableExtensionMethodsInLibrary =>
- _enableExtensionMethodsInLibrary ??= loader.target
- .isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.extensionMethods,
- _packageUri ?? importUri,
- languageVersion.version);
-
- bool get enableGenericMetadataInLibrary => _enableGenericMetadataInLibrary ??=
- loader.target.isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.genericMetadata,
- _packageUri ?? importUri,
- languageVersion.version);
-
- bool get enableExtensionTypesInLibrary => _enableExtensionTypesInLibrary ??=
- loader.target.isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.extensionTypes,
- _packageUri ?? importUri,
- languageVersion.version);
-
- Version get enableExtensionTypesVersionInLibrary =>
- _enableExtensionTypesVersionInLibrary ??= loader.target
- .getExperimentEnabledVersionInLibrary(
- ExperimentalFlag.extensionTypes, _packageUri ?? importUri);
-
- bool get enableNamedArgumentsAnywhereInLibrary =>
- _enableNamedArgumentsAnywhereInLibrary ??= loader.target
- .isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.namedArgumentsAnywhere,
- _packageUri ?? importUri,
- languageVersion.version);
-
- Version get enableNamedArgumentsAnywhereVersionInLibrary =>
- _enableNamedArgumentsAnywhereVersionInLibrary ??= loader.target
- .getExperimentEnabledVersionInLibrary(
- ExperimentalFlag.namedArgumentsAnywhere,
- _packageUri ?? importUri);
-
- bool get enableSuperParametersInLibrary => _enableSuperParametersInLibrary ??=
- loader.target.isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.superParameters,
- _packageUri ?? importUri,
- languageVersion.version);
-
- Version get enableSuperParametersVersionInLibrary =>
- _enableSuperParametersVersionInLibrary ??= loader.target
- .getExperimentEnabledVersionInLibrary(
- ExperimentalFlag.superParameters, _packageUri ?? importUri);
-
- bool get enableEnhancedEnumsInLibrary => _enableEnhancedEnumsInLibrary ??=
- loader.target.isExperimentEnabledInLibraryByVersion(
- ExperimentalFlag.enhancedEnums,
- _packageUri ?? importUri,
- languageVersion.version);
-
- Version get enableEnhancedEnumsVersionInLibrary =>
- _enableEnhancedEnumsVersionInLibrary ??= loader.target
- .getExperimentEnabledVersionInLibrary(
- ExperimentalFlag.enhancedEnums, _packageUri ?? importUri);
-
- bool get enableMacrosInLibrary => _enableMacrosInLibrary ??= loader.target
- .isExperimentEnabledInLibraryByVersion(ExperimentalFlag.macros,
- _packageUri ?? importUri, languageVersion.version);
-
- Version get enableMacrosVersionInLibrary => _enableMacrosVersionInLibrary ??=
- loader.target.getExperimentEnabledVersionInLibrary(
- ExperimentalFlag.macros, _packageUri ?? importUri);
-
void _updateLibraryNNBDSettings() {
library.isNonNullableByDefault = isNonNullableByDefault;
switch (loader.nnbdMode) {
@@ -571,8 +441,8 @@
}
bool _computeIsNonNullableByDefault() =>
- enableNonNullableInLibrary &&
- languageVersion.version >= enableNonNullableVersionInLibrary;
+ libraryFeatures.nonNullable.isSupported &&
+ languageVersion.version >= libraryFeatures.nonNullable.enabledVersion;
LanguageVersion get languageVersion {
assert(
@@ -711,7 +581,7 @@
prefix = name as String;
suffix = null;
}
- if (enableConstructorTearOffsInLibrary) {
+ if (libraryFeatures.constructorTearoffs.isEnabled) {
suffix = suffix == "new" ? "" : suffix;
}
if (prefix == className) {
@@ -2635,7 +2505,8 @@
if (constructorBuilder.isConst) {
currentTypeParameterScopeBuilder.declaresConstConstructor = true;
}
- if (constructorBuilder.isConst || enableSuperParametersInLibrary) {
+ if (constructorBuilder.isConst ||
+ libraryFeatures.superParameters.isEnabled) {
// const constructors will have their initializers compiled and written
// into the outline. In case of super-parameters language feature, the
// super initializers are required to infer the types of super parameters.
@@ -2999,7 +2870,7 @@
if (typeVariables != null) {
for (TypeVariableBuilder builder in typeVariables) {
if (builder.metadata != null) {
- if (!enableGenericMetadataInLibrary) {
+ if (!libraryFeatures.genericMetadata.isEnabled) {
addProblem(messageAnnotationOnFunctionTypeTypeVariable,
builder.charOffset, builder.name.length, builder.fileUri);
}
@@ -3589,7 +3460,7 @@
/// any errors were reported.
bool _recursivelyReportGenericFunctionTypesAsBoundsForVariable(
TypeVariableBuilder typeVariable) {
- if (enableGenericMetadataInLibrary) return false;
+ if (libraryFeatures.genericMetadata.isEnabled) return false;
bool hasReportedErrors = false;
hasReportedErrors =
@@ -3609,7 +3480,7 @@
/// reported.
bool _recursivelyReportGenericFunctionTypesAsBoundsForType(
TypeBuilder? typeBuilder) {
- if (enableGenericMetadataInLibrary) return false;
+ if (libraryFeatures.genericMetadata.isEnabled) return false;
List<FunctionTypeBuilder> genericFunctionTypeBuilders =
<FunctionTypeBuilder>[];
@@ -3637,7 +3508,7 @@
/// Returns `true` if any errors were reported.
bool _reportGenericFunctionTypeAsBoundIfNeeded(
TypeVariableBuilder typeVariable) {
- if (enableGenericMetadataInLibrary) return false;
+ if (libraryFeatures.genericMetadata.isEnabled) return false;
TypeBuilder? bound = typeVariable.bound;
bool isUnaliasedGenericFunctionType = bound is FunctionTypeBuilder &&
@@ -3687,7 +3558,7 @@
bool haveErroneousBounds = false;
if (!inErrorRecovery) {
- if (!enableGenericMetadataInLibrary) {
+ if (!libraryFeatures.genericMetadata.isEnabled) {
for (TypeVariableBuilder variable in variables) {
haveErroneousBounds =
_recursivelyReportGenericFunctionTypesAsBoundsForVariable(
@@ -4207,7 +4078,8 @@
: SubtypeCheckMode.ignoringNullabilities,
allowSuperBounded: true,
isNonNullableByDefault: library.isNonNullableByDefault,
- areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
+ areGenericArgumentsAllowed:
+ libraryFeatures.genericMetadata.isEnabled);
for (TypeArgumentIssue issue in issues) {
DartType argument = issue.argument;
TypeParameter typeParameter = issue.typeParameter;
@@ -4284,7 +4156,8 @@
: SubtypeCheckMode.ignoringNullabilities,
allowSuperBounded: true,
isNonNullableByDefault: library.isNonNullableByDefault,
- areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
+ areGenericArgumentsAllowed:
+ libraryFeatures.genericMetadata.isEnabled);
for (TypeArgumentIssue issue in issues) {
DartType argument = issue.argument;
TypeParameter typeParameter = issue.typeParameter;
@@ -4394,7 +4267,7 @@
: SubtypeCheckMode.ignoringNullabilities,
allowSuperBounded: allowSuperBounded,
isNonNullableByDefault: library.isNonNullableByDefault,
- areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
+ areGenericArgumentsAllowed: libraryFeatures.genericMetadata.isEnabled);
reportTypeArgumentIssues(issues, fileUri, offset, inferred: inferred);
}
@@ -4461,7 +4334,7 @@
: SubtypeCheckMode.ignoringNullabilities,
bottomType,
isNonNullableByDefault: library.isNonNullableByDefault,
- areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
+ areGenericArgumentsAllowed: libraryFeatures.genericMetadata.isEnabled);
if (issues.isNotEmpty) {
DartType? targetReceiver;
if (klass != null) {
@@ -4547,7 +4420,7 @@
: SubtypeCheckMode.ignoringNullabilities,
bottomType,
isNonNullableByDefault: library.isNonNullableByDefault,
- areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
+ areGenericArgumentsAllowed: libraryFeatures.genericMetadata.isEnabled);
reportTypeArgumentIssues(issues, fileUri, offset,
typeArgumentsInfo: getTypeArgumentsInfo(arguments),
targetReceiver: receiverType,
@@ -4580,7 +4453,7 @@
: SubtypeCheckMode.ignoringNullabilities,
bottomType,
isNonNullableByDefault: library.isNonNullableByDefault,
- areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
+ areGenericArgumentsAllowed: libraryFeatures.genericMetadata.isEnabled);
reportTypeArgumentIssues(issues, fileUri, offset,
typeArgumentsInfo: getTypeArgumentsInfo(arguments),
// TODO(johnniwinther): Special-case messaging on function type
@@ -4617,7 +4490,7 @@
: SubtypeCheckMode.ignoringNullabilities,
bottomType,
isNonNullableByDefault: library.isNonNullableByDefault,
- areGenericArgumentsAllowed: enableGenericMetadataInLibrary);
+ areGenericArgumentsAllowed: libraryFeatures.genericMetadata.isEnabled);
reportTypeArgumentIssues(issues, fileUri, offset,
targetReceiver: functionType,
typeArgumentsInfo: inferred
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 280a71d..3d323b0 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -815,10 +815,10 @@
Template<SummaryTemplate> get outlineSummaryTemplate =>
templateSourceOutlineSummary;
- Future<Token> tokenize(SourceLibraryBuilder library,
+ Future<Token> tokenize(SourceLibraryBuilder libraryBuilder,
{bool suppressLexicalErrors: false}) async {
target.benchmarker?.beginSubdivide(BenchmarkSubdivides.tokenize);
- Uri fileUri = library.fileUri;
+ Uri fileUri = libraryBuilder.fileUri;
// Lookup the file URI in the cache.
List<int>? bytes = sourceBytes[fileUri];
@@ -827,18 +827,18 @@
// Error recovery.
if (fileUri.isScheme(untranslatableUriScheme)) {
Message message =
- templateUntranslatableUri.withArguments(library.importUri);
- library.addProblemAtAccessors(message);
- bytes = synthesizeSourceForMissingFile(library.importUri, null);
+ templateUntranslatableUri.withArguments(libraryBuilder.importUri);
+ libraryBuilder.addProblemAtAccessors(message);
+ bytes = synthesizeSourceForMissingFile(libraryBuilder.importUri, null);
} else if (!fileUri.hasScheme) {
target.benchmarker?.endSubdivide();
return internalProblem(
templateInternalProblemUriMissingScheme.withArguments(fileUri),
-1,
- library.importUri);
+ libraryBuilder.importUri);
} else if (fileUri.isScheme(SourceLibraryBuilder.MALFORMED_URI_SCHEME)) {
- library.addProblemAtAccessors(messageExpectedUri);
- bytes = synthesizeSourceForMissingFile(library.importUri, null);
+ libraryBuilder.addProblemAtAccessors(messageExpectedUri);
+ bytes = synthesizeSourceForMissingFile(libraryBuilder.importUri, null);
}
if (bytes != null) {
Uint8List zeroTerminatedBytes = new Uint8List(bytes.length + 1);
@@ -857,8 +857,9 @@
} on FileSystemException catch (e) {
Message message =
templateCantReadFile.withArguments(fileUri, e.message);
- library.addProblemAtAccessors(message);
- rawBytes = synthesizeSourceForMissingFile(library.importUri, message);
+ libraryBuilder.addProblemAtAccessors(message);
+ rawBytes =
+ synthesizeSourceForMissingFile(libraryBuilder.importUri, message);
}
Uint8List zeroTerminatedBytes = new Uint8List(rawBytes.length + 1);
zeroTerminatedBytes.setRange(0, rawBytes.length, rawBytes);
@@ -872,36 +873,38 @@
configuration: new ScannerConfiguration(
enableTripleShift: target.isExperimentEnabledInLibraryByVersion(
ExperimentalFlag.tripleShift,
- library.importUri,
- library.packageLanguageVersion.version),
+ libraryBuilder.importUri,
+ libraryBuilder.packageLanguageVersion.version),
enableExtensionMethods:
target.isExperimentEnabledInLibraryByVersion(
ExperimentalFlag.extensionMethods,
- library.importUri,
- library.packageLanguageVersion.version),
+ libraryBuilder.importUri,
+ libraryBuilder.packageLanguageVersion.version),
enableNonNullable: target.isExperimentEnabledInLibraryByVersion(
ExperimentalFlag.nonNullable,
- library.importUri,
- library.packageLanguageVersion.version),
- forAugmentationLibrary: library.isAugmentation),
+ libraryBuilder.importUri,
+ libraryBuilder.packageLanguageVersion.version),
+ forAugmentationLibrary: libraryBuilder.isAugmentation),
languageVersionChanged:
(Scanner scanner, LanguageVersionToken version) {
if (!suppressLexicalErrors) {
- library.registerExplicitLanguageVersion(
+ libraryBuilder.registerExplicitLanguageVersion(
new Version(version.major, version.minor),
offset: version.offset,
length: version.length);
}
scanner.configuration = new ScannerConfiguration(
- enableTripleShift: library.enableTripleShiftInLibrary,
- enableExtensionMethods: library.enableExtensionMethodsInLibrary,
- enableNonNullable: library.isNonNullableByDefault);
+ enableTripleShift:
+ libraryBuilder.libraryFeatures.tripleShift.isEnabled,
+ enableExtensionMethods:
+ libraryBuilder.libraryFeatures.extensionMethods.isEnabled,
+ enableNonNullable: libraryBuilder.isNonNullableByDefault);
});
Token token = result.tokens;
if (!suppressLexicalErrors) {
List<int> source = getSource(bytes);
- Uri importUri = library.importUri;
- if (library.isPatch) {
+ Uri importUri = libraryBuilder.importUri;
+ if (libraryBuilder.isPatch) {
// For patch files we create a "fake" import uri.
// We cannot use the import uri from the patched library because
// several different files would then have the same import uri,
@@ -910,19 +913,19 @@
// represented several files?
List<String> newPathSegments =
new List<String>.of(importUri.pathSegments);
- newPathSegments.add(library.fileUri.pathSegments.last);
+ newPathSegments.add(libraryBuilder.fileUri.pathSegments.last);
newPathSegments[0] = "${newPathSegments[0]}-patch";
importUri = importUri.replace(pathSegments: newPathSegments);
}
target.addSourceInformation(
- importUri, library.fileUri, result.lineStarts, source);
+ importUri, libraryBuilder.fileUri, result.lineStarts, source);
}
- library.issuePostponedProblems();
- library.markLanguageVersionFinal();
+ libraryBuilder.issuePostponedProblems();
+ libraryBuilder.markLanguageVersionFinal();
while (token is ErrorToken) {
if (!suppressLexicalErrors) {
ErrorToken error = token;
- library.addProblem(error.assertionMessage, offsetForToken(token),
+ libraryBuilder.addProblem(error.assertionMessage, offsetForToken(token),
lengthForToken(token), fileUri);
}
token = token.next!;
@@ -1900,7 +1903,7 @@
}
bool checkEnumSupertypeIsDenylisted(SourceClassBuilder cls) {
- if (!cls.libraryBuilder.enableEnhancedEnumsInLibrary) {
+ if (!cls.libraryBuilder.libraryFeatures.enhancedEnums.isEnabled) {
cls.addProblem(
templateEnumSupertypeOfNonAbstractClass.withArguments(cls.name),
cls.charOffset,
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
index 3e8326c..be0fc08 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
@@ -12,6 +12,7 @@
import 'package:kernel/ast.dart';
+import '../../api_prototype/experimental_flags.dart';
import '../fasta_codes.dart';
import '../problems.dart' as problems
@@ -22,6 +23,8 @@
abstract class StackListenerImpl extends StackListener {
SourceLibraryBuilder get libraryBuilder;
+ LibraryFeatures get libraryFeatures => libraryBuilder.libraryFeatures;
+
AsyncMarker asyncMarkerFromTokens(Token? asyncToken, Token? starToken) {
if (asyncToken == null || identical(asyncToken.stringValue, "sync")) {
if (starToken == null) {
@@ -75,11 +78,11 @@
assert(!libraryBuilder.isNonNullableByDefault);
// ignore: unnecessary_null_comparison
assert(token != null);
- if (libraryBuilder.enableNonNullableInLibrary) {
+ if (libraryFeatures.nonNullable.isSupported) {
if (libraryBuilder.languageVersion.isExplicit) {
addProblem(
templateNonNullableOptOutExplicit.withArguments(
- libraryBuilder.enableNonNullableVersionInLibrary.toText()),
+ libraryFeatures.nonNullable.enabledVersion.toText()),
token.charOffset,
token.charCount,
context: <LocatedMessage>[
@@ -91,16 +94,16 @@
} else {
addProblem(
templateNonNullableOptOutImplicit.withArguments(
- libraryBuilder.enableNonNullableVersionInLibrary.toText()),
+ libraryFeatures.nonNullable.enabledVersion.toText()),
token.charOffset,
token.charCount);
}
} else {
if (libraryBuilder.languageVersion.version <
- libraryBuilder.enableNonNullableVersionInLibrary) {
+ libraryFeatures.nonNullable.enabledVersion) {
addProblem(
templateExperimentDisabledInvalidLanguageVersion.withArguments(
- libraryBuilder.enableNonNullableVersionInLibrary.toText()),
+ libraryFeatures.nonNullable.enabledVersion.toText()),
token.offset,
noLength);
} else {
@@ -110,6 +113,18 @@
}
}
+ /// Reports an error if [feature] is not enabled, using [charOffset] and
+ /// [length] for the location of the message.
+ ///
+ /// Return `true` if the [feature] is not enabled.
+ bool reportIfNotEnabled(LibraryFeature feature, int charOffset, int length) {
+ if (!feature.isEnabled) {
+ addProblem(feature.notEnabledMessage, charOffset, length);
+ return true;
+ }
+ return false;
+ }
+
void reportErrorIfNullableType(Token? questionMark) {
if (questionMark != null) {
reportMissingNonNullableSupport(questionMark);
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index e19c27a..b99f8f5 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -15,6 +15,7 @@
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
+import '../../api_prototype/experimental_flags.dart';
import '../../base/instrumentation.dart'
show
Instrumentation,
@@ -193,7 +194,7 @@
new TypeOperationsCfe(engine.typeSchemaEnvironment),
assignedVariables,
respectImplicitlyTypedVarInitializers:
- libraryBuilder.enableConstructorTearOffsInLibrary)
+ libraryFeatures.constructorTearoffs.isEnabled)
: new FlowAnalysis.legacy(
new TypeOperationsCfe(engine.typeSchemaEnvironment),
assignedVariables);
@@ -253,6 +254,8 @@
NnbdMode get nnbdMode => libraryBuilder.loader.nnbdMode;
+ LibraryFeatures get libraryFeatures => libraryBuilder.libraryFeatures;
+
DartType get bottomType =>
isNonNullableByDefault ? const NeverType.nonNullable() : const NullType();
@@ -817,7 +820,7 @@
}
}
ImplicitInstantiation? implicitInstantiation;
- if (coerceExpression && libraryBuilder.enableConstructorTearOffsInLibrary) {
+ if (coerceExpression && libraryFeatures.constructorTearoffs.isEnabled) {
implicitInstantiation =
computeImplicitInstantiation(expressionType, contextType);
if (implicitInstantiation != null) {
@@ -1249,7 +1252,7 @@
target = isReceiverTypePotentiallyNullable
? const ObjectAccessTarget.nullableCallFunction()
: const ObjectAccessTarget.callFunction();
- } else if (libraryBuilder.enableExtensionTypesInLibrary &&
+ } else if (libraryFeatures.extensionTypes.isEnabled &&
receiverBound is ExtensionType) {
target = _findDirectExtensionTypeMember(receiverBound, name, fileOffset,
isSetter: isSetter,
@@ -2291,7 +2294,7 @@
}
List<VariableDeclaration>? localHoistedExpressions;
- if (libraryBuilder.enableNamedArgumentsAnywhereInLibrary &&
+ if (libraryFeatures.namedArgumentsAnywhere.isEnabled &&
arguments.argumentsOriginalOrder != null &&
hoistedExpressions == null &&
!isTopLevel) {
@@ -2337,7 +2340,7 @@
// TODO(paulberry): if we are doing top level inference and type arguments
// were omitted, report an error.
List<Object?> argumentsEvaluationOrder;
- if (libraryBuilder.enableNamedArgumentsAnywhereInLibrary &&
+ if (libraryFeatures.namedArgumentsAnywhere.isEnabled &&
arguments.argumentsOriginalOrder != null) {
if (staticTarget?.isExtensionMember ?? false) {
// Add the receiver.
@@ -2368,7 +2371,7 @@
// vector, and none of the arguments is hoisted. That way the legacy
// behavior is preserved.
int hoistingEndIndex;
- if (libraryBuilder.enableNamedArgumentsAnywhereInLibrary) {
+ if (libraryFeatures.namedArgumentsAnywhere.isEnabled) {
hoistingEndIndex = argumentsEvaluationOrder.length - 1;
for (int i = argumentsEvaluationOrder.length - 2;
i >= 0 && hoistingEndIndex == i + 1;
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 98030ea..d7d8f6a1 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -475,6 +475,7 @@
InitializerOutsideConstructor/example: Fail
InputFileNotFound/analyzerCode: Fail
InputFileNotFound/example: Fail
+InstanceAndSynthesizedStaticConflict/example: Fail
InstantiationNonGenericFunctionType/analyzerCode: Fail
InstantiationTooFewArguments/analyzerCode: Fail
InstantiationTooManyArguments/analyzerCode: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 7079da9..dfd77a5 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -4597,6 +4597,10 @@
problemMessage: "This is the instance member."
severity: CONTEXT
+InstanceAndSynthesizedStaticConflict:
+ problemMessage: "This instance member conflicts with the synthesized static member called '#name'."
+ analyzerCode: CONFLICTING_STATIC_AND_INSTANCE
+
FfiAbiSpecificIntegerInvalid:
# Used by dart:ffi
problemMessage: "Classes extending 'AbiSpecificInteger' must have exactly one const constructor, no other members, and no type arguments."
diff --git a/pkg/front_end/test/constant_evaluator_benchmark.dart b/pkg/front_end/test/constant_evaluator_benchmark.dart
index c86c066..8319bc8 100644
--- a/pkg/front_end/test/constant_evaluator_benchmark.dart
+++ b/pkg/front_end/test/constant_evaluator_benchmark.dart
@@ -87,12 +87,11 @@
new SilentErrorReporter(),
evaluationMode,
evaluateAnnotations: true,
- enableTripleShift: target
- .isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
- enableConstFunctions: target
- .isExperimentEnabledGlobally(ExperimentalFlag.constFunctions),
- enableConstructorTearOff: target.isExperimentEnabledGlobally(
- ExperimentalFlag.constructorTearoffs),
+ enableTripleShift: target.globalFeatures.tripleShift.isEnabled,
+ enableConstFunctions:
+ target.globalFeatures.constFunctions.isEnabled,
+ enableConstructorTearOff:
+ target.globalFeatures.constructorTearoffs.isEnabled,
errorOnUnevaluatedConstant:
incrementalCompiler.context.options.errorOnUnevaluatedConstant);
print("Transformed constants with $environmentDefinesDescription"
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 81a45e4..c2ab5a9 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -869,7 +869,7 @@
target.backendTarget,
result.component,
result.options.environmentDefines,
- target.isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
+ target.globalFeatures.tripleShift.isEnabled,
environment,
!target.backendTarget.supportsSetLiterals,
result.options.errorOnUnevaluatedConstant,
diff --git a/pkg/front_end/test/incremental_suite.dart b/pkg/front_end/test/incremental_suite.dart
index e72f3f2..84d3b6c 100644
--- a/pkg/front_end/test/incremental_suite.dart
+++ b/pkg/front_end/test/incremental_suite.dart
@@ -23,7 +23,7 @@
show CompilerOptions, parseExperimentalArguments, parseExperimentalFlags;
import 'package:front_end/src/api_prototype/experimental_flags.dart'
- show ExperimentalFlag, experimentEnabledVersion;
+ show ExperimentalFlag;
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
show IncrementalCompilerResult;
import "package:front_end/src/api_prototype/memory_file_system.dart"
@@ -392,7 +392,7 @@
String doStringReplacements(String input) {
Version enableNonNullableVersion =
- experimentEnabledVersion[ExperimentalFlag.nonNullable]!;
+ ExperimentalFlag.nonNullable.experimentEnabledVersion;
String output = input.replaceAll("%NNBD_VERSION_MARKER%",
"${enableNonNullableVersion.major}.${enableNonNullableVersion.minor}");
return output;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index a85eeaf..099e6f8 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -639,6 +639,7 @@
interior
interleaved
intermediate
+internet
interpolations
interrupted
intersects
@@ -651,6 +652,7 @@
ints
invariants
io
+ipv
isolate
isolated
isolates
@@ -734,6 +736,7 @@
logged
logically
lookahead
+loopback
lots
lp
lparen
@@ -968,6 +971,7 @@
pulled
pure
puts
+pv
q
q'i
qi
diff --git a/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart
new file mode 100644
index 0000000..78f8244
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, 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.
+
+enum E {
+ e1,
+ e2;
+
+ void set values(List<E> val) {} // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.strong.expect
new file mode 100644
index 0000000..f257434
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.strong.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart:9:12: Error: This instance member conflicts with the synthesized static member called 'values'.
+// void set values(List<E> val) {} // Error.
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/ {
+ static const field core::List<self::E> values = #C7;
+ static const field self::E e1 = #C3;
+ static const field self::E e2 = #C6;
+ const constructor •(core::int index, core::String name) → self::E
+ : super core::_Enum::•(index, name)
+ ;
+ method toString() → core::String
+ return "E.${this.{core::_Enum::_name}{core::String}}";
+ set values(core::List<self::E> val) → void {}
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = 0
+ #C2 = "e1"
+ #C3 = self::E {index:#C1, _name:#C2}
+ #C4 = 1
+ #C5 = "e2"
+ #C6 = self::E {index:#C4, _name:#C5}
+ #C7 = <self::E>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///member_values_conflicts.dart:
+- E. (from org-dartlang-testcase:///member_values_conflicts.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.strong.transformed.expect
new file mode 100644
index 0000000..f257434
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.strong.transformed.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart:9:12: Error: This instance member conflicts with the synthesized static member called 'values'.
+// void set values(List<E> val) {} // Error.
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/ {
+ static const field core::List<self::E> values = #C7;
+ static const field self::E e1 = #C3;
+ static const field self::E e2 = #C6;
+ const constructor •(core::int index, core::String name) → self::E
+ : super core::_Enum::•(index, name)
+ ;
+ method toString() → core::String
+ return "E.${this.{core::_Enum::_name}{core::String}}";
+ set values(core::List<self::E> val) → void {}
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = 0
+ #C2 = "e1"
+ #C3 = self::E {index:#C1, _name:#C2}
+ #C4 = 1
+ #C5 = "e2"
+ #C6 = self::E {index:#C4, _name:#C5}
+ #C7 = <self::E>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///member_values_conflicts.dart:
+- E. (from org-dartlang-testcase:///member_values_conflicts.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.textual_outline.expect
new file mode 100644
index 0000000..77502aa
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+enum E {
+ e1,
+ e2;
+
+ void set values(List<E> val) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..77502aa
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+enum E {
+ e1,
+ e2;
+
+ void set values(List<E> val) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.expect
new file mode 100644
index 0000000..756f859
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart:9:12: Error: This instance member conflicts with the synthesized static member called 'values'.
+// void set values(List<E> val) {} // Error.
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/ {
+ static const field core::List<self::E> values = #C7;
+ static const field self::E e1 = #C3;
+ static const field self::E e2 = #C6;
+ const constructor •(core::int index, core::String name) → self::E
+ : super core::_Enum::•(index, name)
+ ;
+ method toString() → core::String
+ return "E.${this.{core::_Enum::_name}{core::String}}";
+ set values(core::List<self::E> val) → void {}
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = 0
+ #C2 = "e1"
+ #C3 = self::E {index:#C1, _name:#C2}
+ #C4 = 1
+ #C5 = "e2"
+ #C6 = self::E {index:#C4, _name:#C5}
+ #C7 = <self::E*>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///member_values_conflicts.dart:
+- E. (from org-dartlang-testcase:///member_values_conflicts.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.modular.expect
new file mode 100644
index 0000000..756f859
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.modular.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart:9:12: Error: This instance member conflicts with the synthesized static member called 'values'.
+// void set values(List<E> val) {} // Error.
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/ {
+ static const field core::List<self::E> values = #C7;
+ static const field self::E e1 = #C3;
+ static const field self::E e2 = #C6;
+ const constructor •(core::int index, core::String name) → self::E
+ : super core::_Enum::•(index, name)
+ ;
+ method toString() → core::String
+ return "E.${this.{core::_Enum::_name}{core::String}}";
+ set values(core::List<self::E> val) → void {}
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = 0
+ #C2 = "e1"
+ #C3 = self::E {index:#C1, _name:#C2}
+ #C4 = 1
+ #C5 = "e2"
+ #C6 = self::E {index:#C4, _name:#C5}
+ #C7 = <self::E*>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///member_values_conflicts.dart:
+- E. (from org-dartlang-testcase:///member_values_conflicts.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.outline.expect
new file mode 100644
index 0000000..5cd70a0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.outline.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart:9:12: Error: This instance member conflicts with the synthesized static member called 'values'.
+// void set values(List<E> val) {} // Error.
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/ {
+ static const field core::List<self::E> values = const <self::E>[self::E::e1, self::E::e2];
+ static const field self::E e1 = const self::E::•(0, "e1");
+ static const field self::E e2 = const self::E::•(1, "e2");
+ const constructor •(core::int index, core::String name) → self::E
+ : super core::_Enum::•(index, name)
+ ;
+ method toString() → core::String
+ return "E.${this.{core::_Enum::_name}{core::String}}";
+ set values(core::List<self::E> val) → void
+ ;
+}
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///member_values_conflicts.dart:5:6 -> ListConstant(const <E*>[const E{_Enum.index: 0, _Enum._name: "e1"}, const E{_Enum.index: 1, _Enum._name: "e2"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///member_values_conflicts.dart:6:3 -> InstanceConstant(const E{_Enum.index: 0, _Enum._name: "e1"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///member_values_conflicts.dart:7:3 -> InstanceConstant(const E{_Enum.index: 1, _Enum._name: "e2"})
+Extra constant evaluation: evaluated: 8, effectively constant: 3
diff --git a/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.transformed.expect
new file mode 100644
index 0000000..756f859
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart.weak.transformed.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/member_values_conflicts.dart:9:12: Error: This instance member conflicts with the synthesized static member called 'values'.
+// void set values(List<E> val) {} // Error.
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/ {
+ static const field core::List<self::E> values = #C7;
+ static const field self::E e1 = #C3;
+ static const field self::E e2 = #C6;
+ const constructor •(core::int index, core::String name) → self::E
+ : super core::_Enum::•(index, name)
+ ;
+ method toString() → core::String
+ return "E.${this.{core::_Enum::_name}{core::String}}";
+ set values(core::List<self::E> val) → void {}
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = 0
+ #C2 = "e1"
+ #C3 = self::E {index:#C1, _name:#C2}
+ #C4 = 1
+ #C5 = "e2"
+ #C6 = self::E {index:#C4, _name:#C5}
+ #C7 = <self::E*>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///member_values_conflicts.dart:
+- E. (from org-dartlang-testcase:///member_values_conflicts.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/super_parameters/issue48714.dart b/pkg/front_end/testcases/super_parameters/issue48714.dart
new file mode 100644
index 0000000..f813a85
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48714.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Base {
+ int value;
+ Base(this.value);
+}
+
+class Extended extends Base {
+ Extended.one(final super.value); // Ok.
+ Extended.two(var super.value); // Error.
+ Extended.three(const super.value); // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48714.dart.strong.expect b/pkg/front_end/testcases/super_parameters/issue48714.dart.strong.expect
new file mode 100644
index 0000000..fb8c1e75
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48714.dart.strong.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:13:18: Error: Can't have modifier 'const' here.
+// Try removing 'const'.
+// Extended.three(const super.value); // Error.
+// ^^^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:12:16: Error: Can't have modifier 'var' here.
+// Try removing 'var'.
+// Extended.two(var super.value); // Error.
+// ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Base extends core::Object {
+ field core::int value;
+ constructor •(core::int value) → self::Base
+ : self::Base::value = value, super core::Object::•()
+ ;
+}
+class Extended extends self::Base {
+ constructor one(final core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor two(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor three(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48714.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48714.dart.strong.transformed.expect
new file mode 100644
index 0000000..fb8c1e75
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48714.dart.strong.transformed.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:13:18: Error: Can't have modifier 'const' here.
+// Try removing 'const'.
+// Extended.three(const super.value); // Error.
+// ^^^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:12:16: Error: Can't have modifier 'var' here.
+// Try removing 'var'.
+// Extended.two(var super.value); // Error.
+// ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Base extends core::Object {
+ field core::int value;
+ constructor •(core::int value) → self::Base
+ : self::Base::value = value, super core::Object::•()
+ ;
+}
+class Extended extends self::Base {
+ constructor one(final core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor two(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor three(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48714.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/issue48714.dart.textual_outline.expect
new file mode 100644
index 0000000..c5daa03
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48714.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+class Base {
+ int value;
+ Base(this.value);
+}
+class Extended extends Base {
+ Extended.one(final super.value);
+ Extended.two(var super.value);
+ Extended.three(const super.value);
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.expect b/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.expect
new file mode 100644
index 0000000..fb8c1e75
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:13:18: Error: Can't have modifier 'const' here.
+// Try removing 'const'.
+// Extended.three(const super.value); // Error.
+// ^^^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:12:16: Error: Can't have modifier 'var' here.
+// Try removing 'var'.
+// Extended.two(var super.value); // Error.
+// ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Base extends core::Object {
+ field core::int value;
+ constructor •(core::int value) → self::Base
+ : self::Base::value = value, super core::Object::•()
+ ;
+}
+class Extended extends self::Base {
+ constructor one(final core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor two(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor three(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.modular.expect
new file mode 100644
index 0000000..fb8c1e75
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.modular.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:13:18: Error: Can't have modifier 'const' here.
+// Try removing 'const'.
+// Extended.three(const super.value); // Error.
+// ^^^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:12:16: Error: Can't have modifier 'var' here.
+// Try removing 'var'.
+// Extended.two(var super.value); // Error.
+// ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Base extends core::Object {
+ field core::int value;
+ constructor •(core::int value) → self::Base
+ : self::Base::value = value, super core::Object::•()
+ ;
+}
+class Extended extends self::Base {
+ constructor one(final core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor two(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor three(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.outline.expect
new file mode 100644
index 0000000..288205c
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.outline.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:13:18: Error: Can't have modifier 'const' here.
+// Try removing 'const'.
+// Extended.three(const super.value); // Error.
+// ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Base extends core::Object {
+ field core::int value;
+ constructor •(core::int value) → self::Base
+ ;
+}
+class Extended extends self::Base {
+ constructor one(final core::int value) → self::Extended
+ ;
+ constructor two(core::int value) → self::Extended
+ ;
+ constructor three(core::int value) → self::Extended
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.transformed.expect
new file mode 100644
index 0000000..fb8c1e75
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48714.dart.weak.transformed.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:13:18: Error: Can't have modifier 'const' here.
+// Try removing 'const'.
+// Extended.three(const super.value); // Error.
+// ^^^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48714.dart:12:16: Error: Can't have modifier 'var' here.
+// Try removing 'var'.
+// Extended.two(var super.value); // Error.
+// ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Base extends core::Object {
+ field core::int value;
+ constructor •(core::int value) → self::Base
+ : self::Base::value = value, super core::Object::•()
+ ;
+}
+class Extended extends self::Base {
+ constructor one(final core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor two(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+ constructor three(core::int value) → self::Extended
+ : super self::Base::•(value)
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index df71eb8..fab8f81 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -217,6 +217,7 @@
regress/issue_41265.crash: FormatterCrash
super_parameters/issue47741: FormatterCrash
super_parameters/issue47922: FormatterCrash
+super_parameters/issue48714: FormatterCrash
super_parameters/opt_out: FormatterCrash
super_parameters/var_before_super: FormatterCrash
triple_shift/invalid_operator: FormatterCrash
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
index e321747..7b29209 100644
--- a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
@@ -120,36 +120,185 @@
sb.write('''
-enum ExperimentalFlag {
+/// An experiment flag including its fixed properties.
+class ExperimentalFlag {
+ /// The name of this flag as used in the --enable-experiment option.
+ final String name;
+
+ /// `true` if this experimental feature is enabled by default.
+ ///
+ /// When `true`, the feature can still be disabled in individual libraries
+ /// with a language version below the [experimentEnabledVersion], and if not
+ /// [isExpired], the feature can also be disabled by using a 'no-' prefix
+ /// in the --enable-experiment option.
+ final bool isEnabledByDefault;
+
+ /// `true` if this feature can no longer be changed using the
+ /// --enable-experiment option.
+ ///
+ /// Libraries can still opt out of the feature by using a language version
+ /// below the [experimentEnabledVersion].
+ final bool isExpired;
+ final Version enabledVersion;
+
+ /// The minimum version that supports this feature.
+ ///
+ /// If the feature is not enabled by default, this is the current language
+ /// version.
+ final Version experimentEnabledVersion;
+
+ /// The minimum version that supports this feature in allowed libraries.
+ ///
+ /// Allowed libraries are specified in
+ ///
+ /// sdk/lib/_internal/allowed_experiments.json
+ final Version experimentReleasedVersion;
+
+ const ExperimentalFlag(
+ {required this.name,
+ required this.isEnabledByDefault,
+ required this.isExpired,
+ required this.enabledVersion,
+ required this.experimentEnabledVersion,
+ required this.experimentReleasedVersion});
''');
for (String key in keys) {
- sb.writeln(' ${keyToIdentifier(key)},');
+ String identifier = keyToIdentifier(key);
+ int enabledInMajor;
+ int enabledInMinor;
+ String? enabledIn =
+ getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
+ if (enabledIn == null) {
+ enabledInMajor = currentVersionMajor;
+ enabledInMinor = currentVersionMinor;
+ } else {
+ List<String> split = enabledIn.split(".");
+ enabledInMajor = int.parse(split[0]);
+ enabledInMinor = int.parse(split[1]);
+ }
+ bool? expired = (features[key] as YamlMap)['expired'];
+ bool shipped = (features[key] as YamlMap)['enabledIn'] != null;
+ if (shipped) {
+ if (expired == false) {
+ throw 'Cannot mark shipped feature "$key" as "expired: false"';
+ }
+ }
+ int releaseMajor;
+ int releaseMinor;
+ String? experimentalReleaseVersion = getAsVersionNumberString(
+ (features[key] as YamlMap)['experimentalReleaseVersion']);
+ if (experimentalReleaseVersion != null) {
+ List<String> split = experimentalReleaseVersion.split(".");
+ releaseMajor = int.parse(split[0]);
+ releaseMinor = int.parse(split[1]);
+ } else if (enabledIn != null) {
+ List<String> split = enabledIn.split(".");
+ releaseMajor = int.parse(split[0]);
+ releaseMinor = int.parse(split[1]);
+ } else {
+ releaseMajor = currentVersionMajor;
+ releaseMinor = currentVersionMinor;
+ }
+
+ sb.writeln('''
+ static const ExperimentalFlag ${identifier} =
+ const ExperimentalFlag(
+ name: '$key',
+ isEnabledByDefault: $shipped,
+ isExpired: ${expired == true},
+ enabledVersion: const Version($enabledInMajor, $enabledInMinor),
+ experimentEnabledVersion: const Version($enabledInMajor, $enabledInMinor),
+ experimentReleasedVersion: const Version($releaseMajor, $releaseMinor));
+''');
+ }
+ sb.write('''
+}
+''');
+
+ sb.write('''
+/// Interface for accessing the global state of experimental features.
+class GlobalFeatures {
+ final Map<ExperimentalFlag, bool> explicitExperimentalFlags;
+ final AllowedExperimentalFlags? allowedExperimentalFlags;
+ final Map<ExperimentalFlag, bool>? defaultExperimentFlagsForTesting;
+ final Map<ExperimentalFlag, Version>? experimentEnabledVersionForTesting;
+ final Map<ExperimentalFlag, Version>? experimentReleasedVersionForTesting;
+
+ GlobalFeatures(this.explicitExperimentalFlags,
+ {this.allowedExperimentalFlags,
+ this.defaultExperimentFlagsForTesting,
+ this.experimentEnabledVersionForTesting,
+ this.experimentReleasedVersionForTesting});
+
+ GlobalFeature _computeGlobalFeature(ExperimentalFlag flag) {
+ return new GlobalFeature(
+ flag,
+ isExperimentEnabled(flag,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ explicitExperimentalFlags: explicitExperimentalFlags));
+ }
+
+ LibraryFeature _computeLibraryFeature(
+ ExperimentalFlag flag, Uri canonicalUri, Version libraryVersion) {
+ return new LibraryFeature(
+ flag,
+ isExperimentEnabledInLibrary(flag, canonicalUri,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ explicitExperimentalFlags: explicitExperimentalFlags,
+ allowedExperimentalFlags: allowedExperimentalFlags),
+ getExperimentEnabledVersionInLibrary(
+ flag, canonicalUri, explicitExperimentalFlags,
+ allowedExperimentalFlags: allowedExperimentalFlags,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ experimentEnabledVersionForTesting:
+ experimentEnabledVersionForTesting,
+ experimentReleasedVersionForTesting:
+ experimentReleasedVersionForTesting),
+ isExperimentEnabledInLibraryByVersion(
+ flag, canonicalUri, libraryVersion,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ explicitExperimentalFlags: explicitExperimentalFlags,
+ allowedExperimentalFlags: allowedExperimentalFlags));
+ }
+''');
+ for (String key in keys) {
+ String identifier = keyToIdentifier(key);
+ sb.write('''
+
+ GlobalFeature? _${identifier};
+ GlobalFeature get ${identifier} =>
+ _${identifier} ??= _computeGlobalFeature(ExperimentalFlag.${identifier});
+''');
}
sb.write('''
}
+/// Interface for accessing the state of experimental features within a
+/// specific library.
+class LibraryFeatures {
+ final GlobalFeatures globalFeatures;
+ final Uri canonicalUri;
+ final Version libraryVersion;
+
+ LibraryFeatures(this.globalFeatures, this.canonicalUri, this.libraryVersion);
+''');
+ for (String key in keys) {
+ String identifier = keyToIdentifier(key);
+ sb.write('''
+
+ LibraryFeature? _${identifier};
+ LibraryFeature get ${identifier} => _${identifier} ??= globalFeatures
+ ._computeLibraryFeature(
+ ExperimentalFlag.${identifier},
+ canonicalUri,
+ libraryVersion);
+''');
+ }
+ sb.write('''
+}
''');
- for (String key in keys) {
- int major;
- int minor;
- String? enabledIn =
- getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
- if (enabledIn == null) {
- major = currentVersionMajor;
- minor = currentVersionMinor;
- } else {
- List<String> split = enabledIn.split(".");
- major = int.parse(split[0]);
- minor = int.parse(split[1]);
- }
- sb.writeln(' const Version enable'
- '${keyToIdentifier(key, upperCaseFirst: true)}'
- 'Version = const Version($major, $minor);');
- }
-
sb.write('''
-
ExperimentalFlag? parseExperimentalFlag(String flag) {
switch (flag) {
''');
@@ -161,78 +310,15 @@
return null;
}
-const Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
+final Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
''');
for (String key in keys) {
- bool? expired = (features[key] as YamlMap)['expired'];
- bool shipped = (features[key] as YamlMap)['enabledIn'] != null;
- sb.writeln(' ExperimentalFlag.${keyToIdentifier(key)}: ${shipped},');
- if (shipped) {
- if (expired == false) {
- throw 'Cannot mark shipped feature "$key" as "expired: false"';
- }
- }
+ sb.writeln('''
+ ExperimentalFlag.${keyToIdentifier(key)}:
+ ExperimentalFlag.${keyToIdentifier(key)}.isEnabledByDefault,''');
}
sb.write('''
};
-
-const Map<ExperimentalFlag, bool> expiredExperimentalFlags = {
-''');
- for (String key in keys) {
- bool expired = (features[key] as YamlMap)['expired'] == true;
- sb.writeln(' ExperimentalFlag.${keyToIdentifier(key)}: ${expired},');
- }
- sb.write('''
-};
-
-const Map<ExperimentalFlag, Version> experimentEnabledVersion = {
-''');
- for (String key in keys) {
- int major;
- int minor;
- String? enabledIn =
- getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
- if (enabledIn != null) {
- List<String> split = enabledIn.split(".");
- major = int.parse(split[0]);
- minor = int.parse(split[1]);
- } else {
- major = currentVersionMajor;
- minor = currentVersionMinor;
- }
- sb.writeln(' ExperimentalFlag.${keyToIdentifier(key)}: '
- 'const Version($major, $minor),');
- }
- sb.write('''
-};
-
-const Map<ExperimentalFlag, Version> experimentReleasedVersion = {
-''');
- for (String key in keys) {
- int major;
- int minor;
- String? enabledIn =
- getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
- String? experimentalReleaseVersion = getAsVersionNumberString(
- (features[key] as YamlMap)['experimentalReleaseVersion']);
- if (experimentalReleaseVersion != null) {
- List<String> split = experimentalReleaseVersion.split(".");
- major = int.parse(split[0]);
- minor = int.parse(split[1]);
- } else if (enabledIn != null) {
- List<String> split = enabledIn.split(".");
- major = int.parse(split[0]);
- minor = int.parse(split[1]);
- } else {
- major = currentVersionMajor;
- minor = currentVersionMinor;
- }
- sb.writeln(' ExperimentalFlag.${keyToIdentifier(key)}: '
- 'const Version($major, $minor),');
- }
- sb.write('''
-};
-
''');
Uri allowListFile = computeAllowListFile(repoDir);
diff --git a/pkg/frontend_server/lib/compute_kernel.dart b/pkg/frontend_server/lib/compute_kernel.dart
index 3754d31..e51cafc 100644
--- a/pkg/frontend_server/lib/compute_kernel.dart
+++ b/pkg/frontend_server/lib/compute_kernel.dart
@@ -7,7 +7,6 @@
/// A library to invoke the CFE to compute kernel summary files.
///
/// Used by `utils/bazel/kernel_worker.dart`.
-
import 'dart:async';
import 'dart:io';
@@ -22,7 +21,6 @@
import 'package:compiler/src/kernel/dart2js_target.dart';
import 'package:dev_compiler/src/kernel/target.dart';
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart';
-import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
import 'package:front_end/src/fasta/kernel/macro/macro.dart';
import 'package:kernel/ast.dart' show Component, Library, Reference;
@@ -299,8 +297,7 @@
// Either set up or reset the state for macros based on experiment status.
// TODO: Make this a part of `initializeCompiler`, if/when we want to make it
// more widely supported.
- if (state.processedOpts
- .isExperimentEnabledGlobally(ExperimentalFlag.macros)) {
+ if (state.processedOpts.globalFeatures.macros.isEnabled) {
enableMacros = true;
forceEnableMacros = true;
@@ -324,8 +321,8 @@
() => isolatedExecutor.start(serializationMode);
break;
case 'aot':
- state.options.macroExecutorProvider =
- () => processExecutor.start(serializationMode);
+ state.options.macroExecutorProvider = () => processExecutor.start(
+ serializationMode, processExecutor.CommunicationChannel.socket);
break;
default:
throw ArgumentError('Unrecognized precompiled macro format $format');
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index a9fe7dd..2a303b8 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -521,7 +521,7 @@
}
if (nullSafety == null &&
- compilerOptions.isExperimentEnabled(ExperimentalFlag.nonNullable)) {
+ compilerOptions.globalFeatures.nonNullable.isEnabled) {
await autoDetectNullSafetyMode(_mainSource, compilerOptions);
}
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index e77ba6b..e228973 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -25,7 +25,6 @@
InvocationMode,
DiagnosticMessage,
DiagnosticMessageHandler,
- ExperimentalFlag,
FileSystem,
FileSystemEntity,
NnbdMode,
@@ -277,7 +276,7 @@
..verbosity = verbosity;
if (nullSafety == null &&
- compilerOptions.isExperimentEnabled(ExperimentalFlag.nonNullable)) {
+ compilerOptions.globalFeatures.nonNullable.isEnabled) {
await autoDetectNullSafetyMode(mainUri, compilerOptions);
}
diff --git a/tools/VERSION b/tools/VERSION
index 825b9b2..41c7365 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 261
+PRERELEASE 262
PRERELEASE_PATCH 0
\ No newline at end of file