renderWhitespace: the dot of a space is painted at its pre-widget column when an inline 'after' decoration sits immediately before it
- Dominant language
- TypeScript
- Stars
- 193k
- Forks
- 42.4k
- PR merge metrics
- PR metrics pending
Description
In the following example, the dot above the "a" should actually be drawn in the blank space two positions further along:
- VS Code Version: 1.134.0 (110a328ea54b42367b803ec53ee0bf52ef26b419, x64)
- OS Version: Windows 11 Pro 10.0.26200
Does this issue occur when all extensions are disabled?: N/A — reproducing it requires an extension, since it involves the decorations API.
### Steps to Reproduce
1. Set `"editor.renderWhitespace": "all"`.
2. From an extension, apply a decoration with a non-empty `renderOptions.after.contentText` to a one-character range, chosen so that a **real space character immediately follows** the decorated range:
```js
const type = vscode.window.createTextEditorDecorationType({});
// line 0 is: "| A1 |" — the widget renders between "1" (col 3) and " " (col 4)
editor.setDecorations(type, [{
range: new vscode.Range(0, 3, 0, 4),
renderOptions: { after: { contentText: ' ', backgroundColor: 'rgba(255,128,0,0.4)' } }
}]);
```
3. Look at the whitespace dot of the space that follows the widget.
### Actual
The dot is painted at the column the space would occupy **without** the widget — that is, on top of the widget's own content — while the space's real, shifted position shows no dot at all. The widget's background does not hide the misplaced dot either, since the two are painted in different layers.
### Expected
The dot follows the space to the column where the space is actually rendered: shifted right by the widget's width.
### Notes
- The mirror cases are all correct: `before` attachments never displace a dot, and a space sitting to the **left** of an `after` widget is painted at its right column. Only a space immediately to the **right** of an `after` attachment is affected, which suggests the whitespace layer derives its columns from the model without accounting for the width of inline decorations placed earlier in the same line.
- Reproduces consistently at any widget width. It was isolated with a small test harness that renders one widget per digit on a line, each widget's text encoding its own attachment configuration (`before`/`after`, over a one-char range, an empty range, or the preceding character), across three neighbourhoods: no spaces, a space to the right, spaces on both sides. Only the `after`-then-space combinations misplace a dot.
- Found while building [Markdown Ghost Tables](https://github.com/goohan/markdownghosttables), which injects virtual alignment padding into markdown tables so the file can stay compact. It is cosmetic, but the dots are exactly what tells the user which spaces are real and which are virtual, so in the affected cell that signal is lost.
Contributor guide
Assessment
This issue has not been assessed yet.