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.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.KotlinSyntheticClass;
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();
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());
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);
for (String string : BitEncoding.encodeBytes(SerializationUtil.serializePackageData(data))) {
array.visit(null, string);
@@ -30,6 +30,7 @@ import java.util.Set;
public final class JvmAnnotationNames {
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_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_SIGNATURE = new FqName("kotlin.jvm.KotlinSignature");
@@ -32,6 +32,7 @@ public class KotlinClassHeader(
public enum class Kind {
CLASS,
PACKAGE_FACADE,
FILE_FACADE,
SYNTHETIC_CLASS
}
@@ -44,4 +45,5 @@ public class KotlinClassHeader(
public fun KotlinClassHeader.isCompatibleClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.CLASS
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
@@ -41,6 +41,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
static {
HEADER_KINDS.put(KotlinClass.CLASS_NAME, CLASS);
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);
initOldAnnotations();
@@ -77,7 +78,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
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.
// We tell the outside world that there's really no annotation at all
return null;
@@ -105,6 +106,8 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
return new ClassHeaderReader();
case PACKAGE_FACADE:
return new PackageHeaderReader();
case FILE_FACADE:
return new FileFacadeHeaderReader();
case SYNTHETIC_CLASS:
return new SyntheticClassHeaderReader();
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 {
public SyntheticClassHeaderReader() {
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.kotlin.KotlinBinaryClassCache
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.isCompatibleSyntheticClassKind
import org.jetbrains.kotlin.name.FqName
@@ -75,7 +76,7 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
val context = components.createContext(classData.getNameResolver(), packageFqName)
createTopLevelClassStub(classId, classData.getClassProto(), context)
}
header.isCompatibleSyntheticClassKind() && header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART -> {
header.isCompatibleFileFacadeKind() -> {
val packageData = JvmProtoBufUtil.readPackageDataFrom(annotationData)
val context = components.createContext(packageData.getNameResolver(), packageFqName)
createPackageFacadeFileStub(packageData.getPackageProto(), packageFqName, context)
@@ -44,7 +44,8 @@ public object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinAbiVersion
OLD_KOTLIN_CLASS,
OLD_KOTLIN_PACKAGE,
KOTLIN_CLASS,
KOTLIN_PACKAGE)
KOTLIN_PACKAGE,
KOTLIN_FILE_FACADE)
.map { asmDescByFqNameWithoutInnerClasses(it) }
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.kotlin.PackageClassUtils
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.incremental.components.IncrementalCache
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
}
header.isCompatibleFileFacadeKind() ||
header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART -> {
assert(sourceFiles.size() == 1) { "Package part from several source files: $sourceFiles" }