Generate ex-package parts as file facades.

Support new facade kind in stub building and incremental compilation.
This commit is contained in:
Dmitry Petrov
2015-08-25 17:37:01 +03:00
committed by Michael Bogdanov
parent 43af127ce8
commit e050ff3271
8 changed files with 49 additions and 12 deletions
@@ -44,6 +44,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.ABI_VERSION_FIELD_NAME; import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.ABI_VERSION_FIELD_NAME;
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass; import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.org.objectweb.asm.Opcodes.*; import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -111,14 +112,6 @@ public class PackagePartCodegen extends MemberCodegen<JetFile> {
} }
} }
AnnotationVisitor av = v.newAnnotation(Type.getObjectType(KotlinSyntheticClass.CLASS_NAME.getInternalName()).getDescriptor(), true);
av.visit(ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
av.visitEnum(
JvmAnnotationNames.KIND_FIELD_NAME,
Type.getObjectType(KotlinSyntheticClass.KIND_INTERNAL_NAME).getDescriptor(),
KotlinSyntheticClass.Kind.PACKAGE_PART.toString()
);
JvmSerializationBindings bindings = v.getSerializationBindings(); JvmSerializationBindings bindings = v.getSerializationBindings();
DescriptorSerializer serializer = DescriptorSerializer.createTopLevel(new JvmSerializerExtension(bindings, state.getTypeMapper())); DescriptorSerializer serializer = DescriptorSerializer.createTopLevel(new JvmSerializerExtension(bindings, state.getTypeMapper()));
@@ -140,7 +133,8 @@ public class PackagePartCodegen extends MemberCodegen<JetFile> {
NameResolver nameResolver = new NameResolver(strings.serializeSimpleNames(), strings.serializeQualifiedNames()); NameResolver nameResolver = new NameResolver(strings.serializeSimpleNames(), strings.serializeQualifiedNames());
PackageData data = new PackageData(nameResolver, packageProto); PackageData data = new PackageData(nameResolver, packageProto);
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FILE_FACADE), true);
av.visit(ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
for (String string : BitEncoding.encodeBytes(SerializationUtil.serializePackageData(data))) { for (String string : BitEncoding.encodeBytes(SerializationUtil.serializePackageData(data))) {
array.visit(null, string); array.visit(null, string);
@@ -30,6 +30,7 @@ import java.util.Set;
public final class JvmAnnotationNames { public final class JvmAnnotationNames {
public static final FqName KOTLIN_CLASS = KotlinClass.CLASS_NAME.getFqNameForClassNameWithoutDollars(); public static final FqName KOTLIN_CLASS = KotlinClass.CLASS_NAME.getFqNameForClassNameWithoutDollars();
public static final FqName KOTLIN_PACKAGE = new FqName("kotlin.jvm.internal.KotlinPackage"); public static final FqName KOTLIN_PACKAGE = new FqName("kotlin.jvm.internal.KotlinPackage");
public static final FqName KOTLIN_FILE_FACADE = new FqName("kotlin.jvm.internal.KotlinFileFacade");
public static final FqName KOTLIN_CALLABLE = new FqName("kotlin.jvm.internal.KotlinCallable"); public static final FqName KOTLIN_CALLABLE = new FqName("kotlin.jvm.internal.KotlinCallable");
public static final FqName KOTLIN_SIGNATURE = new FqName("kotlin.jvm.KotlinSignature"); public static final FqName KOTLIN_SIGNATURE = new FqName("kotlin.jvm.KotlinSignature");
@@ -32,6 +32,7 @@ public class KotlinClassHeader(
public enum class Kind { public enum class Kind {
CLASS, CLASS,
PACKAGE_FACADE, PACKAGE_FACADE,
FILE_FACADE,
SYNTHETIC_CLASS SYNTHETIC_CLASS
} }
@@ -44,4 +45,5 @@ public class KotlinClassHeader(
public fun KotlinClassHeader.isCompatibleClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.CLASS public fun KotlinClassHeader.isCompatibleClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.CLASS
public fun KotlinClassHeader.isCompatiblePackageFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.PACKAGE_FACADE public fun KotlinClassHeader.isCompatiblePackageFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.PACKAGE_FACADE
public fun KotlinClassHeader.isCompatibleFileFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.FILE_FACADE
public fun KotlinClassHeader.isCompatibleSyntheticClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS public fun KotlinClassHeader.isCompatibleSyntheticClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS
@@ -41,6 +41,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
static { static {
HEADER_KINDS.put(KotlinClass.CLASS_NAME, CLASS); HEADER_KINDS.put(KotlinClass.CLASS_NAME, CLASS);
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE), PACKAGE_FACADE); HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE), PACKAGE_FACADE);
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_FILE_FACADE), FILE_FACADE);
HEADER_KINDS.put(KotlinSyntheticClass.CLASS_NAME, SYNTHETIC_CLASS); HEADER_KINDS.put(KotlinSyntheticClass.CLASS_NAME, SYNTHETIC_CLASS);
initOldAnnotations(); initOldAnnotations();
@@ -77,7 +78,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
return new KotlinClassHeader(headerKind, version, null, classKind, syntheticClassKind); return new KotlinClassHeader(headerKind, version, null, classKind, syntheticClassKind);
} }
if ((headerKind == CLASS || headerKind == PACKAGE_FACADE) && annotationData == null) { if ((headerKind == CLASS || headerKind == PACKAGE_FACADE || headerKind == FILE_FACADE) && annotationData == null) {
// This means that the annotation is found and its ABI version is compatible, but there's no "data" string array in it. // This means that the annotation is found and its ABI version is compatible, but there's no "data" string array in it.
// We tell the outside world that there's really no annotation at all // We tell the outside world that there's really no annotation at all
return null; return null;
@@ -105,6 +106,8 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
return new ClassHeaderReader(); return new ClassHeaderReader();
case PACKAGE_FACADE: case PACKAGE_FACADE:
return new PackageHeaderReader(); return new PackageHeaderReader();
case FILE_FACADE:
return new FileFacadeHeaderReader();
case SYNTHETIC_CLASS: case SYNTHETIC_CLASS:
return new SyntheticClassHeaderReader(); return new SyntheticClassHeaderReader();
default: default:
@@ -201,6 +204,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
} }
} }
private class FileFacadeHeaderReader extends HeaderAnnotationArgumentVisitor {
public FileFacadeHeaderReader() {
super(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_FILE_FACADE));
}
}
private class SyntheticClassHeaderReader extends HeaderAnnotationArgumentVisitor { private class SyntheticClassHeaderReader extends HeaderAnnotationArgumentVisitor {
public SyntheticClassHeaderReader() { public SyntheticClassHeaderReader() {
super(KotlinSyntheticClass.CLASS_NAME); super(KotlinSyntheticClass.CLASS_NAME);
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2015 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 kotlin.jvm.internal;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface KotlinFileFacade {
int abiVersion();
String[] data();
}
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleSyntheticClassKind import org.jetbrains.kotlin.load.kotlin.header.isCompatibleSyntheticClassKind
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -75,7 +76,7 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
val context = components.createContext(classData.getNameResolver(), packageFqName) val context = components.createContext(classData.getNameResolver(), packageFqName)
createTopLevelClassStub(classId, classData.getClassProto(), context) createTopLevelClassStub(classId, classData.getClassProto(), context)
} }
header.isCompatibleSyntheticClassKind() && header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART -> { header.isCompatibleFileFacadeKind() -> {
val packageData = JvmProtoBufUtil.readPackageDataFrom(annotationData) val packageData = JvmProtoBufUtil.readPackageDataFrom(annotationData)
val context = components.createContext(packageData.getNameResolver(), packageFqName) val context = components.createContext(packageData.getNameResolver(), packageFqName)
createPackageFacadeFileStub(packageData.getPackageProto(), packageFqName, context) createPackageFacadeFileStub(packageData.getPackageProto(), packageFqName, context)
@@ -44,7 +44,8 @@ public object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinAbiVersion
OLD_KOTLIN_CLASS, OLD_KOTLIN_CLASS,
OLD_KOTLIN_PACKAGE, OLD_KOTLIN_PACKAGE,
KOTLIN_CLASS, KOTLIN_CLASS,
KOTLIN_PACKAGE) KOTLIN_PACKAGE,
KOTLIN_FILE_FACADE)
.map { asmDescByFqNameWithoutInnerClasses(it) } .map { asmDescByFqNameWithoutInnerClasses(it) }
private val INDEXER = DataIndexer<Int, Void, FileContent>() { inputData: FileContent -> private val INDEXER = DataIndexer<Int, Void, FileContent>() { inputData: FileContent ->
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -169,6 +170,7 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
JvmAnnotationNames.KotlinClass.Kind.LOCAL_CLASS, JvmAnnotationNames.KotlinClass.Kind.ANONYMOUS_OBJECT -> DO_NOTHING JvmAnnotationNames.KotlinClass.Kind.LOCAL_CLASS, JvmAnnotationNames.KotlinClass.Kind.ANONYMOUS_OBJECT -> DO_NOTHING
} }
header.isCompatibleFileFacadeKind() ||
header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART -> { header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART -> {
assert(sourceFiles.size() == 1) { "Package part from several source files: $sourceFiles" } assert(sourceFiles.size() == 1) { "Package part from several source files: $sourceFiles" }