A constructor that forwards all its parameters to a https://dart.dev/language/constructors#non-default-superclass-constructors[superclass constructor] should use https://dart.dev/language/constructors#super-parameters[`super` parameters] (e.g. `ConstructorName(super.field)`) instead of manually forwarding each parameter (as in `ConstructorName(int field) : super(field)`).

== Why is this an issue?

In Dart, constructors can "forward" their parameters to a constructor of the parent class, using the `super` keyword.

[source,dart]
----
class ComplexNumber {
  final double real;
  final double imaginary;

  const ComplexNumber(this.real, this.imaginary);
}

class RealNumber extends ComplexNumber {
  const RealNumber(double real) : super(real, 0); // Forwards the `real` parameter
}
----

When a constructor forwards all its parameters to a superclass constructor, and does not alter them in any way, it is recommended to use https://dart.dev/language/constructors#super-parameters[`super` parameters] instead of manually forwarding each parameter.

[source,dart]
----
class Point {
  final int x;
  final int y;

  const Point(this.x, this.y);
}

class ThreeDPoint extends Point {
  final int z;

  const ThreeDPoint(super.x, super.y, this.z);
}
----

=== What is the potential impact?

Manually forwarding parameters is more verbose. It can also be error-prone. For instance, if the superclass constructor has multiple parameters of the same type, there is the risk of mixing them up:

[source,dart]
----
class Parent {
  final int field1;
  final int field2;

  const Parent(this.field1, this.field2);
}

class Child extends Parent {
  const Child(int field2, int field1) : super(field2, field1); // Wrong order
}
----

This cannot happen with `super` parameters, no matter what is the order of parameters declared in the `Child` class, as they are matched by name.

=== Exceptions

The rule doesn't apply if parameters are altered before being passed to the superclass constructor. 

For example, if they need to be swapped:

[source,dart]
----
class Child extends Parent {
  const Child(int field1, int field2) : super(field2, field1); // Non applicable
}
----

or their values transformed:

[source,dart]
----
class Child extends Parent {
  const Child(int field1, int field2) : super(field1 + field2, field1 - field2); // Non applicable
}
----

On the other hand, changing the type of the parameter in the subclass with a compatible one is not considered a transformation, so the rule applies:

[source,dart]
----
class Child extends Parent {
  const Child(dynamic field1, dynamic field2) : super(field1, field2); // Non compliant
}
----

Similarly, the rule applies if the parameter has a different name in the child class:

[source,dart]
----
class Child extends Parent {
  const Child(int field3, int field4) : super(field3, field4); // Non compliant
}
----

However, it's enough for a single parameter to be altered for the rule to be considered as not applicable:

[source,dart]
----
class Child extends Parent {
  Child(int field1) : super(field1, field1.hashCode); // Non applicable
}
----

That includes swapping them:

[source,dart]
----
class Child extends Parent {
  Child(int field1, int field2) : super(field2, field1); // Non applicable
}
----

== How to fix it

Remove the call to the superclass constructor and replace normal parameters with `super` parameters, matching the names of the parameter in the parent class.

=== Code examples

==== Noncompliant code example

[source,dart,diff-id=1,diff-type=noncompliant]
----
class Point {
  final int x;
  final int y;

  const Point(this.x, this.y);
}

class ThreeDPoint extends Point {
  final int z;

  const ThreeDPoint(int x, int y, this.z): super(x, y);
}
----

==== Compliant solution

[source,dart,diff-id=1,diff-type=compliant]
----
class Point {
  final int x;
  final int y;

  const Point(this.x, this.y);
}

class ThreeDPoint extends Point {
  final int z;

  const ThreeDPoint(super.x, super.y, this.z);
}
----

== Resources

=== Documentation

* Dart Docs - https://dart.dev/tools/linter-rules/use_super_parameters[Dart Linter rule - use_super_parameters]
* Dart Docs - https://dart.dev/language/constructors#non-default-superclass-constructors[Language - Non-default superclass constructors]
* Dart Docs - https://dart.dev/language/constructors#super-parameters[Language - Super parameters]


ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

* Convert '<parameterName>' to a super parameter.
* Convert '<parameterName1>' and '<parameterName2>' to super parameters.
* Convert '<parameterName1>' (, '<parameterNameI>')+, and '<parameterNameN>' to super parameters.

=== Highlighting

The identifier of the constructor at the declaration site.

endif::env-github,rspecator-view[]
