diff --git a/packages/language-server/src/workspace.ts b/packages/language-server/src/workspace.ts index dc25a72..1b13954 100644 --- a/packages/language-server/src/workspace.ts +++ b/packages/language-server/src/workspace.ts @@ -17,10 +17,15 @@ const getPackageManagerRequestType = new RequestType< GetPackageManagerRequest.ErrorType >(GET_PACKAGE_MANAGER_METHOD) -function createLanguageServerAdapter(folderUri: URI, connection: Connection): WorkspaceAdapter { +function createLanguageServerAdapter(folderUri: URI, connection: Connection, server: LanguageServer): WorkspaceAdapter { return { async readFile(path: string): Promise { - return await readFile(folderUri.with({ path }).fsPath, 'utf-8') + const uri = folderUri.with({ path }) + const doc = server.documents.get(uri) + if (doc) + return doc.getText() + + return await readFile(uri.fsPath, 'utf-8') }, async fileExists(path: string): Promise { @@ -102,7 +107,7 @@ export class WorkspaceState implements IWorkspaceState { return await WorkspaceContext.create( folderUri.path, - createLanguageServerAdapter(folderUri, this.#connection), + createLanguageServerAdapter(folderUri, this.#connection, this.#server), ) }, { diff --git a/packages/language-service/package.json b/packages/language-service/package.json index 0f8756d..847a9a2 100644 --- a/packages/language-service/package.json +++ b/packages/language-service/package.json @@ -26,6 +26,7 @@ "npmx-language-core": "workspace:*", "npmx-shared": "workspace:*", "semver": "catalog:inline", + "vscode-languageserver-textdocument": "catalog:inline", "vscode-uri": "catalog:lsp" } } diff --git a/packages/language-service/src/plugins/catalog.ts b/packages/language-service/src/plugins/catalog.ts index 41db272..2ca372a 100644 --- a/packages/language-service/src/plugins/catalog.ts +++ b/packages/language-service/src/plugins/catalog.ts @@ -3,7 +3,7 @@ import type { DependencyInfo } from 'npmx-language-core/workspace' import type { IWorkspaceState } from '../types' import { isPackageManifest, normalizeCatalogName } from 'npmx-language-core/utils' import { URI } from 'vscode-uri' -import { getResolvedDependencyAtOffset } from '../utils/range' +import { getDocumentByUri, getResolvedDependencyAtOffset } from '../utils/document' export function create(workspaceState: IWorkspaceState): LanguageServicePlugin { function getDependencyFileUri(documentUri: string): URI | undefined { @@ -103,12 +103,10 @@ export function create(workspaceState: IWorkspaceState): LanguageServicePlugin { return const workspaceFileUri = dependencyFileUri.with({ path: workspaceContext.workspaceFilePath }) - const sourceScript = context.language.scripts.get(workspaceFileUri) - if (!sourceScript) + const workspaceDocument = await getDocumentByUri(context, workspaceFileUri) + if (!workspaceDocument) return - const workspaceDocument = context.documents.get(sourceScript.id, sourceScript.languageId, sourceScript.snapshot) - const [targetStart, targetEnd] = targetDependency.specRange const originStart = document.positionAt(dependency.specRange[0]) const originEnd = document.positionAt(dependency.specRange[1]) diff --git a/packages/language-service/src/plugins/hover.ts b/packages/language-service/src/plugins/hover.ts index 8a27de2..74358b2 100644 --- a/packages/language-service/src/plugins/hover.ts +++ b/packages/language-service/src/plugins/hover.ts @@ -5,7 +5,7 @@ import { jsrPackageUrl, npmxDocsUrl, npmxPackageUrl } from 'npmx-language-core/l import { getImportSpecifierAtOffset, isDependencyFile } from 'npmx-language-core/utils' import { URI } from 'vscode-uri' import { getConfig } from '../config' -import { getResolvedDependencyAtOffset } from '../utils/range' +import { getResolvedDependencyAtOffset } from '../utils/document' export function create(workspaceState: IWorkspaceState): LanguageServicePlugin { const SPACER = ' ' diff --git a/packages/language-service/src/plugins/version-completion.ts b/packages/language-service/src/plugins/version-completion.ts index 902a0fd..25d24cd 100644 --- a/packages/language-service/src/plugins/version-completion.ts +++ b/packages/language-service/src/plugins/version-completion.ts @@ -3,7 +3,7 @@ import type { IWorkspaceState } from '../types' import { isDependencyFile } from 'npmx-language-core/utils' import { URI } from 'vscode-uri' import { getConfig } from '../config' -import { getResolvedDependencyAtOffset } from '../utils/range' +import { getResolvedDependencyAtOffset } from '../utils/document' import { formatUpgradeVersion } from '../utils/version' const PRERELEASE_PATTERN = /-.+/ diff --git a/packages/language-service/src/utils/document.ts b/packages/language-service/src/utils/document.ts new file mode 100644 index 0000000..0a435ec --- /dev/null +++ b/packages/language-service/src/utils/document.ts @@ -0,0 +1,30 @@ +import type { LanguageServiceContext } from '@volar/language-service' +import type { OffsetRange } from 'npmx-language-core/types' +import type { DependencyInfo } from 'npmx-language-core/workspace' +import type { URI } from 'vscode-uri' +import { TextDocument } from 'vscode-languageserver-textdocument' + +export async function getDocumentByUri(context: LanguageServiceContext, uri: URI) { + const sourceScript = context.language.scripts.get(uri, true) + if (sourceScript) + return context.documents.get(sourceScript.id, sourceScript.languageId, sourceScript.snapshot) + + const text = await context.env.fs!.readFile(uri) + if (text == null) + return + + return TextDocument.create(uri.toString(), 'json', 0, text) +} + +function isOffsetInRange(offset: number, [start, end]: OffsetRange): boolean { + return offset >= start && offset <= end +} + +export function getResolvedDependencyAtOffset( + dependencies: DependencyInfo[], + offset: number, +): DependencyInfo | undefined { + return dependencies.find((dep) => + isOffsetInRange(offset, dep.nameRange) || isOffsetInRange(offset, dep.specRange), + ) +} diff --git a/packages/language-service/src/utils/range.ts b/packages/language-service/src/utils/range.ts deleted file mode 100644 index feca297..0000000 --- a/packages/language-service/src/utils/range.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { OffsetRange } from 'npmx-language-core/types' -import type { DependencyInfo } from 'npmx-language-core/workspace' - -function isOffsetInRange(offset: number, [start, end]: OffsetRange): boolean { - return offset >= start && offset <= end -} - -export function getResolvedDependencyAtOffset( - dependencies: DependencyInfo[], - offset: number, -): DependencyInfo | undefined { - return dependencies.find((dep) => - isOffsetInRange(offset, dep.nameRange) || isOffsetInRange(offset, dep.specRange), - ) -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dda93dc..fe1612d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,6 +61,9 @@ catalogs: vscode-find-up: specifier: ^0.1.1 version: 0.1.1 + vscode-languageserver-textdocument: + specifier: ^1.0.12 + version: 1.0.12 yaml: specifier: ^2.8.3 version: 2.8.3 @@ -231,6 +234,9 @@ importers: semver: specifier: catalog:inline version: 7.7.4 + vscode-languageserver-textdocument: + specifier: catalog:inline + version: 1.0.12 vscode-uri: specifier: catalog:lsp version: 3.1.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 12ae65d..78fbe39 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -26,6 +26,7 @@ catalogs: reactive-vscode: ^1.0.0-beta.2 semver: ^7.7.4 vscode-find-up: ^0.1.1 + vscode-languageserver-textdocument: ^1.0.12 yaml: ^2.8.3 lsp: '@volar/language-server': ^2.4.28