mirror of
https://github.com/atom/atom.git
synced 2026-01-25 23:08:18 -05:00
Merge pull request #17738 from atom/regex-matchers-for-style-map
Allow scope mappings to be refined via match rules
This commit is contained in:
@@ -159,7 +159,7 @@
|
||||
"temp": "^0.8.3",
|
||||
"text-buffer": "13.14.5",
|
||||
"timecop": "https://www.atom.io/api/packages/timecop/versions/0.36.2/tarball",
|
||||
"tree-sitter": "0.13.0",
|
||||
"tree-sitter": "0.13.2",
|
||||
"tree-view": "https://www.atom.io/api/packages/tree-view/versions/0.222.0/tarball",
|
||||
"typescript-simple": "1.0.0",
|
||||
"underscore-plus": "^1.6.8",
|
||||
|
||||
@@ -314,6 +314,39 @@ describe('TreeSitterLanguageMode', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('applies rules when specified', async () => {
|
||||
const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, {
|
||||
parser: 'tree-sitter-javascript',
|
||||
scopes: {
|
||||
'identifier': [
|
||||
{match: '^(exports|document|window|global)$', scopes: 'global'},
|
||||
{match: '^[A-Z_]+$', scopes: 'constant'},
|
||||
{match: '^[A-Z]', scopes: 'constructor'},
|
||||
'variable'
|
||||
],
|
||||
}
|
||||
})
|
||||
|
||||
buffer.setText(`exports.object = Class(SOME_CONSTANT, x)`)
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
{text: 'exports', scopes: ['global']},
|
||||
{text: '.object = ', scopes: []},
|
||||
{text: 'Class', scopes: ['constructor']},
|
||||
{text: '(', scopes: []},
|
||||
{text: 'SOME_CONSTANT', scopes: ['constant']},
|
||||
{text: ', ', scopes: []},
|
||||
{text: 'x', scopes: ['variable']},
|
||||
{text: ')', scopes: []},
|
||||
]
|
||||
])
|
||||
})
|
||||
|
||||
it('handles nodes that start before their first child and end after their last child', async () => {
|
||||
const grammar = new TreeSitterGrammar(atom.grammars, rubyGrammarPath, {
|
||||
parser: 'tree-sitter-ruby',
|
||||
|
||||
@@ -22,10 +22,7 @@ class TreeSitterGrammar {
|
||||
|
||||
const scopeSelectors = {}
|
||||
for (const key in params.scopes || {}) {
|
||||
scopeSelectors[key] = params.scopes[key]
|
||||
.split('.')
|
||||
.map(s => `syntax--${s}`)
|
||||
.join(' ')
|
||||
scopeSelectors[key] = toSyntaxClasses(params.scopes[key])
|
||||
}
|
||||
|
||||
this.scopeMap = new SyntaxScopeMap(scopeSelectors)
|
||||
@@ -74,6 +71,18 @@ class TreeSitterGrammar {
|
||||
}
|
||||
}
|
||||
|
||||
const toSyntaxClasses = scopes =>
|
||||
typeof scopes === 'string'
|
||||
? scopes
|
||||
.split('.')
|
||||
.map(s => `syntax--${s}`)
|
||||
.join(' ')
|
||||
: Array.isArray(scopes)
|
||||
? scopes.map(toSyntaxClasses)
|
||||
: scopes.match
|
||||
? {match: new RegExp(scopes.match), scopes: toSyntaxClasses(scopes.scopes)}
|
||||
: Object.assign({}, scopes, {scopes: toSyntaxClasses(scopes.scopes)})
|
||||
|
||||
const NODE_NAME_REGEX = /[\w_]+/
|
||||
|
||||
function matcherForSpec (spec) {
|
||||
|
||||
@@ -870,7 +870,6 @@ class LayerHighlightIterator {
|
||||
}
|
||||
|
||||
// Private methods
|
||||
|
||||
_moveUp (atLastChild) {
|
||||
let result = false
|
||||
const {endIndex} = this.treeCursor
|
||||
@@ -928,13 +927,37 @@ class LayerHighlightIterator {
|
||||
}
|
||||
|
||||
_currentScopeId () {
|
||||
const name = this.languageLayer.grammar.scopeMap.get(
|
||||
const rules = this.languageLayer.grammar.scopeMap.get(
|
||||
this.containingNodeTypes,
|
||||
this.containingNodeChildIndices,
|
||||
this.treeCursor.nodeIsNamed
|
||||
)
|
||||
if (name) {
|
||||
return this.languageLayer.languageMode.grammar.idForScope(name)
|
||||
const scopes = applyLeafRules(rules, this.treeCursor)
|
||||
if (scopes) {
|
||||
return this.languageLayer.languageMode.grammar.idForScope(scopes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const applyLeafRules = (rules, cursor) => {
|
||||
if (!rules || typeof rules === 'string') return rules
|
||||
if (Array.isArray(rules)) {
|
||||
for (let i = 0, {length} = rules; i !== length; ++i) {
|
||||
const result = applyLeafRules(rules[i], cursor)
|
||||
if (result) return result
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
if (typeof rules === 'object') {
|
||||
if (rules.exact) {
|
||||
return cursor.nodeText === rules.exact
|
||||
? applyLeafRules(rules.scopes, cursor)
|
||||
: undefined
|
||||
}
|
||||
if (rules.match) {
|
||||
return rules.match.test(cursor.nodeText)
|
||||
? applyLeafRules(rules.scopes, cursor)
|
||||
: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user