Light classes: allow light classes for inner/nested classes to be build separately
Avoid analyzing/generating bytecode for outers
This commit is contained in:
@@ -77,9 +77,13 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generatePrimaryConstructorProperties();
|
boolean generateNonClassMembers = shouldGenerateNonClassMembers();
|
||||||
generateConstructors();
|
|
||||||
generateDefaultImplsIfNeeded();
|
if (generateNonClassMembers) {
|
||||||
|
generatePrimaryConstructorProperties();
|
||||||
|
generateConstructors();
|
||||||
|
generateDefaultImplsIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
// Generate _declared_ companions
|
// Generate _declared_ companions
|
||||||
for (KtObjectDeclaration companion : companions) {
|
for (KtObjectDeclaration companion : companions) {
|
||||||
@@ -92,23 +96,30 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
|||||||
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) companionObjectDescriptor);
|
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) companionObjectDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DescriptorUtils.isInterface(descriptor)) {
|
if (generateNonClassMembers) {
|
||||||
for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
generateBridges();
|
||||||
if (memberDescriptor instanceof CallableMemberDescriptor) {
|
}
|
||||||
CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor;
|
}
|
||||||
if (!member.getKind().isReal() && ImplKt.findInterfaceImplementation(member) == null) {
|
|
||||||
if (member instanceof FunctionDescriptor) {
|
private void generateBridges() {
|
||||||
functionCodegen.generateBridges((FunctionDescriptor) member);
|
if (DescriptorUtils.isInterface(descriptor)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
||||||
|
if (memberDescriptor instanceof CallableMemberDescriptor) {
|
||||||
|
CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor;
|
||||||
|
if (!member.getKind().isReal() && ImplKt.findInterfaceImplementation(member) == null) {
|
||||||
|
if (member instanceof FunctionDescriptor) {
|
||||||
|
functionCodegen.generateBridges((FunctionDescriptor) member);
|
||||||
|
}
|
||||||
|
else if (member instanceof PropertyDescriptor) {
|
||||||
|
PropertyGetterDescriptor getter = ((PropertyDescriptor) member).getGetter();
|
||||||
|
if (getter != null) {
|
||||||
|
functionCodegen.generateBridges(getter);
|
||||||
}
|
}
|
||||||
else if (member instanceof PropertyDescriptor) {
|
PropertySetterDescriptor setter = ((PropertyDescriptor) member).getSetter();
|
||||||
PropertyGetterDescriptor getter = ((PropertyDescriptor) member).getGetter();
|
if (setter != null) {
|
||||||
if (getter != null) {
|
functionCodegen.generateBridges(setter);
|
||||||
functionCodegen.generateBridges(getter);
|
|
||||||
}
|
|
||||||
PropertySetterDescriptor setter = ((PropertyDescriptor) member).getSetter();
|
|
||||||
if (setter != null) {
|
|
||||||
functionCodegen.generateBridges(setter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,6 +127,11 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldGenerateNonClassMembers() {
|
||||||
|
return !(myClass instanceof KtClassOrObject) ||
|
||||||
|
state.getGenerateDeclaredClassFilter().shouldGenerateClassMembers((KtClassOrObject) myClass);
|
||||||
|
}
|
||||||
|
|
||||||
protected void generateConstructors() {
|
protected void generateConstructors() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -130,7 +146,9 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
|||||||
|
|
||||||
protected void generateDeclaration(KtDeclaration declaration) {
|
protected void generateDeclaration(KtDeclaration declaration) {
|
||||||
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction || declaration instanceof KtTypeAlias) {
|
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction || declaration instanceof KtTypeAlias) {
|
||||||
genSimpleMember(declaration);
|
if (shouldGenerateNonClassMembers()) {
|
||||||
|
genSimpleMember(declaration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (declaration instanceof KtClassOrObject) {
|
else if (declaration instanceof KtClassOrObject) {
|
||||||
if (declaration instanceof KtEnumEntry && !enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) {
|
if (declaration instanceof KtEnumEntry && !enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) {
|
||||||
|
|||||||
@@ -127,7 +127,10 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
|||||||
|
|
||||||
generateBody();
|
generateBody();
|
||||||
|
|
||||||
generateSyntheticParts();
|
if (!(element instanceof KtClassOrObject) ||
|
||||||
|
state.getGenerateDeclaredClassFilter().shouldGenerateClassMembers((KtClassOrObject) element)) {
|
||||||
|
generateSyntheticParts();
|
||||||
|
}
|
||||||
|
|
||||||
if (state.getClassBuilderMode().generateMetadata) {
|
if (state.getClassBuilderMode().generateMetadata) {
|
||||||
generateKotlinMetadataAnnotation();
|
generateKotlinMetadataAnnotation();
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ class GenerationState @JvmOverloads constructor(
|
|||||||
abstract fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean
|
abstract fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean
|
||||||
abstract fun shouldGeneratePackagePart(jetFile: KtFile): Boolean
|
abstract fun shouldGeneratePackagePart(jetFile: KtFile): Boolean
|
||||||
abstract fun shouldGenerateScript(script: KtScript): Boolean
|
abstract fun shouldGenerateScript(script: KtScript): Boolean
|
||||||
|
open fun shouldGenerateClassMembers(processingClassOrObject: KtClassOrObject) = shouldGenerateClass(processingClassOrObject)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField val GENERATE_ALL: GenerateClassFilter = object : GenerateClassFilter() {
|
@JvmField val GENERATE_ALL: GenerateClassFilter = object : GenerateClassFilter() {
|
||||||
|
|||||||
+13
-21
@@ -34,11 +34,10 @@ import com.intellij.psi.stubs.StubElement
|
|||||||
import com.intellij.psi.util.CachedValueProvider
|
import com.intellij.psi.util.CachedValueProvider
|
||||||
import com.intellij.psi.util.PsiModificationTracker
|
import com.intellij.psi.util.PsiModificationTracker
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.util.containers.ContainerUtil
|
|
||||||
import com.intellij.util.containers.Stack
|
import com.intellij.util.containers.Stack
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
||||||
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
|
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
|
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
|
||||||
@@ -48,8 +47,8 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||||
import org.jetbrains.kotlin.psi.KtScript
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration
|
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
|
|
||||||
abstract class LightClassDataProvider<T : WithFileStubAndExtraDiagnostics>(
|
abstract class LightClassDataProvider<T : WithFileStubAndExtraDiagnostics>(
|
||||||
@@ -177,21 +176,13 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
|
|||||||
javaFileStub: PsiJavaFileStub,
|
javaFileStub: PsiJavaFileStub,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
extraDiagnostics: Diagnostics): WithFileStubAndExtraDiagnostics {
|
extraDiagnostics: Diagnostics): WithFileStubAndExtraDiagnostics {
|
||||||
val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassData
|
bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassData
|
||||||
|
|
||||||
val allInnerClasses = CodegenBinding.getAllInnerClasses(bindingContext, classDescriptor)
|
|
||||||
|
|
||||||
val innerClassesMap = ContainerUtil.newHashMap<KtClassOrObject, InnerKotlinClassLightClassData>()
|
|
||||||
for (innerClassDescriptor in allInnerClasses) {
|
|
||||||
val declaration = descriptorToDeclaration(innerClassDescriptor) as? KtClassOrObject ?: continue
|
|
||||||
innerClassesMap.put(declaration, InnerKotlinClassLightClassData(declaration))
|
|
||||||
}
|
|
||||||
|
|
||||||
return OutermostKotlinClassLightClassData(
|
return OutermostKotlinClassLightClassData(
|
||||||
javaFileStub,
|
javaFileStub,
|
||||||
extraDiagnostics,
|
extraDiagnostics,
|
||||||
classOrObject,
|
classOrObject)
|
||||||
innerClassesMap)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val files: Collection<KtFile>
|
override val files: Collection<KtFile>
|
||||||
@@ -211,15 +202,11 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
|
|||||||
return shouldGenerateClass(processingClassOrObject)
|
return shouldGenerateClass(processingClassOrObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean {
|
override fun shouldGenerateClassMembers(processingClassOrObject: KtClassOrObject): Boolean {
|
||||||
// Trivial: generate and analyze class we are interested in.
|
|
||||||
if (classOrObject === processingClassOrObject) return true
|
if (classOrObject === processingClassOrObject) return true
|
||||||
|
|
||||||
// Process all parent classes as they are context for current class
|
// process all children
|
||||||
// Process child classes because they probably affect members (heuristic)
|
if (classOrObject.isAncestor(processingClassOrObject, true)) {
|
||||||
|
|
||||||
if (PsiTreeUtil.isAncestor(classOrObject, processingClassOrObject, true) ||
|
|
||||||
PsiTreeUtil.isAncestor(processingClassOrObject, classOrObject, true)) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,6 +232,11 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean {
|
||||||
|
// generate outer classes but not their members
|
||||||
|
return shouldGenerateClassMembers(processingClassOrObject) || processingClassOrObject.isAncestor(classOrObject, true)
|
||||||
|
}
|
||||||
|
|
||||||
override fun shouldGenerateScript(script: KtScript): Boolean {
|
override fun shouldGenerateScript(script: KtScript): Boolean {
|
||||||
return PsiTreeUtil.isAncestor(script, classOrObject, false)
|
return PsiTreeUtil.isAncestor(script, classOrObject, false)
|
||||||
}
|
}
|
||||||
@@ -255,7 +247,7 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
|
|||||||
val file = classOrObject.containingKtFile
|
val file = classOrObject.containingKtFile
|
||||||
val packagePartType = state.fileClassesProvider.getFileClassType(file)
|
val packagePartType = state.fileClassesProvider.getFileClassType(file)
|
||||||
val context = state.rootContext.intoPackagePart(packageCodegen.packageFragment, packagePartType, file)
|
val context = state.rootContext.intoPackagePart(packageCodegen.packageFragment, packagePartType, file)
|
||||||
packageCodegen.generateClassOrObject(classOrObject, context)
|
packageCodegen.generateClassOrObject(getOutermostClassOrObject(classOrObject), context)
|
||||||
state.factory.asList()
|
state.factory.asList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-8
@@ -55,11 +55,5 @@ data class InnerKotlinClassLightClassData(
|
|||||||
data class OutermostKotlinClassLightClassData(
|
data class OutermostKotlinClassLightClassData(
|
||||||
override val javaFileStub: PsiJavaFileStub,
|
override val javaFileStub: PsiJavaFileStub,
|
||||||
override val extraDiagnostics: Diagnostics,
|
override val extraDiagnostics: Diagnostics,
|
||||||
override val classOrObject: KtClassOrObject,
|
override val classOrObject: KtClassOrObject
|
||||||
val allInnerClasses: Map<KtClassOrObject, InnerKotlinClassLightClassData>
|
): LightClassDataForKotlinClass, WithFileStubAndExtraDiagnostics
|
||||||
): LightClassDataForKotlinClass, WithFileStubAndExtraDiagnostics {
|
|
||||||
|
|
||||||
fun dataForClass(cls: KtClassOrObject): LightClassDataForKotlinClass? =
|
|
||||||
if (cls == classOrObject) this else allInnerClasses[cls]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
+13
-11
@@ -388,23 +388,17 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<WithFileStubAndExtraDiagnostics> {
|
fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<WithFileStubAndExtraDiagnostics> {
|
||||||
val outermostClassOrObject = getOutermostClassOrObject(classOrObject)
|
var value =
|
||||||
var value = outermostClassOrObject.getUserData(JAVA_API_STUB)
|
getOutermostClassOrObject(classOrObject).getUserData(JAVA_API_STUB) // stub computed for outer class can be used for inner/nested
|
||||||
|
?: classOrObject.getUserData (JAVA_API_STUB)
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
value = CachedValuesManager.getManager(classOrObject.project).createCachedValue(
|
value = CachedValuesManager.getManager(classOrObject.project).createCachedValue(
|
||||||
LightClassDataProviderForClassOrObject(outermostClassOrObject), false)
|
LightClassDataProviderForClassOrObject(classOrObject), false)
|
||||||
value = outermostClassOrObject.putUserDataIfAbsent(JAVA_API_STUB, value)
|
value = classOrObject.putUserDataIfAbsent(JAVA_API_STUB, value)
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOutermostClassOrObject(classOrObject: KtClassOrObject): KtClassOrObject {
|
|
||||||
val outermostClass = KtPsiUtil.getOutermostClassOrObject(classOrObject) ?:
|
|
||||||
throw IllegalStateException("Attempt to build a light class for a local class: " + classOrObject.text)
|
|
||||||
|
|
||||||
return outermostClass
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkSuperTypeByFQName(classDescriptor: ClassDescriptor, qualifiedName: String, deep: Boolean): Boolean {
|
private fun checkSuperTypeByFQName(classDescriptor: ClassDescriptor, qualifiedName: String, deep: Boolean): Boolean {
|
||||||
if (CommonClassNames.JAVA_LANG_OBJECT == qualifiedName) return true
|
if (CommonClassNames.JAVA_LANG_OBJECT == qualifiedName) return true
|
||||||
|
|
||||||
@@ -441,3 +435,11 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
override val originKind: LightClassOriginKind
|
override val originKind: LightClassOriginKind
|
||||||
get() = LightClassOriginKind.SOURCE
|
get() = LightClassOriginKind.SOURCE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getOutermostClassOrObject(classOrObject: KtClassOrObject): KtClassOrObject {
|
||||||
|
val outermostClass = KtPsiUtil.getOutermostClassOrObject(classOrObject) ?:
|
||||||
|
throw IllegalStateException("Attempt to build a light class for a local class: " + classOrObject.text)
|
||||||
|
|
||||||
|
return outermostClass
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user