Report exposed type for properties in class primary constructor

Before this commit, we compared property visibility with constructor
visibility only, which is incorrect. Now we compare property visibility
also with class visibility

#KT-19613 Fixed
This commit is contained in:
Mikhail Glukhikh
2018-11-06 17:52:48 +03:00
parent f160eabaf6
commit b3857e85e0
14 changed files with 200 additions and 10 deletions
@@ -116,6 +116,7 @@ public interface Errors {
// Exposed visibility group
DiagnosticFactory3<PsiElement, EffectiveVisibility, DescriptorWithRelation, EffectiveVisibility> EXPOSED_PROPERTY_TYPE = DiagnosticFactory3.create(ERROR);
DiagnosticFactory3<PsiElement, EffectiveVisibility, DescriptorWithRelation, EffectiveVisibility> EXPOSED_PROPERTY_TYPE_IN_CONSTRUCTOR = DiagnosticFactory3.create(WARNING);
DiagnosticFactory3<PsiElement, EffectiveVisibility, DescriptorWithRelation, EffectiveVisibility> EXPOSED_FUNCTION_RETURN_TYPE = DiagnosticFactory3.create(ERROR);
DiagnosticFactory3<KtParameter, EffectiveVisibility, DescriptorWithRelation, EffectiveVisibility> EXPOSED_PARAMETER_TYPE = DiagnosticFactory3.create(ERROR);
DiagnosticFactory3<KtTypeReference, EffectiveVisibility, DescriptorWithRelation, EffectiveVisibility> EXPOSED_RECEIVER_TYPE = DiagnosticFactory3.create(ERROR);
@@ -69,6 +69,7 @@ public class DefaultErrorMessages {
MAP.put(PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL, "Protected constructor ''{0}'' from other classes can only be used in super-call", Renderers.SHORT_NAMES_IN_TYPES);
MAP.put(EXPOSED_PROPERTY_TYPE, "''{0}'' property exposes its ''{2}'' type{1}", TO_STRING, TO_STRING, TO_STRING);
MAP.put(EXPOSED_PROPERTY_TYPE_IN_CONSTRUCTOR, "''{0}'' property exposes its ''{2}'' type{1}", TO_STRING, TO_STRING, TO_STRING);
MAP.put(EXPOSED_FUNCTION_RETURN_TYPE, "''{0}'' function exposes its ''{2}'' return type{1}", TO_STRING, TO_STRING, TO_STRING);
MAP.put(EXPOSED_PARAMETER_TYPE, "''{0}'' function exposes its ''{2}'' parameter type{1}", TO_STRING, TO_STRING, TO_STRING);
MAP.put(EXPOSED_RECEIVER_TYPE, "''{0}'' member exposes its ''{2}'' receiver type{1}", TO_STRING, TO_STRING, TO_STRING);
@@ -91,15 +91,31 @@ class ExposedVisibilityChecker(private val trace: DiagnosticSink = DO_NOTHING) {
}
}
functionDescriptor.valueParameters.forEachIndexed { i, parameterDescriptor ->
val restricting = parameterDescriptor.type.leastPermissiveDescriptor(functionVisibility)
if (restricting != null && i < function.valueParameters.size) {
trace.report(
Errors.EXPOSED_PARAMETER_TYPE.on(
function.valueParameters[i], functionVisibility,
restricting, restricting.effectiveVisibility()
if (i < function.valueParameters.size) {
val valueParameter = function.valueParameters[i]
val restricting = parameterDescriptor.type.leastPermissiveDescriptor(functionVisibility)
if (restricting != null) {
trace.report(
Errors.EXPOSED_PARAMETER_TYPE.on(
valueParameter, functionVisibility,
restricting, restricting.effectiveVisibility()
)
)
)
result = false
result = false
} else if (functionDescriptor is ClassConstructorDescriptor && valueParameter.hasValOrVar()) {
val propertyDescriptor = (trace as? BindingTrace)?.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameterDescriptor)
val propertyOrClassVisibility = (propertyDescriptor ?: functionDescriptor.constructedClass).effectiveVisibility()
val restrictingByProperty = parameterDescriptor.type.leastPermissiveDescriptor(propertyOrClassVisibility)
if (restrictingByProperty != null) {
trace.report(
Errors.EXPOSED_PROPERTY_TYPE_IN_CONSTRUCTOR.on(
valueParameter, propertyOrClassVisibility,
restrictingByProperty, restrictingByProperty.effectiveVisibility()
)
)
result = false
}
}
}
}
return result and checkMemberReceiver(function.receiverTypeReference, functionDescriptor)
@@ -0,0 +1,3 @@
private enum class Foo { A, B }
class Bar private constructor(private val foo: Foo)
@@ -0,0 +1,30 @@
package
public final class Bar {
private constructor Bar(/*0*/ foo: Foo)
private final val foo: Foo
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
}
private final enum class Foo : kotlin.Enum<Foo> {
enum entry A
enum entry B
private constructor Foo()
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Foo): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<Foo!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Foo
public final /*synthesized*/ fun values(): kotlin.Array<Foo>
}
@@ -0,0 +1,3 @@
private enum class Foo { A, B }
private class Bar(val foo: Foo)
@@ -0,0 +1,30 @@
package
private final class Bar {
public constructor Bar(/*0*/ foo: Foo)
public final val foo: Foo
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
}
private final enum class Foo : kotlin.Enum<Foo> {
enum entry A
enum entry B
private constructor Foo()
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Foo): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<Foo!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Foo
public final /*synthesized*/ fun values(): kotlin.Array<Foo>
}
@@ -0,0 +1,3 @@
private enum class Foo { A, B }
class Bar private constructor(<!EXPOSED_PROPERTY_TYPE_IN_CONSTRUCTOR!>val foo: Foo<!>)
@@ -0,0 +1,30 @@
package
public final class Bar {
private constructor Bar(/*0*/ foo: Foo)
public final val foo: Foo
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
}
private final enum class Foo : kotlin.Enum<Foo> {
enum entry A
enum entry B
private constructor Foo()
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Foo): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<Foo!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Foo
public final /*synthesized*/ fun values(): kotlin.Array<Foo>
}
@@ -0,0 +1,3 @@
private enum class Foo { A, B }
class Bar(<!EXPOSED_PARAMETER_TYPE!>val foo: Foo<!>)
@@ -0,0 +1,30 @@
package
public final class Bar {
public constructor Bar(/*0*/ foo: Foo)
public final val foo: Foo
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
}
private final enum class Foo : kotlin.Enum<Foo> {
enum entry A
enum entry B
private constructor Foo()
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Foo): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<Foo!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Foo
public final /*synthesized*/ fun values(): kotlin.Array<Foo>
}
@@ -7315,6 +7315,26 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/exposed/privateFromLocal.kt");
}
@TestMetadata("privatePropertyInPrivateConstructor.kt")
public void testPrivatePropertyInPrivateConstructor() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/privatePropertyInPrivateConstructor.kt");
}
@TestMetadata("propertyInConstructorOfPrivateClass.kt")
public void testPropertyInConstructorOfPrivateClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/propertyInConstructorOfPrivateClass.kt");
}
@TestMetadata("propertyInPrivateConstructor.kt")
public void testPropertyInPrivateConstructor() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/propertyInPrivateConstructor.kt");
}
@TestMetadata("propertyInSimpleConstructor.kt")
public void testPropertyInSimpleConstructor() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/propertyInSimpleConstructor.kt");
}
@TestMetadata("protected.kt")
public void testProtected() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/protected.kt");
@@ -7315,6 +7315,26 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/exposed/privateFromLocal.kt");
}
@TestMetadata("privatePropertyInPrivateConstructor.kt")
public void testPrivatePropertyInPrivateConstructor() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/privatePropertyInPrivateConstructor.kt");
}
@TestMetadata("propertyInConstructorOfPrivateClass.kt")
public void testPropertyInConstructorOfPrivateClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/propertyInConstructorOfPrivateClass.kt");
}
@TestMetadata("propertyInPrivateConstructor.kt")
public void testPropertyInPrivateConstructor() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/propertyInPrivateConstructor.kt");
}
@TestMetadata("propertyInSimpleConstructor.kt")
public void testPropertyInSimpleConstructor() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/propertyInSimpleConstructor.kt");
}
@TestMetadata("protected.kt")
public void testProtected() throws Exception {
runTest("compiler/testData/diagnostics/tests/exposed/protected.kt");
@@ -188,8 +188,8 @@ class QuickFixRegistrar : QuickFixContributor {
INVISIBLE_SETTER.registerFactory(MakeVisibleFactory)
for (exposed in listOf(
EXPOSED_FUNCTION_RETURN_TYPE, EXPOSED_PARAMETER_TYPE, EXPOSED_PROPERTY_TYPE, EXPOSED_RECEIVER_TYPE,
EXPOSED_SUPER_CLASS, EXPOSED_SUPER_INTERFACE, EXPOSED_TYPE_PARAMETER_BOUND
EXPOSED_FUNCTION_RETURN_TYPE, EXPOSED_PARAMETER_TYPE, EXPOSED_PROPERTY_TYPE, EXPOSED_PROPERTY_TYPE_IN_CONSTRUCTOR,
EXPOSED_RECEIVER_TYPE, EXPOSED_SUPER_CLASS, EXPOSED_SUPER_INTERFACE, EXPOSED_TYPE_PARAMETER_BOUND
)) {
exposed.registerFactory(ChangeVisibilityOnExposureFactory)
}