Skip to content

Commit

Permalink
feat(graindoc)!: Add --current-version flag, required for since/his…
Browse files Browse the repository at this point in the history
…tory attributes (grain-lang#1116)

chore(stdlib): Regenerate markdown docs with `--current-version` flag
  • Loading branch information
phated authored Feb 3, 2022
1 parent d7386eb commit 0f681ea
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 45 deletions.
4 changes: 4 additions & 0 deletions cli/bin/grain.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ program
program
.command("doc <file>")
.description("generate documentation for a grain file")
.forwardOption(
"--current-version <version>",
"provide a version to use as current when generating markdown for `@since` and `@history` attributes"
)
.action(
wrapAction(function (file, options, program) {
doc(file, program);
Expand Down
64 changes: 52 additions & 12 deletions compiler/graindoc/docblock.re
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,27 @@ type t = {
attributes: list(Comments.Attribute.t),
};

exception
MissingFlag({
flag: string,
attr: string,
});

let () =
Printexc.register_printer(exn => {
switch (exn) {
| MissingFlag({flag, attr}) =>
let msg =
Printf.sprintf(
"Must provide %s when generating docs with `%s` attribute.",
flag,
attr,
);
Some(msg);
| _ => None
}
});

let module_name_of_location = (loc: Grain_parsing.Location.t) => {
Grain_utils.Files.filename_to_module_name(loc.loc_start.pos_fname);
};
Expand All @@ -27,6 +48,35 @@ let title_for_api = (~module_name, ident: Ident.t) => {
Format.asprintf("%s.**%a**", module_name, Printtyp.ident, ident);
};

let output_for_since = (~current_version, attr_version) => {
let current_version =
switch (current_version) {
| Some(version) => version
| None => raise(MissingFlag({flag: "--current-version", attr: "@since"}))
};
let (<) = Version.String.less_than;
if (current_version < attr_version) {
Format.sprintf("Added in %s", Html.code("next"));
} else {
Format.sprintf("Added in %s", Html.code(attr_version));
};
};

let output_for_history = (~current_version, attr_version, attr_desc) => {
let current_version =
switch (current_version) {
| Some(version) => version
| None =>
raise(MissingFlag({flag: "--current-version", attr: "@history"}))
};
let (<) = Version.String.less_than;
if (current_version < attr_version) {
[Html.code("next"), attr_desc];
} else {
[Html.code(attr_version), attr_desc];
};
};

let types_for_function = (~ident, vd: Types.value_description) => {
switch (Ctype.repr(vd.val_type).desc) {
| TTyArrow(_) =>
Expand Down Expand Up @@ -162,12 +212,7 @@ let to_markdown = (~current_version, docblock) => {
|> Option.map((attr: Comments.Attribute.t) => {
switch (attr) {
| Since({attr_version}) =>
let (<) = Version.String.less_than;
if (current_version < attr_version) {
Format.sprintf("Added in %s", Html.code("next"));
} else {
Format.sprintf("Added in %s", Html.code(attr_version));
};
output_for_since(~current_version, attr_version)
| _ =>
failwith("Unreachable: Non-`since` attribute can't exist here.")
}
Expand All @@ -178,12 +223,7 @@ let to_markdown = (~current_version, docblock) => {
|> List.map((attr: Comments.Attribute.t) => {
switch (attr) {
| History({attr_version, attr_desc}) =>
let (<) = Version.String.less_than;
if (current_version < attr_version) {
[Html.code("next"), attr_desc];
} else {
[Html.code(attr_version), attr_desc];
};
output_for_history(~current_version, attr_version, attr_desc)
| _ =>
failwith("Unreachable: Non-`since` attribute can't exist here.")
}
Expand Down
48 changes: 22 additions & 26 deletions compiler/graindoc/graindoc.re
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ type params = {
/** Output filename */
[@name "o"] [@docv "FILE"]
output: option(Output.t),
/**
The version to use as current when generating markdown for `@since` and `@history` attributes.
Any future versions will be replace with `next` in the output.
*/
[@name "current-version"] [@docv "VERSION"]
current_version: option(string),
};

let compile_typed = (opts: params) => {
Expand Down Expand Up @@ -97,11 +103,7 @@ let compile_typed = (opts: params) => {
};

let generate_docs =
(
~version as current_version,
opts: params,
program: Typedtree.typed_program,
) => {
({current_version, output}: params, program: Typedtree.typed_program) => {
Comments.setup_comments(program.comments);

let env = program.env;
Expand Down Expand Up @@ -132,12 +134,7 @@ let generate_docs =
|> Option.map((attr: Comments.Attribute.t) => {
switch (attr) {
| Since({attr_version}) =>
let (<) = Version.String.less_than;
if (current_version < attr_version) {
Format.sprintf("Added in %s", Html.code("next"));
} else {
Format.sprintf("Added in %s", Html.code(attr_version));
};
Docblock.output_for_since(~current_version, attr_version)
| _ =>
failwith("Unreachable: Non-`since` attribute can't exist here.")
}
Expand All @@ -148,12 +145,11 @@ let generate_docs =
|> List.map((attr: Comments.Attribute.t) => {
switch (attr) {
| History({attr_version, attr_desc}) =>
let (<) = Version.String.less_than;
if (current_version < attr_version) {
[Html.code("next"), attr_desc];
} else {
[Html.code(attr_version), attr_desc];
};
Docblock.output_for_history(
~current_version,
attr_version,
attr_desc,
)
| _ =>
failwith("Unreachable: Non-`since` attribute can't exist here.")
}
Expand Down Expand Up @@ -240,7 +236,7 @@ let generate_docs =
};

let contents = Buffer.to_bytes(buf);
switch (opts.output) {
switch (output) {
| Some(outfile) =>
let oc = Fs_access.open_file_for_writing(outfile);
output_bytes(oc, contents);
Expand All @@ -251,13 +247,14 @@ let generate_docs =
`Ok();
};

let graindoc = (~version, opts) =>
try({
let program = compile_typed(opts);
generate_docs(~version, opts, program);
}) {
| e => `Error((false, Printexc.to_string(e)))
let graindoc = opts => {
let program = compile_typed(opts);
try(generate_docs(opts, program)) {
| exn =>
Format.eprintf("@[%s@]@.", Printexc.to_string(exn));
exit(2);
};
};

let cmd = {
open Term;
Expand All @@ -270,8 +267,7 @@ let cmd = {
};

(
Grain_utils.Config.with_cli_options(graindoc(~version))
$ params_cmdliner_term(),
Grain_utils.Config.with_cli_options(graindoc) $ params_cmdliner_term(),
Term.info(Sys.argv[0], ~version, ~doc),
);
};
Expand Down
6 changes: 3 additions & 3 deletions stdlib/array.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ Returns:
### Array.**cycle**

<details disabled>
<summary tabindex="-1">Added in <code>next</code></summary>
<summary tabindex="-1">Added in <code>0.4.4</code></summary>
No other changes yet.
</details>

Expand Down Expand Up @@ -1030,7 +1030,7 @@ Returns:
### Array.**sort**

<details disabled>
<summary tabindex="-1">Added in <code>next</code></summary>
<summary tabindex="-1">Added in <code>0.4.5</code></summary>
No other changes yet.
</details>

Expand All @@ -1052,7 +1052,7 @@ Parameters:
### Array.**rotate**

<details disabled>
<summary tabindex="-1">Added in <code>next</code></summary>
<summary tabindex="-1">Added in <code>0.4.5</code></summary>
No other changes yet.
</details>

Expand Down
2 changes: 1 addition & 1 deletion stdlib/number.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ Returns:
### Number.**parseInt**

<details disabled>
<summary tabindex="-1">Added in <code>next</code></summary>
<summary tabindex="-1">Added in <code>0.4.5</code></summary>
No other changes yet.
</details>

Expand Down
2 changes: 1 addition & 1 deletion stdlib/option.md
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ No other changes yet.
</details>

```grain
( or ) : (Option<a>, Option<a>) -> Option<a>
or : (Option<a>, Option<a>) -> Option<a>
```

Behaves like a logical OR (`||`) where the first Option is only returned if it is the `Some` variant and falling back to the second Option in all other cases.
Expand Down
2 changes: 1 addition & 1 deletion stdlib/result.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ No other changes yet.
</details>

```grain
( or ) : (Result<a, b>, Result<a, b>) -> Result<a, b>
or : (Result<a, b>, Result<a, b>) -> Result<a, b>
```

Behaves like a logical OR (`||`) where the first Result is only returned if it is the `Ok` variant and falling back to the second Result in all other cases.
Expand Down
2 changes: 1 addition & 1 deletion stdlib/string.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ String.implode([> 'H', 'e', 'l', 'l', 'o']) == "Hello"
### String.**reverse**

<details disabled>
<summary tabindex="-1">Added in <code>next</code></summary>
<summary tabindex="-1">Added in <code>0.4.5</code></summary>
No other changes yet.
</details>

Expand Down

0 comments on commit 0f681ea

Please sign in to comment.