From 7f090a348f3032fec747dd9d15c03a71aba4b08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Houl=C3=A9?= <13155277+tomhoule@users.noreply.github.com> Date: Thu, 1 Dec 2022 09:57:06 +0100 Subject: [PATCH] psl: fix newline boundary search in relation reformatting (#3457) When adding an @relation attribute to a forward relation field in the relation reformatting code that deals with adding missing relation fields and attributes, we searched for the last character before a newline to check whether it is a carriage return, but we failed to check whether the byte offset was a char boundary first. This caused crashes. This commit fixes the problem by adding the relation attribute directly after the field type, rather than walking back from the end of the field (including trailing comment). We could do better with a proper AST. closes https://github.com/prisma/prisma/issues/14895 --- psl/psl-core/src/reformat.rs | 16 ++++++------- psl/psl/tests/reformat_tests.rs | 2 ++ ...ld_with_multi_byte_trailing_comment.prisma | 23 +++++++++++++++++++ ...i_byte_trailing_comment.reformatted.prisma | 23 +++++++++++++++++++ 4 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.prisma create mode 100644 psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.reformatted.prisma diff --git a/psl/psl-core/src/reformat.rs b/psl/psl-core/src/reformat.rs index d2ce95518505..129576dd6325 100644 --- a/psl/psl-core/src/reformat.rs +++ b/psl/psl-core/src/reformat.rs @@ -137,7 +137,7 @@ fn push_missing_relation_attribute(inline_relation: walkers::InlineRelationWalke content.push(')'); ctx.missing_bits.push(MissingBit { - position: before_newline(forward.ast_field().span().end, ctx.original_schema), + position: after_type(forward.ast_field().field_type.span().end, ctx.original_schema), content, }) } @@ -328,12 +328,10 @@ fn references_argument(inline: walkers::InlineRelationWalker<'_>) -> String { format!("references: [{}]", field_names.join(", ")) } -/// Assuming the last characters before span_end are newlines. We can fix this more thoroughly by -/// not including the newline in field spans. -fn before_newline(span_end: usize, original_schema: &str) -> usize { - assert!(&original_schema[span_end - 1..span_end] == "\n"); - match &original_schema[span_end - 2..span_end - 1] { - "\r" => span_end - 2, - _ => span_end - 1, - } +fn after_type(type_span_end: usize, original_schema: &str) -> usize { + original_schema[type_span_end..] + .chars() + .position(|chr| !['[', ']', '?', '!'].contains(&chr)) + .map(|pos| type_span_end + pos) + .unwrap_or(type_span_end) } diff --git a/psl/psl/tests/reformat_tests.rs b/psl/psl/tests/reformat_tests.rs index 1d070107a7d5..ea6207894047 100644 --- a/psl/psl/tests/reformat_tests.rs +++ b/psl/psl/tests/reformat_tests.rs @@ -28,6 +28,8 @@ fn run_reformat_test(test_file_path: &str) { } if reformat(&reformatted_text) != reformatted_text { + println!("=== reformatted ===\n{reformatted_text}"); + println!("=== reformatted again ===\n{}", reformat(&reformatted_text)); panic!("Reformatting this schema is not idempotent."); } } diff --git a/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.prisma b/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.prisma new file mode 100644 index 000000000000..faa11066ff2a --- /dev/null +++ b/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.prisma @@ -0,0 +1,23 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +generator client { + provider = "prisma-client-js" + output = "./generated/client" +} + +datasource db { + provider = "sqlserver" + url = "***" +} + +model somemodel { + frownyFaceId String + frownyFace frownyface // 囧 + + id Int @id +} + +model frownyface { + somes somemodel[] +} diff --git a/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.reformatted.prisma b/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.reformatted.prisma new file mode 100644 index 000000000000..410deb2686d8 --- /dev/null +++ b/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.reformatted.prisma @@ -0,0 +1,23 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +generator client { + provider = "prisma-client-js" + output = "./generated/client" +} + +datasource db { + provider = "sqlserver" + url = "***" +} + +model somemodel { + frownyFaceId String + frownyFace frownyface @relation(fields: [], references: []) // 囧 + + id Int @id +} + +model frownyface { + somes somemodel[] +}