LHS of qualified expressions are determined manually

ExpressionPosition is useless now and will be dropped

 #KT-3866 Fixed
This commit is contained in:
Alexander Udalov
2013-11-14 23:33:55 +04:00
parent e8089cc461
commit 838c408e68
5 changed files with 48 additions and 13 deletions
@@ -431,6 +431,13 @@ public class JetPsiUtil {
return selectorParent instanceof JetQualifiedExpression && (((JetQualifiedExpression) selectorParent).getSelectorExpression() == selector);
}
public static boolean isLHSOfDot(@NotNull JetExpression expression) {
PsiElement parent = expression.getParent();
if (!(parent instanceof JetQualifiedExpression)) return false;
JetQualifiedExpression qualifiedParent = (JetQualifiedExpression) parent;
return qualifiedParent.getReceiverExpression() == expression || isLHSOfDot(qualifiedParent);
}
public static boolean isVoidType(@Nullable JetTypeReference typeReference) {
if (typeReference == null) {
return false;
@@ -53,6 +53,7 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
import static org.jetbrains.jet.lang.psi.JetPsiUtil.isLHSOfDot;
public class CallExpressionResolver {
@NotNull
@@ -71,7 +72,7 @@ public class CallExpressionResolver {
JetType classObjectType = classifier.getClassObjectType();
if (classObjectType != null) {
context.trace.record(REFERENCE_TARGET, expression, classifier);
JetType result = getExtendedClassObjectType(classObjectType, referencedName, classifier, context);
JetType result = getExtendedClassObjectType(expression, classObjectType, classifier, context);
checkClassObjectVisibility(classifier, expression, context);
return DataFlowUtils.checkType(result, expression, context);
}
@@ -86,14 +87,14 @@ public class CallExpressionResolver {
// To report NO_CLASS_OBJECT when no namespace found
if (classifier != null) {
if (classifier instanceof TypeParameterDescriptor) {
if (context.expressionPosition == ExpressionPosition.FREE) {
context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(expression, (TypeParameterDescriptor) classifier));
}
else {
if (isLHSOfDot(expression)) {
context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(expression, (TypeParameterDescriptor) classifier));
}
else {
context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(expression, (TypeParameterDescriptor) classifier));
}
}
else if (context.expressionPosition == ExpressionPosition.FREE) {
else if (!isLHSOfDot(expression)) {
context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
}
context.trace.record(REFERENCE_TARGET, expression, classifier);
@@ -134,17 +135,18 @@ public class CallExpressionResolver {
@NotNull
private static JetType getExtendedClassObjectType(
@NotNull JetSimpleNameExpression expression,
@NotNull JetType classObjectType,
@NotNull Name referencedName,
@NotNull ClassifierDescriptor classifier,
@NotNull ResolutionContext context
) {
if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT && classifier instanceof ClassDescriptor) {
if (isLHSOfDot(expression) && classifier instanceof ClassDescriptor) {
List<JetScope> scopes = new ArrayList<JetScope>(3);
scopes.add(classObjectType.getMemberScope());
scopes.add(getStaticNestedClassesScope((ClassDescriptor) classifier));
Name referencedName = expression.getReferencedNameAsName();
NamespaceDescriptor namespace = context.scope.getNamespace(referencedName);
if (namespace != null) {
//for enums loaded from java binaries
@@ -166,7 +168,7 @@ public class CallExpressionResolver {
if (namespaceType == null) {
return false;
}
if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT) {
if (isLHSOfDot(expression)) {
result[0] = namespaceType;
return true;
}
@@ -266,7 +268,7 @@ public class CallExpressionResolver {
JetType type = getVariableType(nameExpression, receiver, callOperationNode, context.replaceTraceAndCache(temporaryForVariable), result);
if (result[0]) {
temporaryForVariable.commit();
if (type instanceof NamespaceType && context.expressionPosition == ExpressionPosition.FREE) {
if (type instanceof NamespaceType && !isLHSOfDot(nameExpression)) {
type = null;
}
return JetTypeInfo.create(type, context.dataFlowInfo);
@@ -36,7 +36,6 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability;
import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition;
import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
@@ -281,10 +280,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public JetTypeInfo visitSuperExpression(@NotNull JetSuperExpression expression, ExpressionTypingContext context) {
LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, true);
if (context.expressionPosition == ExpressionPosition.FREE) {
if (!JetPsiUtil.isLHSOfDot(expression)) {
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText()));
return errorInSuper(expression, context);
}
switch (resolutionResult.getCode()) {
case LABEL_RESOLUTION_ERROR:
// The error is already reported
@@ -1124,7 +1124,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override
public JetTypeInfo visitRootNamespaceExpression(@NotNull JetRootNamespaceExpression expression, ExpressionTypingContext context) {
if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT) {
if (JetPsiUtil.isLHSOfDot(expression)) {
return DataFlowUtils.checkType(JetModuleUtil.getRootNamespaceType(expression), expression, context, context.dataFlowInfo);
}
context.trace.report(NAMESPACE_IS_NOT_AN_EXPRESSION.on(expression));
@@ -0,0 +1,21 @@
open class C {
}
fun C.foo() {}
open class X {
class object : C() {}
}
open class Y {
class object : C() {}
}
fun bar() {
val x = X
x.foo()
X.foo()
(X : C).foo()
(X <!USELESS_CAST_STATIC_ASSERT_IS_FINE!>as<!> C).foo()
((if (1<2) X else Y) : C).foo()
}
@@ -1374,6 +1374,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/classObjects/invisibleClassObjects.kt");
}
@TestMetadata("kt3866.kt")
public void testKt3866() throws Exception {
doTest("compiler/testData/diagnostics/tests/classObjects/kt3866.kt");
}
@TestMetadata("nestedClassInPrivateClassObject.kt")
public void testNestedClassInPrivateClassObject() throws Exception {
doTest("compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.kt");