fix excess xml parsing when renaming resources
- rebuild resource name -> xml attribute mappings same time as rebuilding synthetic properties - update mappings during rename
This commit is contained in:
committed by
Yan Zhulanow
parent
9f20c36959
commit
37c851cafc
@@ -23,10 +23,14 @@ import com.intellij.openapi.actionSystem.DataContext
|
|||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor
|
import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import com.intellij.psi.PsiReferenceExpression
|
||||||
|
|
||||||
public class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
|
public class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
|
||||||
override fun getGotoDeclarationTargets(sourceElement: PsiElement?, offset: Int, editor: Editor?): Array<PsiElement>? {
|
override fun getGotoDeclarationTargets(sourceElement: PsiElement?, offset: Int, editor: Editor?): Array<PsiElement>? {
|
||||||
|
// FIXME: find a way to filter out more bad sourceElements before they hit idToXmlAttribute() resulting in cache rebuild
|
||||||
if (sourceElement is LeafPsiElement) {
|
if (sourceElement is LeafPsiElement) {
|
||||||
|
val refExp = PsiTreeUtil.getParentOfType(sourceElement, javaClass<PsiReferenceExpression>())
|
||||||
val parser = ServiceManager.getService(sourceElement.getProject(), javaClass<AndroidUIXmlProcessor>())
|
val parser = ServiceManager.getService(sourceElement.getProject(), javaClass<AndroidUIXmlProcessor>())
|
||||||
val psiElement = parser?.resourceManager?.idToXmlAttribute(sourceElement.getText())
|
val psiElement = parser?.resourceManager?.idToXmlAttribute(sourceElement.getText())
|
||||||
if (psiElement != null) {
|
if (psiElement != null) {
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
|||||||
for (prop in matchedProps) {
|
for (prop in matchedProps) {
|
||||||
allRenames[prop] = newPropName
|
allRenames[prop] = newPropName
|
||||||
}
|
}
|
||||||
|
processor.resourceManager.renameProperty(oldPropName!!, newPropName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renameLightClassField(field: LightElement, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
private fun renameLightClassField(field: LightElement, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ import com.intellij.psi.XmlElementVisitor
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.xml.XmlElement
|
import com.intellij.psi.xml.XmlElement
|
||||||
import com.intellij.psi.xml.XmlTag
|
import com.intellij.psi.xml.XmlTag
|
||||||
|
import com.intellij.psi.xml.XmlAttribute
|
||||||
|
|
||||||
class AndroidXmlVisitor(val elementCallback: (String, String) -> Unit) : XmlElementVisitor() {
|
class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> Unit) : XmlElementVisitor() {
|
||||||
|
|
||||||
override fun visitElement(element: PsiElement) {
|
override fun visitElement(element: PsiElement) {
|
||||||
element.acceptChildren(this)
|
element.acceptChildren(this)
|
||||||
@@ -35,7 +36,7 @@ class AndroidXmlVisitor(val elementCallback: (String, String) -> Unit) : XmlElem
|
|||||||
val idPrefix = "@+id/"
|
val idPrefix = "@+id/"
|
||||||
val attribute = tag?.getAttribute("android:id")
|
val attribute = tag?.getAttribute("android:id")
|
||||||
if (attribute != null && attribute.getValue() != null) {
|
if (attribute != null && attribute.getValue() != null) {
|
||||||
elementCallback(attribute.getValue()!!.replace(idPrefix, ""), tag!!.getLocalName())
|
elementCallback(attribute.getValue()!!.replace(idPrefix, ""), tag!!.getLocalName(), attribute)
|
||||||
}
|
}
|
||||||
tag?.acceptChildren(this)
|
tag?.acceptChildren(this)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,53 +21,30 @@ import org.jetbrains.jet.lang.resolve.android.AndroidResourceManagerBase
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
import com.intellij.psi.xml.XmlAttribute
|
import com.intellij.psi.xml.XmlAttribute
|
||||||
import com.intellij.psi.xml.XmlFile
|
|
||||||
import com.intellij.psi.XmlElementVisitor
|
|
||||||
import com.intellij.psi.xml.XmlTag
|
|
||||||
|
|
||||||
public class IDEAndroidResourceManager(project: Project, searchPath: String?) : AndroidResourceManagerBase(project, searchPath) {
|
public class IDEAndroidResourceManager(project: Project, searchPath: String?) : AndroidResourceManagerBase(project, searchPath) {
|
||||||
|
|
||||||
private val idToXmlAttributeCache = HashMap<String, PsiElement>()
|
private val idToXmlAttributeCache = HashMap<String, PsiElement>()
|
||||||
|
|
||||||
;{
|
public fun addMapping(name: String, attr: XmlAttribute) {
|
||||||
setupElementCache()
|
idToXmlAttributeCache[name] = attr
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupElementCache() {
|
public fun resetAttributeCache() {
|
||||||
idToXmlAttributeCache.clear()
|
idToXmlAttributeCache.clear()
|
||||||
for (file in getLayoutXmlFiles()) {
|
|
||||||
if (file is XmlFile) {
|
|
||||||
file.accept(object : XmlElementVisitor() {
|
|
||||||
override fun visitElement(element: PsiElement) {
|
|
||||||
element.acceptChildren(this)
|
|
||||||
}
|
|
||||||
override fun visitXmlTag(tag: XmlTag?) {
|
|
||||||
val attribute = tag?.getAttribute("android:id")
|
|
||||||
val s = attribute?.getValue()
|
|
||||||
if (attribute != null && s != null && isResourceId(s)) {
|
|
||||||
idToXmlAttributeCache[idToName(s)] = attribute
|
|
||||||
}
|
|
||||||
tag?.acceptChildren(this)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun idToXmlAttribute(id: String): PsiElement? {
|
override fun idToXmlAttribute(id: String): PsiElement? {
|
||||||
val element = idToXmlAttributeCache[id]
|
val element = idToXmlAttributeCache[id]
|
||||||
// element not in cache - files might have changed
|
|
||||||
if (element == null) {
|
|
||||||
setupElementCache()
|
|
||||||
return idToXmlAttributeCache[id]
|
|
||||||
}
|
|
||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renameXmlAttr(elem: PsiElement, newName: String) {
|
override fun renameXmlAttr(elem: PsiElement, newName: String) {
|
||||||
val xmlAttr = elem as XmlAttribute
|
val xmlAttr = elem as XmlAttribute
|
||||||
idToXmlAttributeCache.remove(xmlAttr.getName())
|
idToXmlAttributeCache.remove(xmlAttr.getName())
|
||||||
idToXmlAttributeCache[newName] = xmlAttr
|
idToXmlAttributeCache[newName] = xmlAttr
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renameProperty(oldName: String, newName: String) {
|
override fun renameProperty(oldName: String, newName: String) {
|
||||||
val oldElem = idToXmlAttributeCache[oldName]
|
val oldElem = idToXmlAttributeCache[oldName]
|
||||||
idToXmlAttributeCache.remove(oldName)
|
idToXmlAttributeCache.remove(oldName)
|
||||||
|
|||||||
@@ -22,13 +22,12 @@ import java.util.ArrayList
|
|||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import org.jetbrains.jet.lang.resolve.android.AndroidWidget
|
import org.jetbrains.jet.lang.resolve.android.AndroidWidget
|
||||||
import org.jetbrains.jet.lang.resolve.android.KotlinStringWriter
|
import org.jetbrains.jet.lang.resolve.android.KotlinStringWriter
|
||||||
import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager
|
|
||||||
|
|
||||||
class IDEAndroidUIXmlProcessor(project: Project) : AndroidUIXmlProcessor(project) {
|
class IDEAndroidUIXmlProcessor(project: Project) : AndroidUIXmlProcessor(project) {
|
||||||
override val searchPath: String? = project.getBasePath() + "/res/layout/"
|
override val searchPath: String? = project.getBasePath() + "/res/layout/"
|
||||||
override var androidAppPackage: String = ""
|
override var androidAppPackage: String = ""
|
||||||
|
|
||||||
override val resourceManager: AndroidResourceManager = IDEAndroidResourceManager(project, searchPath)
|
override val resourceManager: IDEAndroidResourceManager = IDEAndroidResourceManager(project, searchPath)
|
||||||
|
|
||||||
override protected fun lazySetup() {
|
override protected fun lazySetup() {
|
||||||
if (listenerSetUp) return
|
if (listenerSetUp) return
|
||||||
@@ -39,7 +38,11 @@ class IDEAndroidUIXmlProcessor(project: Project) : AndroidUIXmlProcessor(project
|
|||||||
|
|
||||||
override fun parseSingleFileImpl(file: PsiFile): String {
|
override fun parseSingleFileImpl(file: PsiFile): String {
|
||||||
val ids: MutableCollection<AndroidWidget> = ArrayList()
|
val ids: MutableCollection<AndroidWidget> = ArrayList()
|
||||||
file.accept(AndroidXmlVisitor({ id, wClass -> ids.add(AndroidWidget(id, wClass)) }))
|
resourceManager.resetAttributeCache()
|
||||||
|
file.accept(AndroidXmlVisitor { id, wClass, valueElement ->
|
||||||
|
ids.add(AndroidWidget(id, wClass))
|
||||||
|
resourceManager.addMapping(id, valueElement)
|
||||||
|
})
|
||||||
return produceKotlinProperties(KotlinStringWriter(), ids).toString()
|
return produceKotlinProperties(KotlinStringWriter(), ids).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user