Search code examples
javakotlinintellij-ideaintellij-plugin

When writing an IntelliJ Plugin in Java I get ClassNotFoundException but the class exists


There are similar question in SO, but I'm sure this is different.

I'm developing an IntelliJ Idea Plugin, and the issue is with a class that is under IDE's classpath, I mean that the class is loaded with the IDE application itself.

Please look at these screenshots:

I can get the class by .javaClass in kotlin or .getClass() in java.

fig 1

When accessing the class (no luck)

fig 2

Getting class by reflection (no luck)

fig 3

The code: github reference

class SelectLiteralElementUnderCaretAction : SelectTextUnderCaretAction() {
    private fun rawSelectionRange(caret: Caret) = caret.util.run {
        if (!moveUntilReached("\"'`", "\n", BACKWARD)) return@run null
        val startCandidateOffset = prevCharOffset
        val startCandidateChar = prevChar!!
        val backwardDistance = (caret.offset - startCandidateOffset).absoluteValue
        reset()
        
        if (!moveUntilReached("\"'`", "\n", FORWARD)) return@run null
        val endCandidateOffset = nextCharOffset
        val endCandidateChar = nextChar!!
        val forwardDistance = (caret.offset - endCandidateOffset).absoluteValue
        reset()
        
        if (startCandidateChar == endCandidateChar)
            return@run startCandidateOffset..endCandidateOffset + 1
        
        if (backwardDistance < forwardDistance) {
            if (!moveUntilReached(startCandidateChar.toString(), "\n", FORWARD)) return@run null
            return@run startCandidateOffset..nextCharOffset + 1
        }
        
        if (backwardDistance > forwardDistance) {
            if (!moveUntilReached(endCandidateChar.toString(), "\n", BACKWARD)) return@run null
            return@run prevCharOffset..endCandidateOffset + 1
        }
        
        return@run null
    }
    
    private fun shrinkSelection(caret: Caret): IntRange? {
        val text = caret.selectedText!!
        val first = text.first()
        val last = text.last()
        
        if (first == last && first in "`'\"") {
            val oldStart = caret.selectionStart
            val start = text.indexOfFirst { it != first }
            val end = text.indexOfLast { it != last }
            
            return (oldStart + start)..(oldStart + end + 1)
        }
        
        return null
    }
    
    override fun getSelectionRange(caret: Caret, psiFile: PsiFile): IntRange? {
        if (caret.hasSelection())
            shrinkSelection(caret)?.let { return it }
        
        val element = psiFile.elementAt(caret)
        
        return when (psiFile.fileType.name.lowercase()) {
            "java" -> element?.parentOfType<PsiLiteralExpression>(true)?.textRange?.intRange
            
            "kotlin" -> element?.parentOfType<KtStringTemplateExpression>(true)?.textRange?.intRange // issue is here
            
            "javascript",
            "typescript" -> element?.parentOfTypes(
                JSStringTemplateExpression::class,
                JSLiteralExpression::class,
                withSelf = true
            )?.textRange?.intRange
            
            "go" -> element?.parentOfType<GoStringLiteral>()?.textRange?.intRange
            
            else -> rawSelectionRange(caret)
        }
    }
}

What I Tried

I tried reflection and it didn't help.

I used ide-scripting-console to be sure that this type exists at runtime and existed

I also have the dependency on Kotlin plugin

enter image description here


Solution

  • Finally I solved the issue. thanks to @Queeg and @chubbsondubs for their comments.

    I added the dependency to kotlin plugin in plugin.xml like below:

    <depends>org.jetbrains.kotlin</depends>
    

    and also changed the plugin ids in build.gradle as follows (but I don't think that the problem was actually from here):

    plugins.add("com.intellij.java")
    plugins.add("org.jetbrains.kotlin")
    

    which previously was:

    plugins.add("java")
    plugins.add("Kotlin")