From 81600e18caa8b6eb802842b367b1720c3bd99418 Mon Sep 17 00:00:00 2001 From: Alberto Schiabel Date: Fri, 13 Dec 2024 10:59:54 +0100 Subject: [PATCH] feat(psl): add support for multi-line comments (#5083) --- psl/psl/tests/parsing/comments.rs | 4 +-- ...k_attribute_comments_are_canonised.prisma} | 9 +++++++ ...comments_are_canonised.reformatted.prisma} | 11 ++++++++ ...nts_allowed_in_configuration_blocks.prisma | 4 +-- ...in_configuration_blocks.reformatted.prisma | 4 +-- .../mixed_line_docs_field_block.prisma | 18 +++++++++++++ .../comments/multi_line_block.prisma | 9 +++++++ .../comments/muti_line_field.prisma | 9 +++++++ .../comments/single_line_block.prisma | 7 +++++ .../single_line_docs_field_block.prisma | 9 +++++++ .../comments/single_line_field.prisma | 6 +++++ psl/schema-ast/src/parser/datamodel.pest | 10 +++++-- psl/schema-ast/src/parser/parse_comments.rs | 9 +++++++ psl/schema-ast/src/reformat.rs | 26 +++++++++++++++++++ 14 files changed, 127 insertions(+), 8 deletions(-) rename psl/psl/tests/reformatter/{block_attribute_comments_are_preserved.prisma => block_attribute_comments_are_canonised.prisma} (90%) rename psl/psl/tests/reformatter/{block_attribute_comments_are_preserved.reformatted.prisma => block_attribute_comments_are_canonised.reformatted.prisma} (89%) create mode 100644 psl/psl/tests/validation/comments/mixed_line_docs_field_block.prisma create mode 100644 psl/psl/tests/validation/comments/multi_line_block.prisma create mode 100644 psl/psl/tests/validation/comments/muti_line_field.prisma create mode 100644 psl/psl/tests/validation/comments/single_line_block.prisma create mode 100644 psl/psl/tests/validation/comments/single_line_docs_field_block.prisma create mode 100644 psl/psl/tests/validation/comments/single_line_field.prisma diff --git a/psl/psl/tests/parsing/comments.rs b/psl/psl/tests/parsing/comments.rs index 4816c4e77f95..6917c0b580dd 100644 --- a/psl/psl/tests/parsing/comments.rs +++ b/psl/psl/tests/parsing/comments.rs @@ -6,12 +6,12 @@ fn trailing_comments_allowed_in_configuration_blocks() { datasource db { provider = "postgres" // "mysql" | "sqlite" ... url = env("TEST_POSTGRES_URI") - relationMode = "prisma" // = on or set to "foreignKeys" to turn off emulation + relationMode = "prisma" /* = on or set to "foreignKeys" to turn off emulation */ } generator js { provider = "prisma-client-js" // optional - previewFeatures = ["referentialIntegrity"] // [] + previewFeatures = ["referentialIntegrity"] /* [] */ } "#; diff --git a/psl/psl/tests/reformatter/block_attribute_comments_are_preserved.prisma b/psl/psl/tests/reformatter/block_attribute_comments_are_canonised.prisma similarity index 90% rename from psl/psl/tests/reformatter/block_attribute_comments_are_preserved.prisma rename to psl/psl/tests/reformatter/block_attribute_comments_are_canonised.prisma index c6e3912ce68e..5bb6750249bb 100644 --- a/psl/psl/tests/reformatter/block_attribute_comments_are_preserved.prisma +++ b/psl/psl/tests/reformatter/block_attribute_comments_are_canonised.prisma @@ -1,3 +1,10 @@ +/** + * Models + With + Several + Lines + */ + model MyModel { // Example Comment field1 Int // Comment Field 1 @@ -11,6 +18,8 @@ model MyModel { @@unique([field1, field3]) // there too } +/* Types */ + type YourType { // Example Comment field1 Int // Comment Field 1 diff --git a/psl/psl/tests/reformatter/block_attribute_comments_are_preserved.reformatted.prisma b/psl/psl/tests/reformatter/block_attribute_comments_are_canonised.reformatted.prisma similarity index 89% rename from psl/psl/tests/reformatter/block_attribute_comments_are_preserved.reformatted.prisma rename to psl/psl/tests/reformatter/block_attribute_comments_are_canonised.reformatted.prisma index 43539c4ae7de..04f21c9cd365 100644 --- a/psl/psl/tests/reformatter/block_attribute_comments_are_preserved.reformatted.prisma +++ b/psl/psl/tests/reformatter/block_attribute_comments_are_canonised.reformatted.prisma @@ -1,3 +1,10 @@ +/** + * Models + * With + * Several + * Lines + */ + model MyModel { // Example Comment field1 Int // Comment Field 1 @@ -10,6 +17,10 @@ model MyModel { @@unique([field1, field3]) // there too } +/** + * Types + */ + type YourType { // Example Comment field1 Int // Comment Field 1 diff --git a/psl/psl/tests/reformatter/trailing_comments_allowed_in_configuration_blocks.prisma b/psl/psl/tests/reformatter/trailing_comments_allowed_in_configuration_blocks.prisma index 7675b45bbc31..7e756e947469 100644 --- a/psl/psl/tests/reformatter/trailing_comments_allowed_in_configuration_blocks.prisma +++ b/psl/psl/tests/reformatter/trailing_comments_allowed_in_configuration_blocks.prisma @@ -1,11 +1,11 @@ datasource db { provider = "postgres" // "mysql" | "sqlite" ... url = env("TEST_POSTGRES_URI") - relationMode = "prisma" // = on or set to "foreignKeys" to turn off emulation + relationMode = "prisma" /* = on or set to "foreignKeys" to turn off emulation */ } generator js { provider = "prisma-client-js" // optional - previewFeatures = ["referentialIntegrity"] // [] + previewFeatures = ["referentialIntegrity"] /* [] */ } diff --git a/psl/psl/tests/reformatter/trailing_comments_allowed_in_configuration_blocks.reformatted.prisma b/psl/psl/tests/reformatter/trailing_comments_allowed_in_configuration_blocks.reformatted.prisma index b25bb56a7536..f0a12ebe93d6 100644 --- a/psl/psl/tests/reformatter/trailing_comments_allowed_in_configuration_blocks.reformatted.prisma +++ b/psl/psl/tests/reformatter/trailing_comments_allowed_in_configuration_blocks.reformatted.prisma @@ -1,10 +1,10 @@ datasource db { provider = "postgres" // "mysql" | "sqlite" ... url = env("TEST_POSTGRES_URI") - relationMode = "prisma" // = on or set to "foreignKeys" to turn off emulation + relationMode = "prisma" /* = on or set to "foreignKeys" to turn off emulation */ } generator js { provider = "prisma-client-js" // optional - previewFeatures = ["referentialIntegrity"] // [] + previewFeatures = ["referentialIntegrity"] /* [] */ } diff --git a/psl/psl/tests/validation/comments/mixed_line_docs_field_block.prisma b/psl/psl/tests/validation/comments/mixed_line_docs_field_block.prisma new file mode 100644 index 000000000000..3b9395879de6 --- /dev/null +++ b/psl/psl/tests/validation/comments/mixed_line_docs_field_block.prisma @@ -0,0 +1,18 @@ +/// Example Doc Comment +model MyModel { + pk Int @id + + /* + * Multi-line comment + * There are several lines here. + */ + + field1 Int // Comment Field 1 + field2 Int // Comment Field 2 + + /** + * Multi-line comment for + * field3. This can contain **asterisks**. + */ + field3 Int // Comment Field 3 +} diff --git a/psl/psl/tests/validation/comments/multi_line_block.prisma b/psl/psl/tests/validation/comments/multi_line_block.prisma new file mode 100644 index 000000000000..cf1ef9d5c340 --- /dev/null +++ b/psl/psl/tests/validation/comments/multi_line_block.prisma @@ -0,0 +1,9 @@ +/** + * Comment MyModel + */ +model MyModel { + pk Int @id + + field1 Int + field2 Int +} diff --git a/psl/psl/tests/validation/comments/muti_line_field.prisma b/psl/psl/tests/validation/comments/muti_line_field.prisma new file mode 100644 index 000000000000..692ef493314f --- /dev/null +++ b/psl/psl/tests/validation/comments/muti_line_field.prisma @@ -0,0 +1,9 @@ +model MyModel { + pk Int @id + + /** + * Multi-line comment for + * field1. This can contain **asterisks**. + */ + field1 Int +} diff --git a/psl/psl/tests/validation/comments/single_line_block.prisma b/psl/psl/tests/validation/comments/single_line_block.prisma new file mode 100644 index 000000000000..86968ec9e145 --- /dev/null +++ b/psl/psl/tests/validation/comments/single_line_block.prisma @@ -0,0 +1,7 @@ +// Comment MyModel +model MyModel { + pk Int @id + + field1 Int + field2 Int +} diff --git a/psl/psl/tests/validation/comments/single_line_docs_field_block.prisma b/psl/psl/tests/validation/comments/single_line_docs_field_block.prisma new file mode 100644 index 000000000000..0a7fb87ec84a --- /dev/null +++ b/psl/psl/tests/validation/comments/single_line_docs_field_block.prisma @@ -0,0 +1,9 @@ +/// Example Doc Comment +model MyModel { + // Example Comment + pk Int @id + + field1 Int // Comment Field 1 + field2 Int // Comment Field 2 + field3 Int // Comment Field 3 +} diff --git a/psl/psl/tests/validation/comments/single_line_field.prisma b/psl/psl/tests/validation/comments/single_line_field.prisma new file mode 100644 index 000000000000..02a19361b9e5 --- /dev/null +++ b/psl/psl/tests/validation/comments/single_line_field.prisma @@ -0,0 +1,6 @@ +model MyModel { + pk Int @id + + field1 Int // Comment Field 1 + field2 Int // Comment Field 2 +} diff --git a/psl/schema-ast/src/parser/datamodel.pest b/psl/schema-ast/src/parser/datamodel.pest index a0b84bd0d060..c4e904ca28fa 100644 --- a/psl/schema-ast/src/parser/datamodel.pest +++ b/psl/schema-ast/src/parser/datamodel.pest @@ -121,11 +121,17 @@ trailing_comma = @{ "," } // ###################################### // Comments and Documentation Comments // ###################################### -comment_block = ${ ((doc_comment | comment) ~ NEWLINE?)+ } -trailing_comment = ${ doc_comment | comment } +comment_block = ${ ((doc_comment | comment | multi_line_comment) ~ NEWLINE?)+ } +trailing_comment = ${ doc_comment | comment | multi_line_comment } doc_comment = { WHITESPACE* ~ "///" ~ doc_content } comment = { WHITESPACE* ~ (!"///") ~ "//" ~ doc_content } doc_content = @{ (!NEWLINE ~ ANY)* } +multi_line_comment = { + WHITESPACE* + ~ "/*" + ~ (!"*/" ~ ANY)* // Match any characters until the closing */ + ~ "*/" +} // ###################################### // shared building blocks diff --git a/psl/schema-ast/src/parser/parse_comments.rs b/psl/schema-ast/src/parser/parse_comments.rs index 75afabd6f3f6..b11b61610788 100644 --- a/psl/schema-ast/src/parser/parse_comments.rs +++ b/psl/schema-ast/src/parser/parse_comments.rs @@ -10,6 +10,7 @@ pub(crate) fn parse_comment_block(token: Pair<'_>) -> Option { for comment in token.clone().into_inner() { match comment.as_rule() { Rule::doc_comment => lines.push(parse_doc_comment(comment)), + Rule::multi_line_comment => lines.push(parse_multi_line_comment(comment)), Rule::comment | Rule::NEWLINE | Rule::WHITESPACE => {} _ => parsing_catch_all(&comment, "comment block"), } @@ -28,6 +29,7 @@ pub(crate) fn parse_trailing_comment(pair: Pair<'_>) -> Option { for current in pair.into_inner() { match current.as_rule() { Rule::doc_comment => lines.push(parse_doc_comment(current)), + Rule::multi_line_comment => lines.push(parse_multi_line_comment(current)), Rule::comment | Rule::NEWLINE | Rule::WHITESPACE => {} _ => parsing_catch_all(¤t, "trailing comment"), } @@ -52,3 +54,10 @@ pub(crate) fn parse_doc_comment(token: Pair<'_>) -> &str { ), } } + +fn parse_multi_line_comment(token: Pair<'_>) -> &str { + // The matched string includes `/*` and `*/`. Strip them off. + let text = token.as_str(); + // Safety check: multi_line_comment matches `/* ... */`, so length is at least 4. + text[2..text.len() - 2].trim() +} diff --git a/psl/schema-ast/src/reformat.rs b/psl/schema-ast/src/reformat.rs index 3492bb0524f0..98905c0a7eae 100644 --- a/psl/schema-ast/src/reformat.rs +++ b/psl/schema-ast/src/reformat.rs @@ -439,6 +439,32 @@ fn reformat_comment_block(pair: Pair<'_>, table: &mut TableFormat) { } } } + Rule::multi_line_comment => { + // Start the canonical multi-line comment block + table.start_new_line(); + table.append_suffix_to_current_row("/**"); + + let content = current.as_str(); + // Strip off `/*` and `*/` + let inner = &content[2..content.len() - 2]; + + // Normalize lines by removing leading `*` and extra whitespace. + for line in inner.lines() { + let line = line.trim(); + // Remove a leading `*` if present, along with any following spaces. + let line = line.strip_prefix('*').map(str::trim_start).unwrap_or(line); + + if !line.is_empty() { + table.start_new_line(); + table.append_suffix_to_current_row(" * "); + table.append_suffix_to_current_row(line); + } + } + + // Close the multi-line comment block + table.start_new_line(); + table.append_suffix_to_current_row(" */"); + } _ => unreachable!(), } }