From 3272b8fc2c9e30c858f36bebb8c5f1b9dd625f87 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 13 May 2020 06:39:08 +0900 Subject: [PATCH] CanSealedSubClassBeObjectInspection: don't report if sub-class has classModifier #KT-38790 Fixed --- .../CanSealedSubClassBeObjectInspection.kt | 20 +++++++++++++-- .../annotation.kt | 5 ++++ .../convertSealedSubClassToObject/data.kt | 5 ++++ .../convertSealedSubClassToObject/enum.kt | 5 ++++ .../convertSealedSubClassToObject/inner.kt | 5 ++++ .../convertSealedSubClassToObject/sealed.kt | 4 +++ .../LocalInspectionTestGenerated.java | 25 +++++++++++++++++++ 7 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 idea/testData/inspectionsLocal/convertSealedSubClassToObject/annotation.kt create mode 100644 idea/testData/inspectionsLocal/convertSealedSubClassToObject/data.kt create mode 100644 idea/testData/inspectionsLocal/convertSealedSubClassToObject/enum.kt create mode 100644 idea/testData/inspectionsLocal/convertSealedSubClassToObject/inner.kt create mode 100644 idea/testData/inspectionsLocal/convertSealedSubClassToObject/sealed.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/CanSealedSubClassBeObjectInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/CanSealedSubClassBeObjectInspection.kt index 93257905908..ab4b1f88318 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/CanSealedSubClassBeObjectInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/CanSealedSubClassBeObjectInspection.kt @@ -46,6 +46,7 @@ class CanSealedSubClassBeObjectInspection : AbstractKotlinInspection() { val candidates = klass.getSubclasses() .withEmptyConstructors() + .thatHasNoClassModifiers() .thatAreFinal() .thatHasNoTypeParameters() .thatHasNoInnerClasses() @@ -80,6 +81,13 @@ class CanSealedSubClassBeObjectInspection : AbstractKotlinInspection() { .filter { klass -> klass.secondaryConstructors.all { cons -> cons.valueParameters.isEmpty() } }.toList() } + private fun List.thatHasNoClassModifiers(): List { + return filter { klass -> + val modifierList = klass.modifierList ?: return@filter true + CLASS_MODIFIERS.none { modifierList.hasModifier(it) } + } + } + private fun List.thatHasNoCompanionObjects(): List { return filter { klass -> klass.companionObjects.isEmpty() } } @@ -110,7 +118,7 @@ class CanSealedSubClassBeObjectInspection : AbstractKotlinInspection() { private fun KtClass.hasNoStateOrEquals(): Boolean { if (primaryConstructor?.valueParameters?.isNotEmpty() == true) return false - val body = getBody() + val body = body return body == null || run { val declarations = body.declarations declarations.asSequence().filterIsInstance().none { property -> @@ -132,7 +140,7 @@ class CanSealedSubClassBeObjectInspection : AbstractKotlinInspection() { } private fun KtClass.hasNoInnerClass(): Boolean { - val internalClasses = getBody() + val internalClasses = body ?.declarations ?.filterIsInstance() ?: return true @@ -143,5 +151,13 @@ class CanSealedSubClassBeObjectInspection : AbstractKotlinInspection() { val EQUALS = OperatorNameConventions.EQUALS.asString() const val HASH_CODE = "hashCode" + + val CLASS_MODIFIERS = listOf( + KtTokens.ANNOTATION_KEYWORD, + KtTokens.DATA_KEYWORD, + KtTokens.ENUM_KEYWORD, + KtTokens.INNER_KEYWORD, + KtTokens.SEALED_KEYWORD, + ) } } diff --git a/idea/testData/inspectionsLocal/convertSealedSubClassToObject/annotation.kt b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/annotation.kt new file mode 100644 index 00000000000..9676638ef10 --- /dev/null +++ b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/annotation.kt @@ -0,0 +1,5 @@ +// PROBLEM: none +// DISABLE-ERRORS +sealed class Bar + +annotation class Foo : Bar() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/convertSealedSubClassToObject/data.kt b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/data.kt new file mode 100644 index 00000000000..5a1ea9eb54f --- /dev/null +++ b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/data.kt @@ -0,0 +1,5 @@ +// PROBLEM: none +// DISABLE-ERRORS +sealed class Bar + +data class Foo : Bar() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/convertSealedSubClassToObject/enum.kt b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/enum.kt new file mode 100644 index 00000000000..1fbd9948767 --- /dev/null +++ b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/enum.kt @@ -0,0 +1,5 @@ +// PROBLEM: none +// DISABLE-ERRORS +sealed class Bar + +enum class Foo : Bar() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/convertSealedSubClassToObject/inner.kt b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/inner.kt new file mode 100644 index 00000000000..a6dcac2ab30 --- /dev/null +++ b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/inner.kt @@ -0,0 +1,5 @@ +// PROBLEM: none +// DISABLE-ERRORS +sealed class Bar + +inner class Foo : Bar() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/convertSealedSubClassToObject/sealed.kt b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/sealed.kt new file mode 100644 index 00000000000..c097c09d9fd --- /dev/null +++ b/idea/testData/inspectionsLocal/convertSealedSubClassToObject/sealed.kt @@ -0,0 +1,4 @@ +// PROBLEM: none +sealed class Bar + +sealed class Foo : Bar() \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 1bde061c43a..5d841f87fca 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -3385,6 +3385,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/inspectionsLocal/convertSealedSubClassToObject"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), null, true); } + @TestMetadata("annotation.kt") + public void testAnnotation() throws Exception { + runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/annotation.kt"); + } + @TestMetadata("baseEquals.kt") public void testBaseEquals() throws Exception { runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/baseEquals.kt"); @@ -3415,6 +3420,16 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/convertSubClassWithoutParentheses.kt"); } + @TestMetadata("data.kt") + public void testData() throws Exception { + runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/data.kt"); + } + + @TestMetadata("enum.kt") + public void testEnum() throws Exception { + runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/enum.kt"); + } + @TestMetadata("fakeState.kt") public void testFakeState() throws Exception { runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/fakeState.kt"); @@ -3425,6 +3440,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/generic.kt"); } + @TestMetadata("inner.kt") + public void testInner() throws Exception { + runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/inner.kt"); + } + @TestMetadata("noEquals.kt") public void testNoEquals() throws Exception { runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/noEquals.kt"); @@ -3450,6 +3470,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/ownState.kt"); } + @TestMetadata("sealed.kt") + public void testSealed() throws Exception { + runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/sealed.kt"); + } + @TestMetadata("sealedEquals.kt") public void testSealedEquals() throws Exception { runTest("idea/testData/inspectionsLocal/convertSealedSubClassToObject/sealedEquals.kt");