getModuleInfo: Provide utility to default to null instead of logging an error
Use it to workaround cases when java resolve references some unexpected classes/files, referencing non-physical Dummy.java in particular
This commit is contained in:
@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class JvmPlatformParameters(
|
public class JvmPlatformParameters(
|
||||||
public val moduleByJavaClass: (JavaClass) -> ModuleInfo
|
public val moduleByJavaClass: (JavaClass) -> ModuleInfo?
|
||||||
) : PlatformAnalysisParameters
|
) : PlatformAnalysisParameters
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +68,10 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmPlatformParameters>() {
|
|||||||
// We don't have full control over idea resolve api so we allow for a situation which should not happen in Kotlin.
|
// We don't have full control over idea resolve api so we allow for a situation which should not happen in Kotlin.
|
||||||
// For example, type in a java library can reference a class declared in a source root (is valid but rare case)
|
// For example, type in a java library can reference a class declared in a source root (is valid but rare case)
|
||||||
// Providing a fallback strategy in this case can hide future problems, so we should at least log to be able to diagnose those
|
// Providing a fallback strategy in this case can hide future problems, so we should at least log to be able to diagnose those
|
||||||
val resolverForReferencedModule = resolverForProject.tryGetResolverForModule(referencedClassModule as M)
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val resolverForReferencedModule = referencedClassModule?.let { resolverForProject.tryGetResolverForModule(it as M) }
|
||||||
|
|
||||||
val resolverForModule = resolverForReferencedModule ?: run {
|
val resolverForModule = resolverForReferencedModule ?: run {
|
||||||
LOG.warn("Java referenced $referencedClassModule from $moduleInfo\nReferenced class was: $javaClass\n")
|
LOG.warn("Java referenced $referencedClassModule from $moduleInfo\nReferenced class was: $javaClass\n")
|
||||||
// in case referenced class lies outside of our resolver, resolve the class as if it is inside our module
|
// in case referenced class lies outside of our resolver, resolve the class as if it is inside our module
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ fun createModuleResolverProvider(
|
|||||||
val jvmPlatformParameters = JvmPlatformParameters {
|
val jvmPlatformParameters = JvmPlatformParameters {
|
||||||
javaClass: JavaClass ->
|
javaClass: JavaClass ->
|
||||||
val psiClass = (javaClass as JavaClassImpl).getPsi()
|
val psiClass = (javaClass as JavaClassImpl).getPsi()
|
||||||
psiClass.getModuleInfo()
|
psiClass.getNullableModuleInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
val resolverForProject = analyzerFacade.setupResolverForProject(
|
val resolverForProject = analyzerFacade.setupResolverForProject(
|
||||||
|
|||||||
@@ -31,12 +31,17 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
|
|
||||||
fun PsiElement.getModuleInfo(): IdeaModuleInfo {
|
fun PsiElement.getModuleInfo(): IdeaModuleInfo = this.getModuleInfo { reason ->
|
||||||
fun logAndReturnDefault(message: String): IdeaModuleInfo {
|
LOG.error("Could not find correct module information.\nReason: $reason")
|
||||||
LOG.error("Could not find correct module information.\nReason: $message")
|
NotUnderContentRootModuleInfo
|
||||||
return NotUnderContentRootModuleInfo
|
}.sure { "Defaulting to NotUnderContentRootModuleInfo so null is not possible" }
|
||||||
}
|
|
||||||
|
|
||||||
|
fun PsiElement.getNullableModuleInfo(): IdeaModuleInfo? = this.getModuleInfo { reason ->
|
||||||
|
LOG.warn("Could not find correct module information.\nReason: $reason")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiElement.getModuleInfo(onFailure: (String) -> IdeaModuleInfo?): IdeaModuleInfo? {
|
||||||
if (this is KtLightElement<*, *>) return this.getModuleInfoForLightElement()
|
if (this is KtLightElement<*, *>) return this.getModuleInfoForLightElement()
|
||||||
|
|
||||||
val containingJetFile = (this as? KtElement)?.getContainingFile() as? KtFile
|
val containingJetFile = (this as? KtElement)?.getContainingFile() as? KtFile
|
||||||
@@ -45,7 +50,7 @@ fun PsiElement.getModuleInfo(): IdeaModuleInfo {
|
|||||||
|
|
||||||
val doNotAnalyze = containingJetFile?.doNotAnalyze
|
val doNotAnalyze = containingJetFile?.doNotAnalyze
|
||||||
if (doNotAnalyze != null) {
|
if (doNotAnalyze != null) {
|
||||||
return logAndReturnDefault(
|
return onFailure(
|
||||||
"Should not analyze element: ${getText()} in file ${containingJetFile?.getName() ?: " <no file>"}\n$doNotAnalyze"
|
"Should not analyze element: ${getText()} in file ${containingJetFile?.getName() ?: " <no file>"}\n$doNotAnalyze"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -55,15 +60,14 @@ fun PsiElement.getModuleInfo(): IdeaModuleInfo {
|
|||||||
|
|
||||||
if (containingJetFile is KtCodeFragment) {
|
if (containingJetFile is KtCodeFragment) {
|
||||||
return containingJetFile.getContext()?.getModuleInfo()
|
return containingJetFile.getContext()?.getModuleInfo()
|
||||||
?: logAndReturnDefault("Analyzing code fragment of type ${containingJetFile.javaClass} with no context element\nText:\n${containingJetFile.getText()}")
|
?: onFailure("Analyzing code fragment of type ${containingJetFile.javaClass} with no context element\nText:\n${containingJetFile.getText()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
val project = getProject()
|
|
||||||
val containingFile = getContainingFile()
|
val containingFile = getContainingFile()
|
||||||
?: return logAndReturnDefault("Analyzing element of type $javaClass with no containing file\nText:\n${getText()}")
|
?: return onFailure("Analyzing element of type $javaClass with no containing file\nText:\n${getText()}")
|
||||||
|
|
||||||
val virtualFile = containingFile.getOriginalFile().getVirtualFile()
|
val virtualFile = containingFile.getOriginalFile().getVirtualFile()
|
||||||
?: return logAndReturnDefault("Analyzing non-physical file $containingFile of type ${containingFile.javaClass}")
|
?: return onFailure("Analyzing non-physical file $containingFile of type ${containingFile.javaClass}")
|
||||||
|
|
||||||
return getModuleInfoByVirtualFile(
|
return getModuleInfoByVirtualFile(
|
||||||
project,
|
project,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.idea.caches.resolve
|
package org.jetbrains.kotlin.idea.caches.resolve
|
||||||
|
|
||||||
import com.intellij.psi.JavaPsiFacade
|
import com.intellij.psi.JavaPsiFacade
|
||||||
|
import com.intellij.psi.PsiElementFactory
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
@@ -36,4 +37,10 @@ public class CustomModuleInfoTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
Assert.assertEquals("Members of decompiled class should have the same module info", classModuleInfo, it.getModuleInfo())
|
Assert.assertEquals("Members of decompiled class should have the same module info", classModuleInfo, it.getModuleInfo())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testModuleInfoForPsiCreatedByJavaPsiFactory() {
|
||||||
|
val dummyClass = PsiElementFactory.SERVICE.getInstance(project).createClass("A")
|
||||||
|
val moduleInfo = dummyClass.getNullableModuleInfo()
|
||||||
|
Assert.assertEquals("Should be null for psi created by factory", null, moduleInfo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user