@markuplint/language-server 0.0.0-stage → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -2
- package/bin/markuplint-language-server.mjs +3 -0
- package/lib/const.d.ts +41 -0
- package/lib/const.js +44 -0
- package/lib/i18n.d.ts +19 -0
- package/lib/i18n.js +63 -0
- package/lib/index.d.ts +41 -0
- package/lib/index.js +40 -0
- package/lib/lsp.d.ts +8 -0
- package/lib/lsp.js +8 -0
- package/lib/protocol.d.ts +10 -0
- package/lib/protocol.js +9 -0
- package/lib/server/client-channel.d.ts +38 -0
- package/lib/server/client-channel.js +89 -0
- package/lib/server/code-actions.d.ts +36 -0
- package/lib/server/code-actions.js +101 -0
- package/lib/server/convert-diagnostics.d.ts +28 -0
- package/lib/server/convert-diagnostics.js +82 -0
- package/lib/server/debug.d.ts +3 -0
- package/lib/server/debug.js +7 -0
- package/lib/server/document-events.d.ts +78 -0
- package/lib/server/document-events.js +299 -0
- package/lib/server/get-accessibility-by-location.d.ts +6 -0
- package/lib/server/get-accessibility-by-location.js +19 -0
- package/lib/server/get-module.d.ts +127 -0
- package/lib/server/get-module.js +257 -0
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.js +5 -0
- package/lib/server/initialize-params.d.ts +32 -0
- package/lib/server/initialize-params.js +28 -0
- package/lib/server/module-notices.d.ts +28 -0
- package/lib/server/module-notices.js +41 -0
- package/lib/server/parser-load-failure.d.ts +36 -0
- package/lib/server/parser-load-failure.js +85 -0
- package/lib/server/server.d.ts +20 -0
- package/lib/server/server.js +96 -0
- package/lib/server/suppression-support.d.ts +57 -0
- package/lib/server/suppression-support.js +233 -0
- package/lib/server/v2.d.ts +12 -0
- package/lib/server/v2.js +109 -0
- package/lib/server/v3.d.ts +19 -0
- package/lib/server/v3.js +208 -0
- package/lib/server/v4.d.ts +85 -0
- package/lib/server/v4.js +292 -0
- package/lib/server/v5.d.ts +89 -0
- package/lib/server/v5.js +339 -0
- package/lib/types.d.ts +88 -0
- package/lib/types.js +1 -0
- package/lib/utils/get-file-path.d.ts +15 -0
- package/lib/utils/get-file-path.js +45 -0
- package/lib/utils/resolve-working-directory.d.ts +44 -0
- package/lib/utils/resolve-working-directory.js +266 -0
- package/locales/en.json +7 -0
- package/locales/ja.json +21 -0
- package/package.json +58 -5
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { SendDiagnostics } from './document-events.js';
|
|
2
|
+
import type { Config, Log } from '../types.js';
|
|
3
|
+
import type { Violation } from '@markuplint/ml-config';
|
|
4
|
+
import type { ARIAVersion } from '@markuplint/ml-spec';
|
|
5
|
+
import type { FixSummary, MLEngine as _MLEngine } from 'markuplint';
|
|
6
|
+
import type { CodeActionParams, Position, TextDocumentIdentifier, CodeAction } from 'vscode-languageserver';
|
|
7
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
8
|
+
/**
|
|
9
|
+
* Snapshot of the latest lint result for a document, used to produce Code Actions.
|
|
10
|
+
*/
|
|
11
|
+
export type FixState = {
|
|
12
|
+
readonly sourceCode: string;
|
|
13
|
+
readonly violations: readonly Violation[];
|
|
14
|
+
readonly fixedCode: string;
|
|
15
|
+
readonly fixSummary: FixSummary | null;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Returns the latest fix state for a document.
|
|
19
|
+
*
|
|
20
|
+
* @param uri - The document URI
|
|
21
|
+
* @returns The fix state, or `undefined` if the document has not been linted yet
|
|
22
|
+
*/
|
|
23
|
+
export declare function getFixState(uri: string): FixState | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Handles the `textDocument/didOpen` event by creating an MLEngine for the document.
|
|
26
|
+
*
|
|
27
|
+
* Sets up linting, diagnostics, and fix-state tracking for the opened document.
|
|
28
|
+
*
|
|
29
|
+
* @param document - The opened text document
|
|
30
|
+
* @param MLEngine - The MLEngine constructor
|
|
31
|
+
* @param config - The language configuration
|
|
32
|
+
* @param locale - The locale for diagnostic messages
|
|
33
|
+
* @param log - Logger for general messages
|
|
34
|
+
* @param diagnosticsLog - Logger for diagnostic-specific messages
|
|
35
|
+
* @param sendDiagnostics - Callback to publish diagnostics to the client
|
|
36
|
+
* @param notFoundParserError - Callback invoked when a parser is not found
|
|
37
|
+
* @param workspace - The working directory the document belongs to; the base for config discovery
|
|
38
|
+
*/
|
|
39
|
+
export declare function onDidOpen(document: TextDocument, MLEngine: typeof _MLEngine, config: Config, locale: string, log: Log, diagnosticsLog: Log, sendDiagnostics: SendDiagnostics, notFoundParserError: (e: unknown) => void, workspace: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Handles the `textDocument/didChangeContent` event by re-running the lint engine.
|
|
42
|
+
*
|
|
43
|
+
* Debounces execution so that rapid successive changes do not trigger
|
|
44
|
+
* multiple lint passes.
|
|
45
|
+
*
|
|
46
|
+
* @param document - The changed text document
|
|
47
|
+
* @param log - Logger for messages
|
|
48
|
+
* @param notFoundParserError - Callback invoked when a parser is not found
|
|
49
|
+
*/
|
|
50
|
+
export declare function onDidChangeContent(document: TextDocument, log: Log, notFoundParserError: (e: unknown) => void): void;
|
|
51
|
+
/**
|
|
52
|
+
* Handles the `textDocument/didClose` event by releasing the engine and the fix state of the document.
|
|
53
|
+
*
|
|
54
|
+
* @param uri - The URI of the closed document
|
|
55
|
+
*/
|
|
56
|
+
export declare function onDidClose(uri: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Retrieves the ARIA accessibility properties of the element at the given position.
|
|
59
|
+
*
|
|
60
|
+
* Used by the hover provider to display accessibility information such as
|
|
61
|
+
* role, exposed state, and ARIA property labels.
|
|
62
|
+
*
|
|
63
|
+
* @param textDocument - The text document identifier
|
|
64
|
+
* @param position - The cursor position within the document
|
|
65
|
+
* @param ariaVersion - The ARIA specification version to use
|
|
66
|
+
* @returns The node's accessibility properties, or null if unavailable
|
|
67
|
+
*/
|
|
68
|
+
export declare function getNodeWithAccessibilityProps(textDocument: TextDocumentIdentifier, position: Position, ariaVersion: ARIAVersion): Promise<{
|
|
69
|
+
nodeName: string;
|
|
70
|
+
exposed: boolean;
|
|
71
|
+
labels: Record<string, string>;
|
|
72
|
+
} | {
|
|
73
|
+
nodeName: string;
|
|
74
|
+
unknown: true;
|
|
75
|
+
} | null>;
|
|
76
|
+
/**
|
|
77
|
+
* Handles `textDocument/codeAction` requests for markuplint v4+.
|
|
78
|
+
*
|
|
79
|
+
* Returns per-violation QuickFix actions and a SourceFixAll action
|
|
80
|
+
* (`source.fixAll.markuplint`) when fixable violations exist.
|
|
81
|
+
*
|
|
82
|
+
* @param params - The LSP Code Action request parameters
|
|
83
|
+
* @returns An array of Code Actions (QuickFix and/or SourceFixAll)
|
|
84
|
+
*/
|
|
85
|
+
export declare function onCodeAction(params: CodeActionParams): CodeAction[];
|
package/lib/server/v4.js
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { t } from '../i18n.js';
|
|
3
|
+
import { getFilePath } from '../utils/get-file-path.js';
|
|
4
|
+
import { createQuickFixActions, createFixAllAction } from './code-actions.js';
|
|
5
|
+
import { convertDiagnostics } from './convert-diagnostics.js';
|
|
6
|
+
import { getAccessibilityByLocation } from './get-accessibility-by-location.js';
|
|
7
|
+
const engines = new Map();
|
|
8
|
+
const fixStates = new Map();
|
|
9
|
+
let moduleLog;
|
|
10
|
+
/**
|
|
11
|
+
* Returns the latest fix state for a document.
|
|
12
|
+
*
|
|
13
|
+
* @param uri - The document URI
|
|
14
|
+
* @returns The fix state, or `undefined` if the document has not been linted yet
|
|
15
|
+
*/
|
|
16
|
+
export function getFixState(uri) {
|
|
17
|
+
return fixStates.get(uri);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Handles the `textDocument/didOpen` event by creating an MLEngine for the document.
|
|
21
|
+
*
|
|
22
|
+
* Sets up linting, diagnostics, and fix-state tracking for the opened document.
|
|
23
|
+
*
|
|
24
|
+
* @param document - The opened text document
|
|
25
|
+
* @param MLEngine - The MLEngine constructor
|
|
26
|
+
* @param config - The language configuration
|
|
27
|
+
* @param locale - The locale for diagnostic messages
|
|
28
|
+
* @param log - Logger for general messages
|
|
29
|
+
* @param diagnosticsLog - Logger for diagnostic-specific messages
|
|
30
|
+
* @param sendDiagnostics - Callback to publish diagnostics to the client
|
|
31
|
+
* @param notFoundParserError - Callback invoked when a parser is not found
|
|
32
|
+
* @param workspace - The working directory the document belongs to; the base for config discovery
|
|
33
|
+
*/
|
|
34
|
+
export async function onDidOpen(
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
36
|
+
document,
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
38
|
+
MLEngine,
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
40
|
+
config, locale, log, diagnosticsLog, sendDiagnostics, notFoundParserError, workspace) {
|
|
41
|
+
moduleLog = log;
|
|
42
|
+
const key = document.uri;
|
|
43
|
+
log(`Opened: ${key}`, 'debug');
|
|
44
|
+
const currentEngine = engines.get(key);
|
|
45
|
+
if (currentEngine) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const filePath = getFilePath(document.uri, document.languageId);
|
|
49
|
+
log(`${filePath.dirname}/${filePath.basename}`, 'debug');
|
|
50
|
+
const absoluteFilePath = `${filePath.dirname}/${filePath.basename}`;
|
|
51
|
+
const sourceCode = document.getText();
|
|
52
|
+
// `name` must be the workspace-relative path (not just the basename), or
|
|
53
|
+
// MLFile.path collapses subdirectory files to workspace-root + basename —
|
|
54
|
+
// which breaks pretender import resolution, nested config discovery, and
|
|
55
|
+
// excludeFiles/overrides glob matching for anything outside the workspace root.
|
|
56
|
+
const relativeFilePath = path.relative(workspace, absoluteFilePath);
|
|
57
|
+
const file = await MLEngine.toMLFile({ sourceCode, name: relativeFilePath, workspace });
|
|
58
|
+
if (!file) {
|
|
59
|
+
log(`File not found: ${filePath.basename}`, 'warn');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const engine = new MLEngine(file, {
|
|
63
|
+
locale,
|
|
64
|
+
debug: config.debug,
|
|
65
|
+
defaultConfig: config.defaultConfig,
|
|
66
|
+
watch: true,
|
|
67
|
+
fix: true,
|
|
68
|
+
});
|
|
69
|
+
log(`Engine created: ${key}`);
|
|
70
|
+
let configSet = null;
|
|
71
|
+
engines.set(key, engine);
|
|
72
|
+
engine.on('config', (_, _configSet) => {
|
|
73
|
+
configSet = _configSet;
|
|
74
|
+
});
|
|
75
|
+
engine.on('log', (phase, message) => {
|
|
76
|
+
log(`[${phase}]: ${message}`, 'trace');
|
|
77
|
+
});
|
|
78
|
+
engine.on('lint-error', (_filePath, _sourceCode, error) => {
|
|
79
|
+
diagnosticsLog(error.message, 'error');
|
|
80
|
+
});
|
|
81
|
+
engine.on('config-errors', (_filePath, errors) => {
|
|
82
|
+
for (const error of errors) {
|
|
83
|
+
diagnosticsLog('ConfigError: ' + error.message, 'error');
|
|
84
|
+
log('ConfigError: ' + error.message, 'warn');
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
engine.on('lint', (filePath, sourceCode, violations, fixedCode, debug, fixSummary) => {
|
|
88
|
+
clearTimeout(debounceTimer);
|
|
89
|
+
diagnosticsLog('', 'clear');
|
|
90
|
+
// Execute after 300ms from the last change.
|
|
91
|
+
debounceTimer = setTimeout(lint, 300);
|
|
92
|
+
function lint() {
|
|
93
|
+
// `onDidClose` cannot clear this timer: it is shared by every document.
|
|
94
|
+
if (engines.get(key) !== engine) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
diagnosticsLog(`Lint: ${document.uri}`);
|
|
98
|
+
const errors = violations.filter(v => v.severity === 'error');
|
|
99
|
+
const warns = violations.filter(v => v.severity === 'warning');
|
|
100
|
+
log(`Errors: ${errors.length}`, 'debug');
|
|
101
|
+
log(`Warnings: ${warns.length}`, 'debug');
|
|
102
|
+
if (debug) {
|
|
103
|
+
diagnosticsLog(' Tracing AST Mapping:\n' + debug.map(line => ` ${line}`).join('\n'), 'trace');
|
|
104
|
+
}
|
|
105
|
+
if (configSet) {
|
|
106
|
+
if (configSet.files.size > 0) {
|
|
107
|
+
diagnosticsLog(' Used configs:');
|
|
108
|
+
for (const files of configSet.files.values()) {
|
|
109
|
+
diagnosticsLog(` ${files}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
diagnosticsLog(' No use configs');
|
|
114
|
+
}
|
|
115
|
+
if (configSet.plugins.length > 0) {
|
|
116
|
+
diagnosticsLog(' Used plugins:');
|
|
117
|
+
for (const plugin of configSet.plugins.values()) {
|
|
118
|
+
diagnosticsLog(` ${plugin.name}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
diagnosticsLog(' No use plugins');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const diagnostics = convertDiagnostics({
|
|
126
|
+
filePath,
|
|
127
|
+
sourceCode,
|
|
128
|
+
violations,
|
|
129
|
+
fixedCode,
|
|
130
|
+
status: 'processed',
|
|
131
|
+
});
|
|
132
|
+
fixStates.set(key, { sourceCode, violations, fixedCode, fixSummary });
|
|
133
|
+
if (diagnostics.length > 0) {
|
|
134
|
+
diagnosticsLog(` Violations(${diagnostics.length}):`);
|
|
135
|
+
for (const d of diagnostics) {
|
|
136
|
+
diagnosticsLog(` [${d.line}:${d.col}] ${d.code}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
diagnosticsLog(' ✔ No violations');
|
|
141
|
+
}
|
|
142
|
+
sendDiagnostics({
|
|
143
|
+
uri: document.uri,
|
|
144
|
+
diagnostics,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
log('Run `engine.exec()` in `onDidOpen`', 'debug');
|
|
149
|
+
engine.exec().catch((error) => {
|
|
150
|
+
log(String(error), 'error');
|
|
151
|
+
notFoundParserError(error);
|
|
152
|
+
throw error;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
let debounceTimer;
|
|
156
|
+
/**
|
|
157
|
+
* Handles the `textDocument/didChangeContent` event by re-running the lint engine.
|
|
158
|
+
*
|
|
159
|
+
* Debounces execution so that rapid successive changes do not trigger
|
|
160
|
+
* multiple lint passes.
|
|
161
|
+
*
|
|
162
|
+
* @param document - The changed text document
|
|
163
|
+
* @param log - Logger for messages
|
|
164
|
+
* @param notFoundParserError - Callback invoked when a parser is not found
|
|
165
|
+
*/
|
|
166
|
+
export function onDidChangeContent(
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
168
|
+
document, log, notFoundParserError) {
|
|
169
|
+
clearTimeout(debounceTimer);
|
|
170
|
+
const key = document.uri;
|
|
171
|
+
const engine = engines.get(key);
|
|
172
|
+
debounceTimer = setTimeout(async () => {
|
|
173
|
+
// The document may have been closed within the debounce delay.
|
|
174
|
+
if (!engine || engines.get(key) !== engine) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const code = document.getText();
|
|
178
|
+
try {
|
|
179
|
+
await engine.setCode(code);
|
|
180
|
+
log('Run `engine.exec()` in `onDidChangeContent`', 'debug');
|
|
181
|
+
engine.exec().catch((error) => notFoundParserError(error));
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (error instanceof Error) {
|
|
185
|
+
log(error.message, 'error');
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
log(`UnknownError: ${error}`, 'error');
|
|
189
|
+
}
|
|
190
|
+
}, 300);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Handles the `textDocument/didClose` event by releasing the engine and the fix state of the document.
|
|
194
|
+
*
|
|
195
|
+
* @param uri - The URI of the closed document
|
|
196
|
+
*/
|
|
197
|
+
export async function onDidClose(uri) {
|
|
198
|
+
fixStates.delete(uri);
|
|
199
|
+
const engine = engines.get(uri);
|
|
200
|
+
if (!engine) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
engines.delete(uri);
|
|
204
|
+
await engine.close();
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Retrieves the ARIA accessibility properties of the element at the given position.
|
|
208
|
+
*
|
|
209
|
+
* Used by the hover provider to display accessibility information such as
|
|
210
|
+
* role, exposed state, and ARIA property labels.
|
|
211
|
+
*
|
|
212
|
+
* @param textDocument - The text document identifier
|
|
213
|
+
* @param position - The cursor position within the document
|
|
214
|
+
* @param ariaVersion - The ARIA specification version to use
|
|
215
|
+
* @returns The node's accessibility properties, or null if unavailable
|
|
216
|
+
*/
|
|
217
|
+
export async function getNodeWithAccessibilityProps(
|
|
218
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
219
|
+
textDocument,
|
|
220
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
221
|
+
position, ariaVersion) {
|
|
222
|
+
const key = textDocument.uri;
|
|
223
|
+
const engine = engines.get(key);
|
|
224
|
+
if (!engine) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
const a11y = await getAccessibilityByLocation(engine, position.line + 1, position.character, ariaVersion);
|
|
228
|
+
if (!a11y) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
const { node, aria } = a11y;
|
|
232
|
+
if (!aria) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
if (aria.unknown) {
|
|
236
|
+
return {
|
|
237
|
+
nodeName: node,
|
|
238
|
+
unknown: true,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
if (!aria.exposedToTree) {
|
|
242
|
+
return {
|
|
243
|
+
nodeName: node,
|
|
244
|
+
exposed: false,
|
|
245
|
+
labels: {},
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
const labels = {};
|
|
249
|
+
const requiredLabel = `\u26A0\uFE0F**${t('Required')}**`;
|
|
250
|
+
labels.role = aria.role ? `\`${aria.role}\`` : t('No corresponding role');
|
|
251
|
+
labels.name = aria.nameProhibited
|
|
252
|
+
? `**${t('Prohibited')}**`
|
|
253
|
+
: // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
254
|
+
aria.name
|
|
255
|
+
? typeof aria.name === 'string'
|
|
256
|
+
? `\`"${aria.name}"\``
|
|
257
|
+
: `**${t('Unknown')}**`
|
|
258
|
+
: `${t('None')}${aria.nameRequired ? ` ${requiredLabel}` : ''}`;
|
|
259
|
+
labels.focusable = `\`${aria.focusable}\``;
|
|
260
|
+
for (const [propName, { value, required }] of Object.entries(aria.props ?? {})) {
|
|
261
|
+
labels[propName] =
|
|
262
|
+
value === undefined ? t('Undefined') + (required ? ` ${requiredLabel}` : '') : `\`${value}\``;
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
nodeName: node,
|
|
266
|
+
exposed: true,
|
|
267
|
+
labels,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Handles `textDocument/codeAction` requests for markuplint v4+.
|
|
272
|
+
*
|
|
273
|
+
* Returns per-violation QuickFix actions and a SourceFixAll action
|
|
274
|
+
* (`source.fixAll.markuplint`) when fixable violations exist.
|
|
275
|
+
*
|
|
276
|
+
* @param params - The LSP Code Action request parameters
|
|
277
|
+
* @returns An array of Code Actions (QuickFix and/or SourceFixAll)
|
|
278
|
+
*/
|
|
279
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
280
|
+
export function onCodeAction(params) {
|
|
281
|
+
const uri = params.textDocument.uri;
|
|
282
|
+
const fixState = getFixState(uri);
|
|
283
|
+
if (!fixState) {
|
|
284
|
+
moduleLog?.(`onCodeAction: no fixState for ${uri}`, 'debug');
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
const fixableCount = fixState.violations.filter(v => v.fix).length;
|
|
288
|
+
moduleLog?.(`onCodeAction: ${fixState.violations.length} violations (${fixableCount} fixable), ${params.context.diagnostics.length} diagnostics`, 'debug');
|
|
289
|
+
const quickFixes = createQuickFixActions(uri, params.context.diagnostics, fixState);
|
|
290
|
+
const fixAll = createFixAllAction(uri, params.context.diagnostics, fixState);
|
|
291
|
+
return fixAll ? [...quickFixes, fixAll] : quickFixes;
|
|
292
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { SendDiagnostics } from './document-events.js';
|
|
2
|
+
import type { Config, Log } from '../types.js';
|
|
3
|
+
import type { Violation } from '@markuplint/ml-config';
|
|
4
|
+
import type { ARIAVersion } from '@markuplint/ml-spec';
|
|
5
|
+
import type { FixSummary, MLEngine as _MLEngine } from 'markuplint';
|
|
6
|
+
import type { CodeActionParams, Position, TextDocumentIdentifier, CodeAction } from 'vscode-languageserver';
|
|
7
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
8
|
+
/**
|
|
9
|
+
* Snapshot of the latest lint result for a document, used to produce Code Actions.
|
|
10
|
+
*/
|
|
11
|
+
export type FixState = {
|
|
12
|
+
readonly sourceCode: string;
|
|
13
|
+
readonly violations: readonly Violation[];
|
|
14
|
+
readonly fixedCode: string;
|
|
15
|
+
readonly fixSummary: FixSummary | null;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Returns the latest fix state for a document.
|
|
19
|
+
*
|
|
20
|
+
* @param uri - The document URI
|
|
21
|
+
* @returns The fix state, or `undefined` if the document has not been linted yet
|
|
22
|
+
*/
|
|
23
|
+
export declare function getFixState(uri: string): FixState | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Handles the `textDocument/didOpen` event by creating an MLEngine for the document.
|
|
26
|
+
*
|
|
27
|
+
* Sets up linting, diagnostics, fix-state tracking, and bulk suppression
|
|
28
|
+
* severity downgrade for the opened document.
|
|
29
|
+
*
|
|
30
|
+
* @param document - The opened text document
|
|
31
|
+
* @param MLEngine - The MLEngine constructor
|
|
32
|
+
* @param config - The language configuration
|
|
33
|
+
* @param locale - The locale for diagnostic messages
|
|
34
|
+
* @param log - Logger for general messages
|
|
35
|
+
* @param diagnosticsLog - Logger for diagnostic-specific messages
|
|
36
|
+
* @param sendDiagnostics - Callback to publish diagnostics to the client
|
|
37
|
+
* @param notFoundParserError - Callback invoked when a parser is not found
|
|
38
|
+
* @param workspace - The working directory the document belongs to; the base for config discovery
|
|
39
|
+
*/
|
|
40
|
+
export declare function onDidOpen(document: TextDocument, MLEngine: typeof _MLEngine, config: Config, locale: string, log: Log, diagnosticsLog: Log, sendDiagnostics: SendDiagnostics, notFoundParserError: (e: unknown) => void, workspace: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Handles the `textDocument/didChangeContent` event by re-running the lint engine.
|
|
43
|
+
*
|
|
44
|
+
* Debounces execution so that rapid successive changes do not trigger
|
|
45
|
+
* multiple lint passes.
|
|
46
|
+
*
|
|
47
|
+
* @param document - The changed text document
|
|
48
|
+
* @param log - Logger for messages
|
|
49
|
+
* @param notFoundParserError - Callback invoked when a parser is not found
|
|
50
|
+
*/
|
|
51
|
+
export declare function onDidChangeContent(document: TextDocument, log: Log, notFoundParserError: (e: unknown) => void): void;
|
|
52
|
+
/**
|
|
53
|
+
* Handles the `textDocument/didClose` event by releasing everything kept for the document.
|
|
54
|
+
*
|
|
55
|
+
* Without it every document opened during a session would keep its engine, its DOM and
|
|
56
|
+
* its config watcher (`watch: true`) until the server exits.
|
|
57
|
+
*
|
|
58
|
+
* @param uri - The URI of the closed document
|
|
59
|
+
*/
|
|
60
|
+
export declare function onDidClose(uri: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Retrieves the ARIA accessibility properties of the element at the given position.
|
|
63
|
+
*
|
|
64
|
+
* Used by the hover provider to display accessibility information such as
|
|
65
|
+
* role, exposed state, and ARIA property labels.
|
|
66
|
+
*
|
|
67
|
+
* @param textDocument - The text document identifier
|
|
68
|
+
* @param position - The cursor position within the document
|
|
69
|
+
* @param ariaVersion - The ARIA specification version to use
|
|
70
|
+
* @returns The node's accessibility properties, or null if unavailable
|
|
71
|
+
*/
|
|
72
|
+
export declare function getNodeWithAccessibilityProps(textDocument: TextDocumentIdentifier, position: Position, ariaVersion: ARIAVersion): Promise<{
|
|
73
|
+
nodeName: string;
|
|
74
|
+
exposed: boolean;
|
|
75
|
+
labels: Record<string, string>;
|
|
76
|
+
} | {
|
|
77
|
+
nodeName: string;
|
|
78
|
+
unknown: true;
|
|
79
|
+
} | null>;
|
|
80
|
+
/**
|
|
81
|
+
* Handles `textDocument/codeAction` requests for markuplint v5.
|
|
82
|
+
*
|
|
83
|
+
* Returns per-violation QuickFix actions and a SourceFixAll action
|
|
84
|
+
* (`source.fixAll.markuplint`) when fixable violations exist.
|
|
85
|
+
*
|
|
86
|
+
* @param params - The LSP Code Action request parameters
|
|
87
|
+
* @returns An array of Code Actions (QuickFix and/or SourceFixAll)
|
|
88
|
+
*/
|
|
89
|
+
export declare function onCodeAction(params: CodeActionParams): CodeAction[];
|