Element Patter

Answered

Hello,
I've stumbled onto another problem with language plugin creation and that is one case of ElementPattern matching.

Grammar starts with parsing those two lines:

extends Something
class_name SomethingElse

Grammar rules in short are as follows:

gdfile ::= inheritance classNaming?
inheritance ::= EXTENDS inheritanceId_nm
inheritanceId_nm ::= IDENTIFIER
classNaming ::= CLASS_NAME className_nm
className_nm ::= IDENTIFIER

For CodeCompletion I've created a pattern for first line like:

val INHERITANCE: ElementPattern<PsiElement> = psiElement().withText(GdKeywords.EXTENDS)
val IN_INHERITANCE: ElementPattern<PsiElement> = psiElement().afterLeaf(INHERITANCE)

The IN_INHERITENCE works perfectly and matches right after 'extends' keyword.

Problem is that I'm unable to match the 'extends' itself... same goes for 'class_name' keyword.

None of following Patterns is able to match the beggining of classNaming rule to add that 'class_name' auto-completion

PsiJavaPatterns.psiElement().withText("class_name").accepts(position)

PlatformPatterns.psiElement(GdTypes.CLASS_NAME).withParent(GdClassNaming.class).accepts(position)

PsiJavaPatterns.psiElement(GdTypes.CLASS_NAME).withParent(psiElement(GdTypes.CLASS_NAMING)).accepts(position))

PsiJavaPatterns.psiElement(GdTypes.CLASS_NAME).accepts(position)

PsiJavaPatterns.psiElement().insideStarting(psiElement(GdClassNaming.class)).accepts(position)

Can anyone lead me to a way how to do it please?
Is there a different approach to match the beggining of a rule?

PsiViewer even shows, that CLASS_NAME element is expected, but none of given patterns matches.

Any help appreciated,
have a nice day.

5 comments
Comment actions Permalink

Ok.. not sure if ideal, but found one working pattern:

psiElement().afterLeaf(psiElement().withParent(GdInheritance.class)).accepts(position)
0
Comment actions Permalink

But if anyone has better solution, please let me know.
and this seems too loose as if GdInheritance would have more leaves it would check for every from second one.

0
Comment actions Permalink

Have you carefully read how you can debug, when ElementPattern doesn't match? We have quite detailed documentation about this since it's a pain-point for many developers:

https://plugins.jetbrains.com/docs/intellij/element-patterns.html#tools-and-debugging

0
Comment actions Permalink

From debugging I've found out, that it does not match class_name token in the place where it's expected, because it has ErrorElement(Identifier) at the moment as class_name is not yet written.

I hoped that patterns might check if the position can be filled with the class_name token, but thats something I can't figure out.

Or is it even possible to match against something that is expected by grammar, but not in place yet?

0
Comment actions Permalink

OK, I think I understood your problem now. The answer is *no*, you can't work with something that isn't there and expect that patterns match because it could/should be filled with something specific. However, your solution idea is correct from what I see. Your class-name keyword is expected after the inheritance node and you should check for that.

Look through the PsiElementPattern because there are a lot of helper functions that are convenient. For instance this here

  @NotNull
public Self afterLeaf(@NotNull final ElementPattern<? extends PsiElement> pattern) {
return afterLeafSkipping(psiElement().whitespaceCommentEmptyOrError(), pattern);
}

which you already used. But also look at afterLeafSkipping which can be tailored to your needs.

1

Please sign in to leave a comment.