Do not disable 'redundant visibility modifier' inspection completely in Explicit API mode.

Instead, disable it only for effectively public declarations.

Add tests for this IDE inspection.
This commit is contained in:
Leonid Startsev
2019-10-16 14:38:47 +03:00
parent 5ab262c977
commit 24688f3503
7 changed files with 121 additions and 1 deletions
@@ -1,3 +1,20 @@
private class Foo {
fun method() {}
}
public interface I {
public fun bar()
}
public fun f() {
val i = object : I {
internal var foo = 0
override fun bar() {}
}
i.foo = 1
class LocalClass {
internal var foo = 0
}
LocalClass().foo = 1
}
@@ -1,5 +1,7 @@
package
public fun f(): kotlin.Unit
private final class Foo {
public constructor Foo()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -7,3 +9,10 @@ private final class Foo {
public final fun method(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface I {
public abstract fun bar(): kotlin.Unit
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
}
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.config.ExplicitApiMode
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.core.implicitVisibility
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
@@ -25,16 +27,18 @@ import org.jetbrains.kotlin.psi.declarationVisitor
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
class RedundantVisibilityModifierInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
return declarationVisitor(fun(declaration: KtDeclaration) {
val isInApiMode = declaration.languageVersionSettings.getFlag(AnalysisFlags.explicitApiMode) != ExplicitApiMode.DISABLED
if (isInApiMode) return@declarationVisitor
if (declaration is KtPropertyAccessor && declaration.isGetter) return // There is a quick fix for REDUNDANT_MODIFIER_IN_GETTER
val visibilityModifier = declaration.visibilityModifier() ?: return
val implicitVisibility = declaration.implicitVisibility()
if (isInApiMode && (declaration.resolveToDescriptorIfAny() as? DeclarationDescriptorWithVisibility)?.isEffectivelyPublicApi == true) return@declarationVisitor
val redundantVisibility = when {
visibilityModifier.node.elementType == implicitVisibility ->
implicitVisibility
@@ -0,0 +1,34 @@
<problems>
<problem>
<file>redundantVisibilityModifierWithExplicitApi.kt</file>
<line>24</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/redundantVisibilityModifierWithExplicitApi.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant visibility modifier</problem_class>
<description>Redundant visibility modifier</description>
</problem>
<problem>
<file>redundantVisibilityModifierWithExplicitApi.kt</file>
<line>29</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/redundantVisibilityModifierWithExplicitApi.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant visibility modifier</problem_class>
<description>Redundant visibility modifier</description>
</problem>
<problem>
<file>redundantVisibilityModifierWithExplicitApi.kt</file>
<line>40</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/redundantVisibilityModifierWithExplicitApi.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant visibility modifier</problem_class>
<description>Redundant visibility modifier</description>
</problem>
<problem>
<file>redundantVisibilityModifierWithExplicitApi.kt</file>
<line>46</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/redundantVisibilityModifierWithExplicitApi.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant visibility modifier</problem_class>
<description>Redundant visibility modifier</description>
</problem>
</problems>
@@ -0,0 +1,2 @@
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.RedundantVisibilityModifierInspection
// COMPILER_ARGUMENTS: -Xexplicit-api=strict
@@ -0,0 +1,49 @@
public class C {
public val foo: Int = 0
public fun bar() {}
}
open class D {
protected open fun willRemainProtected() {
}
protected open fun willBecomePublic() {
}
}
class E : D() {
protected override fun willRemainProtected() {
}
public override fun willBecomePublic() {
}
}
enum class F private constructor(val x: Int) {
FIRST(42)
}
sealed class G constructor(val y: Int) {
private constructor(): this(42)
object H : G()
}
interface I {
fun bar()
}
fun f() {
val i = object : I {
internal var foo = 0
override fun bar() {}
}
i.foo = 1
class LocalClass {
internal var foo = 0
}
LocalClass().foo = 1
}
@@ -313,6 +313,11 @@ public class InspectionTestGenerated extends AbstractInspectionTest {
runTest("idea/testData/inspections/redundantVisibilityModifier/inspectionData/inspections.test");
}
@TestMetadata("redundantVisibilityModifierWithExplicitApi/inspectionData/inspections.test")
public void testRedundantVisibilityModifierWithExplicitApi_inspectionData_Inspections_test() throws Exception {
runTest("idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/inspectionData/inspections.test");
}
@TestMetadata("redundantWith/inspectionData/inspections.test")
public void testRedundantWith_inspectionData_Inspections_test() throws Exception {
runTest("idea/testData/inspections/redundantWith/inspectionData/inspections.test");