Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions src/server/diagnostics.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import assert from "node:assert/strict";
import { describe, test } from "node:test";
import { DiagnosticSeverity } from "vscode-languageserver/node";
import { TextDocument } from "vscode-languageserver-textdocument";
import { toDiagnostic, toDiagnosticSeverity } from "./diagnostics.ts";
import { textlintMessage } from "./test-fixtures.ts";

Expand All @@ -11,17 +12,31 @@ void describe("diagnostic core", () => {
assert.strictEqual(toDiagnosticSeverity(0), DiagnosticSeverity.Information);
assert.strictEqual(toDiagnosticSeverity(3), DiagnosticSeverity.Information);
});
});

void describe("diagnostic ranges", () => {
void test("uses textlint ranges for single-line and zero-width diagnostics", () => {
const textDocument = TextDocument.create("file:///test.txt", "plaintext", 1, "0123456789");
const word = toDiagnostic(textDocument, textlintMessage("word", [2, 5]))[1];
const insertion = toDiagnostic(textDocument, textlintMessage("insert", [7, 7]))[1];

assert.deepStrictEqual(word.range, {
start: { line: 0, character: 2 },
end: { line: 0, character: 5 },
});
assert.deepStrictEqual(insertion.range, {
start: { line: 0, character: 7 },
end: { line: 0, character: 7 },
});
});

void test("preserves the current message-based range behavior", () => {
const plain = toDiagnostic(textlintMessage("plain", [2, 5]))[1];
const arrow = toDiagnostic(textlintMessage("arrow", [2, 5], "arrow", "before -> after"))[1];
const quoted = toDiagnostic(textlintMessage("quoted", [2, 5], "quoted", 'replace "word"'))[1];
void test("converts multiline and surrogate-pair offsets with the document", () => {
const textDocument = TextDocument.create("file:///test.txt", "plaintext", 1, "😀abc\ndef");
const multiline = toDiagnostic(textDocument, textlintMessage("multiline", [2, 8]))[1];

assert.deepStrictEqual(plain.range, {
assert.deepStrictEqual(multiline.range, {
start: { line: 0, character: 2 },
end: { line: 0, character: 2 },
end: { line: 1, character: 2 },
});
assert.strictEqual(arrow.range.end.character, 8);
assert.strictEqual(quoted.range.end.character, 6);
});
});
26 changes: 7 additions & 19 deletions src/server/diagnostics.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DiagnosticSeverity, Position, Range } from "vscode-languageserver/node";
import { DiagnosticSeverity, Range } from "vscode-languageserver/node";
import type { Diagnostic } from "vscode-languageserver/node";
import type { TextDocument } from "vscode-languageserver-textdocument";
import type { TextlintMessage } from "@textlint/types";

export type DiagnosticEntry = readonly [TextlintMessage, Diagnostic];
Expand All @@ -18,30 +19,17 @@ export function toDiagnosticSeverity(severity: TextlintMessage["severity"]): Dia
}
}

export function toDiagnostic(message: TextlintMessage): DiagnosticEntry {
const startPosition = Position.create(
Math.max(0, message.loc.start.line - 1),
Math.max(0, message.loc.start.column - 1),
);
let offset = 0;
if (message.message.includes("->")) {
offset = message.message.indexOf(" ->");
}
const quoteIndex = message.message.indexOf(`"`);
if (quoteIndex >= 0) {
offset = Math.max(0, message.message.indexOf(`"`, quoteIndex + 1) - quoteIndex - 1);
}
const endPosition = Position.create(
Math.max(0, message.loc.start.line - 1),
Math.max(0, message.loc.start.column - 1) + offset,
);
export function toDiagnostic(document: TextDocument, message: TextlintMessage): DiagnosticEntry {
return [
message,
{
message: message.message,
severity: toDiagnosticSeverity(message.severity),
source: "textlint",
range: Range.create(startPosition, endPosition),
range: Range.create(
document.positionAt(message.range[0]),
document.positionAt(message.range[1]),
),
code: message.ruleId,
},
];
Expand Down
2 changes: 1 addition & 1 deletion src/server/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ async function lintDocument(
document.uri,
document.version,
slot,
result.messages.map((message) => toDiagnostic(message)),
result.messages.map((message) => toDiagnostic(document, message)),
);
}

Expand Down
5 changes: 4 additions & 1 deletion tests/e2e/diagnostics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ function assertLintDiagnostics(diagnostics: readonly Diagnostic[]): void {
line: diagnostic.range.end.line,
character: diagnostic.range.end.character,
},
expectedDiagnostics[index],
{
line: expectedDiagnostics[index].line,
character: expectedDiagnostics[index].character + 1,
},
);
}
}
Expand Down
Loading