Skip to content

Commit

Permalink
tech(fmt): extract LSPContext struct (#4924)
Browse files Browse the repository at this point in the history
extracted from #4923
  • Loading branch information
Druue committed Jun 19, 2024
1 parent 836ad78 commit 5e01b93
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 87 deletions.
35 changes: 9 additions & 26 deletions prisma-fmt/src/code_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,23 @@ use crate::offsets::{position_after_span, range_to_span, span_to_range};
use log::warn;
use lsp_types::{CodeActionOrCommand, CodeActionParams, Diagnostic, Range, TextEdit, Url, WorkspaceEdit};
use psl::{
diagnostics::{FileId, Span},
diagnostics::Span,
parser_database::{
ast,
walkers::{ModelWalker, RefinedRelationWalker, ScalarFieldWalker},
ParserDatabase, SourceFile,
SourceFile,
},
schema_ast::ast::{Attribute, IndentationType, NewlineType, WithSpan},
Configuration, Datasource, PreviewFeature,
schema_ast::ast::{self, Attribute, IndentationType, NewlineType, WithSpan},
PreviewFeature,
};
use std::collections::HashMap;

pub(super) struct CodeActionsContext<'a> {
pub(super) db: &'a ParserDatabase,
pub(super) config: &'a Configuration,
pub(super) initiating_file_id: FileId,
pub(super) lsp_params: CodeActionParams,
}
use crate::LSPContext;

impl<'a> CodeActionsContext<'a> {
pub(super) fn initiating_file_source(&self) -> &str {
self.db.source(self.initiating_file_id)
}

pub(super) fn initiating_file_uri(&self) -> &str {
self.db.file_name(self.initiating_file_id)
}
pub(super) type CodeActionsContext<'a> = LSPContext<'a, CodeActionParams>;

impl<'a> CodeActionsContext<'a> {
pub(super) fn diagnostics(&self) -> &[Diagnostic] {
&self.lsp_params.context.diagnostics
}

pub(super) fn datasource(&self) -> Option<&Datasource> {
self.config.datasources.first()
&self.params.context.diagnostics
}

/// A function to find diagnostics matching the given span. Used for
Expand All @@ -55,7 +39,6 @@ impl<'a> CodeActionsContext<'a> {
))
})
}

