Spring Support: Implement Spring-specific references

This commit is contained in:
Alexey Sedunov
2016-02-25 13:02:43 +03:00
parent 72a17b0671
commit 0a71eb777e
45 changed files with 906 additions and 80 deletions
+1
View File
@@ -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:
@@ -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
@@ -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<String>) {
testClass<AbstractQuickFixTest>("UltimateQuickFixTestGenerated") {
model("ultimateQuickFixes", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true)
}
testClass<AbstractSpringReferenceCompletionHandlerTest>() {
model("spring/core/references/completion/handler")
}
testClass<AbstractSpringReferenceCompletionTest>() {
model("spring/core/references/completion/variants")
}
testClass<AbstractSpringReferenceNavigationTest>() {
model("spring/core/references/navigation")
}
}
testGroup("idea/tests", "compiler/testData") {
@@ -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 <reified E : KtElement> PsiReferenceRegistrar.registerProvider(
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY,
crossinline factory: (E) -> PsiReference?
) {
registerMultiProvider<E>(priority) { factory(it)?.let { arrayOf(it) } ?: PsiReference.EMPTY_ARRAY }
}
protected inline fun <reified E : KtElement> PsiReferenceRegistrar.registerMultiProvider(
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY,
crossinline factory: (E) -> Array<PsiReference>
) {
registerMultiProvider(PlatformPatterns.psiElement(E::class.java), priority, factory)
}
protected inline fun <E : KtElement> PsiReferenceRegistrar.registerMultiProvider(
pattern: ElementPattern<E>,
priority: Double = PsiReferenceRegistrar.DEFAULT_PRIORITY,
crossinline factory: (E) -> Array<PsiReference>
) {
registerReferenceProvider(
pattern,
object : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
@Suppress("UNCHECKED_CAST")
return factory(element as E)
}
},
priority
)
}
}
@@ -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<KtSimpleNameExpression> {
KtSimpleNameReference(it)
}
registerMultiProvider(KtNameReferenceExpression::class.java) {
registerMultiProvider<KtNameReferenceExpression> {
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<KtConstructorDelegationReferenceExpression> {
KtConstructorDelegationReference(it)
}
registerProvider(KtCallExpression::class.java) {
registerProvider<KtCallExpression> {
KtInvokeFunctionReference(it)
}
registerProvider(KtArrayAccessExpression::class.java) {
registerProvider<KtArrayAccessExpression> {
KtArrayAccessReference(it)
}
registerProvider(KtForExpression::class.java) {
registerProvider<KtForExpression> {
KtForLoopInReference(it)
}
registerProvider(KtPropertyDelegate::class.java) {
registerProvider<KtPropertyDelegate> {
KtPropertyDelegationMethodsReference(it)
}
registerProvider(KtDestructuringDeclaration::class.java) {
registerProvider<KtDestructuringDeclaration> {
KtDestructuringDeclarationReference(it)
}
registerProvider(KDocName::class.java) {
registerProvider<KDocName> {
KDocReference(it)
}
}
}
private fun <E : KtElement> PsiReferenceRegistrar.registerProvider(elementClass: Class<E>, factory: (E) -> KtReference) {
registerMultiProvider(elementClass, { arrayOf(factory(it)) })
}
private fun <E : KtElement> PsiReferenceRegistrar.registerMultiProvider(elementClass: Class<E>, factory: (E) -> Array<PsiReference>) {
registerReferenceProvider(PlatformPatterns.psiElement(elementClass), object: PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
@Suppress("UNCHECKED_CAST")
return factory(element as E)
}
})
}
}
@@ -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() {
}
}
@@ -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
}
@@ -1,5 +1,7 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<psi.referenceContributor language="kotlin" implementation="org.jetbrains.kotlin.idea.spring.references.KotlinSpringReferenceContributor"/>
<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,129 @@
/*
* 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.openapi.util.TextRange
import com.intellij.psi.PsiReference
import com.intellij.psi.PsiReferenceRegistrar
import com.intellij.spring.constants.SpringAnnotationsConstants
import com.intellij.spring.constants.SpringConstants
import com.intellij.spring.model.utils.resources.SpringResourcesBuilder
import com.intellij.spring.model.utils.resources.SpringResourcesUtil
import com.intellij.spring.references.SpringBeanNamesReferenceProvider
import com.intellij.spring.references.SpringBeanReference
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.references.AbstractKotlinReferenceContributor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getContentRange
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isPlain
import org.jetbrains.kotlin.psi.psiUtil.plainContent
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeAsSequence
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.source.getPsi
class KotlinSpringReferenceContributor : AbstractKotlinReferenceContributor() {
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
registrar.registerProvider<KtStringTemplateExpression> {
if (!it.isPlain()) return@registerProvider null
val callExpression = (it.parent as? KtValueArgument)?.getStrictParentOfType<KtCallExpression>() ?: 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<KtStringTemplateExpression>(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<KtAnnotationEntry>() ?: 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<KtAnnotationEntry>()?.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<KtStringTemplateExpression>(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<KtAnnotationEntry>() ?: 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<KtStringTemplateExpression> {
if (!it.isPlain()) return@registerMultiProvider PsiReference.EMPTY_ARRAY
val callExpression = (it.parent as? KtValueArgument)?.getStrictParentOfType<KtCallExpression>()
?: 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)
}
}
}
@@ -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<KtStringTemplateExpression>(element, ElementManipulators.getManipulator(element).getRangeInElement(element)) {
private fun getScopes(): Sequence<SpringBeanScope> {
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()
}
@@ -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<SpringTestFixtureExtension>(myModule)
.configureFileSet(myFixture, listOf(PathUtil.toSystemIndependentName(File(testPath).parent + "/spring-config.xml")))
}
override fun tearDownFixture() {
TestFixtureExtension.unloadFixture<SpringTestFixtureExtension>()
super.tearDownFixture()
}
}
@@ -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<SpringTestFixtureExtension>(myModule)!!
.configureFileSet(myFixture, listOf(PathUtil.toSystemIndependentName(File(testPath).parent + "/spring-config.xml")))
}
override fun tearDownFixture() {
TestFixtureExtension.unloadFixture<SpringTestFixtureExtension>()
super.tearDownFixture()
}
}
@@ -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<KtStringTemplateExpression>()!!
return GotoTargetHandler.GotoData(stringTemplate,
stringTemplate.references.mapNotNull { it.resolve() }.toTypedArray(),
emptyList())
}
override fun setUp() {
super.setUp()
TestFixtureExtension.loadFixture<SpringTestFixtureExtension>(myModule)!!
}
override fun configureExtra(mainFileBaseName: String, mainFileText: String) {
if (!InTextDirectivesUtils.isDirectiveDefined(mainFileText, "// NO_XML_CONFIG")) {
TestFixtureExtension
.getFixture<SpringTestFixtureExtension>()!!
.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<SpringTestFixtureExtension>()
super.tearDown()
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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),
@@ -0,0 +1,7 @@
// ELEMENT: singleton
package test
import org.springframework.context.annotation.Scope
@Scope("<caret>")
class ScopedBean
@@ -0,0 +1,7 @@
// ELEMENT: singleton
package test
import org.springframework.context.annotation.Scope
@Scope("singleton")
class ScopedBean
@@ -0,0 +1,7 @@
<?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="fooBean" class="java.lang.String"/>
<bean id="barBean" class="java.lang.String"/>
<bean id="scopedBean" class="test.ScopedBean"/>
</beans>
@@ -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("fo<caret>o")
}
}
@@ -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")
}
}
@@ -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("fo<caret>o")
}
}
@@ -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")
}
}
@@ -0,0 +1,9 @@
// NUMBER: 2
// EXIST: { lookupString:"singleton" }
// EXIST: { lookupString:"prototype" }
package test
import org.springframework.context.annotation.Scope
@Scope("<caret>")
class ScopedBean
@@ -0,0 +1,8 @@
<?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="fooBean" class="java.lang.String"/>
<bean id="fooBean2" class="java.lang.String"/>
<bean id="barBean" class="java.lang.String"/>
<bean id="scopedBean" class="test.ScopedBean"/>
</beans>
@@ -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("fo<caret>o")
}
}
@@ -0,0 +1,9 @@
// NO_XML_CONFIG
// REF: /src.fileReferenceInClasspathResource.test.xml
import org.springframework.core.io.ClassPathResource
class Bean {
init {
ClassPathResource("<caret>fileReferenceInClasspathResource.test.xml")
}
}
@@ -0,0 +1,3 @@
<test>
<foo/>
</test>
@@ -0,0 +1,9 @@
// NO_XML_CONFIG
// REF: /src.fileReferenceInClasspathXmlContext.test.xml
import org.springframework.context.support.ClassPathXmlApplicationContext
class Bean {
init {
ClassPathXmlApplicationContext("<caret>fileReferenceInClasspathXmlContext.test.xml")
}
}
@@ -0,0 +1,3 @@
<test>
<foo/>
</test>
@@ -0,0 +1,7 @@
// REF: singleton
package test
import org.springframework.context.annotation.Scope
@Scope("<caret>singleton")
class Bean
@@ -0,0 +1,5 @@
<?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="fooBean" class="test.Bean"/>
</beans>
@@ -0,0 +1,13 @@
// REF: <bean id="fooBean" class="java.lang.String"/>
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("<caret>fooBean")) println("FooBean")
}
}
@@ -0,0 +1,5 @@
<?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="fooBean" class="java.lang.String"/>
</beans>
@@ -0,0 +1,13 @@
// REF: <bean id="fooBean" class="java.lang.String"/>
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("<caret>fooBean")
}
}
@@ -0,0 +1,5 @@
<?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="fooBean" class="java.lang.String"/>
</beans>
@@ -0,0 +1,11 @@
// JAVAX_ANNOTATION_RESOURCE
// REF: <bean id="fooBean" class="test.Bean"/>
package test
import javax.annotation.Resource
class Bean
class Test {
@Resource(name= "<caret>fooBean") lateinit var name: String
}
@@ -0,0 +1,5 @@
<?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="fooBean" class="test.Bean"/>
</beans>
@@ -0,0 +1,11 @@
// JAVAX_ANNOTATION_RESOURCE
// REF: <bean id="fooBean" class="test.Bean"/>
package test
import javax.annotation.Resource
class Bean
class Test {
@Resource(name= "<caret>&fooBean") lateinit var name: String
}
@@ -0,0 +1,5 @@
<?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="fooBean" class="test.Bean"/>
</beans>
@@ -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)
}
@@ -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())
}
}
}
}
@@ -53,7 +53,9 @@ public final class NavigationTestUtils {
// Get expected references from the tested document
List<String> 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);
@@ -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();