Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions extensions/vscode/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { openInBrowser } from './commands/open-in-browser'
import { useCodeActions } from './providers/code-actions'
import { useCompletionItem } from './providers/completion-item'
import { useDecorators } from './providers/decorators'
import { useDefinition } from './providers/definition'
import { useDiagnostics } from './providers/diagnostics'
import { useDocumentLink } from './providers/document-link'
import { logger } from './state'
Expand All @@ -28,7 +27,6 @@ export const { activate, deactivate } = defineExtension((ctx) => {
useDecorators()
useCodeActions()
useDocumentLink()
useDefinition()

useCommands({
[commands.openInBrowser]: openInBrowser,
Expand Down
33 changes: 0 additions & 33 deletions extensions/vscode/src/providers/completion-item/catalog.ts

This file was deleted.

13 changes: 1 addition & 12 deletions extensions/vscode/src/providers/completion-item/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { config } from '#state'
import { PACKAGE_JSON_PATTERN, SUPPORTED_DOCUMENT_PATTERN } from '#utils/constants'
import { SUPPORTED_DOCUMENT_PATTERN } from '#utils/constants'
import { watchEffect } from 'reactive-vscode'
import { languages } from 'vscode'
import { CatalogCompletionItemProvider } from './catalog'
import { VersionCompletionItemProvider } from './version'

export function useCompletionItem() {
Expand All @@ -18,14 +17,4 @@ export function useCompletionItem() {

onCleanup(() => disposable.dispose())
})

watchEffect((onCleanup) => {
const disposable = languages.registerCompletionItemProvider(
{ pattern: PACKAGE_JSON_PATTERN },
new CatalogCompletionItemProvider(),
...CatalogCompletionItemProvider.triggers,
)

onCleanup(() => disposable.dispose())
})
}
39 changes: 0 additions & 39 deletions extensions/vscode/src/providers/definition/catalog.ts

This file was deleted.

10 changes: 0 additions & 10 deletions extensions/vscode/src/providers/definition/index.ts

This file was deleted.

1 change: 0 additions & 1 deletion extensions/vscode/src/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { PACKAGE_JSON_BASENAME, PNPM_WORKSPACE_BASENAME, YARN_WORKSPACE_BASENAME } from 'npmx-language-core/constants'

export const PACKAGE_JSON_PATTERN = `**/${PACKAGE_JSON_BASENAME}`
export const SUPPORTED_DOCUMENT_PATTERN = `**/{${PACKAGE_JSON_BASENAME},${PNPM_WORKSPACE_BASENAME},${YARN_WORKSPACE_BASENAME}}`

export const PRERELEASE_PATTERN = /-.+/
8 changes: 4 additions & 4 deletions packages/language-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@
"yaml": "catalog:inline"
},
"inlinedDependencies": {
"module-replacements": "2.11.0",
"jsonc-parser": "3.3.1",
"yaml": "2.8.2",
"fast-npm-meta": "1.4.2",
"pathe": "2.0.3"
"jsonc-parser": "3.3.1",
"module-replacements": "2.11.0",
"pathe": "2.0.3",
"yaml": "2.8.3"
}
}
24 changes: 12 additions & 12 deletions packages/language-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,21 @@
"vscode-uri": "catalog:lsp"
},
"inlinedDependencies": {
"vscode-languageserver": "9.0.1",
"vscode-jsonrpc": "8.2.0",
"vscode-languageserver-types": "3.17.5",
"vscode-languageserver-protocol": "3.17.5",
"@volar/source-map": "2.4.28",
"@volar/language-core": "2.4.28",
"vscode-uri": "3.1.0",
"@volar/language-service": "2.4.28",
"vscode-languageserver-textdocument": "1.0.12",
"request-light": "0.7.0",
"@volar/language-server": "2.4.28",
"path-browserify": "1.0.1",
"@volar/language-service": "2.4.28",
"@volar/source-map": "2.4.28",
"@volar/typescript": "2.4.28",
"semver": "7.7.4",
"ocache": "0.1.4",
"ohash": "2.0.11",
"ocache": "0.1.4"
"path-browserify": "1.0.1",
"request-light": "0.7.0",
"semver": "7.7.4",
"vscode-jsonrpc": "8.2.0",
"vscode-languageserver": "9.0.1",
"vscode-languageserver-protocol": "3.17.5",
"vscode-languageserver-textdocument": "1.0.12",
"vscode-languageserver-types": "3.17.5",
"vscode-uri": "3.1.0"
}
}
2 changes: 2 additions & 0 deletions packages/language-service/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { LanguageServicePlugin } from '@volar/language-service'
import type { IWorkspaceState } from './types'
import { create as createNpmxCatalogService } from './plugins/catalog'
import { create as createNpmxHoverService } from './plugins/hover'

