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

feat(fmt): lsp find references #4934

Merged
merged 25 commits into from
Jul 3, 2024
Merged

feat(fmt): lsp find references #4934

merged 25 commits into from
Jul 3, 2024

Conversation

Druue
Copy link
Contributor

@Druue Druue commented Jun 20, 2024

I left details on testing this locally in the language-tools pr here

closes https://github.com/prisma/team-orm/issues/1201


Screen.Recording.2024-06-26.at.14.29.33.mov
Screen.Recording.2024-06-26.at.14.27.22.mov

closes https://github.com/prisma/team-orm/issues/1196


Screen.Recording.2024-06-26.at.14.22.53.mov

These only apply to models and views. Composite types have uniques, indices, so on defined in their containing model / view.

closes https://github.com/prisma/team-orm/issues/1200

Copy link

codspeed-hq bot commented Jun 20, 2024

CodSpeed Performance Report

Merging #4934 will not alter performance

Comparing feat/references (3b70d69) with main (34ace0e)

Summary

✅ 11 untouched benchmarks

Copy link
Contributor

github-actions bot commented Jun 20, 2024

WASM Query Engine file Size

Engine This PR Base branch Diff
Postgres 2.044MiB 2.044MiB 255.000B
Postgres (gzip) 814.777KiB 814.575KiB 207.000B
Mysql 2.014MiB 2.014MiB 241.000B
Mysql (gzip) 801.034KiB 801.013KiB 21.000B
Sqlite 1.915MiB 1.915MiB 241.000B
Sqlite (gzip) 763.149KiB 762.983KiB 170.000B

@Druue Druue force-pushed the feat/references branch from fa6d979 to e1b602d Compare June 24, 2024 17:06
prisma-schema-wasm/src/lib.rs Outdated Show resolved Hide resolved
@Druue Druue added this to the 5.17.0 milestone Jun 26, 2024
let arr = arg.value.as_array().unwrap();
let expr = arr.0.iter().find(|expr| expr.span().contains(position));
if let Some(expr) = expr {
return Self::ArgumentValue(arg.name(), expr.to_string());
Copy link
Contributor Author

@Druue Druue Jun 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Problem: when using nested composite type fields in attributes, i.e.

model User {
    id      String  @id @map("_id") @db.String
    address Address

    @@unique([address.poBox.name])
}

type Address {
    street String  @db.String
    city   String
    poBox    POBox
}

type SubType {
    name String
}

We retrieve the whole string that is defined, i.e.

"address.poBox.name"

and dont have more granular understanding of if the cursor is inside address, poBox or name.

This PR already supports finding fields from non-nested fields in block attributes, but I'm not sure what to do with this.

This seems like it would require modification to this pest grammar:

expression = { function_call | array_expression | numeric_literal | string_literal | path }

string_literal = ${ "\"" ~ string_content ~ "\"" }

string_content = @{ (string_escape | !("\"" | ASCII_CONTROL_CHARACTER) ~ ANY)* }

But I'm not fully sure of the ramifications of changing the pest grammar like this. If this is something we want to explore, I think it should be in a follow-up PR as a stretch goal.

We could maybe make string literal an option of string content or string array content 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string literal rule is irrelevant here, it matches a quoted string literal in source code of the schema and there are no quotes here. The relevant rule is path, and it is already defined as

identifier = @{ ASCII_ALPHANUMERIC ~ ( "_" | "-" | ASCII_ALPHANUMERIC)* }
path = @{ identifier ~ ("." ~ path?)* }

so no modifications are necessary in the grammar, it is already defined the way you need.

You need to modify the Rule::path case in parse_expression in psl/schema-ast/src/parser/parse_expression.rs to recurse into path and create a separate span for each identifier token instead of converting the whole subtree to string as it does now.

@Druue Druue marked this pull request as ready for review June 26, 2024 15:39
@Druue Druue requested a review from a team as a code owner June 26, 2024 15:39
@Druue Druue requested review from Weakky and removed request for a team June 26, 2024 15:39
/// `CodeActionParams` object and the response being a list of
/// `CodeActionOrCommand` objects.
#[wasm_bindgen]
pub fn references(schema: String, params: String) -> String {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new wasm endpoint for references to be used by language-tools

Vec::new()
}

pub(crate) fn references(schema_files: Vec<(String, SourceFile)>, params: ReferenceParams) -> Vec<Location> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where we actually handle finding all the references

@@ -495,7 +495,7 @@ impl Connector for PostgresDatamodelConnector {
ast::ModelPosition::ModelAttribute(
"index",
attr_id,
ast::AttributePosition::FunctionArgument(field_name, "ops"),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to line-up with changes in find_at_position

@@ -85,19 +86,47 @@ fn push_ast_completions(ctx: CompletionContext<'_>, completion_list: &mut Comple
.relation_mode()
.unwrap_or_else(|| ctx.connector().default_relation_mode());

match ctx.db.ast(ctx.initiating_file_id).find_at_position(position) {
let find_at_position = ctx.db.ast(ctx.initiating_file_id).find_at_position(position);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the process of updating find_at_position for references I broke completions for referential actions. However, due to the changes in find_at_position we are now able to offer completions on partial values:

Screen.Recording.2024-06-25.at.22.47.11.mov

@@ -86,7 +86,7 @@ pub fn preview_features() -> String {
}

/// 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).
/// request](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-16.md#completion-request-leftwards_arrow_with_hook).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These docs links were outdated, they now link to the correct sections :)

Druue added a commit to prisma/language-tools that referenced this pull request Jun 26, 2024
Copy link
Contributor

@Weakky Weakky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, there's a couple of things you can improve

prisma-fmt/src/references.rs Outdated Show resolved Hide resolved
prisma-fmt/src/references.rs Outdated Show resolved Hide resolved
prisma-fmt/src/references.rs Outdated Show resolved Hide resolved
prisma-fmt/src/references.rs Outdated Show resolved Hide resolved
prisma-fmt/src/references.rs Outdated Show resolved Hide resolved
prisma-fmt/src/references.rs Outdated Show resolved Hide resolved
prisma-fmt/src/references.rs Outdated Show resolved Hide resolved
psl/schema-ast/src/ast/argument.rs Show resolved Hide resolved
prisma-fmt/src/references.rs Outdated Show resolved Hide resolved
Druue and others added 3 commits July 2, 2024 12:26
find_where_used_*
- return iterators instead of immediately collecting to vecs
- Note: these then have to be immediately collected by the caller as rust otherwise complains about opaque types. Can be revisited later if we see fit.

find_where_used_in_model
- rename *_as_field_name
- now returns an optional identifier instead of a vec
- cut down iteration
- finding the model / view is now infallible

find_where_used_as_field_type
- general clean up
- remove fields allocation

find_where_used_as_top_name
- use top interner instead of iterating everything
- return Option of identifier instead of iterator

Co-authored-by: Flavian Desverne <flavian.dsv@gmail.com>
prisma-fmt/src/references.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@Weakky Weakky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work 👍

@Druue Druue merged commit 9b8d05f into main Jul 3, 2024
206 checks passed
@Druue Druue deleted the feat/references branch July 3, 2024 21:34
Druue added a commit to prisma/language-tools that referenced this pull request Jul 4, 2024
Druue added a commit to prisma/language-tools that referenced this pull request Jul 4, 2024
* companion pr to prisma/prisma-engines#4934
* test references in LT

---------

Co-authored-by: Serhii Tatarintsev <tatarintsev@prisma.io>
@Druue Druue linked an issue Jul 18, 2024 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support fetching references for a model
3 participants