diff --git a/compiler/backend/backend.iml b/compiler/backend/backend.iml
index e1b68dd0487..d6c4b6e6622 100644
--- a/compiler/backend/backend.iml
+++ b/compiler/backend/backend.iml
@@ -12,6 +12,8 @@
+
+
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
index 637425c0180..3eb787227b9 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
@@ -41,6 +41,7 @@ import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
+import org.jetbrains.jet.descriptors.serialization.*;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
import org.jetbrains.jet.lang.psi.*;
@@ -60,17 +61,20 @@ import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
+import org.jetbrains.jet.utils.ExceptionUtils;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.util.*;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
+import static org.jetbrains.jet.descriptors.serialization.ClassSerializationUtil.constantSerializer;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
-import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isKindOf;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
@@ -209,9 +213,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
+ writeKotlinInfoIfNeeded();
+
writeClassSignatureIfNeeded(signature);
}
+ private void writeKotlinInfoIfNeeded() {
+ if (!(descriptor.getContainingDeclaration() instanceof ClassOrNamespaceDescriptor)) return;
+
+ final AnnotationVisitor av = v.getVisitor().visitAnnotation("Ljet/KotlinInfo;", true);
+ DescriptorSerializer serializer = new DescriptorSerializer(DescriptorNamer.DEFAULT);
+
+ ClassSerializationUtil.serializeClass(descriptor, constantSerializer(serializer), new ClassSerializationUtil.Sink() {
+ @Override
+ public void writeClass(@NotNull ClassDescriptor classDescriptor, @NotNull ProtoBuf.Class classProto) {
+ av.visit("data", classProto.toByteArray());
+ }
+ });
+
+ ByteArrayOutputStream nameTable = new ByteArrayOutputStream();
+ NameSerializationUtil.serializeNameTable(nameTable, serializer.getNameTable());
+ av.visit("nameTable", nameTable.toByteArray());
+
+ av.visitEnd();
+ }
+
private void writeEnclosingMethod() {
//JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration();
diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/NameSerializationUtil.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/NameSerializationUtil.java
index 39222cd44f2..52ff83a7ce6 100644
--- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/NameSerializationUtil.java
+++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/NameSerializationUtil.java
@@ -17,25 +17,39 @@
package org.jetbrains.jet.descriptors.serialization;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.utils.ExceptionUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class NameSerializationUtil {
- @NotNull
- public static NameResolver deserializeNameResolver(@NotNull InputStream in) throws IOException {
- ProtoBuf.SimpleNameTable simpleNames = ProtoBuf.SimpleNameTable.parseDelimitedFrom(in);
- ProtoBuf.QualifiedNameTable qualifiedNames = ProtoBuf.QualifiedNameTable.parseDelimitedFrom(in);
- return new NameResolver(simpleNames, qualifiedNames);
+ private NameSerializationUtil() {
}
- public static void serializeNameTable(@NotNull OutputStream out, @NotNull NameTable nameTable) throws IOException {
- ProtoBuf.SimpleNameTable simpleNamesProto = toSimpleNameTable(nameTable);
- simpleNamesProto.writeDelimitedTo(out);
+ @NotNull
+ public static NameResolver deserializeNameResolver(@NotNull InputStream in) {
+ try {
+ ProtoBuf.SimpleNameTable simpleNames = ProtoBuf.SimpleNameTable.parseDelimitedFrom(in);
+ ProtoBuf.QualifiedNameTable qualifiedNames = ProtoBuf.QualifiedNameTable.parseDelimitedFrom(in);
+ return new NameResolver(simpleNames, qualifiedNames);
+ }
+ catch (IOException e) {
+ throw ExceptionUtils.rethrow(e);
+ }
+ }
- ProtoBuf.QualifiedNameTable qualifiedNameTable = toQualifiedNameTable(nameTable);
- qualifiedNameTable.writeDelimitedTo(out);
+ public static void serializeNameTable(@NotNull OutputStream out, @NotNull NameTable nameTable) {
+ try {
+ ProtoBuf.SimpleNameTable simpleNamesProto = toSimpleNameTable(nameTable);
+ simpleNamesProto.writeDelimitedTo(out);
+
+ ProtoBuf.QualifiedNameTable qualifiedNameTable = toQualifiedNameTable(nameTable);
+ qualifiedNameTable.writeDelimitedTo(out);
+ }
+ catch (IOException e) {
+ throw ExceptionUtils.rethrow(e);
+ }
}
@NotNull
diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/NameTable.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/NameTable.java
index ae325c2da87..3fbade6e3f4 100644
--- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/NameTable.java
+++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/NameTable.java
@@ -84,10 +84,13 @@ public class NameTable {
NamespaceDescriptor namespaceDescriptor = (NamespaceDescriptor) containingDeclaration;
builder.setParentQualifiedName(getFqNameIndex(namespaceDescriptor));
}
- else {
+ else if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor outerClass = (ClassDescriptor) containingDeclaration;
builder.setParentQualifiedName(getFqNameIndex(outerClass));
}
+ else {
+ throw new IllegalStateException("FQ names are only stored for top-level or inner classes: " + classDescriptor);
+ }
return qualifiedNames.intern(builder);
}
diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java
index e672fe628f1..cd638b1fa22 100644
--- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java
+++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java
@@ -43,19 +43,27 @@ import org.jetbrains.jet.config.CompilerConfiguration;
import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl;
+import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
+import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
+import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
+import org.jetbrains.jet.lang.resolve.java.JavaBridgeConfiguration;
+import org.jetbrains.jet.lang.resolve.java.JavaToKotlinClassMap;
import org.jetbrains.jet.lang.resolve.lazy.LazyResolveTestUtil;
import org.jetbrains.jet.lang.resolve.name.Name;
+import org.jetbrains.jet.lang.resolve.scopes.JetScope;
+import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
+import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.plugin.JetLanguage;
import org.jetbrains.jet.test.InnerTestClasses;
import org.jetbrains.jet.test.TestMetadata;
@@ -614,4 +622,17 @@ public class JetTestUtils {
descriptor.setModuleConfiguration(ModuleConfiguration.EMPTY);
return descriptor;
}
+
+ @NotNull
+ public static NamespaceDescriptorImpl createTestNamespace(@NotNull String testPackageName) {
+ ModuleDescriptorImpl module = new ModuleDescriptorImpl(Name.special(""), JavaBridgeConfiguration.ALL_JAVA_IMPORTS,
+ JavaToKotlinClassMap.getInstance());
+ NamespaceDescriptorImpl rootNamespace =
+ new NamespaceDescriptorImpl(module, Collections.emptyList(), JetPsiUtil.ROOT_NAMESPACE_NAME);
+ module.setRootNamespace(rootNamespace);
+ NamespaceDescriptorImpl test =
+ new NamespaceDescriptorImpl(rootNamespace, Collections.emptyList(), Name.identifier(testPackageName));
+ test.initialize(new WritableScopeImpl(JetScope.EMPTY, test, RedeclarationHandler.DO_NOTHING, "members of test namespace"));
+ return test;
+ }
}
diff --git a/compiler/tests/org/jetbrains/jet/descriptors/serialization/BuiltinsDeserializationTest.java b/compiler/tests/org/jetbrains/jet/descriptors/serialization/BuiltinsDeserializationTest.java
index df8b1a24bd4..2a14c3aac34 100644
--- a/compiler/tests/org/jetbrains/jet/descriptors/serialization/BuiltinsDeserializationTest.java
+++ b/compiler/tests/org/jetbrains/jet/descriptors/serialization/BuiltinsDeserializationTest.java
@@ -21,31 +21,28 @@ import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.ConfigurationKind;
+import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.TestJdkKind;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer;
import org.jetbrains.jet.jvm.compiler.ExpectedLoadErrorsUtil;
import org.jetbrains.jet.lang.descriptors.*;
-import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl;
-import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
-import org.jetbrains.jet.lang.resolve.java.JavaBridgeConfiguration;
-import org.jetbrains.jet.lang.resolve.java.JavaToKotlinClassMap;
import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment;
import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
-import org.jetbrains.jet.lang.resolve.scopes.JetScope;
-import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
-import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.renderer.DescriptorRenderer;
import org.jetbrains.jet.renderer.DescriptorRendererBuilder;
import org.jetbrains.jet.test.util.NamespaceComparator;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
import static org.jetbrains.jet.descriptors.serialization.ClassSerializationUtil.constantSerializer;
@@ -95,7 +92,8 @@ public class BuiltinsDeserializationTest extends KotlinTestWithEnvironment {
List callableProtos = serializeCallables(serializer, allDescriptors);
- final NamespaceDescriptorImpl actualNamespace = createTestNamespace(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME.shortName().asString());
+ final NamespaceDescriptorImpl actualNamespace = JetTestUtils
+ .createTestNamespace(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME.shortName().asString());
final NameResolver nameResolver = NameSerializationUtil.createNameResolver(serializer.getNameTable());
@@ -215,16 +213,4 @@ public class BuiltinsDeserializationTest extends KotlinTestWithEnvironment {
private static ClassId getClassId(ClassDescriptor classDescriptor) {
return ClassSerializationUtil.getClassId(classDescriptor, NAMER);
}
-
- private static NamespaceDescriptorImpl createTestNamespace(String testPackageName) {
- ModuleDescriptorImpl module = new ModuleDescriptorImpl(Name.special(""), JavaBridgeConfiguration.ALL_JAVA_IMPORTS,
- JavaToKotlinClassMap.getInstance());
- NamespaceDescriptorImpl rootNamespace =
- new NamespaceDescriptorImpl(module, Collections.emptyList(), JetPsiUtil.ROOT_NAMESPACE_NAME);
- module.setRootNamespace(rootNamespace);
- NamespaceDescriptorImpl test =
- new NamespaceDescriptorImpl(rootNamespace, Collections.emptyList(), Name.identifier(testPackageName));
- test.initialize(new WritableScopeImpl(JetScope.EMPTY, test, RedeclarationHandler.DO_NOTHING, "members of test namespace"));
- return test;
- }
}
diff --git a/compiler/tests/org/jetbrains/jet/descriptors/serialization/WriteSerializedInfoTest.java b/compiler/tests/org/jetbrains/jet/descriptors/serialization/WriteSerializedInfoTest.java
new file mode 100644
index 00000000000..f5bbac3e51b
--- /dev/null
+++ b/compiler/tests/org/jetbrains/jet/descriptors/serialization/WriteSerializedInfoTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2010-2013 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.jet.descriptors.serialization;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+import jet.KotlinInfo;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.ConfigurationKind;
+import org.jetbrains.jet.JetTestUtils;
+import org.jetbrains.jet.codegen.CodegenTestCase;
+import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer;
+import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
+import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
+import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl;
+import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
+import org.jetbrains.jet.lang.resolve.name.FqName;
+import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
+import org.jetbrains.jet.lang.resolve.name.Name;
+
+import java.io.ByteArrayInputStream;
+
+public class WriteSerializedInfoTest extends CodegenTestCase {
+ public static final FqName NAMESPACE_NAME = new FqName("test");
+ public static final FqNameUnsafe CLASS_NAME = new FqNameUnsafe("A");
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL);
+ }
+
+ public void testKotlinInfo() throws Exception {
+ loadText("package " + NAMESPACE_NAME + "\n" +
+ "\n" +
+ "class " + CLASS_NAME + " {\n" +
+ " fun foo() {}\n" +
+ " fun bar() = 42\n" +
+ "}\n");
+ Class aClass = generateClass(NAMESPACE_NAME + "." + CLASS_NAME);
+
+ assertTrue(aClass.isAnnotationPresent(KotlinInfo.class));
+ KotlinInfo kotlinInfo = (KotlinInfo) aClass.getAnnotation(KotlinInfo.class);
+
+ AbstractClassResolver classResolver = new KotlinInfoBasedClassResolver(kotlinInfo);
+
+ ClassDescriptor descriptor = classResolver.findClass(new ClassId(NAMESPACE_NAME, CLASS_NAME));
+ assertNotNull(descriptor);
+ assertEquals(CLASS_NAME.asString(), descriptor.getName().asString());
+ }
+
+ private static class KotlinInfoBasedClassResolver extends AbstractClassResolver {
+ private final NameResolver nameResolver;
+ private final ProtoBuf.Class classProto;
+ private final NamespaceDescriptorImpl namespace;
+
+ public KotlinInfoBasedClassResolver(@NotNull KotlinInfo kotlinInfo) throws InvalidProtocolBufferException {
+ super(new LockBasedStorageManager(), AnnotationDeserializer.UNSUPPORTED);
+
+ this.nameResolver = NameSerializationUtil.deserializeNameResolver(new ByteArrayInputStream(kotlinInfo.nameTable()));
+ this.classProto = ProtoBuf.Class.parseFrom(kotlinInfo.data());
+ this.namespace = JetTestUtils.createTestNamespace(NAMESPACE_NAME.asString());
+ }
+
+ @Nullable
+ @Override
+ protected ClassData getClassData(@NotNull ClassId classId) {
+ assert classId.getPackageFqName().equals(NAMESPACE_NAME) &&
+ classId.getRelativeClassName().equals(CLASS_NAME) : "Unsupported classId: " + classId;
+ return new ClassData(nameResolver, classProto);
+ }
+
+ @NotNull
+ @Override
+ protected DeclarationDescriptor getPackage(@NotNull FqName fqName) {
+ assert fqName.equals(NAMESPACE_NAME) : "Unsupported namespace: " + fqName;
+ return namespace;
+ }
+
+ @NotNull
+ @Override
+ protected ClassId getClassId(@NotNull ClassDescriptor classDescriptor) {
+ return ClassSerializationUtil.getClassId(classDescriptor, DescriptorNamer.DEFAULT);
+ }
+
+ @NotNull
+ @Override
+ protected Name getClassObjectName(@NotNull ClassDescriptor outerClass) {
+ return Name.special("");
+ }
+
+ @Override
+ protected void classDescriptorCreated(@NotNull ClassDescriptor classDescriptor) {
+ }
+ }
+}
diff --git a/runtime/src/jet/KotlinInfo.java b/runtime/src/jet/KotlinInfo.java
new file mode 100644
index 00000000000..cbbd5bd8dde
--- /dev/null
+++ b/runtime/src/jet/KotlinInfo.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010-2013 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 jet;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface KotlinInfo {
+ byte[] data();
+
+ byte[] nameTable();
+}