diff --git a/Changelog.md b/Changelog.md index b8674c6f2f0..80901effb39 100644 --- a/Changelog.md +++ b/Changelog.md @@ -97,6 +97,7 @@ New features: - [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 +- [KT-11405](https://youtrack.jetbrains.com/issue/KT-11405) Navigation and Find Usages for Spring beans referenced in annotation arguments and BeanFactory method calls General issues fixed: diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt index 4ad0b18d3fe..f9612b0b3bf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt @@ -366,6 +366,9 @@ fun KtStringTemplateExpression.getContentRange(): TextRange { return TextRange(start, if (lastChild.elementType == KtTokens.CLOSING_QUOTE) length - lastChild.textLength else length) } +val KtStringTemplateExpression.plainContent: String + get() = getContentRange().substring(text) + fun KtStringTemplateExpression.isSingleQuoted(): Boolean = node.firstChildNode.textLength == 1 diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 5a49e8a2176..4da5a1a9ae3 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -101,6 +101,9 @@ import org.jetbrains.kotlin.idea.refactoring.pushDown.AbstractPushDownTest import org.jetbrains.kotlin.idea.refactoring.rename.AbstractRenameTest import org.jetbrains.kotlin.idea.refactoring.safeDelete.AbstractSafeDeleteTest import org.jetbrains.kotlin.idea.resolve.* +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 import org.jetbrains.kotlin.idea.structureView.AbstractKotlinFileStructureTest import org.jetbrains.kotlin.idea.stubs.AbstractMultiFileHighlightingTest import org.jetbrains.kotlin.idea.stubs.AbstractResolveByStubTest @@ -782,6 +785,18 @@ fun main(args: Array) { testClass("UltimateQuickFixTestGenerated") { model("ultimateQuickFixes", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true) } + + testClass() { + model("spring/core/references/completion/handler") + } + + testClass() { + model("spring/core/references/completion/variants") + } + + testClass() { + model("spring/core/references/navigation") + } } testGroup("idea/tests", "compiler/testData") { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/AbstractKotlinReferenceContributor.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/AbstractKotlinReferenceContributor.kt new file mode 100644 index 00000000000..36f45f81cf3 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/AbstractKotlinReferenceContributor.kt @@ -0,0 +1,56 @@ +/* + * 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.references + +import com.intellij.patterns.ElementPattern +import com.intellij.patterns.PlatformPatterns +import com.intellij.psi.* +import com.intellij.util.ProcessingContext +import org.jetbrains.kotlin.psi.KtElement + +abstract class AbstractKotlinReferenceContributor : PsiReferenceContributor() { + protected inline fun PsiReferenceRegistrar.registerProvider( + priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY, + crossinline factory: (E) -> PsiReference? + ) { + registerMultiProvider(priority) { factory(it)?.let { arrayOf(it) } ?: PsiReference.EMPTY_ARRAY } + } + + protected inline fun PsiReferenceRegistrar.registerMultiProvider( + priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY, + crossinline factory: (E) -> Array + ) { + registerMultiProvider(PlatformPatterns.psiElement(E::class.java), priority, factory) + } + + protected inline fun PsiReferenceRegistrar.registerMultiProvider( + pattern: ElementPattern, + priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY, + crossinline factory: (E) -> Array + ) { + registerReferenceProvider( + pattern, + object : PsiReferenceProvider() { + override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array { + @Suppress("UNCHECKED_CAST") + return factory(element as E) + } + }, + priority + ) + } +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinReferenceContributor.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinReferenceContributor.kt index f0fc216a224..cf05d938f90 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinReferenceContributor.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinReferenceContributor.kt @@ -16,22 +16,21 @@ package org.jetbrains.kotlin.idea.references -import com.intellij.patterns.PlatformPatterns -import com.intellij.psi.* -import com.intellij.util.ProcessingContext +import com.intellij.psi.PsiReference +import com.intellij.psi.PsiReferenceRegistrar import org.jetbrains.kotlin.idea.kdoc.KDocReference import org.jetbrains.kotlin.kdoc.psi.impl.KDocName import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* -class KotlinReferenceContributor() : PsiReferenceContributor() { +class KotlinReferenceContributor() : AbstractKotlinReferenceContributor() { override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) { with(registrar) { - registerProvider(KtSimpleNameExpression::class.java) { + registerProvider { KtSimpleNameReference(it) } - registerMultiProvider(KtNameReferenceExpression::class.java) { + registerMultiProvider { if (it.getReferencedNameElementType() != KtTokens.IDENTIFIER) return@registerMultiProvider emptyArray() when (it.readWriteAccess(useResolveForReadWrite = false)) { @@ -44,46 +43,33 @@ class KotlinReferenceContributor() : PsiReferenceContributor() { } } - registerProvider(KtConstructorDelegationReferenceExpression::class.java) { + registerProvider { KtConstructorDelegationReference(it) } - registerProvider(KtCallExpression::class.java) { + registerProvider { KtInvokeFunctionReference(it) } - registerProvider(KtArrayAccessExpression::class.java) { + registerProvider { KtArrayAccessReference(it) } - registerProvider(KtForExpression::class.java) { + registerProvider { KtForLoopInReference(it) } - registerProvider(KtPropertyDelegate::class.java) { + registerProvider { KtPropertyDelegationMethodsReference(it) } - registerProvider(KtDestructuringDeclaration::class.java) { + registerProvider { KtDestructuringDeclarationReference(it) } - registerProvider(KDocName::class.java) { + registerProvider { KDocReference(it) } } } - - private fun PsiReferenceRegistrar.registerProvider(elementClass: Class, factory: (E) -> KtReference) { - registerMultiProvider(elementClass, { arrayOf(factory(it)) }) - } - - private fun PsiReferenceRegistrar.registerMultiProvider(elementClass: Class, factory: (E) -> Array) { - registerReferenceProvider(PlatformPatterns.psiElement(elementClass), object: PsiReferenceProvider() { - override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array { - @Suppress("UNCHECKED_CAST") - return factory(element as E) - } - }) - } } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/KotlinFixtureCompletionBaseTestCase.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/KotlinFixtureCompletionBaseTestCase.kt index 3f6f8beae17..3f6764ea9cd 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/KotlinFixtureCompletionBaseTestCase.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/KotlinFixtureCompletionBaseTestCase.kt @@ -36,13 +36,18 @@ abstract class KotlinFixtureCompletionBaseTestCase : KotlinLightCodeInsightFixtu open fun doTest(testPath: String) { setUpFixture(testPath) - val fileText = FileUtil.loadFile(File(testPath), true) + try { + val fileText = FileUtil.loadFile(File(testPath), true) - if (ExpectedCompletionUtils.shouldRunHighlightingBeforeCompletion(fileText)) { - myFixture.doHighlighting() + if (ExpectedCompletionUtils.shouldRunHighlightingBeforeCompletion(fileText)) { + myFixture.doHighlighting() + } + + testCompletion(fileText, getPlatform(), { completionType, count -> complete(completionType, count) }, defaultCompletionType(), defaultInvocationCount()) + } + finally { + tearDownFixture() } - - testCompletion(fileText, getPlatform(), { completionType, count -> complete(completionType, count) }, defaultCompletionType(), defaultInvocationCount()) } protected open fun setUpFixture(testPath: String) { @@ -51,4 +56,8 @@ abstract class KotlinFixtureCompletionBaseTestCase : KotlinLightCodeInsightFixtu myFixture.configureByFile(testPath) } + + protected open fun tearDownFixture() { + + } } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt index 88c1160a85e..08918cc4a60 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt @@ -73,6 +73,7 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType: } finally { settingManager.dropTemporarySettings() + tearDownFixture() } } @@ -80,6 +81,10 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType: fixture.configureByFile(testPath) } + protected open fun tearDownFixture() { + + } + override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE } diff --git a/idea/idea-ultimate/src/META-INF/kotlin-spring.xml b/idea/idea-ultimate/src/META-INF/kotlin-spring.xml index 8999970dab2..a8767bc3bcb 100644 --- a/idea/idea-ultimate/src/META-INF/kotlin-spring.xml +++ b/idea/idea-ultimate/src/META-INF/kotlin-spring.xml @@ -1,5 +1,7 @@ + + { + if (!it.isPlain()) return@registerProvider null + + val callExpression = (it.parent as? KtValueArgument)?.getStrictParentOfType() ?: return@registerProvider null + val context = callExpression.analyze(BodyResolveMode.PARTIAL) + val resolvedCall = callExpression.getResolvedCall(context) ?: return@registerProvider null + val callable = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return@registerProvider null + if (!callable.overriddenTreeAsSequence(true).any { + it.containingDeclaration.importableFqName?.asString() == SpringConstants.BEAN_FACTORY_CLASS + }) return@registerProvider null + if (callable.name.asString() !in SpringBeanNamesReferenceProvider.METHODS) return@registerProvider null + + SpringBeanReference(it, it.getContentRange()) + } + + registrar.registerProvider(PsiReferenceRegistrar.HIGHER_PRIORITY) { + if (!it.isPlain()) return@registerProvider null + + val argument = it.parent as? KtValueArgument ?: return@registerProvider null + val argumentName = argument.getArgumentName() ?: return@registerProvider null + if (argumentName.asName.asString() != "name") return@registerProvider null + + val entry = argument.getStrictParentOfType() ?: return@registerProvider null + val context = entry.analyze(BodyResolveMode.PARTIAL) + val resolvedCall = entry.getResolvedCall(context) ?: return@registerProvider null + val annotation = (resolvedCall.resultingDescriptor as? ConstructorDescriptor)?.containingDeclaration ?: return@registerProvider null + if (annotation.importableFqName?.asString() != SpringAnnotationsConstants.JAVAX_RESOURCE) return@registerProvider null + + val contentRange = it.getContentRange() + var startOffset = contentRange.startOffset + val isFactoryBeanRef: Boolean + if (it.plainContent.startsWith("&")) { + startOffset++ + isFactoryBeanRef = true + } + else { + isFactoryBeanRef = false + } + + val callable = (it.getStrictParentOfType()?.parent as? KtModifierList)?.parent as? KtCallableDeclaration + val callableType = (callable?.resolveToDescriptor() as? CallableDescriptor)?.returnType + val requiredSuperClass = callableType?.constructor?.declarationDescriptor?.source?.getPsi() as? KtClass + + SpringBeanReference(it, TextRange(startOffset, contentRange.endOffset), requiredSuperClass?.toLightClass(), isFactoryBeanRef) + } + + registrar.registerProvider(PsiReferenceRegistrar.HIGHER_PRIORITY) { + if (!it.isPlain()) return@registerProvider null + + val argument = it.parent as? KtValueArgument ?: return@registerProvider null + val argumentName = argument.getArgumentName() + if (argumentName != null && argumentName.asName.asString() != "value") return@registerProvider null + + val entry = argument.getStrictParentOfType() ?: return@registerProvider null + val context = entry.analyze(BodyResolveMode.PARTIAL) + val resolvedCall = entry.getResolvedCall(context) ?: return@registerProvider null + val annotation = (resolvedCall.resultingDescriptor as? ConstructorDescriptor)?.containingDeclaration ?: return@registerProvider null + if (annotation.importableFqName?.asString() != SpringAnnotationsConstants.SCOPE) return@registerProvider null + + KtSpringBeanScopeReference(it) + } + + registrar.registerMultiProvider { + if (!it.isPlain()) return@registerMultiProvider PsiReference.EMPTY_ARRAY + + val callExpression = (it.parent as? KtValueArgument)?.getStrictParentOfType() + ?: return@registerMultiProvider PsiReference.EMPTY_ARRAY + val context = callExpression.analyze(BodyResolveMode.PARTIAL) + val resolvedCall = callExpression.getResolvedCall(context) ?: return@registerMultiProvider PsiReference.EMPTY_ARRAY + val classDescriptor = (resolvedCall.resultingDescriptor as? ConstructorDescriptor)?.containingDeclaration + ?: return@registerMultiProvider PsiReference.EMPTY_ARRAY + val qName = classDescriptor.importableFqName?.asString() + if (qName != SpringConstants.CLASS_PATH_XML_APP_CONTEXT && qName != SpringConstants.CLASS_PATH_RESOURCE) { + return@registerMultiProvider PsiReference.EMPTY_ARRAY + } + + val content = it.plainContent + val resourcesBuilder = SpringResourcesBuilder.create(it, content).fromRoot(content.startsWith("/")).soft(false) + SpringResourcesUtil.getInstance().getClassPathReferences(resourcesBuilder) + } + } +} \ No newline at end of file diff --git a/idea/idea-ultimate/src/org/jetbrains/kotlin/idea/spring/references/KtSpringBeanScopeReference.kt b/idea/idea-ultimate/src/org/jetbrains/kotlin/idea/spring/references/KtSpringBeanScopeReference.kt new file mode 100644 index 00000000000..1254d1be575 --- /dev/null +++ b/idea/idea-ultimate/src/org/jetbrains/kotlin/idea/spring/references/KtSpringBeanScopeReference.kt @@ -0,0 +1,44 @@ +/* + * 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.references + +import com.intellij.codeInsight.lookup.LookupElementBuilder +import com.intellij.ide.TypePresentationService +import com.intellij.psi.ElementManipulators +import com.intellij.psi.PsiReferenceBase +import com.intellij.spring.model.scope.SpringBeanScope +import com.intellij.spring.model.scope.SpringBeanScopeManager +import org.jetbrains.kotlin.psi.KtStringTemplateExpression +import org.jetbrains.kotlin.psi.psiUtil.plainContent + +class KtSpringBeanScopeReference( + element: KtStringTemplateExpression +) : PsiReferenceBase(element, ElementManipulators.getManipulator(element).getRangeInElement(element)) { + private fun getScopes(): Sequence { + return SpringBeanScope.getDefaultScopes().asSequence() + SpringBeanScopeManager.getInstance().getCustomBeanScopes(element) + } + + private fun getLookupElement(scope: String): LookupElementBuilder { + return LookupElementBuilder + .create(scope) + .withIcon(TypePresentationService.getService().getTypeIcon(SpringBeanScope::class.java)) + } + + override fun resolve() = if (element.plainContent in getScopes().map { it.value }) element else null + + override fun getVariants() = getScopes().map { getLookupElement(it.value) }.toList().toTypedArray() +} diff --git a/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/AbstractSpringReferenceCompletionHandlerTest.kt b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/AbstractSpringReferenceCompletionHandlerTest.kt new file mode 100644 index 00000000000..156a945ad3d --- /dev/null +++ b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/AbstractSpringReferenceCompletionHandlerTest.kt @@ -0,0 +1,39 @@ +/* + * 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.references + +import com.intellij.util.PathUtil +import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractBasicCompletionHandlerTest +import org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension +import org.jetbrains.kotlin.idea.test.TestFixtureExtension +import java.io.File + +abstract class AbstractSpringReferenceCompletionHandlerTest : AbstractBasicCompletionHandlerTest() { + override fun setUpFixture(testPath: String) { + super.setUpFixture(testPath) + + TestFixtureExtension + .loadFixture(myModule) + .configureFileSet(myFixture, listOf(PathUtil.toSystemIndependentName(File(testPath).parent + "/spring-config.xml"))) + } + + override fun tearDownFixture() { + TestFixtureExtension.unloadFixture() + + super.tearDownFixture() + } +} \ No newline at end of file diff --git a/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/AbstractSpringReferenceCompletionTest.kt b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/AbstractSpringReferenceCompletionTest.kt new file mode 100644 index 00000000000..b0fa8cb070c --- /dev/null +++ b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/AbstractSpringReferenceCompletionTest.kt @@ -0,0 +1,39 @@ +/* + * 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.references + +import com.intellij.util.PathUtil +import org.jetbrains.kotlin.idea.completion.test.AbstractJvmBasicCompletionTest +import org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension +import org.jetbrains.kotlin.idea.test.TestFixtureExtension +import java.io.File + +abstract class AbstractSpringReferenceCompletionTest : AbstractJvmBasicCompletionTest() { + override fun setUpFixture(testPath: String) { + super.setUpFixture(testPath) + + TestFixtureExtension + .loadFixture(myModule)!! + .configureFileSet(myFixture, listOf(PathUtil.toSystemIndependentName(File(testPath).parent + "/spring-config.xml"))) + } + + override fun tearDownFixture() { + TestFixtureExtension.unloadFixture() + + super.tearDownFixture() + } +} \ No newline at end of file diff --git a/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/AbstractSpringReferenceNavigationTest.kt b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/AbstractSpringReferenceNavigationTest.kt new file mode 100644 index 00000000000..2d8420f5545 --- /dev/null +++ b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/AbstractSpringReferenceNavigationTest.kt @@ -0,0 +1,61 @@ +/* + * 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.references + +import com.intellij.codeInsight.navigation.GotoTargetHandler +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.idea.actions.AbstractNavigationTest +import org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension +import org.jetbrains.kotlin.idea.test.TestFixtureExtension +import org.jetbrains.kotlin.psi.KtStringTemplateExpression +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.test.InTextDirectivesUtils + +abstract class AbstractSpringReferenceNavigationTest : AbstractNavigationTest() { + override fun getSourceAndTargetElements(editor: Editor, file: PsiFile): GotoTargetHandler.GotoData? { + val stringTemplate = file.findElementAt(editor.caretModel.offset)!!.getNonStrictParentOfType()!! + return GotoTargetHandler.GotoData(stringTemplate, + stringTemplate.references.mapNotNull { it.resolve() }.toTypedArray(), + emptyList()) + } + + override fun setUp() { + super.setUp() + TestFixtureExtension.loadFixture(myModule)!! + } + + override fun configureExtra(mainFileBaseName: String, mainFileText: String) { + if (!InTextDirectivesUtils.isDirectiveDefined(mainFileText, "// NO_XML_CONFIG")) { + TestFixtureExtension + .getFixture()!! + .configureFileSet(myFixture, listOf("${mainFileBaseName}_config.xml")) + } + if (InTextDirectivesUtils.isDirectiveDefined(mainFileText, "// JAVAX_ANNOTATION_RESOURCE")) { + myFixture.configureByText( + KotlinFileType.INSTANCE, + """package javax.annotation; annotation class Resource(val name: String = "")""" + ) + } + } + + override fun tearDown() { + TestFixtureExtension.unloadFixture() + super.tearDown() + } +} \ No newline at end of file diff --git a/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionHandlerTestGenerated.java b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionHandlerTestGenerated.java new file mode 100644 index 00000000000..13eeb71a123 --- /dev/null +++ b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionHandlerTestGenerated.java @@ -0,0 +1,55 @@ +/* + * 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.references; + +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/references/completion/handler") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class SpringReferenceCompletionHandlerTestGenerated extends AbstractSpringReferenceCompletionHandlerTest { + public void testAllFilesPresentInHandler() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/spring/core/references/completion/handler"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("scopeReference.kt") + public void testScopeReference() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/completion/handler/scopeReference.kt"); + doTest(fileName); + } + + @TestMetadata("springBeanReferenceEnter.kt") + public void testSpringBeanReferenceEnter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/completion/handler/springBeanReferenceEnter.kt"); + doTest(fileName); + } + + @TestMetadata("springBeanReferenceTab.kt") + public void testSpringBeanReferenceTab() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/completion/handler/springBeanReferenceTab.kt"); + doTest(fileName); + } +} diff --git a/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionTestGenerated.java b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionTestGenerated.java new file mode 100644 index 00000000000..7ae8b2ce091 --- /dev/null +++ b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionTestGenerated.java @@ -0,0 +1,49 @@ +/* + * 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.references; + +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/references/completion/variants") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class SpringReferenceCompletionTestGenerated extends AbstractSpringReferenceCompletionTest { + public void testAllFilesPresentInVariants() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/spring/core/references/completion/variants"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("scopeReference.kt") + public void testScopeReference() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/completion/variants/scopeReference.kt"); + doTest(fileName); + } + + @TestMetadata("springBeanReference.kt") + public void testSpringBeanReference() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/completion/variants/springBeanReference.kt"); + doTest(fileName); + } +} diff --git a/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceNavigationTestGenerated.java b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceNavigationTestGenerated.java new file mode 100644 index 00000000000..1edd7c95cc7 --- /dev/null +++ b/idea/idea-ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceNavigationTestGenerated.java @@ -0,0 +1,79 @@ +/* + * 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.references; + +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/references/navigation") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class SpringReferenceNavigationTestGenerated extends AbstractSpringReferenceNavigationTest { + public void testAllFilesPresentInNavigation() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/spring/core/references/navigation"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("fileReferenceInClasspathResource.kt") + public void testFileReferenceInClasspathResource() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/navigation/fileReferenceInClasspathResource.kt"); + doTest(fileName); + } + + @TestMetadata("fileReferenceInClasspathXmlContext.kt") + public void testFileReferenceInClasspathXmlContext() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/navigation/fileReferenceInClasspathXmlContext.kt"); + doTest(fileName); + } + + @TestMetadata("scopeReference.kt") + public void testScopeReference() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/navigation/scopeReference.kt"); + doTest(fileName); + } + + @TestMetadata("springBeanRefInFactoryContainsBean.kt") + public void testSpringBeanRefInFactoryContainsBean() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/navigation/springBeanRefInFactoryContainsBean.kt"); + doTest(fileName); + } + + @TestMetadata("springBeanRefInFactoryGetBean.kt") + public void testSpringBeanRefInFactoryGetBean() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/navigation/springBeanRefInFactoryGetBean.kt"); + doTest(fileName); + } + + @TestMetadata("springBeanRefInResource.kt") + public void testSpringBeanRefInResource() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/navigation/springBeanRefInResource.kt"); + doTest(fileName); + } + + @TestMetadata("springFactoryBeanRefInResource.kt") + public void testSpringFactoryBeanRefInResource() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/spring/core/references/navigation/springFactoryBeanRefInResource.kt"); + doTest(fileName); + } +} diff --git a/idea/src/org/jetbrains/kotlin/idea/properties/KotlinPropertiesReferenceContributor.kt b/idea/src/org/jetbrains/kotlin/idea/properties/KotlinPropertiesReferenceContributor.kt index abf03e28783..616d8473972 100644 --- a/idea/src/org/jetbrains/kotlin/idea/properties/KotlinPropertiesReferenceContributor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/properties/KotlinPropertiesReferenceContributor.kt @@ -17,12 +17,11 @@ package org.jetbrains.kotlin.idea.properties import com.intellij.patterns.PlatformPatterns -import com.intellij.psi.PsiReferenceContributor import com.intellij.psi.PsiReferenceRegistrar -import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry +import org.jetbrains.kotlin.idea.references.AbstractKotlinReferenceContributor import org.jetbrains.kotlin.psi.KtStringTemplateExpression -class KotlinPropertiesReferenceContributor : PsiReferenceContributor() { +class KotlinPropertiesReferenceContributor : AbstractKotlinReferenceContributor() { override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) { registrar.registerReferenceProvider( PlatformPatterns.psiElement(KtStringTemplateExpression::class.java), diff --git a/idea/testData/spring/core/references/completion/handler/scopeReference.kt b/idea/testData/spring/core/references/completion/handler/scopeReference.kt new file mode 100644 index 00000000000..57a792359c2 --- /dev/null +++ b/idea/testData/spring/core/references/completion/handler/scopeReference.kt @@ -0,0 +1,7 @@ +// ELEMENT: singleton +package test + +import org.springframework.context.annotation.Scope + +@Scope("") +class ScopedBean \ No newline at end of file diff --git a/idea/testData/spring/core/references/completion/handler/scopeReference.kt.after b/idea/testData/spring/core/references/completion/handler/scopeReference.kt.after new file mode 100644 index 00000000000..e8b62870d1c --- /dev/null +++ b/idea/testData/spring/core/references/completion/handler/scopeReference.kt.after @@ -0,0 +1,7 @@ +// ELEMENT: singleton +package test + +import org.springframework.context.annotation.Scope + +@Scope("singleton") +class ScopedBean \ No newline at end of file diff --git a/idea/testData/spring/core/references/completion/handler/spring-config.xml b/idea/testData/spring/core/references/completion/handler/spring-config.xml new file mode 100644 index 00000000000..c3deaeb35c8 --- /dev/null +++ b/idea/testData/spring/core/references/completion/handler/spring-config.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/idea/testData/spring/core/references/completion/handler/springBeanReferenceEnter.kt b/idea/testData/spring/core/references/completion/handler/springBeanReferenceEnter.kt new file mode 100644 index 00000000000..8e60f0bd691 --- /dev/null +++ b/idea/testData/spring/core/references/completion/handler/springBeanReferenceEnter.kt @@ -0,0 +1,14 @@ +// ELEMENT: fooBean +// CHAR: \n +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.xml.XmlBeanFactory +import org.springframework.core.io.FileSystemResource +import org.springframework.core.io.Resource + +class FooBeanClass { + init { + val configFile = FileSystemResource("spring-config.xml") + val factory = XmlBeanFactory(configFile) + factory.getBean("foo") + } +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/completion/handler/springBeanReferenceEnter.kt.after b/idea/testData/spring/core/references/completion/handler/springBeanReferenceEnter.kt.after new file mode 100644 index 00000000000..f83d065dc0d --- /dev/null +++ b/idea/testData/spring/core/references/completion/handler/springBeanReferenceEnter.kt.after @@ -0,0 +1,14 @@ +// ELEMENT: fooBean +// CHAR: \n +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.xml.XmlBeanFactory +import org.springframework.core.io.FileSystemResource +import org.springframework.core.io.Resource + +class FooBeanClass { + init { + val configFile = FileSystemResource("spring-config.xml") + val factory = XmlBeanFactory(configFile) + factory.getBean("fooBeano") + } +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/completion/handler/springBeanReferenceTab.kt b/idea/testData/spring/core/references/completion/handler/springBeanReferenceTab.kt new file mode 100644 index 00000000000..d5c9415da75 --- /dev/null +++ b/idea/testData/spring/core/references/completion/handler/springBeanReferenceTab.kt @@ -0,0 +1,14 @@ +// ELEMENT: fooBean +// CHAR: \t +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.xml.XmlBeanFactory +import org.springframework.core.io.FileSystemResource +import org.springframework.core.io.Resource + +class FooBeanClass { + init { + val configFile = FileSystemResource("spring-config.xml") + val factory = XmlBeanFactory(configFile) + factory.getBean("foo") + } +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/completion/handler/springBeanReferenceTab.kt.after b/idea/testData/spring/core/references/completion/handler/springBeanReferenceTab.kt.after new file mode 100644 index 00000000000..90eafe886ec --- /dev/null +++ b/idea/testData/spring/core/references/completion/handler/springBeanReferenceTab.kt.after @@ -0,0 +1,14 @@ +// ELEMENT: fooBean +// CHAR: \t +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.xml.XmlBeanFactory +import org.springframework.core.io.FileSystemResource +import org.springframework.core.io.Resource + +class FooBeanClass { + init { + val configFile = FileSystemResource("spring-config.xml") + val factory = XmlBeanFactory(configFile) + factory.getBean("fooBean") + } +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/completion/variants/scopeReference.kt b/idea/testData/spring/core/references/completion/variants/scopeReference.kt new file mode 100644 index 00000000000..6a8e5d626f3 --- /dev/null +++ b/idea/testData/spring/core/references/completion/variants/scopeReference.kt @@ -0,0 +1,9 @@ +// NUMBER: 2 +// EXIST: { lookupString:"singleton" } +// EXIST: { lookupString:"prototype" } +package test + +import org.springframework.context.annotation.Scope + +@Scope("") +class ScopedBean \ No newline at end of file diff --git a/idea/testData/spring/core/references/completion/variants/spring-config.xml b/idea/testData/spring/core/references/completion/variants/spring-config.xml new file mode 100644 index 00000000000..b3fb31598a4 --- /dev/null +++ b/idea/testData/spring/core/references/completion/variants/spring-config.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/idea/testData/spring/core/references/completion/variants/springBeanReference.kt b/idea/testData/spring/core/references/completion/variants/springBeanReference.kt new file mode 100644 index 00000000000..eb587c52a04 --- /dev/null +++ b/idea/testData/spring/core/references/completion/variants/springBeanReference.kt @@ -0,0 +1,15 @@ +// NUMBER: 2 +// EXIST: { lookupString:"fooBean" } +// EXIST: { lookupString:"fooBean2" } +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.xml.XmlBeanFactory +import org.springframework.core.io.FileSystemResource +import org.springframework.core.io.Resource + +class FooBeanClass { + init { + val configFile = FileSystemResource("spring-config.xml") + val factory = XmlBeanFactory(configFile) + factory.getBean("foo") + } +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/fileReferenceInClasspathResource.kt b/idea/testData/spring/core/references/navigation/fileReferenceInClasspathResource.kt new file mode 100644 index 00000000000..5b7ed134fbf --- /dev/null +++ b/idea/testData/spring/core/references/navigation/fileReferenceInClasspathResource.kt @@ -0,0 +1,9 @@ +// NO_XML_CONFIG +// REF: /src.fileReferenceInClasspathResource.test.xml +import org.springframework.core.io.ClassPathResource + +class Bean { + init { + ClassPathResource("fileReferenceInClasspathResource.test.xml") + } +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/fileReferenceInClasspathResource.test.xml b/idea/testData/spring/core/references/navigation/fileReferenceInClasspathResource.test.xml new file mode 100644 index 00000000000..5f79f12a9aa --- /dev/null +++ b/idea/testData/spring/core/references/navigation/fileReferenceInClasspathResource.test.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/fileReferenceInClasspathXmlContext.kt b/idea/testData/spring/core/references/navigation/fileReferenceInClasspathXmlContext.kt new file mode 100644 index 00000000000..7fc2d302e59 --- /dev/null +++ b/idea/testData/spring/core/references/navigation/fileReferenceInClasspathXmlContext.kt @@ -0,0 +1,9 @@ +// NO_XML_CONFIG +// REF: /src.fileReferenceInClasspathXmlContext.test.xml +import org.springframework.context.support.ClassPathXmlApplicationContext + +class Bean { + init { + ClassPathXmlApplicationContext("fileReferenceInClasspathXmlContext.test.xml") + } +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/fileReferenceInClasspathXmlContext.test.xml b/idea/testData/spring/core/references/navigation/fileReferenceInClasspathXmlContext.test.xml new file mode 100644 index 00000000000..5f79f12a9aa --- /dev/null +++ b/idea/testData/spring/core/references/navigation/fileReferenceInClasspathXmlContext.test.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/scopeReference.kt b/idea/testData/spring/core/references/navigation/scopeReference.kt new file mode 100644 index 00000000000..34a710a0311 --- /dev/null +++ b/idea/testData/spring/core/references/navigation/scopeReference.kt @@ -0,0 +1,7 @@ +// REF: singleton +package test + +import org.springframework.context.annotation.Scope + +@Scope("singleton") +class Bean \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/scopeReference_config.xml b/idea/testData/spring/core/references/navigation/scopeReference_config.xml new file mode 100644 index 00000000000..aacac5ca9a6 --- /dev/null +++ b/idea/testData/spring/core/references/navigation/scopeReference_config.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/idea/testData/spring/core/references/navigation/springBeanRefInFactoryContainsBean.kt b/idea/testData/spring/core/references/navigation/springBeanRefInFactoryContainsBean.kt new file mode 100644 index 00000000000..6b5fa35e76f --- /dev/null +++ b/idea/testData/spring/core/references/navigation/springBeanRefInFactoryContainsBean.kt @@ -0,0 +1,13 @@ +// REF: +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.xml.XmlBeanFactory +import org.springframework.core.io.FileSystemResource +import org.springframework.core.io.Resource + +class FooBeanClass { + init { + val configFile = FileSystemResource("spring-config.xml") + val factory = XmlBeanFactory(configFile) + if (factory.containsBean("fooBean")) println("FooBean") + } +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/springBeanRefInFactoryContainsBean_config.xml b/idea/testData/spring/core/references/navigation/springBeanRefInFactoryContainsBean_config.xml new file mode 100644 index 00000000000..5d68c8ea557 --- /dev/null +++ b/idea/testData/spring/core/references/navigation/springBeanRefInFactoryContainsBean_config.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/idea/testData/spring/core/references/navigation/springBeanRefInFactoryGetBean.kt b/idea/testData/spring/core/references/navigation/springBeanRefInFactoryGetBean.kt new file mode 100644 index 00000000000..bf12f85b0bd --- /dev/null +++ b/idea/testData/spring/core/references/navigation/springBeanRefInFactoryGetBean.kt @@ -0,0 +1,13 @@ +// REF: +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.xml.XmlBeanFactory +import org.springframework.core.io.FileSystemResource +import org.springframework.core.io.Resource + +class FooBeanClass { + init { + val configFile = FileSystemResource("spring-config.xml") + val factory = XmlBeanFactory(configFile) + factory.getBean("fooBean") + } +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/springBeanRefInFactoryGetBean_config.xml b/idea/testData/spring/core/references/navigation/springBeanRefInFactoryGetBean_config.xml new file mode 100644 index 00000000000..8f56c744117 --- /dev/null +++ b/idea/testData/spring/core/references/navigation/springBeanRefInFactoryGetBean_config.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/springBeanRefInResource.kt b/idea/testData/spring/core/references/navigation/springBeanRefInResource.kt new file mode 100644 index 00000000000..4f79d7dbb6f --- /dev/null +++ b/idea/testData/spring/core/references/navigation/springBeanRefInResource.kt @@ -0,0 +1,11 @@ +// JAVAX_ANNOTATION_RESOURCE +// REF: +package test + +import javax.annotation.Resource + +class Bean + +class Test { + @Resource(name= "fooBean") lateinit var name: String +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/springBeanRefInResource_config.xml b/idea/testData/spring/core/references/navigation/springBeanRefInResource_config.xml new file mode 100644 index 00000000000..aacac5ca9a6 --- /dev/null +++ b/idea/testData/spring/core/references/navigation/springBeanRefInResource_config.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/idea/testData/spring/core/references/navigation/springFactoryBeanRefInResource.kt b/idea/testData/spring/core/references/navigation/springFactoryBeanRefInResource.kt new file mode 100644 index 00000000000..55dd5023aa0 --- /dev/null +++ b/idea/testData/spring/core/references/navigation/springFactoryBeanRefInResource.kt @@ -0,0 +1,11 @@ +// JAVAX_ANNOTATION_RESOURCE +// REF: +package test + +import javax.annotation.Resource + +class Bean + +class Test { + @Resource(name= "&fooBean") lateinit var name: String +} \ No newline at end of file diff --git a/idea/testData/spring/core/references/navigation/springFactoryBeanRefInResource_config.xml b/idea/testData/spring/core/references/navigation/springFactoryBeanRefInResource_config.xml new file mode 100644 index 00000000000..aacac5ca9a6 --- /dev/null +++ b/idea/testData/spring/core/references/navigation/springFactoryBeanRefInResource_config.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/idea/tests/org/jetbrains/kotlin/idea/actions/AbstractGotoTestOrCodeActionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/actions/AbstractGotoTestOrCodeActionTest.kt index 54fcfc6e165..f94af6db18a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/actions/AbstractGotoTestOrCodeActionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/actions/AbstractGotoTestOrCodeActionTest.kt @@ -17,55 +17,13 @@ package org.jetbrains.kotlin.idea.actions import com.intellij.openapi.editor.Editor -import com.intellij.openapi.util.io.FileUtil import com.intellij.psi.PsiFile -import com.intellij.testFramework.PlatformTestUtil import com.intellij.testIntegration.GotoTestOrCodeHandler -import org.jetbrains.kotlin.idea.navigation.NavigationTestUtils -import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil -import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase -import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import org.jetbrains.kotlin.test.InTextDirectivesUtils -import org.jetbrains.kotlin.test.KotlinTestUtils -import java.io.File -abstract class AbstractGotoTestOrCodeActionTest : KotlinLightCodeInsightFixtureTestCase() { +abstract class AbstractGotoTestOrCodeActionTest : AbstractNavigationTest() { private object Handler: GotoTestOrCodeHandler() { public override fun getSourceAndTargetElements(editor: Editor?, file: PsiFile?) = super.getSourceAndTargetElements(editor, file) } - override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - - protected fun doTest(path: String) { - val mainFile = File(path) - val fileText = FileUtil.loadFile(mainFile, true) - val addKotlinRuntime = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// WITH_RUNTIME") != null - - try { - if (addKotlinRuntime) { - ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()) - } - ConfigLibraryUtil.configureLibrariesByDirective(myModule, PlatformTestUtil.getCommunityPath(), fileText) - - myFixture.testDataPath = "${KotlinTestUtils.getHomeDirectory()}/${mainFile.parent}" - - val mainFileName = mainFile.name - val mainFileBaseName = mainFileName.substring(0, mainFileName.indexOf('.')) - mainFile.parentFile - .listFiles { file, name -> - name != mainFileName && name.startsWith("$mainFileBaseName.") && (name.endsWith(".kt") || name.endsWith(".java")) - } - .forEach{ myFixture.configureByFile(it.name) } - val file = myFixture.configureByFile(mainFileName) - - NavigationTestUtils.assertGotoDataMatching(editor, Handler.getSourceAndTargetElements(editor, file)) - } - finally { - ConfigLibraryUtil.unconfigureLibrariesByDirective(myModule, fileText) - if (addKotlinRuntime) { - ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()) - } - } - } + override fun getSourceAndTargetElements(editor: Editor, file: PsiFile) = Handler.getSourceAndTargetElements(editor, file) } diff --git a/idea/tests/org/jetbrains/kotlin/idea/actions/AbstractNavigationTest.kt b/idea/tests/org/jetbrains/kotlin/idea/actions/AbstractNavigationTest.kt new file mode 100644 index 00000000000..78ba636619c --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/actions/AbstractNavigationTest.kt @@ -0,0 +1,75 @@ +/* + * 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.actions + +import com.intellij.codeInsight.navigation.GotoTargetHandler +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.PsiFile +import com.intellij.testFramework.PlatformTestUtil +import org.jetbrains.kotlin.idea.navigation.NavigationTestUtils +import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase +import org.jetbrains.kotlin.test.InTextDirectivesUtils +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.io.File + +abstract class AbstractNavigationTest : KotlinLightCodeInsightFixtureTestCase() { + protected abstract fun getSourceAndTargetElements(editor: Editor, file: PsiFile): GotoTargetHandler.GotoData? + + override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE + + protected open fun configureExtra(mainFileBaseName: String, mainFileText: String) { + + } + + protected fun doTest(path: String) { + val mainFile = File(path) + val fileText = FileUtil.loadFile(mainFile, true) + val addKotlinRuntime = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// WITH_RUNTIME") != null + + try { + if (addKotlinRuntime) { + ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()) + } + ConfigLibraryUtil.configureLibrariesByDirective(myModule, PlatformTestUtil.getCommunityPath(), fileText) + + myFixture.testDataPath = "${KotlinTestUtils.getHomeDirectory()}/${mainFile.parent}" + + val mainFileName = mainFile.name + val mainFileBaseName = mainFileName.substring(0, mainFileName.indexOf('.')) + configureExtra(mainFileBaseName, fileText) + mainFile.parentFile + .listFiles { file, name -> + name != mainFileName && name.startsWith("$mainFileBaseName.") && (name.endsWith(".kt") || name.endsWith(".java") || name.endsWith(".xml")) + } + .forEach{ myFixture.configureByFile(it.name) } + val file = myFixture.configureByFile(mainFileName) + + NavigationTestUtils.assertGotoDataMatching(editor, getSourceAndTargetElements(editor, file)) + } + finally { + ConfigLibraryUtil.unconfigureLibrariesByDirective(myModule, fileText) + if (addKotlinRuntime) { + ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()) + } + } + } +} + diff --git a/idea/tests/org/jetbrains/kotlin/idea/navigation/NavigationTestUtils.java b/idea/tests/org/jetbrains/kotlin/idea/navigation/NavigationTestUtils.java index d0fe9d98e24..5b615d4d004 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/navigation/NavigationTestUtils.java +++ b/idea/tests/org/jetbrains/kotlin/idea/navigation/NavigationTestUtils.java @@ -53,7 +53,9 @@ public final class NavigationTestUtils { // Get expected references from the tested document List expectedReferences = InTextDirectivesUtils.findListWithPrefixes(editor.getDocument().getText(), "// REF:"); for (int i = 0; i < expectedReferences.size(); i++) { - expectedReferences.set(i, PathUtil.toSystemDependentName(expectedReferences.get(i)).replace("//", "/")); + String expectedText = expectedReferences.get(i); + if (expectedText.startsWith("<")) continue; + expectedReferences.set(i, PathUtil.toSystemDependentName(expectedText).replace("//", "/")); } Collections.sort(expectedReferences); diff --git a/idea/tests/org/jetbrains/kotlin/test/ReferenceUtils.java b/idea/tests/org/jetbrains/kotlin/test/ReferenceUtils.java index 2897119d3c8..205f6418e7b 100644 --- a/idea/tests/org/jetbrains/kotlin/test/ReferenceUtils.java +++ b/idea/tests/org/jetbrains/kotlin/test/ReferenceUtils.java @@ -25,6 +25,8 @@ import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.psi.KtClass; import org.jetbrains.kotlin.psi.KtObjectDeclaration; +import org.jetbrains.kotlin.psi.KtStringTemplateExpression; +import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt; import org.junit.Assert; public final class ReferenceUtils { @@ -41,11 +43,16 @@ public final class ReferenceUtils { return "companion object of " + renderAsGotoImplementation(containingClass); } + if (navigationElement instanceof KtStringTemplateExpression) { + return KtPsiUtilKt.getPlainContent((KtStringTemplateExpression) navigationElement); + } + Assert.assertTrue(navigationElement instanceof NavigationItem); ItemPresentation presentation = ((NavigationItem) navigationElement).getPresentation(); if (presentation == null) { - return element.getText(); + String elementText = element.getText(); + return elementText != null ? elementText : navigationElement.getText(); } String presentableText = presentation.getPresentableText();