KT-14641: Nested type alias reference via an instance is an error.
This commit is contained in:
@@ -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);
|
||||
|
||||
+3
-2
@@ -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
-1
@@ -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
|
||||
Reference in New Issue
Block a user