Resolve static methods of enum in front-end
Up to this point, front-end did not suspect that there could be classes which have both a class object and a package for static members. Since this became possible for enums loaded from Java binaries (enum entries and valueOf()/ values() are placed into the class object, and every other static member into the package), we adjust the corresponding scope to also include members from the corresponding package #KT-2990 Fixed
This commit is contained in:
+33
-11
@@ -46,7 +46,9 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
|||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||||
@@ -71,18 +73,9 @@ public class CallExpressionResolver {
|
|||||||
JetType classObjectType = classifier.getClassObjectType();
|
JetType classObjectType = classifier.getClassObjectType();
|
||||||
if (classObjectType != null) {
|
if (classObjectType != null) {
|
||||||
context.trace.record(REFERENCE_TARGET, expression, classifier);
|
context.trace.record(REFERENCE_TARGET, expression, classifier);
|
||||||
JetType result;
|
JetType result = getExtendedClassObjectType(classObjectType, referencedName, classifier, context);
|
||||||
if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT && classifier instanceof ClassDescriptor) {
|
if (result == null) {
|
||||||
JetScope scope = new ChainedScope(classifier, classObjectType.getMemberScope(),
|
|
||||||
getStaticNestedClassesScope((ClassDescriptor) classifier));
|
|
||||||
result = new NamespaceType(referencedName, scope);
|
|
||||||
}
|
|
||||||
else if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT || classifier.isClassObjectAValue()) {
|
|
||||||
result = classObjectType;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
|
context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
|
||||||
result = null;
|
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(result, expression, context);
|
return DataFlowUtils.checkType(result, expression, context);
|
||||||
}
|
}
|
||||||
@@ -109,6 +102,35 @@ public class CallExpressionResolver {
|
|||||||
return result[0];
|
return result[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private JetType getExtendedClassObjectType(
|
||||||
|
@NotNull JetType classObjectType,
|
||||||
|
@NotNull Name referencedName,
|
||||||
|
@NotNull ClassifierDescriptor classifier,
|
||||||
|
@NotNull ResolutionContext context
|
||||||
|
) {
|
||||||
|
if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT && classifier instanceof ClassDescriptor) {
|
||||||
|
List<JetScope> scopes = new ArrayList<JetScope>(3);
|
||||||
|
|
||||||
|
scopes.add(classObjectType.getMemberScope());
|
||||||
|
scopes.add(getStaticNestedClassesScope((ClassDescriptor) classifier));
|
||||||
|
|
||||||
|
NamespaceDescriptor namespace = context.scope.getNamespace(referencedName);
|
||||||
|
if (namespace != null) {
|
||||||
|
scopes.add(namespace.getMemberScope());
|
||||||
|
}
|
||||||
|
|
||||||
|
JetScope scope = new ChainedScope(classifier, scopes.toArray(new JetScope[scopes.size()]));
|
||||||
|
return new NamespaceType(referencedName, scope);
|
||||||
|
}
|
||||||
|
else if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT || classifier.isClassObjectAValue()) {
|
||||||
|
return classObjectType;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean furtherNameLookup(
|
private boolean furtherNameLookup(
|
||||||
@NotNull JetSimpleNameExpression expression,
|
@NotNull JetSimpleNameExpression expression,
|
||||||
@NotNull JetType[] result,
|
@NotNull JetType[] result,
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
public enum staticField {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public static int foo = 42;
|
||||||
|
|
||||||
|
public static final Set<staticField> INSTANCES = EnumSet.of(INSTANCE);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import test.staticField as E
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val instances = E.INSTANCES
|
||||||
|
if (E.foo != 42)
|
||||||
|
return "Wrong foo ${E.foo}"
|
||||||
|
if (instances.size() != 1)
|
||||||
|
return "Wrong size ${instances.size()}"
|
||||||
|
if (E.INSTANCES.iterator().next() != E.INSTANCE)
|
||||||
|
return "Wrong instance ${E.INSTANCES.iterator().next()}"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public enum staticMethod {
|
||||||
|
ENTRY;
|
||||||
|
|
||||||
|
public static String foo() {
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
fun box() = test.staticMethod.foo()
|
||||||
+10
@@ -63,6 +63,16 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
|||||||
doTestWithJava("compiler/testData/codegen/boxWithJava/enum/simpleJavaInnerEnum.kt");
|
doTestWithJava("compiler/testData/codegen/boxWithJava/enum/simpleJavaInnerEnum.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("staticField.kt")
|
||||||
|
public void testStaticField() throws Exception {
|
||||||
|
doTestWithJava("compiler/testData/codegen/boxWithJava/enum/staticField.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("staticMethod.kt")
|
||||||
|
public void testStaticMethod() throws Exception {
|
||||||
|
doTestWithJava("compiler/testData/codegen/boxWithJava/enum/staticMethod.kt");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithJava/functions")
|
@TestMetadata("compiler/testData/codegen/boxWithJava/functions")
|
||||||
|
|||||||
Reference in New Issue
Block a user