Spring Support: Inspection for final Spring-annotated classes/functions
#KT-11098 Fixed
This commit is contained in:
@@ -96,6 +96,7 @@ New features:
|
||||
- Kotlin Education Plugin (for IDEA 2016)
|
||||
- [KT-9752](https://youtrack.jetbrains.com/issue/KT-9752) More usable file chooser for "Move declaration to another file"
|
||||
- [KT-9697](https://youtrack.jetbrains.com/issue/KT-9697) Move method to companion object and back
|
||||
- [KT-11098](https://youtrack.jetbrains.com/issue/KT-11098) Inspection on final classes/functions annotated with Spring @Configuration/@Component/@Bean
|
||||
|
||||
General issues fixed:
|
||||
|
||||
|
||||
@@ -775,7 +775,13 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
|
||||
testGroup("idea/idea-ultimate/tests", "idea/testData") {
|
||||
testClass<AbstractInspectionTest>("UltimateInspectionTestGenerated") {
|
||||
model("ultimateInspections", pattern = "^(inspections\\.test)$", singleClass = true)
|
||||
}
|
||||
|
||||
testClass<AbstractQuickFixTest>("UltimateQuickFixTestGenerated") {
|
||||
model("ultimateQuickFixes", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("idea/tests", "compiler/testData") {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This inspection reports final Kotlin classes and functions annotated with Spring @Component, @Configuration or @Bean annotations
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,11 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
|
||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.spring.inspections.KotlinFinalClassOrFunSpringInspection"
|
||||
displayName="Final Kotlin class or function with Spring annotation"
|
||||
groupBundle="resources.messages.SpringBundle"
|
||||
groupKey="inspection.group.code"
|
||||
groupPath="Spring,Spring Core"
|
||||
enabledByDefault="true"
|
||||
level="WARNING"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.spring.inspections
|
||||
|
||||
import com.intellij.codeInsight.highlighting.HighlightUsagesDescriptionLocation
|
||||
import com.intellij.codeInspection.LocalQuickFix
|
||||
import com.intellij.codeInspection.ProblemDescriptor
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.ElementDescriptionUtil
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.spring.constants.SpringAnnotationsConstants
|
||||
import com.intellij.spring.model.jam.stereotype.SpringComponent
|
||||
import com.intellij.spring.model.jam.stereotype.SpringConfiguration
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
|
||||
import org.jetbrains.kotlin.idea.spring.isAnnotatedWith
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isInheritable
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isOverridable
|
||||
|
||||
class KotlinFinalClassOrFunSpringInspection : AbstractKotlinInspection() {
|
||||
class QuickFix<T: KtModifierListOwner>(private val element: T) : LocalQuickFix {
|
||||
override fun getName(): String {
|
||||
return "Make ${ElementDescriptionUtil.getElementDescription(element, HighlightUsagesDescriptionLocation.INSTANCE)} open"
|
||||
}
|
||||
|
||||
override fun getFamilyName() = "Make declaration open"
|
||||
|
||||
override fun applyFix(project: Project, problemDescriptor: ProblemDescriptor) {
|
||||
(element as? KtNamedDeclaration)?.containingClassOrObject?.addModifier(KtTokens.OPEN_KEYWORD)
|
||||
element.addModifier(KtTokens.OPEN_KEYWORD)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMessage(declaration: KtNamedDeclaration): String? {
|
||||
when (declaration) {
|
||||
is KtClass -> {
|
||||
val lightClass = declaration.toLightClass() ?: return null
|
||||
when {
|
||||
SpringConfiguration.META.getJamElement(lightClass) != null -> return "@Configuration class should be declared open"
|
||||
SpringComponent.META.getJamElement(lightClass) != null -> return "@Component class should be declared open"
|
||||
}
|
||||
}
|
||||
|
||||
is KtNamedFunction -> {
|
||||
val lightMethod = declaration.toLightMethods().firstOrNull() ?: return null
|
||||
if (lightMethod.isAnnotatedWith(SpringAnnotationsConstants.JAVA_SPRING_BEAN)) return "@Bean function should be declared open"
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||
return object: KtVisitorVoid() {
|
||||
override fun visitNamedDeclaration(declaration: KtNamedDeclaration) {
|
||||
when (declaration) {
|
||||
is KtClass -> if (declaration.isInheritable()) return
|
||||
is KtNamedFunction -> if (declaration.isOverridable()) return
|
||||
else -> return
|
||||
}
|
||||
|
||||
val message = getMessage(declaration) ?: return
|
||||
|
||||
holder.registerProblem(
|
||||
declaration.nameIdentifier ?: declaration,
|
||||
message,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
QuickFix(declaration)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.spring
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.psi.PsiModifierListOwner
|
||||
import com.intellij.spring.model.jam.utils.JamAnnotationTypeUtil
|
||||
|
||||
internal fun PsiModifierListOwner.isAnnotatedWith(annotationFqName: String): Boolean {
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(this) ?: return false
|
||||
return JamAnnotationTypeUtil.getInstance(module)
|
||||
.getAnnotationTypesWithChildren(annotationFqName)
|
||||
.mapNotNull { it.qualifiedName }
|
||||
.any { AnnotationUtil.isAnnotated(this, it, true) }
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.codeInsight;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/ultimateInspections")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class UltimateInspectionTestGenerated extends AbstractInspectionTest {
|
||||
public void testAllFilesPresentInUltimateInspections() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/ultimateInspections"), Pattern.compile("^(inspections\\.test)$"));
|
||||
}
|
||||
|
||||
@TestMetadata("spring/finalSpringAnnotatedDeclaration/inspectionData/inspections.test")
|
||||
public void testSpring_finalSpringAnnotatedDeclaration_inspectionData_Inspections_test() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/ultimateInspections/spring/finalSpringAnnotatedDeclaration/inspectionData/inspections.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/ultimateQuickFixes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class UltimateQuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInUltimateQuickFixes() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/ultimateQuickFixes"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/ultimateQuickFixes/spring")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Spring extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInSpring() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/ultimateQuickFixes/spring"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class FinalSpringAnnotatedDeclaration extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInFinalSpringAnnotatedDeclaration() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("classWithComponentRuntime.kt")
|
||||
public void testClassWithComponentRuntime() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classWithConfigurationRuntime.kt")
|
||||
public void testClassWithConfigurationRuntime() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classWithCustomConfigurationRuntime.kt")
|
||||
public void testClassWithCustomConfigurationRuntime() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funWithBeanFinalClassRuntime.kt")
|
||||
public void testFunWithBeanFinalClassRuntime() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funWithBeanOpenClassRuntime.kt")
|
||||
public void testFunWithBeanOpenClassRuntime() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funWithCustomBeanFinalClassRuntime.kt")
|
||||
public void testFunWithCustomBeanFinalClassRuntime() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funWithCustomBeanOpenClassRuntime.kt")
|
||||
public void testFunWithCustomBeanOpenClassRuntime() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -53,9 +53,12 @@ class SpringTestFixtureExtension() : TestFixtureExtension {
|
||||
override fun tearDown() {
|
||||
try {
|
||||
// clear existing SpringFacet configuration before running next test
|
||||
module?.let { SpringFacet.getInstance(it) }?.let {
|
||||
it.removeFileSets()
|
||||
FacetUtil.deleteFacet(it)
|
||||
module?.let { module ->
|
||||
SpringFacet.getInstance(module)?.let { facet ->
|
||||
facet.removeFileSets()
|
||||
FacetUtil.deleteFacet(facet)
|
||||
}
|
||||
ConfigLibraryUtil.removeLibrary(module, "spring" + SpringFramework.FRAMEWORK_4_2_0.version)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
idea/testData/ultimateInspections/spring/finalSpringAnnotatedDeclaration/inspectionData/expected.xml
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
<problems>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>18</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Final Kotlin class or function with Spring annotation</problem_class>
|
||||
<description>@Configuration class should be declared open</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>21</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Final Kotlin class or function with Spring annotation</problem_class>
|
||||
<description>@Configuration class should be declared open</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>32</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Final Kotlin class or function with Spring annotation</problem_class>
|
||||
<description>@Component class should be declared open</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>41</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Final Kotlin class or function with Spring annotation</problem_class>
|
||||
<description>@Bean function should be declared open</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>44</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Final Kotlin class or function with Spring annotation</problem_class>
|
||||
<description>@Bean function should be declared open</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>47</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Final Kotlin class or function with Spring annotation</problem_class>
|
||||
<description>@Bean function should be declared open</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>50</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Final Kotlin class or function with Spring annotation</problem_class>
|
||||
<description>@Bean function should be declared open</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>55</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Final Kotlin class or function with Spring annotation</problem_class>
|
||||
<description>@Bean function should be declared open</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>58</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Final Kotlin class or function with Spring annotation</problem_class>
|
||||
<description>@Bean function should be declared open</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.spring.inspections.KotlinFinalClassOrFunSpringInspection
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.ComponentScan
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Configuration
|
||||
annotation class MyConfiguration
|
||||
|
||||
@Bean
|
||||
annotation class MyBean
|
||||
|
||||
// @Configuration
|
||||
|
||||
@Configuration
|
||||
class Application1
|
||||
|
||||
@MyConfiguration
|
||||
class Application2
|
||||
|
||||
@Configuration
|
||||
open class Application3
|
||||
|
||||
@MyConfiguration
|
||||
open class Application4
|
||||
|
||||
// @Component
|
||||
|
||||
@Component
|
||||
class Component1
|
||||
|
||||
@Component
|
||||
open class Component2
|
||||
|
||||
// @Bean
|
||||
|
||||
class Utils1 {
|
||||
@Bean
|
||||
fun foo1() = Component1()
|
||||
|
||||
@MyBean
|
||||
fun foo2() = Component2()
|
||||
|
||||
@Bean
|
||||
open fun foo3() = Component3()
|
||||
|
||||
@MyBean
|
||||
open fun foo4() = Component4()
|
||||
}
|
||||
|
||||
open class Utils2 {
|
||||
@Bean
|
||||
fun foo1() = Component1()
|
||||
|
||||
@MyBean
|
||||
fun foo2() = Component2()
|
||||
|
||||
@Bean
|
||||
open fun foo3() = Component3()
|
||||
|
||||
@MyBean
|
||||
open fun foo4() = Component4()
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.idea.spring.inspections.KotlinFinalClassOrFunSpringInspection
|
||||
idea/testData/ultimateQuickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
// "Make class Bean open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class <caret>Bean
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Make class Bean open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
open class <caret>Bean
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Make class Application open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
class <caret>Application
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Make class Application open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
open class <caret>Application
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Make class Application open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
annotation class MyConfiguration
|
||||
|
||||
@MyConfiguration
|
||||
class <caret>Application
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Make class Application open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
annotation class MyConfiguration
|
||||
|
||||
@MyConfiguration
|
||||
open class <caret>Application
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make function foo open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Bean
|
||||
|
||||
class Foo {
|
||||
@Bean
|
||||
fun <caret>foo() = ""
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make function foo open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Bean
|
||||
|
||||
open class Foo {
|
||||
@Bean
|
||||
open fun <caret>foo() = ""
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make function foo open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Bean
|
||||
|
||||
open class Foo {
|
||||
@Bean
|
||||
fun <caret>foo() = ""
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make function foo open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Bean
|
||||
|
||||
open class Foo {
|
||||
@Bean
|
||||
open fun <caret>foo() = ""
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Make function foo open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Bean
|
||||
|
||||
@Bean
|
||||
annotation class MyBean
|
||||
|
||||
class Foo {
|
||||
@MyBean
|
||||
fun <caret>foo() = ""
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Make function foo open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Bean
|
||||
|
||||
@Bean
|
||||
annotation class MyBean
|
||||
|
||||
open class Foo {
|
||||
@MyBean
|
||||
open fun <caret>foo() = ""
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Make function foo open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Bean
|
||||
|
||||
@Bean
|
||||
annotation class MyBean
|
||||
|
||||
open class Foo {
|
||||
@MyBean
|
||||
fun <caret>foo() = ""
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Make function foo open" "true"
|
||||
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
|
||||
// DISABLE-ERRORS
|
||||
import org.springframework.context.annotation.Bean
|
||||
|
||||
@Bean
|
||||
annotation class MyBean
|
||||
|
||||
open class Foo {
|
||||
@MyBean
|
||||
open fun <caret>foo() = ""
|
||||
}
|
||||
@@ -24,21 +24,15 @@ import com.intellij.codeInspection.ex.InspectionManagerEx
|
||||
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.testFramework.IdeaTestUtil
|
||||
import com.intellij.testFramework.InspectionTestUtil
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.idea.test.*
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
import kotlin.test.assertFalse
|
||||
import java.util.*
|
||||
|
||||
abstract class AbstractInspectionTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
companion object {
|
||||
@@ -64,6 +58,8 @@ abstract class AbstractInspectionTest : KotlinLightCodeInsightFixtureTestCase()
|
||||
val inspectionClass = Class.forName(InTextDirectivesUtils.findStringWithPrefixes(options, "// INSPECTION_CLASS: ")!!)
|
||||
val toolWrapper = LocalInspectionToolWrapper(inspectionClass.newInstance() as LocalInspectionTool)
|
||||
|
||||
val fixtureClasses = InTextDirectivesUtils.findListWithPrefixes(options, "// FIXTURE_CLASS: ")
|
||||
|
||||
val inspectionsTestDir = optionsFile.parentFile!!
|
||||
val srcDir = inspectionsTestDir.parentFile!!
|
||||
|
||||
@@ -74,7 +70,7 @@ abstract class AbstractInspectionTest : KotlinLightCodeInsightFixtureTestCase()
|
||||
val psiFiles = srcDir.walkTopDown().onEnter { it.name != "inspectionData" }.mapNotNull {
|
||||
file ->
|
||||
if (file.isDirectory) {
|
||||
null
|
||||
null
|
||||
}
|
||||
else if (file.extension != "kt") {
|
||||
val filePath = file.relativeTo(srcDir).invariantSeparatorsPath
|
||||
@@ -112,6 +108,8 @@ abstract class AbstractInspectionTest : KotlinLightCodeInsightFixtureTestCase()
|
||||
)
|
||||
}
|
||||
|
||||
fixtureClasses.forEach { TestFixtureExtension.loadFixture(it, myFixture.module) }
|
||||
|
||||
val scope = AnalysisScope(project, psiFiles.map { it.virtualFile!! })
|
||||
scope.invalidate()
|
||||
|
||||
@@ -139,6 +137,8 @@ abstract class AbstractInspectionTest : KotlinLightCodeInsightFixtureTestCase()
|
||||
|
||||
}
|
||||
finally {
|
||||
fixtureClasses.forEach { TestFixtureExtension.unloadFixture(it) }
|
||||
|
||||
if (isWithRuntime) {
|
||||
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(myFixture.module, IdeaTestUtil.getMockJdk17())
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.jetbrains.kotlin.idea.quickfix.utils.QuickfixTestUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil;
|
||||
import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils;
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase;
|
||||
import org.jetbrains.kotlin.idea.test.TestFixtureExtension;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
@@ -57,6 +58,7 @@ import org.junit.Assert;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -132,8 +134,15 @@ public abstract class AbstractQuickFixTest extends KotlinLightQuickFixTestCase {
|
||||
public void run() {
|
||||
String fileText = "";
|
||||
String expectedErrorMessage = "";
|
||||
List<String> fixtureClasses = Collections.emptyList();
|
||||
try {
|
||||
fileText = FileUtil.loadFile(testFile, CharsetToolkit.UTF8_CHARSET);
|
||||
|
||||
fixtureClasses = InTextDirectivesUtils.findListWithPrefixes(fileText, "// FIXTURE_CLASS: ");
|
||||
for (String fixtureClass : fixtureClasses) {
|
||||
TestFixtureExtension.Companion.loadFixture(fixtureClass, getModule());
|
||||
}
|
||||
|
||||
expectedErrorMessage = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// SHOULD_FAIL_WITH: ");
|
||||
String contents = StringUtil.convertLineSeparators(fileText);
|
||||
quickFixTestCase.configureFromFileText(testFile.getName(), contents);
|
||||
@@ -157,6 +166,9 @@ public abstract class AbstractQuickFixTest extends KotlinLightQuickFixTestCase {
|
||||
fail(testName);
|
||||
}
|
||||
} finally {
|
||||
for (String fixtureClass : fixtureClasses) {
|
||||
TestFixtureExtension.Companion.unloadFixture(fixtureClass);
|
||||
}
|
||||
ConfigLibraryUtil.unconfigureLibrariesByDirective(getModule(), fileText);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user