-
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathversion.ts
More file actions
91 lines (76 loc) · 2.86 KB
/
version.ts
File metadata and controls
91 lines (76 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import type { DependencyInfo, Extractor } from '#types/extractor'
import type { CodeLensProvider, TextDocument } from 'vscode'
import { internalCommands } from '#state'
import { getPackageInfo } from '#utils/api/package'
import { resolveExactVersion } from '#utils/package'
import { resolveUpgradeTargetVersion } from '#utils/upgrade'
import { formatUpgradeVersion, isSupportedProtocol, parseVersion } from '#utils/version'
import { debounce } from 'perfect-debounce'
import diff from 'semver/functions/diff'
import { CodeLens, EventEmitter } from 'vscode'
const dataMap = new WeakMap<CodeLens, DependencyInfo>()
export class VersionCodeLensProvider<T extends Extractor> implements CodeLensProvider {
extractor: T
private readonly onDidChangeCodeLensesEmitter = new EventEmitter<void>()
readonly onDidChangeCodeLenses = this.onDidChangeCodeLensesEmitter.event
private readonly scheduleRefresh = debounce(() => {
this.onDidChangeCodeLensesEmitter.fire()
}, 100, { leading: false, trailing: true })
constructor(extractor: T) {
this.extractor = extractor
}
provideCodeLenses(document: TextDocument): CodeLens[] {
const root = this.extractor.parse(document)
if (!root)
return []
const deps = this.extractor.getDependenciesInfo(root)
const lenses: CodeLens[] = []
for (const dep of deps) {
const versionRange = this.extractor.getNodeRange(document, dep.versionNode)
const lens = new CodeLens(versionRange)
dataMap.set(lens, dep)
lenses.push(lens)
}
return lenses
}
resolveCodeLens(lens: CodeLens) {
const dep = dataMap.get(lens)
if (!dep)
return lens
const parsed = parseVersion(dep.version)
if (!parsed || !isSupportedProtocol(parsed.protocol)) {
lens.command = { title: '$(question) unknown', command: '' }
return lens
}
const pkg = getPackageInfo(dep.name)
if (pkg instanceof Promise) {
lens.command = { title: '$(sync~spin) checking...', command: '' }
pkg.finally(() => this.scheduleRefresh())
return lens
}
if (!pkg) {
lens.command = { title: '$(question) unknown', command: '' }
return lens
}
const exactVersion = resolveExactVersion(pkg, parsed.version)
if (!exactVersion) {
lens.command = { title: '$(question) unknown', command: '' }
return lens
}
const targetVersion = resolveUpgradeTargetVersion(pkg, exactVersion)
if (!targetVersion) {
lens.command = { title: '$(check) latest', command: '' }
return lens
}
const newVersion = formatUpgradeVersion(parsed, targetVersion)
const updateType = diff(exactVersion, targetVersion)
lens.command = {
title: updateType
? `$(arrow-up) ${newVersion} (${updateType})`
: `$(arrow-up) ${newVersion}`,
command: internalCommands.replaceText,
arguments: [lens.range, newVersion],
}
return lens
}
}