diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightElementOrigin.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightElementOrigin.kt index e30bdf732a4..156bd910352 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightElementOrigin.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightElementOrigin.kt @@ -51,6 +51,7 @@ interface LightMemberOrigin : LightElementOrigin { override val originalElement: KtDeclaration? override val originKind: JvmDeclarationOriginKind val parametersForJvmOverloads: List? 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? = null + override val parametersForJvmOverloads: List? = null, + override val auxiliaryOriginalElement: KtDeclaration? = null ) : LightMemberOrigin { override fun isEquivalentTo(other: LightMemberOrigin?): Boolean { if (other !is LightMemberOriginForDeclaration) return false diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMembersCreator.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMembersCreator.kt index db9535afaf7..dcfb4e825c4 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMembersCreator.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMembersCreator.kt @@ -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() 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( diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt index f8a040ba0c1..c93480750d1 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt @@ -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 { @@ -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 ) { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt index 375fc9a501d..9c4a1432543 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt @@ -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)) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt index 936b825a4ed..6feaf2ce096 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt @@ -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()!!, origin.originKind) + return origin.copy( + originalElement = originalElement.getStrictParentOfType()!!, + originKind = origin.originKind, + auxiliaryOriginalElement = originalElement + ) } return origin } diff --git a/idea/tests/org/jetbrains/kotlin/idea/lightClasses/LightClassBehaviorTest.kt b/idea/tests/org/jetbrains/kotlin/idea/lightClasses/LightClassBehaviorTest.kt index ad63fce8e89..49e19e1c176 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/lightClasses/LightClassBehaviorTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/lightClasses/LightClassBehaviorTest.kt @@ -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().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 }