export function createNpmxLanguageServicePlugins(workspace: IWorkspaceState): LanguageServicePlugin[] {
return [
createNpmxCatalogService(workspace),
createNpmxHoverService(workspace),
]
}
135 changes: 135 additions & 0 deletions packages/language-service/src/plugins/catalog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import type { CompletionItemKind, CompletionList, LanguageServicePlugin, LanguageServicePluginInstance, LocationLink } from '@volar/language-service'
import type { DependencyInfo } from 'npmx-language-core/workspace'
import type { IWorkspaceState } from '../types'
import { isDependencyFile, normalizeCatalogName } from 'npmx-language-core/utils'
import { URI } from 'vscode-uri'
import { getResolvedDependencyAtOffset } from '../utils/range'

export function create(workspaceState: IWorkspaceState): LanguageServicePlugin {
function getDependencyFileUri(documentUri: string): URI | undefined {
const uri = URI.parse(documentUri)
if (uri.scheme !== 'file' || !isDependencyFile(uri.path))
return

return uri
}

async function getCatalogDependency(documentUri: string, offset: number): Promise<DependencyInfo | undefined> {
const dependencies = await workspaceState.getResolvedDependencies(documentUri)
if (!dependencies)
return

const dependency = getResolvedDependencyAtOffset(dependencies, offset)
if (!dependency?.rawSpec.startsWith('catalog:'))
return

return dependency
}

function matchesCatalogDependency(candidate: DependencyInfo, dependency: DependencyInfo): boolean {
return candidate.rawName === dependency.resolvedName
&& candidate.categoryName != null
&& dependency.categoryName != null
&& normalizeCatalogName(candidate.categoryName) === normalizeCatalogName(dependency.categoryName)
}

return {
name: 'npmx-catalog',
capabilities: {
completionProvider: {
triggerCharacters: [':'],
},
definitionProvider: true,
},
create(context): LanguageServicePluginInstance {
return {
async provideCompletionItems(document, position): Promise<CompletionList | undefined> {
const dependencyFileUri = getDependencyFileUri(document.uri)
if (!dependencyFileUri)
return

const offset = document.offsetAt(position)
const dependency = await getCatalogDependency(document.uri, offset)
if (!dependency)
return

const workspaceContext = await workspaceState.getWorkspaceContext(document.uri)
if (!workspaceContext)
return

const catalogs = await workspaceContext.getCatalogs()
if (!catalogs)
return

const items: CompletionList['items'] = []

for (const [name, catalog] of Object.entries(catalogs)) {
const version = catalog[dependency.resolvedName]
if (!version)
continue

items.push({
label: name,
kind: 12 satisfies typeof CompletionItemKind.Value,
detail: version,
})
}

return { isIncomplete: false, items }
},

async provideDefinition(document, position): Promise<LocationLink[] | undefined> {
const dependencyFileUri = getDependencyFileUri(document.uri)
if (!dependencyFileUri)
return

const offset = document.offsetAt(position)
const dependency = await getCatalogDependency(document.uri, offset)
if (!dependency)
return

const workspaceContext = await workspaceState.getWorkspaceContext(document.uri)
if (!workspaceContext?.workspaceFilePath)
return

const workspaceFileInfo = await workspaceContext.loadWorkspaceFileInfo(workspaceContext.workspaceFilePath)
if (!workspaceFileInfo)
return

const targetDependency = workspaceFileInfo.dependencies.find((candidate) =>
matchesCatalogDependency(candidate, dependency),
)
if (!targetDependency)
return

const workspaceFileUri = dependencyFileUri.with({ path: workspaceContext.workspaceFilePath })
const sourceScript = context.language.scripts.get(workspaceFileUri)
if (!sourceScript)
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])

return [{
targetUri: workspaceFileUri.toString(),
targetRange: {
start: workspaceDocument.positionAt(targetStart),
end: workspaceDocument.positionAt(targetEnd),
},
targetSelectionRange: {
start: workspaceDocument.positionAt(targetStart),
end: workspaceDocument.positionAt(targetEnd),
},
originSelectionRange: {
start: originStart,
end: originEnd,
},
}]
},
}
},
}
}
Loading