mirror of
https://github.com/atom/atom.git
synced 2026-01-25 06:48:28 -05:00
Make tree-sitter scope descriptors match HTML classes, not syntax tree
This commit is contained in:
@@ -1323,39 +1323,49 @@ describe('TreeSitterLanguageMode', () => {
|
||||
describe('.scopeDescriptorForPosition', () => {
|
||||
it('returns a scope descriptor representing the given position in the syntax tree', async () => {
|
||||
const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, {
|
||||
scopeName: 'javascript',
|
||||
parser: 'tree-sitter-javascript'
|
||||
scopeName: 'source.js',
|
||||
parser: 'tree-sitter-javascript',
|
||||
scopes: {
|
||||
program: 'source.js',
|
||||
property_identifier: 'property.name'
|
||||
}
|
||||
})
|
||||
|
||||
buffer.setText('foo({bar: baz});')
|
||||
|
||||
buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar}))
|
||||
await nextHighlightingUpdate(buffer.getLanguageMode())
|
||||
expect(editor.scopeDescriptorForBufferPosition([0, 6]).getScopesArray()).toEqual([
|
||||
'javascript',
|
||||
'program',
|
||||
'expression_statement',
|
||||
'call_expression',
|
||||
'arguments',
|
||||
'object',
|
||||
'pair',
|
||||
'property_identifier'
|
||||
expect(editor.scopeDescriptorForBufferPosition([0, 'foo({b'.length]).getScopesArray()).toEqual([
|
||||
'source.js',
|
||||
'property.name'
|
||||
])
|
||||
expect(editor.scopeDescriptorForBufferPosition([0, 'foo({'.length]).getScopesArray()).toEqual([
|
||||
'source.js',
|
||||
'property.name'
|
||||
])
|
||||
})
|
||||
|
||||
it('includes nodes in injected syntax trees', async () => {
|
||||
const jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, {
|
||||
scopeName: 'javascript',
|
||||
scopeName: 'source.js',
|
||||
parser: 'tree-sitter-javascript',
|
||||
scopes: {},
|
||||
scopes: {
|
||||
program: 'source.js',
|
||||
template_string: 'string.quoted',
|
||||
interpolation: 'meta.embedded',
|
||||
property_identifier: 'property.name'
|
||||
},
|
||||
injectionRegExp: 'javascript',
|
||||
injectionPoints: [HTML_TEMPLATE_LITERAL_INJECTION_POINT]
|
||||
})
|
||||
|
||||
const htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, {
|
||||
scopeName: 'html',
|
||||
scopeName: 'text.html',
|
||||
parser: 'tree-sitter-html',
|
||||
scopes: {},
|
||||
scopes: {
|
||||
fragment: 'text.html',
|
||||
raw_element: 'script.tag'
|
||||
},
|
||||
injectionRegExp: 'html',
|
||||
injectionPoints: [SCRIPT_TAG_INJECTION_POINT]
|
||||
})
|
||||
@@ -1381,20 +1391,12 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const position = buffer.findSync('name').start
|
||||
expect(languageMode.scopeDescriptorForPosition(position).getScopesArray()).toEqual([
|
||||
'html',
|
||||
'fragment',
|
||||
'element',
|
||||
'raw_element',
|
||||
'raw_text',
|
||||
'program',
|
||||
'expression_statement',
|
||||
'call_expression',
|
||||
'template_string',
|
||||
'fragment',
|
||||
'element',
|
||||
'template_substitution',
|
||||
'member_expression',
|
||||
'property_identifier'
|
||||
'text.html',
|
||||
'script.tag',
|
||||
'source.js',
|
||||
'string.quoted',
|
||||
'text.html',
|
||||
'property.name'
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -52,6 +52,7 @@ class TreeSitterGrammar {
|
||||
|
||||
this.languageModule = require(languageModulePath)
|
||||
this.scopesById = new Map()
|
||||
this.conciseScopesById = new Map()
|
||||
this.idsByScope = {}
|
||||
this.nextScopeId = 256 + 1
|
||||
this.registration = null
|
||||
@@ -75,6 +76,17 @@ class TreeSitterGrammar {
|
||||
return this.scopesById.get(id)
|
||||
}
|
||||
|
||||
scopeNameForScopeId (id) {
|
||||
let result = this.conciseScopesById.get(id)
|
||||
if (!result) {
|
||||
result = this.scopesById.get(id)
|
||||
.slice('syntax--'.length)
|
||||
.replace(/ syntax--/g, '.')
|
||||
this.conciseScopesById.set(id, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
activate () {
|
||||
this.registration = this.registry.addGrammar(this)
|
||||
}
|
||||
|
||||
@@ -398,42 +398,15 @@ class TreeSitterLanguageMode {
|
||||
}
|
||||
|
||||
scopeDescriptorForPosition (point) {
|
||||
if (!this.tree) return this.rootScopeDescriptor
|
||||
point = Point.fromObject(point)
|
||||
|
||||
const iterators = []
|
||||
this._forEachTreeWithRange(new Range(point, point), tree => {
|
||||
const rootStartIndex = tree.rootNode.startIndex
|
||||
let node = tree.rootNode.descendantForPosition(point)
|
||||
|
||||
// Don't include anonymous token types like '(' because they prevent scope chains
|
||||
// from being parsed as CSS selectors by the `slick` parser. Other css selector
|
||||
// parsers like `postcss-selector-parser` do allow arbitrary quoted strings in
|
||||
// selectors.
|
||||
if (!node.isNamed) node = node.parent
|
||||
iterators.push({node, rootStartIndex})
|
||||
})
|
||||
|
||||
iterators.sort(compareScopeDescriptorIterators)
|
||||
|
||||
const iterator = this.buildHighlightIterator()
|
||||
const scopes = []
|
||||
for (;;) {
|
||||
const {length} = iterators
|
||||
if (!length) break
|
||||
const iterator = iterators[length - 1]
|
||||
scopes.push(iterator.node.type)
|
||||
iterator.node = iterator.node.parent
|
||||
if (iterator.node) {
|
||||
let i = length - 1
|
||||
while (i > 0 && compareScopeDescriptorIterators(iterator, iterators[i - 1]) < 0) i--
|
||||
if (i < length - 1) iterators.splice(i, 0, iterators.pop())
|
||||
} else {
|
||||
iterators.pop()
|
||||
}
|
||||
for (const scope of iterator.seek(point)) {
|
||||
scopes.push(this.grammar.scopeNameForScopeId(scope, false))
|
||||
}
|
||||
|
||||
scopes.push(this.grammar.scopeName)
|
||||
return new ScopeDescriptor({scopes: scopes.reverse()})
|
||||
for (const scope of iterator.getOpenScopeIds()) {
|
||||
scopes.push(this.grammar.scopeNameForScopeId(scope, false))
|
||||
}
|
||||
return new ScopeDescriptor({scopes})
|
||||
}
|
||||
|
||||
getGrammar () {
|
||||
@@ -1073,13 +1046,6 @@ function nodeIsSmaller (left, right) {
|
||||
return left.endIndex - left.startIndex < right.endIndex - right.startIndex
|
||||
}
|
||||
|
||||
function compareScopeDescriptorIterators (a, b) {
|
||||
return (
|
||||
a.node.startIndex - b.node.startIndex ||
|
||||
a.rootStartIndex - b.rootStartIndex
|
||||
)
|
||||
}
|
||||
|
||||
function last (array) {
|
||||
return array[array.length - 1]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user