Move AllOpen UL support to separate extension
This commit is contained in:
+7
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.asJava
|
package org.jetbrains.kotlin.asJava
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiModifier
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
|
||||||
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
|
||||||
@@ -32,4 +33,10 @@ interface UltraLightClassModifierExtension {
|
|||||||
containingDeclaration: KtUltraLightClass,
|
containingDeclaration: KtUltraLightClass,
|
||||||
fieldsList: MutableList<KtLightField>
|
fieldsList: MutableList<KtLightField>
|
||||||
) = Unit
|
) = Unit
|
||||||
|
|
||||||
|
fun interceptModalityBuilding(
|
||||||
|
declaration: KtDeclaration,
|
||||||
|
descriptor: Lazy<DeclarationDescriptor?>,
|
||||||
|
modifier: String
|
||||||
|
) = modifier
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-7
@@ -42,10 +42,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
|
|||||||
import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList
|
import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList
|
||||||
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
|
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
|
||||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
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.lexer.KtTokens.*
|
||||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
@@ -230,10 +227,12 @@ abstract class KtLightClassForSourceDeclaration(
|
|||||||
if (isAbstract() || isSealed()) {
|
if (isAbstract() || isSealed()) {
|
||||||
psiModifiers.add(PsiModifier.ABSTRACT)
|
psiModifiers.add(PsiModifier.ABSTRACT)
|
||||||
} else if (!(classOrObject.hasModifier(OPEN_KEYWORD) || (classOrObject is KtClass && classOrObject.isEnum()))) {
|
} else if (!(classOrObject.hasModifier(OPEN_KEYWORD) || (classOrObject is KtClass && classOrObject.isEnum()))) {
|
||||||
// AllOpen can affect on modality of the member. We ought to check if the extension could override the modality
|
val descriptor = lazy { getDescriptor() }
|
||||||
// Resolver will produce correct descriptor corresponding to modality from AllOpen.
|
var modifier = PsiModifier.FINAL
|
||||||
// The easiest way to get new modality is to resolve the descriptor
|
project.applyCompilerPlugins {
|
||||||
if (!kotlinOrigin.isOrdinaryClass || getDescriptor()?.modality != Modality.OPEN) {
|
modifier = it.interceptModalityBuilding(kotlinOrigin, descriptor, modifier)
|
||||||
|
}
|
||||||
|
if (modifier == PsiModifier.FINAL) {
|
||||||
psiModifiers.add(PsiModifier.FINAL)
|
psiModifiers.add(PsiModifier.FINAL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
|
|
||||||
fun ArrayList<KtLightField>.updateWithCompilerPlugins() = also {
|
fun ArrayList<KtLightField>.updateWithCompilerPlugins() = also {
|
||||||
val lazyDescriptor = lazy { getDescriptor() }
|
val lazyDescriptor = lazy { getDescriptor() }
|
||||||
applyCompilerPlugins {
|
project.applyCompilerPlugins {
|
||||||
it.interceptFieldsBuilding(
|
it.interceptFieldsBuilding(
|
||||||
declaration = kotlinOrigin,
|
declaration = kotlinOrigin,
|
||||||
descriptor = lazyDescriptor,
|
descriptor = lazyDescriptor,
|
||||||
@@ -309,7 +309,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
addDelegatesToInterfaceMethods(result)
|
addDelegatesToInterfaceMethods(result)
|
||||||
|
|
||||||
val lazyDescriptor = lazy { getDescriptor() }
|
val lazyDescriptor = lazy { getDescriptor() }
|
||||||
applyCompilerPlugins {
|
project.applyCompilerPlugins {
|
||||||
it.interceptMethodsBuilding(
|
it.interceptMethodsBuilding(
|
||||||
declaration = kotlinOrigin,
|
declaration = kotlinOrigin,
|
||||||
descriptor = lazyDescriptor,
|
descriptor = lazyDescriptor,
|
||||||
@@ -321,10 +321,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun applyCompilerPlugins(body: (UltraLightClassModifierExtension) -> Unit) {
|
|
||||||
UltraLightClassModifierExtension.getInstances(project).forEach { body(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val _ownMethods: CachedValue<List<KtLightMethod>> = CachedValuesManager.getManager(project).createCachedValue(
|
private val _ownMethods: CachedValue<List<KtLightMethod>> = CachedValuesManager.getManager(project).createCachedValue(
|
||||||
{
|
{
|
||||||
CachedValueProvider.Result.create(
|
CachedValueProvider.Result.create(
|
||||||
|
|||||||
+7
-6
@@ -246,14 +246,15 @@ internal class UltraLightMembersCreator(
|
|||||||
|
|
||||||
override fun hasModifierProperty(name: String): Boolean {
|
override fun hasModifierProperty(name: String): Boolean {
|
||||||
|
|
||||||
val modifierResult = hasModifier(name)
|
if (name != PsiModifier.FINAL || !outerDeclaration.isOrdinaryClass) return hasModifier(name)
|
||||||
|
|
||||||
//AllOpen can affect on modality of the member. We ought to check if the extension could override the modality
|
//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
|
val descriptor = lazy { declaration.resolve() }
|
||||||
if (!outerDeclaration.isOrdinaryClass) return modifierResult
|
var modifier = PsiModifier.FINAL
|
||||||
// Resolver will produce correct descriptor corresponding to modality from AllOpen.
|
project.applyCompilerPlugins {
|
||||||
// The easiest way to get new modality is to resolve the descriptor
|
modifier = it.interceptModalityBuilding(declaration, descriptor, modifier)
|
||||||
return (declaration.resolve() as? CallableMemberDescriptor)?.modality == Modality.FINAL
|
}
|
||||||
|
return modifier == PsiModifier.FINAL
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasModifier(name: String): Boolean {
|
private fun hasModifier(name: String): Boolean {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.asJava.classes
|
package org.jetbrains.kotlin.asJava.classes
|
||||||
|
|
||||||
import com.google.common.collect.Lists
|
import com.google.common.collect.Lists
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.cache.ModifierFlags
|
import com.intellij.psi.impl.cache.ModifierFlags
|
||||||
import com.intellij.psi.impl.cache.TypeInfo
|
import com.intellij.psi.impl.cache.TypeInfo
|
||||||
@@ -16,6 +17,7 @@ import com.intellij.psi.impl.light.*
|
|||||||
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.UltraLightClassModifierExtension
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
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
|
||||||
@@ -390,5 +392,9 @@ fun KotlinType.tryResolveMarkerInterfaceFQName(): String? {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal inline fun Project.applyCompilerPlugins(body: (UltraLightClassModifierExtension) -> Unit) {
|
||||||
|
UltraLightClassModifierExtension.getInstances(this).forEach { body(it) }
|
||||||
|
}
|
||||||
|
|
||||||
internal fun <L : Any> L.invalidAccess(): Nothing =
|
internal fun <L : Any> L.invalidAccess(): Nothing =
|
||||||
error("Cls delegate shouldn't be loaded for not too complex ultra-light classes! Qualified name: ${javaClass.name}")
|
error("Cls delegate shouldn't be loaded for not too complex ultra-light classes! Qualified name: ${javaClass.name}")
|
||||||
|
|||||||
@@ -198,6 +198,7 @@
|
|||||||
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
|
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
|
||||||
|
|
||||||
<declarationAttributeAltererExtension implementation="org.jetbrains.kotlin.allopen.ide.IdeAllOpenDeclarationAttributeAltererExtension"/>
|
<declarationAttributeAltererExtension implementation="org.jetbrains.kotlin.allopen.ide.IdeAllOpenDeclarationAttributeAltererExtension"/>
|
||||||
|
<ultraLightClassModifierExtension implementation="org.jetbrains.kotlin.allopen.ide.AllOpenUltraLightClassModifierExtension"/>
|
||||||
|
|
||||||
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.noarg.ide.IdeNoArgComponentContainerContributor"/>
|
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.noarg.ide.IdeNoArgComponentContainerContributor"/>
|
||||||
<expressionCodegenExtension implementation="org.jetbrains.kotlin.noarg.ide.IdeNoArgExpressionCodegenExtension"/>
|
<expressionCodegenExtension implementation="org.jetbrains.kotlin.noarg.ide.IdeNoArgExpressionCodegenExtension"/>
|
||||||
|
|||||||
@@ -198,6 +198,7 @@
|
|||||||
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
|
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
|
||||||
|
|
||||||
<declarationAttributeAltererExtension implementation="org.jetbrains.kotlin.allopen.ide.IdeAllOpenDeclarationAttributeAltererExtension"/>
|
<declarationAttributeAltererExtension implementation="org.jetbrains.kotlin.allopen.ide.IdeAllOpenDeclarationAttributeAltererExtension"/>
|
||||||
|
<ultraLightClassModifierExtension implementation="org.jetbrains.kotlin.allopen.ide.AllOpenUltraLightClassModifierExtension"/>
|
||||||
|
|
||||||
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.noarg.ide.IdeNoArgComponentContainerContributor"/>
|
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.noarg.ide.IdeNoArgComponentContainerContributor"/>
|
||||||
<expressionCodegenExtension implementation="org.jetbrains.kotlin.noarg.ide.IdeNoArgExpressionCodegenExtension"/>
|
<expressionCodegenExtension implementation="org.jetbrains.kotlin.noarg.ide.IdeNoArgExpressionCodegenExtension"/>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ dependencies {
|
|||||||
testRuntimeOnly(intellijDep())
|
testRuntimeOnly(intellijDep())
|
||||||
|
|
||||||
Platform[192].orHigher {
|
Platform[192].orHigher {
|
||||||
|
compileOnly(intellijPluginDep("java"))
|
||||||
testCompileOnly(intellijPluginDep("java"))
|
testCompileOnly(intellijPluginDep("java"))
|
||||||
testRuntimeOnly(intellijPluginDep("java"))
|
testRuntimeOnly(intellijPluginDep("java"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.allopen.ide
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiModifier
|
||||||
|
import org.jetbrains.kotlin.annotation.plugin.ide.CachedAnnotationNames
|
||||||
|
import org.jetbrains.kotlin.annotation.plugin.ide.getAnnotationNames
|
||||||
|
import org.jetbrains.kotlin.asJava.UltraLightClassModifierExtension
|
||||||
|
import org.jetbrains.kotlin.extensions.AnnotationBasedExtension
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isPropertyParameter
|
||||||
|
import org.jetbrains.kotlin.util.isAnnotated
|
||||||
|
import org.jetbrains.kotlin.util.isOrdinaryClass
|
||||||
|
|
||||||
|
class AllOpenUltraLightClassModifierExtension(project: Project) :
|
||||||
|
AnnotationBasedExtension,
|
||||||
|
UltraLightClassModifierExtension {
|
||||||
|
|
||||||
|
private val cachedAnnotationsNames = CachedAnnotationNames(project, ALL_OPEN_ANNOTATION_OPTION_PREFIX)
|
||||||
|
|
||||||
|
override fun getAnnotationFqNames(modifierListOwner: KtModifierListOwner?): List<String> =
|
||||||
|
cachedAnnotationsNames.getAnnotationNames(modifierListOwner)
|
||||||
|
|
||||||
|
private val KtDeclaration.isMethodOrProperty get() = this is KtProperty || this is KtPropertyAccessor || this is KtFunction || (this is KtParameter && this.isPropertyParameter())
|
||||||
|
|
||||||
|
private fun isSuitableDeclaration(declaration: KtDeclaration): Boolean {
|
||||||
|
|
||||||
|
if (getAnnotationFqNames(declaration).isEmpty()) return false
|
||||||
|
|
||||||
|
val declarationToCheck = if (declaration.isMethodOrProperty) declaration.containingClass() else declaration
|
||||||
|
declarationToCheck ?: return false
|
||||||
|
|
||||||
|
if (!declarationToCheck.isOrdinaryClass || declarationToCheck !is KtClassOrObject) return false
|
||||||
|
|
||||||
|
if (declarationToCheck.superTypeListEntries.isEmpty() && !declarationToCheck.isAnnotated) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun interceptModalityBuilding(
|
||||||
|
declaration: KtDeclaration,
|
||||||
|
descriptor: Lazy<DeclarationDescriptor?>,
|
||||||
|
modifier: String
|
||||||
|
): String {
|
||||||
|
|
||||||
|
//Final can be altered to Open only
|
||||||
|
if (modifier != PsiModifier.FINAL) return modifier
|
||||||
|
|
||||||
|
if (!isSuitableDeclaration(declaration)) return modifier
|
||||||
|
|
||||||
|
// Resolver will produce correct descriptor corresponding to modality from AllOpen.
|
||||||
|
// The easiest way to get new modality is to resolve the descriptor
|
||||||
|
return if ((descriptor.value as? MemberDescriptor)?.modality == Modality.OPEN) PsiModifier.OPEN else modifier
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,11 +3,10 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.noarg
|
package org.jetbrains.kotlin.allopen
|
||||||
|
|
||||||
import com.intellij.lang.jvm.JvmModifier
|
import com.intellij.lang.jvm.JvmModifier
|
||||||
import com.intellij.testFramework.LightProjectDescriptor
|
import com.intellij.testFramework.LightProjectDescriptor
|
||||||
import org.jetbrains.kotlin.allopen.AbstractAllOpenDeclarationAttributeAltererExtension
|
|
||||||
import org.jetbrains.kotlin.allopen.ide.ALL_OPEN_ANNOTATION_OPTION_PREFIX
|
import org.jetbrains.kotlin.allopen.ide.ALL_OPEN_ANNOTATION_OPTION_PREFIX
|
||||||
import org.jetbrains.kotlin.config.LanguageVersion
|
import org.jetbrains.kotlin.config.LanguageVersion
|
||||||
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||||
@@ -17,11 +16,8 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
||||||
class TestNoArgForLightClass : KotlinLightCodeInsightFixtureTestCase() {
|
class TestAllOpenForLightClass : KotlinLightCodeInsightFixtureTestCase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val allOpenAnnotationName = AbstractAllOpenDeclarationAttributeAltererExtension.ANNOTATIONS_FOR_TESTS.first()
|
val allOpenAnnotationName = AbstractAllOpenDeclarationAttributeAltererExtension.ANNOTATIONS_FOR_TESTS.first()
|
||||||
|
|||||||
Reference in New Issue
Block a user