Search code examples
eclipseeclipse-pluginxtext

Disable highlighting of keywords when used in identifiers


I'm parsing my Xtext language fine at the moment, but have run into a problem:

My import statements, which look like this:

ImportStatement:
    'use' QualifiedName '.*'? END ;

terminal END:
    ';' ; 

Gives me nice results like this:

use test.io.Classname;
use test.io.*;

However when I want to do something like:

use example.use.TestClass;

The 'use' in the qualified name is highlighted as if it is a keyword, like the first 'use'. I'm brand new to Xtext so have no idea what to do to remove this. I have tried changing the ordering and structure of my grammar but to no avail. The entire thing is below:

/*
 * Parser rules.
 */

Model:
    (imports+=ImportStatement)*;

ImportStatement:
    KEYWORD name=QualifiedName ('.*')? END;

/*
 * Parser types.
 */

QualifiedName:
    Word ('.' Word)?;

Word:
    IDENTIFIER | KEYWORD;

/*
 * Lexer types.
 */

terminal IDENTIFIER: '^'?('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;

KEYWORD: 'use';

terminal END: ';';

I have looked at a tutorial on a blog or their GitHub page which states how to fix this, which was missing some information such as changing Access Restrictions on my ide library, and overall, it doesn't work. I have done everything, and nothing happens, I continue to get this syntax highlighting.

My question is, how can I stop syntax highlighting in Xtext, when the keyword in question is a part of an identifier, or is being used as one?


Solution

  • from your question is not quite clear what is not working. is it parsing that does not work or is it the highlighting. and if it is the highlghting how does your implementation actually look like?

    having at the generation log of your dsl the first thing you get is this

    error(208): ../org.xtext.example.mydsl3/src-gen/org/xtext/example/mydsl3/parser/antlr/internal/InternalMyDsl.g:263:1: The following token definitions can never be matched because prior tokens match the same input: RULE_ID
    error(208): ../org.xtext.example.mydsl3.ide/src-gen/org/xtext/example/mydsl3/ide/contentassist/antlr/internal/InternalMyDsl.g:448:1: The following token definitions can never be matched because prior tokens match the same input: RULE_ID
    

    i assume this errors are there just for fun and you did not care. well in your case it should not be a problem but getting rid of it should be ok in any case.

    Model:
        (imports+=ImportStatement)*;
    
    ImportStatement:
        KEYWORD name=QualifiedName ('.*')? ';';
    
    /*
     * Parser types.
     */
    
    QualifiedName:
        Word ('.' Word)?;
    
    Word:
        ID | KEYWORD;
    
    /*
     * Lexer types.
     */
    
    @Override
    terminal ID: '^'?('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
    
    KEYWORD: 'use';
    

    The next step is to implement the highlighting

    import com.google.inject.Inject
    import org.eclipse.emf.ecore.EObject
    import org.eclipse.xtext.ide.editor.syntaxcoloring.DefaultSemanticHighlightingCalculator
    import org.eclipse.xtext.ide.editor.syntaxcoloring.HighlightingStyles
    import org.eclipse.xtext.ide.editor.syntaxcoloring.IHighlightedPositionAcceptor
    import org.eclipse.xtext.util.CancelIndicator
    import org.xtext.example.mydsl3.myDsl.ImportStatement
    import org.xtext.example.mydsl3.myDsl.MyDslPackage
    import org.xtext.example.mydsl3.services.MyDslGrammarAccess
    
    class MyDslSemanticHighlightingCalculator extends DefaultSemanticHighlightingCalculator {
    
         @Inject package MyDslGrammarAccess grammar
    
        override protected boolean highlightElement(EObject object, IHighlightedPositionAcceptor acceptor,
            CancelIndicator cancelIndicator) {
            if (object instanceof ImportStatement) {
                highlightFeature(acceptor, object, MyDslPackage.eINSTANCE.importStatement_Name, HighlightingStyles.DEFAULT_ID)
            }
            super.highlightElement(object, acceptor, cancelIndicator)
        }
    
    }
    

    and the binding

    @FinalFieldsConstructor
    class MyDslUiModule extends AbstractMyDslUiModule {
    
        def Class<? extends ISemanticHighlightingCalculator> bindISemanticHighlightingCalculator() {
            MyDslSemanticHighlightingCalculator
        }
    }
    

    and it works perfectly fine

    Screenshot of resulting editor