Search code examples
validationwarningsxtextxtend

Xtext custom validator warning - How to mark keyword?


I have the simple Greeting example in xtext. So the DSL is defined like this:

grammar org.xtext.example.mydsl.Tests with org.eclipse.xtext.common.Terminals

generate tests "http://www.xtext.org/example/mydsl/Tests"

Model:
    greetings+= Greeting*;

Greeting:
    'Hello' name=ID '!';

Moreover, I have the following validator:

@Check
def checkGreetingStartsWithCapital(Greeting greeting) {
    if (!Character.isUpperCase(greeting.name.charAt(0))) {
        warning('Name should start with a capital', 
                TestsPackage.Literals.GREETING__NAME,
                -1,
                INVALID_NAME)
    }
}

If I write the validator like this and have an expression like "Hello world!" in my model, the "world" is marked, i.e. there is this yellow line under it. What do I have to do if I want to mark only the keyword so in this case only the "Hello"? I tried quite a few things and I can only manage to either mark the whole line "Hello world!" or just the "world".

Thank you!


Solution

  • have a look at the other methods for reporting a warning/error. there is one that takes an offset and length. you can use the node model to get them for the keyword

    class MyDslValidator extends AbstractMyDslValidator {
    
        public static val INVALID_NAME = 'invalidName'
        @Inject extension MyDslGrammarAccess
    
        @Check
        def checkGreetingStartsWithCapital(Greeting greeting) {
            if (!Character.isUpperCase(greeting.name.charAt(0))) {
                val node = NodeModelUtils.findActualNodeFor(greeting)
    
                for (n : node.asTreeIterable) {
                    val ge = n.grammarElement
                    if (ge instanceof Keyword && ge == greetingAccess.helloKeyword_0) {
                        messageAcceptor.acceptWarning(
                            'Name should start with a capital',
                            greeting,
                            n.offset,
                            n.length,
                            INVALID_NAME
                        )
                    }
                }
    
            }
        }
    }