Skip to content

fix(graindoc): Add all function parameters to the table, even if missing documentation #2293

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 3 commits into
base: main
Choose a base branch
from

Conversation

marcusroberts
Copy link
Member

@marcusroberts marcusroberts commented May 22, 2025

Partially Fixes #2281

Add all function parameters to the documentation table in the order they are defined.

Add an empty documentation field for any that are missing user supplied documentation in the comment above.

(New and Updated tests to follow)

@marcusroberts marcusroberts marked this pull request as draft May 22, 2025 20:41
@marcusroberts marcusroberts marked this pull request as ready for review June 2, 2025 19:25
@marcusroberts marcusroberts requested a review from peblair as a code owner June 2, 2025 19:25
@marcusroberts
Copy link
Member Author

Take care when merging #2292 which makes changes to Graindoc.

Copy link
Member

@spotandjake spotandjake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the stdlib needs to be regened npm run stdlib doc, I think we still want to maintain the errors from before to ensure docs are well structured, and alert people when they mistype params.

);

let match_label_to_arg = arg => {
List.find_opt(((name, _)) => name == arg, param_attributes);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think List.assoc_opt or List.assq_opt might be what you want to use here https://ocaml.org/manual/5.3/api/List.html#1_Associationlists

let matched =
switch (match_label_to_arg(param_id)) {
| Some(_) as result => result
| None => match_label_to_arg(string_of_int(index))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the behaviour here that if you documented a param as x but the function only has position params we would map x to 0 for instance?

let documentation =
switch (matched) {
| Some((_, Comment_attributes.Param({attr_desc}))) => attr_desc
| _ => ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be throwing some sort of exception here?

| Some((Default(_), {desc: TTyConstr(_, [typ], _)})) =>
Printtyp.string_of_type_sch(typ)
| Some((_, typ)) => Printtyp.string_of_type_sch(typ)
| None => ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be throwing some sort of exception here? And do you know if there is any real case this would occur?

// Get parameter type
let param_type =
switch (lookup_arg_by_label(param_id, args)) {
| Some((Labeled(_), typ)) => Printtyp.string_of_type_sch(typ)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This could probably use an or pattern, instead of handling each branch with the same logic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also test a function without the params documented at all, and an only positional argument.

We might also want to test the failing cases, i.e a param doesn't exist.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. Every other test covered this case as they all have undocumented params so I use those as my test case, but an explicit one would be better

// Get parameter type
let param_type =
switch (lookup_arg_by_label(param_id, args)) {
| Some((Labeled(_), typ)) => Printtyp.string_of_type_sch(typ)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We could use an or pattern here to reduce the number of branches.

string_of_int(idx),
Printtyp.string_of_type_sch(typ),
)
| None => raise(MissingUnlabeledParamType({idx: idx}))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we never throw these errors anymore?

  • Do we now allow labeling a positional arg with a label and the other way around? i.e:
/*
 * @param x: test
 */
 let test = (_ as x) => void
  • What happens now if you document a non existing param, or too many positional params?

I see we removed it here and decided to handle the cases but are we sure we want to from a linting and correctness standpoint?

};

// First try to match by name, then by position
let matched =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the logic match specifially by name or position? i.e if we see an int its a position and a name its a position? This way we can continue to give the well formedness errors from before.

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.

Graindoc: Consider warning or adding undocumented params to the param table.
2 participants