Skip to content

Commit

Permalink
spruce up relation field doc with @relation(...) info
Browse files Browse the repository at this point in the history
  • Loading branch information
Druue committed Jul 3, 2024
1 parent 8ef551c commit 9bd8194
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 15 deletions.
53 changes: 43 additions & 10 deletions prisma-fmt/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use log::{info, warn};
use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind};
use psl::{
error_tolerant_parse_configuration,
parser_database::{walkers, ParserDatabase, ScalarFieldType},
parser_database::{
walkers::{self, Walker},
ParserDatabase, RelationFieldId, ScalarFieldType,
},
schema_ast::ast::{
self, CompositeTypePosition, EnumPosition, EnumValuePosition, Field, FieldPosition, ModelPosition,
SchemaPosition, WithDocumentation, WithName,
Expand Down Expand Up @@ -140,22 +143,20 @@ fn hover(ctx: HoverContext<'_>) -> Option<Hover> {
},

walkers::RefinedFieldWalker::Relation(rf) => {
let relation = rf.relation();
let opposite_model = rf.related_model();
let opposite_field = rf.opposite_relation_field().unwrap().ast_field();
let opposite_rf = rf.opposite_relation_field().unwrap();
let opposite_field = opposite_rf.ast_field();
let related_model_type = if opposite_model.ast_model().is_view() {
"view"
} else {
"model"
};
let self_relation = if relation.is_self_relation() { " on self" } else { " " };
let relation_kind = format!("{}{}", relation.relation_kind(), self_relation);

Some(format_hover_content(
opposite_model.ast_model().documentation().unwrap_or_default(),
related_model_type,
name,
Some((relation_kind, opposite_field)),
Some((opposite_rf, opposite_field)),
))
}
}
Expand Down Expand Up @@ -193,12 +194,12 @@ fn format_hover_content(
documentation: &str,
variant: &str,
name: &str,
relation: Option<(String, &Field)>,
relation: Option<(Walker<RelationFieldId>, &Field)>,
) -> HoverContents {
let fancy_line_break = String::from("\n___\n");
let (field, relation_kind) = relation.map_or((Default::default(), Default::default()), |(rk, field)| {
(format!("\n\t...\n\t{field}\n"), format!("{rk}{fancy_line_break}"))
});

let (field, relation_kind) = format_relation_info(relation, &fancy_line_break);

let prisma_display = match variant {
"model" | "enum" | "view" | "type" => {
format!("```prisma\n{variant} {name} {{{field}}}\n```{fancy_line_break}{relation_kind}")
Expand All @@ -213,3 +214,35 @@ fn format_hover_content(
value: full_signature,
})
}

fn format_relation_info(
relation: Option<(Walker<RelationFieldId>, &Field)>,
fancy_line_break: &String,
) -> (String, String) {
if let Some((rf, field)) = relation {
let relation = rf.relation();

let fields = rf
.referencing_fields()
.map(|fields| fields.map(|f| f.to_string()).collect::<Vec<String>>().join(", "))
.map_or_else(String::new, |fields| format!(", fields: [{fields}]"));

let references = rf
.referenced_fields()
.map(|fields| fields.map(|f| f.to_string()).collect::<Vec<String>>().join(", "))
.map_or_else(String::new, |fields| format!(", references: [{fields}]"));

let self_relation = if relation.is_self_relation() { " on self" } else { " " };
let relation_kind = format!("{}{}", relation.relation_kind(), self_relation);

let relation_name = relation.relation_name();
let relation_inner = format!("name: \"{relation_name}\"{fields}{references}");

(
format!("\n\t...\n\t{field} @relation({relation_inner})\n"),
format!("{relation_kind}{fancy_line_break}"),
)
} else {
("".to_owned(), "".to_owned())
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"contents": {
"kind": "markdown",
"value": "```prisma\nmodel ModelNameA {\n\t...\n\tval ModelNameB\n}\n```\n___\none-to-many \n___\nThis is doc for A"
"value": "```prisma\nmodel ModelNameA {\n\t...\n\tval ModelNameB @relation(name: \"ModelNameAToModelNameB\", fields: [bId], references: [id])\n}\n```\n___\none-to-many \n___\nThis is doc for A"
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"contents": {
"kind": "markdown",
"value": "```prisma\nmodel Bee {\n\t...\n\tB Bee?\n}\n```\n___\none-to-many on self\n___\n"
"value": "```prisma\nmodel Bee {\n\t...\n\tB Bee? @relation(name: \"bees\", fields: [bId], references: [id])\n}\n```\n___\none-to-many on self\n___\n"
}
}
2 changes: 1 addition & 1 deletion psl/parser-database/src/walkers/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl<'db> EnumWalker<'db> {

/// Returns the specific value from the model.
pub fn value(self, value_id: ast::EnumValueId) -> EnumValueWalker<'db> {
self.walk((self.id, value_id.into()))
self.walk((self.id, value_id))
}

/// The values of the enum.
Expand Down
4 changes: 2 additions & 2 deletions psl/parser-database/src/walkers/relation_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl<'db> RelationFieldWalker<'db> {
self.db.walk(self.attributes().referenced_model)
}

/// The fields in the `@relation(references: ...)` argument.
/// The fields in the `@relation(references: [...])` argument.
pub fn referenced_fields(self) -> Option<impl ExactSizeIterator<Item = ScalarFieldWalker<'db>>> {
self.attributes()
.references
Expand Down Expand Up @@ -154,7 +154,7 @@ impl<'db> RelationFieldWalker<'db> {
self.fields()
}

/// The fields in the `fields: [...]` argument in the forward relation field.
/// The fields in the `@relation(fields: [...])` argument in the forward relation field.
pub fn fields(self) -> Option<impl ExactSizeIterator<Item = ScalarFieldWalker<'db>> + Clone> {
let attributes = &self.db.types[self.id];
attributes
Expand Down
8 changes: 8 additions & 0 deletions psl/parser-database/src/walkers/scalar_field.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt;

use crate::{
ast::{self, WithName},
types::{DefaultAttribute, FieldWithArgs, OperatorClassStore, ScalarField, ScalarType, SortOrder},
Expand Down Expand Up @@ -163,6 +165,12 @@ impl<'db> ScalarFieldWalker<'db> {
}
}

impl<'db> fmt::Display for ScalarFieldWalker<'db> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}

/// An `@default()` attribute on a field.
#[derive(Clone, Copy)]
pub struct DefaultValueWalker<'db> {
Expand Down

0 comments on commit 9bd8194

Please sign in to comment.