Refactor Android plugin
This commit is contained in:
+2
-1
@@ -28,13 +28,13 @@ import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.jet.lang.psi.JetProperty
|
||||
import com.intellij.psi.impl.light.LightElement
|
||||
import com.intellij.psi.xml.XmlAttribute
|
||||
import org.jetbrains.jet.lang.resolve.android.isRClassField
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.openapi.module.ModuleServiceManager
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo
|
||||
import org.jetbrains.jet.plugin.caches.resolve.ModuleSourceInfo
|
||||
|
||||
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()
|
||||
@@ -60,4 +60,5 @@ public class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
|
||||
override fun getActionText(context: DataContext?): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+60
-18
@@ -29,22 +29,38 @@ import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper
|
||||
import org.jetbrains.android.util.AndroidResourceUtil
|
||||
import com.intellij.psi.xml.XmlAttribute
|
||||
import com.intellij.psi.impl.light.LightElement
|
||||
import org.jetbrains.jet.lang.resolve.android.isRClassField
|
||||
import com.intellij.openapi.module.ModuleServiceManager
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo
|
||||
import org.jetbrains.jet.plugin.caches.resolve.ModuleSourceInfo
|
||||
import com.intellij.openapi.module.Module
|
||||
import org.jetbrains.jet.lang.psi.JetFile
|
||||
import org.jetbrains.jet.lang.psi.moduleInfo
|
||||
import org.jetbrains.jet.lang.resolve.android.nameToIdDeclaration
|
||||
import org.jetbrains.jet.lang.resolve.android.idToName
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.psi.PsiClass
|
||||
|
||||
public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
||||
|
||||
override fun canProcessElement(element: PsiElement): Boolean {
|
||||
// either renaming synthetic property, or value in ui xml, or R class field
|
||||
// Either renaming synthetic property, or value in layout xml, or R class field
|
||||
return (element.namedUnwrappedElement is JetProperty &&
|
||||
isAndroidSyntheticElement(element.namedUnwrappedElement)) || element is XmlAttributeValue ||
|
||||
isRClassField(element)
|
||||
}
|
||||
|
||||
private fun isRClassField(element: PsiElement): Boolean {
|
||||
return if (element is PsiField) {
|
||||
val outerClass = element.getParent()?.getParent()
|
||||
if (outerClass !is PsiClass) return false
|
||||
|
||||
if (outerClass.getQualifiedName()?.startsWith(AndroidConst.SYNTHETIC_PACKAGE) ?: false)
|
||||
true else false
|
||||
}
|
||||
else false
|
||||
}
|
||||
|
||||
|
||||
private fun PsiElement.getModule(): Module? {
|
||||
val moduleInfo = getModuleInfo()
|
||||
if (moduleInfo is ModuleSourceInfo) return moduleInfo.module
|
||||
@@ -58,7 +74,12 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun prepareRenaming(element: PsiElement?, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
override fun prepareRenaming(
|
||||
element: PsiElement?,
|
||||
newName: String,
|
||||
allRenames: MutableMap<PsiElement, String>,
|
||||
scope: SearchScope
|
||||
) {
|
||||
if (element != null && element.namedUnwrappedElement is JetProperty) {
|
||||
renameSyntheticProperty(element.namedUnwrappedElement as JetProperty, newName, allRenames, scope)
|
||||
}
|
||||
@@ -70,45 +91,66 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun renameSyntheticProperty(jetProperty: JetProperty, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
private fun renameSyntheticProperty(
|
||||
jetProperty: JetProperty,
|
||||
newName: String,
|
||||
allRenames: MutableMap<PsiElement, String>,
|
||||
scope: SearchScope
|
||||
) {
|
||||
val oldName = jetProperty.getName()
|
||||
val module = jetProperty.getModule()
|
||||
if (module == null) return
|
||||
|
||||
val processor = ModuleServiceManager.getService(module, javaClass<AndroidUIXmlProcessor>())
|
||||
val resourceManager = processor!!.resourceManager
|
||||
val resourceManager = processor.resourceManager
|
||||
val attr = resourceManager.idToXmlAttribute(oldName) as XmlAttribute
|
||||
allRenames[XmlAttributeValueWrapper(attr.getValueElement()!!)] = resourceManager.nameToIdDeclaration(newName!!)
|
||||
allRenames[XmlAttributeValueWrapper(attr.getValueElement())] = nameToIdDeclaration(newName)
|
||||
val name = AndroidResourceUtil.getResourceNameByReferenceText(newName)
|
||||
for (resField in AndroidResourceUtil.findIdFields(attr)) {
|
||||
allRenames.put(resField, AndroidResourceUtil.getFieldNameByResourceName(name!!))
|
||||
allRenames.put(resField, AndroidResourceUtil.getFieldNameByResourceName(name))
|
||||
}
|
||||
}
|
||||
|
||||
private fun renameAttributeValue(attribute: XmlAttributeValue, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
val element1 = LazyValueResourceElementWrapper.computeLazyElement(attribute)
|
||||
val module = attribute.getModule()
|
||||
private fun renameAttributeValue(
|
||||
attribute: XmlAttributeValue,
|
||||
newName: String,
|
||||
allRenames: MutableMap<PsiElement, String>,
|
||||
scope: SearchScope
|
||||
) {
|
||||
val element = LazyValueResourceElementWrapper.computeLazyElement(attribute)
|
||||
val module = attribute.getModule() ?: ModuleUtilCore.findModuleForFile(
|
||||
attribute.getContainingFile().getVirtualFile(), attribute.getProject())
|
||||
if (module == null) return
|
||||
|
||||
val processor = ModuleServiceManager.getService(module, javaClass<AndroidUIXmlProcessor>())
|
||||
if (element1 == null) return
|
||||
val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue()!!)
|
||||
val newPropName = processor!!.resourceManager.idToName(newName!!)
|
||||
if (element == null) return
|
||||
val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue())
|
||||
val newPropName = idToName(newName)
|
||||
renameSyntheticProperties(allRenames, newPropName, oldPropName, processor)
|
||||
}
|
||||
|
||||
private fun renameSyntheticProperties(allRenames: MutableMap<PsiElement, String>, newPropName: String, oldPropName: String?, processor: AndroidUIXmlProcessor) {
|
||||
val props = processor.lastCachedPsi?.findChildrenByClass(javaClass<JetProperty>())
|
||||
val matchedProps = props?.filter { it.getName() == oldPropName } ?: arrayListOf()
|
||||
private fun renameSyntheticProperties(
|
||||
allRenames: MutableMap<PsiElement, String>,
|
||||
newPropName: String,
|
||||
oldPropName: String,
|
||||
processor: AndroidUIXmlProcessor
|
||||
) {
|
||||
val props = processor.parseToPsi()?.flatMap { it.findChildrenByClass(javaClass<JetProperty>()).toList() }
|
||||
val matchedProps = props?.filter { it.getName() == oldPropName } ?: listOf()
|
||||
for (prop in matchedProps) {
|
||||
allRenames[prop] = 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
|
||||
) {
|
||||
val oldName = field.getName()
|
||||
val processor = ServiceManager.getService(field.getProject(), javaClass<AndroidUIXmlProcessor>())
|
||||
renameSyntheticProperties(allRenames, newName!!, oldName, processor!!)
|
||||
renameSyntheticProperties(allRenames, newName, oldName, processor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ public class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension
|
||||
}
|
||||
if (isAndroidSyntheticElement(resolvedElement)) {
|
||||
if (element is ValueResourceElementWrapper) {
|
||||
val resource = element.getValue()!!
|
||||
val resource = element.getValue()
|
||||
return (resolvedElement as JetProperty).getName() == resource.substring(resource.indexOf('/') + 1)
|
||||
}
|
||||
}
|
||||
|
||||
+13
-5
@@ -22,8 +22,13 @@ import com.intellij.psi.xml.XmlElement
|
||||
import com.intellij.psi.xml.XmlTag
|
||||
import com.intellij.psi.xml.XmlAttribute
|
||||
import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager
|
||||
import org.jetbrains.jet.lang.resolve.android.idToName
|
||||
import org.jetbrains.jet.lang.resolve.android.AndroidConst
|
||||
|
||||
class AndroidXmlVisitor(val resourceManager: AndroidResourceManager, val elementCallback: (String, String, XmlAttribute) -> Unit) : XmlElementVisitor() {
|
||||
class AndroidXmlVisitor(
|
||||
val resourceManager: AndroidResourceManager,
|
||||
val elementCallback: (String, String, XmlAttribute) -> Unit
|
||||
) : XmlElementVisitor() {
|
||||
|
||||
override fun visitElement(element: PsiElement) {
|
||||
element.acceptChildren(this)
|
||||
@@ -34,10 +39,13 @@ class AndroidXmlVisitor(val resourceManager: AndroidResourceManager, val element
|
||||
}
|
||||
|
||||
override fun visitXmlTag(tag: XmlTag?) {
|
||||
val attribute = tag?.getAttribute(resourceManager.idAttribute)
|
||||
if (attribute != null && attribute.getValue() != null) {
|
||||
val classNameAttr = tag?.getAttribute(resourceManager.classAttributeNoNamespace)?.getValue() ?: tag?.getLocalName()
|
||||
elementCallback(resourceManager.idToName(attribute.getValue()), classNameAttr!!, attribute)
|
||||
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()
|
||||
elementCallback(idToName(attributeValue), classNameAttr!!, attribute)
|
||||
}
|
||||
}
|
||||
tag?.acceptChildren(this)
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class IDEAndroidExternalDeclarationsProvider(private val project: Project
|
||||
|
||||
val module = moduleInfo.module
|
||||
val parser = ModuleServiceManager.getService<AndroidUIXmlProcessor>(module, javaClass<AndroidUIXmlProcessor>())
|
||||
val syntheticFile = parser.parseToPsi(project)
|
||||
val syntheticFile = parser.parseToPsi()
|
||||
syntheticFile?.moduleInfo = moduleInfo
|
||||
|
||||
return if (syntheticFile != null) listOf(syntheticFile) else listOf()
|
||||
|
||||
+15
-19
@@ -17,36 +17,23 @@
|
||||
package org.jetbrains.jet.plugin.android
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.jet.lang.resolve.android.AndroidResourceManagerBase
|
||||
import com.intellij.psi.PsiElement
|
||||
import java.util.HashMap
|
||||
import com.intellij.psi.xml.XmlAttribute
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.android.facet.AndroidFacet
|
||||
import org.jetbrains.jet.lang.resolve.android.AndroidManifest
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import java.util.ArrayList
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager
|
||||
import org.jetbrains.jet.lang.resolve.android.AndroidModuleInfo
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
public class IDEAndroidResourceManager(val module: Module, searchPath: String?) : AndroidResourceManagerBase(module.getProject(), searchPath) {
|
||||
public class IDEAndroidResourceManager(val module: Module) : AndroidResourceManager(module.getProject()) {
|
||||
|
||||
override fun getLayoutXmlFiles(): Collection<PsiFile> {
|
||||
val directories = getAndroidFacet()?.getAllResourceDirectories() ?: listOf()
|
||||
return directories.flatMap {
|
||||
(it.findChild("layout")?.getChildren() ?: array<VirtualFile>()).map { virtualFileToPsi(it)!! }
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAndroidFacet(): AndroidFacet? {
|
||||
return AndroidFacet.getInstance(module)
|
||||
}
|
||||
|
||||
override fun readManifest(): AndroidManifest {
|
||||
val facet = getAndroidFacet()
|
||||
val attributeValue = facet?.getManifest()!!.getPackage()
|
||||
return AndroidManifest(attributeValue.getRawText())
|
||||
}
|
||||
override val androidModuleInfo: AndroidModuleInfo? by Delegates.lazy { module.androidFacet?.toAndroidModuleInfo() }
|
||||
|
||||
override fun idToXmlAttribute(id: String): PsiElement? {
|
||||
var ret: PsiElement? = null
|
||||
@@ -58,4 +45,13 @@ public class IDEAndroidResourceManager(val module: Module, searchPath: String?)
|
||||
return ret
|
||||
}
|
||||
|
||||
private val Module.androidFacet: AndroidFacet?
|
||||
get() = AndroidFacet.getInstance(this)
|
||||
|
||||
private fun AndroidFacet.toAndroidModuleInfo(): AndroidModuleInfo {
|
||||
val applicationPackage = getManifest().getPackage().toString()
|
||||
val mainResDirectory = getAllResourceDirectories().firstOrNull()?.getPath()
|
||||
return AndroidModuleInfo(applicationPackage, mainResDirectory)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-10
@@ -28,18 +28,16 @@ import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager
|
||||
import com.intellij.openapi.module.Module
|
||||
|
||||
class IDEAndroidUIXmlProcessor(val module: Module) : AndroidUIXmlProcessor(module.getProject()) {
|
||||
override val searchPath: String? = project.getBasePath() + "/res/layout/"
|
||||
override var androidAppPackage: String = ""
|
||||
get() = resourceManager.readManifest()._package
|
||||
|
||||
override val resourceManager: IDEAndroidResourceManager = IDEAndroidResourceManager(module, searchPath)
|
||||
override val resourceManager: IDEAndroidResourceManager = IDEAndroidResourceManager(module)
|
||||
|
||||
override fun parseSingleFileImpl(file: PsiFile): String {
|
||||
val ids: MutableCollection<AndroidWidget> = ArrayList()
|
||||
override fun parseSingleFile(file: PsiFile): List<AndroidWidget> {
|
||||
val widgets = arrayListOf<AndroidWidget>()
|
||||
file.accept(AndroidXmlVisitor(resourceManager, { id, wClass, valueElement ->
|
||||
ids.add(AndroidWidget(id, wClass))
|
||||
widgets.add(AndroidWidget(id, wClass))
|
||||
}))
|
||||
return produceKotlinProperties(KotlinStringWriter(), ids).toString()
|
||||
}
|
||||
}
|
||||
|
||||
return widgets
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user