I'm trying to add Code Completion feature to a text editor. I thought that I can get non-semantic content assist proposals from Antlr.
At this point, I have several ParserRuleContexts. I want to reach all terminal nodes of any type of ParserRuleContext.
For example I have bnf like below;
class
'class' name = IDENTIFIER '{'
attribute*
'}'
;
attribute
( qualifier += 'public'
| qualifier += 'protected'
| qualifier += 'private')?
(qualifier += 'static')?
(qualifier += 'final')?
'attribute' name = IDENTIFIER ':' type = IDENTIFIER
('(' qualifier += 'unique' ')')?
;
IDENTIFIER : LETTER (LETTER|DIGIT)*;
LETTER : [a-zA-Z];
DIGIT : [0-9];
And I have a sentence that is written on the editor:
class CLAZZ {
public attribute SOMETHING : String;
}
When a user move the cursor to the index below and want to get content assist:
"public [cursor] attribute SOMETHING : String;
"
The content assist should get 'final' and 'static' qualifiers as proposal.
I used Antlr parser to parse this sentence. And then I caught that the cursor is in the ClassContext -> AttributeContext by using Visitor.
In the visitAttributeContext method, I want to get all terminals of AttributeContext like [public, protected, private, static, final, unique]. Then I'll eliminate other qualifiers excluding 'static, final' according to cursor position.
Eventually, my question is, how can i get all terminal nodes from any ParserRuleContex? Or is there any other way?
Note: The grammar may be wrong, I invented for this question. Please just skim that.
The implementation of "ContentAssist" (better known under the term "code completion") is a non-trivial task and you might have to dig deep into the inner classes of ANTLR (atm at least). What you have to do is to walk the ATN, generated by ANTLR for each of your parser and lexer classes. One way to do that is described in the blog post: Building autocompletion for an editor based on ANTLR. A similar approach is used by the LL1Analyzer, which is a class in the ANTLR runtime.
However, both can only give you lexer tokens (e.g. all your keywords + the other ones like IDENTIFIER or DIGIT). That means you won't get e.g. variable references and the like.