PsiElementFinder analogue for Kotlin

Answered

What would be the analogue of PsiElementFinder for Kotlin files? 

As per documentation,

PsiElementFinder allows extending the mechanism of locating classes and packages by full-qualified name ... to be picked up by JavaPsiFacade.

The class I want to resolve by FQN is KtClass. PsiElementFinder method signature wouldn't suit since KtClass is not instance of PsiClass. Any suggestions what would be similar mechanism that will allow returning KtClasses?

public abstract PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope);
4 comments
Comment actions Permalink

If you want to lookup class written in Kotlin via FQN, just use JavaPsiFacade.findClass().

0
Comment actions Permalink

Oh, no. I’m asking because I implemented custom PsiElementFinder to locate classes out of project scope by full-qualified name.

It worked well, but now we’re adding Kotlin support. I want to return Kotlin class instead of Java class, but PsiElementFinder allows only returning PsiClass (not KtClass).

What could I use to implement same mechanism but be able to return KtClass?

0
Comment actions Permalink

You can use Kotlin directly by `org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex`.
Example:

KotlinFullClassNameIndex.getInstance().get(fullQualifierName, project, scope)
Also, you can work with Kotlin like Java using the "light class" wrappers:
// org.jetbrains.kotlin.asJava.LightClassUtilsKt.toLightClass(org.jetbrains.kotlin.psi.KtClassOrObject)
fun wrap(ktClass: KtClass): PsiClass? = ktClass.toLightClass() // e.g. `KtUltraLightClass` as result

// org.jetbrains.kotlin.asJava.LightClassUtilsKt.getUnwrapped
fun unwrap(psiClass: PsiClass): KtClass? = psiClass.unwrapped as? KtClass
0
Comment actions Permalink

Thank you! I tried using "light class wrappers" approach.

(Side note: `psiClass = ktClass.toLightClass()` returns null, but this one work

psiClass = LightClassGenerationSupport.getInstance(project).createUltraLightClass(ktClass)

---

Now, that PsiElementFinder successfully returns PsiClass, I see symbols in Java files are recognized (🎉), but in Kotlin files are not (😞). 

In logs, I noticed this error, which happens only for kotlin file

org.jetbrains.kotlin.idea.caches.resolve.KotlinIdeaResolutionException: Kotlin resolution encountered a problem while analyzing KtClass... Caused by: java.lang.AssertionError: Resolver for 'project source roots and libraries with settings=PlatformAnalysisSettingsImpl(platform=JVM (JVM_1_8))' does not know how to resolve [LibrarySourceInfo(libraryName=//my/custom/path/out/of/project/scope]

What could I do for PsiElementFinder to support symbols recognition in Kotlin files, same way as it works for Java files?

---

Full stack trace:

org.jetbrains.kotlin.idea.caches.resolve.KotlinIdeaResolutionException: Kotlin resolution encountered a problem while analyzing KtClass
at org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacadeWithDebugInfo.resolveToDescriptor(ResolutionFacadeWithDebugInfo.kt:66)
at org.jetbrains.kotlin.idea.resolve.ResolutionFacade$DefaultImpls.resolveToDescriptor$default(ResolutionFacade.kt:31)
at org.jetbrains.kotlin.idea.caches.resolve.util.JavaResolutionUtils.resolveToDescriptor(JavaResolveExtension.kt:109)
at org.jetbrains.kotlin.idea.caches.resolve.util.JavaResolutionUtils.resolveToDescriptor$default(JavaResolveExtension.kt:102)
at org.jetbrains.kotlin.idea.core.KotlinIndicesHelper.getJvmClassesByName(KotlinIndicesHelper.kt:280)
at org.jetbrains.kotlin.idea.quickfix.AbstractImportFixKt.getClassesByName(AbstractImportFix.kt:702)
at org.jetbrains.kotlin.idea.quickfix.AbstractImportFixKt.access$getClassesByName(AbstractImportFix.kt:1)
at org.jetbrains.kotlin.idea.quickfix.OrdinaryImportFixBase.fillCandidates(AbstractImportFix.kt:248)
at org.jetbrains.kotlin.idea.quickfix.AbstractImportFix.fillCandidates(AbstractImportFix.kt:400)
at org.jetbrains.kotlin.idea.quickfix.ImportFixBase.collectSuggestionsForName(AbstractImportFix.kt:169)
at org.jetbrains.kotlin.idea.quickfix.ImportFixBase.collectSuggestions(AbstractImportFix.kt:137)
at org.jetbrains.kotlin.idea.quickfix.ImportFixBase.computeSuggestions(AbstractImportFix.kt:81)
at org.jetbrains.kotlin.idea.quickfix.ImportFixBase$Factory.createAction(AbstractImportFix.kt:223)
at org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory.doCreateActions(KotlinSingleIntentionActionFactory.kt:15)
at org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory.createActions(KotlinIntentionActionsFactory.kt:44)
at org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory.createActionsForAllProblems(KotlinIntentionActionsFactory.kt:26)
at org.jetbrains.kotlin.idea.highlighter.AbstractKotlinHighlightVisitorKt.createQuickFixes(AbstractKotlinHighlightVisitor.kt:289)
at org.jetbrains.kotlin.idea.highlighter.ElementAnnotator.createFixesMap(ElementAnnotator.kt:186)
at org.jetbrains.kotlin.idea.highlighter.ElementAnnotator.createFixesMap$default(ElementAnnotator.kt:179)
at org.jetbrains.kotlin.idea.highlighter.ElementAnnotator.registerDiagnosticsSameFactoryQuickFixes(ElementAnnotator.kt:84)
at org.jetbrains.kotlin.idea.highlighter.ElementAnnotator.registerDiagnosticsQuickFixes(ElementAnnotator.kt:77)
at org.jetbrains.kotlin.idea.highlighter.AbstractKotlinHighlightVisitor.annotateQuickFixes(AbstractKotlinHighlightVisitor.kt:190)
at org.jetbrains.kotlin.idea.highlighter.AbstractKotlinHighlightVisitor.analyze(AbstractKotlinHighlightVisitor.kt:124)
at org.jetbrains.kotlin.idea.highlighter.AbstractKotlinHighlightVisitor.analyze(AbstractKotlinHighlightVisitor.kt:53)
at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.analyzeByVisitors(GeneralHighlightingPass.java:304)
at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.lambda$analyzeByVisitors$6(GeneralHighlightingPass.java:304)
at com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.analyze(DefaultHighlightVisitor.java:96)
at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.analyzeByVisitors(GeneralHighlightingPass.java:304)
at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.collectHighlights(GeneralHighlightingPass.java:272)
at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.collectInformationWithProgress(GeneralHighlightingPass.java:214)
at com.intellij.codeInsight.daemon.impl.ProgressableTextEditorHighlightingPass.doCollectInformation(ProgressableTextEditorHighlightingPass.java:84)
at com.intellij.codeHighlighting.TextEditorHighlightingPass.collectInformation(TextEditorHighlightingPass.java:56)
at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$1(PassExecutorService.java:400)
at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1146)
at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$2(PassExecutorService.java:393)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:658)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:610)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:65)
at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.doRun(PassExecutorService.java:392)
at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$run$0(PassExecutorService.java:368)
at com.intellij.openapi.application.impl.ReadMostlyRWLock.executeByImpatientReader(ReadMostlyRWLock.java:172)
at com.intellij.openapi.application.impl.ApplicationImpl.executeByImpatientReader(ApplicationImpl.java:189)
at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.run(PassExecutorService.java:366)
at com.intellij.concurrency.JobLauncherImpl$VoidForkJoinTask$1.exec(JobLauncherImpl.java:188)
at java.base/java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)

