Fix broken isReferenceTo checking code for Android extensions
#KT-16132 Fixed
This commit is contained in:
+2
-6
@@ -72,12 +72,8 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
|
||||
}
|
||||
|
||||
override fun isReferenceTo(element: PsiElement?): Boolean {
|
||||
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
|
||||
}
|
||||
if (element != null && !canBeReferenceTo(element)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return super.isReferenceTo(element)
|
||||
|
||||
-1
@@ -27,6 +27,5 @@ interface SimpleNameReferenceExtension {
|
||||
ExtensionPointName.create("org.jetbrains.kotlin.simpleNameReferenceExtension")
|
||||
}
|
||||
|
||||
fun isReferenceTo(reference: KtSimpleNameReference, element: PsiElement): Boolean
|
||||
fun handleElementRename(reference: KtSimpleNameReference, psiFactory: KtPsiFactory, newElementName: String): PsiElement?
|
||||
}
|
||||
+1
-6
@@ -25,16 +25,11 @@ 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) = when {
|
||||
element is ValueResourceElementWrapper && AndroidResourceUtil.isIdDeclaration(element) -> true
|
||||
isLayoutPackageIdentifier(reference) -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun isLayoutPackageIdentifier(reference: KtSimpleNameReference): Boolean {
|
||||
val probablyVariant = reference.element?.parent as? KtDotQualifiedExpression ?: return false
|
||||
val probablyKAS = probablyVariant.receiverExpression as? KtDotQualifiedExpression ?: return false
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
// KT-16132 Renaming property provided by kotlinx leads to renaming another members
|
||||
|
||||
object Loginer {
|
||||
fun login() { }
|
||||
}
|
||||
|
||||
public class MyActivity : Activity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
<caret>login.setOnClickListener {
|
||||
Loginer.login()
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
// KT-16132 Renaming property provided by kotlinx leads to renaming another members
|
||||
|
||||
object Loginer {
|
||||
fun login() { }
|
||||
}
|
||||
|
||||
public class MyActivity : Activity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
NEWNAME.setOnClickListener {
|
||||
Loginer.login()
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_detail_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_detail_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/login"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.NEWNAME
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
<view
|
||||
class="org.my.cool.Button"
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.NEWNAME
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
<view
|
||||
class="org.my.cool.Button"
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.NEWNAME
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
<org.my.cool.Button
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.NEWNAME
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
<org.my.cool.Button
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.NEWNAME
|
||||
val button1 = this.loginButton
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_detail_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Enter your password" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="textPassword" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/frameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/passwordField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Enter your password" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/passwordCaption"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="textPassword" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/loginButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.NEWNAME
|
||||
val button1 = this.loginButton
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_detail_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Enter your password" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="textPassword" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/frameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/passwordField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Enter your password" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/passwordCaption"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="textPassword" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/loginButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_detail_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
plugins/android-extensions/android-extensions-idea/testData/android/rename/simple/expected/simple.kt
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
public class MyActivity : Activity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {}
|
||||
val button = NEWNAME
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_detail_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
public class MyFragment : Fragment() {
|
||||
override fun onResume() {}
|
||||
val button = NEWNAME
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_detail_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ItemDetailActivity"
|
||||
tools:ignore="MergeRootFrame" >
|
||||
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/NEWNAME"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sign in" />
|
||||
|
||||
</FrameLayout>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.myapp
|
||||
|
||||
import android.view.View
|
||||
import kotlinx.android.synthetic.main.layout.view.*
|
||||
|
||||
fun View.a() {
|
||||
val button = NEWNAME
|
||||
}
|
||||
|
||||
+13
-14
@@ -17,9 +17,11 @@
|
||||
package org.jetbrains.kotlin.android
|
||||
|
||||
import com.intellij.codeInsight.TargetElementUtil
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
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.testFramework.PlatformTestUtil
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
|
||||
abstract class AbstractAndroidRenameTest : KotlinAndroidTestCase() {
|
||||
@@ -27,22 +29,19 @@ abstract class AbstractAndroidRenameTest : KotlinAndroidTestCase() {
|
||||
private val NEW_ID_NAME = "@+id/$NEW_NAME"
|
||||
|
||||
fun doTest(path: String) {
|
||||
val f = myFixture!!
|
||||
getResourceDirs(path).forEach { myFixture.copyDirectoryToProject(it.name, it.name) }
|
||||
val virtualFile = f.copyFileToProject(path + getTestName(true) + ".kt", "src/" + getTestName(true) + ".kt")
|
||||
f.configureFromExistingVirtualFile(virtualFile)
|
||||
|
||||
val completionEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(f.editor, f.file)
|
||||
|
||||
val element = TargetElementUtil.findTargetElement(
|
||||
completionEditor,
|
||||
TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED or TargetElementUtil.ELEMENT_NAME_ACCEPTED) as XmlAttributeValueImpl
|
||||
|
||||
RenameProcessor(f.project, element, NEW_ID_NAME, false, true).run()
|
||||
|
||||
val expression = TargetElementUtil.findReference(f.editor, f.caretOffset)!!.element as KtNameReferenceExpression
|
||||
assertEquals(NEW_NAME, expression.getReferencedName())
|
||||
val virtualFile = myFixture.copyFileToProject("$path${getTestName(true)}.kt", "src/${getTestName(true)}.kt")
|
||||
myFixture.configureFromExistingVirtualFile(virtualFile)
|
||||
myFixture.renameElement(myFixture.elementAtCaret, NEW_ID_NAME)
|
||||
myFixture.checkResultByFile("expected/${getTestName(true)}.kt")
|
||||
assertResourcesEqual("$path/expected/res")
|
||||
}
|
||||
|
||||
fun assertResourcesEqual(expectedPath: String) {
|
||||
PlatformTestUtil.assertDirectoriesEqual(LocalFileSystem.getInstance().findFileByPath(expectedPath), getResourceDirectory())
|
||||
}
|
||||
|
||||
fun getResourceDirectory() = LocalFileSystem.getInstance().findFileByPath(myFixture.tempDirPath + "/res")
|
||||
|
||||
override fun getTestDataPath() = KotlinAndroidTestCaseBase.getPluginTestDataPathBase() + "/rename/" + getTestName(true) + "/"
|
||||
}
|
||||
|
||||
+6
@@ -36,6 +36,12 @@ public class AndroidRenameTestGenerated extends AbstractAndroidRenameTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/android-extensions/android-extensions-idea/testData/android/rename"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, false);
|
||||
}
|
||||
|
||||
@TestMetadata("commonElementId")
|
||||
public void testCommonElementId() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/rename/commonElementId/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("fqNameInAttr")
|
||||
public void testFqNameInAttr() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/rename/fqNameInAttr/");
|
||||
|
||||
Reference in New Issue
Block a user