Skip to content

Commit e3a9a92

Browse files
authored
feat: migrate completion to language-service (#93)
* feat: migrate completion to language-service * remove useless files * rename
1 parent abc9331 commit e3a9a92

7 files changed

Lines changed: 77 additions & 148 deletions

File tree

extensions/vscode/src/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { launch } from './client'
88
import { addToIgnore } from './commands/add-to-ignore'
99
import { openFileInNpmx } from './commands/open-file-in-npmx'
1010
import { openInBrowser } from './commands/open-in-browser'
11-
import { useCompletionItem } from './providers/completion-item'
1211
import { useDecorators } from './providers/decorators'
1312
import { useDocumentLink } from './providers/document-link'
1413
import { logger } from './state'
@@ -22,7 +21,6 @@ export const { activate, deactivate } = defineExtension((ctx) => {
2221

2322
useWorkspaceContext()
2423

25-
useCompletionItem()
2624
useDecorators()
2725
useDocumentLink()
2826

extensions/vscode/src/providers/completion-item/index.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

extensions/vscode/src/providers/completion-item/version.ts

Lines changed: 0 additions & 54 deletions
This file was deleted.

extensions/vscode/src/utils/version.test.ts

Lines changed: 0 additions & 25 deletions
This file was deleted.

extensions/vscode/src/utils/version.ts

Lines changed: 0 additions & 47 deletions
This file was deleted.

packages/language-service/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import type { IWorkspaceState } from './types'
33
import { create as createNpmxCatalogService } from './plugins/catalog'
44
import { create as createNpmxDiagnosticsService } from './plugins/diagnostics'
55
import { create as createNpmxHoverService } from './plugins/hover'
6+
import { create as createNpmxVersionCompletionService } from './plugins/version-completion'
67

78
export function createNpmxLanguageServicePlugins(workspace: IWorkspaceState): LanguageServicePlugin[] {
89
return [
910
createNpmxCatalogService(workspace),
1011
createNpmxDiagnosticsService(workspace),
1112
createNpmxHoverService(workspace),
13+
createNpmxVersionCompletionService(workspace),
1214
]
1315
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import type { CompletionItemKind, CompletionList, LanguageServicePlugin, LanguageServicePluginInstance } from '@volar/language-service'
2+
import type { IWorkspaceState } from '../types'
3+
import { isDependencyFile } from 'npmx-language-core/utils'
4+
import { URI } from 'vscode-uri'
5+
import { getConfig } from '../config'
6+
import { getResolvedDependencyAtOffset } from '../utils/range'
7+
import { formatUpgradeVersion } from '../utils/version'
8+
9+
const PRERELEASE_PATTERN = /-.+/
10+
11+
export function create(workspaceState: IWorkspaceState): LanguageServicePlugin {
12+
return {
13+
name: 'npmx-version-completion',
14+
capabilities: {
15+
completionProvider: {
16+
triggerCharacters: [':', '^', '~', '.'],
17+
},
18+
},
19+
create(context): LanguageServicePluginInstance {
20+
return {
21+
async provideCompletionItems(document, position): Promise<CompletionList | undefined> {
22+
const completionVersion = await getConfig(context, 'npmx.completion.version')
23+
if (completionVersion === 'off')
24+
return
25+
26+
const uri = URI.parse(document.uri)
27+
if (uri.scheme !== 'file' || !isDependencyFile(uri.path))
28+
return
29+
30+
const dependencies = await workspaceState.getResolvedDependencies(document.uri)
31+
if (!dependencies)
32+
return
33+
34+
const offset = document.offsetAt(position)
35+
const dep = getResolvedDependencyAtOffset(dependencies, offset)
36+
if (!dep || dep.resolvedProtocol !== 'npm')
37+
return
38+
39+
const pkg = await dep.packageInfo()
40+
if (!pkg)
41+
return
42+
43+
const excludePrerelease = await getConfig(context, 'npmx.completion.excludePrerelease')
44+
const items: CompletionList['items'] = []
45+
46+
for (const version in pkg.versionsMeta) {
47+
const meta = pkg.versionsMeta[version]!
48+
49+
if (meta.deprecated != null)
50+
continue
51+
52+
if (excludePrerelease && PRERELEASE_PATTERN.test(version))
53+
continue
54+
55+
if (completionVersion === 'provenance-only' && !meta.provenance)
56+
continue
57+
58+
const text = formatUpgradeVersion(dep, version)
59+
60+
const tag = pkg.versionToTag.get(version)
61+
62+
items.push({
63+
label: text,
64+
kind: 12 satisfies typeof CompletionItemKind.Value,
65+
insertText: text,
66+
detail: tag,
67+
})
68+
}
69+
70+
return { isIncomplete: false, items }
71+
},
72+
}
73+
},
74+
}
75+
}

0 commit comments

Comments
 (0)