sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Macro-augmented constructor loses const-ness and default values

Open goderbauer opened this issue 6 months ago • 2 comments

Code:

void m() {
  const Foo(); // 🔥 error: The constructor being called isn't a const constructor. (const_with_non_const)
}

@MyMacro()
class Foo {
  const Foo({int a = 0});
}

Macro:

macro class MyMacro implements ClassDefinitionMacro {
  const MyMacro();

  @override
  FutureOr<void> buildDefinitionForClass(ClassDeclaration clazz, TypeDefinitionBuilder builder) async {
    final List<ConstructorDeclaration> constructors = await builder.constructorsOf(clazz);
    final ConstructorDefinitionBuilder constructorBuilder = await builder.buildConstructor(constructors.first.identifier);
    constructorBuilder.augment(initializers: [DeclarationCode.fromParts(['assert(1 != 0)'])]);
  }
}

Generated code:

augment class Foo {
  augment Foo({prefix1.int a, }) // 🔥 error: The parameter 'a' can't have a value of 'null' because of its type, but the implicit default value is 'null'. (missing_default_value_for_parameter)
      : assert(1 != 0);
}

There are two issues (see the 🔥 lines above) when augmenting a constructor with ConstructorDefinitionBuilder.augment in a macro:

  • The constructor (which was declared const in the original code) is apparently no longer const.
  • The default value of the constructor parameter is lost.

Should the constructor augmentation inherit these traits from the augmented constructor? Or is the macro maybe generating incomplete code and should instead generate:

augment class Foo {
  augment const Foo({prefix1.int a = 0, })
      : assert(1 != 0);
}

Or am I holding this wrong?

goderbauer avatar Aug 19 '24 21:08 goderbauer