diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 507aeca123a..a1ad0d28296 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -404,6 +404,7 @@ public abstract class AnnotationCodegen { case FULL: throw new IllegalStateException("Don't know how to compile annotation value " + value); case LIGHT_CLASSES: + case LIGHT_CLASSES_WITH_METADATA: return null; default: throw new IllegalStateException("Unknown builder mode: " + mode); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBuilderMode.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBuilderMode.java index d6c73e56322..08077bd1f9a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBuilderMode.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBuilderMode.java @@ -25,4 +25,8 @@ public enum ClassBuilderMode { * Generating light classes: Only function signatures */ LIGHT_CLASSES, + /** + * Function signatures + metadata (to support incremental compilation with kapt) + */ + LIGHT_CLASSES_WITH_METADATA; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt index 0ef0dd506a3..d8b9777ea32 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt @@ -134,7 +134,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) { annotationCodegen.genAnnotations(it.value, signature.valueParameters[it.index].asmType) } - if (state.classBuilderMode == ClassBuilderMode.LIGHT_CLASSES) { + if (state.classBuilderMode != ClassBuilderMode.FULL) { FunctionCodegen.generateLocalVariablesForParameters(mv, signature, null, Label(), Label(), remainingParameters, isStatic) mv.visitEnd() return diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 9273289a9e8..30ae9a74c42 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -198,7 +198,7 @@ public class FunctionCodegen { parentBodyCodegen.addAdditionalTask(new JvmStaticGenerator(functionDescriptor, origin, state, parentBodyCodegen)); } - if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES || isAbstractMethod(functionDescriptor, contextKind)) { + if (state.getClassBuilderMode() != ClassBuilderMode.FULL || isAbstractMethod(functionDescriptor, contextKind)) { generateLocalVariableTable( mv, jvmSignature, @@ -294,7 +294,7 @@ public class FunctionCodegen { private void markEnumOrInnerConstructorParameterAsSynthetic(MethodVisitor mv, int i) { // IDEA's ClsPsi builder fails to annotate synthetic parameters - if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return; + if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; // This is needed to avoid RuntimeInvisibleParameterAnnotations error in javac: // see MethodWriter.visitParameterAnnotation() diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index d25a1d84d8a..79e6cf823ab 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -158,7 +158,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (!ktClass.hasModifier(KtTokens.OPEN_KEYWORD) && !isAbstract) { // Light-class mode: Do not make enum classes final since PsiClass corresponding to enum is expected to be inheritable from - isFinal = !(ktClass.isEnum() && state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES); + isFinal = !(ktClass.isEnum() && state.getClassBuilderMode() != ClassBuilderMode.FULL); } isStatic = !ktClass.isInner(); } @@ -169,7 +169,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { int access = 0; - if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES && !DescriptorUtils.isTopLevelDeclaration(descriptor)) { + if (state.getClassBuilderMode() != ClassBuilderMode.FULL && !DescriptorUtils.isTopLevelDeclaration(descriptor)) { // ClassBuilderMode.LIGHT_CLASSES means we are generating light classes & looking at a nested or inner class // Light class generation is implemented so that Cls-classes only read bare code of classes, // without knowing whether these classes are inner or not (see ClassStubBuilder.EMPTY_STRATEGY) @@ -265,7 +265,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private void writeEnclosingMethod() { // Do not emit enclosing method in "light-classes mode" since currently we generate local light classes as if they're top level - if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) { + if (state.getClassBuilderMode() != ClassBuilderMode.FULL) { return; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 91c05ac389e..eb8534e1fe4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -59,6 +59,7 @@ import java.util.*; import static org.jetbrains.kotlin.codegen.AsmUtil.calculateInnerClassAccessFlags; import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; +import static org.jetbrains.kotlin.codegen.ClassBuilderModeUtilKt.shouldGenerateMetadata; import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED; import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; @@ -119,7 +120,7 @@ public abstract class MemberCodegen initializerValue = computeInitializerValue(property, propertyDescriptor, initializer); // we must write constant values for fields in light classes, // because Java's completion for annotation arguments uses this information - if (initializerValue == null) return state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES; + if (initializerValue == null) return state.getClassBuilderMode() == ClassBuilderMode.FULL; //TODO: OPTIMIZATION: don't initialize static final fields KotlinType jetType = getPropertyOrDelegateType(property, propertyDescriptor); @@ -495,7 +496,7 @@ public abstract class MemberCodegen diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt index 1c372db5961..16b823d2b6f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt @@ -24,7 +24,8 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader -import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.* +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.DELEGATING +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.INHERITING import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtProperty @@ -76,7 +77,7 @@ class MultifileClassPartCodegen( } override fun generate() { - if (state.classBuilderMode == ClassBuilderMode.LIGHT_CLASSES) return + if (state.classBuilderMode != ClassBuilderMode.FULL) return super.generate() diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/classBuilderModeUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/classBuilderModeUtil.kt new file mode 100644 index 00000000000..b86afa3e5d5 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/classBuilderModeUtil.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2016 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.codegen + +fun ClassBuilderMode.shouldGenerateMetadata() = + this == ClassBuilderMode.FULL || this == ClassBuilderMode.LIGHT_CLASSES_WITH_METADATA \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index 7e155688247..2334509c591 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -113,7 +113,7 @@ public class KotlinTypeMapper { @Override public void processErrorType(@NotNull KotlinType kotlinType, @NotNull ClassDescriptor descriptor) { - if (classBuilderMode != ClassBuilderMode.LIGHT_CLASSES) { + if (classBuilderMode == ClassBuilderMode.FULL) { throw new IllegalStateException(generateErrorMessageForErrorType(kotlinType, descriptor)); } } @@ -1122,7 +1122,7 @@ public class KotlinTypeMapper { } private void writeFormalTypeParameter(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull JvmSignatureWriter sw) { - if (classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && typeParameterDescriptor.getName().isSpecial()) { + if (classBuilderMode != ClassBuilderMode.FULL && typeParameterDescriptor.getName().isSpecial()) { // If a type parameter has no name, the code below fails, but it should recover in case of light classes return; } diff --git a/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/StubProducerExtension.kt b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/StubProducerExtension.kt index 7d01f0516c6..9b447210eaf 100644 --- a/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/StubProducerExtension.kt +++ b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/StubProducerExtension.kt @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.DelegatingBindingTrace import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension import org.jetbrains.org.objectweb.asm.ClassWriter @@ -59,7 +58,7 @@ class StubProducerExtension(val stubsOutputDir: File) : AnalysisCompletedHandler private class StubClassBuilderFactory : ClassBuilderFactory { - override fun getClassBuilderMode() = ClassBuilderMode.LIGHT_CLASSES + override fun getClassBuilderMode() = ClassBuilderMode.LIGHT_CLASSES_WITH_METADATA override fun newClassBuilder(origin: JvmDeclarationOrigin) = AbstractClassBuilder.Concrete( ClassWriter(ClassWriter.COMPUTE_FRAMES or ClassWriter.COMPUTE_MAXS))