diff --git a/prisma-fmt/src/code_actions.rs b/prisma-fmt/src/code_actions.rs index 3b88eadd5f3..b9dbdc58067 100644 --- a/prisma-fmt/src/code_actions.rs +++ b/prisma-fmt/src/code_actions.rs @@ -52,7 +52,7 @@ pub(crate) fn available_actions(schema: String, params: CodeActionParams) -> Vec } if matches!(datasource, Some(ds) if ds.active_provider == "mongodb") { - mongodb::add_at_map_for_id(&mut actions, ¶ms, validated_schema.db.source(), model) + mongodb::add_at_map_for_id(&mut actions, ¶ms, validated_schema.db.source(), model); } } diff --git a/prisma-fmt/tests/code_actions/scenarios/mongodb_at_map_with_validation_errors/result.json b/prisma-fmt/tests/code_actions/scenarios/mongodb_at_map_with_validation_errors/result.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/prisma-fmt/tests/code_actions/scenarios/mongodb_at_map_with_validation_errors/result.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/prisma-fmt/tests/code_actions/scenarios/mongodb_at_map_with_validation_errors/schema.prisma b/prisma-fmt/tests/code_actions/scenarios/mongodb_at_map_with_validation_errors/schema.prisma new file mode 100644 index 00000000000..b1ead2cebf8 --- /dev/null +++ b/prisma-fmt/tests/code_actions/scenarios/mongodb_at_map_with_validation_errors/schema.prisma @@ -0,0 +1,24 @@ +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "mongodb" + url = env("DATABASE_URL") +} + +model Kattbjorn { + // As of now, the code action won't appear here until the other validation + // error is fixed. The reason is the implementation of this code action + // relies on the parser database to be fully populated and all attributes + // to be resolved, however when there are name and type resolution errors, + // the attributes are not currently resolved and only an empty stub for + // model attributes is constructed. This may change in the future, and this + // test expectation would need to be updated correspondingly then. + // + // Note that the validation error itself does not appear here too until the + // error on the next line is fixed (due to these being separate validation + // passes), so the behaviour is consistent. + id String @id + bar +} diff --git a/prisma-fmt/tests/code_actions/tests.rs b/prisma-fmt/tests/code_actions/tests.rs index 2c76dd24f49..41035ed65d9 100644 --- a/prisma-fmt/tests/code_actions/tests.rs +++ b/prisma-fmt/tests/code_actions/tests.rs @@ -29,4 +29,5 @@ scenarios! { multi_schema_one_model_one_enum multi_schema_two_models mongodb_at_map + mongodb_at_map_with_validation_errors } diff --git a/prisma-fmt/tests/regression_tests.rs b/prisma-fmt/tests/regression_tests.rs new file mode 100644 index 00000000000..d90744517a6 --- /dev/null +++ b/prisma-fmt/tests/regression_tests.rs @@ -0,0 +1 @@ +mod regressions; diff --git a/prisma-fmt/tests/regressions/language_tools_1466.rs b/prisma-fmt/tests/regressions/language_tools_1466.rs new file mode 100644 index 00000000000..adae2328c31 --- /dev/null +++ b/prisma-fmt/tests/regressions/language_tools_1466.rs @@ -0,0 +1,31 @@ +#[test] +fn code_actions_should_not_crash_on_validation_errors_with_mongodb() { + let schema = r#" + datasource db { + provider = "mongodb" + url = env("DATABASE_URL") + } + + generator client { + provider = "prisma-client-js" + } + + model A { + 1bar Bar[] + } + "#; + + let params = lsp_types::CodeActionParams { + text_document: lsp_types::TextDocumentIdentifier { + uri: "file:/path/to/schema.prisma".parse().unwrap(), + }, + range: lsp_types::Range::default(), + context: lsp_types::CodeActionContext::default(), + work_done_progress_params: lsp_types::WorkDoneProgressParams { work_done_token: None }, + partial_result_params: lsp_types::PartialResultParams { + partial_result_token: None, + }, + }; + + prisma_fmt::code_actions(schema.to_owned(), &serde_json::to_string_pretty(¶ms).unwrap()); +} diff --git a/prisma-fmt/tests/regressions/mod.rs b/prisma-fmt/tests/regressions/mod.rs new file mode 100644 index 00000000000..8161e3c8c3c --- /dev/null +++ b/prisma-fmt/tests/regressions/mod.rs @@ -0,0 +1 @@ +mod language_tools_1466; diff --git a/psl/parser-database/src/attributes.rs b/psl/parser-database/src/attributes.rs index 79630262a76..3ea87fa4734 100644 --- a/psl/parser-database/src/attributes.rs +++ b/psl/parser-database/src/attributes.rs @@ -1091,3 +1091,21 @@ fn validate_clustering_setting(ctx: &mut Context<'_>) -> Option { ctx.visit_optional_arg("clustered") .and_then(|sort| coerce::boolean(sort, ctx.diagnostics)) } + +/// Create the default values of [`ModelAttributes`] and [`EnumAttributes`] for each model and enum +/// in the AST to ensure [`crate::walkers::ModelWalker`] and [`crate::walkers::EnumWalker`] can +/// access their corresponding entries in the attributes map in the database even in the presence +/// of name and type resolution errors. This is useful for the language tools. +pub(super) fn populate_empty_attributes(ctx: &mut Context<'_>) { + for top in ctx.ast.iter_tops() { + match top { + (ast::TopId::Model(model_id), ast::Top::Model(_)) => { + ctx.types.model_attributes.insert(model_id, ModelAttributes::default()); + } + (ast::TopId::Enum(enum_id), ast::Top::Enum(_)) => { + ctx.types.enum_attributes.insert(enum_id, EnumAttributes::default()); + } + _ => (), + } + } +} diff --git a/psl/parser-database/src/lib.rs b/psl/parser-database/src/lib.rs index f8ec2cd651e..009e396d927 100644 --- a/psl/parser-database/src/lib.rs +++ b/psl/parser-database/src/lib.rs @@ -93,6 +93,8 @@ impl ParserDatabase { // Return early on name resolution errors. if ctx.diagnostics.has_errors() { + attributes::populate_empty_attributes(&mut ctx); + return ParserDatabase { ast, file, @@ -108,6 +110,8 @@ impl ParserDatabase { // Return early on type resolution errors. if ctx.diagnostics.has_errors() { + attributes::populate_empty_attributes(&mut ctx); + return ParserDatabase { ast, file,