Create custom rule to report public modifiers in impl 51/85051/5
authorIzabela Zawadzka <izabela.zawadzka@nokia.com>
Thu, 11 Apr 2019 12:27:21 +0000 (14:27 +0200)
committerIzabela Zawadzka <izabela.zawadzka@nokia.com>
Mon, 15 Apr 2019 09:36:18 +0000 (11:36 +0200)
Change-Id: I383ca27a835943bd2dc2508425264ad7f64c7725
Signed-off-by: Izabela Zawadzka <izabela.zawadzka@nokia.com>
Issue-ID: DCAEGEN2-1430

build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/PublicModifiersInImpl.kt [new file with mode: 0644]
build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/VesHvRuleSetProvider.kt
build/hv-collector-analysis/src/main/resources/onap-detekt-config.yml
build/hv-collector-analysis/src/test/kotlin/org/onap/dcae/collectors/veshv/analysis/PublicModifiersInImplTest.kt [new file with mode: 0644]

diff --git a/build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/PublicModifiersInImpl.kt b/build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/PublicModifiersInImpl.kt
new file mode 100644 (file)
index 0000000..027cade
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.analysis
+
+import io.gitlab.arturbosch.detekt.api.*
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.isPublic
+
+class PublicModifiersInImpl(config: Config = Config.empty) : Rule(config) {
+    override val issue: Issue = Issue(javaClass.simpleName, Severity.Maintainability,
+            ISSUE_DESCRIPTION, Debt(mins=10))
+
+    override fun visitKtFile(file: KtFile) {
+        super.visitKtFile(file)
+
+        if(file.packageFqName.toString().contains("impl")) {
+            ImplVisitor.also {
+                file.accept(it)
+                if(it.publicDeclarations.isNotEmpty()){
+                    for(entity in it.publicDeclarations)
+                        report(CodeSmell(issue, entity, REPORT_MESSAGE))
+                    it.publicDeclarations.clear()
+                }
+            }
+        }
+    }
+
+    companion object {
+        private val REPORT_MESSAGE =  """
+                                Implementation package members cannot have public declarations.
+                                Please, add `internal` modifier for this element to disallow usage outside of module
+                            """.trimIndent()
+        private const val ISSUE_DESCRIPTION = "Reports public modifiers inside '*.impl' package."
+    }
+}
+
+private object ImplVisitor: DetektVisitor(){
+    var publicDeclarations = mutableListOf<Entity>()
+
+    override fun visitClassOrObject(classOrObject: KtClassOrObject) {
+        if(classOrObject.isTopLevel() && classOrObject.isPublic){
+            publicDeclarations.add(Entity.from(classOrObject))
+        }
+    }
+
+    override fun visitNamedFunction(function: KtNamedFunction) {
+        if(function.isTopLevel && function.isPublic){
+            publicDeclarations.add(Entity.from(function))
+        }
+    }
+
+    override fun visitProperty(property: KtProperty) {
+        if(property.isTopLevel && property.isPublic) publicDeclarations.add(Entity.from(property))
+    }
+}
\ No newline at end of file
index eec933d..eb906ad 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * dcaegen2-collectors-veshv
  * ================================================================================
- * Copyright (C) 2018 NOKIA
+ * Copyright (C) 2018-2019 NOKIA
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ class VesHvRuleSetProvider : RuleSetProvider {
     override val ruleSetId: String
         get() = "HvVesCustomRules"
 
-    override fun instance(config: Config) = RuleSet(ruleSetId, listOf(SuboptimalLoggerUsage(config)))
+    override fun instance(config: Config) = RuleSet(ruleSetId,
+            listOf(SuboptimalLoggerUsage(config), PublicModifiersInImpl(config)))
 
 }
index f8d8b1e..b45f6b6 100644 (file)
@@ -479,3 +479,5 @@ HvVesCustomRules:
   active: true
   SuboptimalLoggerUsage:
     active: false
+  PublicModifiersInImpl:
+    active: false
diff --git a/build/hv-collector-analysis/src/test/kotlin/org/onap/dcae/collectors/veshv/analysis/PublicModifiersInImplTest.kt b/build/hv-collector-analysis/src/test/kotlin/org/onap/dcae/collectors/veshv/analysis/PublicModifiersInImplTest.kt
new file mode 100644 (file)
index 0000000..b3de1a2
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.collectors.veshv.analysis
+
+import io.gitlab.arturbosch.detekt.test.assertThat
+import io.gitlab.arturbosch.detekt.test.lint
+import org.jetbrains.spek.api.Spek
+import org.jetbrains.spek.api.dsl.describe
+import org.jetbrains.spek.api.dsl.it
+
+internal class PublicModifiersInImplTest: Spek({
+    fun checkPassingCase(code: String, cut: PublicModifiersInImpl = PublicModifiersInImpl()) {
+        describe(code) {
+            val findings = cut.lint(code)
+
+            it("should pass") {
+                assertThat(findings).isEmpty()
+            }
+        }
+    }
+
+    fun checkFailingCase(code: String, cut: PublicModifiersInImpl = PublicModifiersInImpl()) {
+        describe(code) {
+            val findings = cut.lint(code)
+
+            it("should fail") {
+                assertThat(findings).isNotEmpty
+            }
+        }
+    }
+
+    describe("passing cases") {
+        checkPassingCase(ExemplaryCode.publicModifiersOutsideImplPackage)
+        checkPassingCase(ExemplaryCode.internalTopLevelModifiersInsideImplPackage)
+        checkPassingCase(ExemplaryCode.privateTopLevelModifiersInsideImplPackage)
+        checkPassingCase(ExemplaryCode.protectedTopLevelModifiersInsideImplPackage)
+    }
+
+    describe("failing cases") {
+        checkFailingCase(ExemplaryCode.publicTopLevelModifiersInsideImplPackage)
+    }
+})
+
+private object ExemplaryCode {
+    val publicModifiersOutsideImplPackage = """
+        package a.b.c
+
+        class SampleClass {
+
+        }
+
+        object SampleObject {
+
+        }
+    """.trimIndent()
+
+    val internalTopLevelModifiersInsideImplPackage = """
+        package a.impl.b
+
+        internal fun sampleFunction() = true
+
+        internal val sampleProperty = true
+
+        internal class SampleClass {
+            fun someFunction() = true
+        }
+    """.trimIndent()
+
+    val privateTopLevelModifiersInsideImplPackage = """
+        package a.impl.b
+
+        private fun sampleFunction() = true
+
+        private val sampleProperty = true
+
+        private class SampleClass {
+            fun someFunction() = true
+        }
+    """.trimIndent()
+
+    val protectedTopLevelModifiersInsideImplPackage = """
+        package a.impl.b
+
+        protected fun sampleFunction() = true
+
+        protected val sampleProperty = true
+
+        protected class SampleClass {
+            fun someFunction() = true
+        }
+    """.trimIndent()
+
+    val publicTopLevelModifiersInsideImplPackage = """
+        package a.impl.b
+
+        fun sampleFunction() = true
+
+        val sampleProperty = true
+
+        class SampleClass {
+            private fun someFunction() = true
+        }
+    """.trimIndent()
+}
\ No newline at end of file