pub(super) fn diagnostics_for_span_with_message(&self, span: Span, message: &str) -> Vec<Diagnostic> {
self.diagnostics_for_span(span)
.filter(|diag| diag.message.contains(message))
Expand Down Expand Up @@ -89,7 +72,7 @@ pub(crate) fn available_actions(
db: &validated_schema.db,
config,
initiating_file_id,
lsp_params: params,
params: &params,
};

let initiating_ast = validated_schema.db.ast(initiating_file_id);
Expand Down
10 changes: 5 additions & 5 deletions prisma-fmt/src/code_actions/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ pub(super) fn create_missing_block_for_model(
diagnostics.iter().for_each(|diag| {
push_missing_block(
diag,
context.lsp_params.text_document.uri.clone(),
context.params.text_document.uri.clone(),
range,
"model",
actions,
model.newline(),
);
push_missing_block(
diag,
context.lsp_params.text_document.uri.clone(),
context.params.text_document.uri.clone(),
range,
"enum",
actions,
Expand All @@ -52,7 +52,7 @@ pub(super) fn create_missing_block_for_model(
if ds.active_provider == "mongodb" {
push_missing_block(
diag,
context.lsp_params.text_document.uri.clone(),
context.params.text_document.uri.clone(),
range,
"type",
actions,
Expand Down Expand Up @@ -87,15 +87,15 @@ pub(super) fn create_missing_block_for_type(
diagnostics.iter().for_each(|diag| {
push_missing_block(
diag,
context.lsp_params.text_document.uri.clone(),
context.params.text_document.uri.clone(),
range,
"type",
actions,
composite_type.newline(),
);
push_missing_block(
diag,
context.lsp_params.text_document.uri.clone(),
context.params.text_document.uri.clone(),
range,
"enum",
actions,
Expand Down
4 changes: 2 additions & 2 deletions prisma-fmt/src/code_actions/relations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub(super) fn add_referencing_side_unique(
);

let mut changes = HashMap::new();
changes.insert(context.lsp_params.text_document.uri.clone(), vec![text]);
changes.insert(context.params.text_document.uri.clone(), vec![text]);

let edit = WorkspaceEdit {
changes: Some(changes),
Expand Down Expand Up @@ -278,7 +278,7 @@ pub(super) fn add_index_for_relation_fields(
};

let mut changes = HashMap::new();
changes.insert(context.lsp_params.text_document.uri.clone(), vec![text]);
changes.insert(context.params.text_document.uri.clone(), vec![text]);

let edit = WorkspaceEdit {
changes: Some(changes),
Expand Down
36 changes: 36 additions & 0 deletions prisma-fmt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,44 @@ mod validate;

use log::*;
pub use offsets::span_to_range;
use psl::{
datamodel_connector::Connector, diagnostics::FileId, parser_database::ParserDatabase, Configuration, Datasource,
Generator,
};
use schema_file_input::SchemaFileInput;

#[derive(Debug, Clone, Copy)]
pub(crate) struct LSPContext<'a, T> {
pub(crate) db: &'a ParserDatabase,
pub(crate) config: &'a Configuration,
pub(crate) initiating_file_id: FileId,
pub(crate) params: &'a T,
}

impl<'a, T> LSPContext<'a, T> {
pub(crate) fn initiating_file_source(&self) -> &str {
self.db.source(self.initiating_file_id)
}

pub(crate) fn initiating_file_uri(&self) -> &str {
self.db.file_name(self.initiating_file_id)
}

pub(crate) fn datasource(&self) -> Option<&Datasource> {
self.config.datasources.first()
}

pub(crate) fn connector(&self) -> &'static dyn Connector {
self.datasource()
.map(|ds| ds.active_connector)
.unwrap_or(&psl::datamodel_connector::EmptyDatamodelConnector)
}

pub(crate) fn generator(&self) -> Option<&'a Generator> {
self.config.generators.first()
}
}

/// The API is modelled on an LSP [completion
/// request](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-16.md#textDocument_completion).
/// Input and output are both JSON, the request being a `CompletionParams` object and the response
Expand Down
94 changes: 40 additions & 54 deletions prisma-fmt/src/text_document_completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,36 @@ use enumflags2::BitFlags;
use log::*;
use lsp_types::*;
use psl::{
datamodel_connector::Connector,
diagnostics::{FileId, Span},
diagnostics::Span,
error_tolerant_parse_configuration,
parser_database::{ast, ParserDatabase, SourceFile},
Configuration, Datasource, Diagnostics, Generator, PreviewFeature,
Diagnostics, PreviewFeature,
};

use crate::LSPContext;

mod datasource;

pub(super) type CompletionContext<'a> = LSPContext<'a, CompletionParams>;

impl<'a> CompletionContext<'a> {
pub(super) fn namespaces(&'a self) -> &'a [(String, Span)] {
self.datasource().map(|ds| ds.namespaces.as_slice()).unwrap_or(&[])
}
pub(super) fn preview_features(&self) -> BitFlags<PreviewFeature> {
self.generator()
.and_then(|gen| gen.preview_features)
.unwrap_or_default()
}

pub(super) fn position(&self) -> Option<usize> {
let pos = self.params.text_document_position.position;
let initiating_doc = self.initiating_file_source();

position_to_offset(&pos, initiating_doc)
}
}

pub(crate) fn empty_completion_list() -> CompletionList {
CompletionList {
is_incomplete: true,
Expand All @@ -37,19 +58,10 @@ pub(crate) fn completion(schema_files: Vec<(String, SourceFile)>, params: Comple
return empty_completion_list();
};

let initiating_doc = db.source(initiating_file_id);
let position = if let Some(pos) = position_to_offset(&params.text_document_position.position, initiating_doc) {
pos
} else {
warn!("Received a position outside of the document boundaries in CompletionParams");
return empty_completion_list();
};

let ctx = CompletionContext {
config: &config,
params: &params,
db: &db,
position,
initiating_file_id,
};

Expand All @@ -58,48 +70,22 @@ pub(crate) fn completion(schema_files: Vec<(String, SourceFile)>, params: Comple
list
}

#[derive(Debug, Clone, Copy)]
struct CompletionContext<'a> {
config: &'a Configuration,
params: &'a CompletionParams,
db: &'a ParserDatabase,
position: usize,
initiating_file_id: FileId,
}

impl<'a> CompletionContext<'a> {
pub(crate) fn connector(self) -> &'static dyn Connector {
self.datasource()
.map(|ds| ds.active_connector)
.unwrap_or(&psl::datamodel_connector::EmptyDatamodelConnector)
}

pub(crate) fn namespaces(self) -> &'a [(String, Span)] {
self.datasource().map(|ds| ds.namespaces.as_slice()).unwrap_or(&[])
}

pub(crate) fn preview_features(self) -> BitFlags<PreviewFeature> {
self.generator()
.and_then(|gen| gen.preview_features)
.unwrap_or_default()
}

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

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

fn push_ast_completions(ctx: CompletionContext<'_>, completion_list: &mut CompletionList) {
let position = match ctx.position() {
Some(pos) => pos,
None => {
warn!("Received a position outside of the document boundaries in CompletionParams");
completion_list.is_incomplete = true;
return;
}
};

let relation_mode = ctx
.config
.relation_mode()
.unwrap_or_else(|| ctx.connector().default_relation_mode());

match ctx.db.ast(ctx.initiating_file_id).find_at_position(ctx.position) {
match ctx.db.ast(ctx.initiating_file_id).find_at_position(position) {
ast::SchemaPosition::Model(
_model_id,
ast::ModelPosition::Field(_, ast::FieldPosition::Attribute("relation", _, Some(attr_name))),
Expand Down Expand Up @@ -130,23 +116,23 @@ fn push_ast_completions(ctx: CompletionContext<'_>, completion_list: &mut Comple
}

ast::SchemaPosition::DataSource(_source_id, ast::SourcePosition::Source) => {
if !ds_has_prop(ctx, "provider") {
if !ds_has_prop(&ctx, "provider") {
datasource::provider_completion(completion_list);
}

if !ds_has_prop(ctx, "url") {
if !ds_has_prop(&ctx, "url") {
datasource::url_completion(completion_list);
}

if !ds_has_prop(ctx, "shadowDatabaseUrl") {
if !ds_has_prop(&ctx, "shadowDatabaseUrl") {
datasource::shadow_db_completion(completion_list);
}

if !ds_has_prop(ctx, "directUrl") {
if !ds_has_prop(&ctx, "directUrl") {
datasource::direct_url_completion(completion_list);
}

if !ds_has_prop(ctx, "relationMode") {
if !ds_has_prop(&ctx, "relationMode") {
datasource::relation_mode_completion(completion_list);
}

Expand Down Expand Up @@ -179,7 +165,7 @@ fn push_ast_completions(ctx: CompletionContext<'_>, completion_list: &mut Comple
}
}

fn ds_has_prop(ctx: CompletionContext<'_>, prop: &str) -> bool {
fn ds_has_prop(ctx: &CompletionContext<'_>, prop: &str) -> bool {
if let Some(ds) = ctx.datasource() {
match prop {
"relationMode" => ds.relation_mode_defined(),
Expand Down

0 comments on commit 5e01b93

Please sign in to comment.