Skip to content

Commit b06bed5

Browse files
Be more defensive mapping diagnostics. (#1064)
The document may have changed in the meantime so notice when lines don't make sense. I've also added a specific check for the scenario where diagnostics have to < from. Closes #1062
1 parent ce0f095 commit b06bed5

File tree

3 files changed

+108
-3
lines changed

3 files changed

+108
-3
lines changed

src/editor/codemirror/language-server/diagnostics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const diagnosticsMapping = (
2424
let from = positionToOffset(document, range.start);
2525
let to = positionToOffset(document, range.end);
2626
// Skip if we can't map to the current document.
27-
if (from !== undefined && to !== undefined) {
27+
if (from !== undefined && to !== undefined && to >= from) {
2828
return {
2929
from,
3030
to,
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { Text } from "@codemirror/state";
2+
import { positionToOffset } from "./positions";
3+
4+
describe("positionToOffset", () => {
5+
it("empty doc", () => {
6+
const doc = Text.of([""]);
7+
expect(
8+
positionToOffset(doc, {
9+
line: 0,
10+
character: 0,
11+
})
12+
).toEqual(0);
13+
14+
expect(
15+
positionToOffset(doc, {
16+
line: 1,
17+
character: 0,
18+
})
19+
).toBeUndefined();
20+
21+
expect(
22+
positionToOffset(doc, {
23+
line: 0,
24+
character: 1,
25+
})
26+
).toBeUndefined();
27+
});
28+
29+
it("1 char doc", () => {
30+
const doc = Text.of(["x"]);
31+
expect(
32+
positionToOffset(doc, {
33+
line: 0,
34+
character: 0,
35+
})
36+
).toEqual(0);
37+
38+
expect(
39+
positionToOffset(doc, {
40+
line: 0,
41+
character: 1,
42+
})
43+
).toEqual(1);
44+
45+
expect(
46+
positionToOffset(doc, {
47+
line: 0,
48+
character: 2,
49+
})
50+
).toBeUndefined();
51+
});
52+
53+
it("2 line doc", () => {
54+
const doc = Text.of(["x", "y"]);
55+
expect(
56+
positionToOffset(doc, {
57+
line: 0,
58+
character: 0,
59+
})
60+
).toEqual(0);
61+
62+
expect(
63+
positionToOffset(doc, {
64+
line: 1,
65+
character: 0,
66+
})
67+
).toEqual(2);
68+
69+
expect(
70+
positionToOffset(doc, {
71+
line: 1,
72+
character: 1,
73+
})
74+
).toEqual(3);
75+
76+
expect(
77+
positionToOffset(doc, {
78+
line: 1,
79+
character: 2,
80+
})
81+
).toBeUndefined();
82+
});
83+
84+
it("maps to incorrect line", () => {
85+
const doc = Text.of(["hello", "there"]);
86+
// Initial checks to confirm boundary
87+
expect(
88+
positionToOffset(doc, {
89+
line: 0,
90+
character: 5,
91+
})
92+
).toEqual(5);
93+
expect(doc.sliceString(0, 5)).toEqual("hello");
94+
// Actual test that goes one too far
95+
expect(
96+
positionToOffset(doc, {
97+
line: 0,
98+
character: 6,
99+
})
100+
).toBeUndefined();
101+
});
102+
});

src/editor/codemirror/language-server/positions.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ export const positionToOffset = (
1515
if (position.line >= document.lines) {
1616
return undefined;
1717
}
18-
const offset = document.line(position.line + 1).from + position.character;
19-
if (offset > document.length) return;
18+
const line = document.line(position.line + 1);
19+
const offset = line.from + position.character;
20+
if (offset > line.to) {
21+
return undefined;
22+
}
2023
return offset;
2124
};
2225

0 commit comments

Comments
 (0)