fixed INACCESSIBLE_OUTER_CLASS_EXPRESSION check
for extension lambda (with implicit this) in nested class
This commit is contained in:
@@ -39,7 +39,6 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
|||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
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.lang.types.lang.KotlinBuiltIns;
|
||||||
import org.jetbrains.jet.lexer.JetKeywordToken;
|
import org.jetbrains.jet.lexer.JetKeywordToken;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
@@ -1310,36 +1309,22 @@ public class DescriptorResolver {
|
|||||||
@NotNull PsiElement reportErrorsOn,
|
@NotNull PsiElement reportErrorsOn,
|
||||||
@NotNull ClassDescriptor target
|
@NotNull ClassDescriptor target
|
||||||
) {
|
) {
|
||||||
return checkHasOuterClassInstance(scope, trace, reportErrorsOn, target, true);
|
ClassDescriptor classDescriptor = getContainingClass(scope);
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean checkHasOuterClassInstance(
|
if (!isInsideOuterClassOrItsSubclass(classDescriptor, target)) {
|
||||||
@NotNull JetScope scope,
|
return true;
|
||||||
@NotNull BindingTrace trace,
|
}
|
||||||
@NotNull PsiElement reportErrorsOn,
|
|
||||||
@NotNull ClassDescriptor target,
|
|
||||||
boolean doSuperClassCheck
|
|
||||||
) {
|
|
||||||
DeclarationDescriptor descriptor = getContainingClass(scope);
|
|
||||||
|
|
||||||
while (descriptor != null) {
|
while (classDescriptor != null) {
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
if (isSubclass(classDescriptor, target)) {
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
|
return true;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,8 +135,7 @@ public class TypeResolver {
|
|||||||
|
|
||||||
DeclarationDescriptor containing = typeParameterDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containing = typeParameterDescriptor.getContainingDeclaration();
|
||||||
if (containing instanceof ClassDescriptor) {
|
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);
|
||||||
DescriptorResolver.checkHasOuterClassInstance(c.scope, c.trace, referenceExpression, (ClassDescriptor) containing, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (classifierDescriptor instanceof ClassDescriptor) {
|
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");
|
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")
|
@TestMetadata("illegalModifier.kt")
|
||||||
public void testIllegalModifier() throws Exception {
|
public void testIllegalModifier() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/inner/illegalModifier.kt");
|
doTest("compiler/testData/diagnostics/tests/inner/illegalModifier.kt");
|
||||||
|
|||||||
@@ -421,6 +421,14 @@ public class DescriptorUtils {
|
|||||||
return parameterTypes;
|
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) {
|
public static boolean isConstructorOfStaticNestedClass(@Nullable CallableDescriptor descriptor) {
|
||||||
return descriptor instanceof ConstructorDescriptor && isStaticNestedClass(descriptor.getContainingDeclaration());
|
return descriptor instanceof ConstructorDescriptor && isStaticNestedClass(descriptor.getContainingDeclaration());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user