Lookup XML attribute using the property (for a particular layout)
This commit is contained in:
+2
-1
@@ -21,7 +21,8 @@ import com.intellij.openapi.util.Key
|
||||
public object AndroidConst {
|
||||
val ANDROID_USER_PACKAGE: Key<String> = Key.create<String>("ANDROID_USER_PACKAGE")
|
||||
val SYNTHETIC_FILENAME: String = "ANDROIDXML"
|
||||
val SYNTHETIC_PACKAGE: String = "kotlinx.android.synthetic."
|
||||
val SYNTHETIC_PACKAGE: String = "kotlinx.android.synthetic"
|
||||
val SYNTHETIC_PACKAGE_PATH_LENGTH = SYNTHETIC_PACKAGE.count { it == '.' } + 1
|
||||
|
||||
val ANDROID_NAMESPACE: String = "android"
|
||||
val ID_ATTRIBUTE_NO_NAMESPACE: String = "id"
|
||||
|
||||
+2
-1
@@ -26,12 +26,13 @@ import com.intellij.openapi.vfs.*
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.extensions.*
|
||||
import com.intellij.openapi.module.*
|
||||
import org.jetbrains.kotlin.psi.JetProperty
|
||||
|
||||
public abstract class AndroidResourceManager(val project: Project) {
|
||||
|
||||
public abstract val androidModuleInfo: AndroidModuleInfo?
|
||||
|
||||
public open fun idToXmlAttribute(id: String): PsiElement? = null
|
||||
public open fun propertyToXmlAttribute(property: JetProperty): PsiElement? = null
|
||||
|
||||
public fun getLayoutXmlFiles(): Map<String, List<PsiFile>> {
|
||||
val info = androidModuleInfo
|
||||
|
||||
+2
-2
@@ -84,7 +84,7 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) {
|
||||
|
||||
public fun parse(generateCommonFiles: Boolean = true): List<String> {
|
||||
val commonFiles = if (generateCommonFiles) {
|
||||
val clearCacheFile = renderLayoutFile("kotlinx.android.synthetic") {} +
|
||||
val clearCacheFile = renderLayoutFile(AndroidConst.SYNTHETIC_PACKAGE) {} +
|
||||
renderClearCacheFunction("Activity") + renderClearCacheFunction("Fragment")
|
||||
listOf(clearCacheFile, FLEXIBLE_TYPE_FILE)
|
||||
} else listOf()
|
||||
@@ -132,7 +132,7 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) {
|
||||
}
|
||||
|
||||
private fun PsiFile.genSyntheticPackageName(): String {
|
||||
return AndroidConst.SYNTHETIC_PACKAGE + getName().substringBefore('.')
|
||||
return AndroidConst.SYNTHETIC_PACKAGE + "." + getName().substringBefore('.')
|
||||
}
|
||||
|
||||
private fun KotlinStringWriter.writeSyntheticProperty(receiver: String, widget: AndroidWidget, stubCall: String) {
|
||||
|
||||
+12
-6
@@ -27,6 +27,9 @@ import com.intellij.psi.xml.XmlAttribute
|
||||
import org.jetbrains.android.util.AndroidResourceUtil
|
||||
import java.util.ArrayList
|
||||
import com.intellij.find.findUsages.JavaVariableFindUsagesOptions
|
||||
import com.intellij.openapi.module.ModuleServiceManager
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo
|
||||
import org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator
|
||||
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.JetProperty
|
||||
@@ -52,9 +55,10 @@ class AndroidFindMemberUsagesHandler(
|
||||
assert(isAndroidSyntheticElement(declaration))
|
||||
|
||||
val property = declaration as JetProperty
|
||||
val name = property.getName()!!
|
||||
val parser = ServiceManager.getService(declaration.getProject(), javaClass<AndroidUIXmlProcessor>())
|
||||
val psiElement = parser?.resourceManager?.idToXmlAttribute(name) as? XmlAttribute
|
||||
val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements()
|
||||
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<AndroidUIXmlProcessor>())
|
||||
|
||||
val psiElement = parser?.resourceManager?.propertyToXmlAttribute(property) as? XmlAttribute
|
||||
if (psiElement != null && psiElement.getValueElement() != null) {
|
||||
return array(psiElement.getValueElement()!!)
|
||||
}
|
||||
@@ -69,9 +73,11 @@ class AndroidFindMemberUsagesHandler(
|
||||
override fun getSecondaryElements(): Array<PsiElement> {
|
||||
assert(isAndroidSyntheticElement(declaration))
|
||||
|
||||
val name = (declaration as JetProperty).getName()!!
|
||||
val parser = ServiceManager.getService(declaration.getProject(), javaClass<AndroidUIXmlProcessor>())
|
||||
val psiElement = parser?.resourceManager?.idToXmlAttribute(name) as? XmlAttribute
|
||||
val property = declaration as JetProperty
|
||||
val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements()
|
||||
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<AndroidUIXmlProcessor>())
|
||||
|
||||
val psiElement = parser?.resourceManager?.propertyToXmlAttribute(property) as? XmlAttribute
|
||||
if (psiElement != null) {
|
||||
val res = ArrayList<PsiElement>()
|
||||
val fields = AndroidResourceUtil.findIdFields(psiElement)
|
||||
|
||||
+9
-13
@@ -35,20 +35,16 @@ public class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
|
||||
override fun getGotoDeclarationTargets(sourceElement: PsiElement?, offset: Int, editor: Editor?): Array<PsiElement>? {
|
||||
if (sourceElement is LeafPsiElement && sourceElement.getParent() is JetSimpleNameExpression) {
|
||||
val resolved = JetSimpleNameReference(sourceElement.getParent() as JetSimpleNameExpression).resolve()
|
||||
if (resolved == null) return null
|
||||
val name = if (resolved is JetProperty) {
|
||||
resolved.getName()
|
||||
}
|
||||
else null
|
||||
if (name != null) {
|
||||
val moduleInfo = sourceElement.getModuleInfo()
|
||||
if (moduleInfo !is ModuleSourceInfo) return null
|
||||
val property = resolved as? JetProperty ?: return null
|
||||
|
||||
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<AndroidUIXmlProcessor>())
|
||||
val psiElement = parser.resourceManager.idToXmlAttribute(name) as? XmlAttribute
|
||||
if (psiElement != null) {
|
||||
return array(psiElement.getValueElement())
|
||||
}
|
||||
val moduleInfo = sourceElement.getModuleInfo()
|
||||
if (moduleInfo !is ModuleSourceInfo) return null
|
||||
|
||||
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<AndroidUIXmlProcessor>())
|
||||
val psiElement = parser.resourceManager.propertyToXmlAttribute(property) as? XmlAttribute
|
||||
val attributeValue = psiElement?.getValueElement()
|
||||
if (attributeValue != null) {
|
||||
return array(attributeValue)
|
||||
}
|
||||
}
|
||||
return null
|
||||
|
||||
+3
-5
@@ -84,7 +84,7 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
||||
scope: SearchScope
|
||||
) {
|
||||
if (element != null && element.namedUnwrappedElement is JetProperty) {
|
||||
renameSyntheticProperty(element.namedUnwrappedElement as JetProperty, newName, allRenames, scope)
|
||||
renameSyntheticProperty(element.namedUnwrappedElement as JetProperty, newName, allRenames)
|
||||
}
|
||||
else if (element is XmlAttributeValue) {
|
||||
renameAttributeValue(element, newName, allRenames, scope)
|
||||
@@ -97,16 +97,14 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
||||
private fun renameSyntheticProperty(
|
||||
jetProperty: JetProperty,
|
||||
newName: String,
|
||||
allRenames: MutableMap<PsiElement, String>,
|
||||
scope: SearchScope
|
||||
allRenames: MutableMap<PsiElement, String>
|
||||
) {
|
||||
val oldName = jetProperty.getName()
|
||||
val module = jetProperty.getModule()
|
||||
if (module == null) return
|
||||
|
||||
val processor = ModuleServiceManager.getService(module, javaClass<AndroidUIXmlProcessor>())
|
||||
val resourceManager = processor.resourceManager
|
||||
val attr = resourceManager.idToXmlAttribute(oldName) as XmlAttribute
|
||||
val attr = resourceManager.propertyToXmlAttribute(jetProperty) as XmlAttribute
|
||||
allRenames[XmlAttributeValueWrapper(attr.getValueElement())] = nameToIdDeclaration(newName)
|
||||
val name = AndroidResourceUtil.getResourceNameByReferenceText(newName)
|
||||
for (resField in AndroidResourceUtil.findIdFields(attr)) {
|
||||
|
||||
+23
-8
@@ -19,32 +19,47 @@ package org.jetbrains.kotlin.plugin.android
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.android.facet.AndroidFacet
|
||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidConst
|
||||
import kotlin.properties.Delegates
|
||||
import org.jetbrains.kotlin.plugin.android.AndroidXmlVisitor
|
||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidResourceManager
|
||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidModuleInfo
|
||||
import org.jetbrains.kotlin.psi.JetProperty
|
||||
|
||||
public class IDEAndroidResourceManager(val module: Module) : AndroidResourceManager(module.getProject()) {
|
||||
|
||||
override val androidModuleInfo: AndroidModuleInfo? by Delegates.lazy { module.androidFacet?.toAndroidModuleInfo() }
|
||||
|
||||
override fun idToXmlAttribute(id: String): PsiElement? {
|
||||
override fun propertyToXmlAttribute(property: JetProperty): PsiElement? {
|
||||
val fqPath = property.getFqName()?.pathSegments() ?: return null
|
||||
if (fqPath.size() <= AndroidConst.SYNTHETIC_PACKAGE_PATH_LENGTH) return null
|
||||
|
||||
val layoutPackageName = fqPath[AndroidConst.SYNTHETIC_PACKAGE_PATH_LENGTH].asString()
|
||||
val layoutFiles = getLayoutXmlFiles()[layoutPackageName]
|
||||
if (layoutFiles == null || layoutFiles.isEmpty()) return null
|
||||
|
||||
val propertyName = property.getName()
|
||||
|
||||
var ret: PsiElement? = null
|
||||
for (file in getLayoutXmlFiles().values().flatMap { it }) {
|
||||
file.accept(AndroidXmlVisitor({ retId, wClass, valueElement ->
|
||||
if (retId == id) ret = valueElement
|
||||
}))
|
||||
val visitor = AndroidXmlVisitor { retId, wClass, valueElement ->
|
||||
if (retId == propertyName) ret = valueElement
|
||||
}
|
||||
|
||||
layoutFiles.first().accept(visitor)
|
||||
return ret
|
||||
}
|
||||
|
||||
private val Module.androidFacet: AndroidFacet?
|
||||
get() = AndroidFacet.getInstance(this)
|
||||
|
||||
private fun AndroidFacet.toAndroidModuleInfo(): AndroidModuleInfo {
|
||||
val applicationPackage = getManifest().getPackage().toString()
|
||||
private fun AndroidFacet.toAndroidModuleInfo(): AndroidModuleInfo? {
|
||||
val applicationPackage = getManifest()?.getPackage()?.toString()
|
||||
val mainResDirectory = getAllResourceDirectories().firstOrNull()?.getPath()
|
||||
return AndroidModuleInfo(applicationPackage, mainResDirectory)
|
||||
|
||||
return if (applicationPackage != null) {
|
||||
AndroidModuleInfo(applicationPackage, mainResDirectory)
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user