[ddc] Fix named args in redirecting constructors
Change-Id: Iaed36c3cab43672338a5b1750aad25951428052c
Fixes: https://github.com/dart-lang/sdk/issues/47831
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/221887
Reviewed-by: Mark Zhou <markzipan@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index ec112bc..a25692d 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -1612,14 +1612,12 @@
var fn = node.function;
var body = _emitArgumentInitializers(fn, node.name.text);
- // Redirecting constructors: these are not allowed to have initializers,
- // and the redirecting ctor invocation runs before field initializers.
- var redirectCall = node.initializers
- .firstWhere((i) => i is RedirectingInitializer, orElse: () => null)
- as RedirectingInitializer;
-
- if (redirectCall != null) {
- body.add(_emitRedirectingConstructor(redirectCall, className));
+ // Redirecting constructors are not allowed to have conventional
+ // initializers but can have variable declarations in the form of
+ // initializers to support named arguments appearing anywhere in the
+ // arguments list.
+ if (node.initializers.any((i) => i is RedirectingInitializer)) {
+ body.add(_emitRedirectingConstructor(node.initializers, className));
return body;
}
@@ -1652,15 +1650,23 @@
}
js_ast.Statement _emitRedirectingConstructor(
- RedirectingInitializer node, js_ast.Expression className) {
- var ctor = node.target;
- // We can't dispatch to the constructor with `this.new` as that might hit a
- // derived class constructor with the same name.
- return js.statement('#.#.call(this, #);', [
- className,
- _constructorName(ctor.name.text),
- _emitArgumentList(node.arguments, types: false)
- ]);
+ List<Initializer> initializers, js_ast.Expression className) {
+ var jsInitializers = <js_ast.Statement>[
+ for (var init in initializers)
+ if (init is LocalInitializer)
+ // Temporary locals are created when named arguments don't appear at
+ // the end of the arguments list.
+ visitVariableDeclaration(init.variable)
+ else if (init is RedirectingInitializer)
+ // We can't dispatch to the constructor with `this.new` as that might
+ // hit a derived class constructor with the same name.
+ js.statement('#.#.call(this, #);', [
+ className,
+ _constructorName(init.target.name.text),
+ _emitArgumentList(init.arguments, types: false)
+ ])
+ ];
+ return js_ast.Block(jsInitializers);
}
js_ast.Statement _emitSuperConstructorCallIfNeeded(