Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prisma-fmt: Make get_config error tolerant #4875

Merged
merged 2 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
257 changes: 195 additions & 62 deletions prisma-fmt/src/get_config.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion prisma-fmt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ pub fn referential_actions(schema: String) -> String {
/// type GetConfigResponse = GetConfigErrorResponse | GetConfigSuccessResponse
///
/// ```
pub fn get_config(get_config_params: String) -> Result<String, String> {
pub fn get_config(get_config_params: String) -> String {
get_config::get_config(&get_config_params)
}

Expand Down
26 changes: 11 additions & 15 deletions prisma-fmt/src/text_document_completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use lsp_types::*;
use psl::{
datamodel_connector::Connector,
diagnostics::{FileId, Span},
parse_configuration_multi_file,
error_tolerant_parse_configuration,
parser_database::{ast, ParserDatabase, SourceFile},
Configuration, Datasource, Diagnostics, Generator, PreviewFeature,
};
Expand All @@ -21,9 +21,7 @@ pub(crate) fn empty_completion_list() -> CompletionList {
}

pub(crate) fn completion(schema_files: Vec<(String, SourceFile)>, params: CompletionParams) -> CompletionList {
let config = parse_configuration_multi_file(&schema_files)
.ok()
.map(|(_, config)| config);
let (_, config, _) = error_tolerant_parse_configuration(&schema_files);

let mut list = CompletionList {
is_incomplete: false,
Expand All @@ -50,7 +48,7 @@ pub(crate) fn completion(schema_files: Vec<(String, SourceFile)>, params: Comple
};

let ctx = CompletionContext {
config: config.as_ref(),
config: &config,
params: &params,
db: &db,
position,
Expand All @@ -64,7 +62,7 @@ pub(crate) fn completion(schema_files: Vec<(String, SourceFile)>, params: Comple

#[derive(Debug, Clone, Copy)]
struct CompletionContext<'a> {
config: Option<&'a Configuration>,
config: &'a Configuration,
params: &'a CompletionParams,
db: &'a ParserDatabase,
position: usize,
Expand All @@ -89,19 +87,19 @@ impl<'a> CompletionContext<'a> {
}

fn datasource(self) -> Option<&'a Datasource> {
self.config.and_then(|conf| conf.datasources.first())
self.config.datasources.first()
}

fn generator(self) -> Option<&'a Generator> {
self.config.and_then(|conf| conf.generators.first())
self.config.generators.first()
}
}

fn push_ast_completions(ctx: CompletionContext<'_>, completion_list: &mut CompletionList) {
let relation_mode = match ctx.config.map(|c| c.relation_mode()) {
Some(Some(rm)) => rm,
_ => ctx.connector().default_relation_mode(),
};
let relation_mode = ctx
.config
.relation_mode()
.unwrap_or_else(|| ctx.connector().default_relation_mode());
SevInf marked this conversation as resolved.
Show resolved Hide resolved

match ctx.db.ast(ctx.initiating_file_id).find_at_position(ctx.position) {
ast::SchemaPosition::Model(
Expand Down Expand Up @@ -154,9 +152,7 @@ fn push_ast_completions(ctx: CompletionContext<'_>, completion_list: &mut Comple
datasource::relation_mode_completion(completion_list);
}

if let Some(config) = ctx.config {
ctx.connector().datasource_completions(config, completion_list);
}
ctx.connector().datasource_completions(ctx.config, completion_list);
}

ast::SchemaPosition::DataSource(
Expand Down
4 changes: 2 additions & 2 deletions prisma-schema-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ pub fn format(schema: String, params: String) -> String {

/// Docs: https://prisma.github.io/prisma-engines/doc/prisma_fmt/fn.get_config.html
#[wasm_bindgen]
pub fn get_config(params: String) -> Result<String, JsError> {
pub fn get_config(params: String) -> String {
register_panic_hook();
prisma_fmt::get_config(params).map_err(|e| JsError::new(&e))
prisma_fmt::get_config(params)
}

/// Docs: https://prisma.github.io/prisma-engines/doc/prisma_fmt/fn.get_dmmf.html
Expand Down
24 changes: 17 additions & 7 deletions psl/psl-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ mod reformat;
mod set_config_dir;
mod validate;

use std::sync::Arc;

pub use crate::{
common::{PreviewFeature, PreviewFeatures, ALL_PREVIEW_FEATURES},
configuration::{
Expand Down Expand Up @@ -130,16 +132,27 @@ pub fn parse_configuration(
schema: &str,
connectors: ConnectorRegistry<'_>,
) -> Result<Configuration, diagnostics::Diagnostics> {
let mut diagnostics = Diagnostics::default();
let ast = schema_ast::parse_schema(schema, &mut diagnostics, diagnostics::FileId::ZERO);
let out = validate_configuration(&ast, &mut diagnostics, connectors);
let source_file = SourceFile::new_allocated(Arc::from(schema.to_owned().into_boxed_str()));
let (_, out, mut diagnostics) =
error_tolerant_parse_configuration(&[("schema.prisma".into(), source_file)], connectors);
diagnostics.to_result().map(|_| out)
}

pub fn parse_configuration_multi_file(
files: &[(String, SourceFile)],
connectors: ConnectorRegistry<'_>,
) -> Result<(Files, Configuration), (Files, diagnostics::Diagnostics)> {
let (files, configuration, mut diagnostics) = error_tolerant_parse_configuration(files, connectors);
match diagnostics.to_result() {
Ok(_) => Ok((files, configuration)),
Err(err) => Err((files, err)),
}
}

pub fn error_tolerant_parse_configuration(
files: &[(String, SourceFile)],
connectors: ConnectorRegistry<'_>,
) -> (Files, Configuration, Diagnostics) {
let mut diagnostics = Diagnostics::default();
let mut configuration = Configuration::default();

Expand All @@ -150,10 +163,7 @@ pub fn parse_configuration_multi_file(
configuration.extend(out);
}

match diagnostics.to_result() {
Ok(_) => Ok((asts, configuration)),
Err(err) => Err((asts, err)),
}
(asts, configuration, diagnostics)
}

fn validate_configuration(
Expand Down
8 changes: 8 additions & 0 deletions psl/psl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ pub fn parse_configuration_multi_file(
psl_core::parse_configuration_multi_file(files, builtin_connectors::BUILTIN_CONNECTORS)
}

/// Parses and validates Prisma schemas, but skip analyzing everything except datasource and generator
/// blocks. It never fails, but when the returned `Diagnostics` contains errors, it implies that the
/// `Configuration` content is partial.
/// Consumers may then decide whether to convert `Diagnostics` into an error.
pub fn error_tolerant_parse_configuration(files: &[(String, SourceFile)]) -> (Files, Configuration, Diagnostics) {
psl_core::error_tolerant_parse_configuration(files, builtin_connectors::BUILTIN_CONNECTORS)
}

/// Parse and analyze a Prisma schema.
pub fn parse_schema(file: impl Into<SourceFile>) -> Result<ValidatedSchema, String> {
let mut schema = validate(file.into());
Expand Down
Loading