diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/UltraLightClassCodegenSupport.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/UltraLightClassCodegenSupport.kt new file mode 100644 index 00000000000..2e8b74f2202 --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/UltraLightClassCodegenSupport.kt @@ -0,0 +1,20 @@ +/* + * 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.asJava + +import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass +import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.psi.KtDeclaration + +interface UltraLightClassCodegenSupport { + fun interceptMethodsBuilding( + declaration: KtDeclaration, + descriptor: Lazy, + containingDeclaration: KtUltraLightClass, + methodsList: MutableList + ) = Unit +} 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 eb7c32a8e2e..f977485000b 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 @@ -14,6 +14,7 @@ import com.intellij.psi.impl.light.LightMethodBuilder import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager +import org.jetbrains.kotlin.asJava.UltraLightClassCodegenSupport import org.jetbrains.kotlin.asJava.builder.LightClassData import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightMethod @@ -22,6 +23,7 @@ import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.JvmCodegenUtil +import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension import org.jetbrains.kotlin.codegen.kotlinType import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -267,7 +269,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor private fun propertyParameters() = classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() } private fun ownMethods(): List { - val result = arrayListOf() + val result = mutableListOf() for (declaration in this.classOrObject.declarations.filterNot { it.isHiddenByDeprecation(support) }) { if (declaration.hasModifier(PRIVATE_KEYWORD) && isInterface) continue @@ -315,6 +317,14 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor addMethodsFromDataClass(result) addDelegatesToInterfaceMethods(result) + val lazyDescriptor = lazy { getDescriptor() } + + ExpressionCodegenExtension.getInstances(project).forEach { + if (it is UltraLightClassCodegenSupport) { + it.interceptMethodsBuilding(kotlinOrigin, lazyDescriptor, this, result) + } + } + return result } 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 9da6ab57002..b686411eec2 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 @@ -241,9 +241,14 @@ fun KtUltraLightClass.createGeneratedMethodFromDescriptor( lightMethod.addParameter(KtUltraLightParameterForDescriptor(valueParameter, support, wrapper)) } - lightMethod.setMethodReturnType { - support.mapType(wrapper) { typeMapper, signatureWriter -> - typeMapper.mapReturnType(descriptor, signatureWriter) + if (descriptor is ConstructorDescriptor) { + lightMethod.isConstructor = true + lightMethod.setMethodReturnType(PsiType.VOID) + } else { + lightMethod.setMethodReturnType { + support.mapType(wrapper) { typeMapper, signatureWriter -> + typeMapper.mapReturnType(descriptor, signatureWriter) + } } } @@ -253,7 +258,7 @@ fun KtUltraLightClass.createGeneratedMethodFromDescriptor( private fun KtUltraLightClass.lightMethod( descriptor: FunctionDescriptor ): LightMethodBuilder { - val name = support.typeMapper.mapFunctionName(descriptor, OwnerKind.IMPLEMENTATION) + val name = if (descriptor is ConstructorDescriptor) name else support.typeMapper.mapFunctionName(descriptor, OwnerKind.IMPLEMENTATION) val accessFlags: Int by lazyPub { val asmFlags = AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION, support.deprecationResolver) diff --git a/plugins/annotation-based-compiler-plugins-ide-support/src/AnnotationBasedLightClassApplicabilityExtension.kt b/plugins/annotation-based-compiler-plugins-ide-support/src/AnnotationBasedLightClassApplicabilityExtension.kt index 96574fe5f75..c1674e14ad7 100644 --- a/plugins/annotation-based-compiler-plugins-ide-support/src/AnnotationBasedLightClassApplicabilityExtension.kt +++ b/plugins/annotation-based-compiler-plugins-ide-support/src/AnnotationBasedLightClassApplicabilityExtension.kt @@ -28,18 +28,21 @@ abstract class AnnotationBasedLightClassApplicabilityExtension(project: Project, cachedAnnotationsNames.getAnnotationNames(modifierListOwner) override fun checkApplicabilityType(declaration: KtDeclaration, descriptor: Lazy): LightClassApplicabilityType { - if (!declaration.isOrdinaryClass || !declaration.isAnnotated) return UltraLightClass - if (cachedAnnotationsNames.getAnnotationNames(declaration).isEmpty()) return UltraLightClass - - val descriptorValue = descriptor.value ?: return UltraLightClass - - val classDescriptor = (descriptorValue as? ClassDescriptor) - ?: descriptorValue.containingDeclaration as? ClassDescriptor - ?: return UltraLightClass - - val hasSpecialAnnotation = run { classDescriptor.hasSpecialAnnotation(declaration) } - - return if (hasSpecialAnnotation) LightClass else UltraLightClass + return UltraLightClass +// +// if (!declaration.isOrdinaryClass || !declaration.isAnnotated) return UltraLightClass +// +// if (cachedAnnotationsNames.getAnnotationNames(declaration).isEmpty()) return UltraLightClass +// +// val descriptorValue = descriptor.value ?: return UltraLightClass +// +// val classDescriptor = (descriptorValue as? ClassDescriptor) +// ?: descriptorValue.containingDeclaration as? ClassDescriptor +// ?: return UltraLightClass +// +// val hasSpecialAnnotation = run { classDescriptor.hasSpecialAnnotation(declaration) } +// +// return if (hasSpecialAnnotation) LightClass else UltraLightClass } } \ No newline at end of file diff --git a/plugins/noarg/noarg-cli/src/AbstractNoArgExpressionCodegenExtension.kt b/plugins/noarg/noarg-cli/src/AbstractNoArgExpressionCodegenExtension.kt index f8c3ab44c1d..4c95a08c217 100644 --- a/plugins/noarg/noarg-cli/src/AbstractNoArgExpressionCodegenExtension.kt +++ b/plugins/noarg/noarg-cli/src/AbstractNoArgExpressionCodegenExtension.kt @@ -72,7 +72,7 @@ abstract class AbstractNoArgExpressionCodegenExtension(val invokeInitializers: B }) } - private fun createNoArgConstructorDescriptor(containingClass: ClassDescriptor): ConstructorDescriptor { + protected fun createNoArgConstructorDescriptor(containingClass: ClassDescriptor): ConstructorDescriptor { return ClassConstructorDescriptorImpl.createSynthesized(containingClass, Annotations.EMPTY, false, SourceElement.NO_SOURCE).apply { initialize( null, calculateDispatchReceiverParameter(), emptyList(), emptyList(), diff --git a/plugins/noarg/noarg-ide/build.gradle.kts b/plugins/noarg/noarg-ide/build.gradle.kts index 6b4abc83d99..e7a3795f448 100644 --- a/plugins/noarg/noarg-ide/build.gradle.kts +++ b/plugins/noarg/noarg-ide/build.gradle.kts @@ -43,6 +43,8 @@ dependencies { testRuntimeOnly(intellijDep()) Platform[192].orHigher { + compileOnly(intellijPluginDep("java")) + testCompileOnly(intellijPluginDep("java")) testRuntimeOnly(intellijPluginDep("java")) } diff --git a/plugins/noarg/noarg-ide/src/IdeArgExpressionCodegenExtension.kt b/plugins/noarg/noarg-ide/src/IdeArgExpressionCodegenExtension.kt index f1cdbb89606..5523480858b 100644 --- a/plugins/noarg/noarg-ide/src/IdeArgExpressionCodegenExtension.kt +++ b/plugins/noarg/noarg-ide/src/IdeArgExpressionCodegenExtension.kt @@ -8,14 +8,49 @@ package org.jetbrains.kotlin.noarg.ide import com.intellij.openapi.project.Project import org.jetbrains.kotlin.annotation.plugin.ide.CachedAnnotationNames import org.jetbrains.kotlin.annotation.plugin.ide.getAnnotationNames +import org.jetbrains.kotlin.asJava.UltraLightClassCodegenSupport +import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass +import org.jetbrains.kotlin.asJava.classes.createGeneratedMethodFromDescriptor +import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.noarg.AbstractNoArgExpressionCodegenExtension +import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.util.isAnnotated +import org.jetbrains.kotlin.util.isOrdinaryClass class IdeNoArgExpressionCodegenExtension(project: Project) : - AbstractNoArgExpressionCodegenExtension(invokeInitializers = false) { + AbstractNoArgExpressionCodegenExtension(invokeInitializers = false), + UltraLightClassCodegenSupport { private val cachedAnnotationsNames = CachedAnnotationNames(project, NO_ARG_ANNOTATION_OPTION_PREFIX) override fun getAnnotationFqNames(modifierListOwner: KtModifierListOwner?): List = cachedAnnotationsNames.getAnnotationNames(modifierListOwner) + + override fun interceptMethodsBuilding( + declaration: KtDeclaration, + descriptor: Lazy, + containingDeclaration: KtUltraLightClass, + methodsList: MutableList + ) { + if (!declaration.isOrdinaryClass || !declaration.isAnnotated) return + + if (cachedAnnotationsNames.getAnnotationNames(declaration).isEmpty()) return + + val descriptorValue = descriptor.value ?: return + + val classDescriptor = (descriptorValue as? ClassDescriptor) + ?: descriptorValue.containingDeclaration as? ClassDescriptor + ?: return + + if (!run { classDescriptor.hasSpecialAnnotation(declaration) }) return + + val parentClass = containingDeclaration as? KtUltraLightClass ?: return + + val constructorDescriptor = createNoArgConstructorDescriptor(classDescriptor) + + methodsList.add(parentClass.createGeneratedMethodFromDescriptor(constructorDescriptor)) + } } diff --git a/plugins/noarg/noarg-ide/test/org/jetbrains/kotlin/noarg/TestNoArgForLightClass.kt b/plugins/noarg/noarg-ide/test/org/jetbrains/kotlin/noarg/TestNoArgForLightClass.kt index d78fff551a5..f0d40021e7f 100644 --- a/plugins/noarg/noarg-ide/test/org/jetbrains/kotlin/noarg/TestNoArgForLightClass.kt +++ b/plugins/noarg/noarg-ide/test/org/jetbrains/kotlin/noarg/TestNoArgForLightClass.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.noarg import com.intellij.testFramework.LightProjectDescriptor import org.jetbrains.kotlin.config.LanguageVersion -import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks import org.jetbrains.kotlin.idea.facet.KotlinFacet import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinProjectDescriptorWithFacet