Skip to content

Commit 66732d2

Browse files
committed
Improve logic for when to show a decoration as a widget
FIX: Properly display diagnostics that just cover multiple newlines as widgets. See https://discuss.codemirror.net/t/request-make-mark-decorations-visible-on-empty-lines/9532
1 parent 73a454b commit 66732d2

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

src/lint.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class LintState {
103103

104104
let sorted = diagnostics.slice().sort((a, b) => a.from - b.from || a.to - b.to)
105105
let deco = new RangeSetBuilder<Decoration>(), active: Diagnostic[] = [], pos = 0
106+
let scan = state.doc.iter(), scanPos = 0
106107
for (let i = 0;;) {
107108
let next = i == sorted.length ? null : sorted[i]
108109
if (!next && !active.length) break
@@ -127,8 +128,23 @@ class LintState {
127128
break
128129
}
129130
}
131+
let widget = false
132+
if (active.some(d => d.from == from && d.to == to)) {
133+
widget = from == to
134+
if (!widget && to - from < 10) {
135+
let behind = from - (scanPos + scan.value.length)
136+
if (behind > 0) { scan.next(behind); scanPos = from }
137+
for (let check = from;;) {
138+
if (check >= to) { widget = true; break }
139+
if (!scan.lineBreak && scanPos + scan.value.length > check) break
140+
check = scanPos + scan.value.length
141+
scanPos += scan.value.length
142+
scan.next()
143+
}
144+
}
145+
}
130146
let sev = maxSeverity(active)
131-
if (active.some(d => d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from))) {
147+
if (widget) {
132148
deco.add(from, from, Decoration.widget({
133149
widget: new DiagnosticWidget(sev),
134150
diagnostics: active.slice()

test/test-lint.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ function diagnostics(s: EditorState) {
1818
return found
1919
}
2020

21-
function state(ds: readonly Diagnostic[]) {
22-
let s = EditorState.create({doc: "0123456789"})
21+
function state(ds: readonly Diagnostic[], doc = "0123456789") {
22+
let s = EditorState.create({doc})
2323
return s.update(setDiagnostics(s, ds)).state
2424
}
2525

@@ -58,4 +58,14 @@ describe("lint", () => {
5858
})
5959
istJSON(result, [[0, 3, "error"], [3, 4, "error"], [4, 5, "error"], [5, 8, "warning"]])
6060
})
61+
62+
it("creates widgets for empty and newline-only ranges", () => {
63+
let ds = [w(0, 0, "a"), e(1, 2, "b"), e(3, 5, "c"), w(6, 6, "d")]
64+
let deco = state(ds, "a\nb\n\ncd").facet(EditorView.decorations)[0] as DecorationSet
65+
let result: [number, number, boolean][] = []
66+
deco.between(0, 10, (from, to, val) => {
67+
result.push([from, to, !!val.widget])
68+
})
69+
istJSON(result, [[0, 0, true], [1, 1, true], [3, 3, true], [6, 6, true]])
70+
})
6171
})

0 commit comments

Comments
 (0)