Skip to content

Commit

Permalink
feat(LS): references (#1775)
Browse files Browse the repository at this point in the history
* companion pr to prisma/prisma-engines#4934
* test references in LT

---------

Co-authored-by: Serhii Tatarintsev <tatarintsev@prisma.io>
  • Loading branch information
Druue and SevInf committed Jul 4, 2024
1 parent a4ef9e5 commit ca5d029
Show file tree
Hide file tree
Showing 9 changed files with 407 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
generator client {
provider = "prisma-client-js"
previewFeatures = ["prismaSchemaFolder", "views"]
}

datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// enum doc
enum Pet {
/// Cat doc
Cat
RedPanda
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
model User {
id String @id @map("_id")
posts Post[]
/// field doc
pet Pet
address Address
indexedField String
@@index([indexedField])
}

/// Documentation
model Post {
id String @id @map("_id")
authorId String
author User @relation(fields: [authorId], references: [id])
blah UserTwo[]
}

model B {
/// field doc
id String @id @map("_id")
bId String?
bees B[] @relation(name: "bees")
B B? @relation(name: "bees", fields: [bId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/// Address doc
type Address {
street String
city String
/// poBox doc
poBox POBox
}

/// Nested ct doc
type POBox {
name String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
view UserTwo {
id String @id @map("_id")
postId String
posts Post @relation(fields: [postId], references: [id])
address Address
uniqueField String
otherUniqueField String
@@unique(fields: [uniqueField])
@@unique([otherUniqueField])
@@unique([address.poBox.name])
@@map("hi")
}
283 changes: 283 additions & 0 deletions packages/language-server/src/__test__/references.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
import { describe, expect, test } from 'vitest'
import { Position, ReferenceParams } from 'vscode-languageserver'
import { handleReferencesRequest } from '../lib/MessageHandler'
import { PrismaSchema } from '../lib/Schema'
import { getMultifileHelper } from './MultifileHelper'

const getReferences = async (uri: string, schema: PrismaSchema, position: Position) => {
const params: ReferenceParams = {
textDocument: { uri: uri },
position,
context: { includeDeclaration: true },
}

return handleReferencesRequest(schema, params)
}
describe('References', async () => {
const helper = await getMultifileHelper('references')

test('of a composite type block name', async () => {
const file = helper.file('types.prisma')

const references = await getReferences(
file.uri,
helper.schema,
file.lineContaining('type Address').characterAfter('Addr'),
)

expect(references).not.toBeUndefined()
expect(references).toMatchInlineSnapshot(`
[
{
"range": {
"end": {
"character": 12,
"line": 1,
},
"start": {
"character": 5,
"line": 1,
},
},
"uri": "file:///references/types.prisma",
},
{
"range": {
"end": {
"character": 19,
"line": 6,
},
"start": {
"character": 12,
"line": 6,
},
},
"uri": "file:///references/models.prisma",
},
{
"range": {
"end": {
"character": 19,
"line": 6,
},
"start": {
"character": 12,
"line": 6,
},
},
"uri": "file:///references/views.prisma",
},
]
`)
})

test('of a composite type as a field type', async () => {
const file = helper.file('models.prisma')

const references = await getReferences(
file.uri,
helper.schema,
file.lineContaining('address Address').characterAfter('Addr'),
)

expect(references).not.toBeUndefined()
expect(references).toMatchInlineSnapshot(`
[
{
"range": {
"end": {
"character": 12,
"line": 1,
},
"start": {
"character": 5,
"line": 1,
},
},
"uri": "file:///references/types.prisma",
},
{
"range": {
"end": {
"character": 19,
"line": 6,
},
"start": {
"character": 12,
"line": 6,
},
},
"uri": "file:///references/models.prisma",
},
{
"range": {
"end": {
"character": 19,
"line": 6,
},
"start": {
"character": 12,
"line": 6,
},
},
"uri": "file:///references/views.prisma",
},
]
`)
})

test('of a model block name', async () => {
const file = helper.file('models.prisma')

const references = await getReferences(
file.uri,
helper.schema,
file.lineContaining('model Post').characterAfter('Po'),
)

expect(references).not.toBeUndefined()
expect(references).toMatchInlineSnapshot(`
[
{
"range": {
"end": {
"character": 10,
"line": 14,
},
"start": {
"character": 6,
"line": 14,
},
},
"uri": "file:///references/models.prisma",
},
{
"range": {
"end": {
"character": 16,
"line": 3,
},
"start": {
"character": 12,
"line": 3,
},
},
"uri": "file:///references/models.prisma",
},
{
"range": {
"end": {
"character": 15,
"line": 4,
},
"start": {
"character": 11,
"line": 4,
},
},
"uri": "file:///references/views.prisma",
},
]
`)
})

test('of a model relation as a field type', async () => {
const file = helper.file('models.prisma')

const references = await getReferences(
file.uri,
helper.schema,
file.lineContaining('author User').characterAfter('Us'),
)

expect(references).not.toBeUndefined()
expect(references).toMatchInlineSnapshot(`
[
{
"range": {
"end": {
"character": 10,
"line": 0,
},
"start": {
"character": 6,
"line": 0,
},
},
"uri": "file:///references/models.prisma",
},
{
"range": {
"end": {
"character": 17,
"line": 17,
},
"start": {
"character": 13,
"line": 17,
},
},
"uri": "file:///references/models.prisma",
},
]
`)
})

test('of a field from relation fields', async () => {
const file = helper.file('models.prisma')

const references = await getReferences(
file.uri,
helper.schema,
file.lineContaining('author User').characterAfter('fields: [auth'),
)

expect(references).not.toBeUndefined()
expect(references).toMatchInlineSnapshot(`
[
{
"range": {
"end": {
"character": 12,
"line": 16,
},
"start": {
"character": 4,
"line": 16,
},
},
"uri": "file:///references/models.prisma",
},
]
`)
})

test('of a field from relation fields', async () => {
const file = helper.file('models.prisma')

const references = await getReferences(
file.uri,
helper.schema,
file.lineContaining('author User').characterAfter('references: [i'),
)

expect(references).not.toBeUndefined()
expect(references).toMatchInlineSnapshot(`
[
{
"range": {
"end": {
"character": 6,
"line": 1,
},
"start": {
"character": 4,
"line": 1,
},
},
"uri": "file:///references/models.prisma",
},
]
`)
})
})
11 changes: 11 additions & 0 deletions packages/language-server/src/lib/MessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
DocumentSymbol,
SymbolKind,
LocationLink,
ReferenceParams,
Location,
} from 'vscode-languageserver'
import type { TextDocument } from 'vscode-languageserver-textdocument'

Expand Down Expand Up @@ -53,6 +55,7 @@ import {
import { prismaSchemaWasmCompletions, localCompletions } from './completions'
import { PrismaSchema, SchemaDocument } from './Schema'
import { DiagnosticMap } from './DiagnosticMap'
import references from './prisma-schema-wasm/references'

export function handleDiagnosticsRequest(
schema: PrismaSchema,
Expand Down Expand Up @@ -223,6 +226,14 @@ export function handleCompletionRequest(
return prismaSchemaWasmCompletions(schema, params, onError) || localCompletions(schema, document, params, onError)
}

export function handleReferencesRequest(
schema: PrismaSchema,
params: ReferenceParams,
onError?: (errorMessage: string) => void,
): Location[] | undefined {
return references(schema, params, onError)
}

export function handleRenameRequest(
schema: PrismaSchema,
initiatingDocument: TextDocument,
Expand Down
Loading

0 comments on commit ca5d029

Please sign in to comment.