Fix WrongIdFormat exception on Android XML widgets with non-@+id/ format

This commit is contained in:
Yan Zhulanow
2015-03-10 22:01:03 +03:00
parent 07381b765f
commit be954f2c27
7 changed files with 51 additions and 7 deletions
@@ -32,14 +32,12 @@ public object AndroidConst {
val ID_USAGE_PREFIX = "@id/" val ID_USAGE_PREFIX = "@id/"
} }
class WrongIdFormat(id: String) : Exception("Id \"$id\" has wrong format")
public fun nameToIdDeclaration(name: String): String = AndroidConst.ID_DECLARATION_PREFIX + name public fun nameToIdDeclaration(name: String): String = AndroidConst.ID_DECLARATION_PREFIX + name
public fun idToName(id: String): String { public fun idToName(id: String): String? {
return if (isResourceIdDeclaration(id)) id.replace(AndroidConst.ID_DECLARATION_PREFIX, "") return if (isResourceIdDeclaration(id)) id.replace(AndroidConst.ID_DECLARATION_PREFIX, "")
else if (isResourceIdUsage(id)) id.replace(AndroidConst.ID_USAGE_PREFIX, "") else if (isResourceIdUsage(id)) id.replace(AndroidConst.ID_USAGE_PREFIX, "")
else throw WrongIdFormat(id) else null
} }
public fun isResourceIdDeclaration(str: String?): Boolean = str?.startsWith(AndroidConst.ID_DECLARATION_PREFIX) ?: false public fun isResourceIdDeclaration(str: String?): Boolean = str?.startsWith(AndroidConst.ID_DECLARATION_PREFIX) ?: false
@@ -37,7 +37,10 @@ class AndroidXmlHandler(
val attributesMap = attributes.toMap() val attributesMap = attributes.toMap()
val idAttr = attributesMap[AndroidConst.ID_ATTRIBUTE_NO_NAMESPACE] val idAttr = attributesMap[AndroidConst.ID_ATTRIBUTE_NO_NAMESPACE]
val classNameAttr = attributesMap[AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE] ?: localName val classNameAttr = attributesMap[AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE] ?: localName
if (isResourceDeclarationOrUsage(idAttr)) elementCallback(idToName(idAttr), classNameAttr) if (isResourceDeclarationOrUsage(idAttr)) {
val name = idToName(idAttr)
if (name != null) elementCallback(name, classNameAttr)
}
} }
override fun endElement(uri: String?, localName: String, qName: String) { override fun endElement(uri: String?, localName: String, qName: String) {
@@ -129,7 +129,9 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
if (element == null) return if (element == null) return
val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue()) val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue())
val newPropName = idToName(newName) val newPropName = idToName(newName)
renameSyntheticProperties(allRenames, newPropName, oldPropName, processor) if (oldPropName != null && newPropName != null) {
renameSyntheticProperties(allRenames, newPropName, oldPropName, processor)
}
} }
private fun renameSyntheticProperties( private fun renameSyntheticProperties(
@@ -45,7 +45,8 @@ class AndroidXmlVisitor(
val attributeValue = attribute.getValue() val attributeValue = attribute.getValue()
if (attributeValue != null) { if (attributeValue != null) {
val classNameAttr = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.getValue() ?: tag?.getLocalName() val classNameAttr = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.getValue() ?: tag?.getLocalName()
elementCallback(idToName(attributeValue), classNameAttr!!, attribute) val name = idToName(attributeValue)
if (name != null) elementCallback(name, classNameAttr!!, attribute)
} }
} }
tag?.acceptChildren(this) tag?.acceptChildren(this)
@@ -0,0 +1,20 @@
<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="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Sign in" />
</FrameLayout>
@@ -0,0 +1,14 @@
package com.myapp
import android.app.Activity
import android.os.Bundle
import java.io.File
import kotlinx.android.synthetic.layout.*
public class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {}
val button = login<caret>
fun f() = login.toString()
}
@@ -59,4 +59,10 @@ public class AndroidFindUsagesTestGenerated extends AbstractAndroidFindUsagesTes
String fileName = JetTestUtils.navigationMetadata("plugins/android-idea-plugin/testData/android/findUsages/simple/"); String fileName = JetTestUtils.navigationMetadata("plugins/android-idea-plugin/testData/android/findUsages/simple/");
doTest(fileName); doTest(fileName);
} }
@TestMetadata("wrongIdFormat")
public void testWrongIdFormat() throws Exception {
String fileName = JetTestUtils.navigationMetadata("plugins/android-idea-plugin/testData/android/findUsages/wrongIdFormat/");
doTest(fileName);
}
} }