KT-14641: Nested type alias reference via an instance is an error.

This commit is contained in:
Dmitry Petrov
2016-11-09 11:57:26 +03:00
parent a662d777e8
commit 94d7bd7a6b
13 changed files with 70 additions and 28 deletions
@@ -813,7 +813,7 @@ public interface Errors {
DiagnosticFactory1<KtSimpleNameExpression, ClassifierDescriptor> NO_COMPANION_OBJECT = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtSimpleNameExpression, TypeParameterDescriptor> TYPE_PARAMETER_IS_NOT_AN_EXPRESSION = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtSimpleNameExpression, TypeParameterDescriptor> TYPE_PARAMETER_ON_LHS_OF_DOT = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtExpression, ClassDescriptor> NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtExpression, ClassifierDescriptorWithTypeParameters> NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory2<KtExpression, ClassDescriptor, String> NESTED_CLASS_SHOULD_BE_QUALIFIED = DiagnosticFactory2.create(ERROR);
DiagnosticFactory1<PsiElement, ClassDescriptor> INACCESSIBLE_OUTER_CLASS_EXPRESSION = DiagnosticFactory1.create(ERROR);
@@ -17,12 +17,13 @@
package org.jetbrains.kotlin.diagnostics.rendering
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.renderer.DescriptorRenderer
fun <P : Any> renderParameter(parameter: P, renderer: DiagnosticParameterRenderer<P>?, context: RenderingContext): Any
= renderer?.render(parameter, context) ?: parameter
fun ClassDescriptor.renderKindWithName(): String = DescriptorRenderer.getClassKindPrefix(this) + " '" + name + "'"
fun ClassifierDescriptorWithTypeParameters.renderKindWithName(): String = DescriptorRenderer.getClassifierKindPrefix(this) + " '" + name + "'"
fun ClassDescriptor.renderKind(): String = DescriptorRenderer.getClassKindPrefix(this)
fun ClassDescriptor.renderKind(): String = DescriptorRenderer.getClassifierKindPrefix(this)
@@ -38,10 +38,10 @@ import org.jetbrains.kotlin.resolve.calls.inference.*
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ValidityConstraintForConstituentType
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.getValidityConstraintForConstituentType
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
@@ -53,7 +53,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.io.PrintWriter
import java.io.StringWriter
import java.lang.AssertionError
import java.util.*
object Renderers {
@@ -119,7 +118,7 @@ object Renderers {
if (classOrObject is KtClass) "Class" + name else "Object" + name
}
@JvmField val RENDER_CLASS_OR_OBJECT_NAME = Renderer<ClassDescriptor> { it.renderKindWithName() }
@JvmField val RENDER_CLASS_OR_OBJECT_NAME = Renderer<ClassifierDescriptorWithTypeParameters> { it.renderKindWithName() }
@JvmField val RENDER_TYPE = SmartTypeRenderer(DescriptorRenderer.FQ_NAMES_IN_TYPES.withOptions { parameterNamesInFunctionalTypes = false })
@@ -501,10 +501,9 @@ class CallExpressionResolver(
val receiverQualifier = context.trace.get(BindingContext.QUALIFIER, expression.receiverExpression)
if (receiverQualifier == null && expressionQualifier != null) {
assert(expressionQualifier is ClassQualifier) { "Only class can (package cannot) be accessed by instance reference: " + expressionQualifier }
context.trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE.on(
selectorExpression,
(expressionQualifier as ClassQualifier).descriptor))
assert(expressionQualifier is ClassifierQualifier) { "Only class can (package cannot) be accessed by instance reference: " + expressionQualifier }
val descriptor = (expressionQualifier as ClassifierQualifier).descriptor
context.trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE.on(selectorExpression, descriptor))
}
}
}
@@ -0,0 +1,9 @@
class A {
public inner class B { }
public typealias BAlias = B
}
fun f() {
val a = A()
a.<!NO_COMPANION_OBJECT, NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE!>BAlias<!>
}
@@ -0,0 +1,18 @@
package
public fun f(): kotlin.Unit
public final class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final inner class B {
public constructor B()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public typealias BAlias = A.B
}
@@ -20878,6 +20878,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("kt14641.kt")
public void testKt14641() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/kt14641.kt");
doTest(fileName);
}
@TestMetadata("localTypeAlias.kt")
public void testLocalTypeAlias() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/localTypeAlias.kt");
@@ -144,19 +144,25 @@ abstract class DescriptorRenderer {
modifiers = DescriptorRendererModifier.ALL
}
fun getClassKindPrefix(klass: ClassDescriptor): String {
if (klass.isCompanionObject) {
return "companion object"
}
return when (klass.kind) {
ClassKind.CLASS -> "class"
ClassKind.INTERFACE -> "interface"
ClassKind.ENUM_CLASS -> "enum class"
ClassKind.OBJECT -> "object"
ClassKind.ANNOTATION_CLASS -> "annotation class"
ClassKind.ENUM_ENTRY -> "enum entry"
}
}
fun getClassifierKindPrefix(classifier: ClassifierDescriptorWithTypeParameters): String =
when (classifier) {
is TypeAliasDescriptor ->
"typealias"
is ClassDescriptor ->
if (classifier.isCompanionObject) {
"companion object"
}
else when (classifier.kind) {
ClassKind.CLASS -> "class"
ClassKind.INTERFACE -> "interface"
ClassKind.ENUM_CLASS -> "enum class"
ClassKind.OBJECT -> "object"
ClassKind.ANNOTATION_CLASS -> "annotation class"
ClassKind.ENUM_ENTRY -> "enum entry"
}
else ->
throw AssertionError("Unexpected classifier: $classifier")
}
}
}
@@ -931,7 +931,7 @@ internal class DescriptorRendererImpl(
}
private fun renderClassKindPrefix(klass: ClassDescriptor, builder: StringBuilder) {
builder.append(renderKeyword(DescriptorRenderer.getClassKindPrefix(klass)))
builder.append(renderKeyword(DescriptorRenderer.getClassifierKindPrefix(klass)))
}
@@ -78,7 +78,7 @@ private val CALLABLE_RENDERER = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_I
fun DeclarationDescriptor.renderForConflicts(): String {
return when (this) {
is ClassDescriptor -> "${DescriptorRenderer.getClassKindPrefix(this)} ${IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(this)}"
is ClassDescriptor -> "${DescriptorRenderer.getClassifierKindPrefix(this)} ${IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(this)}"
is FunctionDescriptor -> "function '${CALLABLE_RENDERER.render(this)}'"
is PropertyDescriptor -> "property '${CALLABLE_RENDERER.render(this)}'"
else -> ""
@@ -1,4 +1,4 @@
// !DIAGNOSTICS_NUMBER: 3
// !DIAGNOSTICS_NUMBER: 4
// !DIAGNOSTICS: NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE
class A {
@@ -6,11 +6,13 @@ class A {
class NestedWithClassObject { companion object }
enum class NestedEnum { A }
object NestedObj { fun invoke() = 1 }
typealias NestedAlias = Nested
}
fun test(a: A) {
a.NestedWithClassObject
a.NestedEnum
a.NestedObj
a.NestedAlias
a.Nested() // TODO: report "nested class accessed via instance reference" here as well
}
@@ -1,2 +1,2 @@
<!-- nestedClassAcessedViaInstanceReference4 -->
Nested class 'Nested' accessed via instance reference
Nested typealias 'NestedAlias' accessed via instance reference
@@ -0,0 +1,2 @@
<!-- nestedClassAcessedViaInstanceReference5 -->
Nested class 'Nested' accessed via instance reference