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 originKind: JvmDeclarationOriginKind
val parametersForJvmOverloads: List<KtParameter?>? get() = null
val auxiliaryOriginalElement: KtDeclaration? get() = null
fun isEquivalentTo(other: LightMemberOrigin?): Boolean
fun copy(): LightMemberOrigin
@@ -59,7 +60,8 @@ interface LightMemberOrigin : LightElementOrigin {
data class LightMemberOriginForDeclaration(
override val originalElement: KtDeclaration,
override val originKind: JvmDeclarationOriginKind,
override val parametersForJvmOverloads: List<KtParameter?>? = null
override val parametersForJvmOverloads: List<KtParameter?>? = null,
override val auxiliaryOriginalElement: KtDeclaration? = null
) : LightMemberOrigin {
override fun isEquivalentTo(other: LightMemberOrigin?): Boolean {
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.LightParameterListBuilder
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.KtLightMethod
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.STRICTFP_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(
private val containingClass: KtLightClass,
@@ -364,9 +366,16 @@ internal class UltraLightMembersCreator(
val result = arrayListOf<KtLightMethod>()
if (needsAccessor(ktGetter)) {
val getterName = computeMethodName(ktGetter ?: declaration, JvmAbi.getterName(propertyName), MethodType.GETTER)
val getterPrototype = lightMethod(getterName, ktGetter ?: declaration, onlyJvmStatic || forceStatic)
val getterWrapper = KtUltraLightMethodForSourceDeclaration(getterPrototype, declaration, support, containingClass)
val auxiliaryOrigin = ktGetter ?: declaration
val lightMemberOrigin = LightMemberOriginForDeclaration(
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) }
getterPrototype.setMethodReturnType { getterType }
addReceiverParameter(declaration, getterWrapper)
@@ -374,10 +383,17 @@ internal class UltraLightMembersCreator(
}
if (mutable && needsAccessor(ktSetter)) {
val setterName = computeMethodName(ktSetter ?: declaration, JvmAbi.setterName(propertyName), MethodType.SETTER)
val setterPrototype = lightMethod(setterName, ktSetter ?: declaration, onlyJvmStatic || forceStatic)
val auxiliaryOrigin = ktSetter ?: declaration
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)
val setterWrapper = KtUltraLightMethodForSourceDeclaration(setterPrototype, declaration, support, containingClass)
val setterWrapper = KtUltraLightMethodForSourceDeclaration(setterPrototype, lightMemberOrigin, support, containingClass)
addReceiverParameter(declaration, setterWrapper)
val setterParameter = ktSetter?.parameter
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.LightTypeParameterListBuilder
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.MemberIndex
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
@@ -27,14 +28,12 @@ import org.jetbrains.kotlin.types.KotlinType
internal abstract class KtUltraLightMethod(
internal val delegate: LightMethodBuilder,
closestDeclarationForOrigin: KtDeclaration?,
lightMemberOrigin: LightMemberOrigin?,
protected val support: KtUltraLightSupport,
containingClass: KtLightClass
) : KtLightMethodImpl(
{ delegate },
closestDeclarationForOrigin?.let {
LightMemberOriginForDeclaration(it, JvmDeclarationOriginKind.OTHER)
},
lightMemberOrigin,
containingClass
), KtUltraLightElementWithNullabilityAnnotation<KtDeclaration, PsiMethod> {
@@ -103,15 +102,22 @@ internal abstract class KtUltraLightMethod(
internal class KtUltraLightMethodForSourceDeclaration(
delegate: LightMethodBuilder,
declaration: KtDeclaration,
lightMemberOrigin: LightMemberOrigin?,
support: KtUltraLightSupport,
containingClass: KtLightClass
) : KtUltraLightMethod(
delegate,
declaration,
lightMemberOrigin,
support,
containingClass
) {
constructor(
delegate: LightMethodBuilder,
declaration: KtDeclaration,
support: KtUltraLightSupport,
containingClass: KtLightClass
) : this(delegate, LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER), support, containingClass)
override val kotlinTypeForNullabilityAnnotation: KotlinType?
get() = kotlinOrigin?.getKotlinType()
@@ -128,12 +134,12 @@ internal class KtUltraLightMethodForSourceDeclaration(
internal class KtUltraLightMethodForDescriptor(
private val descriptor: FunctionDescriptor,
delegate: LightMethodBuilder,
closestDeclarationForOrigin: KtDeclaration?,
lightMemberOrigin: LightMemberOrigin?,
support: KtUltraLightSupport,
containingClass: KtUltraLightClass
) : KtUltraLightMethod(
delegate,
closestDeclarationForOrigin,
lightMemberOrigin,
support,
containingClass
) {
@@ -18,6 +18,7 @@ import com.intellij.psi.impl.light.LightParameterListBuilder
import com.intellij.util.BitUtil.isSet
import com.intellij.util.containers.ContainerUtil
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.KtLightMethod
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.constants.EnumValue
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.TypeProjectionImpl
import org.jetbrains.kotlin.types.replace
@@ -217,7 +219,8 @@ fun KtUltraLightClass.createGeneratedMethodFromDescriptor(
?: DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtDeclaration
?: 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 ->
lightMethod.addParameter(KtUltraLightParameterForDescriptor(receiver, kotlinOrigin, support, wrapper))
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.asJava.elements
import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
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 {
private fun adjustMethodOrigin(origin: LightMemberOriginForDeclaration?): LightMemberOriginForDeclaration? {
val originalElement = origin?.originalElement
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
}
@@ -7,8 +7,10 @@ package org.jetbrains.kotlin.idea.lightClasses
import com.intellij.psi.PsiMethod
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.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
import org.junit.runner.RunWith
@@ -33,6 +35,35 @@ class LightClassBehaviorTest : KotlinLightCodeInsightFixtureTestCase() {
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 {
return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
}