diff --git a/src/legacy.rs b/src/legacy.rs index ce01d2c..fc11923 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -5,11 +5,37 @@ use rnix::{ use rowan::ast::AstNode; use crate::{ - commonmark::{Argument, SingleArg}, + commonmark::{Argument, ManualEntry, SingleArg}, format::handle_indentation, - retrieve_doc_comment, + retrieve_doc_comment, DocComment, }; +#[derive(Debug)] +pub struct LegacyDocItem { + pub name: String, + pub comment: DocComment, + pub args: Vec, +} + +impl LegacyDocItem { + pub fn into_entry(self, prefix: &str, category: &str) -> ManualEntry { + ManualEntry { + prefix: prefix.to_string(), + category: category.to_string(), + name: self.name, + description: self + .comment + .doc + .split("\n\n") + .map(|s| s.to_string()) + .collect(), + fn_type: self.comment.doc_type, + example: self.comment.example, + args: self.args, + } + } +} + /// Retrieve documentation comments. pub fn retrieve_legacy_comment(node: &SyntaxNode, allow_line_comments: bool) -> Option { // if the current node has a doc comment it'll be immediately preceded by that comment, @@ -70,7 +96,7 @@ pub fn retrieve_legacy_comment(node: &SyntaxNode, allow_line_comments: bool) -> /// Traverse directly chained nix lambdas and collect the identifiers of all lambda arguments /// until an unexpected AST node is encountered. -pub fn collect_lambda_args(mut lambda: Lambda) -> Vec { +pub fn collect_lambda_args_legacy(mut lambda: Lambda) -> Vec { let mut args = vec![]; loop { @@ -87,7 +113,7 @@ pub fn collect_lambda_args(mut lambda: Lambda) -> Vec { } // an ident in a pattern, e.g. `a` in `foo = { a }: a` Param::Pattern(pat) => { - // collect doc-comments for each lambda formal + // collect doc-comments for each lambda formal too // Lambda formals are supported by RFC145 let pattern_vec: Vec<_> = pat .pat_entries() diff --git a/src/main.rs b/src/main.rs index 2cfaa95..512af7c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,7 @@ use crate::{format::handle_indentation, legacy::retrieve_legacy_comment}; use self::comment::get_expr_docs; use self::commonmark::*; use format::shift_headings; -use legacy::collect_lambda_args; +use legacy::{collect_lambda_args_legacy, LegacyDocItem}; use rnix::{ ast::{Attr, AttrpathValue, Expr, Inherit, LetIn}, SyntaxKind, SyntaxNode, @@ -91,26 +91,11 @@ struct DocComment { struct DocItem { name: String, comment: DocComment, - args: Vec, } -impl DocItem { - fn into_entry(self, prefix: &str, category: &str) -> ManualEntry { - ManualEntry { - prefix: prefix.to_string(), - category: category.to_string(), - name: self.name, - description: self - .comment - .doc - .split("\n\n") - .map(|s| s.to_string()) - .collect(), - fn_type: self.comment.doc_type, - example: self.comment.example, - args: self.args, - } - } +enum DocItemOrLegacy { + LegacyDocItem(LegacyDocItem), + DocItem(DocItem), } /// Returns a rfc145 doc-comment if one is present @@ -130,7 +115,7 @@ pub fn retrieve_doc_comment(node: &SyntaxNode, shift_headings_by: Option) /// Transforms an AST node into a `DocItem` if it has a leading /// documentation comment. -fn retrieve_doc_item(node: &AttrpathValue) -> Option { +fn retrieve_doc_item(node: &AttrpathValue) -> Option { let ident = node.attrpath().unwrap(); // TODO this should join attrs() with '.' to handle whitespace, dynamic attrs and string // attrs. none of these happen in nixpkgs lib, and the latter two should probably be @@ -139,23 +124,22 @@ fn retrieve_doc_item(node: &AttrpathValue) -> Option { let doc_comment = retrieve_doc_comment(node.syntax(), Some(2)); match doc_comment { - Some(comment) => Some(DocItem { + Some(comment) => Some(DocItemOrLegacy::DocItem(DocItem { name: item_name, comment: DocComment { doc: comment, doc_type: None, example: None, }, - args: vec![], - }), + })), // Fallback to legacy comment is there is no doc_comment None => { let comment = retrieve_legacy_comment(node.syntax(), false)?; - Some(DocItem { + Some(DocItemOrLegacy::LegacyDocItem(LegacyDocItem { name: item_name, comment: parse_doc_comment(&comment), args: vec![], - }) + })) } } } @@ -208,16 +192,36 @@ fn parse_doc_comment(raw: &str) -> DocComment { /// 2. The attached doc comment on the entry. /// 3. The argument names of any curried functions (pattern functions /// not yet supported). -fn collect_entry_information(entry: AttrpathValue) -> Option { +fn collect_entry_information(entry: AttrpathValue) -> Option { let doc_item = retrieve_doc_item(&entry)?; - if let Some(Expr::Lambda(l)) = entry.value() { - Some(DocItem { - args: collect_lambda_args(l), - ..doc_item - }) - } else { - Some(doc_item) + match doc_item { + DocItemOrLegacy::LegacyDocItem(v) => { + if let Some(Expr::Lambda(l)) = entry.value() { + Some(LegacyDocItem { + args: collect_lambda_args_legacy(l), + ..v + }) + } else { + Some(v) + } + } + // Convert DocItems into legacyItem for markdown rendering + DocItemOrLegacy::DocItem(v) => { + // if let Some(Expr::Lambda(l)) = entry.value() { + // Some(LegacyDocItem { + // args: collect_lambda_args(l), + // name: v.name, + // comment: v.comment, + // }) + // } else { + // } + Some(LegacyDocItem { + args: vec![], + name: v.name, + comment: v.comment, + }) + } } } diff --git a/src/snapshots/nixdoc__test__doc_comment.snap b/src/snapshots/nixdoc__test__doc_comment.snap index c69cec1..08c0af0 100644 --- a/src/snapshots/nixdoc__test__doc_comment.snap +++ b/src/snapshots/nixdoc__test__doc_comment.snap @@ -32,29 +32,6 @@ Type: (Should NOT be a heading) This is just markdown -structured function argument - -: `formal1` - - : Legacy line comment - - `formal2` - - : Legacy Block - - `formal3` - - : Legacy - multiline - comment - - `formal4` - - : official doc-comment variant - - ## `lib.debug.foo` {#function-library-lib.debug.foo} Comment - - diff --git a/src/snapshots/nixdoc__test__doc_comment_no_duplicate_arguments.snap b/src/snapshots/nixdoc__test__doc_comment_no_duplicate_arguments.snap new file mode 100644 index 0000000..65e026c --- /dev/null +++ b/src/snapshots/nixdoc__test__doc_comment_no_duplicate_arguments.snap @@ -0,0 +1,53 @@ +--- +source: src/test.rs +expression: output +--- +# Debug {#sec-functions-library-debug} + + +## `lib.debug.old` {#function-library-lib.debug.old} + +nixdoc comment + +`arg` + +: Should be visible + + +## `lib.debug.omited` {#function-library-lib.debug.omited} + +Doc-comment + +## `lib.debug.multiple` {#function-library-lib.debug.multiple} + +Doc-comment + +## `lib.debug.argumentTest` {#function-library-lib.debug.argumentTest} + +Doc-comment before the lamdba causes the whole +lambda including its arguments to switch to doc-comments ONLY rendering + +## `lib.debug.legacyArgumentTest` {#function-library-lib.debug.legacyArgumentTest} + +Legacy comments allow to use any +form of comments for the lambda arguments/formals + +structured function argument + +: `formal1` + + : Legacy line comment + + `formal2` + + : Legacy Block + + `formal3` + + : Legacy + multiline + comment + + `formal4` + + : doc-comment style diff --git a/src/test.rs b/src/test.rs index a2dd831..cafd651 100644 --- a/src/test.rs +++ b/src/test.rs @@ -179,3 +179,24 @@ fn test_doc_comment_section_description() { insta::assert_snapshot!(output); } + +#[test] +fn test_doc_comment_no_duplicate_arguments() { + let mut output = Vec::new(); + let src = fs::read_to_string("test/doc-comment-arguments.nix").unwrap(); + let nix = rnix::Root::parse(&src).ok().expect("failed to parse input"); + let prefix = "lib"; + let category = "debug"; + let desc = retrieve_description(&nix, &"Debug", category); + writeln!(output, "{}", desc).expect("Failed to write header"); + + for entry in collect_entries(nix, prefix, category) { + entry + .write_section(&Default::default(), &mut output) + .expect("Failed to write section") + } + + let output = String::from_utf8(output).expect("not utf8"); + + insta::assert_snapshot!(output); +} diff --git a/test.nix b/test.nix new file mode 100644 index 0000000..cbd3e9a --- /dev/null +++ b/test.nix @@ -0,0 +1,27 @@ +{ + /** Doc comment*/ + foo = + # Ignored + bar: + bar; + + /** + + doc comment in markdown format + Causes the whole function to use RFC145 conform rendering + + */ + argumentTest = + { + # Not documented + formal1, + formal2, + /* Not documented */ + formal3, + /** + Documented + */ + formal4, + }: + {}; +} \ No newline at end of file diff --git a/test/doc-comment-arguments.nix b/test/doc-comment-arguments.nix new file mode 100644 index 0000000..afa6ac2 --- /dev/null +++ b/test/doc-comment-arguments.nix @@ -0,0 +1,69 @@ +{ + /* nixdoc comment */ + old = + # Should be visible + arg: 1; + + /** Doc-comment */ + omited = + # Not visible + arg: 1; + + /** Doc-comment */ + multiple = + # Not visible + arg: + /* Not visible */ + foo: + /** Not visible */ + bar: + 1; + + /** + Doc-comment before the lamdba causes the whole + lambda including its arguments to switch to doc-comments ONLY rendering + */ + argumentTest = { + # Legacy line comment + formal1, + # Legacy + # Block + formal2, + /* + Legacy + multiline + comment + */ + formal3, + /** + Not shown yet + */ + formal4, + + }: + {}; + + /* + Legacy comments allow to use any + form of comments for the lambda arguments/formals + */ + legacyArgumentTest = { + # Legacy line comment + formal1, + # Legacy + # Block + formal2, + /* + Legacy + multiline + comment + */ + formal3, + /** + doc-comment style + */ + formal4, + + }: + {}; +} \ No newline at end of file diff --git a/test/doc-comment.nix b/test/doc-comment.nix index 07b29ad..1cf749b 100644 --- a/test/doc-comment.nix +++ b/test/doc-comment.nix @@ -32,22 +32,10 @@ This is just markdown */ argumentTest = { - # Legacy line comment formal1, - # Legacy - # Block formal2, - /* - Legacy - multiline - comment - */ formal3, - /** - official doc-comment variant - */ formal4, - }: {};