leafPsiElement cannot be cast to CompositeElement - how to debug ?
Hi,
I got a class cast exception when the user insert new code. This class cast exception only happen for a specific keyword and only in edit mode.
If I close the IDE and restart it after the class cast, I got the correct Psi tree.
This is what I get when I type "if ()" (right parenthesis is automatically inserted):

The If statement is not transformed. If I reopen the IDE, I get the correct Psi tree:

I checked my parser and can't find any problem.If I insert "switch ()" I have no problems.
The stack trace is this one:
java.lang.ClassCastException: com.intellij.psi.impl.source.tree.LeafPsiElement cannot be cast to com.intellij.psi.impl.source.tree.CompositeElement
at com.intellij.psi.impl.DiffLog$InsertEntry.<init>(DiffLog.java:160)
at com.intellij.psi.impl.DiffLog$InsertEntry.<init>(DiffLog.java:153)
at com.intellij.psi.impl.DiffLog.nodeInserted(DiffLog.java:75)
at com.intellij.psi.impl.DiffLog.nodeInserted(DiffLog.java:27)
at com.intellij.lang.impl.PsiBuilderImpl$ConvertFromTokensToASTBuilder.nodeInserted(PsiBuilderImpl.java:972)
at com.intellij.lang.impl.PsiBuilderImpl$ConvertFromTokensToASTBuilder.nodeInserted(PsiBuilderImpl.java:954)
at com.intellij.util.diff.DiffTree.build(DiffTree.java:197)
at com.intellij.util.diff.DiffTree.build(DiffTree.java:151)
at com.intellij.util.diff.DiffTree.build(DiffTree.java:151)
at com.intellij.util.diff.DiffTree.build(DiffTree.java:151)
at com.intellij.util.diff.DiffTree.build(DiffTree.java:151)
at com.intellij.util.diff.DiffTree.build(DiffTree.java:151)
at com.intellij.util.diff.DiffTree.build(DiffTree.java:151)
at com.intellij.util.diff.DiffTree.build(DiffTree.java:151)
at com.intellij.util.diff.DiffTree.diff(DiffTree.java:61)
at com.intellij.psi.impl.BlockSupportImpl.diffTrees(BlockSupportImpl.java:336)
at com.intellij.lang.impl.PsiBuilderImpl.a(PsiBuilderImpl.java:996)
at com.intellij.lang.impl.PsiBuilderImpl.b(PsiBuilderImpl.java:910)
at com.intellij.lang.impl.PsiBuilderImpl.getTreeBuilt(PsiBuilderImpl.java:901)
at com.reason.lang.CommonParser.parse(CommonParser.java:31)
at com.intellij.psi.tree.ILazyParseableElementType.doParseContents(ILazyParseableElementType.java:88)
at com.intellij.psi.tree.IFileElementType.parseContents(IFileElementType.java:49)
at com.intellij.psi.impl.source.tree.LazyParseableElement.lambda$ensureParsed$0(LazyParseableElement.java:193)
at com.intellij.psi.impl.DebugUtil.performPsiModification(DebugUtil.java:544)
at com.intellij.psi.impl.source.tree.LazyParseableElement.ensureParsed(LazyParseableElement.java:192)
at com.intellij.psi.impl.source.tree.LazyParseableElement.getFirstChildNode(LazyParseableElement.java:247)
at com.intellij.psi.impl.source.tree.LazyParseableElement.getFirstChildNode(LazyParseableElement.java:40)
at com.intellij.psi.impl.BlockSupportImpl.isReplaceWholeNode(BlockSupportImpl.java:359)
at com.intellij.psi.impl.BlockSupportImpl.mergeTrees(BlockSupportImpl.java:305)
at com.intellij.psi.impl.BlockSupportImpl.makeFullParse(BlockSupportImpl.java:241)
at com.intellij.psi.impl.BlockSupportImpl.reparse(BlockSupportImpl.java:101)
at com.intellij.psi.impl.DocumentCommitThread.doCommit(DocumentCommitThread.java:682)
at com.intellij.psi.impl.DocumentCommitThread.lambda$commitUnderProgress$4(DocumentCommitThread.java:451)
at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1129)
at com.intellij.psi.impl.DocumentCommitThread.commitUnderProgress(DocumentCommitThread.java:473)
at com.intellij.psi.impl.DocumentCommitThread.commitSynchronously(DocumentCommitThread.java:364)
at com.intellij.psi.impl.PsiDocumentManagerBase.lambda$doCommit$1(PsiDocumentManagerBase.java:447)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:1010)
at com.intellij.psi.impl.PsiDocumentManagerBase.doCommit(PsiDocumentManagerBase.java:455)
at com.intellij.psi.impl.PsiDocumentManagerBase.commitDocument(PsiDocumentManagerBase.java:295)
at com.intellij.codeInsight.editorActions.enter.EnterBetweenBracesDelegate.bracesAreInTheSameElement(EnterBetweenBracesDelegate.java:22)
at com.intellij.codeInsight.editorActions.enter.EnterBetweenBracesFinalHandler.isApplicable(EnterBetweenBracesFinalHandler.java:79)
at com.intellij.codeInsight.editorActions.enter.EnterBetweenBracesFinalHandler.preprocessEnter(EnterBetweenBracesFinalHandler.java:42)
at com.intellij.codeInsight.editorActions.EnterHandler.a(EnterHandler.java:128)
at com.intellij.codeInsight.editorActions.EnterHandler.b(EnterHandler.java:81)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.lambda$disablePostprocessFormattingInside$1(PostprocessReformattingAspect.java:110)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.disablePostprocessFormattingInside(PostprocessReformattingAspect.java:118)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.disablePostprocessFormattingInside(PostprocessReformattingAspect.java:109)
at com.intellij.codeInsight.editorActions.EnterHandler.executeWriteAction(EnterHandler.java:80)
at com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler$1.run(EditorWriteActionHandler.java:51)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:1010)
at com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler.doExecute(EditorWriteActionHandler.java:64)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.execute(EditorActionHandler.java:210)
at com.intellij.codeInsight.template.impl.editorActions.EnterHandler.executeWriteAction(EnterHandler.java:49)
at com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler$1.run(EditorWriteActionHandler.java:51)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:1010)
at com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler.doExecute(EditorWriteActionHandler.java:64)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.lambda$null$2(EditorActionHandler.java:202)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.doIfEnabled(EditorActionHandler.java:110)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.lambda$execute$3(EditorActionHandler.java:201)
at com.intellij.openapi.editor.impl.CaretModelImpl.a(CaretModelImpl.java:363)
at com.intellij.openapi.editor.impl.CaretModelImpl.doWithCaretMerging(CaretModelImpl.java:452)
at com.intellij.openapi.editor.impl.CaretModelImpl.runForEachCaret(CaretModelImpl.java:355)
at com.intellij.openapi.editor.impl.CaretModelImpl.runForEachCaret(CaretModelImpl.java:346)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.execute(EditorActionHandler.java:201)
at com.intellij.openapi.editor.actionSystem.EditorAction.lambda$actionPerformed$0(EditorAction.java:98)
at com.intellij.openapi.command.impl.CoreCommandProcessor.a(CoreCommandProcessor.java:137)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:95)
at com.intellij.openapi.editor.actionSystem.EditorAction.actionPerformed(EditorAction.java:107)
at com.intellij.openapi.editor.actionSystem.EditorAction.actionPerformed(EditorAction.java:86)
at com.intellij.openapi.actionSystem.ex.ActionUtil$1.run(ActionUtil.java:220)
at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAware(ActionUtil.java:237)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher$1.performAction(IdeKeyEventDispatcher.java:578)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.a(IdeKeyEventDispatcher.java:627)
at com.intellij.openapi.application.TransactionGuardImpl.performUserActivity(TransactionGuardImpl.java:195)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.processAction(IdeKeyEventDispatcher.java:626)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.a(IdeKeyEventDispatcher.java:478)
at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.dispatchKeyEvent(IdeKeyEventDispatcher.java:212)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:702)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:395)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Why is the if not transformed ? What is going wrong, what can I do to debug the problem ?
Thanks
Please sign in to leave a comment.
Hgiraud, first, you can put a breakpoint to the exception place and see which type the LeafPsiElement has. Then I'd look closely at how this type is defined, whether it's a leaf or composite, and how it's used throughout your project. Apparently there's some discrepancy: leaves can only be used as tokens produced by lexer, and composite element types should be produced inside parser (based on PsiBuilder) and PSI wrappers should be created for them (presumably in com.intellij.lang.ParserDefinition#createElement).
Recently I encountered similar issue with Groovy GDSL, for some reason GrMethodCallImpl could not be cast to PsiMethodCall or something like that. The only thing I came up with is to add more logging:
synchronized void printClass(Class cls) {
println ""
println "class name: " + cls.canonicalName
println ""
println "superclasses: "
def cur = cls
while (cur = cur.superclass) println cur.canonicalName
println ""
println "interfaces: "
cls.interfaces.each {
cur = it
while (cur = cur.superclass) println cur.canonicalName
}
println ""
}
Another idea is to run PsiManager.dropPsiCaches()
@Peter thanks for your answer.
I did put a breakpoint in difftool, the problematic item is the 'IF'.
I use jflex for the lexer and a hand made parser. In the parser, I only mark a if statement as a PsiElement if I find a right parenthesis (builder.mark(..) ), and since idea is doing more work when a left paren is inserted, that seem to be the root of the problem.
If I unconditionnally mark the if wether there is a paren or not, I don't have the stack trace. But I don't understand why I have to do that. Is it a special behavior due to the () ?
Do you mean 'IF' token? Do you ever create a custom (composite) PSI element for it? If yes, please don't. You can wrap erroneous "if" token with a marker or not wrap it, as you wish, but you shouldn't create a PSI element for the token itself, only for the composite around it (which should have a different element type, e.g. IF_STATEMENT).
thanks. it works.