From d5d50f9596da89fc4ecc28ab33b521308da3f6f3 Mon Sep 17 00:00:00 2001 From: Marin Minnerly Date: Fri, 29 Mar 2024 14:33:42 -0700 Subject: [PATCH 1/3] Add snapshots --- .../test-input/passing/type_definitions.lua | 34 ++++++++++++ ..._passing__type_definitions.lua-stderr.snap | 6 ++ ..._passing__type_definitions.lua-stdout.snap | 55 +++++++++++++++++++ extractor/tests/test-inputs.rs | 5 ++ 4 files changed, 100 insertions(+) create mode 100644 extractor/test-input/passing/type_definitions.lua create mode 100644 extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stderr.snap create mode 100644 extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stdout.snap diff --git a/extractor/test-input/passing/type_definitions.lua b/extractor/test-input/passing/type_definitions.lua new file mode 100644 index 0000000..6196277 --- /dev/null +++ b/extractor/test-input/passing/type_definitions.lua @@ -0,0 +1,34 @@ +--[=[ + Class description + + @class TypeDefs +]=] + +--[=[ + A description of the type + + @within TypeDefs +]=] +export type Foo = { + -- A description for the field + field: number?, + + -- A description for this field too. + -- With a second line. + -- And a third + another: string?, +} + +--[=[ + A description of the type + + @within TypeDefs +]=] +export type MultilineFieldComments = { + --[[ + Now with a multiline comment + + For cases where there's a lot to say about a field + ]] + field: boolean, +} diff --git a/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stderr.snap b/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stderr.snap new file mode 100644 index 0000000..15f0a72 --- /dev/null +++ b/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stderr.snap @@ -0,0 +1,6 @@ +--- +source: tests/test-inputs.rs +expression: stderr + +--- + diff --git a/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stdout.snap b/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stdout.snap new file mode 100644 index 0000000..8832fd8 --- /dev/null +++ b/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stdout.snap @@ -0,0 +1,55 @@ +--- +source: tests/test-inputs.rs +expression: stdout + +--- +[ + { + "functions": [], + "properties": [], + "types": [ + { + "name": "Foo", + "desc": "A description of the type", + "fields": [ + { + "name": "field", + "lua_type": "number?", + "desc": "A description for the field" + }, + { + "name": "another", + "lua_type": "string?, + "desc": "A description for this field too.\nWith a second line.\nAnd a third" + } + ], + "source": { + "line": 12, + "path": "" + } + }, + { + "name": "MultilineFieldComments", + "desc": "A description of the type", + "fields": [ + { + "name": "field", + "lua_type": "string?", + "desc": "Now with a multiline comment\n\nFor cases where there's a lot to say about a field" + } + ], + "source": { + "line": 27, + "path": "" + } + } + ] + "name": "TypeDefs", + "desc": "Class description", + "source": { + "line": 6, + "path": "" + } + } +] + diff --git a/extractor/tests/test-inputs.rs b/extractor/tests/test-inputs.rs index 7448f32..9db9668 100644 --- a/extractor/tests/test-inputs.rs +++ b/extractor/tests/test-inputs.rs @@ -70,6 +70,11 @@ fn triple_dash_wrong_comment() -> anyhow::Result<()> { run_moonwave("passing/triple_dash_wrong_comment.lua", 0) } +#[test] +fn type_definitions() -> anyhow::Result<()> { + run_moonwave("passing/type_definitions.lua", 0) +} + #[test] fn param_validation() -> anyhow::Result<()> { run_moonwave("failing/param_validation.lua", 1) From 0fa1093e8bbd342a36826133f9f3dfff94bbf093 Mon Sep 17 00:00:00 2001 From: Marin Minnerly Date: Mon, 1 Apr 2024 16:51:59 -0700 Subject: [PATCH 2/3] Collect Luau types --- extractor/src/doc_entry.rs | 13 +++++ extractor/src/doc_entry/type_definition.rs | 58 ++++++++++++++++++- ..._passing__type_definitions.lua-stdout.snap | 10 ++-- 3 files changed, 75 insertions(+), 6 deletions(-) diff --git a/extractor/src/doc_entry.rs b/extractor/src/doc_entry.rs index bdf2f05..d24ea8d 100644 --- a/extractor/src/doc_entry.rs +++ b/extractor/src/doc_entry.rs @@ -192,6 +192,19 @@ fn determine_kind( }) } }, + Some(Stmt::ExportedTypeDeclaration(type_decl)) => { + let name = type_decl.type_declaration().type_name().to_string(); + + let within = if let Some(within) = within_tag { + within.name.as_str().to_owned() + } else { + return Err( + doc_comment.diagnostic("Exported type declaration requires @within tag") + ); + }; + + Ok(DocEntryKind::Type { name, within }) + } _ => Err(doc_comment .diagnostic("Explicitly specify a kind tag, like @function, @prop, or @class.")), diff --git a/extractor/src/doc_entry/type_definition.rs b/extractor/src/doc_entry/type_definition.rs index 6c55dae..8768462 100644 --- a/extractor/src/doc_entry/type_definition.rs +++ b/extractor/src/doc_entry/type_definition.rs @@ -4,6 +4,11 @@ use crate::{ serde_util::is_false, tags::{CustomTag, FieldTag, Tag}, }; +use full_moon::{ + ast::{types::TypeInfo, Stmt}, + node::Node, + tokenizer::TokenType, +}; use serde::Serialize; use super::DocEntryParseArguments; @@ -62,12 +67,63 @@ impl<'a> TypeDocEntry<'a> { source, } = args; + let fields = match &source.stmt { + Some(Stmt::ExportedTypeDeclaration(exported_type_declaration)) => { + let type_declaration = exported_type_declaration.type_declaration(); + let type_info = type_declaration.type_definition(); + + match type_info { + TypeInfo::Table { fields, .. } => fields + .iter() + .map(|type_field| { + let name = type_field + .key() + .tokens() + .find_map(|token| match token.token_type() { + TokenType::Identifier { identifier } => { + Some(identifier.to_string()) + } + _ => None, + }) + .unwrap_or(String::new()); + + let desc = type_field + .key() + .surrounding_trivia() + .0 + .iter() + .filter_map(|trivia| match trivia.token_type() { + TokenType::SingleLineComment { comment } => Some(comment), + TokenType::MultiLineComment { comment, .. } => Some(comment), + _ => None, + }) + .map(|comment| comment.lines().map(|line| line.trim())) + .flatten() + .collect::>() + .join("\n") + .trim() + .to_string(); + + return Field { + name, + lua_type: type_field.value().to_string(), + desc, + }; + }) + .collect::>(), + _ => vec![], + } + } + Some(_) => vec![], + None => vec![], + }; + let mut doc_entry = Self { name, desc, source, + fields, lua_type: None, - fields: Vec::new(), within: within.unwrap(), tags: Vec::new(), private: false, diff --git a/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stdout.snap b/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stdout.snap index 8832fd8..51439c6 100644 --- a/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stdout.snap +++ b/extractor/tests/snapshots/test_inputs__passing__type_definitions.lua-stdout.snap @@ -9,7 +9,7 @@ expression: stdout "properties": [], "types": [ { - "name": "Foo", + "name": "Foo ", "desc": "A description of the type", "fields": [ { @@ -19,7 +19,7 @@ expression: stdout }, { "name": "another", - "lua_type": "string?, + "lua_type": "string?", "desc": "A description for this field too.\nWith a second line.\nAnd a third" } ], @@ -29,12 +29,12 @@ expression: stdout } }, { - "name": "MultilineFieldComments", + "name": "MultilineFieldComments ", "desc": "A description of the type", "fields": [ { "name": "field", - "lua_type": "string?", + "lua_type": "boolean", "desc": "Now with a multiline comment\n\nFor cases where there's a lot to say about a field" } ], @@ -43,7 +43,7 @@ expression: stdout "path": "" } } - ] + ], "name": "TypeDefs", "desc": "Class description", "source": { From ba4af971c08c154991edb83006367c0a0b351a1a Mon Sep 17 00:00:00 2001 From: Marin Minnerly Date: Mon, 1 Apr 2024 16:55:02 -0700 Subject: [PATCH 3/3] Add case for unexported types --- extractor/test-input/passing/type_definitions.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/extractor/test-input/passing/type_definitions.lua b/extractor/test-input/passing/type_definitions.lua index 6196277..c18f4a9 100644 --- a/extractor/test-input/passing/type_definitions.lua +++ b/extractor/test-input/passing/type_definitions.lua @@ -32,3 +32,11 @@ export type MultilineFieldComments = { ]] field: boolean, } + +--[[ + Unexported type declarations should never be extracted +]] +type InternalUseOnly = { + -- This comment will also never be hoisted + foo: boolean, +}