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.

0
5 comments

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

psiElement().afterLeaf(psiElement().withParent(GdInheritance.class)).accepts(position)
0

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

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

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

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.