diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java index 93795649b1e..a1e27dd874d 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.java.*; import org.jetbrains.jet.lang.resolve.java.data.ResolverBinaryClassData; import org.jetbrains.jet.lang.resolve.java.data.ResolverClassData; @@ -151,7 +152,7 @@ public final class JavaClassResolver { } // Not let's take a descriptor of a Java class - ResolverClassData classData = classDescriptorCache.get(qualifiedName); + ResolverClassData classData = classDescriptorCache.get(getCorrectedFqName(qualifiedName)); if (classData != null) { return classData.getClassDescriptor(); } @@ -163,15 +164,15 @@ public final class JavaClassResolver { private ClassDescriptor doResolveClass(@NotNull FqName qualifiedName, @NotNull PostponedTasks tasks) { PsiClass psiClass = psiClassFinder.findPsiClass(qualifiedName, PsiClassFinder.RuntimeClassesHandleMode.THROW); if (psiClass == null) { - cacheValue(qualifiedName); + cacheNegativeValue(qualifiedName); return null; } ResolverClassData classData = createJavaClassDescriptor(qualifiedName, psiClass, tasks); return classData.getClassDescriptor(); } - private void cacheValue(@NotNull FqName qualifiedName) { - ResolverClassData oldValue = classDescriptorCache.put(qualifiedName, ResolverBinaryClassData.NEGATIVE); + private void cacheNegativeValue(@NotNull FqName qualifiedName) { + ResolverClassData oldValue = classDescriptorCache.put(getCorrectedFqName(qualifiedName), ResolverBinaryClassData.NEGATIVE); if (oldValue != null) { throw new IllegalStateException("rewrite at " + qualifiedName); } @@ -193,7 +194,7 @@ public final class JavaClassResolver { ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(psiClass); // class may be resolved during resolution of parent - ResolverClassData classData = classDescriptorCache.get(fqName); + ResolverClassData classData = classDescriptorCache.get(getCorrectedFqName(fqName)); if (classData != null) { return classData; } @@ -214,7 +215,7 @@ public final class JavaClassResolver { = new ClassDescriptorFromJvmBytecode(containingDeclaration, kind, psiClass, fqName, javaDescriptorResolver); ResolverClassData classData = classDescriptor.getResolverBinaryClassData(); - classDescriptorCache.put(fqName, classData); + classDescriptorCache.put(getCorrectedFqName(fqName), classData); classDescriptor.setName(Name.identifier(psiClass.getName())); List typeParameterDescriptorInitializations @@ -276,7 +277,7 @@ public final class JavaClassResolver { FqName fqName = new FqName(qualifiedName); assert fqName.equals(desiredFqName); - if (classDescriptorCache.containsKey(fqName)) { + if (classDescriptorCache.containsKey(getCorrectedFqName(fqName))) { throw new IllegalStateException(qualifiedName); } } @@ -298,6 +299,26 @@ public final class JavaClassResolver { return new FqName(qualifiedName); } + @NotNull + private static FqNameUnsafe getCorrectedFqName(@NotNull FqName rawFqName) { + StringBuilder correctedFqName = new StringBuilder(); + List segments = rawFqName.pathSegments(); + for (int i = 0; i < segments.size(); i++) { + Name segment = segments.get(i); + if (correctedFqName.length() != 0) { + correctedFqName.append("."); + } + if (JvmAbi.CLASS_OBJECT_CLASS_NAME.equals(segment.getName())) { + assert i != 0; + correctedFqName.append(DescriptorUtils.getClassObjectName(segments.get(i - 1))); + } + else { + correctedFqName.append(segment); + } + } + return new FqNameUnsafe(correctedFqName.toString()); + } + private static boolean isContainedInClass(@NotNull PsiClass psiClass) { return psiClass.getContainingClass() != null; } diff --git a/compiler/testData/loadKotlin/class/NamedObjectInClassObject.kt b/compiler/testData/loadKotlin/class/NamedObjectInClassObject.kt new file mode 100644 index 00000000000..89e05701b3d --- /dev/null +++ b/compiler/testData/loadKotlin/class/NamedObjectInClassObject.kt @@ -0,0 +1,10 @@ +package test + +public class Outer { + public class object { + public object Obj { + public val v: String = "val" + public fun f(): String = "fun" + } + } +} diff --git a/compiler/testData/loadKotlin/class/NamedObjectInClassObject.txt b/compiler/testData/loadKotlin/class/NamedObjectInClassObject.txt new file mode 100644 index 00000000000..3da8800ded0 --- /dev/null +++ b/compiler/testData/loadKotlin/class/NamedObjectInClassObject.txt @@ -0,0 +1,14 @@ +namespace test + +public final class test.Outer : jet.Any { + public final /*constructor*/ fun (): test.Outer + public final class object test.Outer. : jet.Any { + private final /*constructor*/ fun (): test.Outer. + public final val Obj: test.Outer..Obj + public final object test.Outer..Obj : jet.Any { + private final /*constructor*/ fun (): test.Outer..Obj + public final fun f(): jet.String + public final val v: jet.String + } + } +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java index 0d75f506bf3..b84ce1ee531 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java @@ -140,6 +140,11 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT doTest("compiler/testData/loadKotlin/class/NamedObject.kt"); } + @TestMetadata("NamedObjectInClassObject.kt") + public void testNamedObjectInClassObject() throws Exception { + doTest("compiler/testData/loadKotlin/class/NamedObjectInClassObject.kt"); + } + @TestMetadata("NamedObjectInNamedObject.kt") public void testNamedObjectInNamedObject() throws Exception { doTest("compiler/testData/loadKotlin/class/NamedObjectInNamedObject.kt");