Skip to content

Commit 2142753

Browse files
authored
feat: add links to diagnostic error codes via codeDescription (#2936)
closes #2933
1 parent 8f4fe71 commit 2142753

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

.changeset/good-steaks-judge.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte-language-server': patch
3+
---
4+
5+
feat: add links to diagnostic error codes via codeDescription

packages/language-server/src/plugins/svelte/features/getDiagnostics.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
CancellationToken,
3+
CodeDescription,
34
Diagnostic,
45
DiagnosticSeverity,
56
Position,
@@ -77,7 +78,7 @@ async function tryGetDiagnostics(
7778
.map((warning) => {
7879
const start = warning.start || { line: 1, column: 0 };
7980
const end = warning.end || start;
80-
return {
81+
const result: Diagnostic = {
8182
range: Range.create(start.line - 1, start.column, end.line - 1, end.column),
8283
message: warning.message,
8384
severity:
@@ -87,6 +88,14 @@ async function tryGetDiagnostics(
8788
source: 'svelte',
8889
code: warning.code
8990
};
91+
const codeDescription = getCodeDescription(
92+
warning.code,
93+
'https://svelte.dev/docs/svelte/compiler-warnings#'
94+
);
95+
if (codeDescription) {
96+
result.codeDescription = codeDescription;
97+
}
98+
return result;
9099
})
91100
.map((diag) => mapObjWithRangeToOriginal(transpiled, diag))
92101
.map((diag) => adjustMappings(diag, document))
@@ -154,9 +163,34 @@ function createParserErrorDiagnostic(error: any, document: Document) {
154163
}
155164
}
156165

166+
const codeDescription = getCodeDescription(
167+
error.code,
168+
'https://svelte.dev/docs/svelte/compiler-errors#'
169+
);
170+
if (codeDescription) {
171+
diagnostic.codeDescription = codeDescription;
172+
}
173+
157174
return [diagnostic];
158175
}
159176

177+
function getCodeDescription(code: unknown, url: string): CodeDescription | undefined {
178+
if (typeof code !== 'string') {
179+
return undefined;
180+
}
181+
182+
const firstChar = code.charCodeAt(0);
183+
if (isLowerLetter(firstChar) && (code.includes('-') || code.includes('_'))) {
184+
return {
185+
href: url + code.replace(/-/g, '_')
186+
};
187+
}
188+
}
189+
190+
function isLowerLetter(charCode: number) {
191+
return charCode >= 97 && charCode <= 122;
192+
}
193+
160194
/**
161195
* Try to infer a nice diagnostic error message from the transpilation error.
162196
*/

packages/language-server/test/plugins/svelte/SveltePlugin.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ describe('Svelte Plugin', () => {
4545
isSvelte5Plus ? 'a11y_missing_attribute' : 'a11y-missing-attribute',
4646
'svelte'
4747
);
48+
diagnostic.codeDescription = {
49+
href: 'https://svelte.dev/docs/svelte/compiler-warnings#a11y_missing_attribute'
50+
};
4851

4952
assert.deepStrictEqual(diagnostics, [diagnostic]);
5053
});
@@ -63,6 +66,13 @@ describe('Svelte Plugin', () => {
6366
'svelte'
6467
);
6568

69+
diagnostic.codeDescription = {
70+
href: isSvelte5Plus
71+
? 'https://svelte.dev/docs/svelte/compiler-errors#bind_invalid_name'
72+
: // doesn't actually exist but at least points to the page
73+
'https://svelte.dev/docs/svelte/compiler-errors#binding_undeclared'
74+
};
75+
6676
assert.deepStrictEqual(diagnostics, [diagnostic]);
6777
});
6878

packages/language-server/test/plugins/svelte/features/getDiagnostics.test.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,13 @@ describe('SveltePlugin#getDiagnostics', () => {
475475
(isSvelte5Plus ? '\nhttps://svelte.dev/e/export_let_unused' : ''),
476476
severity: 2,
477477
source: 'svelte',
478-
code: isSvelte5Plus ? 'export_let_unused' : 'unused-export-let'
478+
code: isSvelte5Plus ? 'export_let_unused' : 'unused-export-let',
479+
codeDescription: {
480+
href: isSvelte5Plus
481+
? 'https://svelte.dev/docs/svelte/compiler-warnings#export_let_unused'
482+
: // doesn't actually exist but at least points to the page
483+
'https://svelte.dev/docs/svelte/compiler-warnings#unused_export_let'
484+
}
479485
}
480486
]);
481487
});
@@ -496,7 +502,12 @@ describe('SveltePlugin#getDiagnostics', () => {
496502
source: 'svelte',
497503
code: isSvelte5Plus
498504
? 'reactive_declaration_invalid_placement'
499-
: 'module-script-reactive-declaration'
505+
: 'module-script-reactive-declaration',
506+
codeDescription: {
507+
href: isSvelte5Plus
508+
? 'https://svelte.dev/docs/svelte/compiler-warnings#reactive_declaration_invalid_placement'
509+
: 'https://svelte.dev/docs/svelte/compiler-warnings#module_script_reactive_declaration'
510+
}
500511
}
501512
]
502513
);
@@ -525,7 +536,13 @@ describe('SveltePlugin#getDiagnostics', () => {
525536
}
526537
},
527538
severity: 2,
528-
source: 'svelte'
539+
source: 'svelte',
540+
codeDescription: {
541+
href: isSvelte5Plus
542+
? 'https://svelte.dev/docs/svelte/compiler-warnings#export_let_unused'
543+
: // doesn't actually exist but at least points to the page
544+
'https://svelte.dev/docs/svelte/compiler-warnings#unused_export_let'
545+
}
529546
},
530547
{
531548
code: isSvelte5Plus ? 'export_let_unused' : 'unused-export-let',
@@ -543,7 +560,13 @@ describe('SveltePlugin#getDiagnostics', () => {
543560
}
544561
},
545562
severity: 2,
546-
source: 'svelte'
563+
source: 'svelte',
564+
codeDescription: {
565+
href: isSvelte5Plus
566+
? 'https://svelte.dev/docs/svelte/compiler-warnings#export_let_unused'
567+
: // doesn't actually exist but at least points to the page
568+
'https://svelte.dev/docs/svelte/compiler-warnings#unused_export_let'
569+
}
547570
}
548571
]
549572
);

0 commit comments

Comments
 (0)