StubIndex created, but not used

Answered

Hello,

I'm seeking help with StubIndex of Language plugin that I'm having troubles with.

Index is created and even filled:

I've registered a StubElement interface as 'stubClass' attribute inside bnf grammar, registered StringStubIndexExtension for it into plugin.xml and changed plugin's FileType to IStubFileElement.

As a result I can even see stored values inside index with IndexViewer plugin for GdClassNamingImpl:

This seems ok, problem is that I'm unable to get that Stub back.
I've prepared a method for getting ClassName() which should use value stored inside that index

fun getClassname(element: GdClassNaming?): String {
val stub = element?.stub;
if (stub != null) {
return stub.name();
}

return element?.classNameNm?.name.toString();
}


Method is registered inside bnf grammar as: {methods=[getClassname]}

Which is also ok and it gets called, but problem is that element.stub is always null and never filled.

 

Stub object is created using incoming PsiElement:

override fun createStub(psi: GdClassNaming, parentStub: StubElement<*>?): GdClassNamingStub {
return GdClassNamingStubImpl(parentStub, psi.classNameNm?.name)
}

Generated class implementation is also correctly extending StubBasedPsiElement as follows:

public class GdClassNamingImpl extends StubBasedPsiElementBase<GdClassNamingStub> implements GdClassNaming {}

Can someone help me with where to look why those stubs even though created are not actually paired with PsiElement and not used?

In case source code is:
https://gitlab.com/IceExplosive/gdscript/-/tree/master

Code for this StubIndex is all under kotlin folder.

Thank you for any help and your time,
David Horacek

7 comments
Comment actions Permalink

Please verify javadoc com.intellij.extapi.psi.StubBasedPsiElementBase#getStub . Does it apply in your use case?

1
Comment actions Permalink

Thank you, that wasn't called. I've had StubElement, but not StubBasedPsiElement so I've added extends StubBasedPsiElementBase to implementation and now StubBasedPsiElementBase#getStub() method is called.

Problem now is that this falls into

com.intellij.psi.impl.source.SubstrateRef#getStub()

where lies an implementation:

@Nullable
public Stub getStub() {
return null;
}

So calling element?.stub on the element still results in null.

Do I have to somehow override this method? Or am I still missing some extension?

0
Comment actions Permalink

No, you don't have to worry about that method.

From Javadoc I mentioned in com.intellij.extapi.psi.StubBasedPsiElementBase#getStub, please verify whether these conditions apply in your specific use-case and switch to use getGreenStub().

Note: for most clients (where the logic doesn't crucially differ for stub and AST cases), {@link #getGreenStub()} should be preferred.
* @return the stub that this element is built upon, or null if the element is currently AST-based. The latter can happen
* if the file text was loaded from the very beginning, or if it was loaded via {@link #getNode()} on this or any other element
* in the containing file.
0
Comment actions Permalink

I'm actually more confused by that doc.

From "null if the element is currently AST-based" I understand that I won't get a stub on an element on which the method was called from IDE (like a node on which I triggered CompletionContributor).

So I'd expect that Stub would be loaded when I list all project files and find Stubbed elements inside them, something like:

var vFiles = FileTypeIndex.getFiles(GdFileType.INSTANCE, GlobalSearchScope.allScope(project));
for (VirtualFile vf : virtualFiles) {
var myFile = (GdFile) PsiManager.getInstance(project).findFile(vf);
var prop = (GdClassNamingImpl) PsiTreeUtil.findChildOfType(myFile, GdClassNamingImpl.class);
}

But to me that seems to contradict the part: "returns null... if the file text was loaded from the very beginning"

 

Also getGreenStub only falls into getStub, which returns null:

public Stub getStub() {
return null;
}

public Stub getGreenStub() {
return getStub();
}
0
Comment actions Permalink

Seems I've finally found the last missing piece today:

Before calling

PsiTreeUtil.findChildOfType(file, ...)

to get desired elements I've had to first call

file.getStubTree()

Now I'm finally getting some stub elements instead of full AST nodes.

0
Comment actions Permalink

Ok maybe I don't get it in the end... as getGreenStub or getGreenStubTree seemingly randomly throws an exception of ProcessCancel or something.

Is there anywhere tutorial with more detail about StubTrees and how to correctly use them that https://plugins.jetbrains.com/docs/intellij/indexing-and-psi-stubs.html page?

There's actually not much about actuall usage... only on Stub Indices but not on the tree itself.

0
Comment actions Permalink

Sorry for delay.

https://gitlab.com/IceExplosive/gdscript/-/blob/master/src/main/java/gdscript/psi/GdFile.java does not implement necessary IStubFileElementType, please see "The following steps need to be performed..." paragraph here https://plugins.jetbrains.com/docs/intellij/stub-indexes.html

You can use Tools->View PSI Structure dialog available in internal mode (https://plugins.jetbrains.com/docs/intellij/enabling-internal.html) to check stubs are correctly built for your files/language.

0

Please sign in to leave a comment.