Skip to content

Commit 7bfd33c

Browse files
committed
Add includeChildren injection point API, use it for rust injections
1 parent 8988f87 commit 7bfd33c

File tree

3 files changed

+198
-60
lines changed

3 files changed

+198
-60
lines changed

packages/language-rust-bundled/lib/main.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ exports.activate = function() {
22
for (const nodeType of ['macro_invocation', 'macro_rule']) {
33
atom.grammars.addInjectionPoint('source.rust', {
44
type: nodeType,
5-
language() { return 'rust'; },
6-
content(node) { return node.lastChild; },
5+
language() {
6+
return 'rust';
7+
},
8+
content(node) {
9+
return node.lastChild;
10+
},
11+
includeChildren: true
712
});
813
}
914
};

spec/tree-sitter-language-mode-spec.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ const ejsGrammarPath = require.resolve(
2727
const rubyGrammarPath = require.resolve(
2828
'language-ruby/grammars/tree-sitter-ruby.cson'
2929
);
30+
const rustGrammarPath = require.resolve(
31+
'language-rust-bundled/grammars/tree-sitter-rust.cson'
32+
);
3033

3134
describe('TreeSitterLanguageMode', () => {
3235
let editor, buffer;
@@ -831,6 +834,81 @@ describe('TreeSitterLanguageMode', () => {
831834
]);
832835
});
833836

837+
it('respects the `includeChildren` property of injection points', async () => {
838+
const rustGrammar = new TreeSitterGrammar(
839+
atom.grammars,
840+
rustGrammarPath,
841+
{
842+
scopeName: 'rust',
843+
parser: 'tree-sitter-rust',
844+
scopes: {
845+
identifier: 'variable',
846+
field_identifier: 'property',
847+
'call_expression > field_expression > field_identifier':
848+
'function',
849+
'macro_invocation > identifier': 'macro'
850+
},
851+
injectionRegExp: 'rust',
852+
injectionPoints: [
853+
{
854+
type: 'macro_invocation',
855+
language() {
856+
return 'rust';
857+
},
858+
content(node) {
859+
return node.lastChild;
860+
},
861+
862+
// The tokens within a `token_tree` are all parsed as separate
863+
// children of the `token_tree`. By default, when adding a language
864+
// injection for a node, the node's children's ranges would be
865+
// excluded from the injection. But for this injection point
866+
// (parsing token trees as rust code), we want to reparse all of the
867+
// content of the token tree.
868+
includeChildren: true
869+
}
870+
]
871+
}
872+
);
873+
874+
atom.grammars.addGrammar(rustGrammar);
875+
876+
// Macro call within another macro call.
877+
buffer.setText('assert_eq!(a.b.c(), vec![d.e()]); f.g();');
878+
879+
const languageMode = new TreeSitterLanguageMode({
880+
buffer,
881+
grammar: rustGrammar,
882+
grammars: atom.grammars
883+
});
884+
buffer.setLanguageMode(languageMode);
885+
886+
// There should not be duplicate scopes due to the root layer
887+
// and for the injected rust layer.
888+
expectTokensToEqual(editor, [
889+
[
890+
{ text: 'assert_eq', scopes: ['macro'] },
891+
{ text: '!(', scopes: [] },
892+
{ text: 'a', scopes: ['variable'] },
893+
{ text: '.', scopes: [] },
894+
{ text: 'b', scopes: ['property'] },
895+
{ text: '.', scopes: [] },
896+
{ text: 'c', scopes: ['function'] },
897+
{ text: '(), ', scopes: [] },
898+
{ text: 'vec', scopes: ['macro'] },
899+
{ text: '![', scopes: [] },
900+
{ text: 'd', scopes: ['variable'] },
901+
{ text: '.', scopes: [] },
902+
{ text: 'e', scopes: ['function'] },
903+
{ text: '()]); ', scopes: [] },
904+
{ text: 'f', scopes: ['variable'] },
905+
{ text: '.', scopes: [] },
906+
{ text: 'g', scopes: ['function'] },
907+
{ text: '();', scopes: [] }
908+
]
909+
]);
910+
});
911+
834912
it('notifies onDidTokenize listeners the first time all syntax highlighting is done', async () => {
835913
const promise = new Promise(resolve => {
836914
editor.onDidTokenize(event => {

0 commit comments

Comments
 (0)