Light classes: Fix getTextOffset() and getTextRange() for property accessors

Before this commit, getTextOffset() and getTextRange() coming from the super class, returned numbers for the property, not for its accessor. This commit fixes the inconsistency.
This commit is contained in:
Yan Zhulanow
2019-07-03 18:03:42 +09:00
parent 7078302e6c
commit 36e1149e51
6 changed files with 98 additions and 17 deletions
@@ -51,6 +51,7 @@ interface LightMemberOrigin : LightElementOrigin {
override val originalElement: KtDeclaration? override val originalElement: KtDeclaration?
override val originKind: JvmDeclarationOriginKind override val originKind: JvmDeclarationOriginKind
val parametersForJvmOverloads: List<KtParameter?>? get() = null val parametersForJvmOverloads: List<KtParameter?>? get() = null
val auxiliaryOriginalElement: KtDeclaration? get() = null
fun isEquivalentTo(other: LightMemberOrigin?): Boolean fun isEquivalentTo(other: LightMemberOrigin?): Boolean
fun copy(): LightMemberOrigin fun copy(): LightMemberOrigin
@@ -59,7 +60,8 @@ interface LightMemberOrigin : LightElementOrigin {
data class LightMemberOriginForDeclaration( data class LightMemberOriginForDeclaration(
override val originalElement: KtDeclaration, override val originalElement: KtDeclaration,
override val originKind: JvmDeclarationOriginKind, override val originKind: JvmDeclarationOriginKind,
override val parametersForJvmOverloads: List<KtParameter?>? = null override val parametersForJvmOverloads: List<KtParameter?>? = null,
override val auxiliaryOriginalElement: KtDeclaration? = null
) : LightMemberOrigin { ) : LightMemberOrigin {
override fun isEquivalentTo(other: LightMemberOrigin?): Boolean { override fun isEquivalentTo(other: LightMemberOrigin?): Boolean {
if (other !is LightMemberOriginForDeclaration) return false if (other !is LightMemberOriginForDeclaration) return false
@@ -11,6 +11,7 @@ import com.intellij.psi.impl.light.LightMethodBuilder
import com.intellij.psi.impl.light.LightModifierList import com.intellij.psi.impl.light.LightModifierList
import com.intellij.psi.impl.light.LightParameterListBuilder import com.intellij.psi.impl.light.LightParameterListBuilder
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
@@ -32,6 +33,7 @@ import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_OVERLOADS_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.STRICTFP_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.STRICTFP_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
internal class UltraLightMembersCreator( internal class UltraLightMembersCreator(
private val containingClass: KtLightClass, private val containingClass: KtLightClass,
@@ -364,9 +366,16 @@ internal class UltraLightMembersCreator(
val result = arrayListOf<KtLightMethod>() val result = arrayListOf<KtLightMethod>()
if (needsAccessor(ktGetter)) { if (needsAccessor(ktGetter)) {
val getterName = computeMethodName(ktGetter ?: declaration, JvmAbi.getterName(propertyName), MethodType.GETTER) val auxiliaryOrigin = ktGetter ?: declaration
val getterPrototype = lightMethod(getterName, ktGetter ?: declaration, onlyJvmStatic || forceStatic) val lightMemberOrigin = LightMemberOriginForDeclaration(
val getterWrapper = KtUltraLightMethodForSourceDeclaration(getterPrototype, declaration, support, containingClass) originalElement = declaration,
originKind = JvmDeclarationOriginKind.OTHER,
auxiliaryOriginalElement = auxiliaryOrigin
)
val getterName = computeMethodName(auxiliaryOrigin, JvmAbi.getterName(propertyName), MethodType.GETTER)
val getterPrototype = lightMethod(getterName, auxiliaryOrigin, onlyJvmStatic || forceStatic)
val getterWrapper = KtUltraLightMethodForSourceDeclaration(getterPrototype, lightMemberOrigin, support, containingClass)
val getterType: PsiType by lazyPub { methodReturnType(declaration, getterWrapper, isSuspendFunction = false) } val getterType: PsiType by lazyPub { methodReturnType(declaration, getterWrapper, isSuspendFunction = false) }
getterPrototype.setMethodReturnType { getterType } getterPrototype.setMethodReturnType { getterType }
addReceiverParameter(declaration, getterWrapper) addReceiverParameter(declaration, getterWrapper)
@@ -374,10 +383,17 @@ internal class UltraLightMembersCreator(
} }
if (mutable && needsAccessor(ktSetter)) { if (mutable && needsAccessor(ktSetter)) {
val setterName = computeMethodName(ktSetter ?: declaration, JvmAbi.setterName(propertyName), MethodType.SETTER) val auxiliaryOrigin = ktSetter ?: declaration
val setterPrototype = lightMethod(setterName, ktSetter ?: declaration, onlyJvmStatic || forceStatic) val lightMemberOrigin = LightMemberOriginForDeclaration(
originalElement = declaration,
originKind = JvmDeclarationOriginKind.OTHER,
auxiliaryOriginalElement = auxiliaryOrigin
)
val setterName = computeMethodName(auxiliaryOrigin, JvmAbi.setterName(propertyName), MethodType.SETTER)
val setterPrototype = lightMethod(setterName, auxiliaryOrigin, onlyJvmStatic || forceStatic)
.setMethodReturnType(PsiType.VOID) .setMethodReturnType(PsiType.VOID)
val setterWrapper = KtUltraLightMethodForSourceDeclaration(setterPrototype, declaration, support, containingClass) val setterWrapper = KtUltraLightMethodForSourceDeclaration(setterPrototype, lightMemberOrigin, support, containingClass)
addReceiverParameter(declaration, setterWrapper) addReceiverParameter(declaration, setterWrapper)
val setterParameter = ktSetter?.parameter val setterParameter = ktSetter?.parameter
setterPrototype.addParameter( setterPrototype.addParameter(
@@ -11,6 +11,7 @@ import com.intellij.psi.impl.PsiSuperMethodImplUtil
import com.intellij.psi.impl.light.LightMethodBuilder import com.intellij.psi.impl.light.LightMethodBuilder
import com.intellij.psi.impl.light.LightTypeParameterListBuilder import com.intellij.psi.impl.light.LightTypeParameterListBuilder
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod import com.intellij.psi.util.MethodSignatureBackedByPsiMethod
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.builder.MemberIndex import org.jetbrains.kotlin.asJava.builder.MemberIndex
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
@@ -27,14 +28,12 @@ import org.jetbrains.kotlin.types.KotlinType
internal abstract class KtUltraLightMethod( internal abstract class KtUltraLightMethod(
internal val delegate: LightMethodBuilder, internal val delegate: LightMethodBuilder,
closestDeclarationForOrigin: KtDeclaration?, lightMemberOrigin: LightMemberOrigin?,
protected val support: KtUltraLightSupport, protected val support: KtUltraLightSupport,
containingClass: KtLightClass containingClass: KtLightClass
) : KtLightMethodImpl( ) : KtLightMethodImpl(
{ delegate }, { delegate },
closestDeclarationForOrigin?.let { lightMemberOrigin,
LightMemberOriginForDeclaration(it, JvmDeclarationOriginKind.OTHER)
},
containingClass containingClass
), KtUltraLightElementWithNullabilityAnnotation<KtDeclaration, PsiMethod> { ), KtUltraLightElementWithNullabilityAnnotation<KtDeclaration, PsiMethod> {
@@ -103,15 +102,22 @@ internal abstract class KtUltraLightMethod(
internal class KtUltraLightMethodForSourceDeclaration( internal class KtUltraLightMethodForSourceDeclaration(
delegate: LightMethodBuilder, delegate: LightMethodBuilder,
declaration: KtDeclaration, lightMemberOrigin: LightMemberOrigin?,
support: KtUltraLightSupport, support: KtUltraLightSupport,
containingClass: KtLightClass containingClass: KtLightClass
) : KtUltraLightMethod( ) : KtUltraLightMethod(
delegate, delegate,
declaration, lightMemberOrigin,
support, support,
containingClass containingClass
) { ) {
constructor(
delegate: LightMethodBuilder,
declaration: KtDeclaration,
support: KtUltraLightSupport,
containingClass: KtLightClass
) : this(delegate, LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER), support, containingClass)
override val kotlinTypeForNullabilityAnnotation: KotlinType? override val kotlinTypeForNullabilityAnnotation: KotlinType?
get() = kotlinOrigin?.getKotlinType() get() = kotlinOrigin?.getKotlinType()
@@ -128,12 +134,12 @@ internal class KtUltraLightMethodForSourceDeclaration(
internal class KtUltraLightMethodForDescriptor( internal class KtUltraLightMethodForDescriptor(
private val descriptor: FunctionDescriptor, private val descriptor: FunctionDescriptor,
delegate: LightMethodBuilder, delegate: LightMethodBuilder,
closestDeclarationForOrigin: KtDeclaration?, lightMemberOrigin: LightMemberOrigin?,
support: KtUltraLightSupport, support: KtUltraLightSupport,
containingClass: KtUltraLightClass containingClass: KtUltraLightClass
) : KtUltraLightMethod( ) : KtUltraLightMethod(
delegate, delegate,
closestDeclarationForOrigin, lightMemberOrigin,
support, support,
containingClass containingClass
) { ) {
@@ -18,6 +18,7 @@ import com.intellij.psi.impl.light.LightParameterListBuilder
import com.intellij.util.BitUtil.isSet import com.intellij.util.BitUtil.isSet
import com.intellij.util.containers.ContainerUtil import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -38,6 +39,7 @@ import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.replace import org.jetbrains.kotlin.types.replace
@@ -217,7 +219,8 @@ fun KtUltraLightClass.createGeneratedMethodFromDescriptor(
?: DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtDeclaration ?: DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtDeclaration
?: kotlinOrigin ?: kotlinOrigin
val wrapper = KtUltraLightMethodForDescriptor(descriptor, lightMethod, kotlinOrigin, support, this) val lightMemberOrigin = LightMemberOriginForDeclaration(kotlinOrigin, JvmDeclarationOriginKind.OTHER)
val wrapper = KtUltraLightMethodForDescriptor(descriptor, lightMethod, lightMemberOrigin, support, this)
descriptor.extensionReceiverParameter?.let { receiver -> descriptor.extensionReceiverParameter?.let { receiver ->
lightMethod.addParameter(KtUltraLightParameterForDescriptor(receiver, kotlinOrigin, support, wrapper)) lightMethod.addParameter(KtUltraLightParameterForDescriptor(receiver, kotlinOrigin, support, wrapper))
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.asJava.elements package org.jetbrains.kotlin.asJava.elements
import com.intellij.openapi.util.TextRange
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.compiled.ClsTypeElementImpl import com.intellij.psi.impl.compiled.ClsTypeElementImpl
import com.intellij.psi.scope.PsiScopeProcessor import com.intellij.psi.scope.PsiScopeProcessor
@@ -187,11 +188,33 @@ open class KtLightMethodImpl protected constructor(
} }
} }
override fun getTextOffset(): Int {
val auxiliaryOrigin = lightMemberOrigin?.auxiliaryOriginalElement
if (auxiliaryOrigin is KtPropertyAccessor) {
return auxiliaryOrigin.textOffset
}
return super.getTextOffset()
}
override fun getTextRange(): TextRange {
val auxiliaryOrigin = lightMemberOrigin?.auxiliaryOriginalElement
if (auxiliaryOrigin is KtPropertyAccessor) {
return auxiliaryOrigin.textRange
}
return super.getTextRange()
}
companion object Factory { companion object Factory {
private fun adjustMethodOrigin(origin: LightMemberOriginForDeclaration?): LightMemberOriginForDeclaration? { private fun adjustMethodOrigin(origin: LightMemberOriginForDeclaration?): LightMemberOriginForDeclaration? {
val originalElement = origin?.originalElement val originalElement = origin?.originalElement
if (originalElement is KtPropertyAccessor) { if (originalElement is KtPropertyAccessor) {
return origin.copy(originalElement.getStrictParentOfType<KtProperty>()!!, origin.originKind) return origin.copy(
originalElement = originalElement.getStrictParentOfType<KtProperty>()!!,
originKind = origin.originKind,
auxiliaryOriginalElement = originalElement
)
} }
return origin return origin
} }
@@ -7,8 +7,10 @@ package org.jetbrains.kotlin.idea.lightClasses
import com.intellij.psi.PsiMethod import com.intellij.psi.PsiMethod
import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.asJava.classes.KtLightClass
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
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -33,6 +35,35 @@ class LightClassBehaviorTest : KotlinLightCodeInsightFixtureTestCase() {
assert(offset == range.startOffset) assert(offset == range.startOffset)
} }
fun testPropertyAccessorOffsets() {
myFixture.configureByText(
"test.kt", """
class A {
var a: Int
get() = 5
set(v) {}
}
""".trimIndent()
)
val aClass = myFixture.javaFacade.findClass("A") as KtLightClass
val getAMethod = aClass.findMethodsByName("getA").single() as PsiMethod
val setAMethod = aClass.findMethodsByName("setA").single() as PsiMethod
val ktClass = aClass.kotlinOrigin!!
val ktProperty = ktClass.declarations.filterIsInstance<KtProperty>().single()
assert(getAMethod.textOffset != setAMethod.textOffset)
assert(getAMethod.textOffset > 0)
assert(getAMethod.textOffset != ktProperty.textOffset)
assert(getAMethod.textOffset == getAMethod.textRange.startOffset)
assert(setAMethod.textOffset > 0)
assert(setAMethod.textOffset != ktProperty.textOffset)
assert(setAMethod.textOffset == setAMethod.textRange.startOffset)
}
override fun getProjectDescriptor(): LightProjectDescriptor { override fun getProjectDescriptor(): LightProjectDescriptor {
return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
} }