diff --git a/spec/tree-sitter-language-mode-spec.js b/spec/tree-sitter-language-mode-spec.js
index 73befc226..0b510d408 100644
--- a/spec/tree-sitter-language-mode-spec.js
+++ b/spec/tree-sitter-language-mode-spec.js
@@ -292,13 +292,18 @@ describe('TreeSitterLanguageMode', () => {
})
describe('injections', () => {
- it('highlights code inside of injection points', async () => {
- const jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, {
+ let jsGrammar, htmlGrammar
+
+ beforeEach(() => {
+ jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, {
+ id: 'javascript',
parser: 'tree-sitter-javascript',
scopes: {
'property_identifier': 'property',
'call_expression > identifier': 'function',
- 'template_string': 'string'
+ 'template_string': 'string',
+ 'template_substitution > "${"': 'interpolation',
+ 'template_substitution > "}"': 'interpolation'
},
injectionPoints: [{
type: 'call_expression',
@@ -311,9 +316,11 @@ describe('TreeSitterLanguageMode', () => {
}]
})
- const htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, {
+ htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, {
+ id: 'html',
parser: 'tree-sitter-html',
scopes: {
+ fragment: 'html',
tag_name: 'tag',
attribute_name: 'attr'
},
@@ -322,12 +329,14 @@ describe('TreeSitterLanguageMode', () => {
]
})
+ atom.grammars.addGrammar(jsGrammar)
atom.grammars.addGrammar(htmlGrammar)
+ })
+ it('highlights code inside of injection points', async () => {
const languageMode = new TreeSitterLanguageMode({buffer, grammar: jsGrammar, grammars: atom.grammars})
buffer.setLanguageMode(languageMode)
- buffer.setText('node.innerHTML = html `
`;')
-
+ buffer.setText('node.innerHTML = html `a ${b}
\n`;')
await languageMode.reparsePromise
expectTokensToEqual(editor, [
@@ -337,11 +346,18 @@ describe('TreeSitterLanguageMode', () => {
{text: ' = ', scopes: []},
{text: 'html', scopes: ['function']},
{text: ' ', scopes: []},
- {text: '`<', scopes: ['string']},
- {text: 'img', scopes: ['string', 'tag']},
- {text: ' ', scopes: ['string']},
- {text: 'src', scopes: ['string', 'attr']},
- {text: '="x">`', scopes: ['string']},
+ {text: '`', scopes: ['string']},
+ {text: 'a ', scopes: ['string', 'html']},
+ {text: '${', scopes: ['string', 'html', 'interpolation']},
+ {text: 'b', scopes: ['string', 'html']},
+ {text: '}', scopes: ['string', 'html', 'interpolation']},
+ {text: '<', scopes: ['string', 'html']},
+ {text: 'img', scopes: ['string', 'html', 'tag']},
+ {text: ' ', scopes: ['string', 'html']},
+ {text: 'src', scopes: ['string', 'html', 'attr']},
+ {text: '="d">', scopes: ['string', 'html']},
+ ], [
+ {text: '`', scopes: ['string']},
{text: ';', scopes: []},
],
])
diff --git a/src/tree-sitter-language-mode.js b/src/tree-sitter-language-mode.js
index 9862a8146..cf586539d 100644
--- a/src/tree-sitter-language-mode.js
+++ b/src/tree-sitter-language-mode.js
@@ -599,14 +599,7 @@ class HighlightIterator {
moveToSuccessor () {
this.leader.moveToSuccessor()
- const oldLeader = this.leader
this._findLeader()
- if (
- this.leader !== oldLeader &&
- pointIsLess(this.leader.getPosition(), this.leader.treeCursor.startPosition)
- ) {
- this.leader.moveToSuccessor()
- }
}
getPosition () {
@@ -622,13 +615,12 @@ class HighlightIterator {
}
_findLeader () {
- let minIndex = Infinity
+ let minPosition = Point.INFINITY
for (const it of this.iterators) {
- if (!Number.isFinite(it.getPosition().row)) continue
- const {startIndex} = it.treeCursor
- if (startIndex < minIndex) {
+ const position = it.getPosition()
+ if (pointIsLess(position, minPosition)) {
this.leader = it
- minIndex = startIndex
+ minPosition = position
}
}
}
@@ -673,14 +665,15 @@ class LayerHighlightIterator {
this.currentPosition = targetPosition
this.currentIndex = this.languageLayer.languageMode.buffer.characterIndexForPosition(targetPosition)
+ if (this.treeCursor.endIndex <= this.currentIndex) return containingTags
+
// Descend from the root of the tree to the smallest node that spans the given position.
// Keep track of any nodes along the way that are associated with syntax highlighting
// tags. These tags must be returned.
var childIndex = -1
- var nodeContainsTarget = true
for (;;) {
this.currentChildIndex = childIndex
- if (!nodeContainsTarget) break
+ if (this.treeCursor.startIndex > this.currentIndex) break
this.containingNodeTypes.push(this.treeCursor.nodeType)
this.containingNodeChildIndices.push(childIndex)
@@ -696,7 +689,6 @@ class LayerHighlightIterator {
const nextChildIndex = this.treeCursor.gotoFirstChildForIndex(this.currentIndex)
if (nextChildIndex == null) break
- if (this.treeCursor.startIndex > this.currentIndex) nodeContainsTarget = false
childIndex = nextChildIndex
}
@@ -757,7 +749,10 @@ class LayerHighlightIterator {
// If the iterator is at the end of a node, advance to the node's next sibling. If
// it has no next sibing, then the iterator has reached the end of the tree.
} else if (!this.treeCursor.gotoNextSibling()) {
- this.currentPosition = {row: Infinity, column: Infinity}
+ if (this.atEnd) {
+ this.currentPosition = {row: Infinity, column: Infinity}
+ }
+ this.atEnd = true
break
}
} while (this.closeTags.length === 0 && this.openTags.length === 0)