problems creating stub tree
Hello,
I'm trying to integrate StubTrees for fast access to some data of my psi-elements. I implemented everything according to the documentation here: http://confluence.jetbrains.com/display/IDEADEV/Indexing+and+PSI+Stubs+in+IntelliJ+IDEA .
My problem is that my PSI-elements are never backed by stubs.
In my implementation of IStubElementType the createStub- the serialize-, and deserialize-Methods are called. But the createPsi-Method is never called and the getStub-Method always returns null.
Here is the source of my very simple test language plugin:
public interface ItemStub extends StubElement<Item>{ List<String> getTokens(); }
public class ItemStubImpl extends StubBase<Item> implements ItemStub { private List<String> tokens; public ItemStubImpl(StubElement parent, List<String> tokens) { super(parent, SimpleTypes.ITEM); this.tokens = tokens; } @Override public List<String> getTokens() { return tokens; } public void setTokens(List<String> tokens) { this.tokens = tokens; } }
public class ItemStubElementImpl <T extends StubElement> extends StubBasedPsiElementBase<T> { public ItemStubElementImpl(@NotNull T stub, @NotNull IStubElementType nodeType) { super(stub, nodeType); } public ItemStubElementImpl(@NotNull ASTNode node) { super(node); } }
public interface Item extends StubBasedPsiElement<ItemStub> { List<String> getTokens(); }
public class ItemImpl extends ItemStubElementImpl<ItemStub> implements Item{ public ItemImpl(final @NotNull ItemStub stub, final @NotNull IStubElementType nodeType) { super(stub, nodeType); } public ItemImpl(@NotNull ASTNode node) { super(node); } public List<String> getTokens(){ ItemStub stub = getStub(); if(stub != null) {
// unfortunately I never reach this point. My stub is always null System.out.println("loaded from stub yeah"); List<String> tokens = stub.getTokens(); return tokens; } ASTNode[] children = getNode().getChildren(TokenSet.create(SimpleTypes.TOKEN)); List<String> tokens = new ArrayList<String>(); for (ASTNode child : children) { String text = child.getText(); tokens.add(text); } return tokens; } }
public class SimpleElementType extends IStubElementType<ItemStub, Item> { public SimpleElementType(@NotNull @NonNls String debugName) { super(debugName, SimpleLanguage.INSTANCE); } @Override public Item createPsi(@NotNull ItemStub stub) { return new ItemImpl(stub, this); } @Override public ItemStub createStub(@NotNull Item psi, StubElement parentStub) {
// this is called for every Item List<String> tokens = psi.getTokens(); ItemStubImpl itemStub = new ItemStubImpl(parentStub, tokens); return itemStub; } @Override public String getExternalId() { return null; } @Override public void serialize(ItemStub stub, StubOutputStream dataStream) throws IOException {
// this is called List<String> tokens = stub.getTokens(); String join = StringUtils.join(tokens, ","); dataStream.writeName(join); } @Override public ItemStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException {
// this is called StringRef stringRef = dataStream.readName(); if(stringRef == null) { return null; } String string = stringRef.getString(); String[] split = string.split(","); List<String> tokens = new ArrayList<String>(); for (String s : split) { tokens.add(s); } ItemStubImpl itemStub = new ItemStubImpl(parentStub, tokens); return itemStub; } @Override public void indexStub(ItemStub stub, IndexSink sink) { // TODO later } }
Sorry to just offer the source and hoping that someone finds the error, but I'm not able to find any hints in the web, so I would be very thankful if someone could put me in the right direction,
Sebastian
Please sign in to leave a comment.
One thing to bear in mind is that stubs are generally used to create a lightweight partial PSI tree which is used for global symbol resolution. It looks like your stub code is working correctly based on the methods you're seeing being called, what I suspect is that in your testing you're never performing operations which will require stubs to be used. If you're testing with files that are open in an editor, for example, stubs will be created (as you're seeing) but never actually used since the editor always has the full PSI after parsing the file. Do you have some code that accesses the PSI in a way that would need stubs to be used?
Hallo Colin, thank you for that hint. In fact I always used two test-files that were opened in the editor. Nevertheless changing that didn't have the effect that the stubs were used.
Maybe the problem is that my test-action forces Intellij to parse all the files and so no need for stub access is given.
That is the action I used:
I guess I still have a problem understanding the stubs. This is the workflow how I understood it:
1. When some functionality tries to access some psi-data, intellij checks if the psi-element was parsed?
2. If it was parsed, no reason to use stubs so no stub is deserialized from disk?
3. If it was not parsed, Intellij loads the stub from disk. If the stub can offer the needed data nothing will be parsed? If the stub can't offer the needed data the file gets parsed?
Bit confused and thankful for any help,
Sebastian