Skip to content

refactor: Doc comments from Parameter AstNode. #1

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

pattobrien
Copy link
Owner

@pattobrien pattobrien commented Feb 14, 2024

This PR is tracking a refactor to allow doc comments to be inferred from the ASTNode tree.

Problem

The Dart analyzer's Element model allows for accessing doc comments on an Element, but ParameterElements only ever contain doc comments if they are a Formal Parameter that relates to a field.

/// Command-level doc comment
@cliCommand
Future<void> myCustomCommand({
  // Parameter doc comment (not available in ParameterElement.docComments)
  required String requiredParam,
)} { /* ... */ }


class Foo {
  /// Field-level doc comment
  final String myField;

  const Foo({
    required this.myField, // parameter `this.myField` inherits doc comments from `myField`
  )};

Only in the second case are we able to get doc comments from the Parameter element. What this means is that there is no idiomatic Dart way of inferring --help comments from a Parameter, at least from the element model.

Potential Solutions

Access doc comments via ASTNode

We're easily able to get the doc comment via the ASTNode of the parameter. Users would simply document the parameter of a method/function (as shown above) which would generate the help text.

However, for the upcoming macros feature, it's unclear whether or not the API will allow access to the ASTs. If it is an option (or if we can e.g. read the raw source code and parse it ourselves), then this would likely be the go-to solution. If the AST tree is not available to macros, though, then this would be a case where the user experience is different between build_runner and macros.

relevant issue

Doc Comments via Annotations

We already ship an @Option annotation, which allows doc comments and other explicit values to reach the element model via constant evaluation (i.e. the DartObject interface).

@cliCommand
Future<void> myCustomCommand({
  @Option(help: 'My parameter doc comment')
  required String requiredParam,
)} { /* ... */ }

This isn't the most elegant solution, but it gets the job done. In the case of documenting every single parameter of a method, if users create complex methods with many args, the amount of annotation use will surely be a negative experience.

Arg classes

Another solution is to recommend that users create separate Arg classes for each function, which would allow users to generate help text from doc comments on the Fields of the Arg class.

@cliArgs
class MyCustomCommandArgs {
  const MyCustomCommandArgs({
    required this.requiredParam,
  )};

  /// Some doc comment
  final String requiredParam;
}

// usage below

@cliCommand
Future<void> myCustomCommand(
  MyCustomCommandArgs args,
} { /* ... */ }

This solution makes intuitive sense, and we could recommend this approach for all argument generation, so that it becomes the default way of doing things (rather than individual parameters on a method/function). We lose a little flexibility and gain some verbosity, but in return gain a good amount too. Its possible that macros would help trim the verbosity a good amount as well.

This solution needs a little more investigation to see how effective it is in practice.

Copy link

codecov bot commented Feb 14, 2024

Welcome to Codecov 🎉

Once merged to your default branch, Codecov will compare your coverage reports and display the results in this comment.

Thanks for integrating Codecov - We've got you covered ☂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant