diff --git a/ChangeLog.md b/ChangeLog.md index f804d6a7e68..93d8e6453fd 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -82,6 +82,7 @@ - [`KT-12092`](https://youtrack.jetbrains.com/issue/KT-12092) Implement bean references in @Qualifier annotations - [`KT-12136`](https://youtrack.jetbrains.com/issue/KT-12136) Implement package references inside of string literals - [`KT-12278`](https://youtrack.jetbrains.com/issue/KT-12278) Implement Spring @Autowired inspection +- [`KT-12465`](https://youtrack.jetbrains.com/issue/KT-12465) Implement Spring @ComponentScan inspection ###### Issues fixed diff --git a/ultimate/resources/META-INF/kotlin-spring.xml b/ultimate/resources/META-INF/kotlin-spring.xml index 59afba5808d..62345c3e642 100644 --- a/ultimate/resources/META-INF/kotlin-spring.xml +++ b/ultimate/resources/META-INF/kotlin-spring.xml @@ -45,6 +45,14 @@ enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.kotlin.idea.spring.inspections.SpringKotlinAutowiringInspection"/> + diff --git a/ultimate/resources/inspectionDescriptions/KotlinSpringComponentScan.html b/ultimate/resources/inspectionDescriptions/KotlinSpringComponentScan.html new file mode 100644 index 00000000000..cec04e3e970 --- /dev/null +++ b/ultimate/resources/inspectionDescriptions/KotlinSpringComponentScan.html @@ -0,0 +1,7 @@ + + +Checks @ComponentScan (and similar annotations) for setup errors. + +

+ + \ No newline at end of file diff --git a/ultimate/src/org/jetbrains/kotlin/idea/spring/inspections/KotlinSpringComponentScanInspection.kt b/ultimate/src/org/jetbrains/kotlin/idea/spring/inspections/KotlinSpringComponentScanInspection.kt new file mode 100644 index 00000000000..75aa7228848 --- /dev/null +++ b/ultimate/src/org/jetbrains/kotlin/idea/spring/inspections/KotlinSpringComponentScanInspection.kt @@ -0,0 +1,34 @@ +package org.jetbrains.kotlin.idea.spring.inspections + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleUtilCore +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElementVisitor +import com.intellij.spring.model.highlighting.jam.SpringComponentScanInspection +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection +import org.jetbrains.kotlin.idea.inspections.registerWithElementsUnwrapped +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtVisitorVoid + +class KotlinSpringComponentScanInspection : AbstractKotlinInspection() { + private val javaInspection by lazy { + object : SpringComponentScanInspection() { + // make base method visible + override public fun checkClass(aClass: PsiClass, holder: ProblemsHolder, module: Module) = super.checkClass(aClass, holder, module) + } + } + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { + return object: KtVisitorVoid() { + override fun visitClassOrObject(classOrObject: KtClassOrObject) { + val module = ModuleUtilCore.findModuleForPsiElement(classOrObject) ?: return + val lightClass = classOrObject.toLightClass() ?: return + val tmpHolder = ProblemsHolder(holder.manager, classOrObject.containingFile, isOnTheFly) + javaInspection.checkClass(lightClass, tmpHolder, module) + tmpHolder.resultsArray.registerWithElementsUnwrapped(holder, isOnTheFly) + } + } + } +} \ No newline at end of file diff --git a/ultimate/testData/inspections/spring/componentScan/foo/beans.kt b/ultimate/testData/inspections/spring/componentScan/foo/beans.kt new file mode 100644 index 00000000000..82874a1ce6f --- /dev/null +++ b/ultimate/testData/inspections/spring/componentScan/foo/beans.kt @@ -0,0 +1,6 @@ +package foo + +// Make PsiPackage not empty +fun dummyFun() { + +} \ No newline at end of file diff --git a/ultimate/testData/inspections/spring/componentScan/inspectionData/expected.xml b/ultimate/testData/inspections/spring/componentScan/inspectionData/expected.xml new file mode 100644 index 00000000000..5fb321c5795 --- /dev/null +++ b/ultimate/testData/inspections/spring/componentScan/inspectionData/expected.xml @@ -0,0 +1,18 @@ + + + test.kt + 14 + light_idea_test_case + + @ComponentScan setup (Kotlin) + Cannot resolve package bar + + + test.kt + 18 + light_idea_test_case + + @ComponentScan setup (Kotlin) + Cannot resolve package bar + + diff --git a/ultimate/testData/inspections/spring/componentScan/inspectionData/inspections.test b/ultimate/testData/inspections/spring/componentScan/inspectionData/inspections.test new file mode 100644 index 00000000000..bfa89cff534 --- /dev/null +++ b/ultimate/testData/inspections/spring/componentScan/inspectionData/inspections.test @@ -0,0 +1,3 @@ +// INSPECTION_CLASS: org.jetbrains.kotlin.idea.spring.inspections.KotlinSpringComponentScanInspection +// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension +// CONFIGURE_SPRING_FILE_SET \ No newline at end of file diff --git a/ultimate/testData/inspections/spring/componentScan/test.kt b/ultimate/testData/inspections/spring/componentScan/test.kt new file mode 100644 index 00000000000..bc23e390234 --- /dev/null +++ b/ultimate/testData/inspections/spring/componentScan/test.kt @@ -0,0 +1,19 @@ + +// WITH_RUNTIME + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration + +@Configuration +@ComponentScan(basePackages = arrayOf("foo")) +open class App1 + +@Configuration +@ComponentScan(basePackages = arrayOf("foo", "bar")) +open class App2 + +@Configuration +@ComponentScan(basePackages = arrayOf("bar")) +open class App3 \ No newline at end of file diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/inspections/SpringInspectionTestGenerated.java b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/inspections/SpringInspectionTestGenerated.java index 96846678af9..c9649b60772 100644 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/inspections/SpringInspectionTestGenerated.java +++ b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/inspections/SpringInspectionTestGenerated.java @@ -47,6 +47,12 @@ public class SpringInspectionTestGenerated extends AbstractSpringInspectionTest doTest(fileName); } + @TestMetadata("componentScan/inspectionData/inspections.test") + public void testComponentScan_inspectionData_Inspections_test() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/componentScan/inspectionData/inspections.test"); + doTest(fileName); + } + @TestMetadata("finalSpringAnnotatedDeclaration/inspectionData/inspections.test") public void testFinalSpringAnnotatedDeclaration_inspectionData_Inspections_test() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/inspectionData/inspections.test");