Caused by: java.lang.AssertionError: Resolver for 'project source roots and libraries with settings=PlatformAnalysisSettingsImpl(platform=JVM (JVM_1_8)' does not know how to resolve [LibrarySourceInfo(libraryName=//my/custom/path/out/of/project/scope]
at org.jetbrains.kotlin.analyzer.DiagnoseUnknownModuleInfoReporter.errorInSdkResolver(AbstractResolverForProject.kt:307)
at org.jetbrains.kotlin.analyzer.DiagnoseUnknownModuleInfoReporter.report(AbstractResolverForProject.kt:278)
at org.jetbrains.kotlin.analyzer.AbstractResolverForProject.diagnoseUnknownModuleInfo(AbstractResolverForProject.kt:157)
at org.jetbrains.kotlin.idea.caches.resolve.ProjectResolutionFacade.resolverForElement$kotlin_core(ProjectResolutionFacade.kt:137)
at org.jetbrains.kotlin.idea.caches.resolve.ModuleResolutionFacadeImpl$resolveToDescriptor$1.invoke(ModuleResolutionFacadeImpl.kt:99)
at org.jetbrains.kotlin.idea.caches.resolve.ModuleResolutionFacadeImpl$resolveToDescriptor$1.invoke(ModuleResolutionFacadeImpl.kt:91)
at com.intellij.openapi.progress.impl.CancellationCheck.withCancellationCheck(CancellationCheck.kt:48)
at com.intellij.openapi.progress.impl.CancellationCheck$Companion.runWithCancellationCheck(CancellationCheck.kt:80)
at org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt.runWithCancellationCheck(ApplicationUtils.kt:48)
at org.jetbrains.kotlin.idea.caches.resolve.ModuleResolutionFacadeImpl.resolveToDescriptor(ModuleResolutionFacadeImpl.kt:91)
at org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacadeWithDebugInfo.resolveToDescriptor(ResolutionFacadeWithDebugInfo.kt:67)
0

Please sign in to leave a comment.