Spring Support: Show Spring line markers for Kotlin classes

#KT-3741 Fixed
This commit is contained in:
Alexey Sedunov
2016-03-22 20:26:30 +03:00
parent 8c72b02c9b
commit 28b8cfc3d5
66 changed files with 835 additions and 2 deletions
+1
View File
@@ -98,6 +98,7 @@ New features:
- [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
- [KT-11405](https://youtrack.jetbrains.com/issue/KT-11405) Navigation and Find Usages for Spring beans referenced in annotation arguments and BeanFactory method calls
- [KT-3741](https://youtrack.jetbrains.com/issue/KT-3741) Show Spring-specific line markers on Kotlin classes
General issues fixed:
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.asJava
import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtAnnotationEntry
@@ -66,6 +67,8 @@ class KtLightAnnotation(
}
}
override fun getReference() = references.singleOrNull()
override fun getReferences() = ReferenceProvidersRegistry.getReferencesFromProviders(delegate, PsiReferenceService.Hints.NO_HINTS)
override fun getLanguage() = KotlinLanguage.INSTANCE
}
@@ -145,8 +145,19 @@ public class KtLightParameter extends LightParameter implements KtLightDeclarati
return "";
}
@Override
public TextRange getTextRange() {
KtParameter origin = getOrigin();
return origin != null ? origin.getTextRange() : TextRange.EMPTY_RANGE;
}
@Override
public PsiIdentifier getNameIdentifier() {
return lightIdentifier;
}
@Override
public PsiElement getParent() {
return getMethod().getParameterList();
}
}
@@ -2,6 +2,8 @@
<extensions defaultExtensionNs="com.intellij">
<psi.referenceContributor language="kotlin" implementation="org.jetbrains.kotlin.idea.spring.references.KotlinSpringReferenceContributor"/>
<codeInsight.lineMarkerProvider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.spring.lineMarking.KotlinSpringClassAnnotator"/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.spring.inspections.KotlinFinalClassOrFunSpringInspection"
displayName="Final Kotlin class or function with Spring annotation"
groupBundle="resources.messages.SpringBundle"
@@ -0,0 +1,67 @@
/*
* 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.lineMarking
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.spring.gutter.SpringClassAnnotator
import org.jetbrains.kotlin.asJava.*
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
class KotlinSpringClassAnnotator : SpringClassAnnotator() {
override fun getElementToProcess(psiElement: PsiElement): PsiElement? {
if (psiElement is KtLightIdentifier) return psiElement.parent
psiElement.getParentOfTypeAndBranch<KtClass> { nameIdentifier }?.let { return it.toLightClass() }
psiElement.getParentOfTypeAndBranch<KtNamedFunction> { nameIdentifier }?.let { function ->
val containingClassOrObject = function.containingClassOrObject
val classForLightMethod = if (containingClassOrObject is KtObjectDeclaration
&& containingClassOrObject.isCompanion()
&& function.resolveToDescriptor().hasJvmStaticAnnotation()) {
containingClassOrObject.containingClassOrObject
}
else {
containingClassOrObject
}
return classForLightMethod?.toLightClass()?.methods?.firstOrNull { (it as? KtLightMethod)?.getOrigin() == function }
}
psiElement.getParentOfTypeAndBranch<KtProperty> { nameIdentifier }?.let { return it }
psiElement.getParentOfTypeAndBranch<KtAnnotationEntry> {
(typeReference?.typeElement as? KtUserType)?.referenceExpression?.getReferencedNameElement()
}?.let { return it.toLightAnnotation() }
return null
}
override fun collectNavigationMarkers(psiElement: PsiElement, result: MutableCollection<in RelatedItemLineMarkerInfo<PsiElement>>?) {
if (psiElement is KtProperty) {
for (it in psiElement.toLightElements()) {
val nameIdentifier = (it as? PsiNameIdentifierOwner)?.nameIdentifier ?: continue
super.collectNavigationMarkers(nameIdentifier, result)
}
return
}
// Workaround for SpringClassAnnotator
(getElementToProcess(psiElement) as? KtLightAnnotation)?.let { return super.collectNavigationMarkers(it, result) }
super.collectNavigationMarkers(psiElement, result)
}
}
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.idea.spring.tests
import com.intellij.facet.impl.FacetUtil
import com.intellij.openapi.module.Module
import com.intellij.spring.facet.SpringFacet
import com.intellij.spring.facet.SpringFileSet
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.TestFixtureExtension
@@ -50,6 +52,18 @@ class SpringTestFixtureExtension() : TestFixtureExtension {
FacetUtil.addFacet(module, SpringFacet.getSpringFacetType())
}
fun configureFileSet(fixture: CodeInsightTestFixture, configFiles: Collection<String>): SpringFileSet {
return configureFileSet(fixture, "default", module!!, configFiles)
}
fun configureFileSet(fixture: CodeInsightTestFixture, id: String, module: Module, configFiles: Collection<String>): SpringFileSet {
return module.getSpringFacetWithAssertion().addFileSet(id, id).apply {
configFiles.forEach { addFile(fixture.copyFileToProject(it)) }
}
}
fun Module.getSpringFacetWithAssertion() = SpringFacet.getInstance(this) ?: error("No Spring facet in ${this}")
override fun tearDown() {
try {
// clear existing SpringFacet configuration before running next test
@@ -0,0 +1,96 @@
/*
* 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.gutter
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.intellij.openapi.util.io.FileUtil
import com.intellij.testFramework.LightProjectDescriptor
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import icons.SpringApiIcons
import org.jetbrains.kotlin.idea.jsonUtils.getString
import org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.TestFixtureExtension
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
abstract class AbstractSpringClassAnnotatorTest : KotlinLightCodeInsightFixtureTestCase() {
override fun getProjectDescriptor() = LightCodeInsightFixtureTestCase.JAVA_LATEST
override fun setUp() {
super.setUp()
TestFixtureExtension.loadFixture<SpringTestFixtureExtension>(myModule)
}
protected fun doTest(path: String) {
val configFilePath = "${KotlinTestUtils.getHomeDirectory()}/$path"
val configFile = File(configFilePath)
val testRoot = configFile.parentFile
val config = JsonParser().parse(FileUtil.loadFile(configFile, true)) as JsonObject
val withRuntime = config["withRuntime"]?.asBoolean ?: false
if (withRuntime) {
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk())
}
try {
val springConfigFiles = (config["springConfig"] as JsonArray).map { it.asString }
myFixture.testDataPath = testRoot.absolutePath
TestFixtureExtension.getFixture<SpringTestFixtureExtension>()!!.configureFileSet(myFixture, springConfigFiles)
for (file in testRoot.listFiles()) {
val name = file.name
if (name in springConfigFiles) continue
if (file.isDirectory) myFixture.copyDirectoryToProject(name, name) else myFixture.copyFileToProject(name)
}
val fileName = config.getString("file")
val gutterMark = myFixture.findGutter(fileName)!!
val iconName = config.getString("icon")
val icon = SpringApiIcons::class.java.getField(iconName)[null]
assert(gutterMark.icon == icon)
val tooltip = config.getString("tooltip")
assert(gutterMark.tooltipText == tooltip)
val naming = config.getString("naming")
val targets = (config["targets"] as JsonArray).map { it.asString }
when (naming) {
"bean" -> checkBeanGutterTargets(gutterMark, targets)
"property" -> checkBeanPropertyTargets(gutterMark, targets)
"generic" -> checkPsiElementGutterTargets(gutterMark, targets)
else -> error("Unexpected naming: $naming")
}
}
finally {
if (withRuntime) {
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk())
}
}
}
override fun tearDown() {
TestFixtureExtension.unloadFixture<SpringTestFixtureExtension>()
super.tearDown()
}
}
@@ -0,0 +1,133 @@
/*
* 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.gutter;
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/spring/core/gutter")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class SpringClassAnnotatorTestGenerated extends AbstractSpringClassAnnotatorTest {
public void testAllFilesPresentInGutter() throws Exception {
KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/spring/core/gutter"), Pattern.compile("^(.+)\\.test$"));
}
@TestMetadata("autowiredBeanCandidates/autowiredBeanCandidates.test")
public void testAutowiredBeanCandidates_AutowiredBeanCandidates() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/autowiredBeanCandidates/autowiredBeanCandidates.test");
doTest(fileName);
}
@TestMetadata("autowiredProperty/autowiredProperty.test")
public void testAutowiredProperty_AutowiredProperty() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/autowiredProperty/autowiredProperty.test");
doTest(fileName);
}
@TestMetadata("autowiredSetter/autowiredSetter.test")
public void testAutowiredSetter_AutowiredSetter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/autowiredSetter/autowiredSetter.test");
doTest(fileName);
}
@TestMetadata("classGutter/classGutter.test")
public void testClassGutter_ClassGutter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/classGutter/classGutter.test");
doTest(fileName);
}
@TestMetadata("classGutterAbstractShowMappedInheritors/classGutterAbstractShowMappedInheritors.test")
public void testClassGutterAbstractShowMappedInheritors_ClassGutterAbstractShowMappedInheritors() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/classGutterAbstractShowMappedInheritors/classGutterAbstractShowMappedInheritors.test");
doTest(fileName);
}
@TestMetadata("componentScan/componentScan.test")
public void testComponentScan_ComponentScan() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/componentScan/componentScan.test");
doTest(fileName);
}
@TestMetadata("contextBeanInjectionPoints/contextBeanInjectionPoints.test")
public void testContextBeanInjectionPoints_ContextBeanInjectionPoints() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/contextBeanInjectionPoints/contextBeanInjectionPoints.test");
doTest(fileName);
}
@TestMetadata("contextBeanWithQualifierInjectionPoints/contextBeanWithQualifierInjectionPoints.test")
public void testContextBeanWithQualifierInjectionPoints_ContextBeanWithQualifierInjectionPoints() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/contextBeanWithQualifierInjectionPoints/contextBeanWithQualifierInjectionPoints.test");
doTest(fileName);
}
@TestMetadata("innerBean/innerBean.test")
public void testInnerBean_InnerBean() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/innerBean/innerBean.test");
doTest(fileName);
}
@TestMetadata("methodTypeDefaultInitMethod/methodTypeDefaultInitMethod.test")
public void testMethodTypeDefaultInitMethod_MethodTypeDefaultInitMethod() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/methodTypeDefaultInitMethod/methodTypeDefaultInitMethod.test");
doTest(fileName);
}
@TestMetadata("methodTypeFactory/methodTypeFactory.test")
public void testMethodTypeFactory_MethodTypeFactory() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/methodTypeFactory/methodTypeFactory.test");
doTest(fileName);
}
@TestMetadata("methodTypeInitMethod/methodTypeInitMethod.test")
public void testMethodTypeInitMethod_MethodTypeInitMethod() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/methodTypeInitMethod/methodTypeInitMethod.test");
doTest(fileName);
}
@TestMetadata("methodTypeMultiple/methodTypeMultiple.test")
public void testMethodTypeMultiple_MethodTypeMultiple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/methodTypeMultiple/methodTypeMultiple.test");
doTest(fileName);
}
@TestMetadata("propertyGutterForProperty/propertyGutterForProperty.test")
public void testPropertyGutterForProperty_PropertyGutterForProperty() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/propertyGutterForProperty/propertyGutterForProperty.test");
doTest(fileName);
}
@TestMetadata("propertyGutterForSetter/propertyGutterForSetter.test")
public void testPropertyGutterForSetter_PropertyGutterForSetter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/propertyGutterForSetter/propertyGutterForSetter.test");
doTest(fileName);
}
@TestMetadata("resourceGutter/resourceGutter.test")
public void testResourceGutter_ResourceGutter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/gutter/resourceGutter/resourceGutter.test");
doTest(fileName);
}
}
@@ -0,0 +1,74 @@
/*
* 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.gutter
import com.intellij.codeInsight.daemon.GutterMark
import com.intellij.codeInsight.daemon.LineMarkerInfo
import com.intellij.codeInsight.navigation.NavigationGutterIconRenderer
import com.intellij.pom.PomTargetPsiElement
import com.intellij.psi.PsiElement
import com.intellij.psi.presentation.java.SymbolPresentationUtil
import com.intellij.psi.xml.XmlTag
import com.intellij.spring.SpringPresentationProvider
import com.intellij.spring.model.pom.SpringBeanPomTargetUtils
import com.intellij.spring.model.xml.DomSpringBean
import com.intellij.spring.model.xml.beans.SpringPropertyDefinition
import com.intellij.testFramework.UsefulTestCase.assertSameElements
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.xml.DomUtil
import org.jetbrains.kotlin.test.util.assertInstanceOf
private fun nameBean(element: PsiElement): String {
return when (element) {
is XmlTag -> DomUtil.getDomElement(element).assertInstanceOf<DomSpringBean>().beanName!!
is PomTargetPsiElement -> SpringBeanPomTargetUtils.getSpringBean(element)?.let { SpringPresentationProvider.getSpringBeanName(it) }
?: namePsi(element)
else -> throw IllegalArgumentException("Cannot convert " + element.javaClass + " (" + element.text + ")")
}
}
private fun nameProperty(element: PsiElement) = DomUtil.getDomElement(element).assertInstanceOf<SpringPropertyDefinition>().propertyName!!
private fun namePsi(element: PsiElement) = SymbolPresentationUtil.getSymbolPresentableText(element)
fun checkBeanGutterTargets(gutterMark: GutterMark, expectedBeanNames: Collection<String>) {
checkGutterTargets(gutterMark, expectedBeanNames, ::nameBean)
}
fun checkBeanPropertyTargets(gutterMark: GutterMark, expectedPropertyNames: Collection<String>) {
checkGutterTargets(gutterMark, expectedPropertyNames, ::nameProperty)
}
fun checkPsiElementGutterTargets(gutterMark: GutterMark, expectedSymbolNames: Collection<String>) {
checkGutterTargets(gutterMark, expectedSymbolNames, ::namePsi)
}
fun checkGutterTargets(
gutterMark: GutterMark,
expectedValues: Collection<String>,
targetNamer: (PsiElement) -> String
) {
val targetElements = when (gutterMark) {
is LineMarkerInfo.LineMarkerGutterIconRenderer<*> ->
gutterMark.lineMarkerInfo.navigationHandler.assertInstanceOf<NavigationGutterIconRenderer>().targetElements
is NavigationGutterIconRenderer ->
gutterMark.targetElements
else -> throw IllegalArgumentException("${gutterMark.javaClass.name} not supported")
}
assertSameElements(ContainerUtil.map(targetElements, targetNamer), expectedValues)
}
@@ -49,10 +49,15 @@ class KotlinAnnotatedElementsSearcher : QueryExecutor<PsiModifierListOwner, Anno
val lightClass = declaration.toLightClass()
consumer.process(lightClass)
}
is KtNamedFunction, is KtSecondaryConstructor -> {
is KtNamedFunction, is KtConstructor<*> -> {
val wrappedMethod = LightClassUtil.getLightClassMethod(declaration as KtFunction)
consumer.process(wrappedMethod)
}
is KtProperty -> {
with (LightClassUtil.getLightClassPropertyMethods(declaration)) {
if (backingField != null) consumer.process(backingField) else all { consumer.process(it) }
}
}
else -> true
}
}
@@ -8,4 +8,5 @@ annotation class MyAnnotation(val first: String, val second: String)
// ANNOTATION: MyAnnotation
// SEARCH: method:test1
// SEARCH: class:Test1
// SEARCH: class:Test1
// SEARCH: field:test3
@@ -0,0 +1,17 @@
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
class Bean {
@Autowired
fun setProp1(autowiredProp: String) {
}
@Autowired
lateinit var prop2: String
@Be<caret>an(name = "myBean")
@Autowired
fun myBean(collab: String): String {
return "aaa" + collab
}
}
@@ -0,0 +1,9 @@
{
withRuntime: "true",
springConfig: ["config.xml"],
file: "Bean.kt",
icon: "ShowAutowiredDependencies",
tooltip: "Navigate to autowired candidates",
naming: "generic",
targets: ["myBean(String)", "prop2", "setProp1(String)"]
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-init-method="myDefaultInitMethod"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean" class="Bean"/>
<bean id="stringBean1" class="java.lang.String"/>
<bean id="stringBean2" class="java.lang.String"/>
</beans>
@@ -0,0 +1,6 @@
import org.springframework.beans.factory.annotation.Autowired
class Bean {
@Autowired
lateinit var pr<caret>op: String
}
@@ -0,0 +1,8 @@
{
springConfig: ["config.xml"],
file: "Bean.kt",
icon: "ShowAutowiredDependencies",
tooltip: "Navigate to the autowired dependencies",
naming: "bean",
targets: ["stringBean1", "stringBean2"]
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-init-method="myDefaultInitMethod"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean" class="Bean"/>
<bean id="stringBean1" class="java.lang.String"/>
<bean id="stringBean2" class="java.lang.String"/>
</beans>
@@ -0,0 +1,6 @@
import org.springframework.beans.factory.annotation.Autowired
class Bean {
@Autowired
fun setProp(autowired<caret>Prop: String) { }
}
@@ -0,0 +1,9 @@
{
withRuntime: "true",
"springConfig": ["config.xml"],
file: "Bean.kt",
icon: "ShowAutowiredDependencies",
tooltip: "Navigate to the autowired dependencies",
naming: "bean",
targets: ["stringBean1", "stringBean2"]
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-init-method="myDefaultInitMethod"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean" class="Bean"/>
<bean id="stringBean1" class="java.lang.String"/>
<bean id="stringBean2" class="java.lang.String"/>
</beans>
+7
View File
@@ -0,0 +1,7 @@
class Be<caret>an {
var prop1: String
fun setProp2(value: String) {
}
}
@@ -0,0 +1,8 @@
{
springConfig: ["config.xml"],
file: "Bean.kt",
icon: "SpringBean",
tooltip: "Navigate to the spring bean declaration(s)",
naming: "bean",
targets: ["bean"]
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="bean" class="Bean"/>
</beans>
@@ -0,0 +1 @@
abstract class Abstract<caret>Bean
@@ -0,0 +1 @@
class AbstractBeanInheritor : AbstractBean()
@@ -0,0 +1 @@
class AbstractBeanInheritor2 : AbstractBean()
@@ -0,0 +1,8 @@
{
springConfig: ["inheritors.xml"],
file: "AbstractBean.kt",
icon: "SpringBean",
tooltip: "Navigate to the spring bean declaration(s)",
naming: "bean",
targets: ["inheritor", "inheritor2"]
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="inheritor" class="AbstractBeanInheritor"/>
<bean id="inheritor2" class="AbstractBeanInheritor2"/>
</beans>
@@ -0,0 +1,3 @@
package test
class Bean(val n: Int)
@@ -0,0 +1,6 @@
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
@Component<caret>Scan("beans")
@Configuration
open class ComponentScan
@@ -0,0 +1,6 @@
package beans
import org.springframework.stereotype.Controller
@Controller(value = "customControllerName")
class MyController
@@ -0,0 +1,18 @@
package beans
import org.springframework.stereotype.Component
import javax.annotation.Resource
import test.Bean
@Component
class ResourceGutter {
@Resource(name = "bean1")
fun setResource(be<caret>an: Bean) {
}
@Resource
fun setUnknown(booo: Boolean) {
}
}
@@ -0,0 +1,8 @@
{
springConfig: ["ComponentScan.kt"],
file: "ComponentScan.kt",
icon: "SpringJavaBean",
tooltip: "Navigate to the spring bean declaration(s)",
naming: "bean",
targets: ["resourceGutter", "customControllerName"]
}
@@ -0,0 +1,21 @@
import pkg.*
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Bean
@Configuration
class ContextBeanInjectionPoints {
@Bean
fun foo(): Foo {
return Foo()
}
@Bean
fun foo2(): Foo {
return Foo()
}
@Bean
fun bar(f: F<caret>oo): Bar {
return Bar(f)
}
}
@@ -0,0 +1,5 @@
package pkg
class Foo
class Bar(foo: Foo)
@@ -0,0 +1,8 @@
{
springConfig: [],
file: "ContextBeanInjectionPoints.kt",
icon: "ShowAutowiredDependencies",
tooltip: "Navigate to the autowired dependencies",
naming: "generic",
targets: ["foo()", "foo2()"]
}
@@ -0,0 +1,22 @@
import pkg.*
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Bean
import org.springframework.beans.factory.annotation.Qualifier
@Configuration
class ContextBeanWithQualifierInjectionPoints {
@Bean
fun foo(): Foo {
return Foo()
}
@Bean
fun foo2(): Foo {
return Foo()
}
@Bean
fun bar(@Qualifier("foo2") f: F<caret>oo): Bar {
return Bar(f)
}
}
@@ -0,0 +1,5 @@
package pkg
class Foo
class Bar(foo: Foo)
@@ -0,0 +1,9 @@
{
withRuntime: "true",
springConfig: [],
file: "ContextBeanWithQualifierInjectionPoints.kt",
icon: "ShowAutowiredDependencies",
tooltip: "Navigate to the autowired dependencies",
naming: "generic",
targets: ["foo2()"]
}
@@ -0,0 +1 @@
class Inner<caret>Bean
@@ -0,0 +1,8 @@
{
springConfig: ["innerBeanGutter.xml"],
file: "InnerBean.kt",
icon: "SpringBean",
tooltip: "Navigate to the spring bean declaration(s)",
naming: "bean",
targets: ["InnerBean"]
}
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="bean" class="Bean">
<property name="foo">
<bean class="InnerBean"/>
</property>
</bean>
</beans>
@@ -0,0 +1,4 @@
class Bean {
fun my<caret>Init() {
}
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-init-method="myInit"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean" class="Bean"/>
</beans>
@@ -0,0 +1,8 @@
{
springConfig: ["config.xml"],
file: "Bean.kt",
icon: "SpringBeanMethod",
tooltip: "Navigate to the spring bean init method declaration",
naming: "generic",
targets: ["default-init-method"]
}
@@ -0,0 +1,6 @@
class Bean {
companion object {
@JvmStatic
fun my<caret>Factory() = "TEST"
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean" class="Bean" factory-method="myFactory"/>
</beans>
@@ -0,0 +1,9 @@
{
withRuntime: "true",
springConfig: ["config.xml"],
file: "Bean.kt",
icon: "FactoryMethodBean",
tooltip: "Navigate to the spring bean factory method declaration",
naming: "generic",
targets: ["factory-method"]
}
@@ -0,0 +1,4 @@
class Bean {
fun my<caret>Init() {
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean" class="Bean" init-method="myInit"/>
</beans>
@@ -0,0 +1,8 @@
{
springConfig: ["config.xml"],
file: "Bean.kt",
icon: "SpringBeanMethod",
tooltip: "Navigate to the spring bean init method declaration",
naming: "generic",
targets: ["init-method"]
}
@@ -0,0 +1,4 @@
class Bean {
fun my<caret>Fun() {
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean" class="Bean" destroy-method="myFun" factory-method="myFun" init-method="myFun"/>
</beans>
@@ -0,0 +1,8 @@
{
springConfig: ["config.xml"],
file: "Bean.kt",
icon: "SpringBeanMethod",
tooltip: "Navigate to the spring bean method declarations",
naming: "generic",
targets: ["destroy-method", "init-method"]
}
@@ -0,0 +1,3 @@
class BeanWithProperties {
lateinit var pr<caret>op: String
}
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="my" class="BeanWithProperties" p:prop="2">
<property name="prop" value="2"/>
</bean>
</beans>
@@ -0,0 +1,8 @@
{
springConfig: ["propertyGutter.xml"],
file: "BeanWithProperties.kt",
icon: "SpringProperty",
tooltip: "Navigate to the spring bean property",
naming: "property",
targets: ["prop", "prop"]
}
@@ -0,0 +1,3 @@
class BeanWithProperties {
fun set<caret>Prop(prop: String) { }
}
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="my" class="BeanWithProperties" p:prop="2">
<property name="prop" value="2"/>
</bean>
</beans>
@@ -0,0 +1,8 @@
{
springConfig: ["propertyGutter.xml"],
file: "BeanWithProperties.kt",
icon: "SpringProperty",
tooltip: "Navigate to the spring bean property",
naming: "property",
targets: ["prop", "prop"]
}
@@ -0,0 +1,3 @@
package test
class Bean(val n: Int)
@@ -0,0 +1,3 @@
package javax.annotation
annotation class Resource(val name: String = "")
@@ -0,0 +1,13 @@
package beans
import org.springframework.stereotype.Component
import javax.annotation.Resource
import test.Bean
@Component
class ResourceGutter {
@Resource(name = "bean1")
fun setResource(be<caret>an: Bean) {
}
}
@@ -0,0 +1,8 @@
{
springConfig: ["resourceGutter.xml"],
file: "beans/ResourceGutter.kt",
icon: "ShowAutowiredDependencies",
tooltip: "Navigate to the autowired dependencies",
naming: "bean",
targets: ["bean1"]
}
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ctx="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd ">
<ctx:component-scan annotation-config="true" base-package="beans"/>
<bean id="bean1" class="test.Bean">
<constructor-arg type="int" value="1"/>
</bean>
<bean id="bean2" class="test.Bean">
<constructor-arg type="int" value="2"/>
</bean>
</beans>
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.search;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.LightProjectDescriptor;
@@ -74,6 +75,9 @@ public abstract class AbstractSearcherTest extends LightCodeInsightFixtureTestCa
if (member instanceof PsiMethod) {
return "method:" + ((PsiMethod) member).getName();
}
if (member instanceof PsiField) {
return "field:" + ((PsiField) member).getName();
}
throw new IllegalStateException("Do not know how to render member of type: " + member.getClass().getName());
}