diff --git a/compiler/testData/diagnostics/testsWithExplicitApi/mustBeEffectivelyPublic.kt b/compiler/testData/diagnostics/testsWithExplicitApi/mustBeEffectivelyPublic.kt index aab3f871705..35c2538ed56 100644 --- a/compiler/testData/diagnostics/testsWithExplicitApi/mustBeEffectivelyPublic.kt +++ b/compiler/testData/diagnostics/testsWithExplicitApi/mustBeEffectivelyPublic.kt @@ -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 } \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithExplicitApi/mustBeEffectivelyPublic.txt b/compiler/testData/diagnostics/testsWithExplicitApi/mustBeEffectivelyPublic.txt index caec90ec3d0..9c5aa2265e0 100644 --- a/compiler/testData/diagnostics/testsWithExplicitApi/mustBeEffectivelyPublic.txt +++ b/compiler/testData/diagnostics/testsWithExplicitApi/mustBeEffectivelyPublic.txt @@ -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 +} diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantVisibilityModifierInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantVisibilityModifierInspection.kt index 537be9768fe..12825ac795b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantVisibilityModifierInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantVisibilityModifierInspection.kt @@ -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 diff --git a/idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/inspectionData/expected.xml b/idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/inspectionData/expected.xml new file mode 100644 index 00000000000..78e33d96896 --- /dev/null +++ b/idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/inspectionData/expected.xml @@ -0,0 +1,34 @@ + + + redundantVisibilityModifierWithExplicitApi.kt + 24 + light_idea_test_case + + Redundant visibility modifier + Redundant visibility modifier + + + redundantVisibilityModifierWithExplicitApi.kt + 29 + light_idea_test_case + + Redundant visibility modifier + Redundant visibility modifier + + + redundantVisibilityModifierWithExplicitApi.kt + 40 + light_idea_test_case + + Redundant visibility modifier + Redundant visibility modifier + + + redundantVisibilityModifierWithExplicitApi.kt + 46 + light_idea_test_case + + Redundant visibility modifier + Redundant visibility modifier + + diff --git a/idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/inspectionData/inspections.test b/idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/inspectionData/inspections.test new file mode 100644 index 00000000000..001e46918ce --- /dev/null +++ b/idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/inspectionData/inspections.test @@ -0,0 +1,2 @@ +// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.RedundantVisibilityModifierInspection +// COMPILER_ARGUMENTS: -Xexplicit-api=strict \ No newline at end of file diff --git a/idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/redundantVisibilityModifierWithExplicitApi.kt b/idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/redundantVisibilityModifierWithExplicitApi.kt new file mode 100644 index 00000000000..aeec17baf76 --- /dev/null +++ b/idea/testData/inspections/redundantVisibilityModifierWithExplicitApi/redundantVisibilityModifierWithExplicitApi.kt @@ -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 +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java index 9e95835ed63..6f1f52b873e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java @@ -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");