diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt index 4353f9f790f..19f9e79f8d7 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt @@ -79,8 +79,12 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere } override fun isReferenceTo(element: PsiElement?): Boolean { - if (element != null && !canBeReferenceTo(element)) { - return false + if (element != null) { + if (!canBeReferenceTo(element)) return false + + for (extension in Extensions.getArea(element.project).getExtensionPoint(SimpleNameReferenceExtension.EP_NAME).extensions) { + if (extension.isReferenceTo(this, element)) return true + } } return super.isReferenceTo(element) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt index 5084cd1f44b..a45daa1d86f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt @@ -27,5 +27,7 @@ interface SimpleNameReferenceExtension { ExtensionPointName.create("org.jetbrains.kotlin.simpleNameReferenceExtension") } + fun isReferenceTo(reference: KtSimpleNameReference, element: PsiElement): Boolean + fun handleElementRename(reference: KtSimpleNameReference, psiFactory: KtPsiFactory, newElementName: String): PsiElement? } \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt index 2522b06bbfa..c5e89df0354 100644 --- a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt @@ -18,18 +18,21 @@ package org.jetbrains.kotlin.android.synthetic.idea import com.intellij.psi.PsiElement import com.intellij.psi.xml.XmlAttributeValue -import org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper +import com.intellij.psi.xml.XmlFile +import org.jetbrains.android.facet.AndroidFacet import org.jetbrains.android.util.AndroidResourceUtil import org.jetbrains.kotlin.android.synthetic.AndroidConst import org.jetbrains.kotlin.android.synthetic.androidIdToName import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.plugin.references.SimpleNameReferenceExtension import org.jetbrains.kotlin.psi.KtDotQualifiedExpression -import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtPsiFactory class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension { + override fun isReferenceTo(reference: KtSimpleNameReference, element: PsiElement): Boolean = + element is XmlFile && reference.isReferenceToXmlFile(element) + private fun isLayoutPackageIdentifier(reference: KtSimpleNameReference): Boolean { val probablyVariant = reference.element?.parent as? KtDotQualifiedExpression ?: return false val probablyKAS = probablyVariant.receiverExpression as? KtDotQualifiedExpression ?: return false @@ -43,9 +46,29 @@ class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension { return psiFactory.createNameIdentifier(newSyntheticPropertyName.name) } else if (isLayoutPackageIdentifier(reference)) { - return psiFactory.createSimpleName(newElementName.substringBeforeLast(".xml")).getIdentifier() + return psiFactory.createSimpleName(newElementName.removeSuffix(".xml")).getIdentifier() } return null } + + private fun KtSimpleNameReference.isReferenceToXmlFile(xmlFile: XmlFile): Boolean { + if (!isLayoutPackageIdentifier(this)) { + return false + } + + if (xmlFile.name.removeSuffix(".xml") != element.getReferencedName()) { + return false + } + + val virtualFile = xmlFile.virtualFile ?: return false + val layoutDir = virtualFile.parent + if (layoutDir.name != "layout" && !layoutDir.name.startsWith("layout-")) { + return false + } + + val resourceDirectories = AndroidFacet.getInstance(element)?.allResourceDirectories ?: return false + val resourceDirectory = virtualFile.parent?.parent ?: return false + return resourceDirectories.any { it == resourceDirectory } + } } \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/tests/org/jetbrains/kotlin/android/AbstractAndroidLayoutRenameTest.kt b/plugins/android-extensions/android-extensions-idea/tests/org/jetbrains/kotlin/android/AbstractAndroidLayoutRenameTest.kt index 503c19611ea..5f2ffa2bf7d 100644 --- a/plugins/android-extensions/android-extensions-idea/tests/org/jetbrains/kotlin/android/AbstractAndroidLayoutRenameTest.kt +++ b/plugins/android-extensions/android-extensions-idea/tests/org/jetbrains/kotlin/android/AbstractAndroidLayoutRenameTest.kt @@ -16,10 +16,6 @@ package org.jetbrains.kotlin.android -import com.intellij.codeInsight.TargetElementUtil -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil -import com.intellij.refactoring.rename.RenameProcessor -import com.intellij.psi.impl.source.xml.XmlAttributeValueImpl import com.intellij.psi.xml.XmlFile import org.jetbrains.kotlin.android.synthetic.AndroidConst import org.jetbrains.kotlin.psi.KtFile @@ -32,17 +28,11 @@ abstract class AbstractAndroidLayoutRenameTest : KotlinAndroidTestCase() { copyResourceDirectoryForTest(path) val virtualFile = myFixture.copyFileToProject(path + getTestName(true) + ".kt", "src/" + getTestName(true) + ".kt") myFixture.configureFromExistingVirtualFile(virtualFile) + val xmlFile = myFixture.elementAtCaret.containingFile as XmlFile - val completionEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myFixture.editor, myFixture.file) + myFixture.renameElement(xmlFile, NEW_NAME_XML) - val element = TargetElementUtil.findTargetElement( - completionEditor, - TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED or TargetElementUtil.ELEMENT_NAME_ACCEPTED) as XmlAttributeValueImpl - - val file = element.containingFile as XmlFile - - RenameProcessor(myFixture.project, file, NEW_NAME_XML, false, true).run() - - (myFixture.file as KtFile).importDirectives.any { it.importedFqName!!.asString() == AndroidConst.SYNTHETIC_PACKAGE + ".main." + NEW_NAME } + val expectedImportName = AndroidConst.SYNTHETIC_PACKAGE + ".main." + NEW_NAME + assertTrue((myFixture.file as KtFile).importDirectives.any { it.importedFqName?.asString() == expectedImportName }) } }