Do not use JavaPsiFacade in android-compiler-plugin
This commit is contained in:
+21
-12
@@ -18,14 +18,14 @@ 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.JavaPsiFacade
|
import com.intellij.psi.PsiElementFinder
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
|
import com.intellij.psi.impl.PsiElementFinderImpl
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.android.synthetic.AndroidXmlHandler
|
import org.jetbrains.kotlin.android.synthetic.AndroidXmlHandler
|
||||||
import org.jetbrains.kotlin.android.synthetic.parseAndroidResource
|
import org.jetbrains.kotlin.android.synthetic.parseAndroidResource
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import kotlin.properties.Delegates
|
|
||||||
|
|
||||||
public open class CliSyntheticFileGenerator(
|
public open class CliSyntheticFileGenerator(
|
||||||
project: Project,
|
project: Project,
|
||||||
@@ -33,32 +33,30 @@ public open class CliSyntheticFileGenerator(
|
|||||||
private val resDirectories: List<String>
|
private val resDirectories: List<String>
|
||||||
) : SyntheticFileGenerator(project) {
|
) : SyntheticFileGenerator(project) {
|
||||||
|
|
||||||
private val javaPsiFacade: JavaPsiFacade by lazy { JavaPsiFacade.getInstance(project) }
|
|
||||||
private val projectScope: GlobalSearchScope by lazy { GlobalSearchScope.allScope(project) }
|
|
||||||
|
|
||||||
private val cachedJetFiles by lazy {
|
private val cachedJetFiles by lazy {
|
||||||
val supportV4 = supportV4Available(javaPsiFacade, projectScope)
|
val supportV4 = supportV4Available()
|
||||||
generateSyntheticJetFiles(generateSyntheticFiles(true, projectScope, supportV4))
|
|
||||||
|
generateSyntheticJetFiles(generateSyntheticFiles(true, supportV4))
|
||||||
}
|
}
|
||||||
|
|
||||||
override val layoutXmlFileManager: CliAndroidLayoutXmlFileManager by Delegates.lazy {
|
override val layoutXmlFileManager: CliAndroidLayoutXmlFileManager by lazy {
|
||||||
CliAndroidLayoutXmlFileManager(project, manifestPath, resDirectories)
|
CliAndroidLayoutXmlFileManager(project, manifestPath, resDirectories)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun getSyntheticFiles(): List<JetFile> = cachedJetFiles
|
public override fun getSyntheticFiles(): List<JetFile> = cachedJetFiles
|
||||||
|
|
||||||
override fun extractLayoutResources(files: List<PsiFile>, scope: GlobalSearchScope): List<AndroidResource> {
|
override fun extractLayoutResources(files: List<PsiFile>): List<AndroidResource> {
|
||||||
val resources = arrayListOf<AndroidResource>()
|
val resources = arrayListOf<AndroidResource>()
|
||||||
|
|
||||||
val handler = AndroidXmlHandler { id, tag ->
|
val handler = AndroidXmlHandler { id, tag ->
|
||||||
resources += parseAndroidResource(id, tag) { tag ->
|
resources += parseAndroidResource(id, tag) { tag ->
|
||||||
resolveFqClassNameForView(javaPsiFacade, scope, tag)
|
resolveFqClassNameForView(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (file in files) {
|
for (file in files) {
|
||||||
try {
|
try {
|
||||||
val inputStream = ByteArrayInputStream(file.getVirtualFile().contentsToByteArray())
|
val inputStream = ByteArrayInputStream(file.virtualFile.contentsToByteArray())
|
||||||
layoutXmlFileManager.saxParser.parse(inputStream, handler)
|
layoutXmlFileManager.saxParser.parse(inputStream, handler)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
LOG.error(e)
|
LOG.error(e)
|
||||||
@@ -68,6 +66,17 @@ public open class CliSyntheticFileGenerator(
|
|||||||
return filterDuplicates(resources)
|
return filterDuplicates(resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun checkIfClassExist(fqName: String): Boolean {
|
||||||
|
val scope = GlobalSearchScope.allScope(project)
|
||||||
|
val psiElementFinders = project.getExtensions(PsiElementFinder.EP_NAME).filter { it is PsiElementFinderImpl }
|
||||||
|
|
||||||
|
for (finder in psiElementFinders) {
|
||||||
|
val clazz = finder.findClass(fqName, scope)
|
||||||
|
if (clazz != null) return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private val LOG: Logger = Logger.getInstance(javaClass)
|
private val LOG: Logger = Logger.getInstance(javaClass)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-15
@@ -17,10 +17,9 @@
|
|||||||
package org.jetbrains.kotlin.android.synthetic.res
|
package org.jetbrains.kotlin.android.synthetic.res
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.JavaPsiFacade
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
|
||||||
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 com.intellij.psi.util.CachedValuesManager
|
import com.intellij.psi.util.CachedValuesManager
|
||||||
@@ -46,16 +45,12 @@ public abstract class SyntheticFileGenerator(protected val project: Project) {
|
|||||||
|
|
||||||
public abstract fun getSyntheticFiles(): List<JetFile>
|
public abstract fun getSyntheticFiles(): List<JetFile>
|
||||||
|
|
||||||
protected fun generateSyntheticFiles(
|
protected fun generateSyntheticFiles(generateCommonFiles: Boolean, supportV4: Boolean): List<AndroidSyntheticFile> {
|
||||||
generateCommonFiles: Boolean,
|
|
||||||
scope: GlobalSearchScope,
|
|
||||||
supportV4: Boolean
|
|
||||||
): List<AndroidSyntheticFile> {
|
|
||||||
val commonFiles = if (generateCommonFiles) generateCommonFiles(supportV4) else listOf()
|
val commonFiles = if (generateCommonFiles) generateCommonFiles(supportV4) else listOf()
|
||||||
|
|
||||||
return layoutXmlFileManager.getLayoutXmlFiles().flatMap { entry ->
|
return layoutXmlFileManager.getLayoutXmlFiles().flatMap { entry ->
|
||||||
val files = entry.getValue()
|
val files = entry.getValue()
|
||||||
val resources = extractLayoutResources(files, scope)
|
val resources = extractLayoutResources(files)
|
||||||
|
|
||||||
val layoutName = entry.getKey()
|
val layoutName = entry.getKey()
|
||||||
|
|
||||||
@@ -81,7 +76,9 @@ public abstract class SyntheticFileGenerator(protected val project: Project) {
|
|||||||
return listOf(clearCacheFile, TOOLS_FILE)
|
return listOf(clearCacheFile, TOOLS_FILE)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun extractLayoutResources(files: List<PsiFile>, scope: GlobalSearchScope): List<AndroidResource>
|
protected abstract fun extractLayoutResources(files: List<PsiFile>): List<AndroidResource>
|
||||||
|
|
||||||
|
protected abstract fun checkIfClassExist(fqName: String): Boolean
|
||||||
|
|
||||||
private fun renderMainLayoutFile(layoutName: String, resources: List<AndroidResource>, supportV4: Boolean): AndroidSyntheticFile {
|
private fun renderMainLayoutFile(layoutName: String, resources: List<AndroidResource>, supportV4: Boolean): AndroidSyntheticFile {
|
||||||
return renderLayoutFile(layoutName + AndroidConst.LAYOUT_POSTFIX, escapeAndroidIdentifier(layoutName), resources) {
|
return renderLayoutFile(layoutName + AndroidConst.LAYOUT_POSTFIX, escapeAndroidIdentifier(layoutName), resources) {
|
||||||
@@ -152,25 +149,23 @@ public abstract class SyntheticFileGenerator(protected val project: Project) {
|
|||||||
return fqName.startsWith(AndroidConst.SUPPORT_V4_PACKAGE)
|
return fqName.startsWith(AndroidConst.SUPPORT_V4_PACKAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun resolveFqClassNameForView(javaPsiFacade: JavaPsiFacade, scope: GlobalSearchScope, tag: String): String? {
|
protected fun resolveFqClassNameForView(tag: String): String? {
|
||||||
if (tag.contains('.')) {
|
if (tag.contains('.')) {
|
||||||
if (javaPsiFacade.findClass(tag, scope) == null) {
|
if (!checkIfClassExist(tag)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
for (pkg in AndroidConst.FQNAME_RESOLVE_PACKAGES) {
|
for (pkg in AndroidConst.FQNAME_RESOLVE_PACKAGES) {
|
||||||
val fqName = "$pkg.$tag"
|
val fqName = "$pkg.$tag"
|
||||||
if (javaPsiFacade.findClass(fqName, scope) != null) {
|
if (checkIfClassExist(fqName)) {
|
||||||
return fqName
|
return fqName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun supportV4Available(javaPsiFacade: JavaPsiFacade, scope: GlobalSearchScope): Boolean {
|
protected fun supportV4Available(): Boolean = checkIfClassExist(AndroidConst.SUPPORT_FRAGMENT_FQNAME)
|
||||||
return javaPsiFacade.findClasses(AndroidConst.SUPPORT_FRAGMENT_FQNAME, scope).isNotEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun filterDuplicates(resources: List<AndroidResource>): List<AndroidResource> {
|
protected fun filterDuplicates(resources: List<AndroidResource>): List<AndroidResource> {
|
||||||
val resourceMap = linkedMapOf<String, AndroidResource>()
|
val resourceMap = linkedMapOf<String, AndroidResource>()
|
||||||
|
|||||||
+1
-4
@@ -40,10 +40,7 @@ public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() {
|
|||||||
val parser = CliSyntheticFileGeneratorForConversionTest(
|
val parser = CliSyntheticFileGeneratorForConversionTest(
|
||||||
jetCoreEnvironment.project, path + "AndroidManifest.xml", layoutPaths, supportV4)
|
jetCoreEnvironment.project, path + "AndroidManifest.xml", layoutPaths, supportV4)
|
||||||
|
|
||||||
val module = ModuleManager.getInstance(jetCoreEnvironment.project).modules.first()
|
val actual = parser.gen().toMap { it.name }
|
||||||
val moduleScope = module.getModuleWithDependenciesAndLibrariesScope(false)
|
|
||||||
|
|
||||||
val actual = parser.gen(moduleScope).toMap { it.name }
|
|
||||||
|
|
||||||
val expectedLayoutFiles = testDirectory.listFiles {
|
val expectedLayoutFiles = testDirectory.listFiles {
|
||||||
it.isFile() && it.name.endsWith(".kt")
|
it.isFile() && it.name.endsWith(".kt")
|
||||||
|
|||||||
+1
-2
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.lang.resolve.android.test
|
package org.jetbrains.kotlin.lang.resolve.android.test
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
|
||||||
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.android.synthetic.AndroidConfigurationKeys
|
import org.jetbrains.kotlin.android.synthetic.AndroidConfigurationKeys
|
||||||
@@ -49,7 +48,7 @@ class CliSyntheticFileGeneratorForConversionTest(
|
|||||||
resDirectories: List<String>,
|
resDirectories: List<String>,
|
||||||
private val supportV4: Boolean
|
private val supportV4: Boolean
|
||||||
) : CliSyntheticFileGenerator(project, manifestPath, resDirectories) {
|
) : CliSyntheticFileGenerator(project, manifestPath, resDirectories) {
|
||||||
fun gen(scope: GlobalSearchScope) = generateSyntheticFiles(false, scope, supportV4)
|
fun gen() = generateSyntheticFiles(false, supportV4)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun UsefulTestCase.createAndroidTestEnvironment(
|
fun UsefulTestCase.createAndroidTestEnvironment(
|
||||||
|
|||||||
+14
-10
@@ -20,9 +20,9 @@ import com.intellij.openapi.module.Module
|
|||||||
import com.intellij.psi.JavaPsiFacade
|
import com.intellij.psi.JavaPsiFacade
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
|
||||||
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.AndroidPsiTreeChangePreprocessor
|
||||||
import org.jetbrains.kotlin.android.synthetic.idea.AndroidXmlVisitor
|
import org.jetbrains.kotlin.android.synthetic.idea.AndroidXmlVisitor
|
||||||
import org.jetbrains.kotlin.android.synthetic.parseAndroidResource
|
import org.jetbrains.kotlin.android.synthetic.parseAndroidResource
|
||||||
@@ -32,13 +32,10 @@ import org.jetbrains.kotlin.psi.JetFile
|
|||||||
|
|
||||||
class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(module.project) {
|
class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(module.project) {
|
||||||
|
|
||||||
private val javaPsiFacade: JavaPsiFacade by lazy { JavaPsiFacade.getInstance(module.project) }
|
|
||||||
private val moduleScope: GlobalSearchScope by lazy { module.getModuleWithDependenciesAndLibrariesScope(false) }
|
|
||||||
|
|
||||||
private val cachedJetFiles: CachedValue<List<JetFile>> by lazy {
|
private val cachedJetFiles: CachedValue<List<JetFile>> by lazy {
|
||||||
cachedValue {
|
cachedValue {
|
||||||
val supportV4 = supportV4Available(javaPsiFacade, moduleScope)
|
val supportV4 = supportV4Available()
|
||||||
Result.create(generateSyntheticJetFiles(generateSyntheticFiles(true, moduleScope, supportV4)), psiTreeChangePreprocessor)
|
Result.create(generateSyntheticJetFiles(generateSyntheticFiles(true, supportV4)), psiTreeChangePreprocessor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,13 +45,16 @@ class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(mod
|
|||||||
module.project.getExtensions(PsiTreeChangePreprocessor.EP_NAME).first { it is AndroidPsiTreeChangePreprocessor }
|
module.project.getExtensions(PsiTreeChangePreprocessor.EP_NAME).first { it is AndroidPsiTreeChangePreprocessor }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun getSyntheticFiles(): List<JetFile> = cachedJetFiles.value
|
public override fun getSyntheticFiles(): List<JetFile> {
|
||||||
|
if (!checkIfClassExist(AndroidConst.VIEW_FQNAME)) return listOf()
|
||||||
|
return cachedJetFiles.value
|
||||||
|
}
|
||||||
|
|
||||||
override fun extractLayoutResources(files: List<PsiFile>, scope: GlobalSearchScope): 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 += parseAndroidResource(id, widgetType) {
|
widgets += parseAndroidResource(id, widgetType) { tag ->
|
||||||
resolveFqClassNameForView(javaPsiFacade, scope, it)
|
resolveFqClassNameForView(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,4 +62,8 @@ class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(mod
|
|||||||
return filterDuplicates(widgets)
|
return filterDuplicates(widgets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun checkIfClassExist(fqName: String): Boolean {
|
||||||
|
val moduleScope = module.getModuleWithDependenciesAndLibrariesScope(false)
|
||||||
|
return JavaPsiFacade.getInstance(module.project).findClass(fqName, moduleScope) != null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user