From 076e31c0f8a410a9a239d0773339ed00daf164f7 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Fri, 20 May 2016 17:28:12 +0300 Subject: [PATCH] Spring Support: Automatic configuration by @Import and @ComponentScan ("basePackages"/"basePackageClasses") #KT-12135 Fixed #KT-12139 Fixed --- ChangeLog.md | 2 ++ .../kotlin/asJava/KtLightAnnotation.kt | 8 ++++++++ .../Config.kt | 8 ++++++++ .../bar/beans.kt | 8 ++++++++ .../componentScanWithBasePackageClasses.test | 8 ++++++++ .../foo/beans.kt | 8 ++++++++ .../componentScanWithBasePackages/Config.kt | 6 ++++++ .../componentScanWithBasePackages/bar/beans.kt | 8 ++++++++ .../componentScanWithBasePackages.test | 8 ++++++++ .../componentScanWithBasePackages/foo/beans.kt | 8 ++++++++ .../core/gutter/importConfigClasses/Config.kt | 7 +++++++ .../gutter/importConfigClasses/bar/beans.kt | 8 ++++++++ .../gutter/importConfigClasses/baz/Config2.kt | 10 ++++++++++ .../gutter/importConfigClasses/foo/beans.kt | 8 ++++++++ .../importConfigClasses.test | 8 ++++++++ .../SpringClassAnnotatorTestGenerated.java | 18 ++++++++++++++++++ 16 files changed, 131 insertions(+) create mode 100644 ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/Config.kt create mode 100644 ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/bar/beans.kt create mode 100644 ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/componentScanWithBasePackageClasses.test create mode 100644 ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/foo/beans.kt create mode 100644 ultimate/testData/spring/core/gutter/componentScanWithBasePackages/Config.kt create mode 100644 ultimate/testData/spring/core/gutter/componentScanWithBasePackages/bar/beans.kt create mode 100644 ultimate/testData/spring/core/gutter/componentScanWithBasePackages/componentScanWithBasePackages.test create mode 100644 ultimate/testData/spring/core/gutter/componentScanWithBasePackages/foo/beans.kt create mode 100644 ultimate/testData/spring/core/gutter/importConfigClasses/Config.kt create mode 100644 ultimate/testData/spring/core/gutter/importConfigClasses/bar/beans.kt create mode 100644 ultimate/testData/spring/core/gutter/importConfigClasses/baz/Config2.kt create mode 100644 ultimate/testData/spring/core/gutter/importConfigClasses/foo/beans.kt create mode 100644 ultimate/testData/spring/core/gutter/importConfigClasses/importConfigClasses.test diff --git a/ChangeLog.md b/ChangeLog.md index 93d8e6453fd..7267bdff84f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -80,7 +80,9 @@ - [`KT-11692`](https://youtrack.jetbrains.com/issue/KT-11692) Support Spring model diagrams for Kotlin classes - [`KT-12079`](https://youtrack.jetbrains.com/issue/KT-12079) Support "Autowired members defined in invalid Spring bean" inspection on Kotlin declarations - [`KT-12092`](https://youtrack.jetbrains.com/issue/KT-12092) Implement bean references in @Qualifier annotations +- [`KT-12135`](https://youtrack.jetbrains.com/issue/KT-12135) Automatically configure components based on 'basePackageClasses' attribute of @ComponentScan - [`KT-12136`](https://youtrack.jetbrains.com/issue/KT-12136) Implement package references inside of string literals +- [`KT-12139`](https://youtrack.jetbrains.com/issue/KT-12139) Support Spring configurations linked via @Import annotation - [`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 diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightAnnotation.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightAnnotation.kt index 933a7466e2b..1b121ff5478 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightAnnotation.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightAnnotation.kt @@ -87,6 +87,13 @@ class KtLightAnnotation( override fun getValue() = delegate.value } + inner class LightClassLiteral( + delegate: PsiClassObjectAccessExpression + ) : LightExpressionValue(delegate), PsiClassObjectAccessExpression { + override fun getType() = delegate.type + override fun getOperand(): PsiTypeElement = delegate.operand + } + inner class LightArrayInitializerValue(private val delegate: PsiArrayInitializerMemberValue) : PsiArrayInitializerMemberValue by delegate { private val _initializers by lazy(LazyThreadSafetyMode.PUBLICATION) { delegate.initializers.map { wrapAnnotationValue(it) }.toTypedArray() } @@ -97,6 +104,7 @@ class KtLightAnnotation( private fun wrapAnnotationValue(value: PsiAnnotationMemberValue): PsiAnnotationMemberValue { return when { value is PsiLiteralExpression && value.value is String -> LightStringLiteral(value) + value is PsiClassObjectAccessExpression -> LightClassLiteral(value) value is PsiExpression -> LightExpressionValue(value) value is PsiArrayInitializerMemberValue -> LightArrayInitializerValue(value) else -> value diff --git a/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/Config.kt b/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/Config.kt new file mode 100644 index 00000000000..457624b9d12 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/Config.kt @@ -0,0 +1,8 @@ +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration +import foo.FooBean +import bar.BarBean + +@ComponentScan(basePackageClasses = arrayOf(FooBean::class, BarBean::class)) +@Configuration +open class Config \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/bar/beans.kt b/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/bar/beans.kt new file mode 100644 index 00000000000..ad7370789e4 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/bar/beans.kt @@ -0,0 +1,8 @@ +package bar + +import org.springframework.stereotype.Component + +@Component +class BarBean { + +} \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/componentScanWithBasePackageClasses.test b/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/componentScanWithBasePackageClasses.test new file mode 100644 index 00000000000..8e869e56636 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/componentScanWithBasePackageClasses.test @@ -0,0 +1,8 @@ +{ + springConfig: ["Config.kt"], + file: "foo/beans.kt", + icon: "SpringJavaBean", + tooltip: "Navigate to the spring bean declaration(s)", + naming: "generic", + targets: ["Config"] +} \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/foo/beans.kt b/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/foo/beans.kt new file mode 100644 index 00000000000..6c382177861 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/foo/beans.kt @@ -0,0 +1,8 @@ +package foo + +import org.springframework.stereotype.Component + +@Component +class FooBean { + +} \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/Config.kt b/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/Config.kt new file mode 100644 index 00000000000..4c978113e94 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/Config.kt @@ -0,0 +1,6 @@ +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration + +@ComponentScan(basePackages = arrayOf("foo", "bar")) +@Configuration +open class Config \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/bar/beans.kt b/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/bar/beans.kt new file mode 100644 index 00000000000..ad7370789e4 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/bar/beans.kt @@ -0,0 +1,8 @@ +package bar + +import org.springframework.stereotype.Component + +@Component +class BarBean { + +} \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/componentScanWithBasePackages.test b/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/componentScanWithBasePackages.test new file mode 100644 index 00000000000..8e869e56636 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/componentScanWithBasePackages.test @@ -0,0 +1,8 @@ +{ + springConfig: ["Config.kt"], + file: "foo/beans.kt", + icon: "SpringJavaBean", + tooltip: "Navigate to the spring bean declaration(s)", + naming: "generic", + targets: ["Config"] +} \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/foo/beans.kt b/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/foo/beans.kt new file mode 100644 index 00000000000..6c382177861 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/componentScanWithBasePackages/foo/beans.kt @@ -0,0 +1,8 @@ +package foo + +import org.springframework.stereotype.Component + +@Component +class FooBean { + +} \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/importConfigClasses/Config.kt b/ultimate/testData/spring/core/gutter/importConfigClasses/Config.kt new file mode 100644 index 00000000000..52d9d188234 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/importConfigClasses/Config.kt @@ -0,0 +1,7 @@ +import org.springframework.context.annotation.Import +import org.springframework.context.annotation.Configuration +import baz.Config2 + +@Configuration +@Import(Config2::class) +open class Config \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/importConfigClasses/bar/beans.kt b/ultimate/testData/spring/core/gutter/importConfigClasses/bar/beans.kt new file mode 100644 index 00000000000..ad7370789e4 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/importConfigClasses/bar/beans.kt @@ -0,0 +1,8 @@ +package bar + +import org.springframework.stereotype.Component + +@Component +class BarBean { + +} \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/importConfigClasses/baz/Config2.kt b/ultimate/testData/spring/core/gutter/importConfigClasses/baz/Config2.kt new file mode 100644 index 00000000000..c54448f131f --- /dev/null +++ b/ultimate/testData/spring/core/gutter/importConfigClasses/baz/Config2.kt @@ -0,0 +1,10 @@ +package baz + +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration +import foo.FooBean +import bar.BarBean + +@ComponentScan(basePackageClasses = arrayOf(FooBean::class, BarBean::class)) +@Configuration +open class Config2 \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/importConfigClasses/foo/beans.kt b/ultimate/testData/spring/core/gutter/importConfigClasses/foo/beans.kt new file mode 100644 index 00000000000..6c382177861 --- /dev/null +++ b/ultimate/testData/spring/core/gutter/importConfigClasses/foo/beans.kt @@ -0,0 +1,8 @@ +package foo + +import org.springframework.stereotype.Component + +@Component +class FooBean { + +} \ No newline at end of file diff --git a/ultimate/testData/spring/core/gutter/importConfigClasses/importConfigClasses.test b/ultimate/testData/spring/core/gutter/importConfigClasses/importConfigClasses.test new file mode 100644 index 00000000000..20aa584c26a --- /dev/null +++ b/ultimate/testData/spring/core/gutter/importConfigClasses/importConfigClasses.test @@ -0,0 +1,8 @@ +{ + springConfig: ["Config.kt"], + file: "foo/beans.kt", + icon: "SpringJavaBean", + tooltip: "Navigate to the spring bean declaration(s)", + naming: "generic", + targets: [] +} \ No newline at end of file diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/SpringClassAnnotatorTestGenerated.java b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/SpringClassAnnotatorTestGenerated.java index 6da0890cde4..2309975d09a 100644 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/SpringClassAnnotatorTestGenerated.java +++ b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/SpringClassAnnotatorTestGenerated.java @@ -71,6 +71,18 @@ public class SpringClassAnnotatorTestGenerated extends AbstractSpringClassAnnota doTest(fileName); } + @TestMetadata("componentScanWithBasePackageClasses/componentScanWithBasePackageClasses.test") + public void testComponentScanWithBasePackageClasses_ComponentScanWithBasePackageClasses() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/componentScanWithBasePackageClasses.test"); + doTest(fileName); + } + + @TestMetadata("componentScanWithBasePackages/componentScanWithBasePackages.test") + public void testComponentScanWithBasePackages_ComponentScanWithBasePackages() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/componentScanWithBasePackages/componentScanWithBasePackages.test"); + doTest(fileName); + } + @TestMetadata("contextBeanInjectionPoints/contextBeanInjectionPoints.test") public void testContextBeanInjectionPoints_ContextBeanInjectionPoints() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/contextBeanInjectionPoints/contextBeanInjectionPoints.test"); @@ -83,6 +95,12 @@ public class SpringClassAnnotatorTestGenerated extends AbstractSpringClassAnnota doTest(fileName); } + @TestMetadata("importConfigClasses/importConfigClasses.test") + public void testImportConfigClasses_ImportConfigClasses() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/importConfigClasses/importConfigClasses.test"); + doTest(fileName); + } + @TestMetadata("innerBean/innerBean.test") public void testInnerBean_InnerBean() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/innerBean/innerBean.test");