diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidConst.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidConst.kt index 01d38440e40..6abedf73d55 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidConst.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidConst.kt @@ -47,3 +47,8 @@ public fun isResourceIdDeclaration(str: String?): Boolean = str?.startsWith(Andr public fun isResourceIdUsage(str: String?): Boolean = str?.startsWith(AndroidConst.ID_USAGE_PREFIX) ?: false public fun isResourceDeclarationOrUsage(id: String?): Boolean = isResourceIdDeclaration(id) || isResourceIdUsage(id) + +public fun getRealWidgetType(xmlType: String): String = when (xmlType) { + "fragment", "include", "merge" -> "View" + else -> xmlType +} \ No newline at end of file diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidXmlHandler.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidXmlHandler.kt index ddb74151bf6..8e6ab406e4b 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidXmlHandler.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidXmlHandler.kt @@ -32,11 +32,11 @@ class AndroidXmlHandler(private val elementCallback: (String, String) -> Unit) : override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) { val attributesMap = attributes.toMap() - val idAttr = attributesMap[AndroidConst.ID_ATTRIBUTE_NO_NAMESPACE] - val classNameAttr = attributesMap[AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE] ?: localName - if (isResourceDeclarationOrUsage(idAttr)) { - val name = idToName(idAttr) - if (name != null) elementCallback(name, classNameAttr) + val idAttribute = attributesMap[AndroidConst.ID_ATTRIBUTE_NO_NAMESPACE] + val widgetType = getRealWidgetType(attributesMap[AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE] ?: localName) + if (isResourceDeclarationOrUsage(idAttribute)) { + val name = idToName(idAttribute) + if (name != null) elementCallback(name, widgetType) } } diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/AndroidManifest.xml b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/AndroidManifest.xml new file mode 100644 index 00000000000..580c474f5de --- /dev/null +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/layout.kt b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/layout.kt new file mode 100644 index 00000000000..50662a47f3c --- /dev/null +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/layout.kt @@ -0,0 +1,26 @@ +package kotlinx.android.synthetic.layout + +import android.app.Activity +import android.app.Fragment +import android.view.View +import android.widget.* +import kotlin.internal.flexible.ft + +val Activity.includeTag: ft + get() = findViewById(0) as View + +val Fragment.includeTag: ft + get() = getView().findViewById(0) as View + +val Activity.mergeTag: ft + get() = findViewById(0) as View + +val Fragment.mergeTag: ft + get() = getView().findViewById(0) as View + +val Activity.fragmentTag: ft + get() = findViewById(0) as View + +val Fragment.fragmentTag: ft + get() = getView().findViewById(0) as View + diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/layout1.kt b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/layout1.kt new file mode 100644 index 00000000000..d58b635d302 --- /dev/null +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/layout1.kt @@ -0,0 +1,17 @@ +package kotlinx.android.synthetic.layout.view + +import android.app.Activity +import android.app.Fragment +import android.view.View +import android.widget.* +import kotlin.internal.flexible.ft + +val View.includeTag: ft + get() = findViewById(0) as View + +val View.mergeTag: ft + get() = findViewById(0) as View + +val View.fragmentTag: ft + get() = findViewById(0) as View + diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/res/layout/layout.xml b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/res/layout/layout.xml new file mode 100644 index 00000000000..0198b69b328 --- /dev/null +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/res/layout/layout.xml @@ -0,0 +1,19 @@ + + + + + + + + + \ No newline at end of file diff --git a/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/AndroidXml2KConversionTestGenerated.java b/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/AndroidXml2KConversionTestGenerated.java index 03e6a19eb56..d2a657c4017 100644 --- a/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/AndroidXml2KConversionTestGenerated.java +++ b/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/AndroidXml2KConversionTestGenerated.java @@ -71,6 +71,12 @@ public class AndroidXml2KConversionTestGenerated extends AbstractAndroidXml2KCon String fileName = JetTestUtils.navigationMetadata("plugins/android-compiler-plugin/testData/android/converter/simple/singleFile/"); doTest(fileName); } + + @TestMetadata("specialTags") + public void testSpecialTags() throws Exception { + String fileName = JetTestUtils.navigationMetadata("plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/"); + doTest(fileName); + } } @TestMetadata("plugins/android-compiler-plugin/testData/android/converter/exceptions") diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidXmlVisitor.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidXmlVisitor.kt index 36e6fb73762..e262e0bcca6 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidXmlVisitor.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidXmlVisitor.kt @@ -16,15 +16,13 @@ package org.jetbrains.kotlin.plugin.android -import org.jetbrains.kotlin.lang.resolve.android.AndroidResourceManager import com.intellij.psi.xml.XmlAttribute import com.intellij.psi.XmlElementVisitor import com.intellij.psi.PsiElement import com.intellij.psi.xml.XmlElement import com.intellij.psi.xml.XmlTag -import org.jetbrains.kotlin.lang.resolve.android.AndroidConst import org.jetbrains.kotlin.lang.resolve.android -import org.jetbrains.kotlin.lang.resolve.android.idToName +import org.jetbrains.kotlin.lang.resolve.android.* class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> Unit) : XmlElementVisitor() { @@ -37,14 +35,16 @@ class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> U } override fun visitXmlTag(tag: XmlTag?) { - val attribute = tag?.getAttribute(AndroidConst.ID_ATTRIBUTE) - if (attribute != null) { - val attributeValue = attribute.getValue() - if (attributeValue != null) { - val classNameAttr = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.getValue() ?: tag?.getLocalName() - if (classNameAttr != null) { - val name = idToName(attributeValue) - if (name != null) elementCallback(name, classNameAttr!!, attribute) + val idAttribute = tag?.getAttribute(AndroidConst.ID_ATTRIBUTE) + if (idAttribute != null) { + val idAttributeValue = idAttribute.getValue() + if (idAttributeValue != null) { + val classAttributeValue = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.getValue() + val xmlType = classAttributeValue ?: tag?.getLocalName() + val widgetType = xmlType?.let { getRealWidgetType(it) } + if (widgetType != null && isResourceDeclarationOrUsage(idAttributeValue)) { + val name = idToName(idAttributeValue) + if (name != null) elementCallback(name, widgetType, idAttribute) } } }