move android rename handler out of kotlin property renamer, extract resource manager class
This commit is contained in:
committed by
Yan Zhulanow
parent
395959bf21
commit
1b50b226ae
@@ -296,7 +296,7 @@ public class JetCoreEnvironment {
|
|||||||
);
|
);
|
||||||
|
|
||||||
String s = configuration.get(JVMConfigurationKeys.ANDROID_RES_PATH);
|
String s = configuration.get(JVMConfigurationKeys.ANDROID_RES_PATH);
|
||||||
project.registerService(AndroidUIXmlParser.class, new CliAndroidUIXmlParser(project, s));
|
project.registerService(AndroidUIXmlProcessor.class, new CliAndroidUIXmlProcessor(project, s));
|
||||||
project.registerService(VirtualFileFinderFactory.class, new CliVirtualFileFinderFactory(classPath));
|
project.registerService(VirtualFileFinderFactory.class, new CliVirtualFileFinderFactory(classPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.lang.resolve.android
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
|
||||||
|
abstract class AndroidResourceManager(val project: Project, val searchPath: String?) {
|
||||||
|
abstract fun getLayoutXmlFiles(): Collection<PsiFile>
|
||||||
|
abstract fun idToXmlAttribute(id: String): PsiElement?
|
||||||
|
abstract fun renameXmlAttr(elem: PsiElement, newName: String)
|
||||||
|
abstract fun renameProperty(oldName: String, newName: String)
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.lang.resolve.android
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiManager
|
||||||
|
import java.util.ArrayList
|
||||||
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
|
|
||||||
|
open class AndroidResourceManagerBase(project: Project, searchPath: String?) : AndroidResourceManager(project, searchPath) {
|
||||||
|
override fun getLayoutXmlFiles(): Collection<PsiFile> {
|
||||||
|
val fileManager = VirtualFileManager.getInstance()
|
||||||
|
val watchDir = fileManager.findFileByUrl("file://" + searchPath)
|
||||||
|
val psiManager = PsiManager.getInstance(project)
|
||||||
|
return watchDir?.getChildren()?.toArrayList()?.map { psiManager.findFile(it) }?.mapNotNull { it } ?: ArrayList(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun idToXmlAttribute(id: String): PsiElement? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renameXmlAttr(elem: PsiElement, newName: String) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renameProperty(oldName: String, newName: String) {
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-41
@@ -17,6 +17,9 @@
|
|||||||
package org.jetbrains.jet.lang.resolve.android
|
package org.jetbrains.jet.lang.resolve.android
|
||||||
|
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
import java.util.HashMap
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
|
import java.io.File
|
||||||
import javax.xml.parsers.SAXParserFactory
|
import javax.xml.parsers.SAXParserFactory
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
@@ -44,9 +47,8 @@ import com.intellij.psi.impl.PsiModificationTrackerImpl
|
|||||||
import java.util.Queue
|
import java.util.Queue
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
|
|
||||||
abstract class AndroidUIXmlParser {
|
abstract class AndroidUIXmlProcessor(val project: Project) {
|
||||||
|
|
||||||
inner class NoUIXMLsFound : Exception("No android UI xmls found in $searchPath")
|
inner class NoUIXMLsFound : Exception("No android UI xmls found in $searchPath")
|
||||||
class NoAndroidManifestFound : Exception("No android manifest file found in project root")
|
class NoAndroidManifestFound : Exception("No android manifest file found in project root")
|
||||||
@@ -85,12 +87,10 @@ abstract class AndroidUIXmlParser {
|
|||||||
return renderString()
|
return renderString()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun getXmlLayoutFiles(): Collection<PsiFile> = fileCache.keySet()
|
public open val resourceManager: AndroidResourceManager = AndroidResourceManagerBase(project, searchPath)
|
||||||
|
|
||||||
public abstract fun idToXmlAttribute(id: String): PsiElement?
|
|
||||||
|
|
||||||
public fun parseToPsi(project: Project): JetFile? {
|
public fun parseToPsi(project: Project): JetFile? {
|
||||||
populateQueue(project)
|
populateQueue()
|
||||||
val cacheState = doParse()
|
val cacheState = doParse()
|
||||||
if (cacheState == null) return null
|
if (cacheState == null) return null
|
||||||
return if (cacheState == CacheAction.MISS || lastCachedPsi == null) {
|
return if (cacheState == CacheAction.MISS || lastCachedPsi == null) {
|
||||||
@@ -110,30 +110,6 @@ abstract class AndroidUIXmlParser {
|
|||||||
else lastCachedPsi
|
else lastCachedPsi
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isAndroidUIXml(file: File): Boolean {
|
|
||||||
return file.extension == "xml"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun searchForUIXml(path: String): Collection<File> {
|
|
||||||
return searchForUIXml(arrayListOf(File(path)))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun searchForUIXml(paths: Collection<File>?): Collection<File> {
|
|
||||||
if (paths == null) return ArrayList(0)
|
|
||||||
val res = ArrayList<File>()
|
|
||||||
for (path in paths) {
|
|
||||||
if (!path.exists()) continue;
|
|
||||||
if (path.isFile() && isAndroidUIXml(path)) {
|
|
||||||
res.add(path)
|
|
||||||
}
|
|
||||||
else if (path.isDirectory()) {
|
|
||||||
res.addAll(searchForUIXml(path.listFiles()?.toArrayList()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun writeImports(kw: KotlinStringWriter): KotlinWriter {
|
private fun writeImports(kw: KotlinStringWriter): KotlinWriter {
|
||||||
kw.writePackage(androidAppPackage)
|
kw.writePackage(androidAppPackage)
|
||||||
for (elem in androidImports)
|
for (elem in androidImports)
|
||||||
@@ -185,15 +161,8 @@ abstract class AndroidUIXmlParser {
|
|||||||
lastCachedPsi = null
|
lastCachedPsi = null
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun getXmlLayouts(project: Project): Collection<PsiFile> {
|
protected fun populateQueue() {
|
||||||
val fileManager = VirtualFileManager.getInstance()
|
filesToProcess.addAll(resourceManager.getLayoutXmlFiles())
|
||||||
val watchDir = fileManager.findFileByUrl("file://" + searchPath)
|
|
||||||
val psiManager = PsiManager.getInstance(project)
|
|
||||||
return watchDir?.getChildren()?.toArrayList()?.map { psiManager.findFile(it) }?.mapNotNull { it } ?: ArrayList(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun populateQueue(project: Project) {
|
|
||||||
filesToProcess.addAll(getXmlLayouts(project))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun lazySetup()
|
protected abstract fun lazySetup()
|
||||||
@@ -230,6 +199,4 @@ abstract class AndroidUIXmlParser {
|
|||||||
}
|
}
|
||||||
return kw.output()
|
return kw.output()
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun renameId(oldName: String?, newName: String?, allRenames: MutableMap<PsiElement, String>)
|
|
||||||
}
|
}
|
||||||
+2
-10
@@ -19,15 +19,14 @@ package org.jetbrains.jet.lang.resolve.android
|
|||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
|
|
||||||
class CliAndroidUIXmlParser(val project: Project, override val searchPath: String?) : AndroidUIXmlParser() {
|
class CliAndroidUIXmlProcessor(project: Project, override val searchPath: String?) : AndroidUIXmlProcessor(project) {
|
||||||
|
|
||||||
override var androidAppPackage: String = ""
|
override var androidAppPackage: String = ""
|
||||||
|
|
||||||
|
|
||||||
override fun lazySetup() {
|
override fun lazySetup() {
|
||||||
populateQueue(project)
|
populateQueue()
|
||||||
androidAppPackage = readManifest()._package
|
androidAppPackage = readManifest()._package
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,12 +42,5 @@ class CliAndroidUIXmlParser(val project: Project, override val searchPath: Strin
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun idToXmlAttribute(id: String): PsiElement? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
override fun renameId(oldName: String?, newName: String?, allRenames: MutableMap<PsiElement, String>) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
-2
@@ -23,7 +23,7 @@ import com.intellij.psi.PsiFile;
|
|||||||
import com.intellij.psi.search.GlobalSearchScope;
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlParser;
|
import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor;
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult;
|
import org.jetbrains.kotlin.analyzer.AnalysisResult;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.context.GlobalContext;
|
import org.jetbrains.kotlin.context.GlobalContext;
|
||||||
@@ -176,7 +176,7 @@ public enum TopDownAnalyzerFacadeForJVM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Collection<JetFile> searchAndAddAndroidDeclarations(Project project, Collection<JetFile> files) {
|
private static Collection<JetFile> searchAndAddAndroidDeclarations(Project project, Collection<JetFile> files) {
|
||||||
AndroidUIXmlParser parser = ServiceManager.getService(project, AndroidUIXmlParser.class);
|
AndroidUIXmlProcessor parser = ServiceManager.getService(project, AndroidUIXmlProcessor.class);
|
||||||
JetFile file = parser.parseToPsi(project);
|
JetFile file = parser.parseToPsi(project);
|
||||||
if (file != null) files.add(file);
|
if (file != null) files.add(file);
|
||||||
return files;
|
return files;
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class AndroidXmlTest extends TestCaseWithTmpdir {
|
|||||||
|
|
||||||
public void testConverterOneFile() throws Exception {
|
public void testConverterOneFile() throws Exception {
|
||||||
JetCoreEnvironment jetCoreEnvironment = getEnvironment(singleFileResPath);
|
JetCoreEnvironment jetCoreEnvironment = getEnvironment(singleFileResPath);
|
||||||
AndroidUIXmlParser parser = new CliAndroidUIXmlParser(jetCoreEnvironment.getProject(), singleFileDir.getAbsolutePath());
|
AndroidUIXmlProcessor parser = new CliAndroidUIXmlProcessor(jetCoreEnvironment.getProject(), singleFileDir.getAbsolutePath());
|
||||||
|
|
||||||
String actual = parser.parseToString();
|
String actual = parser.parseToString();
|
||||||
String expected = loadOrCreate(new File(getTestDataPath() + "/converter/singleFile/layout.kt"), actual);
|
String expected = loadOrCreate(new File(getTestDataPath() + "/converter/singleFile/layout.kt"), actual);
|
||||||
|
|||||||
@@ -198,6 +198,9 @@
|
|||||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.caches.resolve.LibraryModificationTracker"
|
<projectService serviceInterface="org.jetbrains.kotlin.idea.caches.resolve.LibraryModificationTracker"
|
||||||
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.LibraryModificationTracker"/>
|
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.LibraryModificationTracker"/>
|
||||||
|
|
||||||
|
<projectService serviceInterface="org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor"
|
||||||
|
serviceImplementation="org.jetbrains.jet.plugin.android.IDEAndroidUIXmlProcessor"/>
|
||||||
|
|
||||||
<projectService serviceInterface="org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade"
|
<projectService serviceInterface="org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade"
|
||||||
serviceImplementation="org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade"/>
|
serviceImplementation="org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade"/>
|
||||||
|
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
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.AndroidUIXmlParser
|
import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
|
|
||||||
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>? {
|
||||||
if (sourceElement is LeafPsiElement) {
|
if (sourceElement is LeafPsiElement) {
|
||||||
val parser = ServiceManager.getService(sourceElement.getProject(), javaClass<AndroidUIXmlParser>())
|
val parser = ServiceManager.getService(sourceElement.getProject(), javaClass<AndroidUIXmlProcessor>())
|
||||||
val psiElement = parser?.idToXmlAttribute(sourceElement.getText())
|
val psiElement = parser?.resourceManager?.idToXmlAttribute(sourceElement.getText())
|
||||||
if (psiElement != null) {
|
if (psiElement != null) {
|
||||||
return array(psiElement)
|
return array(psiElement)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.plugin.android
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
||||||
|
import org.jetbrains.jet.asJava.*
|
||||||
|
import org.jetbrains.jet.lang.psi.JetProperty
|
||||||
|
import org.jetbrains.jet.lang.resolve.android.isAndroidSyntheticElement
|
||||||
|
import com.intellij.openapi.components.ServiceManager
|
||||||
|
import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor
|
||||||
|
import com.intellij.psi.search.SearchScope
|
||||||
|
import com.intellij.psi.xml.XmlAttributeValue
|
||||||
|
import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper
|
||||||
|
import org.jetbrains.android.util.AndroidResourceUtil
|
||||||
|
import com.intellij.psi.xml.XmlFile
|
||||||
|
import com.intellij.psi.XmlElementVisitor
|
||||||
|
import com.intellij.psi.xml.XmlTag
|
||||||
|
import com.intellij.psi.xml.XmlAttribute
|
||||||
|
|
||||||
|
public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
||||||
|
override fun canProcessElement(element: PsiElement): Boolean {
|
||||||
|
return (element.namedUnwrappedElement is JetProperty &&
|
||||||
|
isAndroidSyntheticElement(element.namedUnwrappedElement)) || element is XmlAttributeValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun prepareRenaming(element: PsiElement?, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||||
|
if (element?.namedUnwrappedElement is JetProperty) {
|
||||||
|
renameSyntheticProperty(element!!.namedUnwrappedElement as JetProperty, newName, allRenames, scope)
|
||||||
|
}
|
||||||
|
else if (element is XmlAttributeValue) {
|
||||||
|
renameAttributeValue(element, newName, allRenames, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renameSyntheticProperty(jetProperty: JetProperty, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||||
|
val oldName = jetProperty.getName()!!
|
||||||
|
val processor = ServiceManager.getService(jetProperty.getProject(), javaClass<AndroidUIXmlProcessor>())
|
||||||
|
val resourceManager = processor!!.resourceManager
|
||||||
|
val attr = resourceManager.idToXmlAttribute(oldName) as XmlAttribute
|
||||||
|
for (file in resourceManager.getLayoutXmlFiles()) {
|
||||||
|
if (file is XmlFile) {
|
||||||
|
file.accept(object : XmlElementVisitor() {
|
||||||
|
override fun visitElement(element: PsiElement) {
|
||||||
|
element.acceptChildren(this)
|
||||||
|
}
|
||||||
|
override fun visitXmlTag(tag: XmlTag?) {
|
||||||
|
val idPrefix = "@+id/"
|
||||||
|
val attribute = tag?.getAttribute("android:id")
|
||||||
|
if (attribute != null && attribute.getValue() == idPrefix + oldName) {
|
||||||
|
allRenames[XmlAttributeValueWrapper(attribute.getValueElement()!!)] = idPrefix + newName
|
||||||
|
}
|
||||||
|
tag?.acceptChildren(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val name = AndroidResourceUtil.getResourceNameByReferenceText(newName!!)
|
||||||
|
for (resField in AndroidResourceUtil.findIdFields(attr)) {
|
||||||
|
allRenames.put(resField, AndroidResourceUtil.getFieldNameByResourceName(name!!))
|
||||||
|
}
|
||||||
|
resourceManager.renameProperty(oldName, newName)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renameAttributeValue(attribute: XmlAttributeValue, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||||
|
val element1 = LazyValueResourceElementWrapper.computeLazyElement(attribute);
|
||||||
|
if (element1 == null) return
|
||||||
|
val id = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue()!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.xml.XmlFile
|
||||||
|
import com.intellij.psi.XmlElementVisitor
|
||||||
|
import com.intellij.psi.xml.XmlTag
|
||||||
|
|
||||||
|
public class IDEAndroidResourceManager(project: Project, searchPath: String?) : AndroidResourceManagerBase(project, searchPath) {
|
||||||
|
|
||||||
|
private val idToXmlAttributeCache = HashMap<String, PsiElement>()
|
||||||
|
|
||||||
|
;{
|
||||||
|
setupElementCache()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupElementCache() {
|
||||||
|
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 idPrefix = "@+id/"
|
||||||
|
val attribute = tag?.getAttribute("android:id")
|
||||||
|
val s = attribute?.getValue()
|
||||||
|
if (attribute != null && (s?.startsWith(idPrefix) ?: false)) {
|
||||||
|
idToXmlAttributeCache[s!!.replace(idPrefix, "")] = attribute
|
||||||
|
}
|
||||||
|
tag?.acceptChildren(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
override fun idToXmlAttribute(id: String): PsiElement? {
|
||||||
|
return idToXmlAttributeCache[id]
|
||||||
|
}
|
||||||
|
override fun renameXmlAttr(elem: PsiElement, newName: String) {
|
||||||
|
val xmlAttr = elem as XmlAttribute
|
||||||
|
idToXmlAttributeCache.remove(xmlAttr.getName())
|
||||||
|
idToXmlAttributeCache[newName] = xmlAttr
|
||||||
|
}
|
||||||
|
override fun renameProperty(oldName: String, newName: String) {
|
||||||
|
val oldElem = idToXmlAttributeCache[oldName]
|
||||||
|
idToXmlAttributeCache.remove(oldName)
|
||||||
|
idToXmlAttributeCache[newName] = oldElem!!
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2014 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.plugin.android
|
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlParser
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import java.util.ArrayList
|
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import org.jetbrains.jet.lang.resolve.android.AndroidWidget
|
|
||||||
import org.jetbrains.jet.lang.resolve.android.KotlinStringWriter
|
|
||||||
import com.intellij.psi.xml.XmlFile
|
|
||||||
import com.intellij.psi.XmlElementVisitor
|
|
||||||
import com.intellij.psi.xml.XmlTag
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import java.util.HashMap
|
|
||||||
|
|
||||||
class IDEAndroidUIXmlParser(val project: Project) : AndroidUIXmlParser() {
|
|
||||||
override val searchPath: String? = project.getBasePath() + "/res/layout/"
|
|
||||||
override var androidAppPackage: String = ""
|
|
||||||
|
|
||||||
val idToXmlAttributeCache = HashMap<String, PsiElement>()
|
|
||||||
|
|
||||||
private fun setupElementCache() {
|
|
||||||
for (file in getXmlLayouts(project)) {
|
|
||||||
if (file is XmlFile) {
|
|
||||||
file.accept(object : XmlElementVisitor() {
|
|
||||||
override fun visitElement(element: PsiElement) {
|
|
||||||
element.acceptChildren(this)
|
|
||||||
}
|
|
||||||
override fun visitXmlTag(tag: XmlTag?) {
|
|
||||||
val idPrefix = "@+id/"
|
|
||||||
val attribute = tag?.getAttribute("android:id")
|
|
||||||
val s = attribute?.getValue()
|
|
||||||
if (attribute != null && (s?.startsWith(idPrefix) ?: false)) {
|
|
||||||
idToXmlAttributeCache[s!!.replace(idPrefix, "")] = attribute
|
|
||||||
}
|
|
||||||
tag?.acceptChildren(this)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun idToXmlAttribute(id: String): PsiElement? {
|
|
||||||
return idToXmlAttributeCache[id]
|
|
||||||
}
|
|
||||||
|
|
||||||
override protected fun lazySetup() {
|
|
||||||
if (listenerSetUp) return
|
|
||||||
androidAppPackage = readManifest()._package
|
|
||||||
populateQueue(project)
|
|
||||||
setupElementCache()
|
|
||||||
listenerSetUp = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun parseSingleFileImpl(file: PsiFile): String {
|
|
||||||
val ids: MutableCollection<AndroidWidget> = ArrayList()
|
|
||||||
file.accept(AndroidXmlVisitor({ id, wClass -> ids.add(AndroidWidget(id, wClass)) }))
|
|
||||||
return produceKotlinProperties(KotlinStringWriter(), ids).toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun renameId(oldName: String?, newName: String?, allRenames: MutableMap<PsiElement, String>) {
|
|
||||||
for (file in getXmlLayoutFiles()) {
|
|
||||||
if (file is XmlFile) {
|
|
||||||
file.accept(object : XmlElementVisitor() {
|
|
||||||
override fun visitElement(element: PsiElement) {
|
|
||||||
element.acceptChildren(this)
|
|
||||||
}
|
|
||||||
override fun visitXmlTag(tag: XmlTag?) {
|
|
||||||
val idPrefix = "@+id/"
|
|
||||||
val attribute = tag?.getAttribute("android:id")
|
|
||||||
if (attribute != null && attribute.getValue() == idPrefix + oldName) {
|
|
||||||
allRenames[XmlAttributeValueWrapper(attribute.getValueElement()!!)] = idPrefix + newName
|
|
||||||
}
|
|
||||||
tag?.acceptChildren(this)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.plugin.android
|
||||||
|
|
||||||
|
import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import java.util.ArrayList
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import org.jetbrains.jet.lang.resolve.android.AndroidWidget
|
||||||
|
import org.jetbrains.jet.lang.resolve.android.KotlinStringWriter
|
||||||
|
import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager
|
||||||
|
|
||||||
|
class IDEAndroidUIXmlProcessor(project: Project) : AndroidUIXmlProcessor(project) {
|
||||||
|
override val searchPath: String? = project.getBasePath() + "/res/layout/"
|
||||||
|
override var androidAppPackage: String = ""
|
||||||
|
|
||||||
|
override val resourceManager: AndroidResourceManager = IDEAndroidResourceManager(project, searchPath)
|
||||||
|
|
||||||
|
override protected fun lazySetup() {
|
||||||
|
if (listenerSetUp) return
|
||||||
|
androidAppPackage = readManifest()._package
|
||||||
|
populateQueue()
|
||||||
|
listenerSetUp = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun parseSingleFileImpl(file: PsiFile): String {
|
||||||
|
val ids: MutableCollection<AndroidWidget> = ArrayList()
|
||||||
|
file.accept(AndroidXmlVisitor({ id, wClass -> ids.add(AndroidWidget(id, wClass)) }))
|
||||||
|
return produceKotlinProperties(KotlinStringWriter(), ids).toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -91,11 +91,6 @@ public class RenameKotlinPropertyProcessor : RenamePsiElementProcessor() {
|
|||||||
for (propertyMethod in propertyMethods) {
|
for (propertyMethod in propertyMethods) {
|
||||||
addRenameElements(propertyMethod, jetProperty.getName(), newName, allRenames, scope)
|
addRenameElements(propertyMethod, jetProperty.getName(), newName, allRenames, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAndroidSyntheticElement(element)) {
|
|
||||||
val parser = ServiceManager.getService(element?.getProject()!!, javaClass<AndroidUIXmlParser>())
|
|
||||||
parser?.renameId(jetProperty.getName(), newName, allRenames)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum class UsageKind {
|
private enum class UsageKind {
|
||||||
|
|||||||
Reference in New Issue
Block a user