Spring Support: Implement Spring @Autowired inspection

#KT-12278 Fixed
 #KT-12147 Fixed
 #KT-12366 Fixed
 #KT-12122 Fixed
This commit is contained in:
Alexey Sedunov
2016-05-17 18:19:46 +03:00
parent 36f3d30250
commit 85d07e5f6d
31 changed files with 820 additions and 129 deletions
+4
View File
@@ -26,6 +26,7 @@ New features:
- [KT-12092](https://youtrack.jetbrains.com/issue/KT-12092) Implement bean references in @Qualifier annotations
- [KT-12175](https://youtrack.jetbrains.com/issue/KT-12175) Don't enforce empty line after one-line constructor
- Added "Decompile" button to Kotlin bytecode toolwindow
- [KT-12278](https://youtrack.jetbrains.com/issue/KT-12278) Implement Spring @Autowired inspection
Issues fixed:
@@ -53,6 +54,9 @@ Issues fixed:
- [KT-12067](https://youtrack.jetbrains.com/issue/KT-12067) Deadlock in Kotlin debugger is fixed
- [KT-12070](https://youtrack.jetbrains.com/issue/KT-12070) Add empty line in error message of Maven and Gradle configuration
- [KT-12091](https://youtrack.jetbrains.com/issue/KT-12091) Fixed unstable behavior of Spring line markers
- [KT-12147](https://youtrack.jetbrains.com/issue/KT-12147) Fixed exception on analyzing object declaration with @Component annotation
- [KT-12366](https://youtrack.jetbrains.com/issue/KT-12366) Fixed exception on analyzing class declaration upon annotation typing
- [KT-12122](https://youtrack.jetbrains.com/issue/KT-12122) Fixed line marker popup on functions with @Qualifier-annotated parameters
#### Debugger
@@ -72,9 +72,10 @@ class KtLightAnnotation(
}
override fun getReference() = references.singleOrNull()
override fun getReferences() = ReferenceProvidersRegistry.getReferencesFromProviders(delegate, PsiReferenceService.Hints.NO_HINTS)
override fun getReferences() = originalExpression?.references ?: PsiReference.EMPTY_ARRAY
override fun getLanguage() = KotlinLanguage.INSTANCE
override fun getNavigationElement() = originalExpression
override fun getTextRange() = originalExpression?.textRange ?: TextRange.EMPTY_RANGE
}
inner class LightArrayInitializerValue(private val delegate: PsiArrayInitializerMemberValue) : PsiArrayInitializerMemberValue by delegate {
@@ -52,6 +52,8 @@ sealed class KtLightFieldImpl(
override fun getContainingClass() = containingClass
override fun getContainingFile() = containingClass.containingFile
override fun getType() = clsDelegate.type
override fun getTypeElement() = clsDelegate.typeElement
@@ -17,19 +17,32 @@
package org.jetbrains.kotlin.asJava
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiCompiledElement
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.impl.light.LightIdentifier
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
class KtLightIdentifier(
private val lightOwner: PsiNameIdentifierOwner,
private val ktDeclaration: KtNamedDeclaration?
) : LightIdentifier(lightOwner.manager, ktDeclaration?.name ?: "") {
) : LightIdentifier(lightOwner.manager, ktDeclaration?.name ?: ""), PsiCompiledElement {
val origin: PsiElement?
get() = ktDeclaration?.nameIdentifier
get() = when (ktDeclaration) {
is KtSecondaryConstructor -> ktDeclaration.getConstructorKeyword()
is KtPrimaryConstructor -> ktDeclaration.getConstructorKeyword()
?: ktDeclaration.valueParameterList
?: ktDeclaration.containingClassOrObject?.nameIdentifier
else -> ktDeclaration?.nameIdentifier
}
override fun getMirror() = ((lightOwner as? KtLightElement<*, *>)?.clsDelegate as? PsiNameIdentifierOwner)?.nameIdentifier
override fun isPhysical() = true
override fun getParent() = lightOwner
override fun getTextRange() = ktDeclaration?.nameIdentifier?.textRange ?: TextRange.EMPTY_RANGE
override fun getContainingFile() = lightOwner.containingFile
override fun getTextRange() = origin?.textRange ?: TextRange.EMPTY_RANGE
}
@@ -109,7 +109,12 @@ fun KtTypeParameter.toPsiTypeParameters(): List<PsiTypeParameter> {
// Returns original declaration if given PsiElement is a Kotlin light element, and element itself otherwise
val PsiElement.unwrapped: PsiElement?
get() = if (this is KtLightElement<*, *>) kotlinOrigin else this
get() = when {
this is KtLightElement<*, *> -> kotlinOrigin
this is KtLightIdentifier -> origin
this is KtLightAnnotation.LightExpressionValue -> originalExpression
else -> this
}
val PsiElement.namedUnwrappedElement: PsiNamedElement?
get() = unwrapped?.getNonStrictParentOfType<PsiNamedElement>()
@@ -63,16 +63,18 @@ private fun toSeverity(highlightDisplayLevel: HighlightDisplayLevel): Severity
}
@Suppress("unused")
fun Array<ProblemDescriptor>.registerWithElementsUnwrapped(holder: ProblemsHolder, isOnTheFly: Boolean) {
forEach {
fun Array<ProblemDescriptor>.registerWithElementsUnwrapped(
holder: ProblemsHolder,
isOnTheFly: Boolean,
quickFixSubstitutor: ((LocalQuickFix, PsiElement) -> LocalQuickFix?)? = null) {
forEach { problem ->
@Suppress("UNCHECKED_CAST")
val descriptor = holder.manager.createProblemDescriptor(
it.psiElement.unwrapped ?: it.psiElement,
it.descriptionTemplate,
isOnTheFly,
it.fixes as? Array<LocalQuickFix> ?: LocalQuickFix.EMPTY_ARRAY,
it.highlightType
)
val originalFixes = problem.fixes as? Array<LocalQuickFix> ?: LocalQuickFix.EMPTY_ARRAY
val newElement = problem.psiElement.unwrapped ?: return@forEach
val newFixes = quickFixSubstitutor?.let { subst ->
originalFixes.mapNotNull { subst(it, newElement) }.toTypedArray()
} ?: originalFixes
val descriptor = holder.manager.createProblemDescriptor(newElement, problem.descriptionTemplate, isOnTheFly, newFixes, problem.highlightType)
holder.registerProblem(descriptor)
}
}
@@ -24,6 +24,7 @@ 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
@@ -51,6 +52,10 @@ abstract class AbstractInspectionTest : KotlinLightCodeInsightFixtureTestCase()
super.tearDown()
}
protected open fun configExtra(psiFiles: List<PsiFile>, options: String) {
}
protected fun doTest(path: String) {
val optionsFile = File(path)
val options = FileUtil.loadFile(optionsFile, true)
@@ -110,6 +115,8 @@ abstract class AbstractInspectionTest : KotlinLightCodeInsightFixtureTestCase()
fixtureClasses.forEach { TestFixtureExtension.loadFixture(it, myFixture.module) }
configExtra(psiFiles, options)
val scope = AnalysisScope(project, psiFiles.map { it.virtualFile!! })
scope.invalidate()
@@ -124,6 +124,10 @@ public abstract class AbstractQuickFixTest extends KotlinLightQuickFixTestCase {
}), LocalInspectionTool.class);
}
protected void configExtra(String options) {
}
private void doKotlinQuickFixTest(final String testName, final QuickFixTestCase quickFixTestCase) {
String relativePath = notNull(quickFixTestCase.getBasePath(), "") + "/" + StringsKt.decapitalize(testName);
final String testFullPath = quickFixTestCase.getTestDataPath().replace(File.separatorChar, '/') + relativePath;
@@ -150,6 +154,8 @@ public abstract class AbstractQuickFixTest extends KotlinLightQuickFixTestCase {
checkForUnexpectedActions();
configExtra(fileText);
applyAction(contents, quickFixTestCase, testName, testFullPath);
assertEmpty(expectedErrorMessage);
+9
View File
@@ -0,0 +1,9 @@
<component name="ProjectDictionaryState">
<dictionary name="Alexey.Sedunov">
<words>
<w>autowired</w>
<w>autowiring</w>
<w>springframework</w>
</words>
</dictionary>
</component>
@@ -30,6 +30,14 @@
enabledByDefault="true"
level="WARNING"
implementationClass="org.jetbrains.kotlin.idea.spring.inspections.SpringKotlinAutowiredMembersInspection"/>
<localInspection language="kotlin"
displayName="Autowiring for Bean Class (Kotlin)"
groupBundle="resources.messages.SpringBundle"
groupKey="inspection.group.code"
groupPath="Spring,Spring Core"
enabledByDefault="true"
level="ERROR"
implementationClass="org.jetbrains.kotlin.idea.spring.inspections.SpringKotlinAutowiringInspection"/>
</extensions>
<actions>
@@ -0,0 +1 @@
Checks autowiring problems in a bean class.
@@ -0,0 +1,177 @@
package org.jetbrains.kotlin.idea.spring.inspections
import com.intellij.codeInsight.AnnotationUtil
import com.intellij.codeInsight.FileModificationService
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.template.*
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.OpenFileDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.util.PropertyUtil
import com.intellij.spring.CommonSpringModel
import com.intellij.spring.SpringBundle
import com.intellij.spring.model.SpringBeanPointer
import com.intellij.spring.model.converters.SpringConverterUtil
import com.intellij.spring.model.highlighting.SpringAutowireUtil
import com.intellij.spring.model.highlighting.SpringJavaAutowiringInspection
import org.jetbrains.kotlin.asJava.*
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
import org.jetbrains.kotlin.idea.inspections.registerWithElementsUnwrapped
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
class SpringKotlinAutowiringInspection : AbstractKotlinInspection() {
// Based on SpringJavaAutowiringInspection.AddSpringBeanQualifierFix
class AddQualifierFix(
modifierListOwner: KtModifierListOwner,
private val beanPointers: Collection<SpringBeanPointer<*>>,
private val annotationFqName: String
) : LocalQuickFix {
private val elementPointer = modifierListOwner.createSmartPointer()
override fun getName() = SpringBundle.message("SpringAutowiringInspection.add.qualifier.fix")
override fun getFamilyName() = name
private fun getQualifierNamesSuggestNamesExpression(expression: KtStringTemplateExpression): Expression {
return object : Expression() {
override fun calculateResult(context: ExpressionContext): Result? {
PsiDocumentManager.getInstance(context.project).commitAllDocuments()
return TextResult(expression.plainContent)
}
override fun calculateQuickResult(context: ExpressionContext) = this.calculateResult(context)
override fun calculateLookupItems(context: ExpressionContext): Array<LookupElement>? {
PsiDocumentManager.getInstance(context.project).commitAllDocuments()
return beanPointers.sortedBy { it.name ?: "" }.mapNotNull { SpringConverterUtil.createCompletionVariant(it) }.toTypedArray()
}
}
}
private fun createQualifierNameTemplate(expression: KtStringTemplateExpression): Template {
val builder = TemplateBuilderImpl(expression.containingFile)
builder.replaceRange(
expression.getContentRange().shiftRight(expression.startOffset),
getQualifierNamesSuggestNamesExpression(expression)
)
return builder.buildInlineTemplate()
}
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val modifierListOwner = elementPointer.element ?: return
if(!FileModificationService.getInstance().preparePsiElementForWrite(modifierListOwner)) return
if (beanPointers.isEmpty()) return
val defaultBeanName = with(beanPointers.first().name) { if (isNullOrBlank()) "Unknown" else this }
val entry = KtPsiFactory(project).createAnnotationEntry("@$annotationFqName(\"$defaultBeanName\")")
val addedEntry = modifierListOwner.addAnnotationEntry(entry)
ShortenReferences.DEFAULT.process(addedEntry)
val stringTemplate = addedEntry.valueArguments.first().getArgumentExpression() as? KtStringTemplateExpression ?: return
val virtualFile = modifierListOwner.containingFile.virtualFile!!
val editor = FileEditorManager.getInstance(project).openTextEditor(OpenFileDescriptor(project, virtualFile, 0), false)!!
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
TemplateManager.getInstance(project).startTemplate(editor, createQualifierNameTemplate(stringTemplate))
}
}
private val javaInspection by lazy { SpringJavaAutowiringInspection() }
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = object : KtVisitorVoid() {
// TODO: SpringJavaAutowiringInspection.checkAutowiredMethod() is not accessible here
private fun checkAutowiredMethod(psiMethod: PsiMethod, holder: ProblemsHolder, springModel: CommonSpringModel, required: Boolean) {
val resourceAnnotation = SpringAutowireUtil.getResourceAnnotation(psiMethod)
when {
resourceAnnotation != null -> {
val propertyType = PropertyUtil.getPropertyType(psiMethod) ?: return
SpringJavaAutowiringInspection.checkAutowiredPsiMember(psiMethod, propertyType, holder, springModel, required)
}
psiMethod.parameterList.parametersCount == 0 &&
SpringAutowireUtil.isAutowiredByAnnotation(psiMethod) -> {
val nameIdentifier = psiMethod.nameIdentifier ?: return
val message = SpringBundle.message("bean.autowiring.by.type.no.parameter.for.autowired.method",
if (psiMethod.isConstructor) "constructor" else "method")
holder.registerProblem(nameIdentifier, message)
}
else -> {
for (parameter in psiMethod.parameterList.parameters) {
if (AnnotationUtil.isAnnotated(parameter, "org.springframework.beans.factory.annotation.Value", true)) continue
SpringJavaAutowiringInspection.checkAutowiredPsiMember(parameter, parameter.type, holder, springModel, required)
}
}
}
}
private fun Array<ProblemDescriptor>.registerAdjustedProblems() {
registerWithElementsUnwrapped(holder, isOnTheFly) { qf, element ->
// Can't access AddSpringBeanQualifierFix class directly
val klass = qf.javaClass
if (!klass.name.endsWith("AddSpringBeanQualifierFix")) return@registerWithElementsUnwrapped qf
try {
val fields = klass.declaredFields
@Suppress("UNCHECKED_CAST")
val beanPointers = fields[1].apply { isAccessible = true }.get(qf) as Collection<SpringBeanPointer<*>>
val annotationFqName = fields[2].apply { isAccessible = true }.get(qf) as String
val modifierListOwner = element.getNonStrictParentOfType<KtModifierListOwner>()
?: return@registerWithElementsUnwrapped qf
AddQualifierFix(modifierListOwner, beanPointers, annotationFqName)
}
catch(e: Exception) {
return@registerWithElementsUnwrapped null
}
}
}
private fun <T: PsiMember> T.processLightMember(
action: T.(holder: ProblemsHolder, model: CommonSpringModel, required: Boolean) -> Unit
) {
val model = SpringAutowireUtil.getProcessingSpringModel(containingClass) ?: return
val required = SpringAutowireUtil.isRequired(this)
val tmpHolder = ProblemsHolder(holder.manager, containingFile, isOnTheFly)
action(this, tmpHolder, model, required)
tmpHolder.resultsArray.registerAdjustedProblems()
}
private fun PsiMethod.processLightMethod() {
if (!SpringAutowireUtil.isInjectionPoint(this)) return
processLightMember { holder, model, required -> checkAutowiredMethod(this, holder, model, required) }
}
private fun PsiField.processLightField() {
if (!SpringAutowireUtil.isAutowiredByAnnotation(this)) return
processLightMember { holder, model, required ->
SpringJavaAutowiringInspection.checkAutowiredPsiMember(this, type, holder, model, required)
}
}
private fun PsiClass.processLightClass() {
javaInspection.checkClass(this, holder.manager, isOnTheFly)?.registerAdjustedProblems()
}
override fun visitNamedFunction(function: KtNamedFunction) {
function.toLightMethods().firstOrNull()?.processLightMethod()
}
override fun visitProperty(property: KtProperty) {
for (lightElement in property.toLightElements()) {
when (lightElement) {
is KtLightMethod -> lightElement.processLightMethod()
is KtLightField -> lightElement.processLightField()
}
}
}
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
classOrObject.toLightClass()?.processLightClass()
}
}
}
@@ -23,21 +23,44 @@ import com.intellij.spring.model.converters.SpringConverterUtil
import com.intellij.spring.model.highlighting.SpringAutowireUtil
import com.intellij.spring.model.jam.qualifiers.SpringJamQualifier
import com.intellij.spring.model.utils.SpringModelSearchers
import com.intellij.spring.references.SpringQualifierReference
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.KtLightElement
import org.jetbrains.kotlin.asJava.toLightAnnotation
import org.jetbrains.kotlin.asJava.toLightElements
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.search.allScope
import org.jetbrains.kotlin.idea.spring.springModel
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.plainContent
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import java.util.*
// Based on com.intellij.spring.references.SpringQualifierReference
class KtSpringQualifierReference(element: KtStringTemplateExpression) : PsiReferenceBase.Poly<KtStringTemplateExpression>(element, false) {
// It inherits from SpringQualifierReference to allow reuse of existing Java inspections which explicitly check for SpringQualifierReference
class KtSpringQualifierReference(element: KtStringTemplateExpression) : SpringQualifierReference(StringTemplatePsiLiteralWrapper(element)) {
class StringTemplatePsiLiteralWrapper(
val element: KtStringTemplateExpression
) : PsiElement by element, PsiLiteralExpression, KtLightElement<KtStringTemplateExpression, KtStringTemplateExpression>, PsiCompiledElement {
override fun getName() = null
override fun setName(newName: String) = throw IncorrectOperationException()
override fun getValue() = element.plainContent
override fun getType() = PsiType.getJavaLangString(element.manager, element.project.allScope())
override val clsDelegate: KtStringTemplateExpression
get() = element
override val kotlinOrigin: KtStringTemplateExpression
get() = element
override fun getMirror() = null
}
private fun getAnnotationFqName(): String? {
val annotationEntry = element.getStrictParentOfType<KtAnnotationEntry>() ?: return null
val context = annotationEntry.analyze(BodyResolveMode.PARTIAL)
@@ -0,0 +1,60 @@
// 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
open class AmbiguousConstructors
// Not reported if there is only one constructor
@Component
open class SingleConstructor1(n: Int)
@Component
open class SingleConstructor2 {
constructor(n: Int)
}
// Not reported if no-arg constructor is present
@Component
open class NoArgConstructor1() {
constructor(n: Int): this()
constructor(s: String): this()
}
@Component
open class NoArgConstructor2 {
constructor()
constructor(n: Int)
constructor(s: String)
}
// Not reported if @Autowired constructor is present
@Component
open class AutowiredConstructor1 {
@Autowired constructor(n: Int)
constructor(s: String)
}
@Component
open class AutowiredConstructor2 @Autowired constructor(n: Int) {
constructor(s: String): this(0)
}
// Reported
@Component
open class AmbigiousConstructor1 {
constructor(n: Int)
constructor(s: String)
}
@Component
open class AmbigiousConstructor2(n: Int) {
constructor(s: String): this(0)
}
@@ -0,0 +1,119 @@
<problems>
<problem>
<file>ambiguousConstructors.kt</file>
<line>52</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/ambiguousConstructors.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Class doesn't contain matching constructor for autowiring</description>
</problem>
<problem>
<file>ambiguousConstructors.kt</file>
<line>58</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/ambiguousConstructors.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Class doesn't contain matching constructor for autowiring</description>
</problem>
<problem>
<file>multipleAutowiredConstructors.kt</file>
<line>30</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/multipleAutowiredConstructors.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Only one constructor can have @Autowired annotation</description>
</problem>
<problem>
<file>multipleAutowiredConstructors.kt</file>
<line>31</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/multipleAutowiredConstructors.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Only one constructor can have @Autowired annotation</description>
</problem>
<problem>
<file>multipleAutowiredConstructors.kt</file>
<line>35</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/multipleAutowiredConstructors.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Only one constructor can have @Autowired annotation</description>
</problem>
<problem>
<file>multipleAutowiredConstructors.kt</file>
<line>36</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/multipleAutowiredConstructors.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Only one constructor can have @Autowired annotation</description>
</problem>
<problem>
<file>parameterlessFunction.kt</file>
<line>15</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/parameterlessFunction.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Autowired method without parameters</description>
</problem>
<problem>
<file>invalidAutowiredResource.kt</file>
<line>24</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/mismatchedType.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Could not autowire. Bean should be of 'invalidAutowiredResource.BarBean' type</description>
</problem>
<problem>
<file>invalidAutowiredResource.kt</file>
<line>31</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/invalidAutowiredResource.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Cannot resolve bean 'fooBeannn'</description>
</problem>
<problem>
<file>invalidAutowiredQualifier.kt</file>
<line>23</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/invalidAutowiredQualifier.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Could not autowire. Qualified bean must be of 'BarBean' type.</description>
</problem>
<problem>
<file>invalidAutowiredQualifier.kt</file>
<line>30</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/invalidAutowiredQualifier.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Cannot find bean with qualifier 'fooBeannn'</description>
</problem>
<problem>
<file>invalidAutowiredQualifier.kt</file>
<line>37</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/invalidAutowiredQualifier.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Cannot find bean qualified with @Qualifier</description>
</problem>
<problem>
<file>invalidAutowiredByType.kt</file>
<line>23</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/invalidAutowiredByType.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>Could not autowire. No beans of 'String' type found.</description>
</problem>
<problem>
<file>invalidAutowiredByType.kt</file>
<line>29</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/invalidAutowiredByType.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Autowiring for Bean Class (Kotlin)</problem_class>
<description>&lt;html&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;Could not autowire. There is more than one bean of 'AbstractBarBean' type.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;table&gt;&lt;tr&gt;&lt;td valign='top'&gt;Beans:&lt;/td&gt;&lt;td&gt;abstractBarBean&amp;nbsp;&amp;nbsp; (invalidAutowiredByType.kt)&lt;br&gt;barBean1&amp;nbsp;&amp;nbsp; (invalidAutowiredByType.kt)&lt;br&gt;barBean2&amp;nbsp;&amp;nbsp; (invalidAutowiredByType.kt)&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/html&gt;</description>
</problem>
</problems>
@@ -0,0 +1,3 @@
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.spring.inspections.SpringKotlinAutowiringInspection
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
// CONFIGURE_SPRING_FILE_SET
@@ -0,0 +1,30 @@
// 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
import org.springframework.beans.factory.annotation.Qualifier
@Configuration
@ComponentScan
open class InvalidAutowiredByTypeQualifiers
abstract class AbstractBarBean
@Component
open class BarBean1 : AbstractBarBean()
@Component
open class BarBean2 : AbstractBarBean()
@Component
open class NoAutowiredCandidates() {
@Autowired
lateinit var bean: String
}
@Component
open class MultipleAutowiredCandidates() {
@Autowired
lateinit var bean: AbstractBarBean
}
@@ -0,0 +1,39 @@
// 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
import org.springframework.beans.factory.annotation.Qualifier
@Configuration
@ComponentScan
open class MismatchedTypes
@Component
open class FooBean
@Component
open class BarBean
@Component
open class MismatchedType() {
@Autowired
@Qualifier("fooBean")
lateinit var bean1: BarBean
}
@Component
open class UnresolvedBeanRef() {
@Autowired
@Qualifier("fooBeannn")
lateinit var bean1: FooBean
}
@Component
open class NamelessQualifier() {
@Autowired
@Qualifier
lateinit var bean1: FooBean
}
@@ -0,0 +1,33 @@
// WITH_RUNTIME
// FULL_JDK
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import javax.annotation.Resource
@Configuration
@ComponentScan
open class MismatchedTypes
@Component
open class FooBean
@Component
open class BarBean
@Component
open class MismatchedType() {
@Autowired
@Resource(name = "fooBean")
lateinit var bean1: BarBean
}
@Component
open class UnresolvedBeanRef() {
@Autowired
@Resource(name = "fooBeannn")
lateinit var bean1: FooBean
}
@@ -0,0 +1,37 @@
// 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
open class MultipleAutowiredConstructors
// Not reported if required == false
@Component
open class NonRequiredAutowired1 {
@Autowired(required = false) constructor(n: Int)
@Autowired constructor(s: String)
}
@Component
open class NonRequiredAutowired2 @Autowired(required = false) constructor(n: Int) {
@Autowired constructor(s: String): this(0)
}
// Reported
@Component
open class BothAutowired1 {
@Autowired constructor(n: Int)
@Autowired constructor(s: String)
}
@Component
open class BothAutowired2 @Autowired constructor(n: Int) {
@Autowired constructor(s: String): this(0)
}
@@ -0,0 +1,16 @@
// 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
open class ParameterlessFunctions
@Component
open class ParameterlessFunction {
@Autowired fun foo() = 1
}
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.spring.inspections.SpringKotlinAutowiringInspection
@@ -0,0 +1,27 @@
// "Add qualifier" "true"
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
// CONFIGURE_SPRING_FILE_SET
// WITH_RUNTIME
// DISABLE-ERRORS
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.beans.factory.annotation.Qualifier
@Configuration
@ComponentScan
open class InvalidAutowiredByTypeQualifiers
abstract class BaseBarBean
@Component
open class BarBean1 : BaseBarBean()
@Component
open class BarBean2 : BaseBarBean()
@Component
open class MultipleAutowiredCandidates() {
@Autowired
lateinit var <caret>bean: BaseBarBean
}
@@ -0,0 +1,27 @@
// "Add qualifier" "true"
// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
// CONFIGURE_SPRING_FILE_SET
// WITH_RUNTIME
// DISABLE-ERRORS
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.beans.factory.annotation.Qualifier
@Configuration
@ComponentScan
open class InvalidAutowiredByTypeQualifiers
abstract class BaseBarBean
@Component
open class BarBean1 : BaseBarBean()
@Component
open class BarBean2 : BaseBarBean()
@Component
open class MultipleAutowiredCandidates() {
@Qualifier("barBean1") @Autowired
lateinit var bean: BaseBarBean
}
@@ -1,97 +0,0 @@
/*
* 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("ultimate/testData/quickFixes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class UltimateQuickFixTestGenerated extends AbstractQuickFixTest {
public void testAllFilesPresentInQuickFixes() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/quickFixes"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("ultimate/testData/quickFixes/spring")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Spring extends AbstractQuickFixTest {
public void testAllFilesPresentInSpring() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/quickFixes/spring"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("ultimate/testData/quickFixes/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("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("classWithComponentRuntime.kt")
public void testClassWithComponentRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt");
doTest(fileName);
}
@TestMetadata("classWithConfigurationRuntime.kt")
public void testClassWithConfigurationRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt");
doTest(fileName);
}
@TestMetadata("classWithCustomConfigurationRuntime.kt")
public void testClassWithCustomConfigurationRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt");
doTest(fileName);
}
@TestMetadata("funWithBeanFinalClassRuntime.kt")
public void testFunWithBeanFinalClassRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt");
doTest(fileName);
}
@TestMetadata("funWithBeanOpenClassRuntime.kt")
public void testFunWithBeanOpenClassRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt");
doTest(fileName);
}
@TestMetadata("funWithCustomBeanFinalClassRuntime.kt")
public void testFunWithCustomBeanFinalClassRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt");
doTest(fileName);
}
@TestMetadata("funWithCustomBeanOpenClassRuntime.kt")
public void testFunWithCustomBeanOpenClassRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt");
doTest(fileName);
}
}
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.spring.tests
import com.intellij.facet.impl.FacetUtil
import com.intellij.openapi.module.Module
import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.PsiFile
import com.intellij.spring.facet.SpringFacet
import com.intellij.spring.facet.SpringFileSet
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
@@ -26,6 +27,7 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
import com.intellij.util.PathUtil
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.TestFixtureExtension
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.tests.ULTIMATE_TEST_ROOT
import java.util.*
@@ -89,4 +91,10 @@ fun SpringTestFixtureExtension.loadConfigByMainFilePath(testPath: String, fixtur
val baseName = FileUtil.getNameWithoutExtension(mainFileName)
val configFileName = if (baseName.endsWith("Xml")) "$baseName-config.xml" else mainFileName
configureFileSet(fixture, listOf(PathUtil.toSystemIndependentName("${PathUtil.getParentPath(testPath)}/$configFileName")))
}
fun configureSpringFileSetByDirective(module: Module, directives: String, psiFiles: Collection<PsiFile>) {
if (!InTextDirectivesUtils.isDirectiveDefined(directives, "// CONFIGURE_SPRING_FILE_SET")) return
val fileSet = SpringFacet.getInstance(module)!!.addFileSet("default", "default")!!
psiFiles.forEach { fileSet.addFile(it.virtualFile) }
}
@@ -0,0 +1,11 @@
package org.jetbrains.kotlin.idea.spring.tests.inspections
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.idea.codeInsight.AbstractInspectionTest
import org.jetbrains.kotlin.idea.spring.tests.configureSpringFileSetByDirective
abstract class AbstractSpringInspectionTest : AbstractInspectionTest() {
override fun configExtra(psiFiles: List<PsiFile>, options: String) {
configureSpringFileSetByDirective(myFixture.module, options, psiFiles)
}
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.codeInsight;
package org.jetbrains.kotlin.idea.spring.tests.inspections;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
@@ -27,28 +27,34 @@ import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("ultimate/testData/inspections")
@TestMetadata("ultimate/testData/inspections/spring")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class UltimateInspectionTestGenerated extends AbstractInspectionTest {
public void testAllFilesPresentInInspections() throws Exception {
KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("ultimate/testData/inspections"), Pattern.compile("^(inspections\\.test)$"));
public class SpringInspectionTestGenerated extends AbstractSpringInspectionTest {
public void testAllFilesPresentInSpring() throws Exception {
KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("ultimate/testData/inspections/spring"), Pattern.compile("^(inspections\\.test)$"));
}
@TestMetadata("spring/autowiredMembersInInvalidClass/inspectionData/inspections.test")
public void testSpring_autowiredMembersInInvalidClass_inspectionData_Inspections_test() throws Exception {
@TestMetadata("autowiredMembersInInvalidClass/inspectionData/inspections.test")
public void testAutowiredMembersInInvalidClass_inspectionData_Inspections_test() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/autowiredMembersInInvalidClass/inspectionData/inspections.test");
doTest(fileName);
}
@TestMetadata("spring/finalSpringAnnotatedDeclaration/inspectionData/inspections.test")
public void testSpring_finalSpringAnnotatedDeclaration_inspectionData_Inspections_test() throws Exception {
@TestMetadata("autowiring/inspectionData/inspections.test")
public void testAutowiring_inspectionData_Inspections_test() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/autowiring/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");
doTest(fileName);
}
@TestMetadata("spring/unconfiguredFacet/inspectionData/inspections.test")
public void testSpring_unconfiguredFacet_inspectionData_Inspections_test() throws Exception {
@TestMetadata("unconfiguredFacet/inspectionData/inspections.test")
public void testUnconfiguredFacet_inspectionData_Inspections_test() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/unconfiguredFacet/inspectionData/inspections.test");
doTest(fileName);
}
@@ -0,0 +1,10 @@
package org.jetbrains.kotlin.idea.spring.tests.quickfixes
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixTest
import org.jetbrains.kotlin.idea.spring.tests.configureSpringFileSetByDirective
abstract class AbstractSpringQuickFixTest : AbstractQuickFixTest() {
override fun configExtra(options: String) {
configureSpringFileSetByDirective(getModule(), options, listOf(getFile()))
}
}
@@ -0,0 +1,103 @@
/*
* 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.tests.quickfixes;
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("ultimate/testData/quickFixes/spring")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class SpringQuickFixTestGenerated extends AbstractSpringQuickFixTest {
public void testAllFilesPresentInSpring() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/quickFixes/spring"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("ultimate/testData/quickFixes/spring/addQualifierAnnotation")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AddQualifierAnnotation extends AbstractSpringQuickFixTest {
public void testAllFilesPresentInAddQualifierAnnotation() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/quickFixes/spring/addQualifierAnnotation"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("ambiguousBean.kt")
public void testAmbiguousBean() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/addQualifierAnnotation/ambiguousBean.kt");
doTest(fileName);
}
}
@TestMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FinalSpringAnnotatedDeclaration extends AbstractSpringQuickFixTest {
public void testAllFilesPresentInFinalSpringAnnotatedDeclaration() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("classWithComponentRuntime.kt")
public void testClassWithComponentRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt");
doTest(fileName);
}
@TestMetadata("classWithConfigurationRuntime.kt")
public void testClassWithConfigurationRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt");
doTest(fileName);
}
@TestMetadata("classWithCustomConfigurationRuntime.kt")
public void testClassWithCustomConfigurationRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt");
doTest(fileName);
}
@TestMetadata("funWithBeanFinalClassRuntime.kt")
public void testFunWithBeanFinalClassRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt");
doTest(fileName);
}
@TestMetadata("funWithBeanOpenClassRuntime.kt")
public void testFunWithBeanOpenClassRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt");
doTest(fileName);
}
@TestMetadata("funWithCustomBeanFinalClassRuntime.kt")
public void testFunWithCustomBeanFinalClassRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt");
doTest(fileName);
}
@TestMetadata("funWithCustomBeanOpenClassRuntime.kt")
public void testFunWithCustomBeanOpenClassRuntime() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt");
doTest(fileName);
}
}
}
@@ -17,11 +17,11 @@
package org.jetbrains.kotlin.tests
import org.jetbrains.kotlin.generators.tests.testGroup
import org.jetbrains.kotlin.idea.codeInsight.AbstractInspectionTest
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixTest
import org.jetbrains.kotlin.idea.spring.tests.findUsages.AbstractSpringFindUsagesTest
import org.jetbrains.kotlin.idea.spring.tests.generate.AbstractGenerateSpringDependencyActionTest
import org.jetbrains.kotlin.idea.spring.tests.gutter.AbstractSpringClassAnnotatorTest
import org.jetbrains.kotlin.idea.spring.tests.inspections.AbstractSpringInspectionTest
import org.jetbrains.kotlin.idea.spring.tests.quickfixes.AbstractSpringQuickFixTest
import org.jetbrains.kotlin.idea.spring.tests.references.AbstractSpringReferenceCompletionHandlerTest
import org.jetbrains.kotlin.idea.spring.tests.references.AbstractSpringReferenceCompletionTest
import org.jetbrains.kotlin.idea.spring.tests.references.AbstractSpringReferenceNavigationTest
@@ -31,12 +31,12 @@ fun main(args: Array<String>) {
System.setProperty("java.awt.headless", "true")
testGroup("ultimate/tests", "ultimate/testData") {
testClass<AbstractInspectionTest>("UltimateInspectionTestGenerated") {
model("inspections", pattern = "^(inspections\\.test)$", singleClass = true)
testClass<AbstractSpringInspectionTest> {
model("inspections/spring", pattern = "^(inspections\\.test)$", singleClass = true)
}
testClass<AbstractQuickFixTest>("UltimateQuickFixTestGenerated") {
model("quickFixes", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true)
testClass<AbstractSpringQuickFixTest> {
model("quickFixes/spring", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true)
}
testClass<AbstractSpringClassAnnotatorTest>() {