diff --git a/compiler/frontend/src/org/jetbrains/kotlin/extensions/DeclarationAttributeAltererExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/extensions/DeclarationAttributeAltererExtension.kt index a84ea1339ab..5b539609204 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/extensions/DeclarationAttributeAltererExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/extensions/DeclarationAttributeAltererExtension.kt @@ -36,7 +36,6 @@ interface DeclarationAttributeAltererExtension { declaration: DeclarationDescriptor?, containingDeclaration: DeclarationDescriptor?, currentModality: Modality, - bindingContext: BindingContext, isImplicitModality: Boolean ): Modality? = null @@ -48,10 +47,9 @@ interface DeclarationAttributeAltererExtension { modifierListOwner: KtModifierListOwner, declaration: DeclarationDescriptor?, containingDeclaration: DeclarationDescriptor?, - currentModality: Modality, - bindingContext: BindingContext + currentModality: Modality ): Modality? { - return refineDeclarationModality(modifierListOwner, declaration, containingDeclaration, currentModality, bindingContext, false) + return refineDeclarationModality(modifierListOwner, declaration, containingDeclaration, currentModality, false) } fun shouldConvertFirstSAMParameterToReceiver(function: FunctionDescriptor): Boolean = false diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java index c1114374c8f..99dabe061a8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -88,7 +88,7 @@ public class ModifiersChecker { DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, modifierListOwner); for (DeclarationAttributeAltererExtension extension : extensions) { Modality newModality = extension.refineDeclarationModality( - modifierListOwner, descriptor, containingDescriptor, modality, bindingContext, false); + modifierListOwner, descriptor, containingDescriptor, modality, false); if (newModality != null) { modality = newModality; diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt index 3ce55aa15c5..ca7785cdbee 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt @@ -90,7 +90,7 @@ internal open class KtLightClassForAnonymousDeclaration(classOrObject: KtClassOr companion object { fun KtLightClassForSourceDeclaration.getFirstSupertypeFQNameForAnonymousDeclaration(): String { - val descriptor = getDescriptor() ?: return CommonClassNames.JAVA_LANG_OBJECT + val descriptor = descriptor.value ?: return CommonClassNames.JAVA_LANG_OBJECT val superTypes = descriptor.typeConstructor.supertypes diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt index 51e4a121ff0..9dd7ea4896a 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt @@ -42,7 +42,10 @@ import org.jetbrains.kotlin.asJava.elements.KtLightModifierList import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind import org.jetbrains.kotlin.name.FqNameUnsafe @@ -53,6 +56,7 @@ import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.util.isOrdinaryClass import java.util.* import javax.swing.Icon @@ -105,13 +109,12 @@ abstract class KtLightClassForSourceDeclaration( override val lightClassData: LightClassData get() = findLightClassData() - protected open fun findLightClassData() = getLightClassDataHolder(). - findDataForClassOrObject(classOrObject) + protected open fun findLightClassData() = getLightClassDataHolder().findDataForClassOrObject(classOrObject) private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub - fun getDescriptor(): ClassDescriptor? { - return LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor + public val descriptor = lazyPub { + LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor } protected fun getLightClassDataHolder(): LightClassDataHolder.ForClass { @@ -228,7 +231,15 @@ abstract class KtLightClassForSourceDeclaration( if (isAbstract() || isSealed()) { psiModifiers.add(PsiModifier.ABSTRACT) } else if (!(classOrObject.hasModifier(OPEN_KEYWORD) || (classOrObject is KtClass && classOrObject.isEnum()))) { - psiModifiers.add(PsiModifier.FINAL) + // AllOpen can affect on modality of the member. We ought to check if the extension could override the modality + // Resolver will produce correct descriptor corresponding to modality from AllOpen. + // The easiest way to get new modality is to resolve the descriptor + val modifierToAdd = if (kotlinOrigin.isOrdinaryClass && descriptor.value?.modality == Modality.OPEN) { + PsiModifier.OPEN + } else { + PsiModifier.FINAL + } + psiModifiers.add(modifierToAdd) } if (!classOrObject.isTopLevel() && !classOrObject.hasModifier(INNER_KEYWORD)) { @@ -263,13 +274,13 @@ abstract class KtLightClassForSourceDeclaration( LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it } val qualifiedName: String? = if (baseClass is KtLightClassForSourceDeclaration) { - val baseDescriptor = baseClass.getDescriptor() + val baseDescriptor = baseClass.descriptor.value if (baseDescriptor != null) DescriptorUtils.getFqName(baseDescriptor).asString() else null } else { baseClass.qualifiedName } - val thisDescriptor = getDescriptor() + val thisDescriptor = descriptor.value return qualifiedName != null && thisDescriptor != null && checkSuperTypeByFQName(thisDescriptor, qualifiedName, checkDeep) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt index 13e6ebb22de..03738e6dd73 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt @@ -75,8 +75,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor private val _deprecated by lazyPub { classOrObject.isDeprecated(support) } - private val descriptor = lazyPub { getDescriptor() } - override fun isFinal(isFinalByPsi: Boolean) = if (tooComplex) super.isFinal(isFinalByPsi) else isFinalByPsi @Volatile @@ -104,7 +102,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor override fun getModifierList(): PsiModifierList? = _modifierList private fun allSuperTypes() = - getDescriptor()?.typeConstructor?.supertypes.orEmpty() + descriptor.value?.typeConstructor?.supertypes.orEmpty() private fun mapSupertype(supertype: KotlinType, kotlinCollectionAsIs: Boolean = false) = supertype.asPsiType( 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 6d3dcd363e3..d0a6c0b76f9 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.asJava.classes +import com.intellij.lang.Language import com.intellij.psi.* import com.intellij.psi.impl.light.LightMethodBuilder import com.intellij.psi.impl.light.LightModifierList @@ -17,6 +18,7 @@ import org.jetbrains.kotlin.asJava.elements.convertToLightAnnotationMemberValue import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotated +import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens.REIFIED_KEYWORD import org.jetbrains.kotlin.load.java.JvmAbi @@ -26,6 +28,7 @@ import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier +import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi @@ -35,6 +38,7 @@ import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_ 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 +import org.jetbrains.kotlin.util.isOrdinaryClass internal class UltraLightMembersCreator( private val containingClass: KtLightClass, @@ -232,6 +236,69 @@ internal class UltraLightMembersCreator( private fun DeclarationDescriptor.getterIfProperty() = if (this@getterIfProperty is PropertyDescriptor) this@getterIfProperty.getter else this@getterIfProperty + private inner class UltraLightModifierListForMember( + private val declaration: KtDeclaration, + private val accessedProperty: KtProperty?, + private val outerDeclaration: KtDeclaration, + private val forceStatic: Boolean, + private val forcePrivate: Boolean = false + ) : LightModifierList(declaration.manager, declaration.language) { + + override fun hasModifierProperty(name: String): Boolean { + + val modifierResult = hasModifier(name) + + //AllOpen can affect on modality of the member. We ought to check if the extension could override the modality + if (name != PsiModifier.FINAL) return modifierResult + if (!outerDeclaration.isOrdinaryClass) return modifierResult + // Resolver will produce correct descriptor corresponding to modality from AllOpen. + // The easiest way to get new modality is to resolve the descriptor + return (declaration.resolve() as? CallableMemberDescriptor)?.modality == Modality.FINAL + } + + private fun hasModifier(name: String): Boolean { + if (name == PsiModifier.PUBLIC || name == PsiModifier.PROTECTED || name == PsiModifier.PRIVATE) { + if (forcePrivate || declaration.isPrivate() || accessedProperty?.isPrivate() == true) { + return name == PsiModifier.PRIVATE + } + if (declaration.hasModifier(KtTokens.PROTECTED_KEYWORD) || accessedProperty?.hasModifier(KtTokens.PROTECTED_KEYWORD) == true) { + return name == PsiModifier.PROTECTED + } + + if (outerDeclaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) { + when ((outerDeclaration.resolve() as? CallableDescriptor)?.visibility) { + Visibilities.PUBLIC -> return name == PsiModifier.PUBLIC + Visibilities.PRIVATE -> return name == PsiModifier.PRIVATE + Visibilities.PROTECTED -> return name == PsiModifier.PROTECTED + } + } + + return name == PsiModifier.PUBLIC + } + + return when (name) { + PsiModifier.FINAL -> !containingClass.isInterface && outerDeclaration !is KtConstructor<*> && isFinal(outerDeclaration) + PsiModifier.ABSTRACT -> containingClass.isInterface || outerDeclaration.hasModifier(KtTokens.ABSTRACT_KEYWORD) + PsiModifier.STATIC -> forceStatic || containingClassIsNamedObject && (outerDeclaration.isJvmStatic(support) || declaration.isJvmStatic(support)) + PsiModifier.STRICTFP -> declaration is KtFunction && declaration.hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME) + PsiModifier.SYNCHRONIZED -> declaration is KtFunction && declaration.hasAnnotation(SYNCHRONIZED_ANNOTATION_FQ_NAME) + else -> false + } + } + + private fun KtDeclaration.isPrivate() = + hasModifier(KtTokens.PRIVATE_KEYWORD) || this is KtConstructor<*> && containingClassIsSealed || isInlineOnly() + + private fun KtDeclaration.isInlineOnly(): Boolean { + if (this !is KtCallableDeclaration || !hasModifier(KtTokens.INLINE_KEYWORD)) return false + if (annotationEntries.isEmpty()) return false + + val descriptor = resolve() as? CallableMemberDescriptor ?: return false + + return descriptor.isInlineOnly() + } + } + private fun lightMethod( name: String, declaration: KtDeclaration, @@ -247,52 +314,7 @@ internal class UltraLightMembersCreator( return LightMethodBuilder( manager, language, name, LightParameterListBuilder(manager, language), - object : LightModifierList(manager, language) { - override fun hasModifierProperty(name: String): Boolean { - if (name == PsiModifier.PUBLIC || name == PsiModifier.PROTECTED || name == PsiModifier.PRIVATE) { - if (forcePrivate || declaration.isPrivate() || accessedProperty?.isPrivate() == true) { - return name == PsiModifier.PRIVATE - } - if (declaration.hasModifier(KtTokens.PROTECTED_KEYWORD) || accessedProperty?.hasModifier(KtTokens.PROTECTED_KEYWORD) == true) { - return name == PsiModifier.PROTECTED - } - - if (outer.hasModifier(KtTokens.OVERRIDE_KEYWORD)) { - when ((outer.resolve() as? CallableDescriptor)?.visibility) { - Visibilities.PUBLIC -> return name == PsiModifier.PUBLIC - Visibilities.PRIVATE -> return name == PsiModifier.PRIVATE - Visibilities.PROTECTED -> return name == PsiModifier.PROTECTED - } - } - - return name == PsiModifier.PUBLIC - } - - return when (name) { - PsiModifier.FINAL -> !containingClass.isInterface && outer !is KtConstructor<*> && isFinal(outer) - PsiModifier.ABSTRACT -> containingClass.isInterface || outer.hasModifier(KtTokens.ABSTRACT_KEYWORD) - PsiModifier.STATIC -> forceStatic || containingClassIsNamedObject && (outer.isJvmStatic(support) || declaration.isJvmStatic( - support - )) - PsiModifier.STRICTFP -> declaration is KtFunction && declaration.hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME) - PsiModifier.SYNCHRONIZED -> declaration is KtFunction && declaration.hasAnnotation(SYNCHRONIZED_ANNOTATION_FQ_NAME) - else -> false - } - } - - fun KtDeclaration.isPrivate() = - hasModifier(KtTokens.PRIVATE_KEYWORD) || - this is KtConstructor<*> && containingClassIsSealed || isInlineOnly() - - private fun KtDeclaration.isInlineOnly(): Boolean { - if (this !is KtCallableDeclaration || !hasModifier(KtTokens.INLINE_KEYWORD)) return false - if (annotationEntries.isEmpty()) return false - - val descriptor = resolve() as? CallableMemberDescriptor ?: return false - - return descriptor.isInlineOnly() - } - } + UltraLightModifierListForMember(declaration, accessedProperty, outer, forceStatic, forcePrivate) ).setConstructor(declaration is KtConstructor<*>) } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt index b4c73797ea6..5e0358fbfe4 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt @@ -415,7 +415,6 @@ fun KtDeclaration.implicitModality(): KtModifierKeywordToken { descriptor as? ClassDescriptor, containingDescriptor, mapModalityToken(predictedModality), - bindingContext, isImplicitModality = true ) diff --git a/plugins/allopen/allopen-cli/src/AllOpenDeclarationAttributeAltererExtension.kt b/plugins/allopen/allopen-cli/src/AllOpenDeclarationAttributeAltererExtension.kt index 951980e939c..751e81f6ac2 100644 --- a/plugins/allopen/allopen-cli/src/AllOpenDeclarationAttributeAltererExtension.kt +++ b/plugins/allopen/allopen-cli/src/AllOpenDeclarationAttributeAltererExtension.kt @@ -41,7 +41,6 @@ abstract class AbstractAllOpenDeclarationAttributeAltererExtension : Declaration declaration: DeclarationDescriptor?, containingDeclaration: DeclarationDescriptor?, currentModality: Modality, - bindingContext: BindingContext, isImplicitModality: Boolean ): Modality? { if (currentModality != Modality.FINAL) {