Do not use JavaPsiFacade in android-compiler-plugin

This commit is contained in:
Yan Zhulanow
2015-08-20 19:45:01 +03:00
parent d0d846ccfc
commit 0f5d87957d
5 changed files with 47 additions and 43 deletions
@@ -18,14 +18,14 @@ package org.jetbrains.kotlin.android.synthetic.res
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiFile
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.parseAndroidResource
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.psi.JetFile
import kotlin.properties.Delegates
public open class CliSyntheticFileGenerator(
project: Project,
@@ -33,32 +33,30 @@ public open class CliSyntheticFileGenerator(
private val resDirectories: List<String>
) : 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 {
val supportV4 = supportV4Available(javaPsiFacade, projectScope)
generateSyntheticJetFiles(generateSyntheticFiles(true, projectScope, supportV4))
val supportV4 = supportV4Available()
generateSyntheticJetFiles(generateSyntheticFiles(true, supportV4))
}
override val layoutXmlFileManager: CliAndroidLayoutXmlFileManager by Delegates.lazy {
override val layoutXmlFileManager: CliAndroidLayoutXmlFileManager by lazy {
CliAndroidLayoutXmlFileManager(project, manifestPath, resDirectories)
}
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 handler = AndroidXmlHandler { id, tag ->
resources += parseAndroidResource(id, tag) { tag ->
resolveFqClassNameForView(javaPsiFacade, scope, tag)
resolveFqClassNameForView(tag)
}
}
for (file in files) {
try {
val inputStream = ByteArrayInputStream(file.getVirtualFile().contentsToByteArray())
val inputStream = ByteArrayInputStream(file.virtualFile.contentsToByteArray())
layoutXmlFileManager.saxParser.parse(inputStream, handler)
} catch (e: Throwable) {
LOG.error(e)
@@ -68,6 +66,17 @@ public open class CliSyntheticFileGenerator(
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 val LOG: Logger = Logger.getInstance(javaClass)
}
@@ -17,10 +17,9 @@
package org.jetbrains.kotlin.android.synthetic.res
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.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider.Result
import com.intellij.psi.util.CachedValuesManager
@@ -46,16 +45,12 @@ public abstract class SyntheticFileGenerator(protected val project: Project) {
public abstract fun getSyntheticFiles(): List<JetFile>
protected fun generateSyntheticFiles(
generateCommonFiles: Boolean,
scope: GlobalSearchScope,
supportV4: Boolean
): List<AndroidSyntheticFile> {
protected fun generateSyntheticFiles(generateCommonFiles: Boolean, supportV4: Boolean): List<AndroidSyntheticFile> {
val commonFiles = if (generateCommonFiles) generateCommonFiles(supportV4) else listOf()
return layoutXmlFileManager.getLayoutXmlFiles().flatMap { entry ->
val files = entry.getValue()
val resources = extractLayoutResources(files, scope)
val resources = extractLayoutResources(files)
val layoutName = entry.getKey()
@@ -81,7 +76,9 @@ public abstract class SyntheticFileGenerator(protected val project: Project) {
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 {
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)
}
protected fun resolveFqClassNameForView(javaPsiFacade: JavaPsiFacade, scope: GlobalSearchScope, tag: String): String? {
protected fun resolveFqClassNameForView(tag: String): String? {
if (tag.contains('.')) {
if (javaPsiFacade.findClass(tag, scope) == null) {
if (!checkIfClassExist(tag)) {
return null
}
return tag
}
for (pkg in AndroidConst.FQNAME_RESOLVE_PACKAGES) {
val fqName = "$pkg.$tag"
if (javaPsiFacade.findClass(fqName, scope) != null) {
if (checkIfClassExist(fqName)) {
return fqName
}
}
return null
}
protected fun supportV4Available(javaPsiFacade: JavaPsiFacade, scope: GlobalSearchScope): Boolean {
return javaPsiFacade.findClasses(AndroidConst.SUPPORT_FRAGMENT_FQNAME, scope).isNotEmpty()
}
protected fun supportV4Available(): Boolean = checkIfClassExist(AndroidConst.SUPPORT_FRAGMENT_FQNAME)
protected fun filterDuplicates(resources: List<AndroidResource>): List<AndroidResource> {
val resourceMap = linkedMapOf<String, AndroidResource>()
@@ -40,10 +40,7 @@ public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() {
val parser = CliSyntheticFileGeneratorForConversionTest(
jetCoreEnvironment.project, path + "AndroidManifest.xml", layoutPaths, supportV4)
val module = ModuleManager.getInstance(jetCoreEnvironment.project).modules.first()
val moduleScope = module.getModuleWithDependenciesAndLibrariesScope(false)
val actual = parser.gen(moduleScope).toMap { it.name }
val actual = parser.gen().toMap { it.name }
val expectedLayoutFiles = testDirectory.listFiles {
it.isFile() && it.name.endsWith(".kt")
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.lang.resolve.android.test
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.UsefulTestCase
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.android.synthetic.AndroidConfigurationKeys
@@ -49,7 +48,7 @@ class CliSyntheticFileGeneratorForConversionTest(
resDirectories: List<String>,
private val supportV4: Boolean
) : CliSyntheticFileGenerator(project, manifestPath, resDirectories) {
fun gen(scope: GlobalSearchScope) = generateSyntheticFiles(false, scope, supportV4)
fun gen() = generateSyntheticFiles(false, supportV4)
}
fun UsefulTestCase.createAndroidTestEnvironment(
@@ -20,9 +20,9 @@ import com.intellij.openapi.module.Module
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiFile
import com.intellij.psi.impl.PsiTreeChangePreprocessor
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.CachedValue
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
@@ -32,13 +32,10 @@ import org.jetbrains.kotlin.psi.JetFile
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 {
cachedValue {
val supportV4 = supportV4Available(javaPsiFacade, moduleScope)
Result.create(generateSyntheticJetFiles(generateSyntheticFiles(true, moduleScope, supportV4)), psiTreeChangePreprocessor)
val supportV4 = supportV4Available()
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 }
}
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 visitor = AndroidXmlVisitor { id, widgetType, attribute ->
widgets += parseAndroidResource(id, widgetType) {
resolveFqClassNameForView(javaPsiFacade, scope, it)
widgets += parseAndroidResource(id, widgetType) { tag ->
resolveFqClassNameForView(tag)
}
}
@@ -62,4 +62,8 @@ class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(mod
return filterDuplicates(widgets)
}
override fun checkIfClassExist(fqName: String): Boolean {
val moduleScope = module.getModuleWithDependenciesAndLibrariesScope(false)
return JavaPsiFacade.getInstance(module.project).findClass(fqName, moduleScope) != null
}
}