fixed INACCESSIBLE_OUTER_CLASS_EXPRESSION check

for extension lambda (with implicit this) in nested class
This commit is contained in:
Svetlana Isakova
2013-12-17 15:32:50 +04:00
parent 400e6d3f44
commit 26f66eaea5
5 changed files with 54 additions and 30 deletions
@@ -39,7 +39,6 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.lang.InlineStrategy;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetKeywordToken;
import org.jetbrains.jet.lexer.JetTokens;
@@ -1310,36 +1309,22 @@ public class DescriptorResolver {
@NotNull PsiElement reportErrorsOn,
@NotNull ClassDescriptor target
) {
return checkHasOuterClassInstance(scope, trace, reportErrorsOn, target, true);
}
ClassDescriptor classDescriptor = getContainingClass(scope);
public static boolean checkHasOuterClassInstance(
@NotNull JetScope scope,
@NotNull BindingTrace trace,
@NotNull PsiElement reportErrorsOn,
@NotNull ClassDescriptor target,
boolean doSuperClassCheck
) {
DeclarationDescriptor descriptor = getContainingClass(scope);
if (!isInsideOuterClassOrItsSubclass(classDescriptor, target)) {
return true;
}
while (descriptor != null) {
if (descriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
if (classDescriptor == target) {
return true;
}
if (doSuperClassCheck && isSubclass(classDescriptor, target)) {
return true;
}
if (isStaticNestedClass(classDescriptor)) {
trace.report(INACCESSIBLE_OUTER_CLASS_EXPRESSION.on(reportErrorsOn, classDescriptor));
return false;
}
while (classDescriptor != null) {
if (isSubclass(classDescriptor, target)) {
return true;
}
descriptor = descriptor.getContainingDeclaration();
if (isStaticNestedClass(classDescriptor)) {
trace.report(INACCESSIBLE_OUTER_CLASS_EXPRESSION.on(reportErrorsOn, classDescriptor));
return false;
}
classDescriptor = getParentOfType(classDescriptor, ClassDescriptor.class, true);
}
return true;
}
@@ -135,8 +135,7 @@ public class TypeResolver {
DeclarationDescriptor containing = typeParameterDescriptor.getContainingDeclaration();
if (containing instanceof ClassDescriptor) {
// Type parameter can't be inherited from member of parent class, so we can skip subclass check
DescriptorResolver.checkHasOuterClassInstance(c.scope, c.trace, referenceExpression, (ClassDescriptor) containing, false);
DescriptorResolver.checkHasOuterClassInstance(c.scope, c.trace, referenceExpression, (ClassDescriptor) containing);
}
}
else if (classifierDescriptor instanceof ClassDescriptor) {
@@ -0,0 +1,27 @@
package f
object A {
class LoginFormPage() : Request({
val failed = session.get("LOGIN_FAILED")
})
}
class B {
class object {
class LoginFormPage() : Request({
val failed = session.get("LOGIN_FAILED")
})
}
class C {
class LoginFormPage() : Request({
val failed = session.get("LOGIN_FAILED")
})
}
}
open class Request(private val handler: ActionContext.() -> Unit) {}
trait ActionContext {
val session : Map<String, String>
}
@@ -4216,6 +4216,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/inner/extensionFun.kt");
}
@TestMetadata("extensionLambdaInsideNestedClass.kt")
public void testExtensionLambdaInsideNestedClass() throws Exception {
doTest("compiler/testData/diagnostics/tests/inner/extensionLambdaInsideNestedClass.kt");
}
@TestMetadata("illegalModifier.kt")
public void testIllegalModifier() throws Exception {
doTest("compiler/testData/diagnostics/tests/inner/illegalModifier.kt");
@@ -421,6 +421,14 @@ public class DescriptorUtils {
return parameterTypes;
}
public static boolean isInsideOuterClassOrItsSubclass(@Nullable DeclarationDescriptor nested, @NotNull ClassDescriptor outer) {
if (nested == null) return false;
if (nested instanceof ClassDescriptor && isSubclass((ClassDescriptor) nested, outer)) return true;
return isInsideOuterClassOrItsSubclass(nested.getContainingDeclaration(), outer);
}
public static boolean isConstructorOfStaticNestedClass(@Nullable CallableDescriptor descriptor) {
return descriptor instanceof ConstructorDescriptor && isStaticNestedClass(descriptor.getContainingDeclaration());
}