From 26f66eaea56e5ecb62a53263a565029629e7e6b7 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 17 Dec 2013 15:32:50 +0400 Subject: [PATCH] fixed INACCESSIBLE_OUTER_CLASS_EXPRESSION check for extension lambda (with implicit this) in nested class --- .../jet/lang/resolve/DescriptorResolver.java | 41 ++++++------------- .../jet/lang/resolve/TypeResolver.java | 3 +- .../inner/extensionLambdaInsideNestedClass.kt | 27 ++++++++++++ .../checkers/JetDiagnosticsTestGenerated.java | 5 +++ .../jet/lang/resolve/DescriptorUtils.java | 8 ++++ 5 files changed, 54 insertions(+), 30 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inner/extensionLambdaInsideNestedClass.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 5c767c9b0eb..7a89d07fb63 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -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; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 58911656f0c..a22b6ba626f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -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) { diff --git a/compiler/testData/diagnostics/tests/inner/extensionLambdaInsideNestedClass.kt b/compiler/testData/diagnostics/tests/inner/extensionLambdaInsideNestedClass.kt new file mode 100644 index 00000000000..5b0328ab9fe --- /dev/null +++ b/compiler/testData/diagnostics/tests/inner/extensionLambdaInsideNestedClass.kt @@ -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 +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index ff712272d93..ed47a6cb699 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -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"); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index 258dbfdb494..b3e22ef0272 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -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()); }