diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 4deedeb76ff..42680e7ec44 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -591,6 +591,7 @@ public interface Errors { DiagnosticFactory1 NO_CLASS_OBJECT = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 TYPE_PARAMETER_IS_NOT_AN_EXPRESSION = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 TYPE_PARAMETER_ON_LHS_OF_DOT = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 INACCESSIBLE_OUTER_CLASS_EXPRESSION = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 NESTED_CLASS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index 20ba396d42f..276f25ccc57 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -259,6 +259,7 @@ public class DefaultErrorMessages { MAP.put(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION, "Type parameter ''{0}'' is not an expression", NAME); MAP.put(TYPE_PARAMETER_ON_LHS_OF_DOT, "Type parameter ''{0}'' cannot have or inherit a class object, so it cannot be on the left hand side of dot", NAME); MAP.put(NO_GENERICS_IN_SUPERTYPE_SPECIFIER, "Generic arguments of the base type must be specified"); + MAP.put(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE, "Nested {0} accessed via instance reference", RENDER_CLASS_OR_OBJECT_NAME); MAP.put(INACCESSIBLE_OUTER_CLASS_EXPRESSION, "Expression is inaccessible from a nested class ''{0}'', use ''inner'' keyword to make the class inner", NAME); MAP.put(NESTED_CLASS_NOT_ALLOWED, "Nested class is not allowed here, use ''inner'' keyword to make the class inner"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DiagnosticRendererUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DiagnosticRendererUtil.kt index 50130b810b8..8ac62fe9bb0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DiagnosticRendererUtil.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DiagnosticRendererUtil.kt @@ -17,5 +17,29 @@ package org.jetbrains.jet.lang.diagnostics.rendering import org.jetbrains.jet.renderer.Renderer +import org.jetbrains.jet.lang.descriptors.ClassKind +import org.jetbrains.jet.lang.descriptors.ClassKind.* +import org.jetbrains.jet.lang.descriptors.ClassDescriptor +import org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject public fun

renderParameter(parameter: P, renderer: Renderer

?): Any = renderer?.render(parameter) ?: parameter + +public fun ClassDescriptor.renderKindWithName(): String { + val kind = getKind().getText() + if (isClassObject(this)) { + return "$kind of '${getContainingDeclaration().getName()}'" + } + return "$kind '${getName()}'" +} + +public fun ClassKind.getText(): String { + return when (this) { + CLASS -> "class" + TRAIT -> "trait" + ENUM_CLASS -> "enum class" + ENUM_ENTRY -> "enum entry" + ANNOTATION_CLASS -> "annotation class" + OBJECT -> "object" + CLASS_OBJECT -> "class object" + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java index 72d3d2b52da..18c9a874096 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java @@ -112,7 +112,14 @@ public class Renderers { return "Class" + name; } return "Object" + name; + } + }; + public static final Renderer RENDER_CLASS_OR_OBJECT_NAME = new Renderer() { + @NotNull + @Override + public String render(@NotNull ClassDescriptor classifier) { + return RenderingPackage.renderKindWithName(classifier); } }; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index bd96f19da77..ba9e4d38431 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -298,6 +298,7 @@ public class CallExpressionResolver { JetType selectorReturnType = selectorReturnTypeInfo.getType(); resolveDeferredReceiverInQualifiedExpression(qualifierReceiver, expression, context); + checkNestedClassAccess(expression, context); //TODO move further if (expression.getOperationSign() == JetTokens.SAFE_ACCESS) { @@ -338,4 +339,24 @@ public class CallExpressionResolver { ? context.trace.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression) calleeExpression) : null; ReceiversPackage.resolveAsReceiverInQualifiedExpression(qualifierReceiver, context, selectorDescriptor); } + + private static void checkNestedClassAccess( + @NotNull JetQualifiedExpression expression, + @NotNull ExpressionTypingContext context + ) { + JetExpression selectorExpression = expression.getSelectorExpression(); + if (selectorExpression == null) return; + + // A.B - if B is a nested class accessed by outer class, 'A' and 'A.B' were marked as qualifiers + // a.B - if B is a nested class accessed by instance reference, 'a.B' was marked as a qualifier, but 'a' was not (it's an expression) + + QualifierReceiver expressionQualifier = context.trace.get(BindingContext.QUALIFIER_RECEIVER, expression); + QualifierReceiver receiverQualifier = context.trace.get(BindingContext.QUALIFIER_RECEIVER, expression.getReceiverExpression()); + + if (receiverQualifier == null && expressionQualifier != null) { + assert expressionQualifier.getClassifier() instanceof ClassDescriptor : + "Only class can (package cannot) be accessed by instance reference: " + expressionQualifier; + context.trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE.on(selectorExpression, (ClassDescriptor)expressionQualifier.getClassifier())); + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 9fa329f038a..829daade765 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.resolve.calls.model.*; import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus; import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask; import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer; +import org.jetbrains.jet.lang.resolve.calls.util.FakeCallableDescriptorForObject; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.*; @@ -115,6 +116,9 @@ public class CandidateResolver { } } } + if (!checkThisObject(context)) { + candidateCall.addStatus(OTHER_ERROR); + } List jetTypeArguments = context.call.getTypeArguments(); if (jetTypeArguments.isEmpty()) { @@ -167,6 +171,31 @@ public class CandidateResolver { } } + private static boolean checkThisObject(@NotNull CallCandidateResolutionContext context) { + MutableResolvedCall candidateCall = context.candidateCall; + CallableDescriptor candidateDescriptor = candidateCall.getCandidateDescriptor(); + ReceiverValue thisObject = candidateCall.getThisObject(); + if (thisObject.exists()) { + ClassDescriptor nestedClass = null; + if (candidateDescriptor instanceof ConstructorDescriptor + && DescriptorUtils.isStaticNestedClass(candidateDescriptor.getContainingDeclaration())) { + nestedClass = (ClassDescriptor) candidateDescriptor.getContainingDeclaration(); + } + else if (candidateDescriptor instanceof FakeCallableDescriptorForObject) { + nestedClass = ((FakeCallableDescriptorForObject) candidateDescriptor).getReferencedDescriptor(); + } + if (nestedClass != null) { + context.tracing.nestedClassAccessViaInstanceReference(context.trace, nestedClass); + return false; + } + } + + assert (thisObject.exists() == (candidateCall.getResultingDescriptor().getExpectedThisObject() != null)) + : "Shouldn't happen because of TaskPrioritizer: " + candidateDescriptor; + + return true; + } + private static boolean checkOuterClassMemberIsAccessible(@NotNull CallCandidateResolutionContext context) { // In "this@Outer.foo()" the error will be reported on "this@Outer" instead if (context.call.getExplicitReceiver().exists() || context.call.getThisObject().exists()) return true; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java index b33b4cab096..2c1666e2fa4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java @@ -207,9 +207,6 @@ import static org.jetbrains.jet.lang.resolve.calls.ValueArgumentsToParametersMap processFunctionLiteralArguments(); reportUnmappedParameters(); checkReceiverArgument(); - - assert (candidateCall.getThisObject().exists() == (candidateCall.getResultingDescriptor().getExpectedThisObject() != null)) - : "Shouldn't happen because of TaskPrioritizer: " + candidateCall.getCandidateDescriptor(); } private void processFunctionLiteralArguments() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java index 67773161ebe..a4c7fc9ebf9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java @@ -20,10 +20,7 @@ import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorWithVisibility; -import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.calls.inference.*; @@ -130,6 +127,11 @@ public abstract class AbstractTracingStrategy implements TracingStrategy { trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement())); } + @Override + public void nestedClassAccessViaInstanceReference(@NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor) { + trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE.on(reference, classDescriptor)); + } + @Override public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke) { ASTNode callOperationNode = call.getCallOperationNode(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java index 520b28bb8fa..bd815ac118e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java @@ -275,12 +275,6 @@ public class TaskPrioritizer { @NotNull Call call ) { for (D descriptor : descriptors) { - if (descriptor instanceof ConstructorDescriptor && DescriptorUtils.isStaticNestedClass(descriptor.getContainingDeclaration()) - || descriptor instanceof FakeCallableDescriptorForObject) { - // We don't want static nested class constructor or class object / object (as callable) - // to be resolved with expectedThisObject - continue; - } ResolutionCandidate candidate = ResolutionCandidate.create(call, descriptor); candidate.setThisObject(thisObject); candidate.setReceiverArgument(receiverParameter); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java index 21a2f60e5e8..a885ac4c14f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java @@ -17,10 +17,7 @@ package org.jetbrains.jet.lang.resolve.calls.tasks; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorWithVisibility; -import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.JetFunctionLiteralArgument; import org.jetbrains.jet.lang.resolve.BindingTrace; @@ -83,6 +80,9 @@ public interface TracingStrategy { @Override public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {} + @Override + public void nestedClassAccessViaInstanceReference(@NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor) {} + @Override public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke) {} @@ -132,6 +132,8 @@ public interface TracingStrategy { void instantiationOfAbstractClass(@NotNull BindingTrace trace); + void nestedClassAccessViaInstanceReference(@NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor); + void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke); void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 9c1b1f97b36..fb22940f987 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -591,16 +591,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return null; } - ReceiverValue receiver = new TransientReceiver(lhsType); - TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create( - context, "trace to resolve callable reference with receiver", reference); - CallableDescriptor descriptor = resolveCallableNotCheckingArguments( - reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result); - if (result[0]) { - temporaryWithReceiver.commit(); - return descriptor; - } - JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier); TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create( context, "trace to resolve callable reference in static scope", reference); @@ -611,6 +601,16 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return possibleStaticNestedClassConstructor; } + ReceiverValue receiver = new TransientReceiver(lhsType); + TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create( + context, "trace to resolve callable reference with receiver", reference); + CallableDescriptor descriptor = resolveCallableNotCheckingArguments( + reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result); + if (result[0]) { + temporaryWithReceiver.commit(); + return descriptor; + } + return null; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java index f68826c969a..9ed077ef422 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java @@ -454,6 +454,13 @@ public class ControlStructureTypingUtils { throwError(); } + @Override + public void nestedClassAccessViaInstanceReference( + @NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor + ) { + throwError(); + } + @Override public void unsafeCall( @NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke diff --git a/compiler/testData/codegen/box/objects/kt2398.kt b/compiler/testData/codegen/box/objects/kt2398.kt index a71b1eb426b..a8b11518d1a 100644 --- a/compiler/testData/codegen/box/objects/kt2398.kt +++ b/compiler/testData/codegen/box/objects/kt2398.kt @@ -13,6 +13,6 @@ class C { } fun box(): String { - val res = C().Obj.o + C().Obj.InnerObj.k() + C().Obj.D().ko + val res = C.Obj.o + C.Obj.InnerObj.k() + C.Obj.D().ko return if (res == "OKKO") "OK" else "Fail: $res" } diff --git a/compiler/testData/compileKotlinAgainstKotlin/NestedEnum.B.kt b/compiler/testData/compileKotlinAgainstKotlin/NestedEnum.B.kt index ad3eb7e8928..107693e176c 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/NestedEnum.B.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/NestedEnum.B.kt @@ -1,5 +1,5 @@ fun main(args: Array) { - val str = aaa.A().E.A + val str = aaa.A.E.A if (str.toString() != "A") { throw Exception() } diff --git a/compiler/testData/compileKotlinAgainstKotlin/NestedObject.B.kt b/compiler/testData/compileKotlinAgainstKotlin/NestedObject.B.kt index 70f3f5209be..46bfda75910 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/NestedObject.B.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/NestedObject.B.kt @@ -1,5 +1,5 @@ fun main(args: Array) { - val str = aaa.A().O.s + val str = aaa.A.O.s if (str != "OK") { throw Exception() } diff --git a/compiler/testData/diagnostics/tests/inner/extensionFun.kt b/compiler/testData/diagnostics/tests/inner/extensionFun.kt index 6515d9c486c..61bc65eccac 100644 --- a/compiler/testData/diagnostics/tests/inner/extensionFun.kt +++ b/compiler/testData/diagnostics/tests/inner/extensionFun.kt @@ -23,6 +23,6 @@ class Outer { fun Outer.foo() { Outer() - Nested() + Nested() Inner() } diff --git a/compiler/testData/diagnostics/tests/inner/nestedClassAccessedViaInstanceReference.kt b/compiler/testData/diagnostics/tests/inner/nestedClassAccessedViaInstanceReference.kt new file mode 100644 index 00000000000..0bd87c9ae02 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inner/nestedClassAccessedViaInstanceReference.kt @@ -0,0 +1,54 @@ +trait N { fun foo() = 1 } + +class WithClassObject { + class object {} + + class Nested() + class NestedWithClassObject { class object : N } + enum class NestedEnum { A } + object NestedObj : N { fun invoke() = 1 } +} + +class WithoutClassObject { + class Nested() + class NestedWithClassObject { class object : N } + enum class NestedEnum { A } + object NestedObj : N { fun invoke() = 1 } +} + +object Obj { + class Nested() + class NestedWithClassObject { class object : N } + enum class NestedEnum { A } + object NestedObj : N { fun invoke() = 1 } +} + +fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) { + with.Nested() + with.NestedWithClassObject + with.NestedWithClassObject() + with.NestedWithClassObject.foo() + with.NestedEnum.A + with.NestedObj + with.NestedObj() + with.NestedObj.foo() + + without.Nested() + without.NestedWithClassObject + without.NestedWithClassObject() + without.NestedWithClassObject.foo() + without.NestedEnum.A + without.NestedObj + without.NestedObj() + without.NestedObj.foo() + + obj.Nested() + obj.NestedWithClassObject + obj.NestedWithClassObject() + obj.NestedWithClassObject.foo() + obj.NestedEnum.A + obj.NestedObj + obj.NestedObj() + obj.NestedObj.foo() +} + diff --git a/compiler/testData/diagnostics/tests/objects/invokeOnInnerObject.kt b/compiler/testData/diagnostics/tests/objects/invokeOnInnerObject.kt new file mode 100644 index 00000000000..e5caa6319c6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/objects/invokeOnInnerObject.kt @@ -0,0 +1,12 @@ +//no nested class access via instance reference error +fun test() { + A.f("") +} + +class A() { + class object { + object f { + fun invoke(i: Int) = i + } + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/callableReference/function/nestedConstructorFromExtension.kt b/compiler/testData/diagnostics/testsWithStdLib/callableReference/function/nestedConstructorFromExtension.kt index e002f6de142..2918dcdfa1f 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/callableReference/function/nestedConstructorFromExtension.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/callableReference/function/nestedConstructorFromExtension.kt @@ -6,7 +6,7 @@ class A { } fun A.main() { - ::Nested + ::Nested val y = A::Nested y : KFunction0 diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 12f8e82fc01..c331c7ad4e9 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -4944,6 +4944,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/inner/modality.kt"); } + @TestMetadata("nestedClassAccessedViaInstanceReference.kt") + public void testNestedClassAccessedViaInstanceReference() throws Exception { + doTest("compiler/testData/diagnostics/tests/inner/nestedClassAccessedViaInstanceReference.kt"); + } + @TestMetadata("nestedClassExtendsOuter.kt") public void testNestedClassExtendsOuter() throws Exception { doTest("compiler/testData/diagnostics/tests/inner/nestedClassExtendsOuter.kt"); @@ -5896,6 +5901,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/objects"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("invokeOnInnerObject.kt") + public void testInvokeOnInnerObject() throws Exception { + doTest("compiler/testData/diagnostics/tests/objects/invokeOnInnerObject.kt"); + } + @TestMetadata("kt2240.kt") public void testKt2240() throws Exception { doTest("compiler/testData/diagnostics/tests/objects/kt2240.kt"); diff --git a/idea/testData/checker/regression/createInnerInstance.kt b/idea/testData/checker/regression/createInnerInstance.kt index f2b63b0065e..87e54895934 100644 --- a/idea/testData/checker/regression/createInnerInstance.kt +++ b/idea/testData/checker/regression/createInnerInstance.kt @@ -6,5 +6,5 @@ object A { fun test(a: T) { val c = (a as A) - c.B() + c.B() } \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference.kt b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference.kt new file mode 100644 index 00000000000..7678aec4244 --- /dev/null +++ b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference.kt @@ -0,0 +1,16 @@ +// !DIAGNOSTICS_NUMBER: 4 +// !DIAGNOSTICS: NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE + +class A { + class Nested() + class NestedWithClassObject { class object } + enum class NestedEnum { A } + object NestedObj { fun invoke() = 1 } +} + +fun test(a: A) { + a.Nested() + a.NestedWithClassObject + a.NestedEnum + a.NestedObj +} \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference1.txt b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference1.txt new file mode 100644 index 00000000000..2b14c1a71f0 --- /dev/null +++ b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference1.txt @@ -0,0 +1,2 @@ + +Nested class 'Nested' accessed via instance reference \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference2.txt b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference2.txt new file mode 100644 index 00000000000..7c279a99321 --- /dev/null +++ b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference2.txt @@ -0,0 +1,2 @@ + +Nested class object of 'NestedWithClassObject' accessed via instance reference \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference3.txt b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference3.txt new file mode 100644 index 00000000000..08b3d9a6544 --- /dev/null +++ b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference3.txt @@ -0,0 +1,2 @@ + +Nested enum class 'NestedEnum' accessed via instance reference \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference4.txt b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference4.txt new file mode 100644 index 00000000000..a05479088ad --- /dev/null +++ b/idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference4.txt @@ -0,0 +1,2 @@ + +Nested object 'NestedObj' accessed via instance reference \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/highlighter/DiagnosticMessageTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/highlighter/DiagnosticMessageTestGenerated.java index 8e2c26a4e31..7e4a024a7d5 100644 --- a/idea/tests/org/jetbrains/jet/plugin/highlighter/DiagnosticMessageTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/highlighter/DiagnosticMessageTestGenerated.java @@ -98,6 +98,11 @@ public class DiagnosticMessageTestGenerated extends AbstractDiagnosticMessageTes doTest("idea/testData/diagnosticMessage/nameInConstraintIsNotATypeParameter.kt"); } + @TestMetadata("nestedClassAcessedViaInstanceReference.kt") + public void testNestedClassAcessedViaInstanceReference() throws Exception { + doTest("idea/testData/diagnosticMessage/nestedClassAcessedViaInstanceReference.kt"); + } + @TestMetadata("noneApplicable.kt") public void testNoneApplicable() throws Exception { doTest("idea/testData/diagnosticMessage/noneApplicable.kt"); diff --git a/js/js.translator/testData/enum/cases/accessing.kt b/js/js.translator/testData/enum/cases/accessing.kt index c7595608b05..75c77f1bdb5 100644 --- a/js/js.translator/testData/enum/cases/accessing.kt +++ b/js/js.translator/testData/enum/cases/accessing.kt @@ -5,32 +5,25 @@ enum class A { BAR : A() { fun explicitFromEntry() = A.FOO - //fun byThisFromEntry() = this.FOO fun implicitFromEntry() = FOO } fun explicit() = A.FOO - fun byThis() = this.FOO fun implicit() = FOO } fun A.extExplicit() = A.FOO -fun A.extByThis() = this.FOO //fun A.extImplicit() = FOO fun box(): String { assertEquals(A.FOO, A.FOO.explicit(), "explicit access") - assertEquals(A.FOO, A.FOO.byThis(), "access by this") assertEquals(A.FOO, A.FOO.implicit(), "implicit access") assertEquals(A.FOO, A.FOO.explicit(), "explicit access from BAR") - // TODO uncoment when KT-4692 will be fixed - //assertEquals(A.FOO, A.FOO.byThis(), "access by this from BAR") assertEquals(A.FOO, A.FOO.implicit(), "implicit access from BAR") assertEquals(A.FOO, A.FOO.extExplicit(), "explicit access from ext fun") - assertEquals(A.FOO, A.FOO.extByThis(), "access by this from ext fun") - // TODO uncoment when KT-4692 will be fixed + // TODO uncoment when KT-5605 will be fixed //assertEquals(A.FOO, A.FOO.extImplicit(), "implicit access from ext fun") return "OK"