Version 3.11.0-113.0.dev Merge 2692a110f03d1fa915ef2a259b948aa2dfd31958 into dev
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart index 3c8f88c..b88555e 100644 --- a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart +++ b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
@@ -2669,6 +2669,24 @@ void endConstDotShorthand(Token token) { listener?.beginConstDotShorthand(token); } + + @override + void beginPrimaryConstructorBody(Token token) { + listener?.beginPrimaryConstructorBody(token); + } + + @override + void endPrimaryConstructorBody( + Token beginToken, + Token? beginInitializers, + Token endToken, + ) { + listener?.endPrimaryConstructorBody( + beginToken, + beginInitializers, + endToken, + ); + } } class NullListener extends ForwardingListener {
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart index 7d51650..d5152c2 100644 --- a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart +++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -356,6 +356,21 @@ bool forExtensionType, ) {} + void beginPrimaryConstructorBody(Token token) {} + + // Handles the `this` body block for a primary constructor. Substructures: + /// - metadata + /// - initializers + /// - async marker + /// - body + void endPrimaryConstructorBody( + Token beginToken, + Token? beginInitializers, + Token endToken, + ) { + logEvent("endPrimaryConstructorBody"); + } + void beginCombinators(Token token) {} void endCombinators(int count) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart index 83aee6e..f765781 100644 --- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart +++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -3715,6 +3715,24 @@ return token; } + Token parsePrimaryConstructorBody(Token token) { + Token beginToken = token; + listener.beginPrimaryConstructorBody(token); + + Token? beforeInitializers = token; + token = parseInitializersOpt(beforeInitializers); + + token = parseAsyncModifierOpt(token); + token = parseFunctionBody( + token, + /* ofFunctionExpression = */ false, + /* allowAbstract = */ inPlainSync, + ); + + listener.endPrimaryConstructorBody(beginToken, beforeInitializers, token); + return token; + } + /// Parses an extension type declaration after /// /// 'extension' 'type' @@ -5361,6 +5379,22 @@ return token; } // Fall through to continue parsing `operator` as an identifier. + } else if (identical(value, 'this')) { + Token next2 = next.next!; + if (next2.isA(TokenType.COLON) || + next2.isA(TokenType.SEMICOLON) || + next2.isA(TokenType.OPEN_CURLY_BRACKET)) { + if (!_isDeclaringConstructorsFeatureEnabled) { + reportExperimentNotEnabled( + ExperimentalFlag.declaringConstructors, + next, + next, + ); + } + token = parsePrimaryConstructorBody(next); + listener.endMember(); + return token; + } } else if (!next.isIdentifier || (identical(value, 'typedef') && token == beforeStart &&
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all_in_workspace.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all_in_workspace.dart index d757902..3c46fef 100644 --- a/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all_in_workspace.dart +++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all_in_workspace.dart
@@ -58,29 +58,35 @@ var workspace = DartChangeWorkspace(await server.currentSessions); var processor = BulkFixProcessor(server.instrumentationService, workspace); - var result = await processor.fixErrors( - server.contextManager.analysisContexts, - ); - var errorMessage = result.errorMessage; - if (errorMessage != null) { - return error(ErrorCodes.RequestFailed, errorMessage); - } + progress.begin('Computing fixes…'); + try { + var result = await processor.fixErrors( + server.contextManager.analysisContexts, + ); - var changeBuilder = result.builder!; - var change = changeBuilder.sourceChange; - if (change.edits.isEmpty) { - return success(null); - } + var errorMessage = result.errorMessage; + if (errorMessage != null) { + return error(ErrorCodes.RequestFailed, errorMessage); + } - var edit = createWorkspaceEdit( - server, - clientCapabilities, - change, - annotateChanges: requireConfirmation - ? ChangeAnnotations.requireConfirmation - : ChangeAnnotations.include, - ); - return sendWorkspaceEditToClient(edit); + var changeBuilder = result.builder!; + var change = changeBuilder.sourceChange; + if (change.edits.isEmpty) { + return success(null); + } + + var edit = createWorkspaceEdit( + server, + clientCapabilities, + change, + annotateChanges: requireConfirmation + ? ChangeAnnotations.requireConfirmation + : ChangeAnnotations.include, + ); + return sendWorkspaceEditToClient(edit); + } finally { + progress.end(); + } } }
diff --git a/pkg/analysis_server/test/lsp/commands/fix_all_in_workspace_test.dart b/pkg/analysis_server/test/lsp/commands/fix_all_in_workspace_test.dart index 2e49cb3..b3950d1 100644 --- a/pkg/analysis_server/test/lsp/commands/fix_all_in_workspace_test.dart +++ b/pkg/analysis_server/test/lsp/commands/fix_all_in_workspace_test.dart
@@ -10,6 +10,7 @@ import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../../tool/lsp_spec/matchers.dart'; +import '../request_helpers_mixin.dart'; import '../server_abstract.dart'; void main() { @@ -20,7 +21,8 @@ } abstract class AbstractFixAllInWorkspaceTest - extends AbstractLspAnalysisServerTest { + extends AbstractLspAnalysisServerTest + with LspProgressNotificationsMixin { String get commandId; String get commandName; bool get expectRequiresConfirmation; @@ -229,6 +231,28 @@ '''); } + Future<void> test_progressNotifications_supported() async { + // Advertise that we (the client) support progress. + setWorkDoneProgressSupport(); + + // Expect (during the test) a progress token to be created, started, ended. + expect(progressUpdates, emitsInOrder(['CREATE', 'BEGIN', 'END'])); + + await initialize(); + await executeCommand(Command(command: commandId, title: 'UNUSED')); + } + + Future<void> test_progressNotifications_unsupported() async { + // Advertise that we do not support progress. + setWorkDoneProgressSupport(false); + + // Expect no progress updates at all. + expect(progressUpdates, neverEmits(anything)); + + await initialize(); + await executeCommand(Command(command: commandId, title: 'UNUSED')); + } + Future<void> test_serverAdvertisesCommand() async { await initialize(); expect(
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart index c83079f..4cb4848 100644 --- a/pkg/analysis_server/test/lsp/server_abstract.dart +++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -771,9 +771,9 @@ setTextDocumentDynamicRegistration('synchronization'); } - void setWorkDoneProgressSupport() { + void setWorkDoneProgressSupport([bool supported = true]) { windowCapabilities = extendWindowCapabilities(windowCapabilities, { - 'workDoneProgress': true, + 'workDoneProgress': supported, }); } @@ -826,7 +826,7 @@ /// initialize. ServerCapabilities? _serverCapabilities; - final validProgressTokens = <ProgressToken>{}; + final _validProgressTokens = <ProgressToken>{}; /// Default initialization options to be used if [initialize] is not provided /// options explicitly. @@ -1574,7 +1574,7 @@ request.params as Map<String, Object?>, ); if (params.token != clientProvidedTestWorkDoneToken && - !validProgressTokens.contains(params.token)) { + !_validProgressTokens.contains(params.token)) { throw Exception( 'Server sent a progress notification for a token ' 'that has not been created: ${params.token}', @@ -1582,7 +1582,7 @@ } if (WorkDoneProgressEnd.canParse(params.value, nullLspJsonReporter)) { - validProgressTokens.remove(params.token); + _validProgressTokens.remove(params.token); } if (params.token == analyzingProgressToken) { @@ -1605,10 +1605,10 @@ var params = WorkDoneProgressCreateParams.fromJson( request.params as Map<String, Object?>, ); - if (validProgressTokens.contains(params.token)) { + if (_validProgressTokens.contains(params.token)) { throw Exception('Server tried to create already-active progress token'); } - validProgressTokens.add(params.token); + _validProgressTokens.add(params.token); } /// Checks whether a notification is likely an error from the server (for
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart index a3ad607..7a43d54 100644 --- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart +++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -153,7 +153,7 @@ ) ..addFlag('help', abbr: 'h', help: 'Print this help message.') ..addOption( - CompletionMetricsOptions.OVERLAY, + CompletionMetricsOptions.overlayOption, allowed: [ OverlayMode.none.flag, OverlayMode.removeRestOfFile.flag, @@ -167,7 +167,7 @@ 'complete at the start of the token without modifying the file.', ) ..addOption( - CompletionMetricsOptions.PREFIX_LENGTH, + CompletionMetricsOptions.prefixLengthOption, defaultsTo: '0', help: 'The number of characters to include in the prefix. Each ' @@ -175,14 +175,14 @@ 'start of the token being completed.', ) ..addFlag( - CompletionMetricsQualityOptions.PRINT_MISSED_COMPLETION_DETAILS, + CompletionMetricsQualityOptions._printMissedCompletionDetails, help: 'Print detailed information every time a completion request fails ' 'to produce a suggestions matching the expected suggestion.', negatable: false, ) ..addFlag( - CompletionMetricsQualityOptions.PRINT_MISSED_COMPLETION_SUMMARY, + CompletionMetricsQualityOptions._printMissedCompletionSummary, help: 'Print summary information about the times that a completion ' 'request failed to produce a suggestions matching the expected ' @@ -190,7 +190,7 @@ negatable: false, ) ..addFlag( - CompletionMetricsQualityOptions.PRINT_MISSING_INFORMATION, + CompletionMetricsQualityOptions._printMissingInformation, help: 'Print information about places where no completion location was ' 'computed and about information that is missing in the completion ' @@ -198,7 +198,7 @@ negatable: false, ) ..addFlag( - CompletionMetricsQualityOptions.PRINT_MRR_BY_LOCATION, + CompletionMetricsQualityOptions._printMrrByLocation, help: 'Print information about the mrr score achieved at each completion ' 'location. This can help focus efforts to improve the overall ' @@ -207,7 +207,7 @@ negatable: false, ) ..addFlag( - CompletionMetricsQualityOptions.PRINT_SHADOWED_COMPLETION_DETAILS, + CompletionMetricsQualityOptions._printShadowedCompletionDetails, help: 'Print detailed information every time a completion request ' 'produces a suggestion whose name matches the expected suggestion ' @@ -215,14 +215,14 @@ negatable: false, ) ..addFlag( - CompletionMetricsOptions.PRINT_SLOWEST_RESULTS, + CompletionMetricsOptions.printSlowestResultsFlag, help: 'Print information about the completion requests that were the ' 'slowest to return suggestions.', negatable: false, ) ..addFlag( - CompletionMetricsQualityOptions.PRINT_WORST_RESULTS, + CompletionMetricsQualityOptions._printWorstResults, help: 'Print information about the completion requests that had the ' 'worst mrr scores.', @@ -691,34 +691,34 @@ /// A flag that causes detailed information to be printed every time a /// completion request fails to produce a suggestions matching the expected /// suggestion. - static const String PRINT_MISSED_COMPLETION_DETAILS = + static const String _printMissedCompletionDetails = 'print-missed-completion-details'; /// A flag that causes summary information to be printed about the times that /// a completion request failed to produce a suggestions matching the expected /// suggestion. - static const String PRINT_MISSED_COMPLETION_SUMMARY = + static const String _printMissedCompletionSummary = 'print-missed-completion-summary'; /// A flag that causes information to be printed about places where no /// completion location was computed and about information that's missing in /// the completion tables. - static const String PRINT_MISSING_INFORMATION = 'print-missing-information'; + static const String _printMissingInformation = 'print-missing-information'; /// A flag that causes information to be printed about the mrr score achieved /// at each completion location. - static const String PRINT_MRR_BY_LOCATION = 'print-mrr-by-location'; + static const String _printMrrByLocation = 'print-mrr-by-location'; /// A flag that causes detailed information to be printed every time a /// completion request produce a suggestions whose name matches the expected /// suggestion but that is referencing a different element (one that's /// shadowed by the correct element). - static const String PRINT_SHADOWED_COMPLETION_DETAILS = + static const String _printShadowedCompletionDetails = 'print-shadowed-completion-details'; /// A flag that causes information to be printed about the completion requests /// that had the worst mrr scores. - static const String PRINT_WORST_RESULTS = 'print-worst-results'; + static const String _printWorstResults = 'print-worst-results'; /// A flag indicating whether information should be printed every time a /// completion request fails to produce a suggestions matching the expected @@ -749,15 +749,18 @@ final bool printWorstResults; CompletionMetricsQualityOptions(super.results) - : printMissedCompletionDetails = - results[PRINT_MISSED_COMPLETION_DETAILS] as bool, - printMissedCompletionSummary = - results[PRINT_MISSED_COMPLETION_SUMMARY] as bool, - printMissingInformation = results[PRINT_MISSING_INFORMATION] as bool, - printMrrByLocation = results[PRINT_MRR_BY_LOCATION] as bool, - printShadowedCompletionDetails = - results[PRINT_SHADOWED_COMPLETION_DETAILS] as bool, - printWorstResults = results[PRINT_WORST_RESULTS] as bool; + : printMissedCompletionDetails = results.flag( + _printMissedCompletionDetails, + ), + printMissedCompletionSummary = results.flag( + _printMissedCompletionSummary, + ), + printMissingInformation = results.flag(_printMissingInformation), + printMrrByLocation = results.flag(_printMrrByLocation), + printShadowedCompletionDetails = results.flag( + _printShadowedCompletionDetails, + ), + printWorstResults = results.flag(_printWorstResults); } /// This is the main metrics computer class for code completions. After the
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics_base.dart b/pkg/analysis_server/tool/code_completion/completion_metrics_base.dart index 9731e76..6797729 100644 --- a/pkg/analysis_server/tool/code_completion/completion_metrics_base.dart +++ b/pkg/analysis_server/tool/code_completion/completion_metrics_base.dart
@@ -190,17 +190,17 @@ /// The options specified on the command-line. class CompletionMetricsOptions { /// An option to control whether and how overlays should be produced. - static const String OVERLAY = 'overlay'; + static const String overlayOption = 'overlay'; /// An option controlling how long of a prefix should be used. /// /// This affects the offset of the completion request, and how much content is /// removed in each of the overlay modes. - static const String PREFIX_LENGTH = 'prefix-length'; + static const String prefixLengthOption = 'prefix-length'; /// A flag that causes information to be printed about the completion requests /// that were the slowest to return suggestions. - static const String PRINT_SLOWEST_RESULTS = 'print-slowest-results'; + static const String printSlowestResultsFlag = 'print-slowest-results'; /// The overlay mode that should be used. final OverlayMode overlay; @@ -212,9 +212,9 @@ final bool printSlowestResults; CompletionMetricsOptions(ArgResults results) - : overlay = OverlayMode.parseFlag(results[OVERLAY] as String), - prefixLength = int.parse(results[PREFIX_LENGTH] as String), - printSlowestResults = results[PRINT_SLOWEST_RESULTS] as bool; + : overlay = OverlayMode.parseFlag(results.option(overlayOption)!), + prefixLength = int.parse(results.option(prefixLengthOption)!), + printSlowestResults = results.flag(printSlowestResultsFlag); } enum OverlayMode {
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics_client.dart b/pkg/analysis_server/tool/code_completion/completion_metrics_client.dart index a2f316f..5d7c32e 100644 --- a/pkg/analysis_server/tool/code_completion/completion_metrics_client.dart +++ b/pkg/analysis_server/tool/code_completion/completion_metrics_client.dart
@@ -67,7 +67,7 @@ ) ..addFlag('help', abbr: 'h', help: 'Print this help message.') ..addOption( - CompletionMetricsOptions.OVERLAY, + CompletionMetricsOptions.overlayOption, allowed: [ OverlayMode.none.flag, OverlayMode.removeRestOfFile.flag, @@ -81,7 +81,7 @@ 'complete at the start of the token without modifying the file.', ) ..addOption( - CompletionMetricsOptions.PREFIX_LENGTH, + CompletionMetricsOptions.prefixLengthOption, defaultsTo: '0', help: 'The number of characters to include in the prefix. Each ' @@ -89,7 +89,7 @@ 'start of the token being completed.', ) ..addFlag( - CompletionMetricsOptions.PRINT_SLOWEST_RESULTS, + CompletionMetricsOptions.printSlowestResultsFlag, help: 'Print information about the completion requests that were the ' 'slowest to return suggestions.',
diff --git a/pkg/analysis_server/tool/code_completion/visitors.dart b/pkg/analysis_server/tool/code_completion/visitors.dart index 986514a..67309c5 100644 --- a/pkg/analysis_server/tool/code_completion/visitors.dart +++ b/pkg/analysis_server/tool/code_completion/visitors.dart
@@ -130,19 +130,19 @@ } class ExpectedCompletionsVisitor extends RecursiveAstVisitor<void> { - static const ASYNC_STAR = 'async*'; + static const _asyncStar = 'async*'; - static const DEFAULT_COLON = 'default:'; + static const _defaultColon = 'default:'; - static const DEFERRED_AS = 'deferred as'; + static const _deferredAs = 'deferred as'; - static const EXPORT_STATEMENT = "export '';"; + static const _exportStatement = "export '';"; - static const IMPORT_STATEMENT = "import '';"; + static const _importStatement = "import '';"; - static const PART_STATEMENT = "part '';"; - static const SYNC_STAR = 'sync*'; - static const YIELD_STAR = 'yield*'; + static const _partStatement = "part '';"; + static const _syncStar = 'sync*'; + static const _yieldStar = 'yield*'; /// The result of resolving the file being visited. final ResolvedUnitResult result; @@ -204,7 +204,7 @@ entity, lineNumber, columnNumber, - ASYNC_STAR, + _asyncStar, kind, elementKind, ), @@ -216,7 +216,7 @@ entity, lineNumber, columnNumber, - DEFAULT_COLON, + _defaultColon, kind, elementKind, ), @@ -228,7 +228,7 @@ entity, lineNumber, columnNumber, - DEFERRED_AS, + _deferredAs, kind, elementKind, ), @@ -240,7 +240,7 @@ entity, lineNumber, columnNumber, - EXPORT_STATEMENT, + _exportStatement, kind, elementKind, ), @@ -252,7 +252,7 @@ entity, lineNumber, columnNumber, - IMPORT_STATEMENT, + _importStatement, kind, elementKind, ), @@ -264,7 +264,7 @@ entity, lineNumber, columnNumber, - PART_STATEMENT, + _partStatement, kind, elementKind, ), @@ -276,7 +276,7 @@ entity, lineNumber, columnNumber, - SYNC_STAR, + _syncStar, kind, elementKind, ), @@ -288,7 +288,7 @@ entity, lineNumber, columnNumber, - YIELD_STAR, + _yieldStar, kind, elementKind, ),
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart index b02d2f5..16de183 100644 --- a/pkg/analyzer/lib/src/fasta/ast_builder.dart +++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -618,6 +618,11 @@ } @override + void beginPrimaryConstructorBody(Token beginToken) { + debugEvent("PrimaryConstructorBody"); + } + + @override void beginSwitchCaseWhenClause(Token when) { debugEvent("PatternSwitchCaseGuard"); } @@ -3169,6 +3174,23 @@ } @override + void endPrimaryConstructorBody( + Token beginToken, + Token? beginInitializers, + Token endToken, + ) { + // TODO(declaring-constructors): Implement primary constructor body. + // ignore: unused_local_variable + var bodyObject = pop(); + // ignore: unused_local_variable + var initializers = (pop() as List<ConstructorInitializerImpl>?) ?? const []; + // ignore: unused_local_variable + var separator = pop() as Token?; + // ignore: unused_local_variable + var metadata = pop() as List<AnnotationImpl>?; + } + + @override void endRecordLiteral(Token leftParenthesis, int count, Token? constKeyword) { debugEvent("RecordLiteral");
diff --git a/pkg/analyzer_testing/CHANGELOG.md b/pkg/analyzer_testing/CHANGELOG.md index fa6a0cf..0384c0b 100644 --- a/pkg/analyzer_testing/CHANGELOG.md +++ b/pkg/analyzer_testing/CHANGELOG.md
@@ -4,6 +4,8 @@ analysis options file used in testing specifies a `true` value for `propagate-linter-exceptions`. This ensures that when tests are run, exceptions that occur while processing lint rules will cause the test to fail. +- Deprecate `PubPackageResolutionTest.addKernelPackageDep`. A mock kernel + package can still be written with `PubPackageResolutionTest.newPackage`. ## 0.1.7
diff --git a/pkg/analyzer_testing/lib/src/analysis_rule/pub_package_resolution.dart b/pkg/analyzer_testing/lib/src/analysis_rule/pub_package_resolution.dart index c1bddc2..9318502 100644 --- a/pkg/analyzer_testing/lib/src/analysis_rule/pub_package_resolution.dart +++ b/pkg/analyzer_testing/lib/src/analysis_rule/pub_package_resolution.dart
@@ -235,6 +235,10 @@ /// Adds the 'kernel' package as a dependency to the package-under-test. /// /// This allows various `package:kernel/` imports to resolve. + @Deprecated( + 'The mock kernel package is deprecated; use ' + '`PubPackageResolutionTest.newPackage` to make a custom mock', + ) bool get addKernelPackageDep => false; /// Adds the 'meta' package as a dependency to the package-under-test.
diff --git a/pkg/dart2wasm/lib/closures.dart b/pkg/dart2wasm/lib/closures.dart index 5f2aaef..f01e77c 100644 --- a/pkg/dart2wasm/lib/closures.dart +++ b/pkg/dart2wasm/lib/closures.dart
@@ -59,10 +59,12 @@ /// an entry for each (non-empty) combination of argument names that closures /// with this layout can be called with. class ClosureRepresentation { - /// The struct field index in the vtable struct at which the function - /// entries start. + /// The number of type arguments. final int typeCount; + /// The maximum number of positional parameters. + final int maxPositionalCount; + /// The Wasm struct type for the vtable. final w.StructType vtableStruct; @@ -129,6 +131,7 @@ ClosureRepresentation( Translator translator, this.typeCount, + this.maxPositionalCount, this.vtableStruct, this.closureStruct, this._indexOfCombination, @@ -136,6 +139,8 @@ bool get isGeneric => typeCount > 0; + bool get hasNamed => _indexOfCombination != null; + /// Where the vtable entries for function calls start in the vtable struct. int get vtableBaseIndex => isGeneric ? ClosureLayouter.vtableBaseIndexGeneric @@ -216,6 +221,10 @@ // The member currently being visited while collecting function signatures. Member? currentMember; + /// Whether the kernel [Component] uses `Function.apply` and possibly passes + /// non-empty map for named arguments. + late bool usesFunctionApplyWithNamedArguments; + // For non-generic closures. The entries are: // 0: Dynamic call entry // 1-...: Entries for calling the closure @@ -400,8 +409,9 @@ (translator.component.metadata["vm.procedure-attributes.metadata"] as ProcedureAttributesMetadataRepository) .mapping; - void collect() { + usesFunctionApplyWithNamedArguments = false; + // Dynamic module enabled builds use dynamic call entry points for all // closure invocations so we don't need to generate any representation // info. @@ -478,12 +488,12 @@ ClosureRepresentation _createRepresentation( int typeCount, - int positionalCount, + int maxPositionalCount, List<String> names, ClosureRepresentation? parent, Map<NameCombination, int>? indexOfCombination, Iterable<int> paramCounts) { - List<String> nameTags = ["$typeCount", "$positionalCount", ...names]; + List<String> nameTags = ["$typeCount", "$maxPositionalCount", ...names]; String vtableName = ["#Vtable", ...nameTags].join("-"); String closureName = ["#Closure", ...nameTags].join("-"); w.StructType parentVtableStruct = parent?.vtableStruct ?? @@ -508,7 +518,7 @@ if (typeCount > 0) { // Add or set vtable field for the instantiation function. instantiatedRepresentation = - getClosureRepresentation(0, positionalCount, names)!; + getClosureRepresentation(0, maxPositionalCount, names)!; w.RefType inputType = w.RefType.def(closureBaseStruct, nullable: false); w.RefType outputType = w.RefType.def( instantiatedRepresentation.closureStruct, @@ -564,6 +574,7 @@ ClosureRepresentation representation = ClosureRepresentation( translator, typeCount, + maxPositionalCount, vtableStruct, closureStruct, indexOfCombination, @@ -618,7 +629,7 @@ vtableBaseIndexNonGeneric + instantiationTrampolines.length, vtableStruct, vtableBaseIndexGeneric + - (positionalCount + 1) + + (maxPositionalCount + 1) + genericIndex) : translator .getDummyValuesCollectorForModule(module) @@ -1009,7 +1020,26 @@ } @override + void visitStaticInvocation(StaticInvocation node) { + super.visitStaticInvocation(node); + if (node.target == translator.functionApply) { + // Function.apply(function, positionalArguments, [namedArguments]) + if (node.arguments.positional.length > 2) { + usesFunctionApplyWithNamedArguments = true; + } + } + } + + @override + void visitStaticTearOff(StaticTearOff node) { + visitStaticTearOffConstantReference(StaticTearOffConstant(node.target)); + } + + @override void visitStaticTearOffConstantReference(StaticTearOffConstant constant) { + if (constant.target == translator.functionApply) { + usesFunctionApplyWithNamedArguments = true; + } _visitFunctionNode(constant.function); } @@ -1028,9 +1058,23 @@ @override void visitDynamicInvocation(DynamicInvocation node) { - if (node.name.text == "call") { - _visitFunctionInvocation(node.arguments); - } + // NOTE: One may have two different kinds of calls here: + // ``` + // dynamic x; + // x(namedArg: 1); + // x.foo(namedArg: 1); + // ``` + // It may appear as we only have to handle the first case, namely + // `node.name.text == "call"`, but the second case can also be a + // dynamic closure callsite via call-through-field: + // ``` + // class Foo { + // void Function({int? namedArg}) get foo => ...; + // } + // ``` + // then a `x.foo(namedArg: 1)` will be executed at runtime via + // `var tmp = x.foo; tmp(namedArg: 1)`. + _visitFunctionInvocation(node.arguments); super.visitDynamicInvocation(node); } }
diff --git a/pkg/dart2wasm/lib/constants.dart b/pkg/dart2wasm/lib/constants.dart index fed4b73..89de802 100644 --- a/pkg/dart2wasm/lib/constants.dart +++ b/pkg/dart2wasm/lib/constants.dart
@@ -1180,12 +1180,12 @@ final b = function.body; - final closureLocal = function.locals[0]; final typeArgsListLocal = function.locals[1]; // empty final posArgsListLocal = function.locals[2]; final namedArgsListLocal = function.locals[3]; - b.local_get(closureLocal); + constants.instantiateConstant( + b, tearOffConstantInfo.constant, translator.topTypeNonNullable); constants.instantiateConstant( b, typeArgsArrayConstantInfo.constant, typeArgsListLocal.type); b.local_get(posArgsListLocal);
diff --git a/pkg/dart2wasm/lib/dispatch_table.dart b/pkg/dart2wasm/lib/dispatch_table.dart index 9e34a46..2ef07c2 100644 --- a/pkg/dart2wasm/lib/dispatch_table.dart +++ b/pkg/dart2wasm/lib/dispatch_table.dart
@@ -852,12 +852,17 @@ fun = wrappedDynamicSubmoduleImports[fun] ??= _wrapDynamicSubmoduleFunction(target, fun); } - _definedWasmTable.setElement(i, fun); + _definedWasmTable.moduleBuilder.elements + .activeFunctionSegmentBuilderFor(_definedWasmTable) + .setFunctionAt(i, fun); } else { // This will generate the imported table if it doesn't already // exist. - (getWasmTable(targetModuleBuilder) as w.ImportedTable) - .setElements[i] = fun; + final importedTable = + getWasmTable(targetModuleBuilder) as w.ImportedTable; + targetModuleBuilder.elements + .activeFunctionSegmentBuilderFor(importedTable) + .setFunctionAt(i, fun); } } }
diff --git a/pkg/dart2wasm/lib/dynamic_modules.dart b/pkg/dart2wasm/lib/dynamic_modules.dart index be0e2ac..0a9e37c 100644 --- a/pkg/dart2wasm/lib/dynamic_modules.dart +++ b/pkg/dart2wasm/lib/dynamic_modules.dart
@@ -677,7 +677,8 @@ overridableFunctions.putIfAbsent(index, () { if (!isSubmodule) { final mainFunction = translator.mainModule.functions.define(type, name); - translator.mainModule.functions.declare(mainFunction); + translator.mainModule.elements.declarativeSegmentBuilder + .declare(mainFunction); buildMain(mainFunction); return mainFunction; } @@ -685,7 +686,7 @@ if (skipSubmodule) return null; final submoduleFunction = submodule.functions.define(type, name); - submodule.functions.declare(submoduleFunction); + submodule.elements.declarativeSegmentBuilder.declare(submoduleFunction); buildSubmodule(submoduleFunction); return submoduleFunction; }); @@ -1067,7 +1068,7 @@ // Declare the function so it can be used as a ref_func in a constant // context. - b.moduleBuilder.functions.declare(checker); + b.moduleBuilder.elements.declarativeSegmentBuilder.declare(checker); // Invoke the 'canonicalize' function with the value and checker. b.local_get(valueLocal); @@ -1101,7 +1102,7 @@ // Declare the function so it can be used as a ref_func in a constant // context. - b.moduleBuilder.functions.declare(checker); + b.moduleBuilder.elements.declarativeSegmentBuilder.declare(checker); // Invoke the canonicalizer function with the value and checker. b.local_get(valueLocal);
diff --git a/pkg/dart2wasm/lib/intrinsics.dart b/pkg/dart2wasm/lib/intrinsics.dart index 3736abe..89740b6 100644 --- a/pkg/dart2wasm/lib/intrinsics.dart +++ b/pkg/dart2wasm/lib/intrinsics.dart
@@ -2021,7 +2021,7 @@ b.end(); b.local_set(posArgsLocal); - // Convert named argument map to list, to be passed to shape and type + // Convert named argument map to array, to be passed to shape and type // checkers and the dynamic call entry. final namedArgsListLocal = b.addLocal(translator.nullableObjectArrayTypeRef);
diff --git a/pkg/dart2wasm/lib/kernel_nodes.dart b/pkg/dart2wasm/lib/kernel_nodes.dart index e9455ea..2bd4566 100644 --- a/pkg/dart2wasm/lib/kernel_nodes.dart +++ b/pkg/dart2wasm/lib/kernel_nodes.dart
@@ -276,6 +276,8 @@ index.getTopLevelProcedure("dart:core", "_runtimeTypeEquals"); late final Procedure runtimeTypeHashCode = index.getTopLevelProcedure("dart:core", "_runtimeTypeHashCode"); + late final Procedure? functionApply = + index.tryGetProcedure('dart:core', 'Function', 'apply'); // dart:core invocation/exception procedures late final Procedure invocationGetterFactory =
diff --git a/pkg/dart2wasm/lib/static_dispatch_table.dart b/pkg/dart2wasm/lib/static_dispatch_table.dart index 6c78019..59f53a1 100644 --- a/pkg/dart2wasm/lib/static_dispatch_table.dart +++ b/pkg/dart2wasm/lib/static_dispatch_table.dart
@@ -74,11 +74,15 @@ _table.forEach((fun, index) { final targetModule = translator.moduleToBuilder[fun.enclosingModule]!; if (translator.isMainModule(targetModule)) { - _definedWasmTable.setElement(index, fun); + _definedWasmTable.moduleBuilder.elements + .activeFunctionSegmentBuilderFor(_definedWasmTable) + .setFunctionAt(index, fun); } else { // This will generate the imported table if it doesn't already exist. - (getWasmTable(targetModule) as w.ImportedTable).setElements[index] = - fun; + final importedTable = getWasmTable(targetModule) as w.ImportedTable; + targetModule.elements + .activeFunctionSegmentBuilderFor(importedTable) + .setFunctionAt(index, fun); } });
diff --git a/pkg/dart2wasm/lib/translator.dart b/pkg/dart2wasm/lib/translator.dart index 73e708e..8bd8e44 100644 --- a/pkg/dart2wasm/lib/translator.dart +++ b/pkg/dart2wasm/lib/translator.dart
@@ -1116,6 +1116,33 @@ }); } + final _closureArgumentsDispatchers = + <w.ModuleBuilder, Map<ClosureRepresentation, w.BaseFunction>>{}; + w.BaseFunction getClosureArgumentsDispatcher( + w.ModuleBuilder module, ClosureRepresentation r) { + // We can only unpack (type, positional, named) argument arrays and forward + // to specific vtable entries if we have closed-world knowledge of all used + // name combinations. + assert(!dynamicModuleSupportEnabled && + !closureLayouter.usesFunctionApplyWithNamedArguments); + + final moduleCache = _closureArgumentsDispatchers[module] ??= {}; + return moduleCache.putIfAbsent(r, () { + final representationString = '${r.typeCount}-' + '${r.maxPositionalCount}' + '${r.hasNamed ? '-' : ''}' + '${r.nameCombinations.join('-')}'; + final function = module.functions.define( + dynamicCallVtableEntryFunctionType, + "closure arguments dispatcher representation=$representationString"); + compilationQueue.add(CompilationTask( + function, + _ClosureArgumentsToVtableEntryDispatcherGenerator( + this, r, function))); + return function; + }); + } + ClosureImplementation getClosure( FunctionNode functionNode, w.BaseFunction target, @@ -1249,7 +1276,26 @@ w.RefType.def(representation.vtableStruct, nullable: false), mutable: false)); final ib = vtable.initializer; - final dynamicCallEntry = makeDynamicCallEntry(); + + // NOTE: In dynamic modules we do not have closed world knowledge of closure + // definitions and callsites, so the dynamic call entry cannot dispatch to + // representation specific vtable entries. + // + // Even if we have closed world knowledge, if anywhere in the program + // `Function.apply` is used with named arguments, then we don't know which + // name-combinations may be used and we want to avoid creating vtable + // entries for all possible name combinations. So also in this situation we + // cannot dispatch to representation-specific vtable entries. + // + // If none of the two cases above apply, we can make the dynamic call entry + // be a shared stub that dispatches (based on arguments) to the right + // representation specific vtable entry. This saves code size as we don't + // have 1 dynamic call entry function per closure but rather 1 per closure + // shape / representation. + final dynamicCallEntry = (dynamicModuleSupportEnabled || + closureLayouter.usesFunctionApplyWithNamedArguments) + ? makeDynamicCallEntry() + : getClosureArgumentsDispatcher(closureModule, representation); ib.ref_func(dynamicCallEntry); if (representation.isGeneric) { ib.ref_func(representation @@ -2336,6 +2382,281 @@ } } +class _ClosureArgumentsToVtableEntryDispatcherGenerator + implements CodeGenerator { + final Translator translator; + final ClosureRepresentation representation; + final w.FunctionBuilder function; + + _ClosureArgumentsToVtableEntryDispatcherGenerator( + this.translator, this.representation, this.function); + + @override + void generate(w.InstructionsBuilder b, List<w.Local> paramLocals, + w.Label? returnLabel) { + assert(returnLabel == null); + + final b = function.body; + + final closureLocal = function.locals[0]; + final typeArgsLocal = function.locals[1]; + final posArgsLocal = function.locals[2]; + final namedArgsLocal = function.locals[3]; + + assert(typeArgsLocal.type == translator.typeArrayTypeRef); + assert(posArgsLocal.type == translator.nullableObjectArrayTypeRef); + assert(namedArgsLocal.type == translator.nullableObjectArrayTypeRef); + + _verifyAssumptions( + b, closureLocal, typeArgsLocal, posArgsLocal, namedArgsLocal); + + final vtableStruct = representation.vtableStruct; + + // Downcast closure to this representation's closure type & get + // representation-specific vtable. + b.comment('Obtaining representation-specific vtable'); + b.local_get(closureLocal); + b.ref_cast(w.RefType(representation.closureStruct, nullable: false)); + b.struct_get(representation.closureStruct, FieldIndex.closureVtable); + final vtableVar = b.addLocal(w.RefType(vtableStruct, nullable: false)); + b.local_set(vtableVar); + + final typeStack = <w.ValueType>[]; + + // Load closure context. + b.comment('Loading closure.context'); + b.local_get(closureLocal); + b.struct_get(translator.closureInfo.struct, FieldIndex.closureContext); + typeStack.add(w.RefType.struct(nullable: false)); + + // Load required type arguments. + for (int i = 0; i < representation.typeCount; ++i) { + b.comment('Loading type argument $i'); + b.local_get(typeArgsLocal); + b.i32_const(i); + b.array_get(translator.typeArrayType); + typeStack.add(translator.translateType(translator.typeType)); + } + + // Load optional parameters. + if (representation.hasNamed) { + b.comment('Handle optional named parameters'); + _handleOptionalNamedCase(b, closureLocal, typeArgsLocal, posArgsLocal, + namedArgsLocal, vtableVar, vtableStruct, typeStack); + } else { + b.comment('Handle optional positional parameters'); + _handleOptionalPositionalCase(b, closureLocal, typeArgsLocal, + posArgsLocal, namedArgsLocal, vtableVar, vtableStruct, typeStack); + } + + b.end(); // end function + } + + void _handleOptionalPositionalCase( + w.InstructionsBuilder b, + w.Local closureLocal, + w.Local typeArgsLocal, + w.Local posArgsLocal, + w.Local namedArgsLocal, + w.Local vtableVar, + w.StructType vtableStruct, + List<w.ValueType> typeStack, + ) { + // Possibly variable number of positionals. + for (int i = 0; i <= representation.maxPositionalCount; ++i) { + b.comment('Check whether all positionals are loaded'); + b.local_get(posArgsLocal); + b.array_len(); + b.i32_const(i); + b.i32_eq(); + b.if_(typeStack, typeStack); + b.comment('All positionals loaded, calling corresponding vtable entry'); + b.local_get(vtableVar); + final index = representation.vtableBaseIndex + i; + b.struct_get(vtableStruct, index); + b.call_ref((vtableStruct.fields[index].type.unpacked as w.RefType) + .heapType as w.FunctionType); + b.return_(); + b.end(); + + if (i <= representation.maxPositionalCount) { + // Otherwise load more arguments. + b.comment('Loading positional $i (optional)'); + b.local_get(posArgsLocal); + b.i32_const(i); + b.array_get(translator.nullableObjectArrayType); + typeStack.add(translator.topType); + } + } + + b.unreachable(); + } + + void _handleOptionalNamedCase( + w.InstructionsBuilder b, + w.Local closureLocal, + w.Local typeArgsLocal, + w.Local posArgsLocal, + w.Local namedArgsLocal, + w.Local vtableVar, + w.StructType vtableStruct, + List<w.ValueType> typeStack, + ) { + // All positionals are required, so load them. + for (int i = 0; i < representation.maxPositionalCount; ++i) { + b.comment('Loading positional $i (required)'); + b.local_get(posArgsLocal); + b.i32_const(i); + b.array_get(translator.nullableObjectArrayType); + typeStack.add(translator.topType); + } + + // Check for each name whether it's there or not. + final allCombinations = representation.nameCombinations.toList(); + final sortedNames = allCombinations.expand((nc) => nc.names).toList() + ..sort(); + final nameIndexVar = b.addLocal(w.NumType.i32); + + void codeGenNamedHandling( + List<String> currentNames, List<w.ValueType> typeStack, int nameIndex) { + final currentCombination = NameCombination(currentNames); + final isValidCombination = currentNames.isEmpty || + allCombinations.any((nc) => nc.compareTo(currentCombination) == 0); + + if (isValidCombination) { + b.comment('Check whether all named are loaded'); + b.local_get(namedArgsLocal); + b.array_len(); + b.local_get(nameIndexVar); + b.i32_eq(); + b.if_(typeStack, typeStack); + b.comment('All named loaded, calling corresponding vtable entry'); + b.comment('(passed named arguments: ${currentNames.join('-')})'); + final index = representation.fieldIndexForSignature( + representation.maxPositionalCount, currentNames); + b.local_get(vtableVar); + b.struct_get(vtableStruct, index); + b.call_ref((vtableStruct.fields[index].type.unpacked as w.RefType) + .heapType as w.FunctionType); + b.return_(); + b.end(); + } else { + if (util.compilerAssertsEnabled) { + b.comment('Check there are more names passed by the caller,'); + b.comment('because the currently processed name set'); + b.comment('(which are: ${currentNames.join('-')}) does not'); + b.comment(' correspond to a valid name combination.'); + b.local_get(namedArgsLocal); + b.array_len(); + b.local_get(nameIndexVar); + b.i32_eq(); + b.if_(); + b.comment('Unsupported name combination.'); + b.comment('Maybe bug in closure representation building'); + b.unreachable(); + b.end(); + } + } + + if (nameIndex == sortedNames.length) { + b.comment('More names passed then expected.'); + b.unreachable(); + return; + } + + final newName = sortedNames[nameIndex]; + final symbol = translator.symbols.symbolForNamedParameter(newName); + + b.comment('Load next name and see if it corresponds to "$newName"'); + b.local_get(namedArgsLocal); + b.local_get(nameIndexVar); + b.array_get(translator.nullableObjectArrayType); + translator.constants.instantiateConstant(b, symbol, translator.topType); + b.ref_eq(); + + b.if_(typeStack, typeStack); + { + b.comment('Name "$newName" was provided by caller. Loading its value.'); + b.local_get(namedArgsLocal); + b.local_get(nameIndexVar); + b.i32_const(1); + b.i32_add(); + b.array_get(translator.nullableObjectArrayType); + + b.comment('Increment index in named argument array.'); + b.local_get(nameIndexVar); + b.i32_const(2); + b.i32_add(); + b.local_set(nameIndexVar); + + codeGenNamedHandling([...currentNames, newName], + [...typeStack, translator.topType], nameIndex + 1); + } + b.end(); + + b.comment('Name "$newName" was *not* provided by caller.'); + codeGenNamedHandling(currentNames, typeStack, nameIndex + 1); + } + + codeGenNamedHandling([], typeStack, 0); + } + + // This function is purely used for checking assumptions made by the code this + // generator is producing. + // + // Namely, we assume that the caller has + // * populated default type arguments (if needed) + // * checked the shape of arguments & closure matches + // * performed necessary type checks on arguments. + void _verifyAssumptions( + w.InstructionsBuilder b, + w.Local closureLocal, + w.Local typeArgsLocal, + w.Local posArgsLocal, + w.Local namedArgsLocal, + ) { + if (!util.compilerAssertsEnabled) { + return; + } + b.comment('Verify assumptions of arguments and closure'); + final functionTypeLocal = + b.addLocal(translator.closureLayouter.functionTypeType); + b.local_get(closureLocal); + b.struct_get(translator.closureLayouter.closureBaseStruct, + FieldIndex.closureRuntimeType); + b.local_tee(functionTypeLocal); + + // Ensure type arguments were passed. + b.local_get(typeArgsLocal); + b.array_len(); + b.i32_const(representation.typeCount); + b.i32_ne(); + b.if_(); + b.unreachable(); + b.end(); + + // Ensure closure shape is correct. + b.local_get(typeArgsLocal); + b.local_get(posArgsLocal); + b.local_get(namedArgsLocal); + translator.callReference(translator.checkClosureShape.reference, b); + b.i32_eqz(); + b.if_(); + b.unreachable(); + b.end(); + + // Ensure types are correct. + if (!translator.options.omitImplicitTypeChecks) { + b.local_get(functionTypeLocal); + b.local_get(typeArgsLocal); + b.local_get(posArgsLocal); + b.local_get(namedArgsLocal); + translator.callReference(translator.checkClosureType.reference, b); + b.drop(); + } + } +} + class NodeCounter extends VisitorDefault<void> with VisitorVoidMixin { final bool omitCovarianceChecks; int count = 0;
diff --git a/pkg/dart2wasm/lib/util.dart b/pkg/dart2wasm/lib/util.dart index 88ea5ff..fabda99 100644 --- a/pkg/dart2wasm/lib/util.dart +++ b/pkg/dart2wasm/lib/util.dart
@@ -17,6 +17,12 @@ import 'package:vm/metadata/table_selector.dart' show TableSelectorMetadataRepository; +final bool compilerAssertsEnabled = (() { + bool compilerAsserts = false; + assert(compilerAsserts = true); + return compilerAsserts; +})(); + bool hasPragma(CoreTypes coreTypes, Annotatable node, String name) { return getPragma(coreTypes, node, name, defaultValue: '') != null; }
diff --git a/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use.wat b/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use.wat index 5afbaf4..bac3e34 100644 --- a/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use.wat +++ b/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use.wat
@@ -15,8 +15,8 @@ (type $type1 (func (param $var0 i32) (result (ref $MyConstClass)))) - (global $"C370 \"bad\"" (ref $JSStringImpl) <...>) (table $static0-0 (export "static0-0") 2 (ref null $type1)) + (global $"C370 \"bad\"" (ref $JSStringImpl) <...>) (func $Error._throwWithCurrentStackTrace (param $var0 (ref $#Top)) <...>) (func $"mainImpl <noInline>" (param $var0 i32) (local $var1 (ref $MyConstClass))
diff --git a/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use_module1.wat b/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use_module1.wat index 4a7e2f6..84f328a 100644 --- a/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use_module1.wat +++ b/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use_module1.wat
@@ -14,8 +14,8 @@ (field $b (ref $JSStringImpl))))) (global $S.h1-nonshared-const (import "S" "h1-nonshared-const") (ref extern)) (global $S.shared-const (import "S" "shared-const") (ref extern)) - (table $module0.constant-table0 (import "module0" "constant-table0") 1 (ref null $JSStringImpl) <...>) - (table $module0.constant-table1 (import "module0" "constant-table1") 1 (ref null $MyConstClass) <...>) + (table $module0.constant-table0 (import "module0" "constant-table0") 1 (ref null $JSStringImpl)) + (table $module0.constant-table1 (import "module0" "constant-table1") 1 (ref null $MyConstClass)) (global $"C488 MyConstClass" (ref $MyConstClass) (i32.const 107) (i32.const 0)
diff --git a/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use_module3.wat b/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use_module3.wat index 396d683..3bcd37f 100644 --- a/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use_module3.wat +++ b/pkg/dart2wasm/test/ir_tests/deferred.constant.multi_module_use_module3.wat
@@ -14,8 +14,8 @@ (field $b (ref $JSStringImpl))))) (global $S.shared-const (import "S" "shared-const") (ref extern)) (global $S.h0-nonshared-const (import "S" "h0-nonshared-const") (ref extern)) - (table $module0.constant-table0 (import "module0" "constant-table0") 1 (ref null $JSStringImpl) <...>) - (table $module0.constant-table1 (import "module0" "constant-table1") 1 (ref null $MyConstClass) <...>) + (table $module0.constant-table0 (import "module0" "constant-table0") 1 (ref null $JSStringImpl)) + (table $module0.constant-table1 (import "module0" "constant-table1") 1 (ref null $MyConstClass)) (global $"C492 MyConstClass" (ref $MyConstClass) (i32.const 107) (i32.const 0)
diff --git a/pkg/dart2wasm/test/ir_tests/deferred.constant.wat b/pkg/dart2wasm/test/ir_tests/deferred.constant.wat index 11686f7..8b4a8b2 100644 --- a/pkg/dart2wasm/test/ir_tests/deferred.constant.wat +++ b/pkg/dart2wasm/test/ir_tests/deferred.constant.wat
@@ -6,12 +6,12 @@ (field $field0 i32) (field $field1 (mut i32)) (field $fun (ref $#Closure-0-1))))) - (type $type245 <...>) - (type $type248 <...>) - (type $type251 <...>) - (table $static1-0 (export "static1-0") 1 (ref null $type251)) - (table $static2-0 (export "static2-0") 1 (ref null $type245)) - (table $static3-0 (export "static3-0") 1 (ref null $type248)) + (type $type236 <...>) + (type $type239 <...>) + (type $type242 <...>) + (table $static1-0 (export "static1-0") 1 (ref null $type242)) + (table $static2-0 (export "static2-0") 1 (ref null $type236)) + (table $static3-0 (export "static3-0") 1 (ref null $type239)) (func $print (param $var0 (ref null $#Top)) (result (ref null $#Top)) <...>) (func $"modMainUseH0 <noInline>" i64.const 0
diff --git a/pkg/dart2wasm/test/ir_tests/deferred.constant_module1.wat b/pkg/dart2wasm/test/ir_tests/deferred.constant_module1.wat index 6675b56..ff3b77c 100644 --- a/pkg/dart2wasm/test/ir_tests/deferred.constant_module1.wat +++ b/pkg/dart2wasm/test/ir_tests/deferred.constant_module1.wat
@@ -5,7 +5,7 @@ (type $_Type <...>) (type $Array<_Type> <...>) (type $JSStringImpl <...>) - (type $type20 <...>) + (type $type21 <...>) (type $_TopType <...>) (type $Array<_NamedParameter> <...>) (type $_FunctionType <...>) @@ -31,7 +31,7 @@ (global $"C306 WasmArray<_NamedParameter>[0]" (import "module0" "global4") (ref $Array<_NamedParameter>)) (global $"C28 _InterfaceType" (import "module0" "global7") (ref $_InterfaceType)) (global $S.globalH1Bar< (import "S" "globalH1Bar<") (ref extern)) - (table $module0.constant-table0 (import "module0" "constant-table0") 1 (ref null $_FunctionType) <...>) + (table $module0.constant-table0 (import "module0" "constant-table0") 1 (ref null $_FunctionType)) (global $global7 (ref $#Vtable-1-1) <...>) (global $global4 (ref $#DummyStruct) <...>) (global $"C459 _FunctionType" (ref $_FunctionType) <...>) @@ -70,42 +70,39 @@ local.get $var0 struct.get $#Closure-0-1 $vtable struct.get $#Vtable-0-1 $closureCallEntry-0-1 - call_ref $type20 + call_ref $type21 drop ref.null none ) - (func $globalH1Foo (param $var0 (ref $_Type)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) + (func $"globalH1Foo tear-off trampoline" (param $var0 (ref struct)) (param $var1 (ref $_Type)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) global.get $"C463 \"globalH1Bar<\"" - local.get $var0 - global.get $"C464 \">(\"" local.get $var1 + global.get $"C464 \">(\"" + local.get $var2 global.get $"C21 \")\"" array.new_fixed $Array<Object?> 5 call $JSStringImpl._interpolate call $print ) - (func $"globalH1Foo tear-off dynamic call entry" (param $var0 (ref $#ClosureBase)) (param $var1 (ref $Array<_Type>)) (param $var2 (ref $Array<Object?>)) (param $var3 (ref $Array<Object?>)) (result (ref null $#Top)) - local.get $var1 + (func $"C460 globalH1Foo tear-off (lazy initializer)}" (result (ref $#Closure-1-1)) + (local $var0 (ref $#Closure-1-1)) + i32.const 37 i32.const 0 - array.get $Array<_Type> - local.get $var2 - i32.const 0 - array.get $Array<Object?> - call $globalH1Foo - ) - (func $"globalH1Foo tear-off trampoline" (param $var0 (ref struct)) (param $var1 (ref $_Type)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) - local.get $var1 - local.get $var2 - call $globalH1Foo + global.get $global4 + global.get $global7 + global.get $"C459 _FunctionType" + struct.new $#Closure-1-1 + local.tee $var0 + global.set $"C460 globalH1Foo tear-off" + local.get $var0 ) (func $dynamic call entry (param $var0 (ref $#ClosureBase)) (param $var1 (ref $Array<_Type>)) (param $var2 (ref $Array<Object?>)) (param $var3 (ref $Array<Object?>)) (result (ref null $#Top)) <...>) (func $#dummy function (ref struct) -> (ref null #Top) (param $var0 (ref struct)) (result (ref null $#Top)) <...>) (func $instantiation constant trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>) (func $"C462 H1 (lazy initializer)}" (result (ref $H1)) - (local $var0 (ref $#Closure-1-1)) - (local $var1 (ref $_FunctionType)) - (local $var2 (ref $#Closure-0-1)) - (local $var3 (ref $H1)) + (local $var0 (ref $_FunctionType)) + (local $var1 (ref $#Closure-0-1)) + (local $var2 (ref $H1)) i32.const 105 i32.const 0 block $label0 (result (ref $#Closure-0-1)) @@ -116,15 +113,7 @@ block $label1 (result (ref $#Closure-1-1)) global.get $"C460 globalH1Foo tear-off" br_on_non_null $label1 - i32.const 37 - i32.const 0 - global.get $global4 - global.get $global7 - global.get $"C459 _FunctionType" - struct.new $#Closure-1-1 - local.tee $var0 - global.set $"C460 globalH1Foo tear-off" - local.get $var0 + call $"C460 globalH1Foo tear-off (lazy initializer)}" end $label1 global.get $"C28 _InterfaceType" struct.new $#InstantiationContext-1-1 @@ -148,18 +137,18 @@ i64.const 1 global.get $"C306 WasmArray<_NamedParameter>[0]" struct.new $_FunctionType - local.tee $var1 + local.tee $var0 table.set $module0.constant-table0 - local.get $var1 + local.get $var0 end $label2 struct.new $#Closure-0-1 - local.tee $var2 + local.tee $var1 global.set $"C461 InstantiationConstant(globalH1Foo<int>)" - local.get $var2 + local.get $var1 end $label0 struct.new $H1 - local.tee $var3 + local.tee $var2 global.set $"C462 H1" - local.get $var3 + local.get $var2 ) ) \ No newline at end of file
diff --git a/pkg/dart2wasm/test/ir_tests/deferred.constant_module2.wat b/pkg/dart2wasm/test/ir_tests/deferred.constant_module2.wat index cc2df20..564b714 100644 --- a/pkg/dart2wasm/test/ir_tests/deferred.constant_module2.wat +++ b/pkg/dart2wasm/test/ir_tests/deferred.constant_module2.wat
@@ -1,12 +1,10 @@ (module $module2 (type $#Top <...>) (type $Object <...>) - (type $Array<Object?> <...>) - (type $JSStringImpl <...>) (type $Array<_Type> <...>) + (type $JSStringImpl <...>) (type $Array<_NamedParameter> <...>) (type $_FunctionType <...>) - (type $#ClosureBase <...>) (type $#Vtable-0-1 <...>) (type $#Closure-0-1 <...>) (type $H0 (sub final $Object (struct @@ -21,7 +19,7 @@ (global $"C62 WasmArray<_Type>[1]" (import "module0" "global3") (ref $Array<_Type>)) (global $"C306 WasmArray<_NamedParameter>[0]" (import "module0" "global4") (ref $Array<_NamedParameter>)) (global $S.globalH0Foo (import "S" "globalH0Foo") (ref extern)) - (table $module0.constant-table0 (import "module0" "constant-table0") 1 (ref null $_FunctionType) <...>) + (table $module0.constant-table0 (import "module0" "constant-table0") 1 (ref null $_FunctionType)) (global $global6 (ref $#Vtable-0-1) <...>) (global $global3 (ref $#DummyStruct) <...>) (global $"C465 globalH0Foo tear-off" (mut (ref null $#Closure-0-1)) @@ -37,10 +35,6 @@ global.get $"C467 \"globalH0Foo\"" call $print ) - (func $"globalH0Foo tear-off dynamic call entry" (param $var0 (ref $#ClosureBase)) (param $var1 (ref $Array<_Type>)) (param $var2 (ref $Array<Object?>)) (param $var3 (ref $Array<Object?>)) (result (ref null $#Top)) - global.get $"C467 \"globalH0Foo\"" - call $print - ) (func $"globalH0Foo tear-off trampoline" (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) global.get $"C467 \"globalH0Foo\"" call $print
diff --git a/pkg/dart2wasm/test/ir_tests/dyn_closure.dart b/pkg/dart2wasm/test/ir_tests/dyn_closure.dart new file mode 100644 index 0000000..a5fe2d7 --- /dev/null +++ b/pkg/dart2wasm/test/ir_tests/dyn_closure.dart
@@ -0,0 +1,35 @@ +// Copyright (c) 2025, 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. + +// typeFilter=Closure-0-2|Vtable-0-2 +// functionFilter=XXX +// globalFilter=foo|bar + +void main() { + final objects = <dynamic>[ + () {}, + foo, + bar, + 'a', + 1, + ]; + final emptyClosure = objects[0]; + final fooClosure = objects[1]; + final barClosure = objects[2]; + emptyClosure(); + fooClosure(1); + fooClosure(1, 'b'); + barClosure(1, 2); + barClosure(1, 2); +} + +@pragma('wasm:never-inline') +void foo(int a, [String? b]) { + print('Foo $a $b'); +} + +@pragma('wasm:never-inline') +void bar(int a, [int? b]) { + print('Bar $a $b'); +}
diff --git a/pkg/dart2wasm/test/ir_tests/dyn_closure.wat b/pkg/dart2wasm/test/ir_tests/dyn_closure.wat new file mode 100644 index 0000000..c578f3e --- /dev/null +++ b/pkg/dart2wasm/test/ir_tests/dyn_closure.wat
@@ -0,0 +1,89 @@ +(module $module0 + (type $#Top <...>) + (type $Array<_Type> <...>) + (type $Array<Object?> <...>) + (type $_InterfaceType <...>) + (type $Array<_NamedParameter> <...>) + (type $_FunctionType <...>) + (rec + (type $#Closure-0-0 <...>) + (type $type9 <...>) + (type $#Vtable-0-0 <...>) + ) + (type $type15 <...>) + (type $_TopType <...>) + (type $type12 <...>) + (type $#Vtable-0-2 (sub final $#Vtable-0-0 (struct + (field $dynamiClosureCallEntry (ref $type9)) + (field $closureCallEntry-0-1 (ref $type12)) + (field $closureCallEntry-0-2 (ref $type15))))) + (type $#Closure-0-2 (sub final $#Closure-0-0 (struct + (field $field0 i32) + (field $field1 (mut i32)) + (field $context (ref struct)) + (field $vtable (ref $#Vtable-0-2)) + (field $functionType (ref $_FunctionType))))) + (type $#DummyStruct <...>) + (global $global3 (ref $#DummyStruct) <...>) + (global $"C1 WasmArray<_Type>[0]" (ref $Array<_Type>) <...>) + (global $"C15 _InterfaceType" (ref $_InterfaceType) <...>) + (global $"C303 WasmArray<_NamedParameter>[0]" (ref $Array<_NamedParameter>) <...>) + (global $"C329 _TopType" (ref $_TopType) <...>) + (global $"C333 foo tear-off" (ref $#Closure-0-2) + (i32.const 51) + (i32.const 0) + (global.get $global3) + (ref.func $"closure arguments dispatcher representation=0-2") + (ref.func $"foo tear-off trampoline") + (ref.func $"foo tear-off trampoline_303") + (struct.new $#Vtable-0-2) + (i32.const 12) + (i32.const 0) + (i32.const 0) + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C329 _TopType") + (global.get $"C15 _InterfaceType") + (i32.const 10) + (i32.const 0) + (i32.const 1) + (i32.const 131) + (global.get $"C1 WasmArray<_Type>[0]") + (struct.new $_InterfaceType) + (array.new_fixed $Array<_Type> 2) + (i64.const 1) + (global.get $"C303 WasmArray<_NamedParameter>[0]") + (struct.new $_FunctionType) + (struct.new $#Closure-0-2)) + (global $"C337 bar tear-off" (ref $#Closure-0-2) + (i32.const 51) + (i32.const 0) + (global.get $global3) + (ref.func $"closure arguments dispatcher representation=0-2") + (ref.func $"bar tear-off trampoline") + (ref.func $"bar tear-off trampoline_306") + (struct.new $#Vtable-0-2) + (i32.const 12) + (i32.const 0) + (i32.const 0) + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C329 _TopType") + (global.get $"C15 _InterfaceType") + (i32.const 10) + (i32.const 0) + (i32.const 1) + (i32.const 124) + (global.get $"C1 WasmArray<_Type>[0]") + (struct.new $_InterfaceType) + (array.new_fixed $Array<_Type> 2) + (i64.const 1) + (global.get $"C303 WasmArray<_NamedParameter>[0]") + (struct.new $_FunctionType) + (struct.new $#Closure-0-2)) + (func $closure arguments dispatcher representation=0-2 (param $var0 (ref $#Closure-0-0)) (param $var1 (ref $Array<_Type>)) (param $var2 (ref $Array<Object?>)) (param $var3 (ref $Array<Object?>)) (result (ref null $#Top)) <...>) + (func $foo tear-off trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>) + (func $foo tear-off trampoline_303 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>) + (func $bar tear-off trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>) + (func $bar tear-off trampoline_306 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>) +) \ No newline at end of file
diff --git a/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply.dart b/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply.dart new file mode 100644 index 0000000..6145afd --- /dev/null +++ b/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply.dart
@@ -0,0 +1,25 @@ +// Copyright (c) 2025, 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. + +// typeFilter=Closure-0-2|Vtable-0-2 +// functionFilter=XXX +// globalFilter=foo|bar + +void main() { + Function.apply(() {}, []); + Function.apply(foo, [1]); + Function.apply(foo, [1, 'b']); + Function.apply(bar, [1]); + Function.apply(bar, [1, 2]); +} + +@pragma('wasm:never-inline') +void foo(int a, [String? b]) { + print('Foo $a $b'); +} + +@pragma('wasm:never-inline') +void bar(int a, [int? b]) { + print('Bar $a $b'); +}
diff --git a/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply.wat b/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply.wat new file mode 100644 index 0000000..31b9cc9 --- /dev/null +++ b/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply.wat
@@ -0,0 +1,89 @@ +(module $module0 + (type $#Top <...>) + (type $Array<_Type> <...>) + (type $Array<Object?> <...>) + (type $_InterfaceType <...>) + (type $Array<_NamedParameter> <...>) + (type $_FunctionType <...>) + (rec + (type $#Closure-0-0 <...>) + (type $type9 <...>) + (type $#Vtable-0-0 <...>) + ) + (type $type15 <...>) + (type $_TopType <...>) + (type $type12 <...>) + (type $#Vtable-0-2 (sub final $#Vtable-0-0 (struct + (field $dynamiClosureCallEntry (ref $type9)) + (field $closureCallEntry-0-1 (ref $type12)) + (field $closureCallEntry-0-2 (ref $type15))))) + (type $#Closure-0-2 (sub final $#Closure-0-0 (struct + (field $field0 i32) + (field $field1 (mut i32)) + (field $context (ref struct)) + (field $vtable (ref $#Vtable-0-2)) + (field $functionType (ref $_FunctionType))))) + (type $#DummyStruct <...>) + (global $global3 (ref $#DummyStruct) <...>) + (global $"C1 WasmArray<_Type>[0]" (ref $Array<_Type>) <...>) + (global $"C15 _InterfaceType" (ref $_InterfaceType) <...>) + (global $"C303 WasmArray<_NamedParameter>[0]" (ref $Array<_NamedParameter>) <...>) + (global $"C329 _TopType" (ref $_TopType) <...>) + (global $"C333 foo tear-off" (ref $#Closure-0-2) + (i32.const 51) + (i32.const 0) + (global.get $global3) + (ref.func $"closure arguments dispatcher representation=0-2") + (ref.func $"foo tear-off trampoline") + (ref.func $"foo tear-off trampoline_303") + (struct.new $#Vtable-0-2) + (i32.const 12) + (i32.const 0) + (i32.const 0) + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C329 _TopType") + (global.get $"C15 _InterfaceType") + (i32.const 10) + (i32.const 0) + (i32.const 1) + (i32.const 131) + (global.get $"C1 WasmArray<_Type>[0]") + (struct.new $_InterfaceType) + (array.new_fixed $Array<_Type> 2) + (i64.const 1) + (global.get $"C303 WasmArray<_NamedParameter>[0]") + (struct.new $_FunctionType) + (struct.new $#Closure-0-2)) + (global $"C338 bar tear-off" (ref $#Closure-0-2) + (i32.const 51) + (i32.const 0) + (global.get $global3) + (ref.func $"closure arguments dispatcher representation=0-2") + (ref.func $"bar tear-off trampoline") + (ref.func $"bar tear-off trampoline_308") + (struct.new $#Vtable-0-2) + (i32.const 12) + (i32.const 0) + (i32.const 0) + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C329 _TopType") + (global.get $"C15 _InterfaceType") + (i32.const 10) + (i32.const 0) + (i32.const 1) + (i32.const 124) + (global.get $"C1 WasmArray<_Type>[0]") + (struct.new $_InterfaceType) + (array.new_fixed $Array<_Type> 2) + (i64.const 1) + (global.get $"C303 WasmArray<_NamedParameter>[0]") + (struct.new $_FunctionType) + (struct.new $#Closure-0-2)) + (func $closure arguments dispatcher representation=0-2 (param $var0 (ref $#Closure-0-0)) (param $var1 (ref $Array<_Type>)) (param $var2 (ref $Array<Object?>)) (param $var3 (ref $Array<Object?>)) (result (ref null $#Top)) <...>) + (func $foo tear-off trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>) + (func $foo tear-off trampoline_303 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>) + (func $bar tear-off trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>) + (func $bar tear-off trampoline_308 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>) +) \ No newline at end of file
diff --git a/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply_named.dart b/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply_named.dart new file mode 100644 index 0000000..e4530b7 --- /dev/null +++ b/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply_named.dart
@@ -0,0 +1,25 @@ +// Copyright (c) 2025, 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. + +// typeFilter=Closure-0-2|Vtable-0-2 +// functionFilter=XXX +// globalFilter=foo|bar + +void main() { + Function.apply(() {}, []); + Function.apply(foo, [1]); + Function.apply(foo, [1, 'b']); + Function.apply(bar, [1]); + Function.apply((int a, {int? n}) {}, [1], {#n: 1}); +} + +@pragma('wasm:never-inline') +void foo(int a, [String? b]) { + print('Foo $a $b'); +} + +@pragma('wasm:never-inline') +void bar(int a, [int? b]) { + print('Bar $a $b'); +}
diff --git a/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply_named.wat b/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply_named.wat new file mode 100644 index 0000000..3b95c1c --- /dev/null +++ b/pkg/dart2wasm/test/ir_tests/dyn_closure_function_apply_named.wat
@@ -0,0 +1,80 @@ +(module $module0 + (type $#Top <...>) + (type $Array<Object?> <...>) + (type $Array<_Type> <...>) + (type $_InterfaceType <...>) + (type $type6 <...>) + (type $Array<_NamedParameter> <...>) + (type $_FunctionType <...>) + (rec + (type $#Closure-0-0 <...>) + (type $type3 <...>) + (type $#Vtable-0-0 <...>) + ) + (type $#Vtable-0-2 (sub final $#Vtable-0-0 (struct + (field $dynamiClosureCallEntry (ref $type3)) + (field $closureCallEntry-0-2 (ref $type6))))) + (type $#Closure-0-2 (sub final $#Closure-0-0 (struct + (field $field0 i32) + (field $field1 (mut i32)) + (field $context (ref struct)) + (field $vtable (ref $#Vtable-0-2)) + (field $functionType (ref $_FunctionType))))) + (type $_TopType <...>) + (type $#DummyStruct <...>) + (global $global3 (ref $#DummyStruct) <...>) + (global $"C1 WasmArray<_Type>[0]" (ref $Array<_Type>) <...>) + (global $"C15 _InterfaceType" (ref $_InterfaceType) <...>) + (global $"C303 WasmArray<_NamedParameter>[0]" (ref $Array<_NamedParameter>) <...>) + (global $"C329 _TopType" (ref $_TopType) <...>) + (global $"C333 foo tear-off" (ref $#Closure-0-2) + (i32.const 51) + (i32.const 0) + (global.get $global3) + (ref.func $"foo tear-off dynamic call entry") + (ref.func $"foo tear-off trampoline_307") + (struct.new $#Vtable-0-2) + (i32.const 12) + (i32.const 0) + (i32.const 0) + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C329 _TopType") + (global.get $"C15 _InterfaceType") + (i32.const 10) + (i32.const 0) + (i32.const 1) + (i32.const 131) + (global.get $"C1 WasmArray<_Type>[0]") + (struct.new $_InterfaceType) + (array.new_fixed $Array<_Type> 2) + (i64.const 1) + (global.get $"C303 WasmArray<_NamedParameter>[0]") + (struct.new $_FunctionType) + (struct.new $#Closure-0-2)) + (global $"C335 _InterfaceType" (ref $_InterfaceType) <...>) + (global $"C338 bar tear-off" (ref $#Closure-0-2) + (i32.const 51) + (i32.const 0) + (global.get $global3) + (ref.func $"bar tear-off dynamic call entry") + (ref.func $"bar tear-off trampoline_313") + (struct.new $#Vtable-0-2) + (i32.const 12) + (i32.const 0) + (i32.const 0) + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C1 WasmArray<_Type>[0]") + (global.get $"C329 _TopType") + (global.get $"C15 _InterfaceType") + (global.get $"C335 _InterfaceType") + (array.new_fixed $Array<_Type> 2) + (i64.const 1) + (global.get $"C303 WasmArray<_NamedParameter>[0]") + (struct.new $_FunctionType) + (struct.new $#Closure-0-2)) + (func $foo tear-off dynamic call entry (param $var0 (ref $#Closure-0-0)) (param $var1 (ref $Array<_Type>)) (param $var2 (ref $Array<Object?>)) (param $var3 (ref $Array<Object?>)) (result (ref null $#Top)) <...>) + (func $foo tear-off trampoline_307 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>) + (func $bar tear-off dynamic call entry (param $var0 (ref $#Closure-0-0)) (param $var1 (ref $Array<_Type>)) (param $var2 (ref $Array<Object?>)) (param $var3 (ref $Array<Object?>)) (result (ref null $#Top)) <...>) + (func $bar tear-off trampoline_313 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>) +) \ No newline at end of file
diff --git a/pkg/dart2wasm/test/ir_tests/interop.num.wat b/pkg/dart2wasm/test/ir_tests/interop.num.wat index c1ed442..3b5944f 100644 --- a/pkg/dart2wasm/test/ir_tests/interop.num.wat +++ b/pkg/dart2wasm/test/ir_tests/interop.num.wat
@@ -18,6 +18,7 @@ (func $"dart2wasm._275 (import)" (import "dart2wasm" "_275") (param externref) (result externref)) (func $"dart2wasm._147 (import)" (import "dart2wasm" "_147") (param externref) (result f64)) (func $"dart2wasm._148 (import)" (import "dart2wasm" "_148") (param f64) (result externref)) + (table $dtable1 666 funcref) (global $"C66 WasmArray<WasmArray<_Type>>[727]" (ref $Array<WasmArray<_Type>>) <...>) (global $"C311 _TopType" (ref $_TopType) <...>) (global $"numValueNullable initialized" (mut i32) <...>) @@ -25,7 +26,7 @@ (global $"ktrue initialized" (mut i32) <...>) (global $ktrue (mut i32) <...>) (global $numValue (mut (ref null $#Top)) <...>) - (table $dtable2 666 funcref <...>) + (elem $dtable1 <...>) (func $_TypeUniverse.isSubtype (param $var0 (ref $_Type)) (param $var1 (ref null $_Environment)) (param $var2 (ref $_Type)) (param $var3 (ref null $_Environment)) (result i32) <...>) (func $_TypeUniverse._checkSubclassRelationshipViaTable (param $var0 i32) (param $var1 i32) (result i32) <...>) (func $_TypeUniverse.substituteTypeArgument (param $var0 (ref $_Type)) (param $var1 (ref $Array<_Type>)) (result (ref $_Type)) <...>)
diff --git a/pkg/front_end/lib/src/source/diet_listener.dart b/pkg/front_end/lib/src/source/diet_listener.dart index 2fb2dc5..84680e0 100644 --- a/pkg/front_end/lib/src/source/diet_listener.dart +++ b/pkg/front_end/lib/src/source/diet_listener.dart
@@ -1214,6 +1214,22 @@ } @override + // Coverage-ignore(suite): Not run. + void endPrimaryConstructorBody( + Token beginToken, + Token? beginInitializers, + Token endToken, + ) { + debugEvent("endPrimaryConstructorBody"); + assert( + checkState(beginToken, [/* metadata token */ ValueKinds.TokenOrNull]), + ); + // TODO(declaring-constructors): Implement primary constructor body. + pop() as Token?; + checkEmpty(beginToken.charOffset); + } + + @override void endExtensionTypeDeclaration( Token beginToken, Token? augmentToken,
diff --git a/pkg/front_end/lib/src/source/outline_builder.dart b/pkg/front_end/lib/src/source/outline_builder.dart index c54bc48..3352eeb 100644 --- a/pkg/front_end/lib/src/source/outline_builder.dart +++ b/pkg/front_end/lib/src/source/outline_builder.dart
@@ -1961,6 +1961,31 @@ } @override + // Coverage-ignore(suite): Not run. + void endPrimaryConstructorBody( + Token beginToken, + Token? beginInitializers, + Token endToken, + ) { + debugEvent("endPrimaryConstructorBody"); + assert( + checkState(beginToken, [ + ValueKinds.MethodBody, + ValueKinds.AsyncModifier, + ValueKinds.MetadataListOrNull, + ]), + ); + + // TODO(declaring-constructors): Implement primary constructor body. + // ignore: unused_local_variable + MethodBody bodyKind = pop() as MethodBody; + // ignore: unused_local_variable + AsyncMarker asyncModifier = pop() as AsyncMarker; + // ignore: unused_local_variable + List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?; + } + + @override void beginTopLevelMethod( Token lastConsumed, Token? augmentToken,
diff --git a/pkg/front_end/lib/src/util/parser_ast.dart b/pkg/front_end/lib/src/util/parser_ast.dart index 45a20b2..9faa804 100644 --- a/pkg/front_end/lib/src/util/parser_ast.dart +++ b/pkg/front_end/lib/src/util/parser_ast.dart
@@ -1533,6 +1533,18 @@ if (child is EnumFactoryMethodEnd) return child; throw "Not found"; } + + bool isPrimaryConstructorBody() { + ParserAstNode child = children![1]; + if (child is PrimaryConstructorBodyEnd) return true; + return false; + } + + PrimaryConstructorBodyEnd getPrimaryConstructorBody() { + ParserAstNode child = children![1]; + if (child is PrimaryConstructorBodyEnd) return child; + throw "Not found"; + } } // Coverage-ignore(suite): Not run.
diff --git a/pkg/front_end/lib/src/util/parser_ast_helper.dart b/pkg/front_end/lib/src/util/parser_ast_helper.dart index e369359..6a0d52c 100644 --- a/pkg/front_end/lib/src/util/parser_ast_helper.dart +++ b/pkg/front_end/lib/src/util/parser_ast_helper.dart
@@ -549,6 +549,30 @@ } @override + void beginPrimaryConstructorBody(Token token) { + PrimaryConstructorBodyBegin data = new PrimaryConstructorBodyBegin( + ParserAstType.BEGIN, + token: token, + ); + seen(data); + } + + @override + void endPrimaryConstructorBody( + Token beginToken, + Token? beginInitializers, + Token endToken, + ) { + PrimaryConstructorBodyEnd data = new PrimaryConstructorBodyEnd( + ParserAstType.END, + beginToken: beginToken, + beginInitializers: beginInitializers, + endToken: endToken, + ); + seen(data); + } + + @override void beginCombinators(Token token) { CombinatorsBegin data = new CombinatorsBegin( ParserAstType.BEGIN, @@ -5082,6 +5106,46 @@ R accept<R>(ParserAstVisitor<R> v) => v.visitNoPrimaryConstructorHandle(this); } +class PrimaryConstructorBodyBegin extends ParserAstNode { + final Token token; + + PrimaryConstructorBodyBegin(ParserAstType type, {required this.token}) + : super("PrimaryConstructorBody", type); + + @override + Map<String, Object?> get deprecatedArguments => {"token": token}; + + @override + R accept<R>(ParserAstVisitor<R> v) => + v.visitPrimaryConstructorBodyBegin(this); +} + +class PrimaryConstructorBodyEnd extends ParserAstNode + implements BeginAndEndTokenParserAstNode { + @override + final Token beginToken; + final Token? beginInitializers; + @override + final Token endToken; + + PrimaryConstructorBodyEnd( + ParserAstType type, { + required this.beginToken, + this.beginInitializers, + required this.endToken, + }) : super("PrimaryConstructorBody", type); + + @override + Map<String, Object?> get deprecatedArguments => { + "beginToken": beginToken, + "beginInitializers": beginInitializers, + "endToken": endToken, + }; + + @override + R accept<R>(ParserAstVisitor<R> v) => v.visitPrimaryConstructorBodyEnd(this); +} + class CombinatorsBegin extends ParserAstNode { final Token token; @@ -11379,6 +11443,8 @@ R visitPrimaryConstructorBegin(PrimaryConstructorBegin node); R visitPrimaryConstructorEnd(PrimaryConstructorEnd node); R visitNoPrimaryConstructorHandle(NoPrimaryConstructorHandle node); + R visitPrimaryConstructorBodyBegin(PrimaryConstructorBodyBegin node); + R visitPrimaryConstructorBodyEnd(PrimaryConstructorBodyEnd node); R visitCombinatorsBegin(CombinatorsBegin node); R visitCombinatorsEnd(CombinatorsEnd node); R visitCompilationUnitBegin(CompilationUnitBegin node); @@ -11918,6 +11984,14 @@ node.visitChildren(this); @override + void visitPrimaryConstructorBodyBegin(PrimaryConstructorBodyBegin node) => + node.visitChildren(this); + + @override + void visitPrimaryConstructorBodyEnd(PrimaryConstructorBodyEnd node) => + node.visitChildren(this); + + @override void visitCombinatorsBegin(CombinatorsBegin node) => node.visitChildren(this); @override @@ -13385,6 +13459,15 @@ ) => defaultNode(node); @override + Future<void> visitPrimaryConstructorBodyBegin( + PrimaryConstructorBodyBegin node, + ) => defaultNode(node); + + @override + Future<void> visitPrimaryConstructorBodyEnd(PrimaryConstructorBodyEnd node) => + defaultNode(node); + + @override Future<void> visitCombinatorsBegin(CombinatorsBegin node) => defaultNode(node);
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart new file mode 100644 index 0000000..eb93361 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart
@@ -0,0 +1,15 @@ +class C1() { + this {} +} + +class C2() { + this : assert(1 > 2) {} +} + +class C3() { + this; +} + +class C4() { + this : assert(1 > 2); +}
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.expect b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.expect new file mode 100644 index 0000000..900ec45 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.expect
@@ -0,0 +1,134 @@ +beginCompilationUnit(class) + beginMetadataStar(class) + endMetadataStar(0) + beginClassOrMixinOrNamedMixinApplicationPrelude(class) + handleIdentifier(C1, classOrMixinDeclaration) + handleNoTypeVariables(() + beginClassDeclaration(class, null, null, null, null, null, null, null, null, C1) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, false) + handleNoType()) + handleClassExtends(null, 1) + handleClassNoWithClause() + handleImplements(null, 0) + handleClassHeader(class, class, null) + beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + handleNoInitializers() + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + endPrimaryConstructorBody(this, this, }) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + endClassDeclaration(class, }) + endTopLevelDeclaration(}) + beginMetadataStar(class) + endMetadataStar(0) + beginClassOrMixinOrNamedMixinApplicationPrelude(class) + handleIdentifier(C2, classOrMixinDeclaration) + handleNoTypeVariables(() + beginClassDeclaration(class, null, null, null, null, null, null, null, null, C2) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, false) + handleNoType()) + handleClassExtends(null, 1) + handleClassNoWithClause() + handleImplements(null, 0) + handleClassHeader(class, class, null) + beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + endPrimaryConstructorBody(this, this, }) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + endClassDeclaration(class, }) + endTopLevelDeclaration(}) + beginMetadataStar(class) + endMetadataStar(0) + beginClassOrMixinOrNamedMixinApplicationPrelude(class) + handleIdentifier(C3, classOrMixinDeclaration) + handleNoTypeVariables(() + beginClassDeclaration(class, null, null, null, null, null, null, null, null, C3) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, false) + handleNoType()) + handleClassExtends(null, 1) + handleClassNoWithClause() + handleImplements(null, 0) + handleClassHeader(class, class, null) + beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + handleNoInitializers() + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + endPrimaryConstructorBody(this, this, ;) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + endClassDeclaration(class, }) + endTopLevelDeclaration(}) + beginMetadataStar(class) + endMetadataStar(0) + beginClassOrMixinOrNamedMixinApplicationPrelude(class) + handleIdentifier(C4, classOrMixinDeclaration) + handleNoTypeVariables(() + beginClassDeclaration(class, null, null, null, null, null, null, null, null, C4) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, false) + handleNoType()) + handleClassExtends(null, 1) + handleClassNoWithClause() + handleImplements(null, 0) + handleClassHeader(class, class, null) + beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + endPrimaryConstructorBody(this, this, ;) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + endClassDeclaration(class, }) + endTopLevelDeclaration(}) +endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.intertwined.expect b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.intertwined.expect new file mode 100644 index 0000000..0d49641 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.intertwined.expect
@@ -0,0 +1,264 @@ +parseUnit(class) + skipErrorTokens(class) + listener: beginCompilationUnit(class) + syntheticPreviousToken(class) + parseTopLevelDeclarationImpl(, DirectiveContext(DirectiveState.Unknown)) + parseMetadataStar() + listener: beginMetadataStar(class) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(class, , class, null, null, null, null, DirectiveContext(DirectiveState.Unknown)) + parseClassOrNamedMixinApplication(class, null, null, null, null, null, null, null, null, class) + listener: beginClassOrMixinOrNamedMixinApplicationPrelude(class) + ensureIdentifier(class, classOrMixinDeclaration) + listener: handleIdentifier(C1, classOrMixinDeclaration) + listener: handleNoTypeVariables(() + listener: beginClassDeclaration(class, null, null, null, null, null, null, null, null, C1) + parseClass(C1, class, class, null, C1) + parsePrimaryConstructorOpt(C1, null, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(C1, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, false) + parseClassHeaderOpt(), class, class) + parseClassExtendsOpt(), DeclarationHeaderKind.Class) + listener: handleNoType()) + listener: handleClassExtends(null, 1) + parseClassWithClauseOpt()) + listener: handleClassNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleClassHeader(class, class, null) + parseClassOrMixinOrExtensionBody(), DeclarationKind.Class, C1) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.Class, C1) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + listener: handleNoInitializers() + parseAsyncModifierOpt(this) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(this, false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + listener: endPrimaryConstructorBody(this, this, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + listener: endClassDeclaration(class, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(class) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(class, }, class, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseClassOrNamedMixinApplication(class, null, null, null, null, null, null, null, null, class) + listener: beginClassOrMixinOrNamedMixinApplicationPrelude(class) + ensureIdentifier(class, classOrMixinDeclaration) + listener: handleIdentifier(C2, classOrMixinDeclaration) + listener: handleNoTypeVariables(() + listener: beginClassDeclaration(class, null, null, null, null, null, null, null, null, C2) + parseClass(C2, class, class, null, C2) + parsePrimaryConstructorOpt(C2, null, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(C2, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, false) + parseClassHeaderOpt(), class, class) + parseClassExtendsOpt(), DeclarationHeaderKind.Class) + listener: handleNoType()) + listener: handleClassExtends(null, 1) + parseClassWithClauseOpt()) + listener: handleClassNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleClassHeader(class, class, null) + parseClassOrMixinOrExtensionBody(), DeclarationKind.Class, C2) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.Class, C2) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + listener: endPrimaryConstructorBody(this, this, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + listener: endClassDeclaration(class, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(class) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(class, }, class, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseClassOrNamedMixinApplication(class, null, null, null, null, null, null, null, null, class) + listener: beginClassOrMixinOrNamedMixinApplicationPrelude(class) + ensureIdentifier(class, classOrMixinDeclaration) + listener: handleIdentifier(C3, classOrMixinDeclaration) + listener: handleNoTypeVariables(() + listener: beginClassDeclaration(class, null, null, null, null, null, null, null, null, C3) + parseClass(C3, class, class, null, C3) + parsePrimaryConstructorOpt(C3, null, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(C3, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, false) + parseClassHeaderOpt(), class, class) + parseClassExtendsOpt(), DeclarationHeaderKind.Class) + listener: handleNoType()) + listener: handleClassExtends(null, 1) + parseClassWithClauseOpt()) + listener: handleClassNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleClassHeader(class, class, null) + parseClassOrMixinOrExtensionBody(), DeclarationKind.Class, C3) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.Class, C3) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + listener: handleNoInitializers() + parseAsyncModifierOpt(this) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(this, false, true) + listener: handleEmptyFunctionBody(;) + listener: endPrimaryConstructorBody(this, this, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + listener: endClassDeclaration(class, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(class) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(class, }, class, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseClassOrNamedMixinApplication(class, null, null, null, null, null, null, null, null, class) + listener: beginClassOrMixinOrNamedMixinApplicationPrelude(class) + ensureIdentifier(class, classOrMixinDeclaration) + listener: handleIdentifier(C4, classOrMixinDeclaration) + listener: handleNoTypeVariables(() + listener: beginClassDeclaration(class, null, null, null, null, null, null, null, null, C4) + parseClass(C4, class, class, null, C4) + parsePrimaryConstructorOpt(C4, null, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(C4, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, false) + parseClassHeaderOpt(), class, class) + parseClassExtendsOpt(), DeclarationHeaderKind.Class) + listener: handleNoType()) + listener: handleClassExtends(null, 1) + parseClassWithClauseOpt()) + listener: handleClassNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleClassHeader(class, class, null) + parseClassOrMixinOrExtensionBody(), DeclarationKind.Class, C4) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.Class, C4) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: handleEmptyFunctionBody(;) + listener: endPrimaryConstructorBody(this, this, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + listener: endClassDeclaration(class, }) + listener: endTopLevelDeclaration(}) + reportAllErrorTokens(class) + listener: endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.parser.expect b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.parser.expect new file mode 100644 index 0000000..a66ca35 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.parser.expect
@@ -0,0 +1,33 @@ +class C1() { +this {} +} + +class C2() { +this : assert(1 > 2) {} +} + +class C3() { +this; +} + +class C4() { +this : assert(1 > 2); +} + + +class[KeywordToken] C1[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C2[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C3[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken];[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C4[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.scanner.expect b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.scanner.expect new file mode 100644 index 0000000..a66ca35 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body.dart.scanner.expect
@@ -0,0 +1,33 @@ +class C1() { +this {} +} + +class C2() { +this : assert(1 > 2) {} +} + +class C3() { +this; +} + +class C4() { +this : assert(1 > 2); +} + + +class[KeywordToken] C1[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C2[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C3[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken];[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C4[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart new file mode 100644 index 0000000..2ab967e --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart
@@ -0,0 +1,15 @@ +class C1() { + this() {} +} + +class C2() { + this(int x) : assert(1 > 2) {} +} + +class C3() { + this(); +} + +class C4() { + this(int x) : assert(1 > 2); +}
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.expect b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.expect new file mode 100644 index 0000000..d856662 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.expect
@@ -0,0 +1,204 @@ +Problems reported: + +parser/declaring_constructors/class_primary_constructor_body_error:2:3: 'this' can't be used as an identifier because it's a keyword. + this() {} + ^^^^ + +parser/declaring_constructors/class_primary_constructor_body_error:6:3: 'this' can't be used as an identifier because it's a keyword. + this(int x) : assert(1 > 2) {} + ^^^^ + +parser/declaring_constructors/class_primary_constructor_body_error:6:3: The name of a constructor must match the name of the enclosing class. + this(int x) : assert(1 > 2) {} + ^^^^ + +parser/declaring_constructors/class_primary_constructor_body_error:10:3: 'this' can't be used as an identifier because it's a keyword. + this(); + ^^^^ + +parser/declaring_constructors/class_primary_constructor_body_error:14:3: 'this' can't be used as an identifier because it's a keyword. + this(int x) : assert(1 > 2); + ^^^^ + +parser/declaring_constructors/class_primary_constructor_body_error:14:3: The name of a constructor must match the name of the enclosing class. + this(int x) : assert(1 > 2); + ^^^^ + +beginCompilationUnit(class) + beginMetadataStar(class) + endMetadataStar(0) + beginClassOrMixinOrNamedMixinApplicationPrelude(class) + handleIdentifier(C1, classOrMixinDeclaration) + handleNoTypeVariables(() + beginClassDeclaration(class, null, null, null, null, null, null, null, null, C1) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, false) + handleNoType()) + handleClassExtends(null, 1) + handleClassNoWithClause() + handleImplements(null, 0) + handleClassHeader(class, class, null) + beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, C1) + handleNoType({) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, methodDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.NonStaticMethod) + endFormalParameters(0, (, ), MemberKind.NonStaticMethod) + handleNoInitializers() + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + endClassMethod(null, this, (, null, }) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + endClassDeclaration(class, }) + endTopLevelDeclaration(}) + beginMetadataStar(class) + endMetadataStar(0) + beginClassOrMixinOrNamedMixinApplicationPrelude(class) + handleIdentifier(C2, classOrMixinDeclaration) + handleNoTypeVariables(() + beginClassDeclaration(class, null, null, null, null, null, null, null, null, C2) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, false) + handleNoType()) + handleClassExtends(null, 1) + handleClassNoWithClause() + handleImplements(null, 0) + handleClassHeader(class, class, null) + beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, C2) + handleNoType({) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, methodDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.NonStaticMethod) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + endFormalParameters(1, (, ), MemberKind.NonStaticMethod) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + handleRecoverableError(ConstructorWithWrongName, this, this) + endClassConstructor(null, this, (, :, }) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + endClassDeclaration(class, }) + endTopLevelDeclaration(}) + beginMetadataStar(class) + endMetadataStar(0) + beginClassOrMixinOrNamedMixinApplicationPrelude(class) + handleIdentifier(C3, classOrMixinDeclaration) + handleNoTypeVariables(() + beginClassDeclaration(class, null, null, null, null, null, null, null, null, C3) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, false) + handleNoType()) + handleClassExtends(null, 1) + handleClassNoWithClause() + handleImplements(null, 0) + handleClassHeader(class, class, null) + beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, C3) + handleNoType({) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, methodDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.NonStaticMethod) + endFormalParameters(0, (, ), MemberKind.NonStaticMethod) + handleNoInitializers() + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + endClassMethod(null, this, (, null, ;) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + endClassDeclaration(class, }) + endTopLevelDeclaration(}) + beginMetadataStar(class) + endMetadataStar(0) + beginClassOrMixinOrNamedMixinApplicationPrelude(class) + handleIdentifier(C4, classOrMixinDeclaration) + handleNoTypeVariables(() + beginClassDeclaration(class, null, null, null, null, null, null, null, null, C4) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, false) + handleNoType()) + handleClassExtends(null, 1) + handleClassNoWithClause() + handleImplements(null, 0) + handleClassHeader(class, class, null) + beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, C4) + handleNoType({) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, methodDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.NonStaticMethod) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + endFormalParameters(1, (, ), MemberKind.NonStaticMethod) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + handleRecoverableError(ConstructorWithWrongName, this, this) + endClassConstructor(null, this, (, :, ;) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + endClassDeclaration(class, }) + endTopLevelDeclaration(}) +endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.intertwined.expect b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.intertwined.expect new file mode 100644 index 0000000..d38204b --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.intertwined.expect
@@ -0,0 +1,344 @@ +parseUnit(class) + skipErrorTokens(class) + listener: beginCompilationUnit(class) + syntheticPreviousToken(class) + parseTopLevelDeclarationImpl(, DirectiveContext(DirectiveState.Unknown)) + parseMetadataStar() + listener: beginMetadataStar(class) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(class, , class, null, null, null, null, DirectiveContext(DirectiveState.Unknown)) + parseClassOrNamedMixinApplication(class, null, null, null, null, null, null, null, null, class) + listener: beginClassOrMixinOrNamedMixinApplicationPrelude(class) + ensureIdentifier(class, classOrMixinDeclaration) + listener: handleIdentifier(C1, classOrMixinDeclaration) + listener: handleNoTypeVariables(() + listener: beginClassDeclaration(class, null, null, null, null, null, null, null, null, C1) + parseClass(C1, class, class, null, C1) + parsePrimaryConstructorOpt(C1, null, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(C1, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, false) + parseClassHeaderOpt(), class, class) + parseClassExtendsOpt(), DeclarationHeaderKind.Class) + listener: handleNoType()) + listener: handleClassExtends(null, 1) + parseClassWithClauseOpt()) + listener: handleClassNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleClassHeader(class, class, null) + parseClassOrMixinOrExtensionBody(), DeclarationKind.Class, C1) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.Class, C1) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parseMethod({, null, null, null, null, null, null, null, {, NoType(), null, this, DeclarationKind.Class, C1, false) + listener: beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, C1) + listener: handleNoType({) + ensureIdentifierPotentiallyRecovered({, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.NonStaticMethod) + parseFormalParameters(this, MemberKind.NonStaticMethod) + parseFormalParametersRest((, MemberKind.NonStaticMethod) + listener: beginFormalParameters((, MemberKind.NonStaticMethod) + listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod) + parseInitializersOpt()) + listener: handleNoInitializers() + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + listener: endClassMethod(null, this, (, null, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + listener: endClassDeclaration(class, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(class) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(class, }, class, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseClassOrNamedMixinApplication(class, null, null, null, null, null, null, null, null, class) + listener: beginClassOrMixinOrNamedMixinApplicationPrelude(class) + ensureIdentifier(class, classOrMixinDeclaration) + listener: handleIdentifier(C2, classOrMixinDeclaration) + listener: handleNoTypeVariables(() + listener: beginClassDeclaration(class, null, null, null, null, null, null, null, null, C2) + parseClass(C2, class, class, null, C2) + parsePrimaryConstructorOpt(C2, null, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(C2, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, false) + parseClassHeaderOpt(), class, class) + parseClassExtendsOpt(), DeclarationHeaderKind.Class) + listener: handleNoType()) + listener: handleClassExtends(null, 1) + parseClassWithClauseOpt()) + listener: handleClassNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleClassHeader(class, class, null) + parseClassOrMixinOrExtensionBody(), DeclarationKind.Class, C2) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.Class, C2) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parseMethod({, null, null, null, null, null, null, null, {, NoType(), null, this, DeclarationKind.Class, C2, false) + listener: beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, C2) + listener: handleNoType({) + ensureIdentifierPotentiallyRecovered({, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.NonStaticMethod) + parseFormalParameters(this, MemberKind.NonStaticMethod) + parseFormalParametersRest((, MemberKind.NonStaticMethod) + listener: beginFormalParameters((, MemberKind.NonStaticMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod) + parseInitializersOpt()) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + reportRecoverableError(this, ConstructorWithWrongName) + listener: handleRecoverableError(ConstructorWithWrongName, this, this) + listener: endClassConstructor(null, this, (, :, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + listener: endClassDeclaration(class, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(class) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(class, }, class, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseClassOrNamedMixinApplication(class, null, null, null, null, null, null, null, null, class) + listener: beginClassOrMixinOrNamedMixinApplicationPrelude(class) + ensureIdentifier(class, classOrMixinDeclaration) + listener: handleIdentifier(C3, classOrMixinDeclaration) + listener: handleNoTypeVariables(() + listener: beginClassDeclaration(class, null, null, null, null, null, null, null, null, C3) + parseClass(C3, class, class, null, C3) + parsePrimaryConstructorOpt(C3, null, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(C3, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, false) + parseClassHeaderOpt(), class, class) + parseClassExtendsOpt(), DeclarationHeaderKind.Class) + listener: handleNoType()) + listener: handleClassExtends(null, 1) + parseClassWithClauseOpt()) + listener: handleClassNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleClassHeader(class, class, null) + parseClassOrMixinOrExtensionBody(), DeclarationKind.Class, C3) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.Class, C3) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parseMethod({, null, null, null, null, null, null, null, {, NoType(), null, this, DeclarationKind.Class, C3, false) + listener: beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, C3) + listener: handleNoType({) + ensureIdentifierPotentiallyRecovered({, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.NonStaticMethod) + parseFormalParameters(this, MemberKind.NonStaticMethod) + parseFormalParametersRest((, MemberKind.NonStaticMethod) + listener: beginFormalParameters((, MemberKind.NonStaticMethod) + listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod) + parseInitializersOpt()) + listener: handleNoInitializers() + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: handleEmptyFunctionBody(;) + listener: endClassMethod(null, this, (, null, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + listener: endClassDeclaration(class, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(class) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(class, }, class, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseClassOrNamedMixinApplication(class, null, null, null, null, null, null, null, null, class) + listener: beginClassOrMixinOrNamedMixinApplicationPrelude(class) + ensureIdentifier(class, classOrMixinDeclaration) + listener: handleIdentifier(C4, classOrMixinDeclaration) + listener: handleNoTypeVariables(() + listener: beginClassDeclaration(class, null, null, null, null, null, null, null, null, C4) + parseClass(C4, class, class, null, C4) + parsePrimaryConstructorOpt(C4, null, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(C4, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, false) + parseClassHeaderOpt(), class, class) + parseClassExtendsOpt(), DeclarationHeaderKind.Class) + listener: handleNoType()) + listener: handleClassExtends(null, 1) + parseClassWithClauseOpt()) + listener: handleClassNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleClassHeader(class, class, null) + parseClassOrMixinOrExtensionBody(), DeclarationKind.Class, C4) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.Class, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.Class, C4) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parseMethod({, null, null, null, null, null, null, null, {, NoType(), null, this, DeclarationKind.Class, C4, false) + listener: beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, C4) + listener: handleNoType({) + ensureIdentifierPotentiallyRecovered({, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.NonStaticMethod) + parseFormalParameters(this, MemberKind.NonStaticMethod) + parseFormalParametersRest((, MemberKind.NonStaticMethod) + listener: beginFormalParameters((, MemberKind.NonStaticMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod) + parseInitializersOpt()) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: handleEmptyFunctionBody(;) + reportRecoverableError(this, ConstructorWithWrongName) + listener: handleRecoverableError(ConstructorWithWrongName, this, this) + listener: endClassConstructor(null, this, (, :, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 1, {, }) + listener: endClassDeclaration(class, }) + listener: endTopLevelDeclaration(}) + reportAllErrorTokens(class) + listener: endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.parser.expect b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.parser.expect new file mode 100644 index 0000000..8e768c1 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.parser.expect
@@ -0,0 +1,33 @@ +class C1() { +this() {} +} + +class C2() { +this(int x) : assert(1 > 2) {} +} + +class C3() { +this(); +} + +class C4() { +this(int x) : assert(1 > 2); +} + + +class[KeywordToken] C1[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C2[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C3[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C4[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.scanner.expect b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.scanner.expect new file mode 100644 index 0000000..8e768c1 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/class_primary_constructor_body_error.dart.scanner.expect
@@ -0,0 +1,33 @@ +class C1() { +this() {} +} + +class C2() { +this(int x) : assert(1 > 2) {} +} + +class C3() { +this(); +} + +class C4() { +this(int x) : assert(1 > 2); +} + + +class[KeywordToken] C1[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C2[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C3[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken] +}[SimpleToken] + +class[KeywordToken] C4[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart new file mode 100644 index 0000000..c0f080a --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart
@@ -0,0 +1,19 @@ +enum const E1() { + e; + this {} +} + +enum const E2() { + e; + this : assert(1 > 2) {} +} + +enum const E3() { + e; + this; +} + +enum const E4() { + e; + this : assert(1 > 2); +}
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.expect b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.expect new file mode 100644 index 0000000..177aac5 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.expect
@@ -0,0 +1,170 @@ +beginCompilationUnit(enum) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E1, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E1) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(e) + endMetadataStar(0) + handleIdentifier(e, enumValueDeclaration) + handleNoTypeNameInConstructorReference(;) + beginConstructorReference(e) + handleNoTypeArguments(;) + handleNoConstructorReferenceContinuationAfterTypeArguments(e) + endConstructorReference(e, null, e, ConstructorReferenceContext.Const) + handleNoArguments(e) + handleEnumElement({, null) + handleEnumElements(;, 1) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + handleNoInitializers() + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + endPrimaryConstructorBody(this, this, }) + endMember() + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 1, }) + endTopLevelDeclaration(}) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E2, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E2) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(e) + endMetadataStar(0) + handleIdentifier(e, enumValueDeclaration) + handleNoTypeNameInConstructorReference(;) + beginConstructorReference(e) + handleNoTypeArguments(;) + handleNoConstructorReferenceContinuationAfterTypeArguments(e) + endConstructorReference(e, null, e, ConstructorReferenceContext.Const) + handleNoArguments(e) + handleEnumElement({, null) + handleEnumElements(;, 1) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + endPrimaryConstructorBody(this, this, }) + endMember() + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 1, }) + endTopLevelDeclaration(}) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E3, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E3) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(e) + endMetadataStar(0) + handleIdentifier(e, enumValueDeclaration) + handleNoTypeNameInConstructorReference(;) + beginConstructorReference(e) + handleNoTypeArguments(;) + handleNoConstructorReferenceContinuationAfterTypeArguments(e) + endConstructorReference(e, null, e, ConstructorReferenceContext.Const) + handleNoArguments(e) + handleEnumElement({, null) + handleEnumElements(;, 1) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + handleNoInitializers() + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + endPrimaryConstructorBody(this, this, ;) + endMember() + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 1, }) + endTopLevelDeclaration(}) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E4, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E4) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(e) + endMetadataStar(0) + handleIdentifier(e, enumValueDeclaration) + handleNoTypeNameInConstructorReference(;) + beginConstructorReference(e) + handleNoTypeArguments(;) + handleNoConstructorReferenceContinuationAfterTypeArguments(e) + endConstructorReference(e, null, e, ConstructorReferenceContext.Const) + handleNoArguments(e) + handleEnumElement({, null) + handleEnumElements(;, 1) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + endPrimaryConstructorBody(this, this, ;) + endMember() + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 1, }) + endTopLevelDeclaration(}) +endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.intertwined.expect b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.intertwined.expect new file mode 100644 index 0000000..86fadf0 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.intertwined.expect
@@ -0,0 +1,300 @@ +parseUnit(enum) + skipErrorTokens(enum) + listener: beginCompilationUnit(enum) + syntheticPreviousToken(enum) + parseTopLevelDeclarationImpl(, DirectiveContext(DirectiveState.Unknown)) + parseMetadataStar() + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, , enum, null, null, null, null, DirectiveContext(DirectiveState.Unknown)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E1, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E1) + parsePrimaryConstructorOpt(E1, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E1, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(e) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + listener: handleIdentifier(e, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference(;) + listener: beginConstructorReference(e) + listener: handleNoTypeArguments(;) + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(e) + listener: endConstructorReference(e, null, e, ConstructorReferenceContext.Const) + listener: handleNoArguments(e) + listener: handleEnumElement({, null) + listener: handleEnumElements(;, 1) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl(;, DeclarationKind.Enum, E1) + parseMetadataStar(;) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + listener: handleNoInitializers() + parseAsyncModifierOpt(this) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(this, false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + listener: endPrimaryConstructorBody(this, this, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 1, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, }, enum, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E2, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E2) + parsePrimaryConstructorOpt(E2, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E2, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(e) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + listener: handleIdentifier(e, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference(;) + listener: beginConstructorReference(e) + listener: handleNoTypeArguments(;) + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(e) + listener: endConstructorReference(e, null, e, ConstructorReferenceContext.Const) + listener: handleNoArguments(e) + listener: handleEnumElement({, null) + listener: handleEnumElements(;, 1) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl(;, DeclarationKind.Enum, E2) + parseMetadataStar(;) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + listener: endPrimaryConstructorBody(this, this, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 1, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, }, enum, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E3, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E3) + parsePrimaryConstructorOpt(E3, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E3, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(e) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + listener: handleIdentifier(e, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference(;) + listener: beginConstructorReference(e) + listener: handleNoTypeArguments(;) + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(e) + listener: endConstructorReference(e, null, e, ConstructorReferenceContext.Const) + listener: handleNoArguments(e) + listener: handleEnumElement({, null) + listener: handleEnumElements(;, 1) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl(;, DeclarationKind.Enum, E3) + parseMetadataStar(;) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + listener: handleNoInitializers() + parseAsyncModifierOpt(this) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(this, false, true) + listener: handleEmptyFunctionBody(;) + listener: endPrimaryConstructorBody(this, this, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 1, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, }, enum, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E4, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E4) + parsePrimaryConstructorOpt(E4, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E4, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(e) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + listener: handleIdentifier(e, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference(;) + listener: beginConstructorReference(e) + listener: handleNoTypeArguments(;) + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(e) + listener: endConstructorReference(e, null, e, ConstructorReferenceContext.Const) + listener: handleNoArguments(e) + listener: handleEnumElement({, null) + listener: handleEnumElements(;, 1) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl(;, DeclarationKind.Enum, E4) + parseMetadataStar(;) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: handleEmptyFunctionBody(;) + listener: endPrimaryConstructorBody(this, this, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 1, }) + listener: endTopLevelDeclaration(}) + reportAllErrorTokens(enum) + listener: endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.parser.expect b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.parser.expect new file mode 100644 index 0000000..b4e1efd --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.parser.expect
@@ -0,0 +1,41 @@ +enum const E1() { +e; +this {} +} + +enum const E2() { +e; +this : assert(1 > 2) {} +} + +enum const E3() { +e; +this; +} + +enum const E4() { +e; +this : assert(1 > 2); +} + + +enum[KeywordToken] const[KeywordToken] E1[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +e[StringToken];[SimpleToken] +this[KeywordToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E2[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +e[StringToken];[SimpleToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E3[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +e[StringToken];[SimpleToken] +this[KeywordToken];[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E4[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +e[StringToken];[SimpleToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.scanner.expect b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.scanner.expect new file mode 100644 index 0000000..b4e1efd --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body.dart.scanner.expect
@@ -0,0 +1,41 @@ +enum const E1() { +e; +this {} +} + +enum const E2() { +e; +this : assert(1 > 2) {} +} + +enum const E3() { +e; +this; +} + +enum const E4() { +e; +this : assert(1 > 2); +} + + +enum[KeywordToken] const[KeywordToken] E1[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +e[StringToken];[SimpleToken] +this[KeywordToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E2[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +e[StringToken];[SimpleToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E3[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +e[StringToken];[SimpleToken] +this[KeywordToken];[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E4[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +e[StringToken];[SimpleToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart new file mode 100644 index 0000000..9853cc7 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart
@@ -0,0 +1,23 @@ +enum const E1() { + this() {} +} + +enum const E2() { + this(int x) : assert(1 > 2) {} +} + +enum const E3() { + this(); +} + +enum const E4() { + this(int x) : assert(1 > 2); +} + +enum const E5() { // missing constants + this : assert(1 > 2); +} + +enum const E6() { // missing constants + this {} +}
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.expect b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.expect new file mode 100644 index 0000000..5044ac0 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.expect
@@ -0,0 +1,257 @@ +Problems reported: + +parser/declaring_constructors/enum_primary_constructor_body_error:2:3: 'this' can't be used as an identifier because it's a keyword. + this() {} + ^^^^ + +parser/declaring_constructors/enum_primary_constructor_body_error:2:10: Expected '}' before this. + this() {} + ^ + +parser/declaring_constructors/enum_primary_constructor_body_error:6:3: 'this' can't be used as an identifier because it's a keyword. + this(int x) : assert(1 > 2) {} + ^^^^ + +parser/declaring_constructors/enum_primary_constructor_body_error:6:12: Expected ',' before this. + this(int x) : assert(1 > 2) {} + ^ + +parser/declaring_constructors/enum_primary_constructor_body_error:6:15: Expected '}' before this. + this(int x) : assert(1 > 2) {} + ^ + +parser/declaring_constructors/enum_primary_constructor_body_error:10:3: 'this' can't be used as an identifier because it's a keyword. + this(); + ^^^^ + +parser/declaring_constructors/enum_primary_constructor_body_error:14:3: 'this' can't be used as an identifier because it's a keyword. + this(int x) : assert(1 > 2); + ^^^^ + +parser/declaring_constructors/enum_primary_constructor_body_error:14:12: Expected ',' before this. + this(int x) : assert(1 > 2); + ^ + +parser/declaring_constructors/enum_primary_constructor_body_error:14:15: Expected '}' before this. + this(int x) : assert(1 > 2); + ^ + +parser/declaring_constructors/enum_primary_constructor_body_error:18:3: 'this' can't be used as an identifier because it's a keyword. + this : assert(1 > 2); + ^^^^ + +parser/declaring_constructors/enum_primary_constructor_body_error:18:8: Expected '}' before this. + this : assert(1 > 2); + ^ + +parser/declaring_constructors/enum_primary_constructor_body_error:22:3: 'this' can't be used as an identifier because it's a keyword. + this {} + ^^^^ + +parser/declaring_constructors/enum_primary_constructor_body_error:22:8: Expected '}' before this. + this {} + ^ + +beginCompilationUnit(enum) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E1, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E1) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(this) + endMetadataStar(0) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, enumValueDeclaration) + handleNoTypeNameInConstructorReference(() + beginConstructorReference(this) + handleNoTypeArguments(() + handleNoConstructorReferenceContinuationAfterTypeArguments(this) + endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + beginArguments(() + endArguments(0, (, )) + handleEnumElement({, null) + handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], {, {) + handleEnumElements(}, 1) + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 0, }) + endTopLevelDeclaration(}) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E2, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E2) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(this) + endMetadataStar(0) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, enumValueDeclaration) + handleNoTypeNameInConstructorReference(() + beginConstructorReference(this) + handleNoTypeArguments(() + handleNoConstructorReferenceContinuationAfterTypeArguments(this) + endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + beginArguments(() + handleIdentifier(int, expression) + handleNoTypeArguments(x) + handleNoArguments(x) + handleSend(int, int) + handleRecoverableError(Message[Template(ExpectedButGot), Expected ',' before this., null, {string: ,}], x, x) + handleIdentifier(x, expression) + handleNoTypeArguments()) + handleNoArguments()) + handleSend(x, x) + endArguments(2, (, )) + handleEnumElement({, null) + handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], :, :) + handleEnumElements(}, 1) + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 0, }) + endTopLevelDeclaration(}) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E3, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E3) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(this) + endMetadataStar(0) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, enumValueDeclaration) + handleNoTypeNameInConstructorReference(() + beginConstructorReference(this) + handleNoTypeArguments(() + handleNoConstructorReferenceContinuationAfterTypeArguments(this) + endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + beginArguments(() + endArguments(0, (, )) + handleEnumElement({, null) + handleEnumElements(;, 1) + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 0, }) + endTopLevelDeclaration(}) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E4, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E4) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(this) + endMetadataStar(0) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, enumValueDeclaration) + handleNoTypeNameInConstructorReference(() + beginConstructorReference(this) + handleNoTypeArguments(() + handleNoConstructorReferenceContinuationAfterTypeArguments(this) + endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + beginArguments(() + handleIdentifier(int, expression) + handleNoTypeArguments(x) + handleNoArguments(x) + handleSend(int, int) + handleRecoverableError(Message[Template(ExpectedButGot), Expected ',' before this., null, {string: ,}], x, x) + handleIdentifier(x, expression) + handleNoTypeArguments()) + handleNoArguments()) + handleSend(x, x) + endArguments(2, (, )) + handleEnumElement({, null) + handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], :, :) + handleEnumElements(}, 1) + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 0, }) + endTopLevelDeclaration(}) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E5, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E5) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(this) + endMetadataStar(0) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, enumValueDeclaration) + handleNoTypeNameInConstructorReference(:) + beginConstructorReference(this) + handleNoTypeArguments(:) + handleNoConstructorReferenceContinuationAfterTypeArguments(this) + endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + handleNoArguments(this) + handleEnumElement({, null) + handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], :, :) + handleEnumElements(}, 1) + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 0, }) + endTopLevelDeclaration(}) + beginMetadataStar(enum) + endMetadataStar(0) + beginEnumDeclarationPrelude(enum) + handleIdentifier(E6, enumDeclaration) + handleNoTypeVariables(() + beginEnumDeclaration(enum, null, enum, E6) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, const, false, false) + handleEnumNoWithClause() + handleImplements(null, 0) + handleEnumHeader(null, enum, {) + beginEnumBody({) + beginMetadataStar(this) + endMetadataStar(0) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, enumValueDeclaration) + handleNoTypeNameInConstructorReference({) + beginConstructorReference(this) + handleNoTypeArguments({) + handleNoConstructorReferenceContinuationAfterTypeArguments(this) + endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + handleNoArguments(this) + handleEnumElement({, null) + handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], {, {) + handleEnumElements(}, 1) + endEnumBody({, }) + endEnumDeclaration(enum, enum, {, 0, }) + endTopLevelDeclaration(}) +endCompilationUnit(6, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.intertwined.expect b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.intertwined.expect new file mode 100644 index 0000000..447685c --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.intertwined.expect
@@ -0,0 +1,343 @@ +parseUnit(enum) + skipErrorTokens(enum) + listener: beginCompilationUnit(enum) + syntheticPreviousToken(enum) + parseTopLevelDeclarationImpl(, DirectiveContext(DirectiveState.Unknown)) + parseMetadataStar() + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, , enum, null, null, null, null, DirectiveContext(DirectiveState.Unknown)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E1, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E1) + parsePrimaryConstructorOpt(E1, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E1, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference(() + listener: beginConstructorReference(this) + listener: handleNoTypeArguments(() + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(this) + listener: endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + parseConstructorInvocationArguments(this) + parseArgumentsRest(() + listener: beginArguments(() + listener: endArguments(0, (, )) + listener: handleEnumElement({, null) + reportRecoverableError({, Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}]) + listener: handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], {, {) + listener: handleEnumElements(}, 1) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 0, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, }, enum, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E2, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E2) + parsePrimaryConstructorOpt(E2, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E2, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference(() + listener: beginConstructorReference(this) + listener: handleNoTypeArguments(() + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(this) + listener: endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + parseConstructorInvocationArguments(this) + parseArgumentsRest(() + listener: beginArguments(() + allowedToShortcutParseExpression() + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + skipObjectPatternRest(int) + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + ensureIdentifier((, expression) + listener: handleIdentifier(int, expression) + listener: handleNoTypeArguments(x) + parseArgumentsOpt(int) + listener: handleNoArguments(x) + listener: handleSend(int, int) + rewriteAndRecover(int, Message[Template(ExpectedButGot), Expected ',' before this., null, {string: ,}], ,) + reportRecoverableError(x, Message[Template(ExpectedButGot), Expected ',' before this., null, {string: ,}]) + listener: handleRecoverableError(Message[Template(ExpectedButGot), Expected ',' before this., null, {string: ,}], x, x) + rewriter() + allowedToShortcutParseExpression() + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments()) + listener: handleNoArguments()) + listener: handleSend(x, x) + listener: endArguments(2, (, )) + listener: handleEnumElement({, null) + reportRecoverableError(:, Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}]) + listener: handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], :, :) + listener: handleEnumElements(}, 1) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 0, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, }, enum, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E3, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E3) + parsePrimaryConstructorOpt(E3, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E3, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference(() + listener: beginConstructorReference(this) + listener: handleNoTypeArguments(() + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(this) + listener: endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + parseConstructorInvocationArguments(this) + parseArgumentsRest(() + listener: beginArguments(() + listener: endArguments(0, (, )) + listener: handleEnumElement({, null) + listener: handleEnumElements(;, 1) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 0, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, }, enum, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E4, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E4) + parsePrimaryConstructorOpt(E4, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E4, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference(() + listener: beginConstructorReference(this) + listener: handleNoTypeArguments(() + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(this) + listener: endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + parseConstructorInvocationArguments(this) + parseArgumentsRest(() + listener: beginArguments(() + allowedToShortcutParseExpression() + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + skipObjectPatternRest(int) + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + ensureIdentifier((, expression) + listener: handleIdentifier(int, expression) + listener: handleNoTypeArguments(x) + parseArgumentsOpt(int) + listener: handleNoArguments(x) + listener: handleSend(int, int) + rewriteAndRecover(int, Message[Template(ExpectedButGot), Expected ',' before this., null, {string: ,}], ,) + reportRecoverableError(x, Message[Template(ExpectedButGot), Expected ',' before this., null, {string: ,}]) + listener: handleRecoverableError(Message[Template(ExpectedButGot), Expected ',' before this., null, {string: ,}], x, x) + rewriter() + allowedToShortcutParseExpression() + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments()) + listener: handleNoArguments()) + listener: handleSend(x, x) + listener: endArguments(2, (, )) + listener: handleEnumElement({, null) + reportRecoverableError(:, Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}]) + listener: handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], :, :) + listener: handleEnumElements(}, 1) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 0, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, }, enum, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E5, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E5) + parsePrimaryConstructorOpt(E5, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E5, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference(:) + listener: beginConstructorReference(this) + listener: handleNoTypeArguments(:) + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(this) + listener: endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + listener: handleNoArguments(this) + listener: handleEnumElement({, null) + reportRecoverableError(:, Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}]) + listener: handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], :, :) + listener: handleEnumElements(}, 1) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 0, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(enum) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(enum, }, enum, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseEnum(enum, null, enum) + listener: beginEnumDeclarationPrelude(enum) + ensureIdentifier(const, enumDeclaration) + listener: handleIdentifier(E6, enumDeclaration) + listener: handleNoTypeVariables(() + listener: beginEnumDeclaration(enum, null, enum, E6) + parsePrimaryConstructorOpt(E6, const, false) + listener: beginPrimaryConstructor(() + parseFormalParameters(E6, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + listener: endFormalParameters(0, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, const, false, false) + parseEnumHeaderOpt(), enum) + parseEnumWithClauseOpt()) + listener: handleEnumNoWithClause() + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + listener: handleEnumHeader(null, enum, {) + listener: beginEnumBody({) + parseEnumElement({) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + ensureIdentifier({, enumValueDeclaration) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, enumValueDeclaration) + listener: handleNoTypeNameInConstructorReference({) + listener: beginConstructorReference(this) + listener: handleNoTypeArguments({) + listener: handleNoConstructorReferenceContinuationAfterTypeArguments(this) + listener: endConstructorReference(this, null, this, ConstructorReferenceContext.Const) + listener: handleNoArguments(this) + listener: handleEnumElement({, null) + reportRecoverableError({, Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}]) + listener: handleRecoverableError(Message[Template(ExpectedButGot), Expected '}' before this., null, {string: }}], {, {) + listener: handleEnumElements(}, 1) + listener: endEnumBody({, }) + listener: endEnumDeclaration(enum, enum, {, 0, }) + listener: endTopLevelDeclaration(}) + reportAllErrorTokens(enum) + listener: endCompilationUnit(6, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.parser.expect b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.parser.expect new file mode 100644 index 0000000..dae1e1f --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.parser.expect
@@ -0,0 +1,51 @@ +NOTICE: Stream was rewritten by parser! + +enum const E1() { +this() {} +} + +enum const E2() { +this(int ,x) : assert(1 > 2) {} +} + +enum const E3() { +this(); +} + +enum const E4() { +this(int ,x) : assert(1 > 2); +} + +enum const E5() { +this : assert(1 > 2); +} + +enum const E6() { +this {} +} + + +enum[KeywordToken] const[KeywordToken] E1[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E2[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]int[StringToken] ,[SyntheticToken]x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E3[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E4[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]int[StringToken] ,[SyntheticToken]x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E5[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E6[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.scanner.expect b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.scanner.expect new file mode 100644 index 0000000..a26c6e3 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/enum_primary_constructor_body_error.dart.scanner.expect
@@ -0,0 +1,49 @@ +enum const E1() { +this() {} +} + +enum const E2() { +this(int x) : assert(1 > 2) {} +} + +enum const E3() { +this(); +} + +enum const E4() { +this(int x) : assert(1 > 2); +} + +enum const E5() { +this : assert(1 > 2); +} + +enum const E6() { +this {} +} + + +enum[KeywordToken] const[KeywordToken] E1[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E2[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E3[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E4[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E5[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] + +enum[KeywordToken] const[KeywordToken] E6[StringToken]([BeginToken])[SimpleToken] {[BeginToken] +this[KeywordToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart new file mode 100644 index 0000000..634e4a6 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart
@@ -0,0 +1,15 @@ +extension type E1(int x) { + this {} +} + +extension type E2(int x) { + this : assert(1 > 2) {} +} + +extension type E3(int x) { + this; +} + +extension type E4(int x) { + this : assert(1 > 2); +}
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.expect b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.expect new file mode 100644 index 0000000..8c3ed0a --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.expect
@@ -0,0 +1,150 @@ +beginCompilationUnit(extension) + beginMetadataStar(extension) + endMetadataStar(0) + beginExtensionDeclarationPrelude(extension) + handleNoTypeVariables(() + beginExtensionTypeDeclaration(null, extension, E1) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, true) + handleImplements(null, 0) + beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + handleNoInitializers() + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + endPrimaryConstructorBody(this, this, }) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + endExtensionTypeDeclaration(extension, null, extension, type, }) + endTopLevelDeclaration(}) + beginMetadataStar(extension) + endMetadataStar(0) + beginExtensionDeclarationPrelude(extension) + handleNoTypeVariables(() + beginExtensionTypeDeclaration(null, extension, E2) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, true) + handleImplements(null, 0) + beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + endPrimaryConstructorBody(this, this, }) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + endExtensionTypeDeclaration(extension, null, extension, type, }) + endTopLevelDeclaration(}) + beginMetadataStar(extension) + endMetadataStar(0) + beginExtensionDeclarationPrelude(extension) + handleNoTypeVariables(() + beginExtensionTypeDeclaration(null, extension, E3) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, true) + handleImplements(null, 0) + beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + handleNoInitializers() + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + endPrimaryConstructorBody(this, this, ;) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + endExtensionTypeDeclaration(extension, null, extension, type, }) + endTopLevelDeclaration(}) + beginMetadataStar(extension) + endMetadataStar(0) + beginExtensionDeclarationPrelude(extension) + handleNoTypeVariables(() + beginExtensionTypeDeclaration(null, extension, E4) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, true) + handleImplements(null, 0) + beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginPrimaryConstructorBody(this) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + endPrimaryConstructorBody(this, this, ;) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + endExtensionTypeDeclaration(extension, null, extension, type, }) + endTopLevelDeclaration(}) +endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.intertwined.expect b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.intertwined.expect new file mode 100644 index 0000000..0476cda --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.intertwined.expect
@@ -0,0 +1,276 @@ +parseUnit(extension) + skipErrorTokens(extension) + listener: beginCompilationUnit(extension) + syntheticPreviousToken(extension) + parseTopLevelDeclarationImpl(, DirectiveContext(DirectiveState.Unknown)) + parseMetadataStar() + listener: beginMetadataStar(extension) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(extension, , extension, null, null, null, null, DirectiveContext(DirectiveState.Unknown)) + parseExtension(extension, null, extension) + listener: beginExtensionDeclarationPrelude(extension) + parseExtensionTypeDeclaration(extension, type, null, extension, type) + listener: handleNoTypeVariables(() + listener: beginExtensionTypeDeclaration(null, extension, E1) + parsePrimaryConstructorOpt(E1, null, true) + listener: beginPrimaryConstructor(() + parseFormalParameters(E1, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + listener: endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, true) + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + parseClassOrMixinOrExtensionBody(), DeclarationKind.ExtensionType, E1) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.ExtensionType, E1) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + listener: handleNoInitializers() + parseAsyncModifierOpt(this) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(this, false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + listener: endPrimaryConstructorBody(this, this, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + listener: endExtensionTypeDeclaration(extension, null, extension, type, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(extension) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(extension, }, extension, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseExtension(extension, null, extension) + listener: beginExtensionDeclarationPrelude(extension) + parseExtensionTypeDeclaration(extension, type, null, extension, type) + listener: handleNoTypeVariables(() + listener: beginExtensionTypeDeclaration(null, extension, E2) + parsePrimaryConstructorOpt(E2, null, true) + listener: beginPrimaryConstructor(() + parseFormalParameters(E2, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + listener: endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, true) + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + parseClassOrMixinOrExtensionBody(), DeclarationKind.ExtensionType, E2) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.ExtensionType, E2) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + listener: endPrimaryConstructorBody(this, this, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + listener: endExtensionTypeDeclaration(extension, null, extension, type, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(extension) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(extension, }, extension, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseExtension(extension, null, extension) + listener: beginExtensionDeclarationPrelude(extension) + parseExtensionTypeDeclaration(extension, type, null, extension, type) + listener: handleNoTypeVariables(() + listener: beginExtensionTypeDeclaration(null, extension, E3) + parsePrimaryConstructorOpt(E3, null, true) + listener: beginPrimaryConstructor(() + parseFormalParameters(E3, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + listener: endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, true) + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + parseClassOrMixinOrExtensionBody(), DeclarationKind.ExtensionType, E3) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.ExtensionType, E3) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + listener: handleNoInitializers() + parseAsyncModifierOpt(this) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(this, false, true) + listener: handleEmptyFunctionBody(;) + listener: endPrimaryConstructorBody(this, this, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + listener: endExtensionTypeDeclaration(extension, null, extension, type, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(extension) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(extension, }, extension, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseExtension(extension, null, extension) + listener: beginExtensionDeclarationPrelude(extension) + parseExtensionTypeDeclaration(extension, type, null, extension, type) + listener: handleNoTypeVariables(() + listener: beginExtensionTypeDeclaration(null, extension, E4) + parsePrimaryConstructorOpt(E4, null, true) + listener: beginPrimaryConstructor(() + parseFormalParameters(E4, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + listener: endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, true) + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + parseClassOrMixinOrExtensionBody(), DeclarationKind.ExtensionType, E4) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.ExtensionType, E4) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parsePrimaryConstructorBody(this) + listener: beginPrimaryConstructorBody(this) + parseInitializersOpt(this) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: handleEmptyFunctionBody(;) + listener: endPrimaryConstructorBody(this, this, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + listener: endExtensionTypeDeclaration(extension, null, extension, type, }) + listener: endTopLevelDeclaration(}) + reportAllErrorTokens(extension) + listener: endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.parser.expect b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.parser.expect new file mode 100644 index 0000000..7ea6456 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.parser.expect
@@ -0,0 +1,33 @@ +extension type E1(int x) { +this {} +} + +extension type E2(int x) { +this : assert(1 > 2) {} +} + +extension type E3(int x) { +this; +} + +extension type E4(int x) { +this : assert(1 > 2); +} + + +extension[KeywordToken] type[StringToken] E1[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E2[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E3[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken];[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E4[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.scanner.expect b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.scanner.expect new file mode 100644 index 0000000..7ea6456 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body.dart.scanner.expect
@@ -0,0 +1,33 @@ +extension type E1(int x) { +this {} +} + +extension type E2(int x) { +this : assert(1 > 2) {} +} + +extension type E3(int x) { +this; +} + +extension type E4(int x) { +this : assert(1 > 2); +} + + +extension[KeywordToken] type[StringToken] E1[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E2[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E3[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken];[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E4[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart new file mode 100644 index 0000000..ef6f47b --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart
@@ -0,0 +1,15 @@ +extension type E1(int x) { + this(this.x) {} +} + +extension type E2(int x) { + this(this.x) : assert(1 > 2) {} +} + +extension type E3(int x) { + this(this.x) ; +} + +extension type E4(int x) { + this(this.x) : assert(1 > 2); +}
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.expect b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.expect new file mode 100644 index 0000000..ec736b2 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.expect
@@ -0,0 +1,235 @@ +Problems reported: + +parser/declaring_constructors/extension_type_primary_constructor_body_error:2:3: 'this' can't be used as an identifier because it's a keyword. + this(this.x) {} + ^^^^ + +parser/declaring_constructors/extension_type_primary_constructor_body_error:6:3: 'this' can't be used as an identifier because it's a keyword. + this(this.x) : assert(1 > 2) {} + ^^^^ + +parser/declaring_constructors/extension_type_primary_constructor_body_error:6:3: The name of a constructor must match the name of the enclosing class. + this(this.x) : assert(1 > 2) {} + ^^^^ + +parser/declaring_constructors/extension_type_primary_constructor_body_error:10:3: 'this' can't be used as an identifier because it's a keyword. + this(this.x) ; + ^^^^ + +parser/declaring_constructors/extension_type_primary_constructor_body_error:10:3: Extension types can't declare abstract members. + this(this.x) ; + ^^^^ + +parser/declaring_constructors/extension_type_primary_constructor_body_error:14:3: 'this' can't be used as an identifier because it's a keyword. + this(this.x) : assert(1 > 2); + ^^^^ + +parser/declaring_constructors/extension_type_primary_constructor_body_error:14:3: The name of a constructor must match the name of the enclosing class. + this(this.x) : assert(1 > 2); + ^^^^ + +beginCompilationUnit(extension) + beginMetadataStar(extension) + endMetadataStar(0) + beginExtensionDeclarationPrelude(extension) + handleNoTypeVariables(() + beginExtensionTypeDeclaration(null, extension, E1) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, true) + handleImplements(null, 0) + beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginMethod(DeclarationKind.ExtensionType, null, null, null, null, null, null, this, E1) + handleNoType({) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, methodDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.ExtensionTypeNonStaticMethod) + beginMetadataStar(this) + endMetadataStar(0) + beginFormalParameter(this, MemberKind.ExtensionTypeNonStaticMethod, null, null, null) + handleNoType(() + handleIdentifier(x, fieldInitializer) + handleFormalParameterWithoutValue()) + endFormalParameter(null, this, null, ., x, null, null, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + endFormalParameters(1, (, ), MemberKind.ExtensionTypeNonStaticMethod) + handleNoInitializers() + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + endExtensionTypeMethod(null, this, (, null, }) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + endExtensionTypeDeclaration(extension, null, extension, type, }) + endTopLevelDeclaration(}) + beginMetadataStar(extension) + endMetadataStar(0) + beginExtensionDeclarationPrelude(extension) + handleNoTypeVariables(() + beginExtensionTypeDeclaration(null, extension, E2) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, true) + handleImplements(null, 0) + beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginMethod(DeclarationKind.ExtensionType, null, null, null, null, null, null, this, E2) + handleNoType({) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, methodDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.ExtensionTypeNonStaticMethod) + beginMetadataStar(this) + endMetadataStar(0) + beginFormalParameter(this, MemberKind.ExtensionTypeNonStaticMethod, null, null, null) + handleNoType(() + handleIdentifier(x, fieldInitializer) + handleFormalParameterWithoutValue()) + endFormalParameter(null, this, null, ., x, null, null, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + endFormalParameters(1, (, ), MemberKind.ExtensionTypeNonStaticMethod) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + beginBlockFunctionBody({) + endBlockFunctionBody(0, {, }) + handleRecoverableError(ConstructorWithWrongName, this, this) + endExtensionTypeConstructor(null, this, (, :, }) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + endExtensionTypeDeclaration(extension, null, extension, type, }) + endTopLevelDeclaration(}) + beginMetadataStar(extension) + endMetadataStar(0) + beginExtensionDeclarationPrelude(extension) + handleNoTypeVariables(() + beginExtensionTypeDeclaration(null, extension, E3) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, true) + handleImplements(null, 0) + beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginMethod(DeclarationKind.ExtensionType, null, null, null, null, null, null, this, E3) + handleNoType({) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, methodDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.ExtensionTypeNonStaticMethod) + beginMetadataStar(this) + endMetadataStar(0) + beginFormalParameter(this, MemberKind.ExtensionTypeNonStaticMethod, null, null, null) + handleNoType(() + handleIdentifier(x, fieldInitializer) + handleFormalParameterWithoutValue()) + endFormalParameter(null, this, null, ., x, null, null, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + endFormalParameters(1, (, ), MemberKind.ExtensionTypeNonStaticMethod) + handleNoInitializers() + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + handleRecoverableError(ExtensionTypeDeclaresAbstractMember, this, this) + endExtensionTypeMethod(null, this, (, null, ;) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + endExtensionTypeDeclaration(extension, null, extension, type, }) + endTopLevelDeclaration(}) + beginMetadataStar(extension) + endMetadataStar(0) + beginExtensionDeclarationPrelude(extension) + handleNoTypeVariables(() + beginExtensionTypeDeclaration(null, extension, E4) + beginPrimaryConstructor(() + beginFormalParameters((, MemberKind.PrimaryConstructor) + beginMetadataStar(int) + endMetadataStar(0) + beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + handleIdentifier(int, typeReference) + handleNoTypeArguments(x) + handleType(int, null) + handleIdentifier(x, formalParameterDeclaration) + handleFormalParameterWithoutValue()) + endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + endPrimaryConstructor((, null, false, true) + handleImplements(null, 0) + beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + beginMetadataStar(this) + endMetadataStar(0) + beginMember() + beginMethod(DeclarationKind.ExtensionType, null, null, null, null, null, null, this, E4) + handleNoType({) + handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + handleIdentifier(this, methodDeclaration) + handleNoTypeVariables(() + beginFormalParameters((, MemberKind.ExtensionTypeNonStaticMethod) + beginMetadataStar(this) + endMetadataStar(0) + beginFormalParameter(this, MemberKind.ExtensionTypeNonStaticMethod, null, null, null) + handleNoType(() + handleIdentifier(x, fieldInitializer) + handleFormalParameterWithoutValue()) + endFormalParameter(null, this, null, ., x, null, null, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + endFormalParameters(1, (, ), MemberKind.ExtensionTypeNonStaticMethod) + beginInitializers(:) + beginInitializer(assert) + beginAssert(assert, Assert.Initializer) + handleLiteralInt(1) + beginBinaryExpression(>) + handleLiteralInt(2) + endBinaryExpression(>, 2) + endAssert(assert, Assert.Initializer, (, null, )) + endInitializer()) + endInitializers(1, :, )) + handleAsyncModifier(null, null) + handleEmptyFunctionBody(;) + handleRecoverableError(ConstructorWithWrongName, this, this) + endExtensionTypeConstructor(null, this, (, :, ;) + endMember() + endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + endExtensionTypeDeclaration(extension, null, extension, type, }) + endTopLevelDeclaration(}) +endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.intertwined.expect b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.intertwined.expect new file mode 100644 index 0000000..8166699 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.intertwined.expect
@@ -0,0 +1,374 @@ +parseUnit(extension) + skipErrorTokens(extension) + listener: beginCompilationUnit(extension) + syntheticPreviousToken(extension) + parseTopLevelDeclarationImpl(, DirectiveContext(DirectiveState.Unknown)) + parseMetadataStar() + listener: beginMetadataStar(extension) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(extension, , extension, null, null, null, null, DirectiveContext(DirectiveState.Unknown)) + parseExtension(extension, null, extension) + listener: beginExtensionDeclarationPrelude(extension) + parseExtensionTypeDeclaration(extension, type, null, extension, type) + listener: handleNoTypeVariables(() + listener: beginExtensionTypeDeclaration(null, extension, E1) + parsePrimaryConstructorOpt(E1, null, true) + listener: beginPrimaryConstructor(() + parseFormalParameters(E1, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + listener: endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, true) + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + parseClassOrMixinOrExtensionBody(), DeclarationKind.ExtensionType, E1) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.ExtensionType, E1) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parseMethod({, null, null, null, null, null, null, null, {, NoType(), null, this, DeclarationKind.ExtensionType, E1, false) + listener: beginMethod(DeclarationKind.ExtensionType, null, null, null, null, null, null, this, E1) + listener: handleNoType({) + ensureIdentifierPotentiallyRecovered({, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParameters(this, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParametersRest((, MemberKind.ExtensionTypeNonStaticMethod) + listener: beginFormalParameters((, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + parseMetadataStar(() + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginFormalParameter(this, MemberKind.ExtensionTypeNonStaticMethod, null, null, null) + listener: handleNoType(() + ensureIdentifier(., fieldInitializer) + listener: handleIdentifier(x, fieldInitializer) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, this, null, ., x, null, null, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + listener: endFormalParameters(1, (, ), MemberKind.ExtensionTypeNonStaticMethod) + parseInitializersOpt()) + listener: handleNoInitializers() + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + listener: endExtensionTypeMethod(null, this, (, null, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + listener: endExtensionTypeDeclaration(extension, null, extension, type, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(extension) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(extension, }, extension, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseExtension(extension, null, extension) + listener: beginExtensionDeclarationPrelude(extension) + parseExtensionTypeDeclaration(extension, type, null, extension, type) + listener: handleNoTypeVariables(() + listener: beginExtensionTypeDeclaration(null, extension, E2) + parsePrimaryConstructorOpt(E2, null, true) + listener: beginPrimaryConstructor(() + parseFormalParameters(E2, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + listener: endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, true) + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + parseClassOrMixinOrExtensionBody(), DeclarationKind.ExtensionType, E2) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.ExtensionType, E2) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parseMethod({, null, null, null, null, null, null, null, {, NoType(), null, this, DeclarationKind.ExtensionType, E2, false) + listener: beginMethod(DeclarationKind.ExtensionType, null, null, null, null, null, null, this, E2) + listener: handleNoType({) + ensureIdentifierPotentiallyRecovered({, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParameters(this, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParametersRest((, MemberKind.ExtensionTypeNonStaticMethod) + listener: beginFormalParameters((, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + parseMetadataStar(() + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginFormalParameter(this, MemberKind.ExtensionTypeNonStaticMethod, null, null, null) + listener: handleNoType(() + ensureIdentifier(., fieldInitializer) + listener: handleIdentifier(x, fieldInitializer) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, this, null, ., x, null, null, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + listener: endFormalParameters(1, (, ), MemberKind.ExtensionTypeNonStaticMethod) + parseInitializersOpt()) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(0, {, }) + reportRecoverableError(this, ConstructorWithWrongName) + listener: handleRecoverableError(ConstructorWithWrongName, this, this) + listener: endExtensionTypeConstructor(null, this, (, :, }) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + listener: endExtensionTypeDeclaration(extension, null, extension, type, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(extension) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(extension, }, extension, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseExtension(extension, null, extension) + listener: beginExtensionDeclarationPrelude(extension) + parseExtensionTypeDeclaration(extension, type, null, extension, type) + listener: handleNoTypeVariables(() + listener: beginExtensionTypeDeclaration(null, extension, E3) + parsePrimaryConstructorOpt(E3, null, true) + listener: beginPrimaryConstructor(() + parseFormalParameters(E3, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + listener: endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, true) + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + parseClassOrMixinOrExtensionBody(), DeclarationKind.ExtensionType, E3) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.ExtensionType, E3) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parseMethod({, null, null, null, null, null, null, null, {, NoType(), null, this, DeclarationKind.ExtensionType, E3, false) + listener: beginMethod(DeclarationKind.ExtensionType, null, null, null, null, null, null, this, E3) + listener: handleNoType({) + ensureIdentifierPotentiallyRecovered({, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParameters(this, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParametersRest((, MemberKind.ExtensionTypeNonStaticMethod) + listener: beginFormalParameters((, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + parseMetadataStar(() + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginFormalParameter(this, MemberKind.ExtensionTypeNonStaticMethod, null, null, null) + listener: handleNoType(() + ensureIdentifier(., fieldInitializer) + listener: handleIdentifier(x, fieldInitializer) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, this, null, ., x, null, null, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + listener: endFormalParameters(1, (, ), MemberKind.ExtensionTypeNonStaticMethod) + parseInitializersOpt()) + listener: handleNoInitializers() + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: handleEmptyFunctionBody(;) + reportRecoverableError(this, ExtensionTypeDeclaresAbstractMember) + listener: handleRecoverableError(ExtensionTypeDeclaresAbstractMember, this, this) + listener: endExtensionTypeMethod(null, this, (, null, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + listener: endExtensionTypeDeclaration(extension, null, extension, type, }) + listener: endTopLevelDeclaration(}) + parseTopLevelDeclarationImpl(}, DirectiveContext(DirectiveState.Declarations)) + parseMetadataStar(}) + listener: beginMetadataStar(extension) + listener: endMetadataStar(0) + parseTopLevelKeywordDeclaration(extension, }, extension, null, null, null, null, DirectiveContext(DirectiveState.Declarations)) + parseExtension(extension, null, extension) + listener: beginExtensionDeclarationPrelude(extension) + parseExtensionTypeDeclaration(extension, type, null, extension, type) + listener: handleNoTypeVariables(() + listener: beginExtensionTypeDeclaration(null, extension, E4) + parsePrimaryConstructorOpt(E4, null, true) + listener: beginPrimaryConstructor(() + parseFormalParameters(E4, MemberKind.PrimaryConstructor) + parseFormalParametersRest((, MemberKind.PrimaryConstructor) + listener: beginFormalParameters((, MemberKind.PrimaryConstructor) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.PrimaryConstructor, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.PrimaryConstructor) + listener: endFormalParameters(1, (, ), MemberKind.PrimaryConstructor) + listener: endPrimaryConstructor((, null, false, true) + parseClassOrMixinOrEnumImplementsOpt()) + listener: handleImplements(null, 0) + parseClassOrMixinOrExtensionBody(), DeclarationKind.ExtensionType, E4) + listener: beginClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, {) + notEofOrType(CLOSE_CURLY_BRACKET, this) + parseClassOrMixinOrExtensionOrEnumMemberImpl({, DeclarationKind.ExtensionType, E4) + parseMetadataStar({) + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginMember() + parseMethod({, null, null, null, null, null, null, null, {, NoType(), null, this, DeclarationKind.ExtensionType, E4, false) + listener: beginMethod(DeclarationKind.ExtensionType, null, null, null, null, null, null, this, E4) + listener: handleNoType({) + ensureIdentifierPotentiallyRecovered({, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParameters(this, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParametersRest((, MemberKind.ExtensionTypeNonStaticMethod) + listener: beginFormalParameters((, MemberKind.ExtensionTypeNonStaticMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + parseMetadataStar(() + listener: beginMetadataStar(this) + listener: endMetadataStar(0) + listener: beginFormalParameter(this, MemberKind.ExtensionTypeNonStaticMethod, null, null, null) + listener: handleNoType(() + ensureIdentifier(., fieldInitializer) + listener: handleIdentifier(x, fieldInitializer) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, this, null, ., x, null, null, FormalParameterKind.requiredPositional, MemberKind.ExtensionTypeNonStaticMethod) + listener: endFormalParameters(1, (, ), MemberKind.ExtensionTypeNonStaticMethod) + parseInitializersOpt()) + parseInitializers(:) + listener: beginInitializers(:) + parseInitializer(:) + listener: beginInitializer(assert) + parseAssert(:, Assert.Initializer) + listener: beginAssert(assert, Assert.Initializer) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseLiteralInt(() + listener: handleLiteralInt(1) + listener: beginBinaryExpression(>) + parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none) + parseUnaryExpression(>, true, ConstantPatternContext.none) + parsePrimary(>, expression, ConstantPatternContext.none) + parseLiteralInt(>) + listener: handleLiteralInt(2) + listener: endBinaryExpression(>, 2) + listener: endAssert(assert, Assert.Initializer, (, null, )) + listener: endInitializer()) + listener: endInitializers(1, :, )) + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) + inPlainSync() + inPlainSync() + parseFunctionBody(), false, true) + listener: handleEmptyFunctionBody(;) + reportRecoverableError(this, ConstructorWithWrongName) + listener: handleRecoverableError(ConstructorWithWrongName, this, this) + listener: endExtensionTypeConstructor(null, this, (, :, ;) + listener: endMember() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.ExtensionType, 1, {, }) + listener: endExtensionTypeDeclaration(extension, null, extension, type, }) + listener: endTopLevelDeclaration(}) + reportAllErrorTokens(extension) + listener: endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.parser.expect b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.parser.expect new file mode 100644 index 0000000..5246fe9 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.parser.expect
@@ -0,0 +1,33 @@ +extension type E1(int x) { +this(this.x) {} +} + +extension type E2(int x) { +this(this.x) : assert(1 > 2) {} +} + +extension type E3(int x) { +this(this.x) ; +} + +extension type E4(int x) { +this(this.x) : assert(1 > 2); +} + + +extension[KeywordToken] type[StringToken] E1[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]this[KeywordToken].[SimpleToken]x[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E2[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]this[KeywordToken].[SimpleToken]x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E3[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]this[KeywordToken].[SimpleToken]x[StringToken])[SimpleToken] ;[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E4[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]this[KeywordToken].[SimpleToken]x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.scanner.expect b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.scanner.expect new file mode 100644 index 0000000..5246fe9 --- /dev/null +++ b/pkg/front_end/parser_testcases/declaring_constructors/extension_type_primary_constructor_body_error.dart.scanner.expect
@@ -0,0 +1,33 @@ +extension type E1(int x) { +this(this.x) {} +} + +extension type E2(int x) { +this(this.x) : assert(1 > 2) {} +} + +extension type E3(int x) { +this(this.x) ; +} + +extension type E4(int x) { +this(this.x) : assert(1 > 2); +} + + +extension[KeywordToken] type[StringToken] E1[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]this[KeywordToken].[SimpleToken]x[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E2[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]this[KeywordToken].[SimpleToken]x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E3[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]this[KeywordToken].[SimpleToken]x[StringToken])[SimpleToken] ;[SimpleToken] +}[SimpleToken] + +extension[KeywordToken] type[StringToken] E4[StringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +this[KeywordToken]([BeginToken]this[KeywordToken].[SimpleToken]x[StringToken])[SimpleToken] :[SimpleToken] assert[KeywordToken]([BeginToken]1[StringToken] >[SimpleToken] 2[StringToken])[SimpleToken];[SimpleToken] +}[SimpleToken] +[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect index 5e92672..e0fa28e 100644 --- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect +++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect
@@ -1669,29 +1669,28 @@ listener: beginMetadataStar(int) listener: endMetadataStar(0) listener: beginMember() - recoverFromInvalidMember(int, ;, null, null, null, null, null, null, null, ;, SimpleType(), null, DeclarationKind.Class, WrapperClass) - parseFields(;, null, null, null, null, null, null, null, ;, SimpleType(), this, DeclarationKind.Class, WrapperClass, false) - listener: beginFields(DeclarationKind.Class, null, null, null, null, null, null, null, ;) - listener: handleIdentifier(int, typeReference) - listener: handleNoTypeArguments(this) - listener: handleType(int, null) - ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false) - reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) - listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) - listener: handleIdentifier(this, fieldDeclaration) - parseFieldInitializerOpt(this, this, null, null, null, null, null, DeclarationKind.Class, WrapperClass) - listener: beginFieldInitializer(=) - parseExpression(=) - looksLikeOuterPatternEquals(=) - skipOuterPattern(=) - parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none) - parseUnaryExpression(=, true, ConstantPatternContext.none) - parsePrimary(=, expression, ConstantPatternContext.none) - parseLiteralInt(=) - listener: handleLiteralInt(42) - listener: endFieldInitializer(=, 42) - listener: endClassFields(null, null, null, null, null, null, null, 1, int, ;) - listener: endMember() + parseFields(;, null, null, null, null, null, null, null, ;, SimpleType(), this, DeclarationKind.Class, WrapperClass, false) + listener: beginFields(DeclarationKind.Class, null, null, null, null, null, null, null, ;) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(this) + listener: handleType(int, null) + ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, fieldDeclaration) + parseFieldInitializerOpt(this, this, null, null, null, null, null, DeclarationKind.Class, WrapperClass) + listener: beginFieldInitializer(=) + parseExpression(=) + looksLikeOuterPatternEquals(=) + skipOuterPattern(=) + parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none) + parseUnaryExpression(=, true, ConstantPatternContext.none) + parsePrimary(=, expression, ConstantPatternContext.none) + parseLiteralInt(=) + listener: handleLiteralInt(42) + listener: endFieldInitializer(=, 42) + listener: endClassFields(null, null, null, null, null, null, null, 1, int, ;) + listener: endMember() notEofOrType(CLOSE_CURLY_BRACKET, int) parseClassOrMixinOrExtensionOrEnumMemberImpl(;, DeclarationKind.Class, WrapperClass) parseMetadataStar(;)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect index 77ffd9b..0fff1e6 100644 --- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect +++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect
@@ -348,14 +348,6 @@ int this(int x) { ^^^^ -parser/error_recovery/keyword_named_class_methods:298:7: Expected ';' after this. - int this(int x) { - ^^^^ - -parser/error_recovery/keyword_named_class_methods:298:11: Expected an identifier, but got '('. - int this(int x) { - ^ - parser/error_recovery/keyword_named_class_methods:303:7: 'throw' can't be used as an identifier because it's a keyword. int throw(int x) { ^^^^^ @@ -4105,23 +4097,12 @@ beginMetadataStar(int) endMetadataStar(0) beginMember() - beginFields(DeclarationKind.Class, null, null, null, null, null, null, null, }) + beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, WrapperClass) handleIdentifier(int, typeReference) handleNoTypeArguments(this) handleType(int, null) handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) - handleIdentifier(this, fieldDeclaration) - handleNoFieldInitializer(() - handleRecoverableError(Message[Template(ExpectedAfterButGot), Expected ';' after this., null, {string: ;}], this, this) - endClassFields(null, null, null, null, null, null, null, 1, int, ;) - endMember() - beginMetadataStar(() - endMetadataStar(0) - beginMember() - beginMethod(DeclarationKind.Class, null, null, null, null, null, null, (, WrapperClass) - handleNoType(;) - handleRecoverableError(Message[Template(ExpectedIdentifier), Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, () - handleIdentifier(, methodDeclaration) + handleIdentifier(this, methodDeclaration) handleNoTypeVariables(() beginFormalParameters((, MemberKind.NonStaticMethod) beginMetadataStar(int) @@ -4170,7 +4151,7 @@ endBinaryExpression(+, 1) endReturnStatement(true, return, ;) endBlockFunctionBody(2, {, }) - endClassMethod(null, , (, null, }) + endClassMethod(null, int, (, null, }) endMember() beginMetadataStar(int) endMetadataStar(0) @@ -4778,7 +4759,7 @@ endBlockFunctionBody(2, {, }) endClassMethod(null, int, (, null, }) endMember() - endClassOrMixinOrExtensionBody(DeclarationKind.Class, 71, {, }) + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 70, {, }) endClassDeclaration(class, }) endTopLevelDeclaration(}) endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect index 00bd591..eafcd09 100644 --- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect +++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect
@@ -8915,163 +8915,138 @@ listener: beginMetadataStar(int) listener: endMetadataStar(0) listener: beginMember() - recoverFromInvalidMember(int, }, null, null, null, null, null, null, null, }, SimpleType(), null, DeclarationKind.Class, WrapperClass) - parseFields(}, null, null, null, null, null, null, null, }, SimpleType(), this, DeclarationKind.Class, WrapperClass, false) - listener: beginFields(DeclarationKind.Class, null, null, null, null, null, null, null, }) - listener: handleIdentifier(int, typeReference) - listener: handleNoTypeArguments(this) - listener: handleType(int, null) - ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false) - reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) - listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) - listener: handleIdentifier(this, fieldDeclaration) - parseFieldInitializerOpt(this, this, null, null, null, null, null, DeclarationKind.Class, WrapperClass) - listener: handleNoFieldInitializer(() - ensureSemicolon(this) - reportRecoverableError(this, Message[Template(ExpectedAfterButGot), Expected ';' after this., null, {string: ;}]) - listener: handleRecoverableError(Message[Template(ExpectedAfterButGot), Expected ';' after this., null, {string: ;}], this, this) - rewriter() - listener: endClassFields(null, null, null, null, null, null, null, 1, int, ;) - listener: endMember() - notEofOrType(CLOSE_CURLY_BRACKET, () - parseClassOrMixinOrExtensionOrEnumMemberImpl(;, DeclarationKind.Class, WrapperClass) - parseMetadataStar(;) - listener: beginMetadataStar(() - listener: endMetadataStar(0) - listener: beginMember() - recoverFromInvalidMember(;, ;, null, null, null, null, null, null, null, ;, NoType(), null, DeclarationKind.Class, WrapperClass) - parseMethod(;, null, null, null, null, null, null, null, ;, NoType(), null, (, DeclarationKind.Class, WrapperClass, false) - listener: beginMethod(DeclarationKind.Class, null, null, null, null, null, null, (, WrapperClass) - listener: handleNoType(;) - ensureIdentifierPotentiallyRecovered(;, methodDeclaration, false) - insertSyntheticIdentifier(;, methodDeclaration, message: null, messageOnToken: null) - reportRecoverableError((, Message[Template(ExpectedIdentifier), Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}]) - listener: handleRecoverableError(Message[Template(ExpectedIdentifier), Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, () - rewriter() - listener: handleIdentifier(, methodDeclaration) - parseQualifiedRestOpt(, methodDeclarationContinuation) - parseMethodTypeVar() - listener: handleNoTypeVariables(() - parseGetterOrFormalParameters(, (, false, MemberKind.NonStaticMethod) - parseFormalParameters(, MemberKind.NonStaticMethod) - parseFormalParametersRest((, MemberKind.NonStaticMethod) - listener: beginFormalParameters((, MemberKind.NonStaticMethod) - parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) - parseMetadataStar(() - listener: beginMetadataStar(int) - listener: endMetadataStar(0) - listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null) - listener: handleIdentifier(int, typeReference) - listener: handleNoTypeArguments(x) - listener: handleType(int, null) - ensureIdentifier(int, formalParameterDeclaration) - listener: handleIdentifier(x, formalParameterDeclaration) - listener: handleFormalParameterWithoutValue()) - listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) - listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod) - parseInitializersOpt()) - listener: handleNoInitializers() - parseAsyncModifierOpt()) - listener: handleAsyncModifier(null, null) - inPlainSync() + parseMethod(}, null, null, null, null, null, null, null, }, SimpleType(), null, this, DeclarationKind.Class, WrapperClass, false) + listener: beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, WrapperClass) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(this) + listener: handleType(int, null) + ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.NonStaticMethod) + parseFormalParameters(this, MemberKind.NonStaticMethod) + parseFormalParametersRest((, MemberKind.NonStaticMethod) + listener: beginFormalParameters((, MemberKind.NonStaticMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod) + parseInitializersOpt()) + listener: handleNoInitializers() + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) inPlainSync() - parseFunctionBody(), false, true) - listener: beginBlockFunctionBody({) - notEofOrType(CLOSE_CURLY_BRACKET, if) - parseStatement({) - parseStatementX({) - parseIfStatement({) - listener: beginIfStatement(if) - ensureParenthesizedCondition(if, allowCase: false) - parseExpressionInParenthesisRest((, allowCase: false) - parseExpression(() - parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) - parseUnaryExpression((, true, ConstantPatternContext.none) - parsePrimary((, expression, ConstantPatternContext.none) - parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) - parseSend((, expression, ConstantPatternContext.none) - ensureIdentifier((, expression) - listener: handleIdentifier(x, expression) - listener: handleNoTypeArguments(==) - parseArgumentsOpt(x) - listener: handleNoArguments(==) - listener: handleSend(x, x) - listener: beginBinaryExpression(==) - parsePrecedenceExpression(==, 8, true, ConstantPatternContext.none) - parseUnaryExpression(==, true, ConstantPatternContext.none) - parsePrimary(==, expression, ConstantPatternContext.none) - parseLiteralInt(==) - listener: handleLiteralInt(0) - listener: endBinaryExpression(==, 0) - ensureCloseParen(0, () - listener: handleParenthesizedCondition((, null, null) - listener: beginThenStatement(return) - parseStatement()) - parseStatementX()) - parseReturnStatement()) - listener: beginReturnStatement(return) - parseExpression(return) - parsePrecedenceExpression(return, 1, true, ConstantPatternContext.none) - parseUnaryExpression(return, true, ConstantPatternContext.none) - parsePrimary(return, expression, ConstantPatternContext.none) - parseLiteralInt(return) - listener: handleLiteralInt(42) - ensureSemicolon(42) - listener: endReturnStatement(true, return, ;) - inGenerator() - listener: endThenStatement(return, ;) - listener: endIfStatement(if, null, ;) - notEofOrType(CLOSE_CURLY_BRACKET, return) - parseStatement(;) - parseStatementX(;) - parseReturnStatement(;) - listener: beginReturnStatement(return) - parseExpression(return) - parsePrecedenceExpression(return, 1, true, ConstantPatternContext.none) - parseUnaryExpression(return, true, ConstantPatternContext.none) - parsePrimary(return, expression, ConstantPatternContext.none) - parseThisExpression(return, expression) - listener: handleThisExpression(this, expression) - listener: handleNoTypeArguments(() - parseArguments(this) - parseArgumentsRest(() - listener: beginArguments(() - allowedToShortcutParseExpression() - parseExpression(() - parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) - parseUnaryExpression((, true, ConstantPatternContext.none) - parsePrimary((, expression, ConstantPatternContext.none) - parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) - parseSend((, expression, ConstantPatternContext.none) - ensureIdentifier((, expression) - listener: handleIdentifier(x, expression) - listener: handleNoTypeArguments(-) - parseArgumentsOpt(x) - listener: handleNoArguments(-) - listener: handleSend(x, x) - listener: beginBinaryExpression(-) - parsePrecedenceExpression(-, 14, true, ConstantPatternContext.none) - parseUnaryExpression(-, true, ConstantPatternContext.none) - parsePrimary(-, expression, ConstantPatternContext.none) - parseLiteralInt(-) - listener: handleLiteralInt(1) - listener: endBinaryExpression(-, 1) - listener: endArguments(1, (, )) - listener: handleSend(this, )) - listener: beginBinaryExpression(+) - parsePrecedenceExpression(+, 14, true, ConstantPatternContext.none) - parseUnaryExpression(+, true, ConstantPatternContext.none) - parsePrimary(+, expression, ConstantPatternContext.none) - parseLiteralInt(+) - listener: handleLiteralInt(1) - listener: endBinaryExpression(+, 1) - ensureSemicolon(1) - listener: endReturnStatement(true, return, ;) - inGenerator() - notEofOrType(CLOSE_CURLY_BRACKET, }) - listener: endBlockFunctionBody(2, {, }) - listener: endClassMethod(null, , (, null, }) - listener: endMember() + inPlainSync() + parseFunctionBody(), false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, if) + parseStatement({) + parseStatementX({) + parseIfStatement({) + listener: beginIfStatement(if) + ensureParenthesizedCondition(if, allowCase: false) + parseExpressionInParenthesisRest((, allowCase: false) + parseExpression(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + ensureIdentifier((, expression) + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments(==) + parseArgumentsOpt(x) + listener: handleNoArguments(==) + listener: handleSend(x, x) + listener: beginBinaryExpression(==) + parsePrecedenceExpression(==, 8, true, ConstantPatternContext.none) + parseUnaryExpression(==, true, ConstantPatternContext.none) + parsePrimary(==, expression, ConstantPatternContext.none) + parseLiteralInt(==) + listener: handleLiteralInt(0) + listener: endBinaryExpression(==, 0) + ensureCloseParen(0, () + listener: handleParenthesizedCondition((, null, null) + listener: beginThenStatement(return) + parseStatement()) + parseStatementX()) + parseReturnStatement()) + listener: beginReturnStatement(return) + parseExpression(return) + parsePrecedenceExpression(return, 1, true, ConstantPatternContext.none) + parseUnaryExpression(return, true, ConstantPatternContext.none) + parsePrimary(return, expression, ConstantPatternContext.none) + parseLiteralInt(return) + listener: handleLiteralInt(42) + ensureSemicolon(42) + listener: endReturnStatement(true, return, ;) + inGenerator() + listener: endThenStatement(return, ;) + listener: endIfStatement(if, null, ;) + notEofOrType(CLOSE_CURLY_BRACKET, return) + parseStatement(;) + parseStatementX(;) + parseReturnStatement(;) + listener: beginReturnStatement(return) + parseExpression(return) + parsePrecedenceExpression(return, 1, true, ConstantPatternContext.none) + parseUnaryExpression(return, true, ConstantPatternContext.none) + parsePrimary(return, expression, ConstantPatternContext.none) + parseThisExpression(return, expression) + listener: handleThisExpression(this, expression) + listener: handleNoTypeArguments(() + parseArguments(this) + parseArgumentsRest(() + listener: beginArguments(() + allowedToShortcutParseExpression() + parseExpression(() + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + ensureIdentifier((, expression) + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments(-) + parseArgumentsOpt(x) + listener: handleNoArguments(-) + listener: handleSend(x, x) + listener: beginBinaryExpression(-) + parsePrecedenceExpression(-, 14, true, ConstantPatternContext.none) + parseUnaryExpression(-, true, ConstantPatternContext.none) + parsePrimary(-, expression, ConstantPatternContext.none) + parseLiteralInt(-) + listener: handleLiteralInt(1) + listener: endBinaryExpression(-, 1) + listener: endArguments(1, (, )) + listener: handleSend(this, )) + listener: beginBinaryExpression(+) + parsePrecedenceExpression(+, 14, true, ConstantPatternContext.none) + parseUnaryExpression(+, true, ConstantPatternContext.none) + parsePrimary(+, expression, ConstantPatternContext.none) + parseLiteralInt(+) + listener: handleLiteralInt(1) + listener: endBinaryExpression(+, 1) + ensureSemicolon(1) + listener: endReturnStatement(true, return, ;) + inGenerator() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(2, {, }) + listener: endClassMethod(null, int, (, null, }) + listener: endMember() notEofOrType(CLOSE_CURLY_BRACKET, int) parseClassOrMixinOrExtensionOrEnumMemberImpl(}, DeclarationKind.Class, WrapperClass) parseMetadataStar(}) @@ -10613,7 +10588,7 @@ listener: endClassMethod(null, int, (, null, }) listener: endMember() notEofOrType(CLOSE_CURLY_BRACKET, }) - listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 71, {, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 70, {, }) listener: endClassDeclaration(class, }) listener: endTopLevelDeclaration(}) reportAllErrorTokens(class)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.parser.expect index 6295405..4e77265 100644 --- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.parser.expect +++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.parser.expect
@@ -296,7 +296,7 @@ return sync(x-1) + 1; } -int this;*synthetic*(int x) { +int this(int x) { if (x == 0) return 42; return this(x-1) + 1; } @@ -644,7 +644,7 @@ return[KeywordToken] sync[KeywordToken]([BeginToken]x[StringToken]-[SimpleToken]1[StringToken])[SimpleToken] +[SimpleToken] 1[StringToken];[SimpleToken] }[SimpleToken] -int[StringToken] this[KeywordToken];[SyntheticToken][SyntheticStringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +int[StringToken] this[KeywordToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] if[KeywordToken] ([BeginToken]x[StringToken] ==[SimpleToken] 0[StringToken])[SimpleToken] return[KeywordToken] 42[StringToken];[SimpleToken] return[KeywordToken] this[KeywordToken]([BeginToken]x[StringToken]-[SimpleToken]1[StringToken])[SimpleToken] +[SimpleToken] 1[StringToken];[SimpleToken] }[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.expect index 93c9258..319fa07 100644 --- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.expect +++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.expect
@@ -336,14 +336,6 @@ int this(int x) { ^^^^ -parser/error_recovery/keyword_named_class_methods_2:297:7: Expected ';' after this. - int this(int x) { - ^^^^ - -parser/error_recovery/keyword_named_class_methods_2:297:11: Expected an identifier, but got '('. - int this(int x) { - ^ - parser/error_recovery/keyword_named_class_methods_2:302:7: 'throw' can't be used as an identifier because it's a keyword. int throw(int x) { ^^^^^ @@ -4081,23 +4073,12 @@ beginMetadataStar(int) endMetadataStar(0) beginMember() - beginFields(DeclarationKind.Class, null, null, null, null, null, null, null, }) + beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, WrapperClass) handleIdentifier(int, typeReference) handleNoTypeArguments(this) handleType(int, null) handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) - handleIdentifier(this, fieldDeclaration) - handleNoFieldInitializer(() - handleRecoverableError(Message[Template(ExpectedAfterButGot), Expected ';' after this., null, {string: ;}], this, this) - endClassFields(null, null, null, null, null, null, null, 1, int, ;) - endMember() - beginMetadataStar(() - endMetadataStar(0) - beginMember() - beginMethod(DeclarationKind.Class, null, null, null, null, null, null, (, WrapperClass) - handleNoType(;) - handleRecoverableError(Message[Template(ExpectedIdentifier), Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, () - handleIdentifier(, methodDeclaration) + handleIdentifier(this, methodDeclaration) handleNoTypeVariables(() beginFormalParameters((, MemberKind.NonStaticMethod) beginMetadataStar(int) @@ -4146,7 +4127,7 @@ endBinaryExpression(+, 1) endReturnStatement(true, return, ;) endBlockFunctionBody(2, {, }) - endClassMethod(null, , (, null, }) + endClassMethod(null, int, (, null, }) endMember() beginMetadataStar(int) endMetadataStar(0) @@ -4754,7 +4735,7 @@ endBlockFunctionBody(2, {, }) endClassMethod(null, int, (, null, }) endMember() - endClassOrMixinOrExtensionBody(DeclarationKind.Class, 71, {, }) + endClassOrMixinOrExtensionBody(DeclarationKind.Class, 70, {, }) endClassDeclaration(class, }) endTopLevelDeclaration(}) endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.intertwined.expect index fb96c2b..c857c73 100644 --- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.intertwined.expect +++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.intertwined.expect
@@ -9518,173 +9518,148 @@ listener: beginMetadataStar(int) listener: endMetadataStar(0) listener: beginMember() - recoverFromInvalidMember(int, }, null, null, null, null, null, null, null, }, SimpleType(), null, DeclarationKind.Class, WrapperClass) - parseFields(}, null, null, null, null, null, null, null, }, SimpleType(), this, DeclarationKind.Class, WrapperClass, false) - listener: beginFields(DeclarationKind.Class, null, null, null, null, null, null, null, }) - listener: handleIdentifier(int, typeReference) - listener: handleNoTypeArguments(this) - listener: handleType(int, null) - ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false) - reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) - listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) - listener: handleIdentifier(this, fieldDeclaration) - parseFieldInitializerOpt(this, this, null, null, null, null, null, DeclarationKind.Class, WrapperClass) - listener: handleNoFieldInitializer(() - ensureSemicolon(this) - reportRecoverableError(this, Message[Template(ExpectedAfterButGot), Expected ';' after this., null, {string: ;}]) - listener: handleRecoverableError(Message[Template(ExpectedAfterButGot), Expected ';' after this., null, {string: ;}], this, this) - rewriter() - listener: endClassFields(null, null, null, null, null, null, null, 1, int, ;) - listener: endMember() - notEofOrType(CLOSE_CURLY_BRACKET, () - parseClassOrMixinOrExtensionOrEnumMemberImpl(;, DeclarationKind.Class, WrapperClass) - parseMetadataStar(;) - listener: beginMetadataStar(() - listener: endMetadataStar(0) - listener: beginMember() - recoverFromInvalidMember(;, ;, null, null, null, null, null, null, null, ;, NoType(), null, DeclarationKind.Class, WrapperClass) - parseMethod(;, null, null, null, null, null, null, null, ;, NoType(), null, (, DeclarationKind.Class, WrapperClass, false) - listener: beginMethod(DeclarationKind.Class, null, null, null, null, null, null, (, WrapperClass) - listener: handleNoType(;) - ensureIdentifierPotentiallyRecovered(;, methodDeclaration, false) - insertSyntheticIdentifier(;, methodDeclaration, message: null, messageOnToken: null) - reportRecoverableError((, Message[Template(ExpectedIdentifier), Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}]) - listener: handleRecoverableError(Message[Template(ExpectedIdentifier), Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, () - rewriter() - listener: handleIdentifier(, methodDeclaration) - parseQualifiedRestOpt(, methodDeclarationContinuation) - parseMethodTypeVar() - listener: handleNoTypeVariables(() - parseGetterOrFormalParameters(, (, false, MemberKind.NonStaticMethod) - parseFormalParameters(, MemberKind.NonStaticMethod) - parseFormalParametersRest((, MemberKind.NonStaticMethod) - listener: beginFormalParameters((, MemberKind.NonStaticMethod) - parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) - parseMetadataStar(() - listener: beginMetadataStar(int) - listener: endMetadataStar(0) - listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null) - listener: handleIdentifier(int, typeReference) - listener: handleNoTypeArguments(x) - listener: handleType(int, null) - ensureIdentifier(int, formalParameterDeclaration) - listener: handleIdentifier(x, formalParameterDeclaration) - listener: handleFormalParameterWithoutValue()) - listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) - listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod) - parseInitializersOpt()) - listener: handleNoInitializers() - parseAsyncModifierOpt()) - listener: handleAsyncModifier(null, null) - inPlainSync() + parseMethod(}, null, null, null, null, null, null, null, }, SimpleType(), null, this, DeclarationKind.Class, WrapperClass, false) + listener: beginMethod(DeclarationKind.Class, null, null, null, null, null, null, this, WrapperClass) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(this) + listener: handleType(int, null) + ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false) + reportRecoverableErrorWithToken(this, Template(ExpectedIdentifierButGotKeyword)) + listener: handleRecoverableError(Message[Template(ExpectedIdentifierButGotKeyword), 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this) + listener: handleIdentifier(this, methodDeclaration) + parseQualifiedRestOpt(this, methodDeclarationContinuation) + parseMethodTypeVar(this) + listener: handleNoTypeVariables(() + parseGetterOrFormalParameters(this, this, false, MemberKind.NonStaticMethod) + parseFormalParameters(this, MemberKind.NonStaticMethod) + parseFormalParametersRest((, MemberKind.NonStaticMethod) + listener: beginFormalParameters((, MemberKind.NonStaticMethod) + parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + parseMetadataStar(() + listener: beginMetadataStar(int) + listener: endMetadataStar(0) + listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null) + listener: handleIdentifier(int, typeReference) + listener: handleNoTypeArguments(x) + listener: handleType(int, null) + ensureIdentifier(int, formalParameterDeclaration) + listener: handleIdentifier(x, formalParameterDeclaration) + listener: handleFormalParameterWithoutValue()) + listener: endFormalParameter(null, null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.NonStaticMethod) + listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod) + parseInitializersOpt()) + listener: handleNoInitializers() + parseAsyncModifierOpt()) + listener: handleAsyncModifier(null, null) inPlainSync() - parseFunctionBody(), false, true) - listener: beginBlockFunctionBody({) - notEofOrType(CLOSE_CURLY_BRACKET, if) - parseStatement({) - parseStatementX({) - parseIfStatement({) - listener: beginIfStatement(if) - ensureParenthesizedCondition(if, allowCase: true) - parseExpressionInParenthesisRest((, allowCase: true) - parseExpression(() - looksLikeOuterPatternEquals(() - skipOuterPattern(() - skipObjectPatternRest(x) - parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) - parseUnaryExpression((, true, ConstantPatternContext.none) - parsePrimary((, expression, ConstantPatternContext.none) - parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) - parseSend((, expression, ConstantPatternContext.none) - ensureIdentifier((, expression) - listener: handleIdentifier(x, expression) - listener: handleNoTypeArguments(==) - parseArgumentsOpt(x) - listener: handleNoArguments(==) - listener: handleSend(x, x) - listener: beginBinaryExpression(==) - parsePrecedenceExpression(==, 8, true, ConstantPatternContext.none) - parseUnaryExpression(==, true, ConstantPatternContext.none) - parsePrimary(==, expression, ConstantPatternContext.none) - parseLiteralInt(==) - listener: handleLiteralInt(0) - listener: endBinaryExpression(==, 0) - ensureCloseParen(0, () - listener: handleParenthesizedCondition((, null, null) - listener: beginThenStatement(return) - parseStatement()) - parseStatementX()) - parseReturnStatement()) - listener: beginReturnStatement(return) - parseExpression(return) - looksLikeOuterPatternEquals(return) - skipOuterPattern(return) - parsePrecedenceExpression(return, 1, true, ConstantPatternContext.none) - parseUnaryExpression(return, true, ConstantPatternContext.none) - parsePrimary(return, expression, ConstantPatternContext.none) - parseLiteralInt(return) - listener: handleLiteralInt(42) - ensureSemicolon(42) - listener: endReturnStatement(true, return, ;) - inGenerator() - listener: endThenStatement(return, ;) - listener: endIfStatement(if, null, ;) - notEofOrType(CLOSE_CURLY_BRACKET, return) - parseStatement(;) - parseStatementX(;) - parseReturnStatement(;) - listener: beginReturnStatement(return) - parseExpression(return) - looksLikeOuterPatternEquals(return) - skipOuterPattern(return) - parsePrecedenceExpression(return, 1, true, ConstantPatternContext.none) - parseUnaryExpression(return, true, ConstantPatternContext.none) - parsePrimary(return, expression, ConstantPatternContext.none) - parseThisExpression(return, expression) - listener: handleThisExpression(this, expression) - listener: handleNoTypeArguments(() - parseArguments(this) - parseArgumentsRest(() - listener: beginArguments(() - allowedToShortcutParseExpression() - parseExpression(() - looksLikeOuterPatternEquals(() - skipOuterPattern(() - skipObjectPatternRest(x) - parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) - parseUnaryExpression((, true, ConstantPatternContext.none) - parsePrimary((, expression, ConstantPatternContext.none) - parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) - parseSend((, expression, ConstantPatternContext.none) - ensureIdentifier((, expression) - listener: handleIdentifier(x, expression) - listener: handleNoTypeArguments(-) - parseArgumentsOpt(x) - listener: handleNoArguments(-) - listener: handleSend(x, x) - listener: beginBinaryExpression(-) - parsePrecedenceExpression(-, 14, true, ConstantPatternContext.none) - parseUnaryExpression(-, true, ConstantPatternContext.none) - parsePrimary(-, expression, ConstantPatternContext.none) - parseLiteralInt(-) - listener: handleLiteralInt(1) - listener: endBinaryExpression(-, 1) - listener: endArguments(1, (, )) - listener: handleSend(this, )) - listener: beginBinaryExpression(+) - parsePrecedenceExpression(+, 14, true, ConstantPatternContext.none) - parseUnaryExpression(+, true, ConstantPatternContext.none) - parsePrimary(+, expression, ConstantPatternContext.none) - parseLiteralInt(+) - listener: handleLiteralInt(1) - listener: endBinaryExpression(+, 1) - ensureSemicolon(1) - listener: endReturnStatement(true, return, ;) - inGenerator() - notEofOrType(CLOSE_CURLY_BRACKET, }) - listener: endBlockFunctionBody(2, {, }) - listener: endClassMethod(null, , (, null, }) - listener: endMember() + inPlainSync() + parseFunctionBody(), false, true) + listener: beginBlockFunctionBody({) + notEofOrType(CLOSE_CURLY_BRACKET, if) + parseStatement({) + parseStatementX({) + parseIfStatement({) + listener: beginIfStatement(if) + ensureParenthesizedCondition(if, allowCase: true) + parseExpressionInParenthesisRest((, allowCase: true) + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + skipObjectPatternRest(x) + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + ensureIdentifier((, expression) + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments(==) + parseArgumentsOpt(x) + listener: handleNoArguments(==) + listener: handleSend(x, x) + listener: beginBinaryExpression(==) + parsePrecedenceExpression(==, 8, true, ConstantPatternContext.none) + parseUnaryExpression(==, true, ConstantPatternContext.none) + parsePrimary(==, expression, ConstantPatternContext.none) + parseLiteralInt(==) + listener: handleLiteralInt(0) + listener: endBinaryExpression(==, 0) + ensureCloseParen(0, () + listener: handleParenthesizedCondition((, null, null) + listener: beginThenStatement(return) + parseStatement()) + parseStatementX()) + parseReturnStatement()) + listener: beginReturnStatement(return) + parseExpression(return) + looksLikeOuterPatternEquals(return) + skipOuterPattern(return) + parsePrecedenceExpression(return, 1, true, ConstantPatternContext.none) + parseUnaryExpression(return, true, ConstantPatternContext.none) + parsePrimary(return, expression, ConstantPatternContext.none) + parseLiteralInt(return) + listener: handleLiteralInt(42) + ensureSemicolon(42) + listener: endReturnStatement(true, return, ;) + inGenerator() + listener: endThenStatement(return, ;) + listener: endIfStatement(if, null, ;) + notEofOrType(CLOSE_CURLY_BRACKET, return) + parseStatement(;) + parseStatementX(;) + parseReturnStatement(;) + listener: beginReturnStatement(return) + parseExpression(return) + looksLikeOuterPatternEquals(return) + skipOuterPattern(return) + parsePrecedenceExpression(return, 1, true, ConstantPatternContext.none) + parseUnaryExpression(return, true, ConstantPatternContext.none) + parsePrimary(return, expression, ConstantPatternContext.none) + parseThisExpression(return, expression) + listener: handleThisExpression(this, expression) + listener: handleNoTypeArguments(() + parseArguments(this) + parseArgumentsRest(() + listener: beginArguments(() + allowedToShortcutParseExpression() + parseExpression(() + looksLikeOuterPatternEquals(() + skipOuterPattern(() + skipObjectPatternRest(x) + parsePrecedenceExpression((, 1, true, ConstantPatternContext.none) + parseUnaryExpression((, true, ConstantPatternContext.none) + parsePrimary((, expression, ConstantPatternContext.none) + parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none) + parseSend((, expression, ConstantPatternContext.none) + ensureIdentifier((, expression) + listener: handleIdentifier(x, expression) + listener: handleNoTypeArguments(-) + parseArgumentsOpt(x) + listener: handleNoArguments(-) + listener: handleSend(x, x) + listener: beginBinaryExpression(-) + parsePrecedenceExpression(-, 14, true, ConstantPatternContext.none) + parseUnaryExpression(-, true, ConstantPatternContext.none) + parsePrimary(-, expression, ConstantPatternContext.none) + parseLiteralInt(-) + listener: handleLiteralInt(1) + listener: endBinaryExpression(-, 1) + listener: endArguments(1, (, )) + listener: handleSend(this, )) + listener: beginBinaryExpression(+) + parsePrecedenceExpression(+, 14, true, ConstantPatternContext.none) + parseUnaryExpression(+, true, ConstantPatternContext.none) + parsePrimary(+, expression, ConstantPatternContext.none) + parseLiteralInt(+) + listener: handleLiteralInt(1) + listener: endBinaryExpression(+, 1) + ensureSemicolon(1) + listener: endReturnStatement(true, return, ;) + inGenerator() + notEofOrType(CLOSE_CURLY_BRACKET, }) + listener: endBlockFunctionBody(2, {, }) + listener: endClassMethod(null, int, (, null, }) + listener: endMember() notEofOrType(CLOSE_CURLY_BRACKET, int) parseClassOrMixinOrExtensionOrEnumMemberImpl(}, DeclarationKind.Class, WrapperClass) parseMetadataStar(}) @@ -11333,7 +11308,7 @@ listener: endClassMethod(null, int, (, null, }) listener: endMember() notEofOrType(CLOSE_CURLY_BRACKET, }) - listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 71, {, }) + listener: endClassOrMixinOrExtensionBody(DeclarationKind.Class, 70, {, }) listener: endClassDeclaration(class, }) listener: endTopLevelDeclaration(}) reportAllErrorTokens(class)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.parser.expect index 777511a..02b4683 100644 --- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.parser.expect +++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods_2.dart.parser.expect
@@ -296,7 +296,7 @@ return sync(x-1) + 1; } -int this;*synthetic*(int x) { +int this(int x) { if (x == 0) return 42; return this(x-1) + 1; } @@ -644,7 +644,7 @@ return[KeywordToken] sync[KeywordToken]([BeginToken]x[StringToken]-[SimpleToken]1[StringToken])[SimpleToken] +[SimpleToken] 1[StringToken];[SimpleToken] }[SimpleToken] -int[StringToken] this[KeywordToken];[SyntheticToken][SyntheticStringToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] +int[StringToken] this[KeywordToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken] if[KeywordToken] ([BeginToken]x[StringToken] ==[SimpleToken] 0[StringToken])[SimpleToken] return[KeywordToken] 42[StringToken];[SimpleToken] return[KeywordToken] this[KeywordToken]([BeginToken]x[StringToken]-[SimpleToken]1[StringToken])[SimpleToken] +[SimpleToken] 1[StringToken];[SimpleToken] }[SimpleToken]
diff --git a/pkg/front_end/test/parser/parser_ast_test.dart b/pkg/front_end/test/parser/parser_ast_test.dart index d001c0b..0995e2c 100644 --- a/pkg/front_end/test/parser/parser_ast_test.dart +++ b/pkg/front_end/test/parser/parser_ast_test.dart
@@ -704,6 +704,15 @@ decl.endToken.offset + decl.endToken.length, ), ]; + } else if (item.isPrimaryConstructorBody()) { + PrimaryConstructorBodyEnd decl = item.getPrimaryConstructorBody(); + return [ + getCutContent( + data, + decl.beginToken.offset, + decl.endToken.offset + decl.endToken.length, + ), + ]; } else { if (item.type == ParserAstType.BEGIN) return const []; if (item.type == ParserAstType.HANDLE) return const [];
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart index a8d0faf..e6a144a 100644 --- a/pkg/front_end/test/parser_test_listener.dart +++ b/pkg/front_end/test/parser_test_listener.dart
@@ -597,6 +597,34 @@ } @override + void beginPrimaryConstructorBody(Token token) { + seen(token); + doPrint( + 'beginPrimaryConstructorBody(' + '$token)', + ); + indent++; + } + + @override + void endPrimaryConstructorBody( + Token beginToken, + Token? beginInitializers, + Token endToken, + ) { + indent--; + seen(beginToken); + seen(beginInitializers); + seen(endToken); + doPrint( + 'endPrimaryConstructorBody(' + '$beginToken, ' + '$beginInitializers, ' + '$endToken)', + ); + } + + @override void beginCombinators(Token token) { seen(token); doPrint(
diff --git a/pkg/front_end/test/parser_test_parser.dart b/pkg/front_end/test/parser_test_parser.dart index 34ddf6f..22912ff 100644 --- a/pkg/front_end/test/parser_test_parser.dart +++ b/pkg/front_end/test/parser_test_parser.dart
@@ -1236,6 +1236,18 @@ } @override + Token parsePrimaryConstructorBody(Token token) { + doPrint( + 'parsePrimaryConstructorBody(' + '$token)', + ); + indent++; + var result = super.parsePrimaryConstructorBody(token); + indent--; + return result; + } + + @override Token parseExtensionTypeDeclaration( Token beginToken, Token token,
diff --git a/pkg/front_end/testcases/general/issue43363.dart.strong.expect b/pkg/front_end/testcases/general/issue43363.dart.strong.expect index d16ec61..2d3100c 100644 --- a/pkg/front_end/testcases/general/issue43363.dart.strong.expect +++ b/pkg/front_end/testcases/general/issue43363.dart.strong.expect
@@ -2,45 +2,91 @@ // // Problems in library: // -// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Expected a class member, but got 'this'. +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: 'this' can't be used as an identifier because it's a keyword. +// Try renaming this to be an identifier that isn't a keyword. // this.y = 2; // ^^^^ // -// pkg/front_end/testcases/general/issue43363.dart:10:13: Error: Expected a class member, but got '.'. +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: A method declaration needs an explicit list of parameters. +// Try adding a parameter list to the method declaration. // this.y = 2; -// ^ +// ^^^^ // -// pkg/front_end/testcases/general/issue43363.dart:10:14: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name. -// Try adding the name of the type of the variable or the keyword 'var'. +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Only factory constructor can specify '=' redirection. +// Try making this a factory constructor, or remove the redirection. // this.y = 2; -// ^ +// ^ // -// pkg/front_end/testcases/general/issue43363.dart:10:14: Error: 'y' is already declared in this scope. +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Expected an identifier, but got '2'. +// Try inserting an identifier before '2'. // this.y = 2; -// ^ -// pkg/front_end/testcases/general/issue43363.dart:7:13: Context: Previous declaration of 'y'. -// final int y; -// ^ +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Expected ';' after this. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: The name of a constructor must match the name of the enclosing class. +// this.y = 2; +// ^^^^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Expected a class member, but got '2'. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:19: Error: Expected a class member, but got ';'. +// this.y = 2; +// ^ // // pkg/front_end/testcases/general/issue43363.dart:9:16: Error: A redirecting constructor can't have other initializers. // this.x = 1; // ^ // +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Expected a function body or '=>'. +// Try adding {}. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Constructors can't have a return type. +// Try removing the return type. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Final field 'x' is not initialized by this constructor. +// Try to initialize the field using an initializing formal or a field initializer. +// this.y = 2; +// ^ +// pkg/front_end/testcases/general/issue43363.dart:6:13: Context: 'x' is defined here. +// final int x; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Final field 'y' is not initialized by this constructor. +// Try to initialize the field using an initializing formal or a field initializer. +// this.y = 2; +// ^ +// pkg/front_end/testcases/general/issue43363.dart:7:13: Context: 'y' is defined here. +// final int y; +// ^ +// import self as self; import "dart:core" as core; class E extends core::Object { final field core::int x; final field core::int y; + erroneous constructor y() → self::E + : self::E::y = null, self::E::x = null, super core::Object::•() + invalid-expression "pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Constructors can't have a return type. +Try removing the return type. + this.y = 2; + ^"; erroneous constructor •() → self::E : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/issue43363.dart:9:16: Error: A redirecting constructor can't have other initializers. this.x = 1; ^", this self::E::named() ; constructor named() → self::E - : self::E::x = 5, final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/issue43363.dart:13:20: Error: Can't use 'y' because it is declared more than once. - this.y = 6; - ^" + : self::E::x = 5, self::E::y = 6, super core::Object::•() ; } static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue43363.dart.strong.modular.expect b/pkg/front_end/testcases/general/issue43363.dart.strong.modular.expect index d16ec61..2d3100c 100644 --- a/pkg/front_end/testcases/general/issue43363.dart.strong.modular.expect +++ b/pkg/front_end/testcases/general/issue43363.dart.strong.modular.expect
@@ -2,45 +2,91 @@ // // Problems in library: // -// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Expected a class member, but got 'this'. +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: 'this' can't be used as an identifier because it's a keyword. +// Try renaming this to be an identifier that isn't a keyword. // this.y = 2; // ^^^^ // -// pkg/front_end/testcases/general/issue43363.dart:10:13: Error: Expected a class member, but got '.'. +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: A method declaration needs an explicit list of parameters. +// Try adding a parameter list to the method declaration. // this.y = 2; -// ^ +// ^^^^ // -// pkg/front_end/testcases/general/issue43363.dart:10:14: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name. -// Try adding the name of the type of the variable or the keyword 'var'. +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Only factory constructor can specify '=' redirection. +// Try making this a factory constructor, or remove the redirection. // this.y = 2; -// ^ +// ^ // -// pkg/front_end/testcases/general/issue43363.dart:10:14: Error: 'y' is already declared in this scope. +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Expected an identifier, but got '2'. +// Try inserting an identifier before '2'. // this.y = 2; -// ^ -// pkg/front_end/testcases/general/issue43363.dart:7:13: Context: Previous declaration of 'y'. -// final int y; -// ^ +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Expected ';' after this. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: The name of a constructor must match the name of the enclosing class. +// this.y = 2; +// ^^^^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Expected a class member, but got '2'. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:19: Error: Expected a class member, but got ';'. +// this.y = 2; +// ^ // // pkg/front_end/testcases/general/issue43363.dart:9:16: Error: A redirecting constructor can't have other initializers. // this.x = 1; // ^ // +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Expected a function body or '=>'. +// Try adding {}. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Constructors can't have a return type. +// Try removing the return type. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Final field 'x' is not initialized by this constructor. +// Try to initialize the field using an initializing formal or a field initializer. +// this.y = 2; +// ^ +// pkg/front_end/testcases/general/issue43363.dart:6:13: Context: 'x' is defined here. +// final int x; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Final field 'y' is not initialized by this constructor. +// Try to initialize the field using an initializing formal or a field initializer. +// this.y = 2; +// ^ +// pkg/front_end/testcases/general/issue43363.dart:7:13: Context: 'y' is defined here. +// final int y; +// ^ +// import self as self; import "dart:core" as core; class E extends core::Object { final field core::int x; final field core::int y; + erroneous constructor y() → self::E + : self::E::y = null, self::E::x = null, super core::Object::•() + invalid-expression "pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Constructors can't have a return type. +Try removing the return type. + this.y = 2; + ^"; erroneous constructor •() → self::E : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/issue43363.dart:9:16: Error: A redirecting constructor can't have other initializers. this.x = 1; ^", this self::E::named() ; constructor named() → self::E - : self::E::x = 5, final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/issue43363.dart:13:20: Error: Can't use 'y' because it is declared more than once. - this.y = 6; - ^" + : self::E::x = 5, self::E::y = 6, super core::Object::•() ; } static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue43363.dart.strong.outline.expect b/pkg/front_end/testcases/general/issue43363.dart.strong.outline.expect index 21d01c4..00476c2 100644 --- a/pkg/front_end/testcases/general/issue43363.dart.strong.outline.expect +++ b/pkg/front_end/testcases/general/issue43363.dart.strong.outline.expect
@@ -2,25 +2,41 @@ // // Problems in library: // -// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Expected a class member, but got 'this'. +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: 'this' can't be used as an identifier because it's a keyword. +// Try renaming this to be an identifier that isn't a keyword. // this.y = 2; // ^^^^ // -// pkg/front_end/testcases/general/issue43363.dart:10:13: Error: Expected a class member, but got '.'. +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: A method declaration needs an explicit list of parameters. +// Try adding a parameter list to the method declaration. // this.y = 2; -// ^ +// ^^^^ // -// pkg/front_end/testcases/general/issue43363.dart:10:14: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name. -// Try adding the name of the type of the variable or the keyword 'var'. +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Only factory constructor can specify '=' redirection. +// Try making this a factory constructor, or remove the redirection. // this.y = 2; -// ^ +// ^ // -// pkg/front_end/testcases/general/issue43363.dart:10:14: Error: 'y' is already declared in this scope. +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Expected an identifier, but got '2'. +// Try inserting an identifier before '2'. // this.y = 2; -// ^ -// pkg/front_end/testcases/general/issue43363.dart:7:13: Context: Previous declaration of 'y'. -// final int y; -// ^ +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Expected ';' after this. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: The name of a constructor must match the name of the enclosing class. +// this.y = 2; +// ^^^^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Expected a class member, but got '2'. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:19: Error: Expected a class member, but got ';'. +// this.y = 2; +// ^ // import self as self; import "dart:core" as core; @@ -28,6 +44,8 @@ class E extends core::Object { final field core::int x; final field core::int y; + constructor y() → self::E + ; constructor •() → self::E ; constructor named() → self::E
diff --git a/pkg/front_end/testcases/general/issue43363.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue43363.dart.strong.transformed.expect index d16ec61..2d3100c 100644 --- a/pkg/front_end/testcases/general/issue43363.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/general/issue43363.dart.strong.transformed.expect
@@ -2,45 +2,91 @@ // // Problems in library: // -// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Expected a class member, but got 'this'. +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: 'this' can't be used as an identifier because it's a keyword. +// Try renaming this to be an identifier that isn't a keyword. // this.y = 2; // ^^^^ // -// pkg/front_end/testcases/general/issue43363.dart:10:13: Error: Expected a class member, but got '.'. +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: A method declaration needs an explicit list of parameters. +// Try adding a parameter list to the method declaration. // this.y = 2; -// ^ +// ^^^^ // -// pkg/front_end/testcases/general/issue43363.dart:10:14: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name. -// Try adding the name of the type of the variable or the keyword 'var'. +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Only factory constructor can specify '=' redirection. +// Try making this a factory constructor, or remove the redirection. // this.y = 2; -// ^ +// ^ // -// pkg/front_end/testcases/general/issue43363.dart:10:14: Error: 'y' is already declared in this scope. +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Expected an identifier, but got '2'. +// Try inserting an identifier before '2'. // this.y = 2; -// ^ -// pkg/front_end/testcases/general/issue43363.dart:7:13: Context: Previous declaration of 'y'. -// final int y; -// ^ +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Expected ';' after this. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: The name of a constructor must match the name of the enclosing class. +// this.y = 2; +// ^^^^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Expected a class member, but got '2'. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:19: Error: Expected a class member, but got ';'. +// this.y = 2; +// ^ // // pkg/front_end/testcases/general/issue43363.dart:9:16: Error: A redirecting constructor can't have other initializers. // this.x = 1; // ^ // +// pkg/front_end/testcases/general/issue43363.dart:10:16: Error: Expected a function body or '=>'. +// Try adding {}. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Constructors can't have a return type. +// Try removing the return type. +// this.y = 2; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Final field 'x' is not initialized by this constructor. +// Try to initialize the field using an initializing formal or a field initializer. +// this.y = 2; +// ^ +// pkg/front_end/testcases/general/issue43363.dart:6:13: Context: 'x' is defined here. +// final int x; +// ^ +// +// pkg/front_end/testcases/general/issue43363.dart:10:9: Error: Final field 'y' is not initialized by this constructor. +// Try to initialize the field using an initializing formal or a field initializer. +// this.y = 2; +// ^ +// pkg/front_end/testcases/general/issue43363.dart:7:13: Context: 'y' is defined here. +// final int y; +// ^ +// import self as self; import "dart:core" as core; class E extends core::Object { final field core::int x; final field core::int y; + erroneous constructor y() → self::E + : self::E::y = null, self::E::x = null, super core::Object::•() + invalid-expression "pkg/front_end/testcases/general/issue43363.dart:10:18: Error: Constructors can't have a return type. +Try removing the return type. + this.y = 2; + ^"; erroneous constructor •() → self::E : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/issue43363.dart:9:16: Error: A redirecting constructor can't have other initializers. this.x = 1; ^", this self::E::named() ; constructor named() → self::E - : self::E::x = 5, final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/issue43363.dart:13:20: Error: Can't use 'y' because it is declared more than once. - this.y = 6; - ^" + : self::E::x = 5, self::E::y = 6, super core::Object::•() ; } static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue43363.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue43363.dart.textual_outline.expect index 789eed9..b80822e 100644 --- a/pkg/front_end/testcases/general/issue43363.dart.textual_outline.expect +++ b/pkg/front_end/testcases/general/issue43363.dart.textual_outline.expect
@@ -2,8 +2,8 @@ final int x; final int y; E() : this.named(), this.x = 1; - this. - y = 2; + this.y ()= ; + 2; E.named() : this.x = 5, this.y = 6; }
diff --git a/pkg/linter/lib/src/rules/parameter_assignments.dart b/pkg/linter/lib/src/rules/parameter_assignments.dart index d9c4eb3..2805fac 100644 --- a/pkg/linter/lib/src/rules/parameter_assignments.dart +++ b/pkg/linter/lib/src/rules/parameter_assignments.dart
@@ -42,6 +42,8 @@ var visitor = _Visitor(this); registry.addFunctionDeclaration(this, visitor); registry.addMethodDeclaration(this, visitor); + registry.addFunctionExpression(this, visitor); + registry.addConstructorDeclaration(this, visitor); } } @@ -152,6 +154,11 @@ _Visitor(this.rule); @override + void visitConstructorDeclaration(ConstructorDeclaration node) { + _checkParameters(node.parameters, node.body); + } + + @override void visitFunctionDeclaration(FunctionDeclaration node) { _checkParameters( node.functionExpression.parameters, @@ -160,6 +167,13 @@ } @override + void visitFunctionExpression(FunctionExpression node) { + if (node.parent is! FunctionDeclaration) { + _checkParameters(node.parameters, node.body); + } + } + + @override void visitMethodDeclaration(MethodDeclaration node) { _checkParameters(node.parameters, node.body); }
diff --git a/pkg/linter/test/rules/erase_dart_type_extension_types_test.dart b/pkg/linter/test/rules/erase_dart_type_extension_types_test.dart index 3ea96a3..41e90fb 100644 --- a/pkg/linter/test/rules/erase_dart_type_extension_types_test.dart +++ b/pkg/linter/test/rules/erase_dart_type_extension_types_test.dart
@@ -15,10 +15,21 @@ @reflectiveTest class EraseDartTypeExtensionTypesTest extends LintRuleTest { @override - bool get addKernelPackageDep => true; + String get lintRule => LintNames.erase_dart_type_extension_types; @override - String get lintRule => LintNames.erase_dart_type_extension_types; + void setUp() { + newPackage('kernel').addFile('lib/ast.dart', r''' +library kernel.ast; + +abstract class Node {} + +class DartType extends Node {} + +class InterfaceType extends DartType {} +'''); + super.setUp(); + } test_isDartType() async { await assertDiagnostics(
diff --git a/pkg/linter/test/rules/parameter_assignments_test.dart b/pkg/linter/test/rules/parameter_assignments_test.dart index e596d0a..e896a75 100644 --- a/pkg/linter/test/rules/parameter_assignments_test.dart +++ b/pkg/linter/test/rules/parameter_assignments_test.dart
@@ -17,6 +17,43 @@ @override String get lintRule => LintNames.parameter_assignments; + test_anonymousFunction_assignment() async { + await assertDiagnostics( + r''' +void main() { + (int i) { + i = 42; + }(0); +} +''', + [lint(30, 6)], + ); + } + + test_anonymousFunction_assignment_arrowBody() async { + await assertDiagnostics( + r''' +void main() { + (int i) => i = 42; +} +''', + [lint(27, 6)], + ); + } + + test_anonymousFunction_assignment_notInvoked() async { + await assertDiagnostics( + r''' +void main() { + (int i) { + i = 42; + }; +} +''', + [lint(30, 6)], + ); + } + test_assignment_inIfElseBranches() async { await assertDiagnostics( r''' @@ -70,7 +107,6 @@ ); } - @FailingTest(reason: 'Closures not implemented') test_closure_assignment() async { await assertDiagnostics( r''' @@ -95,6 +131,19 @@ ); } + test_constructor_assignment() async { + await assertDiagnostics( + r''' +class Foo { + Foo(int x) { + x = 4; + } +} +''', + [lint(31, 5)], + ); + } + test_function_assignment() async { await assertDiagnostics( r'''
diff --git a/pkg/wasm_builder/lib/src/builder/builder.dart b/pkg/wasm_builder/lib/src/builder/builder.dart index 6a380e1..6e154b5 100644 --- a/pkg/wasm_builder/lib/src/builder/builder.dart +++ b/pkg/wasm_builder/lib/src/builder/builder.dart
@@ -11,6 +11,7 @@ export 'global.dart' show GlobalBuilder; export 'functions.dart' show FunctionsBuilder; export 'function.dart' show FunctionBuilder; +export 'elements.dart' show ElementsBuilder; export 'memories.dart' show MemoriesBuilder; export 'module.dart' show ModuleBuilder; export 'tables.dart' show TablesBuilder;
diff --git a/pkg/wasm_builder/lib/src/builder/elements.dart b/pkg/wasm_builder/lib/src/builder/elements.dart new file mode 100644 index 0000000..a3082f9 --- /dev/null +++ b/pkg/wasm_builder/lib/src/builder/elements.dart
@@ -0,0 +1,107 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:math' as math; + +import '../ir/ir.dart' as ir; +import 'builder.dart'; + +/// Builder for the elements section of a wasm module. +class ElementsBuilder with Builder<ir.Elements> { + final ModuleBuilder _moduleBuilder; + final _functionTableBuilders = <ir.Table, ActiveFunctionSegmentBuilder>{}; + + late final declarativeSegmentBuilder = + DeclarativeSegmentBuilder(_moduleBuilder); + + ElementsBuilder(this._moduleBuilder); + + ActiveFunctionSegmentBuilder activeFunctionSegmentBuilderFor(ir.Table table) { + assert(table.type.isSubtypeOf(ir.RefType.func(nullable: true))); + assert(table.enclosingModule == _moduleBuilder.module); + return _functionTableBuilders.putIfAbsent( + table, () => ActiveFunctionSegmentBuilder(table)); + } + + @override + ir.Elements forceBuild() { + final segments = <ir.ElementSegment>[]; + for (final b in _functionTableBuilders.values) { + segments.addAll(b.build()); + } + if (declarativeSegmentBuilder._declaredFunctions.isNotEmpty) { + segments.add(declarativeSegmentBuilder.build()); + } + return ir.Elements(segments); + } +} + +class DeclarativeSegmentBuilder with Builder<ir.DeclarativeElementSegment> { + final ModuleBuilder _moduleBuilder; + final _declaredFunctions = <ir.BaseFunction>{}; + + DeclarativeSegmentBuilder(this._moduleBuilder); + + /// Pre-declare [function] in a declared segment which allows using that + /// function in `ref.func` constant instructions. + void declare(ir.BaseFunction function) { + assert(function.enclosingModule == _moduleBuilder.module); + _declaredFunctions.add(function); + } + + @override + ir.DeclarativeElementSegment forceBuild() => + ir.DeclarativeElementSegment(_declaredFunctions.toList()); +} + +class ActiveFunctionSegmentBuilder with Builder<List<ir.ActiveElementSegment>> { + final ir.Table table; + final Map<int, ir.BaseFunction> _functions = {}; + + ActiveFunctionSegmentBuilder(this.table); + + void setFunctionAt(int index, ir.BaseFunction function) { + assert(function.enclosingModule == table.enclosingModule); + assert(table.maxSize == null || index < table.maxSize!, + 'Index $index greater than max table size ${table.maxSize}'); + _functions[index] = function; + table.minSize = math.max(table.minSize, index + 1); + } + + @override + List<ir.ActiveElementSegment> forceBuild() { + final entries = _functions.entries.toList() + ..sort((a, b) => a.key.compareTo(b.key)); + + final segments = <ir.ActiveElementSegment>[]; + if (const ir.RefType.func(nullable: false).isSubtypeOf(table.type)) { + ir.ActiveFunctionElementSegment? current; + int lastIndex = -2; + for (final entry in entries) { + final index = entry.key; + final function = entry.value; + if (index != lastIndex + 1) { + current = ir.ActiveFunctionElementSegment(table, index); + segments.add(current); + } + current!.entries.add(function); + lastIndex = index; + } + } else { + ir.ActiveExpressionElementSegment? current; + int lastIndex = -2; + for (final entry in entries) { + final index = entry.key; + final function = entry.value; + if (index != lastIndex + 1) { + current = ir.ActiveExpressionElementSegment(table, table.type, index); + segments.add(current); + } + current!.expressions.add([ir.RefFunc(function), ir.End()]); + lastIndex = index; + } + } + return segments; + } +}
diff --git a/pkg/wasm_builder/lib/src/builder/functions.dart b/pkg/wasm_builder/lib/src/builder/functions.dart index 6e957d5a..0999e08 100644 --- a/pkg/wasm_builder/lib/src/builder/functions.dart +++ b/pkg/wasm_builder/lib/src/builder/functions.dart
@@ -11,7 +11,6 @@ final ModuleBuilder _moduleBuilder; final _functionBuilders = <FunctionBuilder>[]; final _importedFunctions = <ir.ImportedFunction>[]; - final _declaredFunctions = <ir.BaseFunction>{}; FunctionsBuilder(this._moduleBuilder); @@ -45,17 +44,10 @@ return function; } - /// Declare [function] as a module element so it can be used in a constant - /// context. - void declare(ir.BaseFunction function) { - assert(function.enclosingModule == _moduleBuilder.module); - _declaredFunctions.add(function); - } - @override ir.Functions forceBuild() { final built = finalizeImportsAndBuilders<ir.DefinedFunction>( _importedFunctions, _functionBuilders); - return ir.Functions(_importedFunctions, built, [..._declaredFunctions]); + return ir.Functions(_importedFunctions, built); } }
diff --git a/pkg/wasm_builder/lib/src/builder/module.dart b/pkg/wasm_builder/lib/src/builder/module.dart index 088db5c..668d195 100644 --- a/pkg/wasm_builder/lib/src/builder/module.dart +++ b/pkg/wasm_builder/lib/src/builder/module.dart
@@ -26,7 +26,8 @@ final List<int> watchPoints; late final TypesBuilder types; late final functions = FunctionsBuilder(this); - late final tables = TablesBuilder(module); + late final elements = ElementsBuilder(this); + late final tables = TablesBuilder(this); late final memories = MemoriesBuilder(module); late final tags = TagsBuilder(module); final dataSegments = DataSegmentsBuilder(); @@ -54,6 +55,7 @@ ir.Module forceBuild() { final finalFunctions = functions.build(); final finalTables = tables.build(); + final finalElements = elements.build(); final finalMemories = memories.build(); final finalGlobals = globals.build(); final finalTags = tags.build(); @@ -70,6 +72,7 @@ finalFunctions, _startFunction, finalTables, + finalElements, finalTags, finalMemories, exports.build(),
diff --git a/pkg/wasm_builder/lib/src/builder/table.dart b/pkg/wasm_builder/lib/src/builder/table.dart index 3c30615..caea162 100644 --- a/pkg/wasm_builder/lib/src/builder/table.dart +++ b/pkg/wasm_builder/lib/src/builder/table.dart
@@ -7,25 +7,13 @@ /// A table defined in a module. class TableBuilder extends ir.Table with IndexableBuilder<ir.DefinedTable> { - final List<ir.BaseFunction?> elements; + final ModuleBuilder moduleBuilder; - TableBuilder(super.enclosingModule, super.index, super.type, super.minSize, - super.maxSize) - : elements = List.filled(minSize, null, growable: true); - - void setElement(int index, ir.BaseFunction function) { - assert(type.isSubtypeOf(ir.RefType.func(nullable: true)), - "Elements are only supported for funcref tables"); - assert(maxSize == null || index < maxSize!, - 'Index $index greater than max table size $maxSize'); - assert(function.enclosingModule == enclosingModule); - if (index >= elements.length) { - elements.length = index + 1; - } - elements[index] = function; - } + TableBuilder(this.moduleBuilder, ir.FinalizableIndex index, ir.RefType type, + int minSize, int? maxSize) + : super(moduleBuilder.module, index, type, minSize, maxSize); @override ir.DefinedTable forceBuild() => ir.DefinedTable( - enclosingModule, elements, finalizableIndex, type, minSize, maxSize); + enclosingModule, finalizableIndex, type, minSize, maxSize); }
diff --git a/pkg/wasm_builder/lib/src/builder/tables.dart b/pkg/wasm_builder/lib/src/builder/tables.dart index 4cb9dd8..793141d 100644 --- a/pkg/wasm_builder/lib/src/builder/tables.dart +++ b/pkg/wasm_builder/lib/src/builder/tables.dart
@@ -8,16 +8,16 @@ /// The interface for the tables in a module. class TablesBuilder with Builder<ir.Tables> { - final ir.Module _module; + final ModuleBuilder _moduleBuilder; final _tableBuilders = <TableBuilder>[]; final _importedTables = <ir.ImportedTable>[]; - TablesBuilder(this._module); + TablesBuilder(this._moduleBuilder); /// Defines a new table in this module. TableBuilder define(ir.RefType type, int minSize, [int? maxSize]) { - final table = - TableBuilder(_module, ir.FinalizableIndex(), type, minSize, maxSize); + final table = TableBuilder( + _moduleBuilder, ir.FinalizableIndex(), type, minSize, maxSize); _tableBuilders.add(table); return table; } @@ -26,8 +26,8 @@ ir.ImportedTable import( String module, String name, ir.RefType type, int minSize, [int? maxSize]) { - final table = ir.ImportedTable( - _module, module, name, ir.FinalizableIndex(), type, minSize, maxSize); + final table = ir.ImportedTable(_moduleBuilder.module, module, name, + ir.FinalizableIndex(), type, minSize, maxSize); _importedTables.add(table); return table; }
diff --git a/pkg/wasm_builder/lib/src/ir/element.dart b/pkg/wasm_builder/lib/src/ir/element.dart new file mode 100644 index 0000000..4e172dd --- /dev/null +++ b/pkg/wasm_builder/lib/src/ir/element.dart
@@ -0,0 +1,199 @@ +// Copyright (c) 2025, 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 '../serialize/serialize.dart'; +import 'ir.dart'; + +sealed class ElementSegment implements Serializable {} + +sealed class ActiveElementSegment extends ElementSegment { + final Table table; + final int startIndex; + + ActiveElementSegment(this.table, this.startIndex); +} + +/// Initializes a specific table with function references. +/// +/// NOTE: Can only be used if the table type is `RefType.func(nullable: true)`. +final class ActiveFunctionElementSegment extends ActiveElementSegment { + final List<BaseFunction> entries; + + ActiveFunctionElementSegment(super.table, super.startIndex, + [List<BaseFunction>? entries]) + : entries = entries ?? []; + + @override + void serialize(Serializer s) { + final useTable0Encoding = table.index == 0; + if (useTable0Encoding) { + s.writeByte(0x00); + } else { + s.writeByte(0x02); + s.writeUnsigned(table.index); + } + s.serializeTableOffset(startIndex); + + if (!useTable0Encoding) { + s.writeByte(_ElemKind.refFunc); + } + + s.writeUnsigned(entries.length); + for (var entry in entries) { + s.writeUnsigned(entry.index); + } + } + + static ActiveFunctionElementSegment deserialize( + Deserializer d, + Module module, + Types types, + Functions functions, + Tables tables, + Globals globals, + ) { + const int tableIndex = 0; + final byte = d.readByte(); + assert(byte == 0x00 || byte == 0x02); + + final offset = d.deserializeTableOffset(types, functions, globals); + + if (byte == 0x02) { + final elemKind = d.readByte(); + if (elemKind != _ElemKind.refFunc) { + throw UnimplementedError('Unsupported element kind.'); + } + } + + final table = tables[tableIndex]; + final tableElement = ActiveFunctionElementSegment(table, offset); + final count = d.readUnsigned(); + for (int i = 0; i < count; i++) { + tableElement.entries.add(functions[d.readUnsigned()]); + } + return tableElement; + } +} + +/// Initializes a specific table with initialization expressions. +final class ActiveExpressionElementSegment extends ActiveElementSegment { + final RefType type; + final List<List<Instruction>> expressions = []; + + ActiveExpressionElementSegment(super.table, this.type, super.startIndex); + + @override + void serialize(Serializer s) { + final useTableTable0RefNullFuncEncoding = + table.index == 0 && type == RefType.func(nullable: true); + if (useTableTable0RefNullFuncEncoding) { + s.writeByte(0x04); + } else { + s.writeByte(0x06); + s.writeUnsigned(table.index); + } + s.serializeTableOffset(startIndex); + if (!useTableTable0RefNullFuncEncoding) { + s.write(type); + } + s.writeUnsigned(expressions.length); + for (final expression in expressions) { + for (final instruction in expression) { + instruction.serialize(s); + } + } + } + + static ActiveExpressionElementSegment deserialize( + Deserializer d, + Module module, + Types types, + Functions functions, + Tables tables, + Globals globals, + ) { + final kind = d.readByte(); + assert(kind == 0x04 || kind == 0x06); + + final useTableTable0RefNullFuncEncoding = kind == 0x04; + final tableIndex = useTableTable0RefNullFuncEncoding ? 0 : d.readUnsigned(); + final offset = d.deserializeTableOffset(types, functions, globals); + final type = useTableTable0RefNullFuncEncoding + ? RefType.func(nullable: true) + : RefType.deserialize(d, types.defined); + + final table = tables[tableIndex]; + final tableElement = ActiveExpressionElementSegment(table, type, offset); + final count = d.readUnsigned(); + for (int i = 0; i < count; i++) { + final instructions = <Instruction>[]; + while (true) { + final instruction = + Instruction.deserializeConst(d, types, functions, globals); + instructions.add(instruction); + if (instruction is End) break; + } + tableElement.expressions.add(instructions); + } + return tableElement; + } +} + +final class DeclarativeElementSegment implements ElementSegment { + final List<BaseFunction> entries; + + DeclarativeElementSegment(this.entries); + + @override + void serialize(Serializer s) { + if (entries.isEmpty) return; + s.writeByte(0x03); + s.writeByte(_ElemKind.refFunc); + + s.writeUnsigned(entries.length); + for (final entry in entries) { + s.writeUnsigned(entry.index); + } + } + + static DeclarativeElementSegment deserialize( + Deserializer d, Functions functions) { + if (d.readByte() != 0x03) { + throw StateError('Expected declarative segment to start with 0x03.'); + } + + final elemkind = d.readByte(); + if (elemkind != _ElemKind.refFunc) { + throw UnsupportedError('Unsupported element kind: $elemkind'); + } + + final declaredFunctions = d.readList((d) => functions[d.readUnsigned()]); + return DeclarativeElementSegment(declaredFunctions); + } +} + +abstract class _ElemKind { + static const refFunc = 0; +} + +extension on Serializer { + void serializeTableOffset(int offset) { + I32Const(offset).serialize(this); + End().serialize(this); + } +} + +extension on Deserializer { + int deserializeTableOffset( + Types types, Functions functions, Globals globals) { + final i0 = Instruction.deserializeConst(this, types, functions, globals); + final i1 = Instruction.deserializeConst(this, types, functions, globals); + if (i0 is! I32Const || i1 is! End) { + throw StateError('Expected offset to be encoded as ' + '`(i32.const <value>) (end)`. ' + 'Got instead: (${i0.name}) (${i1.name})'); + } + return i0.value; + } +}
diff --git a/pkg/wasm_builder/lib/src/ir/elements.dart b/pkg/wasm_builder/lib/src/ir/elements.dart new file mode 100644 index 0000000..8dde374 --- /dev/null +++ b/pkg/wasm_builder/lib/src/ir/elements.dart
@@ -0,0 +1,11 @@ +// Copyright (c) 2025, 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 'ir.dart'; + +class Elements { + final List<ElementSegment> segments; + + Elements(this.segments); +}
diff --git a/pkg/wasm_builder/lib/src/ir/functions.dart b/pkg/wasm_builder/lib/src/ir/functions.dart index 6ea06ddc..1f15e45 100644 --- a/pkg/wasm_builder/lib/src/ir/functions.dart +++ b/pkg/wasm_builder/lib/src/ir/functions.dart
@@ -12,12 +12,7 @@ /// Defined functions. final List<DefinedFunction> defined; - /// Declared functions. - late final List<BaseFunction> declared; - - Functions(this.imported, this.defined, this.declared); - - Functions.withoutDeclared(this.imported, this.defined); + Functions(this.imported, this.defined); BaseFunction operator [](int index) => index < imported.length ? imported[index]
diff --git a/pkg/wasm_builder/lib/src/ir/ir.dart b/pkg/wasm_builder/lib/src/ir/ir.dart index b6cf0a2..481c4a7 100644 --- a/pkg/wasm_builder/lib/src/ir/ir.dart +++ b/pkg/wasm_builder/lib/src/ir/ir.dart
@@ -21,6 +21,14 @@ export 'memory.dart' show DefinedMemory, ImportedMemory, Memory, MemoryExport; export 'module.dart' show Module; export 'tables.dart' show Tables; +export 'elements.dart' show Elements; +export 'element.dart' + show + ElementSegment, + ActiveElementSegment, + ActiveFunctionElementSegment, + ActiveExpressionElementSegment, + DeclarativeElementSegment; export 'table.dart' show DefinedTable, ImportedTable, Table, TableExport; export 'tags.dart' show DefinedTag, ImportedTag, Tag, Tags, TagExport; export 'types.dart' show Types;
diff --git a/pkg/wasm_builder/lib/src/ir/module.dart b/pkg/wasm_builder/lib/src/ir/module.dart index 29cda4c..8ea4981 100644 --- a/pkg/wasm_builder/lib/src/ir/module.dart +++ b/pkg/wasm_builder/lib/src/ir/module.dart
@@ -26,6 +26,7 @@ late final Functions _functions; late final BaseFunction? _start; late final Tables _tables; + late final Elements _elements; late final Tags _tags; late final Memories _memories; late final Exports _exports; @@ -43,6 +44,7 @@ Functions functions, BaseFunction? start, Tables tables, + Elements elements, Tags tags, Memories memories, Exports exports, @@ -60,6 +62,7 @@ _functions = functions; _start = start; _tables = tables; + _elements = elements; _tags = tags; _memories = memories; _exports = exports; @@ -75,6 +78,7 @@ Functions get functions => _functions; BaseFunction? get start => _start; Tables get tables => _tables; + Elements get elements => _elements; Tags get tags => _tags; Memories get memories => _memories; Exports get exports => _exports; @@ -103,9 +107,7 @@ GlobalSection(globals.defined, watchPoints).serialize(s); ExportSection(exports.exported, watchPoints).serialize(s); StartSection(start, watchPoints).serialize(s); - ElementSection( - tables.defined, tables.imported, functions.declared, watchPoints) - .serialize(s); + ElementSection(elements, watchPoints).serialize(s); DataCountSection(dataSegments.defined, watchPoints).serialize(s); CodeSection(functions.defined, watchPoints).serialize(s); DataSection(dataSegments.defined, watchPoints).serialize(s); @@ -198,10 +200,7 @@ StartSection.deserialize(startFunctionSections?.single, functions); final elementSections = sections[ElementSection.sectionId]; - // As side-effect initializes [Table.elements] - // As side-effect initializes [ImprotedTable.setElements] - // As side-effect initializes [Functions.declaredFunctions] - ElementSection.deserialize( + final elements = ElementSection.deserialize( elementSections?.single, module, types, functions, tables, globals); final dataCountSections = sections[DataCountSection.sectionId]; @@ -230,6 +229,7 @@ functions, start, tables, + elements, tags, memories, exports,
diff --git a/pkg/wasm_builder/lib/src/ir/table.dart b/pkg/wasm_builder/lib/src/ir/table.dart index dc760d8..23d35b5 100644 --- a/pkg/wasm_builder/lib/src/ir/table.dart +++ b/pkg/wasm_builder/lib/src/ir/table.dart
@@ -41,14 +41,10 @@ /// A table defined in a module. class DefinedTable extends Table { - final List<BaseFunction?> elements; + DefinedTable(super.enclosingModule, super.finalizableIndex, super.type, + super.minSize, super.maxSize); - DefinedTable(super.enclosingModule, this.elements, super.finalizableIndex, - super.type, super.minSize, super.maxSize); - - void printTo(IrPrinter p, {bool includeElements = true}) { - // NOTE: This format differs from what V8's `wami` will print. - // It makes it easier to see the exact values of the table. + void printTo(IrPrinter p) { p.write('(table '); p.writeTableReference(this, alwaysPrint: true); String? exportName; @@ -65,23 +61,6 @@ p.write(' $minSize '); p.writeValueType(type); - if (includeElements) { - if (elements.any((e) => e != null)) { - p.writeln(); - p.withIndent(() { - for (int i = 0; i < elements.length; ++i) { - final function = elements[i]; - if (function != null) { - p.write('(def $i '); - p.writeFunctionReference(function); - p.writeln(')'); - } - } - }); - } - } else { - p.write(' <...>'); - } p.write(')'); } } @@ -93,9 +72,6 @@ @override final String name; - /// Functions to be inserted via the elements section. - final Map<int, BaseFunction> setElements = {}; - ImportedTable(super.enclosingModule, this.module, this.name, super.finalizableIndex, super.type, super.minSize, super.maxSize); @@ -107,29 +83,13 @@ super.serialize(s); } - void printTo(IrPrinter p, {bool includeElements = true}) { - // NOTE: This format differs from what V8's `wami` will print. - // It makes it easier to see the exact values of the table. + void printTo(IrPrinter p) { p.write('(table '); p.writeTableReference(this, alwaysPrint: true); p.write(' '); p.writeImport(module, name); p.write(' $minSize '); p.writeValueType(type); - if (includeElements) { - if (setElements.isNotEmpty) { - p.writeln(); - p.withIndent(() { - setElements.forEach((int i, function) { - p.write('(set $i '); - p.writeFunctionReference(function); - p.writeln(')'); - }); - }); - } - } else { - p.write(' <...>'); - } p.write(')'); } }
diff --git a/pkg/wasm_builder/lib/src/serialize/printer.dart b/pkg/wasm_builder/lib/src/serialize/printer.dart index 49e1136..bf511db 100644 --- a/pkg/wasm_builder/lib/src/serialize/printer.dart +++ b/pkg/wasm_builder/lib/src/serialize/printer.dart
@@ -26,6 +26,9 @@ final _types = <ir.DefType, String>{}; final _tags = <ir.Tag, String>{}; final _tables = <ir.Table, String>{}; + final _elementSegments = <ir.ElementSegment>{}; + final _activeElementSegments = <ir.Table, Map<int, String>>{}; + final _declarativeElements = <ir.DeclarativeElementSegment, String>{}; final _globals = <ir.Global, String>{}; final _functions = <ir.BaseFunction, String>{}; final _dataSegments = <ir.BaseDataSegment, String>{}; @@ -81,9 +84,84 @@ void enqueueTable(ir.Table table) { if (!_tables.containsKey(table)) { _tables[table] = ''; - _generateTable(table, - includeElements: settings.printTableElements( - tableNamer.nameTable(table, activateOnReferenceCallback: false))); + _generateTable(table); + + for (final segment in _module.elements.segments) { + if (segment is ir.ActiveElementSegment && segment.table == table) { + enqueueElementSegment(segment); + } + } + } + } + + void enqueueElementSegment(ir.ElementSegment segment) { + if (_elementSegments.add(segment)) { + switch (segment) { + case ir.ActiveFunctionElementSegment( + startIndex: final start, + table: final table, + entries: final entries + ): + final printedEntries = + _activeElementSegments.putIfAbsent(table, () => {}); + if (settings.printTableElements(tableNamer.nameTable(segment.table, + activateOnReferenceCallback: false))) { + for (int i = 0; i < entries.length; ++i) { + final index = start + i; + final ip = newIrPrinter(); + ip.write('('); + ir.RefFunc(entries[i]).printTo(ip); + ip.write(')'); + printedEntries[index] = ip.getText(); + } + } + + break; + case ir.ActiveExpressionElementSegment( + startIndex: final start, + table: final table, + expressions: final expressions + ): + final printedEntries = + _activeElementSegments.putIfAbsent(table, () => {}); + if (settings.printTableElements(tableNamer.nameTable(segment.table, + activateOnReferenceCallback: false))) { + for (int i = 0; i < expressions.length; ++i) { + final index = start + i; + final expression = expressions[i]; + final ip = newIrPrinter(); + for (int j = 0; j < expression.length; ++j) { + ip.write(j > 0 ? ' (' : '('); + expression[j].printTo(ip); + ip.write(')'); + } + printedEntries[index] = ip.getText(); + } + } + break; + case ir.DeclarativeElementSegment(entries: final entries): + final ip = newIrPrinter(); + ip.write('(elem declare'); + if (ip.preferMultiline) { + ip.indent(); + } + for (final entry in entries) { + if (ip.preferMultiline) { + ip.writeln(); + } else { + ip.write(' '); + } + ip.write('('); + ir.RefFunc(entry).printTo(ip); + ip.write(')'); + } + if (ip.preferMultiline) { + ip.deindent(); + } + ip.write(')'); + _declarativeElements[segment] = ip.getText(); + break; + } } } @@ -151,6 +229,13 @@ mp.writeln(); } } + for (final table in _module.tables.defined) { + final s = _tables[table]; + if (s != null) { + mp.write(s); + mp.writeln(); + } + } for (final tag in _module.tags.defined) { final s = _tags[tag]; if (s != null) { @@ -165,13 +250,30 @@ mp.writeln(); } } - for (final table in _module.tables.defined) { - final s = _tables[table]; - if (s != null) { - mp.write(s); - mp.writeln(); + _activeElementSegments.forEach((table, values) { + final ip = newIrPrinter(); + ip.write('(elem '); + ip.writeTableReference(table, alwaysPrint: true); + if (values.isEmpty) { + ip.write(' <...>'); + } else { + ip.withIndent(() { + final indices = values.keys.toList()..sort(); + for (int i = 0; i < indices.length; ++i) { + ip.writeln(); + final index = indices[i]; + final value = values[index]!; + ip.write('(set $index $value)'); + } + }); } - } + ip.write(')'); + mp.writeln(ip.getText()); + }); + _declarativeElements.forEach((_, value) { + mp.writeln(value); + }); + for (final fun in _module.functions.defined) { final s = _functions[fun]; if (s != null) { @@ -197,12 +299,12 @@ _tags[tag] = p.getText(); } - void _generateTable(ir.Table table, {required bool includeElements}) { + void _generateTable(ir.Table table) { final p = newIrPrinter(); if (table is ir.DefinedTable) { - table.printTo(p, includeElements: includeElements); + table.printTo(p); } else if (table is ir.ImportedTable) { - table.printTo(p, includeElements: includeElements); + table.printTo(p); } else { return; }
diff --git a/pkg/wasm_builder/lib/src/serialize/sections.dart b/pkg/wasm_builder/lib/src/serialize/sections.dart index 3ae4b13..6b73699 100644 --- a/pkg/wasm_builder/lib/src/serialize/sections.dart +++ b/pkg/wasm_builder/lib/src/serialize/sections.dart
@@ -240,7 +240,7 @@ static ir.Functions deserialize(Deserializer? d, ir.Module module, ir.Types types, List<ir.ImportedFunction> imported) { if (d == null) { - return ir.Functions.withoutDeclared(imported, []); + return ir.Functions(imported, []); } final List<ir.DefinedFunction> defined = []; @@ -252,7 +252,7 @@ module, ir.FinalizableIndex()..value = imported.length + i, type); defined.add(function); } - return ir.Functions.withoutDeclared(imported, defined); + return ir.Functions(imported, defined); } } @@ -286,7 +286,6 @@ final maxSize = limits == 0x01 ? d.readUnsigned() : null; final table = ir.DefinedTable( module, - [], ir.FinalizableIndex()..value = imported.length + i, type, minSize, @@ -500,188 +499,24 @@ } } -sealed class _Element implements Serializable {} - -class _TableElement implements _Element { - final ir.Table table; - final int startIndex; - final List<ir.BaseFunction> entries = []; - - _TableElement(this.table, this.startIndex); - - @override - void serialize(Serializer s) { - final int kind; - if (table.index == 0) { - kind = 0x00; - s.writeByte(kind); - } else { - kind = 0x06; - s.writeByte(kind); - s.writeUnsigned(table.index); - } - - ir.I32Const(startIndex).serialize(s); - ir.End().serialize(s); - - if (kind == 0x06) { - s.write(table.type); - } - s.writeUnsigned(entries.length); - for (var entry in entries) { - if (kind == 0x0) { - s.writeUnsigned(entry.index); - } else { - ir.RefFunc(entry).serialize(s); - ir.End().serialize(s); - } - } - } - - static _TableElement deserialize( - Deserializer d, - ir.Module module, - ir.Types types, - ir.Functions functions, - ir.Tables tables, - ir.Globals globals, - ) { - final int tableIndex; - final kind = d.readByte(); - switch (kind) { - case 0x00: - tableIndex = 0; - break; - case 0x06: - tableIndex = d.readUnsigned(); - break; - default: - throw "unsupported element segment kind $kind"; - } - - final i0 = ir.Instruction.deserializeConst(d, types, functions, globals); - final i1 = ir.Instruction.deserializeConst(d, types, functions, globals); - if (i0 is! ir.I32Const || i1 is! ir.End) { - throw StateError('Expected offset to be encoded as ' - '`(i32.const <value>) (end)`. ' - 'Got instead: (${i0.name}) (${i1.name})'); - } - final offset = i0.value; - - if (kind == 0x06) { - ir.RefType.deserialize(d, types.defined); - } - - final table = tables[tableIndex]; - final tableElement = _TableElement(table, offset); - final count = d.readUnsigned(); - for (int i = 0; i < count; i++) { - if (kind == 0x0) { - tableElement.entries.add(functions[d.readUnsigned()]); - } else { - final i0 = - ir.Instruction.deserializeConst(d, types, functions, globals); - final i1 = - ir.Instruction.deserializeConst(d, types, functions, globals); - if (i0 is! ir.RefFunc || i1 is! ir.End) { - throw StateError('Expected function reference to be encoded as ' - '`(ref.func <value>) (end)`. ' - 'Got instead: (${i0.name}) (${i1.name})'); - } - tableElement.entries.add(i0.function); - } - } - return tableElement; - } -} - -class _DeclaredElement implements _Element { - final List<ir.BaseFunction> entries; - - _DeclaredElement(this.entries); - - @override - void serialize(Serializer s) { - if (entries.isEmpty) return; - s.writeByte(0x03); - s.writeByte(0x00); - - s.writeUnsigned(entries.length); - for (final entry in entries) { - s.writeUnsigned(entry.index); - } - } - - static _DeclaredElement deserialize(Deserializer d, ir.Functions functions) { - if (d.readByte() != 0x03) throw 'bad encoding'; - - final elemkind = d.readByte(); - if (elemkind != 0x00) throw "unsupported elemkind"; - - final declaredFunctions = d.readList((d) => functions[d.readUnsigned()]); - return _DeclaredElement(declaredFunctions); - } -} - class ElementSection extends Section { static const int sectionId = 9; - final List<ir.DefinedTable> definedTables; - final List<ir.ImportedTable> importedTables; - final List<ir.BaseFunction> declaredFunctions; + final ir.Elements elementSegments; - ElementSection(this.definedTables, this.importedTables, - this.declaredFunctions, super.watchPoints); + ElementSection(this.elementSegments, super.watchPoints); @override int get id => sectionId; @override void serializeContents(Serializer s) { - // Group nonempty element entries into contiguous stretches and serialize - // each stretch as an element. - List<_Element> elements = []; - for (final table in definedTables) { - _TableElement? current; - for (int i = 0; i < table.elements.length; i++) { - ir.BaseFunction? function = table.elements[i]; - if (function != null) { - if (current == null) { - current = _TableElement(table, i); - elements.add(current); - } - current.entries.add(function); - } else { - current = null; - } - } - } - for (final table in importedTables) { - final entries = [...table.setElements.entries] - ..sort((a, b) => a.key.compareTo(b.key)); - - _TableElement? current; - int lastIndex = -2; - for (final entry in entries) { - final index = entry.key; - final function = entry.value; - if (index != lastIndex + 1) { - current = _TableElement(table, index); - elements.add(current); - } - current!.entries.add(function); - lastIndex = index; - } - } - if (declaredFunctions.isNotEmpty) { - elements.add(_DeclaredElement(declaredFunctions)); - } - if (elements.isNotEmpty) { - s.writeList(elements); + if (elementSegments.segments.isNotEmpty) { + s.writeList(elementSegments.segments); } } - static void deserialize( + static ir.Elements deserialize( Deserializer? d, ir.Module module, ir.Types types, @@ -690,38 +525,36 @@ ir.Globals globals, ) { if (d == null) { - functions.declared = []; - return; + return ir.Elements([]); } - final declaredFunctions = <ir.BaseFunction>[]; + + final segments = <ir.ElementSegment>[]; final count = d.readUnsigned(); for (int i = 0; i < count; i++) { - if (d.peekByte() == 0x03) { - final declaredElement = _DeclaredElement.deserialize(d, functions); - declaredFunctions.addAll(declaredElement.entries); + final byte = d.peekByte(); + if (byte == 0x03) { + // Declarative segment, only to forward-declare functions. + final es = ir.DeclarativeElementSegment.deserialize(d, functions); + segments.add(es); continue; } - final tableElement = _TableElement.deserialize( - d, module, types, functions, tables, globals); - for (int i = 0; i < tableElement.entries.length; i++) { - final table = tableElement.table; - final offset = tableElement.startIndex; - final function = tableElement.entries[i]; - - if (table is ir.DefinedTable) { - if (table.elements.length <= offset + i) { - table.elements.length = offset + i + 1; - } - table.elements[offset + i] = function; - } else if (table is ir.ImportedTable) { - table.setElements[offset + i] = function; - } else { - throw "unsupported table type $table"; - } + if (byte == 0x00 || byte == 0x02) { + // Active element, table values are function indices. + final es = ir.ActiveFunctionElementSegment.deserialize( + d, module, types, functions, tables, globals); + segments.add(es); + continue; + } + if (byte == 0x04 || byte == 0x06) { + // Active element, table values are expressions. + final es = ir.ActiveExpressionElementSegment.deserialize( + d, module, types, functions, tables, globals); + segments.add(es); + continue; } } - functions.declared = declaredFunctions; + return ir.Elements(segments); } }
diff --git a/sdk/lib/_internal/wasm/lib/type.dart b/sdk/lib/_internal/wasm/lib/type.dart index 2222c78..f6d62ce 100644 --- a/sdk/lib/_internal/wasm/lib/type.dart +++ b/sdk/lib/_internal/wasm/lib/type.dart
@@ -1780,10 +1780,6 @@ /// Checks that argument lists have expected number of arguments for the /// closure. /// -/// If the type argument list ([typeArguments]) is empty but the closure has -/// type parameters, updates [typeArguments] with the default bounds of the -/// type parameters. -/// /// [namedArguments] is a list of `Symbol` and `Object?` pairs. @pragma("wasm:entry-point") bool _checkClosureShape(
diff --git a/tests/web/wasm/closures/dynamic_call_via_field_test.dart b/tests/web/wasm/closures/dynamic_call_via_field_test.dart new file mode 100644 index 0000000..6bc4d2d --- /dev/null +++ b/tests/web/wasm/closures/dynamic_call_via_field_test.dart
@@ -0,0 +1,21 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:expect/expect.dart'; + +void main() { + final runtimeTrue = int.parse('1') == 1; + final dynamic object = runtimeTrue ? A() : 'a'; + + // The purpose of this test is to ensure that dar2wasm's closed-world closure + // layouter will consider `(foobar: 1)` as a closure call site and therefore + // register `foobar` to be a used name combination. + Expect.equals('foo<$int>(1)', object.closureGetter<int>(foobar: 1)); +} + +class A { + void Function<T>() get closureGetter => foo; +} + +String foo<T>({int? foobar}) => "foo<$T>($foobar)";
diff --git a/tests/web/wasm/closures/function_apply_test.dart b/tests/web/wasm/closures/function_apply_test.dart new file mode 100644 index 0000000..7547272 --- /dev/null +++ b/tests/web/wasm/closures/function_apply_test.dart
@@ -0,0 +1,29 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "package:expect/expect.dart"; + +main() { + // Prevent constant propagation of closure into `Function.apply`. + for (final (name, closure) in <(String, Function)>[ + ('static1', static1), + ('static2', static2), + ]) { + test('$name: 1 missing-b', closure, [1]); + test('$name: 1 2', closure, [1, 2]); + } +} + +String static1(a, [b = 'missing-b']) => 'static1: $a $b'; +String static2(a, [b = 'missing-b']) => 'static2: $a $b'; + +void test(String expected, Function function, List positional) { + Expect.equals(expected, Function.apply(function, positional)); + final oneMoreThanAllowed = [ + for (int i = positional.length; i < 3; ++i) 'extra$i', + ]; + Expect.throwsNoSuchMethodError( + () => Function.apply(function, [...positional, ...oneMoreThanAllowed]), + ); +}
diff --git a/tools/VERSION b/tools/VERSION index 1305895..960133e 100644 --- a/tools/VERSION +++ b/tools/VERSION
@@ -27,5 +27,5 @@ MAJOR 3 MINOR 11 PATCH 0 -PRERELEASE 112 +PRERELEASE 113 PRERELEASE_PATCH 0