Skip to content

Commit

Permalink
feat(diagnostic): code action for suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
bhsd-harry committed Dec 6, 2024
1 parent 6f7680a commit 29fd91c
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 28 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## v1.0.5

*2024-12-06*

**Added**

- More suggested code actions for syntax errors

## v1.0.4

*2024-12-03*
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vscode-extension-wikiparser",
"version": "1.0.4",
"version": "1.0.5",
"description": "Language server extension for MediaWiki Wikitext that supports linting, autocomplete, and more.",
"displayName": "WikiParser Language Server",
"categories": [
Expand Down Expand Up @@ -55,7 +55,7 @@
"color-rgba": "^3.0.0",
"vscode-languageserver": "^9.0.1",
"vscode-languageserver-textdocument": "^1.0.12",
"wikilint": "^2.13.8"
"wikilint": "^2.13.9"
},
"devDependencies": {
"@stylistic/eslint-plugin": "^2.11.0",
Expand Down
48 changes: 36 additions & 12 deletions server/src/diagnostic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,54 @@ import type {
TextEdit,
} from 'vscode-languageserver/node';

declare interface QuickFixData extends TextEdit {
title: string;
fix: boolean;
}

export const diagnose = async ({textDocument: {uri}}: DocumentDiagnosticParams): Promise<Diagnostic[]> => {
const root = await parse(uri);
return root.lint().filter(({severity, rule}) => severity === 'error' && rule !== 'no-arg')
.map(({startLine, startCol, endLine, endCol, severity, message, fix}) => ({
.map(({startLine, startCol, endLine, endCol, severity, message, fix, suggestions}) => ({
range: {
start: {line: startLine, character: startCol},
end: {line: endLine, character: endCol},
},
severity: severity === 'error' ? 1 : 2,
source: 'WikiLint',
message,
data: fix && {range: createRange(root, ...fix.range), newText: fix.text} as TextEdit,
data: [
...fix
? [
{
range: createRange(root, ...fix.range),
newText: fix.text,
title: `Fix: ${fix.desc}`,
fix: true,
},
]
: [],
...suggestions
? suggestions.map(({range, text, desc}) => ({
range: createRange(root, ...range),
newText: text,
title: `Suggestion: ${desc}`,
fix: false,
}))
: [],
] satisfies QuickFixData[],
}));
};

export const quickFix = ({context: {diagnostics}, textDocument: {uri}}: CodeActionParams): CodeAction[] =>
diagnostics.filter(({data}) => data).map(diagnostic => ({
title: 'Fix',
kind: CodeActionKind.QuickFix,
diagnostics: [diagnostic],
isPreferred: true,
edit: {
changes: {
[uri]: [diagnostic.data as TextEdit],
diagnostics.filter(({data}) => data).flatMap(
diagnostic => (diagnostic.data as QuickFixData[]).map(data => ({
title: data.title,
kind: CodeActionKind.QuickFix,
diagnostics: [diagnostic],
isPreferred: data.fix,
edit: {
changes: {[uri]: [data]},
},
},
}));
})),
);
83 changes: 83 additions & 0 deletions server/src/test/diagnostic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import * as assert from 'assert';
import {CodeActionKind} from 'vscode-languageserver/node';
import {getParams} from './util';
import {diagnose, quickFix} from '../diagnostic';
import type {Diagnostic, CodeAction, CodeActionParams} from 'vscode-languageserver/node';

const wikitext = `
http://a]
</p>
`,
params = getParams(__filename, wikitext),
diagnostics: Diagnostic[] = [
{
range: {
start: {line: 1, character: 7},
end: {line: 1, character: 8},
},
severity: 1,
source: 'WikiLint',
message: 'lonely "]"',
data: [
{
range: {
start: {line: 1, character: 0},
end: {line: 1, character: 1},
},
newText: '[',
title: 'Fix: left bracket',
fix: true,
},
],
},
{
range: {
start: {line: 2, character: 0},
end: {line: 2, character: 4},
},
severity: 2,
source: 'WikiLint',
message: 'unmatched closing tag',
data: [
{
range: {
start: {line: 2, character: 0},
end: {line: 2, character: 4},
},
newText: '',
title: 'Suggestion: remove',
fix: false,
},
],
},
],
actions: CodeAction[] = [
{
title: 'Fix: left bracket',
kind: CodeActionKind.QuickFix,
diagnostics: [diagnostics[0]!],
isPreferred: true,
edit: {
changes: {[params.textDocument.uri]: [diagnostics[0]!.data]},
},
},
{
title: 'Suggestion: remove',
kind: CodeActionKind.QuickFix,
diagnostics: [diagnostics[1]!],
isPreferred: false,
edit: {
changes: {[params.textDocument.uri]: [diagnostics[1]!.data]},
},
},
];

describe('diagnosticProvider', () => {
it('Diagnostic', async () => {
assert.deepStrictEqual(await diagnose(params), diagnostics);
});
it('QuickFix', done => {
assert.deepStrictEqual(quickFix({...params, context: {diagnostics}} as unknown as CodeActionParams), actions);
done();
});
});
5 changes: 3 additions & 2 deletions server/src/test/folding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,11 @@ y }} z
];

describe('foldingRangeProvider', () => {
const params = getParams(__filename, wikitext);
it('FoldingRange', async () => {
assert.deepStrictEqual(await provideFolding(getParams(__filename, wikitext)), foldingRanges);
assert.deepStrictEqual(await provideFolding(params), foldingRanges);
});
it('DocumentSymbol', async () => {
assert.deepStrictEqual(await provideSymbol(getParams(__filename, wikitext)), symbols);
assert.deepStrictEqual(await provideSymbol(params), symbols);
});
});
16 changes: 4 additions & 12 deletions server/src/test/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,22 +89,14 @@ News:e
];

describe('documentLinkProvider', () => {
const {textDocument} = getParams(__filename, wikitext);
it('https://mediawiki.org/wiki/$1', async () => {
assert.deepStrictEqual(
await provideLinks(getParams(__filename, wikitext).textDocument, 'https://mediawiki.org/wiki/$1'),
results,
);
assert.deepStrictEqual(await provideLinks(textDocument, 'https://mediawiki.org/wiki/$1'), results);
});
it('https://mediawiki.org/wiki/', async () => {
assert.deepStrictEqual(
await provideLinks(getParams(__filename, wikitext).textDocument, 'https://mediawiki.org/wiki/'),
results,
);
assert.deepStrictEqual(await provideLinks(textDocument, 'https://mediawiki.org/wiki/'), results);
});
it('https://mediawiki.org/wiki', async () => {
assert.deepStrictEqual(
await provideLinks(getParams(__filename, wikitext).textDocument, 'https://mediawiki.org/wiki'),
results,
);
assert.deepStrictEqual(await provideLinks(textDocument, 'https://mediawiki.org/wiki'), results);
});
});

0 comments on commit 29fd91c

Please sign in to comment.