Always create descriptors for class object psi element in lazy resolve

KT-4397 Exception: @NotNull method org/jetbrains/jet/lang/resolve/lazy/ResolveSession.getClassDescriptor must not return null

 #KT-4397 Fixed
This commit is contained in:
Nikolay Krasko
2014-01-11 23:44:41 +04:00
parent 4928ff575d
commit c0187ffcd1
9 changed files with 65 additions and 30 deletions
@@ -214,7 +214,8 @@ public class ResolveSession implements KotlinCodeAnalyzer {
return (ClassDescriptor) declaration; return (ClassDescriptor) declaration;
} }
/*package*/ LazyClassDescriptor getClassObjectDescriptor(JetClassObject classObject) { @NotNull
/*package*/ LazyClassDescriptor getClassObjectDescriptor(@NotNull JetClassObject classObject) {
JetClass aClass = PsiTreeUtil.getParentOfType(classObject, JetClass.class); JetClass aClass = PsiTreeUtil.getParentOfType(classObject, JetClass.class);
final LazyClassDescriptor parentClassDescriptor; final LazyClassDescriptor parentClassDescriptor;
@@ -237,16 +238,18 @@ public class ResolveSession implements KotlinCodeAnalyzer {
// It's possible that there are several class objects and another class object is taking part in lazy resolve. We still want to // It's possible that there are several class objects and another class object is taking part in lazy resolve. We still want to
// build descriptors for such class objects. // build descriptors for such class objects.
final JetClassLikeInfo classObjectInfo = parentClassDescriptor.getClassObjectInfo(classObject); final JetClassLikeInfo classObjectInfo = parentClassDescriptor.getClassObjectInfo(classObject);
if (classObjectInfo != null) { assert classObjectInfo != null :
final Name name = SpecialNames.getClassObjectName(parentClassDescriptor.getName()); String.format("Failed to find class object info for existent class object declaration: %s",
return storageManager.compute(new Function0<LazyClassDescriptor>() { JetPsiUtil.getElementTextWithContext(classObject));
@Override
public LazyClassDescriptor invoke() { final Name name = SpecialNames.getClassObjectName(parentClassDescriptor.getName());
// Create under lock to avoid premature access to published 'this' return storageManager.compute(new Function0<LazyClassDescriptor>() {
return new LazyClassDescriptor(ResolveSession.this, parentClassDescriptor, name, classObjectInfo); @Override
} public LazyClassDescriptor invoke() {
}); // Create under lock to avoid premature access to published 'this'
} return new LazyClassDescriptor(ResolveSession.this, parentClassDescriptor, name, classObjectInfo);
}
});
} }
return (LazyClassDescriptor) declaration; return (LazyClassDescriptor) declaration;
@@ -258,9 +258,6 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
@Nullable @Nullable
public JetClassLikeInfo getClassObjectInfo(JetClassObject classObject) { public JetClassLikeInfo getClassObjectInfo(JetClassObject classObject) {
if (classObject != null) { if (classObject != null) {
if (!DescriptorUtils.inStaticContext(this)) {
return null;
}
JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration(); JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
if (objectDeclaration != null) { if (objectDeclaration != null) {
return JetClassInfoUtil.createClassLikeInfo(objectDeclaration); return JetClassInfoUtil.createClassLikeInfo(objectDeclaration);
@@ -269,6 +266,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
else if (getKind() == ClassKind.OBJECT || getKind() == ClassKind.ENUM_ENTRY || getKind() == ClassKind.ENUM_CLASS) { else if (getKind() == ClassKind.OBJECT || getKind() == ClassKind.ENUM_ENTRY || getKind() == ClassKind.ENUM_CLASS) {
return new SyntheticClassObjectInfo(originalClassInfo, this); return new SyntheticClassObjectInfo(originalClassInfo, this);
} }
return null; return null;
} }
@@ -0,0 +1,9 @@
package test
class A {
class B {
class object {
val TEST = 1
}
}
}
@@ -0,0 +1,15 @@
package test
internal final class A {
/*primary*/ public constructor A()
internal final class B {
/*primary*/ public constructor B()
internal class object <class-object-for-B> {
/*primary*/ private constructor <class-object-for-B>()
internal final val TEST: jet.Int
internal final fun <get-TEST>(): jet.Int
}
}
}
@@ -1577,6 +1577,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/classes/ClassObject.kt"); doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/classes/ClassObject.kt");
} }
@TestMetadata("ClassObjectInStaticNestedClass.kt")
public void testClassObjectInStaticNestedClass() throws Exception {
doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/classes/ClassObjectInStaticNestedClass.kt");
}
@TestMetadata("Deprecated.kt") @TestMetadata("Deprecated.kt")
public void testDeprecated() throws Exception { public void testDeprecated() throws Exception {
doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/classes/Deprecated.kt"); doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/classes/Deprecated.kt");
@@ -105,6 +105,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/classes/ClassObject.kt"); doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/classes/ClassObject.kt");
} }
@TestMetadata("ClassObjectInStaticNestedClass.kt")
public void testClassObjectInStaticNestedClass() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/classes/ClassObjectInStaticNestedClass.kt");
}
@TestMetadata("Deprecated.kt") @TestMetadata("Deprecated.kt")
public void testDeprecated() throws Exception { public void testDeprecated() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/classes/Deprecated.kt"); doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/classes/Deprecated.kt");
@@ -310,22 +310,6 @@ public class DescriptorUtils {
return superClassDescriptor.equals(KotlinBuiltIns.getInstance().getAny()); return superClassDescriptor.equals(KotlinBuiltIns.getInstance().getAny());
} }
public static boolean inStaticContext(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration instanceof PackageFragmentDescriptor) {
return true;
}
if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
if (classDescriptor.getKind().isSingleton()) {
return inStaticContext(classDescriptor.getContainingDeclaration());
}
}
return false;
}
public static boolean isEnumClassObject(@NotNull DeclarationDescriptor descriptor) { public static boolean isEnumClassObject(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() == ClassKind.CLASS_OBJECT) { if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() == ClassKind.CLASS_OBJECT) {
DeclarationDescriptor containing = descriptor.getContainingDeclaration(); DeclarationDescriptor containing = descriptor.getContainingDeclaration();
@@ -0,0 +1,12 @@
trait <lineMarker></lineMarker>TestTrait {
fun <lineMarker></lineMarker>test()
}
class A {
class B {
class object : TestTrait { // TODO: No line marker
override fun <lineMarker descr="<b>internal</b> <b>open</b> <b>fun</b> test(): jet.Unit <i>defined in</i> A.B.&lt;class-object-for-B&gt;<br/>implements<br/><b>internal</b> <b>abstract</b> <b>fun</b> test(): jet.Unit <i>defined in</i> TestTrait"></lineMarker>test() {
}
}
}
}
@@ -61,6 +61,10 @@ public class OverrideImplementLineMarkerTest extends JetLightCodeInsightFixtureT
doTest(); doTest();
} }
public void testClassObjectInStaticNestedClass() throws Exception {
doTest();
}
public void testFakeOverrideProperty() throws Exception { public void testFakeOverrideProperty() throws Exception {
doTest(); doTest();
} }