-
Notifications
You must be signed in to change notification settings - Fork 209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to write doc comment or metadata on primary constructor #3300
Comments
I'm not sure about the metadata, but the answer in Kotlin to the questions about the doc comments, is that all of that goes in the doc comment for the class. |
Putting the constructor documentation into the class documentation worked for Kotlin because they have doc-tags like Dart has so far chosen not to have doc tags, and rely on convention like a paragraph starting with "Returns" being the documentation of the returned value, and an early reference to a parameter starting the parameter documentation, like " That means that our tools can't easily provide the documentation for just a single parameter the way Java/Kotlin can. We can document the individual parameters if we want to, by taking DartDoc on the primary constructor parameter as documentation for the implicit field: class Foo(
/// The number of bars.
int bar,
/// ...
) ... But there is no good place to put documentation for the constructor. Maybe if we put the constructor last: class Foo implements FooBar
/// Constructs a foo.
///
/// The `bar` is the number of bars.
new(
/// Number of bars.
final int bar,
) {
..
} Where you can document the constructor by putting a comment before the primary constructor declaration, and the fields out introduces by putting comments on the field-declaring parameters. At that point, we might as well just declare it inside the body as: class Foo implements FooBar {
/// Constructs a foo.
///
/// The `bar` is the number of bars.
primary new(
/// Number of bars.
final int bar,
) {
..
} (Can still use dartdoc on "field parameters" as property documentation.) |
True, but this might be OK. Primary constructors (as I've been thinking about them while writing this feature specification, and I think I'm not alone in that respect) are optimized for simple and small declarations. This might justify the advice that the documentation of the constructor is integrated into the documentation of the class, and DartDoc pages would show the documentation for the class as the documentation of the primary constructor as well. In that case it isn't necessary to introduce tags like If there is a need to add more detail then the primary constructor in the header can be turned into a primary constructor in the body: /// An extension type.
extension type V1 {
/// Wraps an [int] as a [V1].
primary V1(int it);
...
} |
It's a small tangent, but honestly I wish Dart allowed docs on parameters. class Foo {
Foo({
// The IDE will show a's docs when the parameter is hovered
this.a,
});
/// This is documented
final int? a;
} To me it's counter intuitive that we don't allow: class Foo {
Foo({
// Allow the IDE to still show docs
/// Documentation for a
int? a,
}) : _a = a;
final int? _a;
} If we could do that, then docs on primary constructors likely wouldn't be an issue. Right? |
There are several things in play here:
We have the first one, which is why I'd definitely want the second item: Allowing you to write DartDoc on a primary constructor field parameter, one which implicitly introduces a field, so that that field can get DartDoc too. It'd be completely fair to treat the result as equivalent to a documented field and an initializing formal with the same name. That should just work. Then there is what I believe you are suggesting here: Allowing docs on parameters in general, to be shown on hover. And then there is the discussion of whether we can allow an primary constructor initializing formal to have a private name, and still expose a public-named parameter, like (Again, let's not try top automatically rename references inside docs. Maybe we could allow dartdoc macros to be parameterized, so you can reuse, but also change the name: default Floo(
/// {@template isFastDoc name}
/// Whether this floo is fast.
///
/// If [@{templatearg name}] is `null`, it's unknown whether the floo is fast.
/// Any attempt to [Floo.actFast] may fail, so you should use [Floo.tryActFast].
/// {@endtemplate)
/// {@macro isFastDoc #fast} <!-- the #fast is checked to resolve to a name in scope, use "fast" if you don't want that -->
bool? fast,
) : isFast = fast;
/// {@macro isFastDoc #isFast}
final bool? isFast; But also, you can just copy, it's only two occurrences, so there are limits to how much effort is worth it.) |
To be clear, I wasn't necessarily talking about private parameters here but rather initializers in general. Class({required List list}):
list = list.map(...).toList(); or: Class({Color? primaryColor, this.scheme}):
primaryColor = primaryColor ?? scheme?[0] ?? fallback; Heck sometimes constructor parameters don't even have an associated field. This makes dartdoc a bit unpredictable. Sometimes the IDE shows useful doc; sometimes it doesn't. And it can vary between two versions of the same package. Because after a refactoring, maybe an initializer was added/removed. |
I've been thinking a little bit about how primary constructors could help with cutting down verbosity in Flutter - and I share some of the concerns w.r.t. to documentation discussed in this issue: In Flutter, the doc comments on constructors are mostly just there to check the box that all public members have docs. They rarely add anything useful. Therefore, I don't think we need a dedicated place for docs of the primary constructor itself. Usually, the class comment as a whole is just sufficient here. However, we do need a place to provide docs for the individual parameters of the primary constructor (the docs that traditionally would just go on the fields). There's lots of great documentation on the fields today that I wouldn't want to loose and I also wouldn't want to turn the class docs into a wall of text that include documentation for each argument. Something with a little more structure would be desirable. I really like putting the parameter docs inline into the primary constructor: /// A widget that shows the current count along with a button to increase it.
class Counter const (
super.key,
/// The name of the counter.
///
/// Will be displayed in the UI.
String name,
/// The starting value for the counter.
///
/// Defaults to 0.
int startValue = 0,
) extends StatelessWidget {
// ...
} |
I believe that neither the spec for extension types nor the proposed spec for primary constructors allow for doc comments or metadata (annotations) on a primary constructor.
Maybe that's fine. Let's examine each of these cases:
Cannot specify doc comment on an extension type's primary constructor
Well, an extension type's primary constructor can only have one parameter. The meaning of that parameter is always the same. Maybe it is difficult to conceive of a case where a doc comment specific to the primary constructor is important.
If the ability to specify doc comments is important, maybe we can just introduce a doc comment directive, e.g.
(Doc comment directives use kebab case; it is important to use as many cases in a programming language as possible.)
Cannot specify metadata on an extension type's primary constructor
This one worries me because I have to imagine there are plenty of cases where users desire to annotate a constructor. Maybe many cases can be handled by just assuming an annotation on the extension type is intended for the primary constructor. Maybe not.
I want to highlight the 3 primary purposes of annotations:
@visibleForTesting
,@experimental
, etc.Cannot specify doc comment on a (class's, etc.) primary constructor
Move the constructor (and fields) to be written explicitly, and then document the constructor as usual. The same goes for documenting the fields.
Cannot specify metadata on a (class's, etc.) primary constructor
Move the constructor (and fields) to be written explicitly, and then annotate as usual.
The text was updated successfully, but these errors were encountered: