Create dummy method for light class without reformat (EA-115803)

This commit is contained in:
Nikolay Krasko
2018-05-08 14:32:55 +03:00
parent c9f31099f2
commit 9e2412b887
@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.idea.caches.lightClasses
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElementFactory
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiType
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.impl.light.AbstractLightClass
import com.intellij.psi.impl.light.LightMethod
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.LightClassInheritanceHelper
import org.jetbrains.kotlin.asJava.elements.KtLightElement
@@ -32,13 +32,14 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.resolve.DescriptorUtils
import javax.swing.Icon
// Used as a placeholder when actual light class does not exist (expect-classes, for example)
// The main purpose is to allow search of inheritors within hierarchies containing such classes
class KtFakeLightClass(override val kotlinOrigin: KtClassOrObject) :
AbstractLightClass(kotlinOrigin.manager, KotlinLanguage.INSTANCE),
KtLightClass {
private val _delegate by lazy { PsiElementFactory.SERVICE.getInstance(kotlinOrigin.project).createClass("dummy") }
private val _delegate by lazy { DummyJavaPsiFactory.createDummyClass(kotlinOrigin.project) }
private val _containingClass by lazy { kotlinOrigin.containingClassOrObject?.let { KtFakeLightClass(it) } }
override val clsDelegate get() = _delegate
@@ -74,7 +75,7 @@ class KtFakeLightMethod private constructor(
ktClassOrObject: KtClassOrObject
) : LightMethod(
ktDeclaration.manager,
PsiElementFactory.SERVICE.getInstance(ktDeclaration.project).createMethod("dummy", PsiType.VOID),
DummyJavaPsiFactory.createDummyVoidMethod(ktDeclaration.project),
KtFakeLightClass(ktClassOrObject),
KotlinLanguage.INSTANCE
), KtLightElement<KtNamedDeclaration, PsiMethod> {
@@ -84,7 +85,7 @@ class KtFakeLightMethod private constructor(
override fun getName() = ktDeclaration.name ?: ""
override fun getNavigationElement() = ktDeclaration
override fun getIcon(flags: Int) = ktDeclaration.getIcon(flags)
override fun getIcon(flags: Int): Icon? = ktDeclaration.getIcon(flags)
override fun getUseScope() = ktDeclaration.useScope
companion object {
@@ -93,4 +94,32 @@ class KtFakeLightMethod private constructor(
return KtFakeLightMethod(ktDeclaration, ktClassOrObject)
}
}
}
private object DummyJavaPsiFactory {
fun createDummyVoidMethod(project: Project): PsiMethod {
// Can't use PsiElementFactory.createMethod() because of formatting in PsiElementFactoryImpl.
val name = "dummy"
val returnType = PsiType.VOID
val canonicalText = GenericsUtil.getVariableTypeByExpressionType(returnType).getCanonicalText(true)
val file = createDummyJavaFile(project, "class _Dummy_ { public $canonicalText $name() {\n} }")
val klass = file.classes.singleOrNull()
?: throw IncorrectOperationException("Class was not created. Method name: $name; return type: $canonicalText")
return klass.methods.singleOrNull()
?: throw IncorrectOperationException("Method was not created. Method name: $name; return type: $canonicalText")
}
fun createDummyClass(project: Project): PsiClass = PsiElementFactory.SERVICE.getInstance(project).createClass("dummy")
private fun createDummyJavaFile(project: Project, text: String): PsiJavaFile {
return PsiFileFactory.getInstance(project).createFileFromText(
DUMMY_FILE_NAME,
JavaFileType.INSTANCE,
text
) as PsiJavaFile
}
private val DUMMY_FILE_NAME = "_Dummy_." + JavaFileType.INSTANCE.defaultExtension
}