Check supportv4 library presence on the spot
This commit is contained in:
+10
-26
@@ -19,50 +19,34 @@ package org.jetbrains.kotlin.android
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.gradle.api
|
||||
import com.android.build.gradle.BaseExtension
|
||||
import java.io.File
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
|
||||
public class AndroidSubplugin : KotlinGradleSubplugin {
|
||||
|
||||
override fun getExtraArguments(project: api.Project, task: AbstractCompile): List<SubpluginOption>? {
|
||||
val androidExtension = project.getExtensions().getByName("android") as? BaseExtension
|
||||
val androidExtension = project.extensions.getByName("android") as? BaseExtension ?: return null
|
||||
|
||||
if (androidExtension == null) return null
|
||||
|
||||
val sourceSets = androidExtension.getSourceSets()
|
||||
val sourceSets = androidExtension.sourceSets
|
||||
val mainSourceSet = sourceSets.getByName("main")
|
||||
|
||||
val resourceDirs = mainSourceSet.getRes().getSrcDirs()
|
||||
val manifestFile = mainSourceSet.getManifest().getSrcFile()
|
||||
|
||||
val compileDependencies = project.getConfigurations().getByName("compile").getFiles()
|
||||
val supportV4 = compileDependencies?.filter { it.name.startsWith("support-v4-") }?.isNotEmpty() ?: false
|
||||
val supportV4Property = if (supportV4) "true" else "false"
|
||||
val resourceDirs = mainSourceSet.res.srcDirs
|
||||
val manifestFile = mainSourceSet.manifest.srcFile
|
||||
|
||||
if (resourceDirs.isNotEmpty()) {
|
||||
val resourceDirOptions = resourceDirs.map { resourceDir ->
|
||||
resourceDir.listFiles { it.isDirectory() && it.name.startsWith("layout") }?.forEach { task.source(it) }
|
||||
SubpluginOption("androidRes", resourceDir.getAbsolutePath())
|
||||
resourceDir.listFiles { it.isDirectory && it.name.startsWith("layout") }?.forEach { task.source(it) }
|
||||
SubpluginOption("androidRes", resourceDir.absolutePath)
|
||||
}
|
||||
return listOf(
|
||||
SubpluginOption("androidManifest", manifestFile.getAbsolutePath()),
|
||||
SubpluginOption("supportV4", supportV4Property)
|
||||
) + resourceDirOptions
|
||||
return listOf(SubpluginOption("androidManifest", manifestFile.absolutePath)) + resourceDirOptions
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "org.jetbrains.kotlin.android"
|
||||
}
|
||||
override fun getPluginName() = "org.jetbrains.kotlin.android"
|
||||
|
||||
override fun getGroupName(): String {
|
||||
return "org.jetbrains.kotlin"
|
||||
}
|
||||
override fun getGroupName() = "org.jetbrains.kotlin"
|
||||
|
||||
override fun getArtifactName(): String {
|
||||
return "kotlin-android-extensions"
|
||||
}
|
||||
override fun getArtifactName() = "kotlin-android-extensions"
|
||||
}
|
||||
+2
-6
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.psi.JetFile
|
||||
public object AndroidConfigurationKeys {
|
||||
public val ANDROID_RES_PATH: CompilerConfigurationKey<List<String>> = CompilerConfigurationKey.create<List<String>>("android resources search path")
|
||||
public val ANDROID_MANIFEST: CompilerConfigurationKey<String> = CompilerConfigurationKey.create<String>("android manifest file")
|
||||
public val SUPPORT_V4: CompilerConfigurationKey<String> = CompilerConfigurationKey.create<String>("'true' if compiled with support-v4 library")
|
||||
}
|
||||
|
||||
public class AndroidCommandLineProcessor : CommandLineProcessor {
|
||||
@@ -47,12 +46,11 @@ public class AndroidCommandLineProcessor : CommandLineProcessor {
|
||||
|
||||
public val RESOURCE_PATH_OPTION: CliOption = CliOption("androidRes", "<path>", "Android resources path", allowMultipleOccurrences = true)
|
||||
public val MANIFEST_FILE_OPTION: CliOption = CliOption("androidManifest", "<path>", "Android manifest file")
|
||||
public val SUPPORT_V4_OPTION: CliOption = CliOption("supportV4", "<path>", "Support android-v4 library", required = false)
|
||||
}
|
||||
|
||||
override val pluginId: String = ANDROID_COMPILER_PLUGIN_ID
|
||||
|
||||
override val pluginOptions: Collection<CliOption> = listOf(RESOURCE_PATH_OPTION, MANIFEST_FILE_OPTION, SUPPORT_V4_OPTION)
|
||||
override val pluginOptions: Collection<CliOption> = listOf(RESOURCE_PATH_OPTION, MANIFEST_FILE_OPTION)
|
||||
|
||||
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
|
||||
when (option) {
|
||||
@@ -62,7 +60,6 @@ public class AndroidCommandLineProcessor : CommandLineProcessor {
|
||||
configuration.put(AndroidConfigurationKeys.ANDROID_RES_PATH, paths)
|
||||
}
|
||||
MANIFEST_FILE_OPTION -> configuration.put(AndroidConfigurationKeys.ANDROID_MANIFEST, value)
|
||||
SUPPORT_V4_OPTION -> configuration.put(AndroidConfigurationKeys.SUPPORT_V4, value)
|
||||
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
|
||||
}
|
||||
}
|
||||
@@ -80,10 +77,9 @@ public class AndroidComponentRegistrar : ComponentRegistrar {
|
||||
public override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||
val androidResPath = configuration.get(AndroidConfigurationKeys.ANDROID_RES_PATH)
|
||||
val androidManifest = configuration.get(AndroidConfigurationKeys.ANDROID_MANIFEST)
|
||||
val supportV4 = configuration.get(AndroidConfigurationKeys.SUPPORT_V4) ?: "false"
|
||||
|
||||
if (androidResPath != null && androidManifest != null) {
|
||||
val xmlProcessor = CliSyntheticFileGenerator(project, androidManifest, androidResPath, supportV4 == "true")
|
||||
val xmlProcessor = CliSyntheticFileGenerator(project, androidManifest, androidResPath)
|
||||
|
||||
project.registerService(javaClass<SyntheticFileGenerator>(), xmlProcessor)
|
||||
project.registerService(javaClass<AndroidLayoutXmlFileManager>(), CliAndroidLayoutXmlFileManager(project, androidManifest, androidResPath))
|
||||
|
||||
+3
-7
@@ -30,19 +30,15 @@ import kotlin.properties.Delegates
|
||||
public open class CliSyntheticFileGenerator(
|
||||
project: Project,
|
||||
private val manifestPath: String,
|
||||
private val resDirectories: List<String>,
|
||||
private val supportV4: Boolean
|
||||
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 {
|
||||
generateSyntheticJetFiles(generateSyntheticFiles(true, projectScope))
|
||||
}
|
||||
|
||||
override fun supportV4(): Boolean {
|
||||
return supportV4
|
||||
val supportV4 = supportV4Available(javaPsiFacade, projectScope)
|
||||
generateSyntheticJetFiles(generateSyntheticFiles(true, projectScope, supportV4))
|
||||
}
|
||||
|
||||
override val layoutXmlFileManager: CliAndroidLayoutXmlFileManager by Delegates.lazy {
|
||||
|
||||
+18
-11
@@ -39,12 +39,14 @@ public abstract class SyntheticFileGenerator(protected val project: Project) {
|
||||
|
||||
public abstract val layoutXmlFileManager: AndroidLayoutXmlFileManager
|
||||
|
||||
protected abstract fun supportV4(): Boolean
|
||||
|
||||
public abstract fun getSyntheticFiles(): List<JetFile>
|
||||
|
||||
protected fun generateSyntheticFiles(generateCommonFiles: Boolean = true, scope: GlobalSearchScope): List<AndroidSyntheticFile> {
|
||||
val commonFiles = if (generateCommonFiles) generateCommonFiles() else listOf()
|
||||
protected fun generateSyntheticFiles(
|
||||
generateCommonFiles: Boolean,
|
||||
scope: GlobalSearchScope,
|
||||
supportV4: Boolean
|
||||
): List<AndroidSyntheticFile> {
|
||||
val commonFiles = if (generateCommonFiles) generateCommonFiles(supportV4) else listOf()
|
||||
|
||||
return layoutXmlFileManager.getLayoutXmlFiles().flatMap { entry ->
|
||||
val files = entry.getValue()
|
||||
@@ -52,20 +54,22 @@ public abstract class SyntheticFileGenerator(protected val project: Project) {
|
||||
|
||||
val layoutName = entry.getKey()
|
||||
|
||||
val mainLayoutFile = renderMainLayoutFile(layoutName, resources)
|
||||
val mainLayoutFile = renderMainLayoutFile(layoutName, resources, supportV4)
|
||||
val viewLayoutFile = renderViewLayoutFile(layoutName, resources)
|
||||
|
||||
listOf(mainLayoutFile, viewLayoutFile)
|
||||
}.filterNotNull() + commonFiles
|
||||
}
|
||||
|
||||
private fun generateCommonFiles(): List<AndroidSyntheticFile> {
|
||||
private fun generateCommonFiles(supportV4: Boolean): List<AndroidSyntheticFile> {
|
||||
val renderSyntheticFile = renderSyntheticFile("clearCache") {
|
||||
writePackage(AndroidConst.SYNTHETIC_PACKAGE)
|
||||
writeAndroidImports()
|
||||
writeClearCacheFunction(AndroidConst.ACTIVITY_FQNAME)
|
||||
writeClearCacheFunction(AndroidConst.FRAGMENT_FQNAME)
|
||||
if (supportV4()) writeClearCacheFunction(AndroidConst.SUPPORT_FRAGMENT_FQNAME)
|
||||
if (supportV4) {
|
||||
writeClearCacheFunction(AndroidConst.SUPPORT_FRAGMENT_FQNAME)
|
||||
}
|
||||
}
|
||||
val clearCacheFile = renderSyntheticFile
|
||||
|
||||
@@ -74,11 +78,10 @@ public abstract class SyntheticFileGenerator(protected val project: Project) {
|
||||
|
||||
protected abstract fun extractLayoutResources(files: List<PsiFile>, scope: GlobalSearchScope): List<AndroidResource>
|
||||
|
||||
private fun renderMainLayoutFile(layoutName: String, resources: List<AndroidResource>): AndroidSyntheticFile {
|
||||
return renderLayoutFile(layoutName + AndroidConst.LAYOUT_POSTFIX,
|
||||
escapeAndroidIdentifier(layoutName), resources) {
|
||||
private fun renderMainLayoutFile(layoutName: String, resources: List<AndroidResource>, supportV4: Boolean): AndroidSyntheticFile {
|
||||
return renderLayoutFile(layoutName + AndroidConst.LAYOUT_POSTFIX, escapeAndroidIdentifier(layoutName), resources) {
|
||||
val properties = it.mainProperties.toArrayList()
|
||||
if (supportV4()) properties.addAll(it.mainPropertiesForSupportV4)
|
||||
if (supportV4) properties.addAll(it.mainPropertiesForSupportV4)
|
||||
properties
|
||||
}
|
||||
}
|
||||
@@ -155,6 +158,10 @@ public abstract class SyntheticFileGenerator(protected val project: Project) {
|
||||
return null
|
||||
}
|
||||
|
||||
protected fun supportV4Available(javaPsiFacade: JavaPsiFacade, scope: GlobalSearchScope): Boolean {
|
||||
return javaPsiFacade.findClasses(AndroidConst.SUPPORT_FRAGMENT_FQNAME, scope).isNotEmpty()
|
||||
}
|
||||
|
||||
protected fun filterDuplicates(resources: List<AndroidResource>): List<AndroidResource> {
|
||||
val resourceMap = linkedMapOf<String, AndroidResource>()
|
||||
val resourcesToExclude = hashSetOf<String>()
|
||||
|
||||
+5
-5
@@ -47,9 +47,9 @@ class CliSyntheticFileGeneratorForConversionTest(
|
||||
project: Project,
|
||||
manifestPath: String,
|
||||
resDirectories: List<String>,
|
||||
supportV4: Boolean
|
||||
) : CliSyntheticFileGenerator(project, manifestPath, resDirectories, supportV4) {
|
||||
fun gen(scope: GlobalSearchScope) = generateSyntheticFiles(false, scope)
|
||||
private val supportV4: Boolean
|
||||
) : CliSyntheticFileGenerator(project, manifestPath, resDirectories) {
|
||||
fun gen(scope: GlobalSearchScope) = generateSyntheticFiles(false, scope, supportV4)
|
||||
}
|
||||
|
||||
fun UsefulTestCase.createAndroidTestEnvironment(
|
||||
@@ -61,7 +61,7 @@ fun UsefulTestCase.createAndroidTestEnvironment(
|
||||
configuration.put(AndroidConfigurationKeys.ANDROID_RES_PATH, resPaths)
|
||||
configuration.put(AndroidConfigurationKeys.ANDROID_MANIFEST, manifestPath)
|
||||
|
||||
val myEnvironment = KotlinCoreEnvironment.createForTests(getTestRootDisposable()!!, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
val myEnvironment = KotlinCoreEnvironment.createForTests(testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
val project = myEnvironment.project
|
||||
|
||||
val declarationsProvider = AndroidTestExternalDeclarationsProvider(project, resPaths, manifestPath, supportV4)
|
||||
@@ -72,5 +72,5 @@ fun UsefulTestCase.createAndroidTestEnvironment(
|
||||
}
|
||||
|
||||
fun getResPaths(path: String): List<String> {
|
||||
return File(path).listFiles { it.name.startsWith("res") && it.isDirectory() }!!.map { "$path${it.name}/" }
|
||||
return File(path).listFiles { it.name.startsWith("res") && it.isDirectory }!!.map { "$path${it.name}/" }
|
||||
}
|
||||
+2
-10
@@ -23,7 +23,6 @@ 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
|
||||
@@ -33,23 +32,16 @@ import org.jetbrains.kotlin.psi.JetFile
|
||||
|
||||
class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(module.project) {
|
||||
|
||||
private val supportV4: Boolean
|
||||
|
||||
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 {
|
||||
Result.create(generateSyntheticJetFiles(generateSyntheticFiles(true, moduleScope)), psiTreeChangePreprocessor)
|
||||
val supportV4 = supportV4Available(javaPsiFacade, moduleScope)
|
||||
Result.create(generateSyntheticJetFiles(generateSyntheticFiles(true, moduleScope, supportV4)), psiTreeChangePreprocessor)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
supportV4 = javaPsiFacade.findClasses(AndroidConst.SUPPORT_FRAGMENT_FQNAME, moduleScope).isNotEmpty()
|
||||
}
|
||||
|
||||
override fun supportV4() = supportV4
|
||||
|
||||
override val layoutXmlFileManager: IDEAndroidLayoutXmlFileManager = IDEAndroidLayoutXmlFileManager(module)
|
||||
|
||||
private val psiTreeChangePreprocessor by lazy {
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase()
|
||||
"$path${it.name}/"
|
||||
}
|
||||
|
||||
val cliParser = CliSyntheticFileGenerator(project, "$path../AndroidManifest.xml", resDirs, false)
|
||||
val cliParser = CliSyntheticFileGenerator(project, "$path../AndroidManifest.xml", resDirs)
|
||||
val ideParser = IDESyntheticFileGenerator(ModuleManager.getInstance(project).getModules()[0])
|
||||
|
||||
val cliResult = cliParser.getSyntheticFiles().joinToString("\n\n")
|
||||
|
||||
@@ -23,9 +23,6 @@ import org.jetbrains.jps.model.module.JpsModule
|
||||
import java.io.File
|
||||
import org.jetbrains.jps.android.AndroidJpsUtil
|
||||
import com.intellij.util.PathUtil
|
||||
import org.jetbrains.jps.model.library.JpsOrderRootType
|
||||
import org.jetbrains.jps.model.module.JpsLibraryDependency
|
||||
import org.jetbrains.jps.model.module.JpsModuleDependency
|
||||
|
||||
public class KotlinAndroidJpsPlugin : KotlinJpsCompilerArgumentsProvider {
|
||||
override fun getExtraArguments(moduleBuildTarget: ModuleBuildTarget, context: CompileContext): List<String> {
|
||||
@@ -33,27 +30,13 @@ public class KotlinAndroidJpsPlugin : KotlinJpsCompilerArgumentsProvider {
|
||||
val pluginId = ANDROID_COMPILER_PLUGIN_ID
|
||||
val resPath = getAndroidResPath(module)
|
||||
val manifestFile = getAndroidManifest(module)
|
||||
val supportV4 = if (isSupportV4LibraryAttached(module)) "true" else "false"
|
||||
|
||||
return if (resPath != null && manifestFile != null) listOf(
|
||||
getPluginOptionString(pluginId, RESOURCE_PATH_OPTION_NAME, resPath),
|
||||
getPluginOptionString(pluginId, MANIFEST_FILE_OPTION_NAME, manifestFile),
|
||||
getPluginOptionString(pluginId, SUPPORT_V4_OPTION_NAME, supportV4))
|
||||
getPluginOptionString(pluginId, MANIFEST_FILE_OPTION_NAME, manifestFile))
|
||||
else listOf()
|
||||
}
|
||||
|
||||
private fun isSupportV4LibraryAttached(module: JpsModule): Boolean {
|
||||
return module.getDependenciesList().getDependencies().any { dep ->
|
||||
when (dep) {
|
||||
is JpsLibraryDependency ->
|
||||
dep.getLibrary()?.getFiles(JpsOrderRootType.COMPILED)?.any {
|
||||
it.name.startsWith("support-v4") && it.extension.toUpperCase() == "JAR"
|
||||
} ?: false
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getClasspath(moduleBuildTarget: ModuleBuildTarget, context: CompileContext): List<String> {
|
||||
val inJar = File(PathUtil.getJarPathForClass(javaClass)).isFile()
|
||||
val manifestFile = getAndroidManifest(moduleBuildTarget.getModule())
|
||||
@@ -88,7 +71,6 @@ public class KotlinAndroidJpsPlugin : KotlinJpsCompilerArgumentsProvider {
|
||||
|
||||
private val RESOURCE_PATH_OPTION_NAME = "androidRes"
|
||||
private val MANIFEST_FILE_OPTION_NAME = "androidManifest"
|
||||
private val SUPPORT_V4_OPTION_NAME = "supportV4"
|
||||
|
||||
private fun getPluginOptionString(pluginId: String, key: String, value: String): String {
|
||||
return "plugin:$pluginId:$key=$value"
|
||||
|
||||
Reference in New Issue
Block a user