Multi-line `<%# %>` ERB comments are parsed as Ruby, so semantic highlighting colors the prose as method calls
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- ruby
- Domain
- developer-experience, tooling
Research direction
Start in lib/ruby_lsp/erb_document.rb at ERBScanner#scan_char, then reproduce the issue by requesting textDocument/semanticTokens/full for an ERB document containing a multi-line <%# ... %> comment. Done means the complete comment block produces no semantic tokens while semantic highlighting remains available elsewhere in the document.
Written by the indexing model from the issue text.
Description
Description
Ruby LSP Information
- ruby-lsp 0.26.10
- shopify.ruby-lsp VS Code extension 0.10.5
- VS Code 1.128.1
- ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +PRISM [arm64-darwin25]
Reproduction steps
Only the first line of a multi-line <%# … %> ERB comment is treated as a comment. Every following line is handed to Prism as Ruby, so the prose parses as a chain of method calls and semantic highlighting repaints each word with the method token type.
The TextMate grammar is correct here — erb.cson.json scopes the whole block as comment.block.erb — so this is only the semantic-token layer painting over it. On screen the first line stays comment-colored and the rest of the block turns code-colored.
- Open a
.erbfile in VS Code with the Ruby LSP extension active. - Add a single-line
<%# … %>comment and a multi-line one (snippet below). - Look at the multi-line comment: line 1 is comment-colored, every later line is colored as code.
- Optionally request
textDocument/semanticTokens/fullfor the document (languageId: "erb", defaultinitializationOptions) to see the tokens directly.
Code snippet or error message
<%# A single-line comment stays a comment. %>
<%# The first line of this comment is fine,
but every following line is parsed as Ruby
and each word here becomes a method token %>
<div>markup</div>
Expected: no semantic tokens inside either comment.
Actual: the single-line comment yields 0 tokens; the three-line block yields 13, all method:
ok L1-1 (1 line) tokens inside: 0
MISCOLORED L3-5 (3 lines) tokens inside: 13
L4 "but" -> method
L4 "every" -> method
L4 "following" -> method
L4 "line" -> method
L4 "is" -> method
L4 "parsed" -> method
L4 "as" -> method
L5 "each" -> method
L5 "word" -> method
L5 "here" -> method
L5 "becomes" -> method
L5 "a" -> method
L5 "token" -> method
Two details that make this easy to recognize:
- L3 (the first comment line) is clean — the problem starts on line 2 of the block.
- Words that happen to be Ruby keywords produce no token and so keep the comment color (
andon L5). In a real comment most words turn code-colored while the occasional keyword stays green, which looks arbitrary until you know the cause.
It scales with block length: a 6-line comment in one of our views produces 53 tokens.
Cause
ERBScanner#scan_char in lib/ruby_lsp/erb_document.rb (present on main as of filing):
when "<"
if next_char == "%"
@inside_ruby = true
@current_pos += 1
push_char(" ")
if next_char == "=" && @source[@current_pos + 2] == "="
@current_pos += 2
push_char(" ")
elsif next_char == "=" || next_char == "-"
@current_pos += 1
push_char(" ")
end
There is no branch for #, so <%# opens an ordinary Ruby region and the # is pushed into the Ruby buffer as a plain character. when "\n" then appends the newline to @ruby without closing the region or tracking that a # comment is open.
The extracted Ruby for the snippet above is therefore:
# The first line of this comment is fine,
but every following line is parsed as Ruby
and each word here becomes a method token
The # comments out line 1 only; lines 2-3 are live code as far as Prism is concerned.
A fix would be for the scanner to recognize <%# and blank the region through to the matching %>, the way it already blanks the tag delimiters, rather than emitting it as Ruby.
Workaround
For anyone hitting this, disabling semantic tokens for ERB only, which keeps them for .rb files:
"[erb]": { "editor.semanticHighlighting.enabled": false }
- Dominant language
- Ruby
- Stars
- 2k
- Forks
- 282
- Avg merge
- 10h 12m
- Merged PRs (30d)
- 11
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Shopify/ruby-lsp
-
Linux file system with square brackets in the directory/filename are failing to be indexedPossibly taken @andriytyurnikov claimed this 201 days ago. Openbug help-wanted pinned
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Shopify/ruby-lsp#3503 · 8 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
Paths need to be escapedPossibly taken @Vraiment claimed this 2 days ago. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 25/100
Maintainers usually reply within 1 day
-
check-labels intermittently fails due to the organization IP allow listPossibly taken @soutaro claimed this 5 days ago. Open
Shopify/ruby-lsp#4219 · 1 assignee ·
Maintainers usually reply within 1 day
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 38/100
Maintainers usually reply within 1 day
-
bug pinned
Difficulty 4/5 3-5 days Newbie friendliness 45/100
Shopify/ruby-lsp#4208 · 3 comments ·
Maintainers usually reply within 1 day
All issues in Shopify/ruby-lsp
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
rubys/roundhouse#571 ·
Maintainers usually reply within 1 day
-
area/web interface
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
mastodon/mastodon#40924 · 1 comment ·
Maintainers usually reply within 1 day
-
area: cli enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
mail processing verified
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 7 days
-
L: github:actions L: php:composer
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
dependabot/dependabot-core#16493 ·
Maintainers usually reply within 1 day