-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SONARKT-302 - Implement rule S6526: abstract class should be interface (
#384)
- Loading branch information
1 parent
eadf3d3
commit 8c052ee
Showing
11 changed files
with
433 additions
and
0 deletions.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
...ling/src/test/resources/expected/kotlin/android-architecture-components/kotlin-S6526.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"kotlin-android-architecture-components-project:sources/kotlin/android-architecture-components/GithubBrowserSample/app/src/main/java/com/android/example/github/di/FragmentBuildersModule.kt": [ | ||
28 | ||
], | ||
"kotlin-android-architecture-components-project:sources/kotlin/android-architecture-components/GithubBrowserSample/app/src/main/java/com/android/example/github/di/MainActivityModule.kt": [ | ||
26 | ||
], | ||
"kotlin-android-architecture-components-project:sources/kotlin/android-architecture-components/GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelModule.kt": [ | ||
33 | ||
] | ||
} |
45 changes: 45 additions & 0 deletions
45
its/ruling/src/test/resources/expected/kotlin/corda/kotlin-S6526.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
{ | ||
"kotlin-corda-project:sources/kotlin/corda/client/jackson/src/main/kotlin/net/corda/client/jackson/JacksonSupport.kt": [ | ||
487, | ||
501 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/core/src/main/kotlin/net/corda/core/node/services/vault/QueryCriteriaUtils.kt": [ | ||
146 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/node/src/integration-test/kotlin/net/corda/node/amqp/AMQPBridgeTest.kt": [ | ||
46 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/node/src/integration-test/kotlin/net/corda/node/amqp/CertificateRevocationListNodeTests.kt": [ | ||
75 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt": [ | ||
50 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/node/src/test/kotlin/net/corda/node/internal/NodeTest.kt": [ | ||
33 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/node/src/test/kotlin/net/corda/node/services/messaging/ArtemisMessagingTest.kt": [ | ||
67 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelperTest.kt": [ | ||
54 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/EvolutionSerializer.kt": [ | ||
250 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/serialization/src/main/kotlin/net/corda/serialization/internal/amqp/PropertySerializers.kt": [ | ||
12 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/serialization/src/test/kotlin/net/corda/serialization/internal/CordaClassResolverTests.kt": [ | ||
68 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/SerializationOutputTests.kt": [ | ||
212 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt": [ | ||
461 | ||
], | ||
"kotlin-corda-project:sources/kotlin/corda/testing/test-utils/src/test/kotlin/net/corda/testing/internal/RigorousMockTest.kt": [ | ||
18 | ||
] | ||
} |
115 changes: 115 additions & 0 deletions
115
its/ruling/src/test/resources/expected/kotlin/kotlin/kotlin-S6526.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
{ | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/compiler/container/tests/org/jetbrains/kotlin/container/tests/ComponentContainerTest.kt": [ | ||
316 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt": [ | ||
310 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt": [ | ||
86 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt": [ | ||
291 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/compiler/tests/org/jetbrains/kotlin/codegen/AbstractCustomScriptCodegenTest.kt": [ | ||
139, | ||
150 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/compiler/tests/org/jetbrains/kotlin/daemon/CompilerDaemonTest.kt": [ | ||
927 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt": [ | ||
563, | ||
587, | ||
590, | ||
593 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/core/builtins/native/kotlin/Number.kt": [ | ||
22 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/core/descriptors.runtime/src/kotlin/reflect/jvm/internal/structure/ReflectJavaElement.kt": [ | ||
21 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/CommonAlignmentStrategy.kt": [ | ||
22 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/idea/idea-analysis/src/org/jetbrains/kotlin/idea/configuration/BuildSystemType.kt": [ | ||
12 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/flags/flags.kt": [ | ||
24 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinStepActionFactory.kt": [ | ||
36 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/FunctionIntrinsic.kt": [ | ||
26 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/examples/scripting/jvm-maven-deps/script/src/org/jetbrains/kotlin/script/examples/jvm/resolve/maven/scriptDef.kt": [ | ||
28 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/examples/scripting/jvm-simple-script/script/src/org/jetbrains/kotlin/script/examples/jvm/simple/scriptDef.kt": [ | ||
16 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/stdlib/js/src/org.w3c/org.khronos.webgl.kt": [ | ||
69, | ||
75, | ||
81, | ||
87, | ||
93, | ||
99, | ||
105, | ||
111 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/stdlib/js/src/org.w3c/org.w3c.dom.kt": [ | ||
280, | ||
335, | ||
341, | ||
356, | ||
543, | ||
581, | ||
719 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/stdlib/js/src/org.w3c/org.w3c.dom.svg.kt": [ | ||
368, | ||
371, | ||
377, | ||
383, | ||
389, | ||
395, | ||
401, | ||
436, | ||
540, | ||
587, | ||
615, | ||
621, | ||
661, | ||
667, | ||
735, | ||
779, | ||
782, | ||
785, | ||
814, | ||
817 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/stdlib/js/src/org.w3c/org.w3c.xhr.kt": [ | ||
39 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/tools/binary-compatibility-validator/src/test/kotlin/cases/companions/companions.kt": [ | ||
13, | ||
47, | ||
80 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/tools/binary-compatibility-validator/src/test/kotlin/cases/nestedClasses/publicAbstractClass.kt": [ | ||
3 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/tools/kotlin-maven-plugin-test/src/it/test-dagger-maven-example/src/main/kotlin/PumpModule.kt": [ | ||
7 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/libraries/tools/kotlin-maven-plugin-test/src/it/test-kapt-allopen/src/main/kotlin/PumpModule.kt": [ | ||
7 | ||
], | ||
"kotlin-kotlin-project:sources/kotlin/kotlin/plugins/sam-with-receiver/sam-with-receiver-cli/test/org/jetbrains/kotlin/samWithReceiver/AbstractSamWithReceiverScriptTest.kt": [ | ||
41 | ||
] | ||
} |
13 changes: 13 additions & 0 deletions
13
its/ruling/src/test/resources/expected/kotlin/ktor/kotlin-S6526.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"kotlin-ktor-project:sources/kotlin/ktor/ktor-io/common/src/io/ktor/utils/io/charsets/Encoding.kt": [ | ||
20, | ||
90 | ||
], | ||
"kotlin-ktor-project:sources/kotlin/ktor/ktor-utils/common/src/io/ktor/util/internal/LockFreeLinkedList.kt": [ | ||
58, | ||
114 | ||
], | ||
"kotlin-ktor-project:sources/kotlin/ktor/ktor-utils/common/src/io/ktor/util/network/NetworkAddress.kt": [ | ||
14 | ||
] | ||
} |
96 changes: 96 additions & 0 deletions
96
...n-checks-test-sources/src/main/kotlin/checks/AbstractClassShouldBeInterfaceCheckSample.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package checks | ||
|
||
class AbstractClassShouldBeInterfaceCheckSample { | ||
|
||
abstract class ShapeA { // Noncompliant {{Replace this abstract class with an interface, or add function implementations or state properties to the class.}} | ||
// ^^^^^^ | ||
abstract fun getPath(): Int | ||
abstract fun getBoundingBox(): Pair<Int,Int> | ||
} | ||
|
||
interface ShapeB { // Compliant, we are using an interface here | ||
fun getPath(): Int | ||
fun getBoundingBox(): Pair<Int,Int> | ||
} | ||
|
||
|
||
abstract class ShapeC { // Compliant, abstract class has function implementations | ||
abstract fun getPath(): Int | ||
fun getBoundingBox(): Pair<Int,Int> { | ||
return Pair(0,0) | ||
} | ||
} | ||
|
||
abstract class Foo { // Noncompliant | ||
abstract var bar: String | ||
abstract val baz: String | ||
} | ||
|
||
abstract class Bar { // compliant | ||
var bar: String = "" | ||
abstract val baz: String | ||
} | ||
|
||
abstract class A { // Noncompliant | ||
abstract class Inner { // Noncompliant | ||
abstract fun foo() | ||
} | ||
} | ||
|
||
abstract class B { // Compliant | ||
abstract class Inner { | ||
fun foo() {} | ||
} | ||
} | ||
|
||
abstract class C { // Noncompliant | ||
object Inner { | ||
|
||
} | ||
} | ||
|
||
|
||
abstract class D { // Compliant | ||
companion object Inner { | ||
fun foo() {} | ||
} | ||
} | ||
|
||
interface E { // Compliant | ||
object Inner { | ||
|
||
} | ||
} | ||
|
||
abstract class F { // Compliant, at least one property in the initializer | ||
init { | ||
val x = 0 | ||
} | ||
} | ||
|
||
abstract class G { // Compliant | ||
constructor() { | ||
val x = 0 | ||
} | ||
} | ||
|
||
abstract class I { // Noncompliant | ||
init { | ||
} | ||
} | ||
|
||
abstract class J { // Compliant | ||
constructor() { | ||
} | ||
} | ||
|
||
abstract class K {} // Noncompliant | ||
abstract class L : K() {} // compliant, extend an abstract as he may have no other choice | ||
|
||
interface M {} // compliant | ||
abstract class N : M {} // Noncompliant | ||
abstract class O : K(), M {} // compliant | ||
|
||
abstract interface ZZZ { // Compliant | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
...checks/src/main/java/org/sonarsource/kotlin/checks/AbstractClassShouldBeInterfaceCheck.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* SonarSource Kotlin | ||
* Copyright (C) 2018-2023 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this program; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
package org.sonarsource.kotlin.checks | ||
|
||
import org.jetbrains.kotlin.lexer.KtTokens | ||
import org.jetbrains.kotlin.psi.KtClass | ||
import org.jetbrains.kotlin.psi.KtDeclaration | ||
import org.jetbrains.kotlin.psi.KtFunction | ||
import org.jetbrains.kotlin.psi.KtProperty | ||
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry | ||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType | ||
import org.sonar.check.Rule | ||
import org.sonarsource.kotlin.api.checks.AbstractCheck | ||
import org.sonarsource.kotlin.api.frontend.KotlinFileContext | ||
|
||
@Rule(key = "S6526") | ||
class AbstractClassShouldBeInterfaceCheck : AbstractCheck() { | ||
|
||
override fun visitClass(klass: KtClass, context: KotlinFileContext) { | ||
|
||
if (!klass.isAbstract() || klass.isInterface() || klass.extendsClass()) return | ||
|
||
val allMethods = klass.collectDescendantsOfType<KtFunction>() | ||
val allProperties: List<KtProperty> by lazy { klass.collectDescendantsOfType<KtProperty>() } | ||
|
||
if (allMethods.all { it.isAbstract() } && allProperties.all { it.isAbstract() }) { | ||
context.reportIssue( | ||
klass.nameIdentifier!!, | ||
"Replace this abstract class with an interface, or add function implementations or state properties to the class." | ||
) | ||
} | ||
} | ||
|
||
private fun KtClass.extendsClass(): Boolean { | ||
return superTypeListEntries.any { it is KtSuperTypeCallEntry } | ||
} | ||
|
||
private fun KtDeclaration.isAbstract() = hasModifier(KtTokens.ABSTRACT_KEYWORD) | ||
|
||
} |
22 changes: 22 additions & 0 deletions
22
...ks/src/test/java/org/sonarsource/kotlin/checks/AbstractClassShouldBeInterfaceCheckTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* SonarSource Kotlin | ||
* Copyright (C) 2018-2023 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this program; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
package org.sonarsource.kotlin.checks | ||
|
||
internal class AbstractClassShouldBeInterfaceCheckTest : CheckTest(AbstractClassShouldBeInterfaceCheck()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.