Skip to content

Commit a7111ff

Browse files
committed
feat(diagnostics): add clickable links to diagnostic codes
1 parent defe552 commit a7111ff

5 files changed

Lines changed: 41 additions & 10 deletions

File tree

src/providers/diagnostics/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { checkDeprecation } from './rules/deprecation'
1212
import { checkReplacement } from './rules/replacement'
1313
import { checkVulnerability } from './rules/vulnerability'
1414

15-
export interface NodeDiagnosticInfo extends Pick<Diagnostic, 'message' | 'severity'> {
15+
export interface NodeDiagnosticInfo extends Pick<Diagnostic, 'message' | 'severity' | 'code'> {
1616
node: ValidNode
1717
}
1818
export type DiagnosticRule = (dep: DependencyInfo, pkg: ResolvedPackument) => Awaitable<NodeDiagnosticInfo | undefined>
@@ -59,6 +59,7 @@ export function registerDiagnosticCollection(mapping: Record<string, Extractor |
5959
source: displayName,
6060
message: diagnostic.message,
6161
severity: diagnostic.severity,
62+
code: diagnostic.code,
6263
range: extractor.getNodeRange(document, diagnostic.node),
6364
})
6465
}

src/providers/diagnostics/rules/deprecation.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { DiagnosticRule } from '..'
2+
import { npmxPackageUrl } from '#utils/links'
23
import { extractVersion } from '#utils/package'
3-
import { DiagnosticSeverity } from 'vscode'
4+
import { DiagnosticSeverity, Uri } from 'vscode'
45

56
export const checkDeprecation: DiagnosticRule = (dep, pkg) => {
67
const exactVersion = extractVersion(dep.version)
@@ -13,5 +14,9 @@ export const checkDeprecation: DiagnosticRule = (dep, pkg) => {
1314
node: dep.versionNode,
1415
message: `${dep.name} v${exactVersion} has been deprecated: ${versionInfo.deprecated}`,
1516
severity: DiagnosticSeverity.Error,
17+
code: {
18+
value: 'deprecation',
19+
target: Uri.parse(npmxPackageUrl(dep.name, exactVersion)),
20+
},
1621
}
1722
}
Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { ModuleReplacement } from '#utils/api/replacement'
22
import type { DiagnosticRule } from '..'
33
import { getReplacement } from '#utils/api/replacement'
4-
import { DiagnosticSeverity } from 'vscode'
4+
import { DiagnosticSeverity, Uri } from 'vscode'
55

66
function getMdnUrl(path: string): string {
77
return `https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/${path}`
@@ -12,16 +12,26 @@ function getReplacementsDocUrl(path: string): string {
1212
}
1313

1414
// https://github.com/npmx-dev/npmx.dev/blob/main/app/components/PackageReplacement.vue#L8-L30
15-
function generateMessage(replacement: ModuleReplacement) {
15+
function getReplacementInfo(replacement: ModuleReplacement) {
1616
switch (replacement.type) {
1717
case 'native':
18-
return `This can be replaced with ${replacement.replacement}, available since Node ${replacement.nodeVersion}. Read more here: ${getMdnUrl(replacement.mdnPath)}`
18+
return {
19+
message: `This can be replaced with ${replacement.replacement}, available since Node ${replacement.nodeVersion}.`,
20+
link: getMdnUrl(replacement.mdnPath),
21+
}
1922
case 'simple':
20-
return `The community has flagged this package as redundant, with the advice: ${replacement.replacement}.`
23+
return {
24+
message: `The community has flagged this package as redundant, with the advice:\n${replacement.replacement}.`,
25+
}
2126
case 'documented':
22-
return `The community has flagged this package as having more performant alternatives. Read more here: ${getReplacementsDocUrl(replacement.docPath)}`
27+
return {
28+
message: 'The community has flagged this package as having more performant alternatives.',
29+
link: getReplacementsDocUrl(replacement.docPath),
30+
}
2331
case 'none':
24-
return 'This package has been flagged as no longer needed, and its functionality is likely available natively in all engines.'
32+
return {
33+
message: 'This package has been flagged as no longer needed, and its functionality is likely available natively in all engines.',
34+
}
2535
}
2636
}
2737

@@ -30,9 +40,12 @@ export const checkReplacement: DiagnosticRule = async (dep) => {
3040
if (!replacement)
3141
return
3242

43+
const { message, link } = getReplacementInfo(replacement)
44+
3345
return {
3446
node: dep.nameNode,
35-
message: generateMessage(replacement),
47+
message,
3648
severity: DiagnosticSeverity.Warning,
49+
code: link ? { value: 'replacement', target: Uri.parse(link) } : 'replacement',
3750
}
3851
}

src/providers/diagnostics/rules/vulnerability.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { OsvSeverityLevel } from '#utils/api/vulnerability'
22
import type { DiagnosticRule } from '..'
33
import { getVulnerability, SEVERITY_LEVELS } from '#utils/api/vulnerability'
4+
import { npmxPackageUrl } from '#utils/links'
45
import { extractVersion } from '#utils/package'
5-
import { DiagnosticSeverity } from 'vscode'
6+
import { DiagnosticSeverity, Uri } from 'vscode'
67

78
const DIAGNOSTIC_MAPPING: Record<Exclude<OsvSeverityLevel, 'unknown'>, DiagnosticSeverity> = {
89
critical: DiagnosticSeverity.Error,
@@ -45,5 +46,9 @@ export const checkVulnerability: DiagnosticRule = async (dep, pkg) => {
4546
node: dep.versionNode,
4647
message: `This version has ${message.join(', ')} ${message.length === 1 ? 'vulnerability' : 'vulnerabilities'}`,
4748
severity: DiagnosticSeverity.Error,
49+
code: {
50+
value: 'vulnerability',
51+
target: Uri.parse(npmxPackageUrl(dep.name, exactVersion)),
52+
},
4853
}
4954
}

src/utils/links.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { NPMX_DEV } from '#constants'
2+
3+
export function npmxPackageUrl(name: string, version?: string): string {
4+
return version
5+
? `${NPMX_DEV}/package/${name}/v/${version}`
6+
: `${NPMX_DEV}/package/${name}`
7+
}

0 commit comments

Comments
 (0)