Android Extensions refactoring
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
|||||||
org.jetbrains.kotlin.android.AndroidCommandLineProcessor
|
org.jetbrains.kotlin.android.synthetic.AndroidCommandLineProcessor
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
org.jetbrains.kotlin.android.AndroidComponentRegistrar
|
org.jetbrains.kotlin.android.synthetic.AndroidComponentRegistrar
|
||||||
+11
-10
@@ -14,14 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.android
|
package org.jetbrains.kotlin.android.synthetic
|
||||||
|
|
||||||
import com.intellij.mock.MockProject
|
import com.intellij.mock.MockProject
|
||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import com.intellij.openapi.extensions.Extensions
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
|
||||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.codegen.AndroidExpressionCodegenExtension
|
||||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||||
import org.jetbrains.kotlin.compiler.plugin.CliOption
|
import org.jetbrains.kotlin.compiler.plugin.CliOption
|
||||||
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
|
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
|
||||||
@@ -30,7 +29,10 @@ import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
|||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
||||||
import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider
|
import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.*
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.CliAndroidLayoutXmlFileManager
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
|
|
||||||
public object AndroidConfigurationKeys {
|
public object AndroidConfigurationKeys {
|
||||||
@@ -68,8 +70,8 @@ public class AndroidCommandLineProcessor : CommandLineProcessor {
|
|||||||
|
|
||||||
public class CliAndroidDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider {
|
public class CliAndroidDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider {
|
||||||
override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection<JetFile> {
|
override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection<JetFile> {
|
||||||
val parser = ServiceManager.getService(project, javaClass<AndroidUIXmlProcessor>())
|
val parser = ServiceManager.getService(project, javaClass<SyntheticFileGenerator>())
|
||||||
return parser.parseToPsi() ?: listOf()
|
return parser.getSyntheticFiles() ?: listOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,11 +83,10 @@ public class AndroidComponentRegistrar : ComponentRegistrar {
|
|||||||
val supportV4 = configuration.get(AndroidConfigurationKeys.SUPPORT_V4) ?: "false"
|
val supportV4 = configuration.get(AndroidConfigurationKeys.SUPPORT_V4) ?: "false"
|
||||||
|
|
||||||
if (androidResPath != null && androidManifest != null) {
|
if (androidResPath != null && androidManifest != null) {
|
||||||
val xmlProcessor = CliAndroidUIXmlProcessor(project, androidManifest, androidResPath)
|
val xmlProcessor = CliSyntheticFileGenerator(project, androidManifest, androidResPath, supportV4 == "true")
|
||||||
if (supportV4 == "true") xmlProcessor.supportV4 = true
|
|
||||||
|
|
||||||
project.registerService(javaClass<AndroidUIXmlProcessor>(), xmlProcessor)
|
project.registerService(javaClass<SyntheticFileGenerator>(), xmlProcessor)
|
||||||
project.registerService(javaClass<AndroidResourceManager>(), CliAndroidResourceManager(project, androidManifest, androidResPath))
|
project.registerService(javaClass<AndroidLayoutXmlFileManager>(), CliAndroidLayoutXmlFileManager(project, androidManifest, androidResPath))
|
||||||
|
|
||||||
ExternalDeclarationsProvider.registerExtension(project, CliAndroidDeclarationsProvider(project))
|
ExternalDeclarationsProvider.registerExtension(project, CliAndroidDeclarationsProvider(project))
|
||||||
ExpressionCodegenExtension.registerExtension(project, AndroidExpressionCodegenExtension())
|
ExpressionCodegenExtension.registerExtension(project, AndroidExpressionCodegenExtension())
|
||||||
+4
-1
@@ -14,9 +14,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic
|
||||||
|
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidFragment
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidResource
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidWidget
|
||||||
import org.jetbrains.kotlin.lexer.JetKeywordToken
|
import org.jetbrains.kotlin.lexer.JetKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
|
|
||||||
+4
-9
@@ -14,17 +14,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic
|
||||||
|
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
|
||||||
import com.intellij.psi.PsiField
|
|
||||||
import com.intellij.psi.PsiClass
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.util.Computable
|
import com.intellij.openapi.util.Computable
|
||||||
import com.intellij.openapi.module.ModuleServiceManager
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
|
||||||
fun isAndroidSyntheticFile(f: PsiFile?): Boolean {
|
fun isAndroidSyntheticFile(f: PsiFile?): Boolean {
|
||||||
return f?.getUserData(AndroidConst.ANDROID_USER_PACKAGE) != null
|
return f?.getUserData(AndroidConst.ANDROID_USER_PACKAGE) != null
|
||||||
@@ -32,6 +27,6 @@ fun isAndroidSyntheticFile(f: PsiFile?): Boolean {
|
|||||||
|
|
||||||
public fun isAndroidSyntheticElement(element: PsiElement?): Boolean {
|
public fun isAndroidSyntheticElement(element: PsiElement?): Boolean {
|
||||||
return isAndroidSyntheticFile(ApplicationManager.getApplication().runReadAction(Computable {
|
return isAndroidSyntheticFile(ApplicationManager.getApplication().runReadAction(Computable {
|
||||||
element?.getContainingFile()
|
element?.containingFile
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
+2
-2
@@ -14,10 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic
|
||||||
|
|
||||||
import org.xml.sax.helpers.DefaultHandler
|
|
||||||
import org.xml.sax.Attributes
|
import org.xml.sax.Attributes
|
||||||
|
import org.xml.sax.helpers.DefaultHandler
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
|
||||||
class AndroidXmlHandler(private val elementCallback: (String, String) -> Unit) : DefaultHandler() {
|
class AndroidXmlHandler(private val elementCallback: (String, String) -> Unit) : DefaultHandler() {
|
||||||
+1
-2
@@ -14,11 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic
|
||||||
|
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
|
||||||
open class Context(val buffer: StringBuffer = StringBuffer(), private var indentDepth: Int = 0) {
|
open class Context(val buffer: StringBuffer = StringBuffer(), private var indentDepth: Int = 0) {
|
||||||
open class InvalidIndent(num: Int) : RuntimeException("Indentation level < 0: $num")
|
open class InvalidIndent(num: Int) : RuntimeException("Indentation level < 0: $num")
|
||||||
|
|
||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic
|
||||||
|
|
||||||
interface KotlinWriter {
|
interface KotlinWriter {
|
||||||
fun toStringBuffer(): StringBuffer
|
fun toStringBuffer(): StringBuffer
|
||||||
+2
-7
@@ -14,29 +14,24 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.android
|
package org.jetbrains.kotlin.android.synthetic.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
|
||||||
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidConst
|
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
|
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
|
||||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassReceiver
|
|
||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
import org.jetbrains.kotlin.types.Flexibility
|
|
||||||
import org.jetbrains.kotlin.types.lowerIfFlexible
|
import org.jetbrains.kotlin.types.lowerIfFlexible
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE
|
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE
|
||||||
+28
-22
@@ -14,21 +14,20 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic.res
|
||||||
|
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.openapi.module.ModuleServiceManager
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.openapi.util.*
|
|
||||||
import com.intellij.openapi.vfs.impl.*
|
|
||||||
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
|
import org.jetbrains.kotlin.psi.JetProperty
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
public abstract class AndroidResourceManager(val project: Project) {
|
public abstract class AndroidLayoutXmlFileManager(val project: Project) {
|
||||||
|
|
||||||
public abstract val androidModuleInfo: AndroidModuleInfo?
|
public abstract val androidModuleInfo: AndroidModuleInfo?
|
||||||
|
|
||||||
@@ -42,9 +41,9 @@ public abstract class AndroidResourceManager(val project: Project) {
|
|||||||
|
|
||||||
fun VirtualFile.getAllChildren(): List<VirtualFile> {
|
fun VirtualFile.getAllChildren(): List<VirtualFile> {
|
||||||
val allChildren = arrayListOf<VirtualFile>()
|
val allChildren = arrayListOf<VirtualFile>()
|
||||||
val currentChildren = getChildren() ?: emptyArray()
|
val currentChildren = children ?: emptyArray()
|
||||||
for (child in currentChildren) {
|
for (child in currentChildren) {
|
||||||
if (child.isDirectory()) {
|
if (child.isDirectory) {
|
||||||
allChildren.addAll(child.getAllChildren())
|
allChildren.addAll(child.getAllChildren())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -57,20 +56,27 @@ public abstract class AndroidResourceManager(val project: Project) {
|
|||||||
val resDirectories = info.resDirectories.map { fileManager.findFileByUrl("file://$it") }
|
val resDirectories = info.resDirectories.map { fileManager.findFileByUrl("file://$it") }
|
||||||
val allChildren = resDirectories.flatMap { it?.getAllChildren() ?: listOf() }
|
val allChildren = resDirectories.flatMap { it?.getAllChildren() ?: listOf() }
|
||||||
|
|
||||||
return allChildren
|
val allLayoutFiles = allChildren.filter { it.parent.name.startsWith("layout") && it.name.toLowerCase().endsWith(".xml") }
|
||||||
.filter { it.getParent().getName().startsWith("layout") && it.getName().toLowerCase().endsWith(".xml") }
|
val allLayoutPsiFiles = allLayoutFiles.fold(ArrayList<PsiFile>(allLayoutFiles.size())) { list, file ->
|
||||||
.map { psiManager.findFile(it) }
|
val psiFile = psiManager.findFile(file)
|
||||||
.filterNotNull()
|
if (psiFile != null && psiFile.parent != null) {
|
||||||
.groupBy { it.getName().substringBeforeLast('.') }
|
list += psiFile
|
||||||
.mapValues { it.getValue().sortBy { it.getParent()!!.getName().length() } }
|
}
|
||||||
|
list
|
||||||
|
}
|
||||||
|
|
||||||
|
val layoutNameToXmls = allLayoutPsiFiles
|
||||||
|
.groupBy { it.name.substringBeforeLast('.') }
|
||||||
|
.mapValues { it.getValue().sortBy { it.parent!!.name.length() } }
|
||||||
|
|
||||||
|
return layoutNameToXmls
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
public fun getInstance(module: Module): AndroidResourceManager {
|
public fun getInstance(module: Module): AndroidLayoutXmlFileManager {
|
||||||
val service = ModuleServiceManager.getService(module, javaClass<AndroidResourceManager>())
|
val service = ModuleServiceManager.getService(module, javaClass<AndroidLayoutXmlFileManager>())
|
||||||
return service ?: module.getComponent(javaClass<AndroidResourceManager>())!!
|
return service ?: module.getComponent(javaClass<AndroidLayoutXmlFileManager>())!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+5
-4
@@ -14,9 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic.res
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.toMap
|
||||||
import org.xml.sax.Attributes
|
import org.xml.sax.Attributes
|
||||||
import org.xml.sax.helpers.DefaultHandler
|
import org.xml.sax.helpers.DefaultHandler
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -24,11 +25,11 @@ import java.io.FileInputStream
|
|||||||
import javax.xml.parsers.SAXParser
|
import javax.xml.parsers.SAXParser
|
||||||
import javax.xml.parsers.SAXParserFactory
|
import javax.xml.parsers.SAXParserFactory
|
||||||
|
|
||||||
public class CliAndroidResourceManager(
|
public class CliAndroidLayoutXmlFileManager(
|
||||||
project: Project,
|
project: Project,
|
||||||
private val manifestPath: String,
|
private val manifestPath: String,
|
||||||
private val resDirectories: List<String>
|
private val resDirectories: List<String>
|
||||||
) : AndroidResourceManager(project) {
|
) : AndroidLayoutXmlFileManager(project) {
|
||||||
|
|
||||||
override val androidModuleInfo by lazy {
|
override val androidModuleInfo by lazy {
|
||||||
AndroidModuleInfo(getApplicationPackage(manifestPath), resDirectories)
|
AndroidModuleInfo(getApplicationPackage(manifestPath), resDirectories)
|
||||||
@@ -60,7 +61,7 @@ public class CliAndroidResourceManager(
|
|||||||
return applicationPackage
|
return applicationPackage
|
||||||
}
|
}
|
||||||
catch (e: Exception) {
|
catch (e: Exception) {
|
||||||
throw AndroidUIXmlProcessor.NoAndroidManifestFound()
|
throw SyntheticFileGenerator.NoAndroidManifestFound()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+19
-11
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic.res
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.ModificationTracker
|
import com.intellij.openapi.util.ModificationTracker
|
||||||
@@ -22,33 +22,41 @@ import com.intellij.psi.PsiFile
|
|||||||
import com.intellij.psi.util.CachedValue
|
import com.intellij.psi.util.CachedValue
|
||||||
import com.intellij.psi.util.CachedValueProvider.Result
|
import com.intellij.psi.util.CachedValueProvider.Result
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.AndroidXmlHandler
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.parseAndroidResource
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
public class CliAndroidUIXmlProcessor(
|
public class CliSyntheticFileGenerator(
|
||||||
project: Project,
|
project: Project,
|
||||||
private val manifestPath: String,
|
private val manifestPath: String,
|
||||||
private val resDirectories: List<String>
|
private val resDirectories: List<String>,
|
||||||
) : AndroidUIXmlProcessor(project) {
|
private val supportV4: Boolean
|
||||||
|
) : SyntheticFileGenerator(project) {
|
||||||
|
|
||||||
override val resourceManager: CliAndroidResourceManager by lazy {
|
override fun supportV4(): Boolean {
|
||||||
CliAndroidResourceManager(project, manifestPath, resDirectories)
|
return supportV4
|
||||||
|
}
|
||||||
|
|
||||||
|
override val layoutXmlFileManager: CliAndroidLayoutXmlFileManager by Delegates.lazy {
|
||||||
|
CliAndroidLayoutXmlFileManager(project, manifestPath, resDirectories)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val cachedSources: CachedValue<List<AndroidSyntheticFile>> by lazy {
|
override val cachedSources: CachedValue<List<AndroidSyntheticFile>> by lazy {
|
||||||
cachedValue {
|
cachedValue {
|
||||||
Result.create(parse(), ModificationTracker.NEVER_CHANGED)
|
Result.create(generateSyntheticFiles(), ModificationTracker.NEVER_CHANGED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun parseLayout(files: List<PsiFile>): List<AndroidResource> {
|
override fun extractLayoutResources(files: List<PsiFile>): List<AndroidResource> {
|
||||||
val resources = arrayListOf<AndroidResource>()
|
val resources = arrayListOf<AndroidResource>()
|
||||||
val handler = AndroidXmlHandler { id, widgetType -> resources.add(parseAndroidResource(id, widgetType)) }
|
val handler = AndroidXmlHandler { id, widgetType -> resources.add(parseAndroidResource(id, widgetType)) }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (file in files) {
|
for (file in files) {
|
||||||
val inputStream = ByteArrayInputStream(file.virtualFile.contentsToByteArray())
|
val inputStream = ByteArrayInputStream(file.getVirtualFile().contentsToByteArray())
|
||||||
resourceManager.saxParser.parse(inputStream, handler)
|
layoutXmlFileManager.saxParser.parse(inputStream, handler)
|
||||||
}
|
}
|
||||||
return removeDuplicates(resources)
|
return filterDuplicates(resources)
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
LOG.error(e)
|
LOG.error(e)
|
||||||
+20
-18
@@ -14,39 +14,38 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic.res
|
||||||
|
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
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.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.psi.util.CachedValue
|
import com.intellij.psi.util.CachedValue
|
||||||
import com.intellij.psi.util.CachedValueProvider
|
|
||||||
import com.intellij.psi.util.CachedValueProvider.Result
|
import com.intellij.psi.util.CachedValueProvider.Result
|
||||||
import com.intellij.psi.util.CachedValuesManager
|
import com.intellij.psi.util.CachedValuesManager
|
||||||
import com.intellij.testFramework.LightVirtualFile
|
import com.intellij.testFramework.LightVirtualFile
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.KotlinStringWriter
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.escapeAndroidIdentifier
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import org.jetbrains.kotlin.types.Flexibility
|
import org.jetbrains.kotlin.types.Flexibility
|
||||||
|
|
||||||
public class AndroidSyntheticFile(val name: String, val contents: String)
|
public class AndroidSyntheticFile(val name: String, val contents: String)
|
||||||
|
|
||||||
public abstract class AndroidUIXmlProcessor(protected val project: Project) {
|
public abstract class SyntheticFileGenerator(protected val project: Project) {
|
||||||
|
|
||||||
public class NoAndroidManifestFound : Exception("No android manifest file found in project root")
|
public class NoAndroidManifestFound : Exception("No android manifest file found in project root")
|
||||||
|
|
||||||
protected val LOG: Logger = Logger.getInstance(javaClass)
|
protected val LOG: Logger = Logger.getInstance(javaClass)
|
||||||
|
|
||||||
public abstract val resourceManager: AndroidResourceManager
|
public abstract val layoutXmlFileManager: AndroidLayoutXmlFileManager
|
||||||
|
|
||||||
protected abstract val cachedSources: CachedValue<List<AndroidSyntheticFile>>
|
protected abstract val cachedSources: CachedValue<List<AndroidSyntheticFile>>
|
||||||
|
|
||||||
//MAKE CONSTANT (or abstract)
|
|
||||||
var supportV4 = false
|
|
||||||
|
|
||||||
private val cachedJetFiles: CachedValue<List<JetFile>> by lazy {
|
private val cachedJetFiles: CachedValue<List<JetFile>> by lazy {
|
||||||
cachedValue {
|
cachedValue {
|
||||||
val psiManager = PsiManager.getInstance(project)
|
val psiManager = PsiManager.getInstance(project)
|
||||||
val applicationPackage = resourceManager.androidModuleInfo?.applicationPackage
|
val applicationPackage = layoutXmlFileManager.androidModuleInfo?.applicationPackage
|
||||||
|
|
||||||
val jetFiles = cachedSources.value.mapIndexed { index, syntheticFile ->
|
val jetFiles = cachedSources.value.mapIndexed { index, syntheticFile ->
|
||||||
val fileName = AndroidConst.SYNTHETIC_FILENAME_PREFIX + syntheticFile.name + ".kt"
|
val fileName = AndroidConst.SYNTHETIC_FILENAME_PREFIX + syntheticFile.name + ".kt"
|
||||||
@@ -62,15 +61,18 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun parse(generateCommonFiles: Boolean = true): List<AndroidSyntheticFile> {
|
protected abstract fun supportV4(): Boolean
|
||||||
|
|
||||||
|
public fun generateSyntheticFiles(generateCommonFiles: Boolean = true): List<AndroidSyntheticFile> {
|
||||||
val commonFiles = if (generateCommonFiles) {
|
val commonFiles = if (generateCommonFiles) {
|
||||||
val clearCacheFile = renderSyntheticFile("clearCache") {
|
val renderSyntheticFile = renderSyntheticFile("clearCache") {
|
||||||
writePackage(AndroidConst.SYNTHETIC_PACKAGE)
|
writePackage(AndroidConst.SYNTHETIC_PACKAGE)
|
||||||
writeAndroidImports()
|
writeAndroidImports()
|
||||||
writeClearCacheFunction(AndroidConst.ACTIVITY_FQNAME)
|
writeClearCacheFunction(AndroidConst.ACTIVITY_FQNAME)
|
||||||
writeClearCacheFunction(AndroidConst.FRAGMENT_FQNAME)
|
writeClearCacheFunction(AndroidConst.FRAGMENT_FQNAME)
|
||||||
if (supportV4) writeClearCacheFunction(AndroidConst.SUPPORT_FRAGMENT_FQNAME)
|
if (supportV4()) writeClearCacheFunction(AndroidConst.SUPPORT_FRAGMENT_FQNAME)
|
||||||
}
|
}
|
||||||
|
val clearCacheFile = renderSyntheticFile
|
||||||
|
|
||||||
listOf(clearCacheFile,
|
listOf(clearCacheFile,
|
||||||
FLEXIBLE_TYPE_FILE,
|
FLEXIBLE_TYPE_FILE,
|
||||||
@@ -79,9 +81,9 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) {
|
|||||||
FAKE_SUPPORT_V4_WIDGET_FILE)
|
FAKE_SUPPORT_V4_WIDGET_FILE)
|
||||||
} else listOf()
|
} else listOf()
|
||||||
|
|
||||||
return resourceManager.getLayoutXmlFiles().flatMap { entry ->
|
return layoutXmlFileManager.getLayoutXmlFiles().flatMap { entry ->
|
||||||
val files = entry.getValue()
|
val files = entry.getValue()
|
||||||
val resources = parseLayout(files)
|
val resources = extractLayoutResources(files)
|
||||||
|
|
||||||
val layoutName = files[0].name.substringBefore('.')
|
val layoutName = files[0].name.substringBefore('.')
|
||||||
|
|
||||||
@@ -92,15 +94,15 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) {
|
|||||||
}.filterNotNull() + commonFiles
|
}.filterNotNull() + commonFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun parseToPsi(): List<JetFile>? = cachedJetFiles.value
|
public fun getSyntheticFiles(): List<JetFile>? = cachedJetFiles.value
|
||||||
|
|
||||||
protected abstract fun parseLayout(files: List<PsiFile>): List<AndroidResource>
|
protected abstract fun extractLayoutResources(files: List<PsiFile>): List<AndroidResource>
|
||||||
|
|
||||||
private fun renderMainLayoutFile(layoutName: String, resources: List<AndroidResource>): AndroidSyntheticFile {
|
private fun renderMainLayoutFile(layoutName: String, resources: List<AndroidResource>): AndroidSyntheticFile {
|
||||||
return renderLayoutFile(layoutName + AndroidConst.LAYOUT_POSTFIX,
|
return renderLayoutFile(layoutName + AndroidConst.LAYOUT_POSTFIX,
|
||||||
escapeAndroidIdentifier(layoutName), resources) {
|
escapeAndroidIdentifier(layoutName), resources) {
|
||||||
val properties = it.mainProperties.toArrayList()
|
val properties = it.mainProperties.toArrayList()
|
||||||
if (supportV4) properties.addAll(it.mainPropertiesForSupportV4)
|
if (supportV4()) properties.addAll(it.mainPropertiesForSupportV4)
|
||||||
properties
|
properties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +155,7 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) {
|
|||||||
writeText("public fun $receiver.${AndroidConst.CLEAR_FUNCTION_NAME}() {}\n")
|
writeText("public fun $receiver.${AndroidConst.CLEAR_FUNCTION_NAME}() {}\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun <T> cachedValue(result: () -> CachedValueProvider.Result<T>): CachedValue<T> {
|
protected fun <T> cachedValue(result: () -> Result<T>): CachedValue<T> {
|
||||||
return CachedValuesManager.getManager(project).createCachedValue(result, false)
|
return CachedValuesManager.getManager(project).createCachedValue(result, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +163,7 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) {
|
|||||||
return fqName.startsWith(AndroidConst.SUPPORT_V4_PACKAGE)
|
return fqName.startsWith(AndroidConst.SUPPORT_V4_PACKAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun removeDuplicates(resources: List<AndroidResource>): List<AndroidResource> {
|
protected fun filterDuplicates(resources: List<AndroidResource>): List<AndroidResource> {
|
||||||
val resourceMap = linkedMapOf<String, AndroidResource>()
|
val resourceMap = linkedMapOf<String, AndroidResource>()
|
||||||
val resourcesToExclude = hashSetOf<String>()
|
val resourcesToExclude = hashSetOf<String>()
|
||||||
|
|
||||||
+4
-2
@@ -14,7 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.lang.resolve.android
|
package org.jetbrains.kotlin.android.synthetic.res
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||||
|
|
||||||
public data class AndroidModuleInfo(val applicationPackage: String, resDirectories: List<String>) {
|
public data class AndroidModuleInfo(val applicationPackage: String, resDirectories: List<String>) {
|
||||||
val resDirectories = resDirectories.sort()
|
val resDirectories = resDirectories.sort()
|
||||||
@@ -40,7 +42,7 @@ public class AndroidWidget(id: String, override val className: String) : Android
|
|||||||
|
|
||||||
val MAIN_PROPERTIES_SUPPORT_V4 = listOf(AndroidConst.SUPPORT_FRAGMENT_FQNAME to "getView().findViewById(0)")
|
val MAIN_PROPERTIES_SUPPORT_V4 = listOf(AndroidConst.SUPPORT_FRAGMENT_FQNAME to "getView().findViewById(0)")
|
||||||
|
|
||||||
val VIEW_PROPERTIES = listOf("android.view.View" to "findViewById(0)")
|
val VIEW_PROPERTIES = listOf(AndroidConst.VIEW_FQNAME to "findViewById(0)")
|
||||||
}
|
}
|
||||||
|
|
||||||
override val mainProperties = MAIN_PROPERTIES
|
override val mainProperties = MAIN_PROPERTIES
|
||||||
+6
-6
@@ -23,9 +23,9 @@ import org.jetbrains.kotlin.test.JetTestUtils
|
|||||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||||
import org.jetbrains.kotlin.test.TestJdkKind
|
import org.jetbrains.kotlin.test.TestJdkKind
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidConst
|
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.CliAndroidUIXmlProcessor
|
import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor
|
import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() {
|
public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() {
|
||||||
@@ -35,10 +35,10 @@ public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() {
|
|||||||
|
|
||||||
val jetCoreEnvironment = getEnvironment()
|
val jetCoreEnvironment = getEnvironment()
|
||||||
val layoutPaths = getResPaths(path)
|
val layoutPaths = getResPaths(path)
|
||||||
val parser = CliAndroidUIXmlProcessor(jetCoreEnvironment.project, path + "AndroidManifest.xml", layoutPaths)
|
val parser = CliSyntheticFileGenerator(jetCoreEnvironment.project, path + "AndroidManifest.xml", layoutPaths)
|
||||||
parser.supportV4 = testDirectory.name.startsWith("support")
|
parser.supportV4 = testDirectory.name.startsWith("support")
|
||||||
|
|
||||||
val actual = parser.parse(false).toMap { it.name }
|
val actual = parser.generateSyntheticFiles(false).toMap { it.name }
|
||||||
|
|
||||||
val expectedLayoutFiles = testDirectory.listFiles {
|
val expectedLayoutFiles = testDirectory.listFiles {
|
||||||
it.isFile() && it.name.endsWith(".kt")
|
it.isFile() && it.name.endsWith(".kt")
|
||||||
@@ -58,7 +58,7 @@ public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() {
|
|||||||
doTest(path)
|
doTest(path)
|
||||||
fail("NoAndroidManifestFound not thrown")
|
fail("NoAndroidManifestFound not thrown")
|
||||||
}
|
}
|
||||||
catch (e: AndroidUIXmlProcessor.NoAndroidManifestFound) {
|
catch (e: SyntheticFileGenerator.NoAndroidManifestFound) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -20,16 +20,16 @@ import com.intellij.openapi.extensions.Extensions
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
||||||
import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider
|
import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider
|
||||||
import org.jetbrains.kotlin.android.AndroidConfigurationKeys
|
import org.jetbrains.kotlin.android.synthetic.AndroidConfigurationKeys
|
||||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||||
import org.jetbrains.kotlin.android.AndroidExpressionCodegenExtension
|
import org.jetbrains.kotlin.android.synthetic.codegen.AndroidExpressionCodegenExtension
|
||||||
import com.intellij.testFramework.UsefulTestCase
|
import com.intellij.testFramework.UsefulTestCase
|
||||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.CliAndroidUIXmlProcessor
|
import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
private class AndroidTestExternalDeclarationsProvider(
|
private class AndroidTestExternalDeclarationsProvider(
|
||||||
@@ -39,9 +39,9 @@ private class AndroidTestExternalDeclarationsProvider(
|
|||||||
val supportV4: Boolean
|
val supportV4: Boolean
|
||||||
) : ExternalDeclarationsProvider {
|
) : ExternalDeclarationsProvider {
|
||||||
override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection<JetFile> {
|
override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection<JetFile> {
|
||||||
val parser = CliAndroidUIXmlProcessor(project, manifestPath, resPaths)
|
val parser = CliSyntheticFileGenerator(project, manifestPath, resPaths)
|
||||||
parser.supportV4 = supportV4
|
parser.supportV4 = supportV4
|
||||||
return parser.parseToPsi() ?: listOf()
|
return parser.getSyntheticFiles() ?: listOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,22 +12,22 @@
|
|||||||
<depends optional="false">org.jetbrains.android</depends>
|
<depends optional="false">org.jetbrains.android</depends>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<moduleService serviceInterface="org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor"
|
<moduleService serviceInterface="org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator"
|
||||||
serviceImplementation="org.jetbrains.kotlin.plugin.android.IDEAndroidUIXmlProcessor"/>
|
serviceImplementation="org.jetbrains.kotlin.android.synthetic.idea.res.IDESyntheticFileGenerator"/>
|
||||||
<moduleService serviceInterface="org.jetbrains.kotlin.lang.resolve.android.AndroidResourceManager"
|
<moduleService serviceInterface="org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager"
|
||||||
serviceImplementation="org.jetbrains.kotlin.plugin.android.IDEAndroidResourceManager"/>
|
serviceImplementation="org.jetbrains.kotlin.android.synthetic.idea.res.IDEAndroidLayoutXmlFileManager"/>
|
||||||
<compileServer.plugin classpath="jps/kotlin-android-extensions-jps.jar;android-compiler-plugin.jar"/>
|
<compileServer.plugin classpath="jps/kotlin-android-extensions-jps.jar;android-compiler-plugin.jar"/>
|
||||||
<gotoDeclarationHandler implementation="org.jetbrains.kotlin.plugin.android.AndroidGotoDeclarationHandler"/>
|
<gotoDeclarationHandler implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidGotoDeclarationHandler"/>
|
||||||
<psi.treeChangePreprocessor implementation="org.jetbrains.kotlin.plugin.android.AndroidPsiTreeChangePreprocessor"/>
|
<psi.treeChangePreprocessor implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidPsiTreeChangePreprocessor"/>
|
||||||
<renamePsiElementProcessor id="KotlinAndroidSyntheticProperty"
|
<renamePsiElementProcessor id="KotlinAndroidSyntheticProperty"
|
||||||
implementation="org.jetbrains.kotlin.plugin.android.AndroidRenameProcessor"
|
implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidRenameProcessor"
|
||||||
order="first"/>
|
order="first"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||||
<externalDeclarationsProvider implementation="org.jetbrains.kotlin.plugin.android.IDEAndroidExternalDeclarationsProvider"/>
|
<externalDeclarationsProvider implementation="org.jetbrains.kotlin.android.synthetic.idea.IDEAndroidExternalDeclarationsProvider"/>
|
||||||
<expressionCodegenExtension implementation="org.jetbrains.kotlin.android.AndroidExpressionCodegenExtension"/>
|
<expressionCodegenExtension implementation="org.jetbrains.kotlin.android.synthetic.codegen.AndroidExpressionCodegenExtension"/>
|
||||||
<findUsagesHandlerDecorator implementation="org.jetbrains.kotlin.plugin.android.AndroidFindUsageHandlerDecorator"/>
|
<findUsagesHandlerDecorator implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidFindUsageHandlerDecorator"/>
|
||||||
<simpleNameReferenceExtension implementation="org.jetbrains.kotlin.plugin.android.AndroidSimpleNameReferenceExtension"/>
|
<simpleNameReferenceExtension implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidSimpleNameReferenceExtension"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
|||||||
+20
-16
@@ -14,28 +14,27 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android
|
package org.jetbrains.kotlin.android.synthetic.idea
|
||||||
|
|
||||||
import com.intellij.find.findUsages.FindUsagesHandler
|
import com.intellij.find.findUsages.FindUsagesHandler
|
||||||
|
import com.intellij.find.findUsages.FindUsagesOptions
|
||||||
|
import com.intellij.find.findUsages.JavaVariableFindUsagesOptions
|
||||||
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.module.ModuleServiceManager
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.xml.XmlAttribute
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import com.intellij.find.findUsages.FindUsagesOptions
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
|
||||||
import com.intellij.psi.xml.XmlAttribute
|
|
||||||
import org.jetbrains.android.util.AndroidResourceUtil
|
import org.jetbrains.android.util.AndroidResourceUtil
|
||||||
import java.util.ArrayList
|
import org.jetbrains.kotlin.android.synthetic.isAndroidSyntheticElement
|
||||||
import com.intellij.find.findUsages.JavaVariableFindUsagesOptions
|
import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator
|
||||||
import com.intellij.openapi.module.ModuleServiceManager
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo
|
import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo
|
import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo
|
||||||
import org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator
|
import org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator
|
||||||
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
||||||
import org.jetbrains.kotlin.psi.JetProperty
|
import org.jetbrains.kotlin.psi.JetProperty
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import java.util.ArrayList
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.isAndroidSyntheticElement
|
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor
|
|
||||||
|
|
||||||
class AndroidFindUsageHandlerDecorator : KotlinFindUsagesHandlerDecorator {
|
class AndroidFindUsageHandlerDecorator : KotlinFindUsagesHandlerDecorator {
|
||||||
override fun decorateHandler(element: PsiElement, forHighlightUsages: Boolean, delegate: FindUsagesHandler): FindUsagesHandler {
|
override fun decorateHandler(element: PsiElement, forHighlightUsages: Boolean, delegate: FindUsagesHandler): FindUsagesHandler {
|
||||||
@@ -56,9 +55,9 @@ class AndroidFindMemberUsagesHandler(
|
|||||||
|
|
||||||
val property = declaration as JetProperty
|
val property = declaration as JetProperty
|
||||||
val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements()
|
val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements()
|
||||||
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<AndroidUIXmlProcessor>())
|
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<SyntheticFileGenerator>())
|
||||||
|
|
||||||
val psiElements = parser?.resourceManager?.propertyToXmlAttributes(property)
|
val psiElements = parser?.layoutXmlFileManager?.propertyToXmlAttributes(property)
|
||||||
val valueElements = psiElements?.map { (it as? XmlAttribute)?.getValueElement() as? PsiElement }?.filterNotNull()
|
val valueElements = psiElements?.map { (it as? XmlAttribute)?.getValueElement() as? PsiElement }?.filterNotNull()
|
||||||
if (valueElements != null && valueElements.isNotEmpty()) return valueElements.toTypedArray()
|
if (valueElements != null && valueElements.isNotEmpty()) return valueElements.toTypedArray()
|
||||||
|
|
||||||
@@ -74,9 +73,9 @@ class AndroidFindMemberUsagesHandler(
|
|||||||
|
|
||||||
val property = declaration as JetProperty
|
val property = declaration as JetProperty
|
||||||
val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements()
|
val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements()
|
||||||
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<AndroidUIXmlProcessor>())
|
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<SyntheticFileGenerator>())
|
||||||
|
|
||||||
val psiElements = parser?.resourceManager?.propertyToXmlAttributes(property) ?: listOf()
|
val psiElements = parser?.layoutXmlFileManager?.propertyToXmlAttributes(property) ?: listOf()
|
||||||
|
|
||||||
val res = ArrayList<PsiElement>()
|
val res = ArrayList<PsiElement>()
|
||||||
for (psiElement in psiElements) {
|
for (psiElement in psiElements) {
|
||||||
@@ -97,7 +96,7 @@ class AndroidFindMemberUsagesHandler(
|
|||||||
override fun processElementUsages(element: PsiElement, processor: Processor<UsageInfo>, options: FindUsagesOptions): Boolean {
|
override fun processElementUsages(element: PsiElement, processor: Processor<UsageInfo>, options: FindUsagesOptions): Boolean {
|
||||||
assert(isAndroidSyntheticElement(declaration))
|
assert(isAndroidSyntheticElement(declaration))
|
||||||
|
|
||||||
val findUsagesOptions = JavaVariableFindUsagesOptions(runReadAction { element.getProject() })
|
val findUsagesOptions = JavaVariableFindUsagesOptions(runReadAction { element.project })
|
||||||
findUsagesOptions.isSearchForTextOccurrences = false
|
findUsagesOptions.isSearchForTextOccurrences = false
|
||||||
findUsagesOptions.isSkipImportStatements = true
|
findUsagesOptions.isSkipImportStatements = true
|
||||||
findUsagesOptions.isUsages = true
|
findUsagesOptions.isUsages = true
|
||||||
@@ -105,4 +104,9 @@ class AndroidFindMemberUsagesHandler(
|
|||||||
findUsagesOptions.isWriteAccess = true
|
findUsagesOptions.isWriteAccess = true
|
||||||
return super.processElementUsages(element, processor, findUsagesOptions)
|
return super.processElementUsages(element, processor, findUsagesOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Android extensions plugin has it's own runtime -> different function classes
|
||||||
|
private fun runReadAction<T>(action: () -> T): T {
|
||||||
|
return ApplicationManager.getApplication().runReadAction<T>(action)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+13
-13
@@ -14,21 +14,21 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android
|
package org.jetbrains.kotlin.android.synthetic.idea
|
||||||
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo
|
|
||||||
import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler
|
import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.openapi.editor.Editor
|
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
|
||||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
|
||||||
import org.jetbrains.kotlin.psi.JetProperty
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo
|
|
||||||
import com.intellij.psi.xml.XmlAttribute
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.module.ModuleServiceManager
|
import com.intellij.openapi.module.ModuleServiceManager
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
|
import com.intellij.psi.xml.XmlAttribute
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo
|
||||||
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||||
|
import org.jetbrains.kotlin.psi.JetProperty
|
||||||
|
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||||
|
|
||||||
public class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
|
public class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@ public class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
|
|||||||
val moduleInfo = sourceElement.getModuleInfo()
|
val moduleInfo = sourceElement.getModuleInfo()
|
||||||
if (moduleInfo !is ModuleSourceInfo) return null
|
if (moduleInfo !is ModuleSourceInfo) return null
|
||||||
|
|
||||||
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<AndroidUIXmlProcessor>())!!
|
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<SyntheticFileGenerator>())!!
|
||||||
val psiElements = parser.resourceManager.propertyToXmlAttributes(property)
|
val psiElements = parser.layoutXmlFileManager.propertyToXmlAttributes(property)
|
||||||
val valueElements = psiElements.map { (it as? XmlAttribute)?.getValueElement() as? PsiElement }.filterNotNull()
|
val valueElements = psiElements.map { (it as? XmlAttribute)?.getValueElement() as? PsiElement }.filterNotNull()
|
||||||
if (valueElements.isNotEmpty()) return valueElements.toTypedArray()
|
if (valueElements.isNotEmpty()) return valueElements.toTypedArray()
|
||||||
}
|
}
|
||||||
+4
-4
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android
|
package org.jetbrains.kotlin.android.synthetic.idea
|
||||||
|
|
||||||
import com.intellij.ide.highlighter.XmlFileType
|
import com.intellij.ide.highlighter.XmlFileType
|
||||||
import com.intellij.openapi.roots.ProjectRootManager
|
import com.intellij.openapi.roots.ProjectRootManager
|
||||||
@@ -25,7 +25,7 @@ import com.intellij.psi.PsiFile
|
|||||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl
|
import com.intellij.psi.impl.PsiTreeChangeEventImpl
|
||||||
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
||||||
import com.intellij.psi.xml.XmlFile
|
import com.intellij.psi.xml.XmlFile
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidResourceManager
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager
|
||||||
|
|
||||||
public class AndroidPsiTreeChangePreprocessor : PsiTreeChangePreprocessor, SimpleModificationTracker() {
|
public class AndroidPsiTreeChangePreprocessor : PsiTreeChangePreprocessor, SimpleModificationTracker() {
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ public class AndroidPsiTreeChangePreprocessor : PsiTreeChangePreprocessor, Simpl
|
|||||||
val projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex()
|
val projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex()
|
||||||
val module = projectFileIndex.getModuleForFile(file.getVirtualFile())
|
val module = projectFileIndex.getModuleForFile(file.getVirtualFile())
|
||||||
if (module != null) {
|
if (module != null) {
|
||||||
val resourceManager = AndroidResourceManager.getInstance(module)
|
val resourceManager = AndroidLayoutXmlFileManager.getInstance(module)
|
||||||
val resDirectories = resourceManager.getModuleResDirectories()
|
val resDirectories = resourceManager.getModuleResDirectories()
|
||||||
val baseDirectory = file.getParent()?.getParent()?.getVirtualFile()
|
val baseDirectory = file.getParent()?.getParent()?.getVirtualFile()
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ public class AndroidPsiTreeChangePreprocessor : PsiTreeChangePreprocessor, Simpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AndroidResourceManager.getModuleResDirectories(): List<VirtualFile> {
|
private fun AndroidLayoutXmlFileManager.getModuleResDirectories(): List<VirtualFile> {
|
||||||
val info = androidModuleInfo ?: return listOf()
|
val info = androidModuleInfo ?: return listOf()
|
||||||
|
|
||||||
val fileManager = VirtualFileManager.getInstance()
|
val fileManager = VirtualFileManager.getInstance()
|
||||||
+29
-32
@@ -14,34 +14,31 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android
|
package org.jetbrains.kotlin.android.synthetic.idea
|
||||||
|
|
||||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo
|
|
||||||
import org.jetbrains.kotlin.psi.moduleInfo
|
|
||||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.psi.JetProperty
|
|
||||||
import com.intellij.psi.xml.XmlAttributeValue
|
|
||||||
import com.intellij.psi.PsiField
|
|
||||||
import com.intellij.psi.PsiClass
|
|
||||||
import com.intellij.openapi.module.Module
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo
|
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
|
||||||
import com.intellij.psi.search.SearchScope
|
|
||||||
import com.intellij.psi.impl.light.LightElement
|
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor
|
|
||||||
import com.intellij.psi.xml.XmlAttribute
|
|
||||||
import org.jetbrains.kotlin.lang.resolve.android
|
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidConst
|
|
||||||
import com.intellij.openapi.module.ModuleServiceManager
|
|
||||||
import org.jetbrains.android.util.AndroidResourceUtil
|
|
||||||
import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper
|
|
||||||
import com.intellij.openapi.module.ModuleUtilCore
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.isAndroidSyntheticElement
|
import com.intellij.openapi.module.Module
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.nameToIdDeclaration
|
import com.intellij.openapi.module.ModuleServiceManager
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.idToName
|
import com.intellij.openapi.module.ModuleUtilCore
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiField
|
||||||
|
import com.intellij.psi.impl.light.LightElement
|
||||||
|
import com.intellij.psi.search.SearchScope
|
||||||
|
import com.intellij.psi.xml.XmlAttribute
|
||||||
|
import com.intellij.psi.xml.XmlAttributeValue
|
||||||
|
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
||||||
|
import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper
|
||||||
|
import org.jetbrains.android.util.AndroidResourceUtil
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.idToName
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.isAndroidSyntheticElement
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.nameToIdDeclaration
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator
|
||||||
|
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo
|
||||||
|
import org.jetbrains.kotlin.psi.JetProperty
|
||||||
|
|
||||||
public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
||||||
|
|
||||||
@@ -93,8 +90,8 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
|||||||
) {
|
) {
|
||||||
val module = jetProperty.getModule() ?: return
|
val module = jetProperty.getModule() ?: return
|
||||||
|
|
||||||
val processor = ModuleServiceManager.getService(module, javaClass<AndroidUIXmlProcessor>())!!
|
val processor = ModuleServiceManager.getService(module, javaClass<SyntheticFileGenerator>())!!
|
||||||
val resourceManager = processor.resourceManager
|
val resourceManager = processor.layoutXmlFileManager
|
||||||
|
|
||||||
val psiElements = resourceManager.propertyToXmlAttributes(jetProperty).map { it as? XmlAttribute }.filterNotNull()
|
val psiElements = resourceManager.propertyToXmlAttributes(jetProperty).map { it as? XmlAttribute }.filterNotNull()
|
||||||
|
|
||||||
@@ -120,7 +117,7 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
|||||||
val module = attribute.getModule() ?: ModuleUtilCore.findModuleForFile(
|
val module = attribute.getModule() ?: ModuleUtilCore.findModuleForFile(
|
||||||
attribute.getContainingFile().getVirtualFile(), attribute.getProject()) ?: return
|
attribute.getContainingFile().getVirtualFile(), attribute.getProject()) ?: return
|
||||||
|
|
||||||
val processor = ModuleServiceManager.getService(module, javaClass<AndroidUIXmlProcessor>())!!
|
val processor = ModuleServiceManager.getService(module, javaClass<SyntheticFileGenerator>())!!
|
||||||
if (element == null) return
|
if (element == null) return
|
||||||
val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue())
|
val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue())
|
||||||
val newPropName = idToName(newName)
|
val newPropName = idToName(newName)
|
||||||
@@ -133,9 +130,9 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
|||||||
allRenames: MutableMap<PsiElement, String>,
|
allRenames: MutableMap<PsiElement, String>,
|
||||||
newPropName: String,
|
newPropName: String,
|
||||||
oldPropName: String,
|
oldPropName: String,
|
||||||
processor: AndroidUIXmlProcessor
|
processor: SyntheticFileGenerator
|
||||||
) {
|
) {
|
||||||
val props = processor.parseToPsi()?.flatMap { it.findChildrenByClass(javaClass<JetProperty>()).toList() }
|
val props = processor.getSyntheticFiles()?.flatMap { it.findChildrenByClass(javaClass<JetProperty>()).toList() }
|
||||||
val matchedProps = props?.filter { it.getName() == oldPropName } ?: listOf()
|
val matchedProps = props?.filter { it.getName() == oldPropName } ?: listOf()
|
||||||
for (prop in matchedProps) {
|
for (prop in matchedProps) {
|
||||||
allRenames[prop] = newPropName
|
allRenames[prop] = newPropName
|
||||||
@@ -148,7 +145,7 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
|
|||||||
allRenames: MutableMap<PsiElement, String>
|
allRenames: MutableMap<PsiElement, String>
|
||||||
) {
|
) {
|
||||||
val oldName = field.getName()!!
|
val oldName = field.getName()!!
|
||||||
val processor = ServiceManager.getService(field.getProject(), javaClass<AndroidUIXmlProcessor>())
|
val processor = ServiceManager.getService(field.getProject(), javaClass<SyntheticFileGenerator>())
|
||||||
renameSyntheticProperties(allRenames, newName, oldName, processor)
|
renameSyntheticProperties(allRenames, newName, oldName, processor)
|
||||||
}
|
}
|
||||||
|
|
||||||
+7
-7
@@ -14,24 +14,24 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android
|
package org.jetbrains.kotlin.android.synthetic.idea
|
||||||
|
|
||||||
import org.jetbrains.kotlin.plugin.references.SimpleNameReferenceExtension
|
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper
|
import org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.isAndroidSyntheticElement
|
||||||
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||||
|
import org.jetbrains.kotlin.plugin.references.SimpleNameReferenceExtension
|
||||||
import org.jetbrains.kotlin.psi.JetProperty
|
import org.jetbrains.kotlin.psi.JetProperty
|
||||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.isAndroidSyntheticElement
|
|
||||||
|
|
||||||
public class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension {
|
public class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension {
|
||||||
override fun isReferenceTo(reference: JetSimpleNameReference, element: PsiElement): Boolean? {
|
override fun isReferenceTo(reference: JetSimpleNameReference, element: PsiElement): Boolean? {
|
||||||
val resolvedElement = reference.resolve() ?: return null
|
val resolvedElement = reference.resolve() as? JetProperty ?: return null
|
||||||
|
|
||||||
if (isAndroidSyntheticElement(resolvedElement)) {
|
if (isAndroidSyntheticElement(resolvedElement)) {
|
||||||
if (element is ValueResourceElementWrapper) {
|
if (element is ValueResourceElementWrapper) {
|
||||||
val resource = element.getValue()
|
val resource = element.value
|
||||||
return (resolvedElement as JetProperty).getName() == resource.substring(resource.indexOf('/') + 1)
|
return resolvedElement.name == resource.substring(resource.indexOf('/') + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
+9
-8
@@ -14,15 +14,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android
|
package org.jetbrains.kotlin.android.synthetic.idea
|
||||||
|
|
||||||
import com.intellij.psi.xml.XmlAttribute
|
|
||||||
import com.intellij.psi.XmlElementVisitor
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.XmlElementVisitor
|
||||||
|
import com.intellij.psi.xml.XmlAttribute
|
||||||
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 org.jetbrains.kotlin.lang.resolve.android
|
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.*
|
import org.jetbrains.kotlin.android.synthetic.idToName
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.isWidgetTypeIgnored
|
||||||
|
|
||||||
class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> Unit) : XmlElementVisitor() {
|
class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> Unit) : XmlElementVisitor() {
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> U
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitXmlTag(tag: XmlTag?) {
|
override fun visitXmlTag(tag: XmlTag?) {
|
||||||
val localName = tag?.getLocalName() ?: ""
|
val localName = tag?.localName ?: ""
|
||||||
if (isWidgetTypeIgnored(localName)) {
|
if (isWidgetTypeIgnored(localName)) {
|
||||||
tag?.acceptChildren(this)
|
tag?.acceptChildren(this)
|
||||||
return
|
return
|
||||||
@@ -43,9 +44,9 @@ class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> U
|
|||||||
|
|
||||||
val idAttribute = tag?.getAttribute(AndroidConst.ID_ATTRIBUTE)
|
val idAttribute = tag?.getAttribute(AndroidConst.ID_ATTRIBUTE)
|
||||||
if (idAttribute != null) {
|
if (idAttribute != null) {
|
||||||
val idAttributeValue = idAttribute.getValue()
|
val idAttributeValue = idAttribute.value
|
||||||
if (idAttributeValue != null) {
|
if (idAttributeValue != null) {
|
||||||
val xmlType = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.getValue() ?: localName
|
val xmlType = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.value ?: localName
|
||||||
val name = idToName(idAttributeValue)
|
val name = idToName(idAttributeValue)
|
||||||
if (name != null) elementCallback(name, xmlType, idAttribute)
|
if (name != null) elementCallback(name, xmlType, idAttribute)
|
||||||
}
|
}
|
||||||
+9
-9
@@ -14,15 +14,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android
|
package org.jetbrains.kotlin.android.synthetic.idea
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider
|
|
||||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo
|
|
||||||
import com.intellij.openapi.module.ModuleServiceManager
|
import com.intellij.openapi.module.ModuleServiceManager
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator
|
||||||
|
import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo
|
||||||
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import org.jetbrains.kotlin.psi.moduleInfo
|
import org.jetbrains.kotlin.psi.moduleInfo
|
||||||
|
|
||||||
public class IDEAndroidExternalDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider {
|
public class IDEAndroidExternalDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider {
|
||||||
@@ -30,8 +30,8 @@ public class IDEAndroidExternalDeclarationsProvider(private val project: Project
|
|||||||
if (moduleInfo !is ModuleSourceInfo) return listOf()
|
if (moduleInfo !is ModuleSourceInfo) return listOf()
|
||||||
|
|
||||||
val module = moduleInfo.module
|
val module = moduleInfo.module
|
||||||
val parser = ModuleServiceManager.getService(module, javaClass<AndroidUIXmlProcessor>())!!
|
val parser = ModuleServiceManager.getService(module, javaClass<SyntheticFileGenerator>())!!
|
||||||
val syntheticFiles = parser.parseToPsi()
|
val syntheticFiles = parser.getSyntheticFiles()
|
||||||
syntheticFiles?.forEach { it.moduleInfo = moduleInfo }
|
syntheticFiles?.forEach { it.moduleInfo = moduleInfo }
|
||||||
|
|
||||||
return syntheticFiles ?: listOf()
|
return syntheticFiles ?: listOf()
|
||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android;
|
package org.jetbrains.kotlin.android.synthetic.idea;
|
||||||
|
|
||||||
import com.intellij.openapi.util.Key;
|
import com.intellij.openapi.util.Key;
|
||||||
|
|
||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android;
|
package org.jetbrains.kotlin.android.synthetic.idea;
|
||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.lang.Language;
|
import com.intellij.lang.Language;
|
||||||
+8
-9
@@ -14,21 +14,20 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android
|
package org.jetbrains.kotlin.android.synthetic.idea.res
|
||||||
|
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.android.facet.AndroidFacet
|
import org.jetbrains.android.facet.AndroidFacet
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidConst
|
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||||
import kotlin.properties.Delegates
|
import org.jetbrains.kotlin.android.synthetic.idea.AndroidXmlVisitor
|
||||||
import org.jetbrains.kotlin.plugin.android.AndroidXmlVisitor
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidModuleInfo
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidResourceManager
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.AndroidModuleInfo
|
|
||||||
import org.jetbrains.kotlin.psi.JetProperty
|
import org.jetbrains.kotlin.psi.JetProperty
|
||||||
|
|
||||||
public class IDEAndroidResourceManager(val module: Module) : AndroidResourceManager(module.getProject()) {
|
public class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileManager(module.getProject()) {
|
||||||
|
|
||||||
override val androidModuleInfo: AndroidModuleInfo? by Delegates.lazy { module.androidFacet?.toAndroidModuleInfo() }
|
override val androidModuleInfo: AndroidModuleInfo? by lazy { module.androidFacet?.toAndroidModuleInfo() }
|
||||||
|
|
||||||
override fun propertyToXmlAttributes(property: JetProperty): List<PsiElement> {
|
override fun propertyToXmlAttributes(property: JetProperty): List<PsiElement> {
|
||||||
val fqPath = property.getFqName()?.pathSegments() ?: return listOf()
|
val fqPath = property.getFqName()?.pathSegments() ?: return listOf()
|
||||||
@@ -53,7 +52,7 @@ public class IDEAndroidResourceManager(val module: Module) : AndroidResourceMana
|
|||||||
get() = AndroidFacet.getInstance(this)
|
get() = AndroidFacet.getInstance(this)
|
||||||
|
|
||||||
private fun AndroidFacet.toAndroidModuleInfo(): AndroidModuleInfo? {
|
private fun AndroidFacet.toAndroidModuleInfo(): AndroidModuleInfo? {
|
||||||
val applicationPackage = getManifest()?.getPackage()?.toString()
|
val applicationPackage = manifest?.getPackage()?.toString()
|
||||||
val mainResDirectories = getAllResourceDirectories().map { it.getPath() }
|
val mainResDirectories = getAllResourceDirectories().map { it.getPath() }
|
||||||
|
|
||||||
return if (applicationPackage != null) {
|
return if (applicationPackage != null) {
|
||||||
+21
-15
@@ -14,21 +14,25 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.plugin.android
|
package org.jetbrains.kotlin.android.synthetic.idea.res
|
||||||
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.psi.JavaPsiFacade
|
import com.intellij.psi.JavaPsiFacade
|
||||||
import org.jetbrains.kotlin.plugin.android.IDEAndroidResourceManager
|
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import org.jetbrains.kotlin.plugin.android.AndroidXmlVisitor
|
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
||||||
import com.intellij.psi.impl.*
|
|
||||||
import kotlin.properties.*
|
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.*
|
|
||||||
import com.intellij.psi.util.CachedValue
|
import com.intellij.psi.util.CachedValue
|
||||||
import com.intellij.psi.util.CachedValueProvider.Result
|
import com.intellij.psi.util.CachedValueProvider.Result
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.idea.AndroidPsiTreeChangePreprocessor
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.idea.AndroidXmlVisitor
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.parseAndroidResource
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidResource
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticFile
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator
|
||||||
|
|
||||||
class IDEAndroidUIXmlProcessor(val module: Module) : AndroidUIXmlProcessor(module.getProject()) {
|
class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(module.project) {
|
||||||
|
|
||||||
|
private val supportV4: Boolean
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val scope = module.getModuleWithDependenciesAndLibrariesScope(false)
|
val scope = module.getModuleWithDependenciesAndLibrariesScope(false)
|
||||||
@@ -36,26 +40,28 @@ class IDEAndroidUIXmlProcessor(val module: Module) : AndroidUIXmlProcessor(modul
|
|||||||
.findClasses(AndroidConst.SUPPORT_FRAGMENT_FQNAME, scope).isNotEmpty()
|
.findClasses(AndroidConst.SUPPORT_FRAGMENT_FQNAME, scope).isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val resourceManager: IDEAndroidResourceManager = IDEAndroidResourceManager(module)
|
override fun supportV4() = supportV4
|
||||||
|
|
||||||
private val psiTreeChangePreprocessor by Delegates.lazy {
|
override val layoutXmlFileManager: IDEAndroidLayoutXmlFileManager = IDEAndroidLayoutXmlFileManager(module)
|
||||||
module.getProject().getExtensions(PsiTreeChangePreprocessor.EP_NAME).first { it is AndroidPsiTreeChangePreprocessor }
|
|
||||||
|
private val psiTreeChangePreprocessor by lazy {
|
||||||
|
module.project.getExtensions(PsiTreeChangePreprocessor.EP_NAME).first { it is AndroidPsiTreeChangePreprocessor }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val cachedSources: CachedValue<List<AndroidSyntheticFile>> by Delegates.lazy {
|
override val cachedSources: CachedValue<List<AndroidSyntheticFile>> by lazy {
|
||||||
cachedValue {
|
cachedValue {
|
||||||
Result.create(parse(), psiTreeChangePreprocessor)
|
Result.create(generateSyntheticFiles(), psiTreeChangePreprocessor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun parseLayout(files: List<PsiFile>): List<AndroidResource> {
|
override fun extractLayoutResources(files: List<PsiFile>): List<AndroidResource> {
|
||||||
val widgets = arrayListOf<AndroidResource>()
|
val widgets = arrayListOf<AndroidResource>()
|
||||||
val visitor = AndroidXmlVisitor { id, widgetType, attribute ->
|
val visitor = AndroidXmlVisitor { id, widgetType, attribute ->
|
||||||
widgets.add(parseAndroidResource(id, widgetType))
|
widgets.add(parseAndroidResource(id, widgetType))
|
||||||
}
|
}
|
||||||
|
|
||||||
files.forEach { it.accept(visitor) }
|
files.forEach { it.accept(visitor) }
|
||||||
return removeDuplicates(widgets)
|
return filterDuplicates(widgets)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+7
-13
@@ -16,16 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.android
|
package org.jetbrains.kotlin.android
|
||||||
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator
|
||||||
import org.jetbrains.kotlin.plugin.android.TestConst
|
|
||||||
import org.jetbrains.kotlin.lang.resolve.android.CliAndroidUIXmlProcessor
|
|
||||||
import com.intellij.openapi.module.ModuleManager
|
import com.intellij.openapi.module.ModuleManager
|
||||||
import org.jetbrains.kotlin.plugin.android.IDEAndroidUIXmlProcessor
|
import org.jetbrains.kotlin.android.synthetic.idea.TestConst
|
||||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
import org.jetbrains.kotlin.android.synthetic.idea.res.IDESyntheticFileGenerator
|
||||||
import org.jetbrains.kotlin.test.TestJdkKind
|
|
||||||
import org.jetbrains.kotlin.test.JetTestUtils
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
|
||||||
import java.io.File
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase() {
|
public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase() {
|
||||||
@@ -37,11 +31,11 @@ public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase()
|
|||||||
"$path${it.name}/"
|
"$path${it.name}/"
|
||||||
}
|
}
|
||||||
|
|
||||||
val cliParser = CliAndroidUIXmlProcessor(project, path + "../AndroidManifest.xml", resDirs)
|
val cliParser = CliSyntheticFileGenerator(project, path + "../AndroidManifest.xml", resDirs, false)
|
||||||
val ideParser = IDEAndroidUIXmlProcessor(ModuleManager.getInstance(project).getModules()[0])
|
val ideParser = IDESyntheticFileGenerator(ModuleManager.getInstance(project).getModules()[0])
|
||||||
|
|
||||||
val cliResult = cliParser.parseToPsi()!!.joinToString("\n\n")
|
val cliResult = cliParser.getSyntheticFiles()!!.joinToString("\n\n")
|
||||||
val ideResult = ideParser.parseToPsi()!!.joinToString("\n\n")
|
val ideResult = ideParser.getSyntheticFiles()!!.joinToString("\n\n")
|
||||||
|
|
||||||
assertEquals(cliResult, ideResult)
|
assertEquals(cliResult, ideResult)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user