diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt index 56f4977cac0..393c3bfda77 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt @@ -16,13 +16,12 @@ package org.jetbrains.kotlin.asJava.elements -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiField -import com.intellij.psi.PsiNamedElement +import com.intellij.psi.* import com.intellij.psi.impl.PsiVariableEx import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind interface KtLightElement : PsiNamedElement { val kotlinOrigin: T? @@ -30,8 +29,16 @@ interface KtLightElement : PsiNamedElemen val clsDelegate: D } -interface KtLightDeclaration: KtLightElement +interface KtLightDeclaration : KtLightElement -interface KtLightField : PsiField, KtLightDeclaration, PsiVariableEx { +interface KtLightMember : PsiMember, KtLightElement, PsiNameIdentifierOwner, PsiDocCommentOwner { val lightMemberOrigin: LightMemberOrigin? +} + +interface KtLightField : PsiField, KtLightMember, PsiVariableEx + +interface KtLightMethod : PsiAnnotationMethod, KtLightMember { + val isDelegated: Boolean + get() = lightMemberOrigin?.originKind == JvmDeclarationOriginKind.DELEGATION + || lightMemberOrigin?.originKind == JvmDeclarationOriginKind.DELEGATION_TO_DEFAULT_IMPLS } \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt index 6d5c0342d80..e88881bfa4a 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt @@ -16,12 +16,8 @@ package org.jetbrains.kotlin.asJava.elements -import com.intellij.navigation.ItemPresentation -import com.intellij.navigation.ItemPresentationProviders -import com.intellij.openapi.util.TextRange import com.intellij.psi.* import com.intellij.psi.impl.PsiVariableEx -import com.intellij.psi.impl.light.LightElement import com.intellij.util.IncorrectOperationException import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory @@ -30,42 +26,24 @@ import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClassForEnumEntry import org.jetbrains.kotlin.asJava.classes.lazyPub -import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtNamedDeclaration import java.lang.UnsupportedOperationException -// Copied from com.intellij.psi.impl.light.LightField -sealed class KtLightFieldImpl( +sealed class KtLightFieldImpl( override val lightMemberOrigin: LightMemberOrigin?, - computeRealDelegate: () -> T, - private val containingClass: KtLightClass, - private val dummyDelegate: PsiField? -) : LightElement(containingClass.manager, KotlinLanguage.INSTANCE), KtLightField { - private val lightIdentifier by lazyPub { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) } + computeRealDelegate: () -> D, + containingClass: KtLightClass, + dummyDelegate: PsiField? +) : KtLightMemberImpl(computeRealDelegate, lightMemberOrigin, containingClass, dummyDelegate), KtLightField { - override val clsDelegate: T by lazyPub(computeRealDelegate) + override val clsDelegate: D + @Suppress("UNCHECKED_CAST") + get() = super.clsDelegate as D @Throws(IncorrectOperationException::class) override fun setInitializer(initializer: PsiExpression?) = throw IncorrectOperationException("Not supported") - override fun getUseScope() = kotlinOrigin?.useScope ?: super.getUseScope() - - override fun getPresentation(): ItemPresentation? = (kotlinOrigin ?: this).let { ItemPresentationProviders.getItemPresentation(it) } - - override fun getName() = dummyDelegate?.name ?: clsDelegate.name - - override fun getNameIdentifier() = lightIdentifier - - override fun getDocComment() = clsDelegate.docComment - - override fun isDeprecated() = clsDelegate.isDeprecated - - override fun getContainingClass() = containingClass - - override fun getContainingFile() = containingClass.containingFile - override fun getType() = clsDelegate.type override fun getTypeElement() = clsDelegate.typeElement @@ -84,34 +62,12 @@ sealed class KtLightFieldImpl( return this } - private val _modifierList by lazyPub { - if (lightMemberOrigin is LightMemberOriginForDeclaration) - clsDelegate.modifierList?.let { KtLightModifierList(it, this) } - else clsDelegate.modifierList - } - - override fun getModifierList() = _modifierList - - override fun hasModifierProperty(@NonNls name: String) = (dummyDelegate ?: clsDelegate).hasModifierProperty(name) - - override fun getText() = kotlinOrigin?.text ?: "" - - override fun getTextRange() = kotlinOrigin?.textRange ?: TextRange.EMPTY_RANGE - - override fun isValid() = containingClass.isValid - - override fun toString(): String = "${this::class.java.simpleName}:$name" - override fun equals(other: Any?): Boolean = other is KtLightFieldImpl<*> && this.name == other.name && this.containingClass == other.containingClass - override fun hashCode() = 31 * containingClass.hashCode() + (name?.hashCode() ?: 0) - - override val kotlinOrigin: KtDeclaration? get() = lightMemberOrigin?.originalElement - - override fun getNavigationElement() = kotlinOrigin ?: super.getNavigationElement() + override fun hashCode() = 31 * containingClass.hashCode() + name.hashCode() override fun computeConstantValue(visitedVars: MutableSet?): Any? { return (clsDelegate as PsiVariableEx).computeConstantValue(visitedVars) @@ -124,8 +80,6 @@ sealed class KtLightFieldImpl( return super.isEquivalentTo(another) } - override fun isWritable() = kotlinOrigin?.isWritable ?: false - override fun copy() = Factory.create(lightMemberOrigin?.copy(), clsDelegate, containingClass) @@ -134,7 +88,7 @@ sealed class KtLightFieldImpl( computeDelegate: () -> PsiEnumConstant, containingClass: KtLightClass, dummyDelegate: PsiField? - ) : KtLightFieldImpl(origin, computeDelegate , containingClass, dummyDelegate), PsiEnumConstant { + ) : KtLightFieldImpl(origin, computeDelegate, containingClass, dummyDelegate), PsiEnumConstant { private val initializingClass by lazyPub { val kotlinEnumEntry = (lightMemberOrigin as? LightMemberOriginForDeclaration)?.originalElement as? KtEnumEntry if (kotlinEnumEntry != null && kotlinEnumEntry.declarations.isNotEmpty()) { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt new file mode 100644 index 00000000000..2f2410ad617 --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.asJava.elements + +import com.intellij.navigation.ItemPresentation +import com.intellij.navigation.ItemPresentationProviders +import com.intellij.openapi.util.TextRange +import com.intellij.psi.* +import com.intellij.psi.impl.light.LightElement +import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin +import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.classes.lazyPub +import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtNamedDeclaration + +abstract class KtLightMemberImpl( + computeRealDelegate: () -> D, + override val lightMemberOrigin: LightMemberOrigin?, + private val containingClass: KtLightClass, + private val dummyDelegate: D? +) : LightElement(containingClass.manager, KotlinLanguage.INSTANCE), PsiMember, KtLightMember { + override val clsDelegate by lazyPub(computeRealDelegate) + private val lightIdentifier by lazyPub { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) } + + private val _modifierList by lazyPub { + if (lightMemberOrigin is LightMemberOriginForDeclaration) + clsDelegate.modifierList?.let { KtLightModifierList(it, this) } + else clsDelegate.modifierList + } + + override fun hasModifierProperty(name: String) = (dummyDelegate ?: clsDelegate).hasModifierProperty(name) + + override fun getModifierList(): PsiModifierList? = _modifierList + + override fun toString(): String = "${this::class.java.simpleName}:$name" + + override fun getContainingClass() = containingClass + + override fun getContainingFile() = containingClass.containingFile + + override fun getParent(): PsiElement = containingClass + + override fun isValid() = containingClass.isValid + + override fun getName(): String = dummyDelegate?.name ?: clsDelegate.name!! + + override fun getNameIdentifier(): PsiIdentifier = lightIdentifier + + override fun getUseScope() = kotlinOrigin?.useScope ?: super.getUseScope() + + override val kotlinOrigin: KtDeclaration? get() = lightMemberOrigin?.originalElement + + override fun getNavigationElement() = kotlinOrigin ?: super.getNavigationElement() + + override fun getPresentation(): ItemPresentation? = (kotlinOrigin ?: this).let { ItemPresentationProviders.getItemPresentation(it) } + + override fun getText() = kotlinOrigin?.text ?: "" + + override fun getTextRange() = kotlinOrigin?.textRange ?: TextRange.EMPTY_RANGE + + override fun isWritable() = kotlinOrigin?.isWritable ?: false + + override fun getDocComment() = (clsDelegate as PsiDocCommentOwner).docComment + + override fun isDeprecated() = (clsDelegate as PsiDocCommentOwner).isDeprecated +} \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethod.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt similarity index 76% rename from compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethod.kt rename to compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt index 448475f19e8..94eb38c9846 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethod.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt @@ -16,13 +16,8 @@ package org.jetbrains.kotlin.asJava.elements -import com.intellij.core.JavaCoreBundle -import com.intellij.navigation.ItemPresentation -import com.intellij.openapi.util.TextRange import com.intellij.psi.* import com.intellij.psi.impl.compiled.ClsTypeElementImpl -import com.intellij.psi.impl.light.LightElement -import com.intellij.psi.javadoc.PsiDocComment import com.intellij.psi.scope.PsiScopeProcessor import com.intellij.psi.util.* import com.intellij.util.IncorrectOperationException @@ -32,29 +27,17 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.propertyNameByAccessor import org.jetbrains.kotlin.asJava.unwrapped -import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade -import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind - -interface KtLightMethod : PsiAnnotationMethod, KtLightDeclaration { - val lightMethodOrigin: LightMemberOrigin? - val isDelegated: Boolean -} class KtLightMethodImpl private constructor( computeRealDelegate: () -> PsiMethod, - override val lightMethodOrigin: LightMemberOrigin?, - private val containingClass: KtLightClass, + lightMemberOrigin: LightMemberOrigin?, + containingClass: KtLightClass, private val dummyDelegate: PsiMethod? = null -) : LightElement(containingClass.manager, containingClass.language), KtLightMethod { - override val kotlinOrigin: KtDeclaration? get() = lightMethodOrigin?.originalElement as? KtDeclaration - - override val clsDelegate by lazyPub(computeRealDelegate) - - private val lightIdentifier by lazyPub { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) } +) : KtLightMemberImpl(computeRealDelegate, lightMemberOrigin, containingClass, dummyDelegate), KtLightMethod { private val returnTypeElem by lazyPub { val delegateTypeElement = clsDelegate.returnTypeElement as? ClsTypeElementImpl delegateTypeElement?.let { ClsTypeElementImpl(this, it.canonicalText, /*ClsTypeElementImpl.VARIANCE_NONE */ 0.toChar()) } @@ -62,8 +45,6 @@ class KtLightMethodImpl private constructor( private val calculatingReturnType = ThreadLocal() - override fun getContainingClass(): KtLightClass = containingClass - private val paramsList: PsiParameterList by lazyPub { KtLightParameterList(this, dummyDelegate?.parameterList?.parametersCount ?: clsDelegate.parameterList.parametersCount) { clsDelegate.parameterList.parameters.mapIndexed { index, clsParameter -> KtLightParameter(clsParameter, index, this@KtLightMethodImpl) } @@ -74,7 +55,7 @@ class KtLightMethodImpl private constructor( val cacheManager = CachedValuesManager.getManager(clsDelegate.project) cacheManager.createCachedValue( { - val origin = (lightMethodOrigin as? LightMemberOriginForDeclaration)?.originalElement + val origin = (lightMemberOrigin as? LightMemberOriginForDeclaration)?.originalElement val list = if (origin != null) { if (origin is KtClassOrObject) { KotlinLightTypeParameterListBuilder(manager) @@ -91,16 +72,6 @@ class KtLightMethodImpl private constructor( ) } - override fun getNavigationElement(): PsiElement = kotlinOrigin?.navigationElement ?: super.getNavigationElement() - override fun getPresentation(): ItemPresentation? = kotlinOrigin?.presentation ?: super.getPresentation() - override fun getParent(): PsiElement = containingClass - override fun getText() = kotlinOrigin?.text ?: "" - override fun getTextRange() = kotlinOrigin?.textRange ?: TextRange.EMPTY_RANGE - - override val isDelegated: Boolean - get() = lightMethodOrigin?.originKind == JvmDeclarationOriginKind.DELEGATION - || lightMethodOrigin?.originKind == JvmDeclarationOriginKind.DELEGATION_TO_DEFAULT_IMPLS - override fun accept(visitor: PsiElementVisitor) { if (visitor is JavaElementVisitor) { visitor.visitMethod(this) @@ -136,31 +107,22 @@ class KtLightMethodImpl private constructor( } ?: throwCanNotModify() } - private fun throwCanNotModify(): Nothing { - throw IncorrectOperationException(JavaCoreBundle.message("psi.error.attempt.to.edit.class.file")) - } - - private val _modifierList by lazyPub { - if (lightMethodOrigin is LightMemberOriginForDeclaration) - KtLightModifierList(clsDelegate.modifierList, this) - else clsDelegate.modifierList - } + // TODO: add message + private fun throwCanNotModify(): Nothing = throw IncorrectOperationException() override fun getModifierList(): PsiModifierList { if (calculatingReturnType.get() == true) { return KotlinJavaPsiFacade.getInstance(project).emptyModifierList } - return _modifierList + return super.getModifierList()!! } - override fun getNameIdentifier() = lightIdentifier - override fun getParameterList() = paramsList override fun getTypeParameterList() = typeParamsList.value override fun getTypeParameters(): Array = - typeParameterList?.let { it.typeParameters } ?: PsiTypeParameter.EMPTY_ARRAY + typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY override fun getSignature(substitutor: PsiSubstitutor): MethodSignature { if (substitutor == PsiSubstitutor.EMPTY) { @@ -170,13 +132,9 @@ class KtLightMethodImpl private constructor( } override fun copy(): PsiElement { - return Factory.create(clsDelegate, lightMethodOrigin?.copy(), containingClass) + return Factory.create(clsDelegate, lightMemberOrigin?.copy(), containingClass) } - override fun getUseScope() = kotlinOrigin?.useScope ?: super.getUseScope() - - override fun getLanguage() = KotlinLanguage.INSTANCE - override fun processDeclarations(processor: PsiScopeProcessor, state: ResolveState, lastParent: PsiElement?, place: PsiElement): Boolean { return typeParameters.all { processor.execute(it, state) } } @@ -200,12 +158,10 @@ class KtLightMethodImpl private constructor( other is KtLightMethodImpl && this.name == other.name && this.containingClass == other.containingClass && - this.lightMethodOrigin == other.lightMethodOrigin && + this.lightMemberOrigin == other.lightMemberOrigin && this._memberIndex == other._memberIndex - override fun hashCode(): Int = ((getName().hashCode() * 31 + (lightMethodOrigin?.hashCode() ?: 0)) * 31 + containingClass.hashCode()) * 31 + (_memberIndex?.hashCode() ?: 0) - - override fun toString(): String = "${this::class.java.simpleName}:$name" + override fun hashCode(): Int = ((getName().hashCode() * 31 + (lightMemberOrigin?.hashCode() ?: 0)) * 31 + containingClass.hashCode()) * 31 + (_memberIndex?.hashCode() ?: 0) override fun getDefaultValue() = (clsDelegate as? PsiAnnotationMethod)?.defaultValue @@ -253,10 +209,6 @@ class KtLightMethodImpl private constructor( } } - override fun getName() = dummyDelegate?.name ?: clsDelegate.name - - override fun hasModifierProperty(name: String) = (dummyDelegate ?: clsDelegate).hasModifierProperty(name) - override fun getThrowsList() = clsDelegate.throwsList override fun hasTypeParameters() = clsDelegate.hasTypeParameters() @@ -267,14 +219,10 @@ class KtLightMethodImpl private constructor( override fun getHierarchicalMethodSignature() = clsDelegate.hierarchicalMethodSignature - override fun getDocComment() = clsDelegate.docComment - override fun findSuperMethodSignaturesIncludingStatic(checkAccess: Boolean) = clsDelegate.findSuperMethodSignaturesIncludingStatic(checkAccess) override fun getBody() = null - override fun isDeprecated() = clsDelegate.isDeprecated - override fun findDeepestSuperMethod() = clsDelegate.findDeepestSuperMethod() override fun findDeepestSuperMethods() = clsDelegate.findDeepestSuperMethods() @@ -284,10 +232,6 @@ class KtLightMethodImpl private constructor( override fun findSuperMethods(checkAccess: Boolean) = clsDelegate.findSuperMethods(checkAccess) override fun findSuperMethods(parentClass: PsiClass?) = clsDelegate.findSuperMethods(parentClass) - - override fun getContainingFile() = parent.containingFile - - override fun isValid() = containingClass.isValid } fun KtLightMethod.isTraitFakeOverride(): Boolean { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightParameter.java b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightParameter.java index ead19724b00..15e9f56d838 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightParameter.java +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightParameter.java @@ -53,7 +53,7 @@ public class KtLightParameter extends LightParameter implements KtLightDeclarati this.index = index; this.method = method; - if (method.getLightMethodOrigin() instanceof LightMemberOriginForDeclaration) { + if (method.getLightMemberOrigin() instanceof LightMemberOriginForDeclaration) { this.modifierList = new KtLightModifierListWithExplicitModifiers(this, ArrayUtil.EMPTY_STRING_ARRAY) { @Override public PsiAnnotationOwner getDelegate() { diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/KotlinShortNamesCacheTest.kt b/idea/tests/org/jetbrains/kotlin/idea/caches/KotlinShortNamesCacheTest.kt index 45492eef3f6..94b0d407118 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/KotlinShortNamesCacheTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/KotlinShortNamesCacheTest.kt @@ -105,7 +105,7 @@ class KotlinShortNamesCacheTest : KotlinCodeInsightTestCase() { = a.map { "${(it as KtLightMethod).clsDelegate.getKotlinFqName()} static=${it.hasModifierProperty(PsiModifier.STATIC)}" }.joinToString("\n") fun accessorArrayDebugToString(a: Array) - = a.map { "${(it as KtLightMethod).clsDelegate.getKotlinFqName()} property=${(it.lightMethodOrigin?.originalElement as KtProperty).fqName} static=${it.hasModifierProperty(PsiModifier.STATIC)}" }.joinToString("\n") + = a.map { "${(it as KtLightMethod).clsDelegate.getKotlinFqName()} property=${(it.lightMemberOrigin?.originalElement as KtProperty).fqName} static=${it.hasModifierProperty(PsiModifier.STATIC)}" }.joinToString("\n") fun checkMethodFound(methods: Array, stringFqName: String, static: Boolean) { assertNotNull("Method $stringFqName with static=$static not found\n" + methodArrayDebugToString(methods), @@ -191,7 +191,7 @@ class KotlinShortNamesCacheTest : KotlinCodeInsightTestCase() { methods.find { stringFqName == (it as KtLightMethod).clsDelegate.getKotlinFqName().toString() && - (it.lightMethodOrigin?.originalElement as KtProperty).fqName?.asString() == propertyFqName + (it.lightMemberOrigin?.originalElement as KtProperty).fqName?.asString() == propertyFqName && it.hasModifierProperty(PsiModifier.STATIC) == static })