mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-10-26 11:08:40 +03:00
Allow for any number of @_IGNORE_ capture names in a query…
…by namespacing them as `@_IGNORE_.foo`, `@_IGNORE_.bar`, etc. It's sometimes necessary to define a capture in a query not because you want to apply a scope name, but because you need to use it as the argument to a predicate. `@_IGNORE_` was intended for that purpose, but it was the _only_ capture name with that special effect. Now, you can specify any number of captures that don't apply scope names. As long as it equals `@_IGNORE_` or _starts with_ `@_IGNORE_.`, it'll have the same effect. This lets you target two or more nodes and use them all in predicates in the same query without any of them applying a scope name.
This commit is contained in:
parent
e547ace81c
commit
f691cfce28
@ -159,6 +159,67 @@ describe('ScopeResolver', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not apply any scopes when @_IGNORE_ is used', async () => {
|
||||
await grammar.setQueryForTest('highlightsQuery', `
|
||||
(lexical_declaration kind: _ @_IGNORE_
|
||||
(#match? @_IGNORE_ "const"))
|
||||
(lexical_declaration kind: _ @let
|
||||
(#match? @let "let"))
|
||||
`);
|
||||
|
||||
const languageMode = new WASMTreeSitterLanguageMode({ grammar, buffer });
|
||||
buffer.setLanguageMode(languageMode);
|
||||
buffer.setText(dedent`
|
||||
// this is a comment
|
||||
const foo = "ahaha";
|
||||
let bar = 'troz'
|
||||
`);
|
||||
await languageMode.ready;
|
||||
|
||||
let { scopeResolver, captures } = await getAllCaptures(grammar, languageMode);
|
||||
|
||||
for (let capture of captures) {
|
||||
let { node, name } = capture;
|
||||
let result = scopeResolver.store(capture);
|
||||
if (name === '_IGNORE_') {
|
||||
expect(!!result).toBe(false);
|
||||
} else {
|
||||
expect(!!result).toBe(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('does not apply any scopes when multiple @_IGNORE_s are used', async () => {
|
||||
await grammar.setQueryForTest('highlightsQuery', `
|
||||
(variable_declarator
|
||||
(identifier) @_IGNORE_.identifier
|
||||
(string) @_IGNORE_.string
|
||||
)
|
||||
`);
|
||||
|
||||
const languageMode = new WASMTreeSitterLanguageMode({ grammar, buffer });
|
||||
buffer.setLanguageMode(languageMode);
|
||||
buffer.setText(dedent`
|
||||
// this is a comment
|
||||
const foo = "ahaha";
|
||||
let bar = false
|
||||
`);
|
||||
await languageMode.ready;
|
||||
|
||||
let { scopeResolver, captures } = await getAllCaptures(grammar, languageMode);
|
||||
|
||||
for (let capture of captures) {
|
||||
let { node, name } = capture;
|
||||
let result = scopeResolver.store(capture);
|
||||
if (name.startsWith('_IGNORE_')) {
|
||||
expect(!!result).toBe(false);
|
||||
} else {
|
||||
expect(!!result).toBe(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
describe('adjustments', () => {
|
||||
it('adjusts ranges with (#set! adjust.startAt)', async () => {
|
||||
await grammar.setQueryForTest('highlightsQuery', `
|
||||
|
@ -487,12 +487,15 @@ class ScopeResolver {
|
||||
this.setDataForRange(range, props);
|
||||
}
|
||||
|
||||
if (name === '_IGNORE_') {
|
||||
if (name === '_IGNORE_' || name.startsWith('_IGNORE_.')) {
|
||||
// "@_IGNORE_" is a magical variable in an SCM file that will not be
|
||||
// applied in the grammar, but which allows us to prevent other kinds of
|
||||
// scopes from matching. We purposefully allowed this syntax node to set
|
||||
// data for a given range, but not to apply its scope ID to any
|
||||
// boundaries.
|
||||
//
|
||||
// A query can also use multiple different @_IGNORE_-style variables by
|
||||
// adding segments after the @_IGNORE_, such as @_IGNORE_.foo.bar.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user