Change properties to methods in light class hierarchy

There's a Kotlin-Java-Kotlin hierarchy with an abstract property in a
superclass and its implementation (as a get-method) in the Java subclass, which
caused problems because Kotlin subclass can't have both (different symbols,
same JVM signatures)
This commit is contained in:
Alexander Udalov
2015-02-04 12:03:30 +03:00
parent cafc1ea24d
commit 1c87464695
15 changed files with 35 additions and 24 deletions
@@ -21,5 +21,5 @@ import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.JetClassOrObject
public trait KotlinLightClass : PsiClass, KotlinLightElement<JetClassOrObject, PsiClass> {
val fqName: FqName
public fun getFqName(): FqName
}
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.psi.JetDeclaration
import com.intellij.psi.PsiElement
public trait KotlinLightElement<T : JetDeclaration, D : PsiElement> {
public val origin: T?
public val delegate: D
public fun getOrigin(): T?
public fun getDelegate(): D
}
@@ -34,8 +34,8 @@ import com.intellij.psi.util.MethodSignatureBackedByPsiMethod
open public class KotlinLightMethodForDeclaration(
manager: PsiManager,
override val delegate: PsiMethod,
override val origin: JetDeclaration,
private val delegate: PsiMethod,
private val origin: JetDeclaration,
containingClass: PsiClass
): LightMethod(manager, delegate, containingClass), KotlinLightMethod {
@@ -65,8 +65,12 @@ open public class KotlinLightMethodForDeclaration(
}, false)
}
override fun getNavigationElement() : PsiElement = origin
override fun getOriginalElement() : PsiElement = origin
override fun getNavigationElement(): PsiElement = origin
override fun getOriginalElement(): PsiElement = origin
override fun getDelegate(): PsiMethod = delegate
override fun getOrigin(): JetDeclaration = origin
override fun getParent(): PsiElement? = getContainingClass()
@@ -82,7 +86,7 @@ open public class KotlinLightMethodForDeclaration(
}
override fun isEquivalentTo(another: PsiElement?): Boolean {
if (another is KotlinLightMethod && origin == another.origin) {
if (another is KotlinLightMethod && origin == another.getOrigin()) {
return true
}
@@ -24,11 +24,15 @@ import com.intellij.psi.PsiElement
public class KotlinLightMethodForTraitFakeOverride(
manager: PsiManager,
override val delegate: PsiMethod,
override val origin: JetDeclaration,
private val delegate: PsiMethod,
private val origin: JetDeclaration,
containingClass: PsiClass
) : KotlinLightMethodForDeclaration(manager, delegate, origin, containingClass) {
override fun getDelegate(): PsiMethod = delegate
override fun getOrigin(): JetDeclaration = origin
override fun copy(): PsiElement {
return KotlinLightMethodForTraitFakeOverride(getManager()!!, delegate, origin.copy() as JetDeclaration, getContainingClass()!!)
return KotlinLightMethodForTraitFakeOverride(getManager(), delegate, origin.copy() as JetDeclaration, getContainingClass())
}
}
@@ -97,7 +97,7 @@ public fun JetTypeParameter.toPsiTypeParameters(): List<PsiTypeParameter> {
// Returns original declaration if given PsiElement is a Kotlin light element, and element itself otherwise
public val PsiElement.unwrapped: PsiElement?
get() = if (this is KotlinLightElement<*, *>) origin else this
get() = if (this is KotlinLightElement<*, *>) getOrigin() else this
public val PsiElement.namedUnwrappedElement: PsiNamedElement?
get() = unwrapped?.getNonStrictParentOfType<PsiNamedElement>()
@@ -48,7 +48,7 @@ public object JavaResolveExtension : CacheExtension<(PsiElement) -> Pair<JavaDes
}
fun PsiMethod.getJavaMethodDescriptor(): FunctionDescriptor {
if (this is KotlinLightMethod) throw AssertionError("Light methods are not allowed here: ${origin?.getText()}")
if (this is KotlinLightMethod) throw AssertionError("Light methods are not allowed here: ${getOrigin()?.getText()}")
val resolver = JavaResolveExtension.getResolver(getProject(), this)
val methodDescriptor = when {
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.name.FqName
class KotlinLightClassForDecompiledDeclaration(
private val clsClass: ClsClassImpl,
override val origin: JetClassOrObject?
private val origin: JetClassOrObject?
) : KotlinWrappingLightClass(clsClass.getManager()) {
override fun copy() = this
@@ -38,5 +38,7 @@ class KotlinLightClassForDecompiledDeclaration(
override fun getDelegate() = clsClass
override val fqName: FqName = origin?.getFqName() ?: FqName(clsClass.getQualifiedName())
override fun getOrigin() = origin
override fun getFqName() = origin?.getFqName() ?: FqName(clsClass.getQualifiedName())
}
@@ -111,7 +111,7 @@ private fun KotlinLightElement<*, *>.getModuleInfoForLightElement(): IdeaModuleI
if (this is KotlinLightClassForDecompiledDeclaration) {
return getModuleInfoByVirtualFile(getProject(), getContainingFile().getVirtualFile(), false)
}
val element = origin ?: when (this) {
val element = getOrigin() ?: when (this) {
is FakeLightClassForFileOfPackage -> this.getContainingFile()!!
is KotlinLightClassForPackage -> this.getFiles().first()
else -> throw IllegalStateException("Unknown light class without origin is referenced by IDE lazy resolve: $javaClass")
@@ -140,7 +140,7 @@ fun PsiReference.isPropertyReadOnlyUsage(): Boolean {
val refTarget = resolve()
if (refTarget is KotlinLightMethod) {
val origin = refTarget.origin
val origin = refTarget.getOrigin()
val declaration: JetNamedDeclaration? = when (origin) {
is JetPropertyAccessor -> origin.getNonStrictParentOfType<JetProperty>()
is JetProperty, is JetParameter -> origin as JetNamedDeclaration
@@ -286,7 +286,7 @@ class TypeInstantiationItems(
val parameters = ClassInheritorsSearch.SearchParameters(psiClass, inheritorSearchScope, true, true, false, nameFilter)
for (inheritor in ClassInheritorsSearch.search(parameters)) {
val descriptor = if (inheritor is KotlinLightClass && inheritor !is KotlinLightClassForDecompiledDeclaration) {
val origin = inheritor.origin ?: continue
val origin = inheritor.getOrigin() ?: continue
val declaration = toFromOriginalFileMapper.toSyntheticFile(origin) ?: continue
resolutionFacade.resolveToDescriptor(declaration)
}
@@ -105,7 +105,7 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
}
if (elementAt is KotlinLightClass) {
return getContextElement(elementAt.origin)
return getContextElement(elementAt.getOrigin())
}
val expressionAtOffset = PsiTreeUtil.findElementOfClassAtOffset(elementAt.getContainingFile()!!, elementAt.getTextOffset(), javaClass<JetExpression>(), false)
@@ -78,7 +78,7 @@ public class JetChangeSignatureData(
val overrides = lightMethod?.let { OverridingMethodsSearch.search(it).findAll() } ?: Collections.emptyList()
overrides.map { method ->
if (method is KotlinLightMethod) {
val overridingDeclaration = method.origin
val overridingDeclaration = method.getOrigin()
val overridingDescriptor = overridingDeclaration?.resolveToDescriptor() as FunctionDescriptor
JetFunctionDefinitionUsage<PsiElement>(overridingDeclaration, overridingDescriptor, primaryFunction, null)
}
@@ -36,7 +36,7 @@ public class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() {
}
override fun canProcessElement(element: PsiElement): Boolean {
return element is JetNamedFunction || (element is KotlinLightMethod && element.origin is JetNamedFunction)
return element is JetNamedFunction || (element is KotlinLightMethod && element.getOrigin() is JetNamedFunction)
}
override fun substituteElementToRename(element: PsiElement?, editor: Editor?): PsiElement? {
@@ -50,7 +50,7 @@ public class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() {
val substitutedJavaElement = javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor)
return when (substitutedJavaElement) {
is KotlinLightMethod -> substitutedJavaElement.origin as? JetNamedFunction
is KotlinLightMethod -> substitutedJavaElement.getOrigin() as? JetNamedFunction
else -> substitutedJavaElement
}
}
@@ -210,7 +210,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val typeArguments = convertTypeArguments(expression)
if (target is KotlinLightMethod) {
val origin = target.origin
val origin = target.getOrigin()
val isTopLevel = origin?.getStrictParentOfType<JetClassOrObject>() == null
if (origin is JetProperty || origin is JetPropertyAccessor || origin is JetParameter) {
val property = if (origin is JetPropertyAccessor)
@@ -369,7 +369,7 @@ class TypeConverter(val converter: Converter) {
override fun fromAnnotations(owner: PsiModifierListOwner): Mutability {
if (owner is KotlinLightElement<*, *>) {
val jetDeclaration = owner.origin as? JetCallableDeclaration ?: return Mutability.Default
val jetDeclaration = owner.getOrigin() as? JetCallableDeclaration ?: return Mutability.Default
val descriptor = converter.resolverForConverter.resolveToDescriptor(jetDeclaration) as? CallableDescriptor ?: return Mutability.Default
val type = descriptor.getReturnType() ?: return Mutability.Default
val classDescriptor = TypeUtils.getClassDescriptor(type) ?: return Mutability.Default