diff --git a/idea/src/META-INF/android.xml b/idea/src/META-INF/android.xml index 29613450d0e..34f5f836571 100644 --- a/idea/src/META-INF/android.xml +++ b/idea/src/META-INF/android.xml @@ -99,4 +99,8 @@ + + + + diff --git a/idea/src/META-INF/extensions/ide.xml b/idea/src/META-INF/extensions/ide.xml index 51d03d52c76..cdf672a0cb9 100644 --- a/idea/src/META-INF/extensions/ide.xml +++ b/idea/src/META-INF/extensions/ide.xml @@ -11,6 +11,10 @@ interface="org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.AndroidDexer" area="IDEA_PROJECT"/> + + diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/model/AndroidModuleInfoProvider.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/model/AndroidModuleInfoProvider.kt new file mode 100644 index 00000000000..f072092f9f6 --- /dev/null +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/model/AndroidModuleInfoProvider.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.android.model + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleUtilCore +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiElement +import java.io.File + +val Module.isAndroidModule + + get() = AndroidModuleInfoProvider.getInstance(this)?.isAndroidModule() ?: false + +interface AndroidModuleInfoProvider { + companion object { + val EP_NAME = ExtensionPointName.create("org.jetbrains.kotlin.android.model.androidModuleInfoProvider") + + fun getInstance(module: Module): AndroidModuleInfoProvider? { + val extensionArea = Extensions.getArea(module) + if (!extensionArea.hasExtensionPoint(EP_NAME.name)) { + return null + } + return extensionArea.getExtensionPoint(EP_NAME).extension + } + + fun getInstance(element: PsiElement): AndroidModuleInfoProvider? { + val module = ApplicationManager.getApplication().runReadAction { + ModuleUtilCore.findModuleForPsiElement(element) + } + return getInstance(module) + } + } + + val module: Module + + fun isAndroidModule(): Boolean + fun isGradleModule(): Boolean + + fun getApplicationPackage(): String? + + // For old Android Extensions + fun getMainSourceProvider(): SourceProviderMirror? + fun getFlavorSourceProviders(): List + fun getAllResourceDirectories(): List + + // For experimental Android Extensions + fun getApplicationResourceDirectories(createIfNecessary: Boolean): Collection + fun getAllSourceProviders(): List + fun getActiveSourceProviders(): List + + + interface SourceProviderMirror { + val name: String + val resDirectories: Collection + } +} + diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/model/impl/AndroidModuleInfoProviderImpl.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/model/impl/AndroidModuleInfoProviderImpl.kt new file mode 100644 index 00000000000..548206fdc8e --- /dev/null +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/model/impl/AndroidModuleInfoProviderImpl.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.android.model.impl + +import com.android.builder.model.SourceProvider +import com.android.tools.idea.gradle.project.GradleProjectInfo +import com.android.tools.idea.gradle.project.model.AndroidModuleModel +import com.intellij.openapi.module.Module +import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.android.facet.AndroidFacet +import org.jetbrains.kotlin.android.model.AndroidModuleInfoProvider +import java.io.File + +class AndroidModuleInfoProviderImpl(override val module: Module) : AndroidModuleInfoProvider { + private val androidFacet: AndroidFacet? + get() = AndroidFacet.getInstance(module) + + private val androidModuleModel: AndroidModuleModel? + get() = AndroidModuleModel.get(module) + + override fun isAndroidModule() = androidFacet != null + override fun isGradleModule() = GradleProjectInfo.getInstance(module.project).isBuildWithGradle + + override fun getAllResourceDirectories(): List { + return androidFacet?.allResourceDirectories ?: emptyList() + } + + override fun getApplicationPackage() = androidFacet?.manifest?.`package`?.toString() + + override fun getMainSourceProvider(): AndroidModuleInfoProvider.SourceProviderMirror? { + return androidFacet?.mainSourceProvider?.let(::SourceProviderMirrorImpl) + } + + override fun getApplicationResourceDirectories(createIfNecessary: Boolean): Collection { + return androidFacet?.getAppResources(createIfNecessary)?.resourceDirs ?: emptyList() + } + + override fun getAllSourceProviders(): List { + val androidModuleModel = this.androidModuleModel ?: return emptyList() + return androidModuleModel.allSourceProviders.map(::SourceProviderMirrorImpl) + } + + override fun getActiveSourceProviders(): List { + val androidModuleModel = this.androidModuleModel ?: return emptyList() + return androidModuleModel.activeSourceProviders.map(::SourceProviderMirrorImpl) + } + + override fun getFlavorSourceProviders(): List { + val androidModuleModel = this.androidModuleModel ?: return emptyList() + + val getFlavorSourceProvidersMethod = try { + AndroidFacet::class.java.getMethod("getFlavorSourceProviders") + } catch (e: NoSuchMethodException) { + null + } + + return if (getFlavorSourceProvidersMethod != null) { + @Suppress("UNCHECKED_CAST") + val sourceProviders = getFlavorSourceProvidersMethod.invoke(androidFacet) as? List + sourceProviders?.map(::SourceProviderMirrorImpl) ?: emptyList() + } else { + androidModuleModel.flavorSourceProviders.map(::SourceProviderMirrorImpl) + } + } + + private class SourceProviderMirrorImpl(val sourceProvider: SourceProvider) : + AndroidModuleInfoProvider.SourceProviderMirror { + override val name: String + get() = sourceProvider.name + + override val resDirectories: Collection + get() = sourceProvider.resDirectories + } +} \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/quickfixes/ParcelableAddSupertypeQuickfix.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/quickfixes/ParcelableAddSupertypeQuickfix.kt index d75b6745b29..a9a766a0b2c 100644 --- a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/quickfixes/ParcelableAddSupertypeQuickfix.kt +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/quickfixes/ParcelableAddSupertypeQuickfix.kt @@ -16,7 +16,7 @@ package org.jetbrains.kotlin.android.parcel.quickfixes -import com.android.SdkConstants.CLASS_PARCELABLE +import org.jetbrains.kotlin.android.parcel.ANDROID_PARCELABLE_CLASS_FQNAME import org.jetbrains.kotlin.psi.* class ParcelableAddSupertypeQuickfix(clazz: KtClassOrObject) : AbstractParcelableQuickFix(clazz) { @@ -24,6 +24,7 @@ class ParcelableAddSupertypeQuickfix(clazz: KtClassOrObject) : AbstractParcelabl override fun getText() = "Add ''Parcelable'' supertype" override fun invoke(ktPsiFactory: KtPsiFactory, element: KtClassOrObject) { - element.addSuperTypeListEntry(ktPsiFactory.createSuperTypeEntry(CLASS_PARCELABLE)).shortenReferences() + val supertypeName = ANDROID_PARCELABLE_CLASS_FQNAME.asString() + element.addSuperTypeListEntry(ktPsiFactory.createSuperTypeEntry(supertypeName)).shortenReferences() } } \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt index c5e89df0354..41bf4a44b45 100644 --- a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt @@ -19,8 +19,7 @@ package org.jetbrains.kotlin.android.synthetic.idea import com.intellij.psi.PsiElement import com.intellij.psi.xml.XmlAttributeValue import com.intellij.psi.xml.XmlFile -import org.jetbrains.android.facet.AndroidFacet -import org.jetbrains.android.util.AndroidResourceUtil +import org.jetbrains.kotlin.android.model.AndroidModuleInfoProvider import org.jetbrains.kotlin.android.synthetic.AndroidConst import org.jetbrains.kotlin.android.synthetic.androidIdToName import org.jetbrains.kotlin.idea.references.KtSimpleNameReference @@ -41,7 +40,7 @@ class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension { override fun handleElementRename(reference: KtSimpleNameReference, psiFactory: KtPsiFactory, newElementName: String): PsiElement? { val resolvedElement = reference.resolve() - if (resolvedElement is XmlAttributeValue && AndroidResourceUtil.isIdDeclaration(resolvedElement)) { + if (resolvedElement is XmlAttributeValue && isIdDeclaration(resolvedElement)) { val newSyntheticPropertyName = androidIdToName(newElementName) ?: return null return psiFactory.createNameIdentifier(newSyntheticPropertyName.name) } @@ -52,6 +51,8 @@ class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension { return null } + private fun isIdDeclaration(declaration: XmlAttributeValue) = declaration.value?.startsWith("@+id/") ?: false + private fun KtSimpleNameReference.isReferenceToXmlFile(xmlFile: XmlFile): Boolean { if (!isLayoutPackageIdentifier(this)) { return false @@ -67,7 +68,7 @@ class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension { return false } - val resourceDirectories = AndroidFacet.getInstance(element)?.allResourceDirectories ?: return false + val resourceDirectories = AndroidModuleInfoProvider.getInstance(element)?.getAllResourceDirectories() ?: return false val resourceDirectory = virtualFile.parent?.parent ?: return false return resourceDirectories.any { it == resourceDirectory } } diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/ExperimentalUtils.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/ExperimentalUtils.kt index 2d5ad64dc5a..e7b35d595f1 100644 --- a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/ExperimentalUtils.kt +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/ExperimentalUtils.kt @@ -19,8 +19,9 @@ package org.jetbrains.kotlin.android.synthetic.idea import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.module.Module import kotlinx.android.extensions.CacheImplementation -import org.jetbrains.android.facet.AndroidFacet import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.android.model.AndroidModuleInfoProvider +import org.jetbrains.kotlin.android.model.isAndroidModule import org.jetbrains.kotlin.android.synthetic.AndroidCommandLineProcessor.Companion.ANDROID_COMPILER_PLUGIN_ID import org.jetbrains.kotlin.android.synthetic.AndroidCommandLineProcessor.Companion.EXPERIMENTAL_OPTION import org.jetbrains.kotlin.android.synthetic.AndroidCommandLineProcessor.Companion.ENABLED_OPTION @@ -46,7 +47,7 @@ private fun Module.getOptionValueInFacet(option: CliOption): String? { } private fun isTestMode(module: Module): Boolean { - return ApplicationManager.getApplication().isUnitTestMode && AndroidFacet.getInstance(module) != null + return ApplicationManager.getApplication().isUnitTestMode && module.isAndroidModule } internal val Module.androidExtensionsIsEnabled: Boolean diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt index 5a8ce10fc7a..c93b0ad7cf1 100644 --- a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt @@ -16,15 +16,14 @@ package org.jetbrains.kotlin.android.synthetic.idea.res -import com.android.builder.model.SourceProvider -import com.android.tools.idea.gradle.project.model.AndroidModuleModel import com.intellij.openapi.module.Module import com.intellij.openapi.roots.ProjectRootModificationTracker import com.intellij.psi.PsiElement import com.intellij.psi.impl.PsiTreeChangePreprocessor import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider -import org.jetbrains.android.facet.AndroidFacet +import org.jetbrains.kotlin.android.model.AndroidModuleInfoProvider +import org.jetbrains.kotlin.android.model.AndroidModuleInfoProvider.SourceProviderMirror import org.jetbrains.kotlin.android.synthetic.AndroidConst.SYNTHETIC_PACKAGE_PATH_LENGTH import org.jetbrains.kotlin.android.synthetic.idea.AndroidPsiTreeChangePreprocessor import org.jetbrains.kotlin.android.synthetic.idea.AndroidXmlVisitor @@ -37,7 +36,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileManager(module.project) { override val androidModule: AndroidModule? - get() = AndroidFacet.getInstance(module)?.let { getAndroidModuleInfo(it) } + get() = AndroidModuleInfoProvider.getInstance(module)?.let { getAndroidModuleInfo(it) } @Volatile private var _moduleData: CachedValue? = null @@ -108,56 +107,45 @@ class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileM return listOf() } - private fun SourceProvider.toVariant() = AndroidVariant(name, resDirectories.map { it.canonicalPath }) + private fun SourceProviderMirror.toVariant() = AndroidVariant(name, resDirectories.map { it.canonicalPath }) - private fun getAndroidModuleInfo(androidFacet: AndroidFacet): AndroidModule? { - if (androidFacet.module.androidExtensionsIsExperimental) { - return getAndroidModuleInfoExperimental(androidFacet) + private fun getAndroidModuleInfo(androidInfoProvider: AndroidModuleInfoProvider): AndroidModule? { + if (androidInfoProvider.module.androidExtensionsIsExperimental) { + return getAndroidModuleInfoExperimental(androidInfoProvider) } - val applicationPackage = androidFacet.manifest?.`package`?.toString() + val applicationPackage = androidInfoProvider.getApplicationPackage() if (applicationPackage != null) { - val mainVariant = androidFacet.mainSourceProvider.toVariant() + val mainVariant = androidInfoProvider.getMainSourceProvider()?.toVariant() + val variantsForFlavorts = androidInfoProvider.getFlavorSourceProviders().map { it.toVariant() } + val allVariants = listOfNotNull(mainVariant) + variantsForFlavorts - val method = try { androidFacet::class.java.getMethod("getFlavorSourceProviders") } catch (e: NoSuchMethodException) { null } - val variants: List? = if (method != null) { - val sourceProviders = method.invoke(androidFacet) as List? - sourceProviders?.map { it.toVariant() } ?: listOf() - } - else { - val model = AndroidModuleModel.get(androidFacet.module) - model?.flavorSourceProviders?.map { it.toVariant() } ?: listOf(androidFacet.mainSourceProvider.toVariant()) - } - - if (variants != null) { - return AndroidModule(applicationPackage, listOf(mainVariant) + variants) + if (allVariants.isNotEmpty()) { + return AndroidModule(applicationPackage, allVariants) } } return null } - private fun getAndroidModuleInfoExperimental(androidFacet: AndroidFacet): AndroidModule? { - val applicationPackage = androidFacet.manifest?.`package`?.toString() ?: return null - - val allResDirectories = androidFacet.getAppResources(true)?.resourceDirs.orEmpty().mapNotNull { it.canonicalPath } + private fun getAndroidModuleInfoExperimental(androidFacet: AndroidModuleInfoProvider): AndroidModule? { + val applicationPackage = androidFacet.getApplicationPackage() ?: return null + val appResourceDirectories = androidFacet.getApplicationResourceDirectories(true).mapNotNull { it.canonicalPath } val resDirectoriesForMainVariant = androidFacet.run { - val resDirsFromSourceProviders = AndroidModuleModel.get(this.module)?.allSourceProviders.orEmpty() - .filter { it.name != "main" } - .flatMap { it.resDirectories } - .map { it.canonicalPath } + val resDirsFromSourceProviders = androidFacet.getAllSourceProviders() + .filter { it.name != "main" } + .flatMap { it.resDirectories } + .map { it.canonicalPath } - allResDirectories - resDirsFromSourceProviders + appResourceDirectories - resDirsFromSourceProviders } val variants = mutableListOf(AndroidVariant("main", resDirectoriesForMainVariant)) - AndroidModuleModel.get(androidFacet.module)?.let { androidGradleModel -> - androidGradleModel.activeSourceProviders.filter { it.name != "main" }.forEach { sourceProvider -> - variants += sourceProvider.toVariant() - } - } + androidFacet.getActiveSourceProviders() + .filter { it.name != "main" } + .forEach { sourceProvider -> variants += sourceProvider.toVariant() } return AndroidModule(applicationPackage, variants) } diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidPackageFragmentProviderExtension.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidPackageFragmentProviderExtension.kt index 85cd3cc01e3..d228f4aaa39 100644 --- a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidPackageFragmentProviderExtension.kt +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidPackageFragmentProviderExtension.kt @@ -16,12 +16,12 @@ package org.jetbrains.kotlin.android.synthetic.idea.res -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleServiceManager import com.intellij.openapi.project.Project -import org.jetbrains.android.facet.AndroidFacet import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.android.model.AndroidModuleInfoProvider +import org.jetbrains.kotlin.android.model.isAndroidModule import org.jetbrains.kotlin.android.synthetic.idea.androidExtensionsIsEnabled import org.jetbrains.kotlin.android.synthetic.idea.androidExtensionsIsExperimental import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager @@ -36,14 +36,10 @@ class IDEAndroidPackageFragmentProviderExtension(val project: Project) : Android override fun getLayoutXmlFileManager(project: Project, moduleInfo: ModuleInfo?): AndroidLayoutXmlFileManager? { val moduleSourceInfo = moduleInfo as? ModuleSourceInfo ?: return null val module = moduleSourceInfo.module - if (!isAndroidExtensionsEnabled(module) && !isTestMode(module)) return null + if (!isAndroidExtensionsEnabled(module)) return null return ModuleServiceManager.getService(module, AndroidLayoutXmlFileManager::class.java) } - private fun isTestMode(module: Module): Boolean { - return ApplicationManager.getApplication().isUnitTestMode && AndroidFacet.getInstance(module) != null - } - private fun isAndroidExtensionsEnabled(module: Module): Boolean { // Android Extensions should be always enabled for Android/JPS if (isLegacyIdeaAndroidModule(module)) return true @@ -51,7 +47,7 @@ class IDEAndroidPackageFragmentProviderExtension(val project: Project) : Android } private fun isLegacyIdeaAndroidModule(module: Module): Boolean { - val facet = AndroidFacet.getInstance(module) - return facet != null && !facet.requiresAndroidModel() + val infoProvider = AndroidModuleInfoProvider.getInstance(module) ?: return false + return infoProvider.isAndroidModule() && !infoProvider.isGradleModule() } } \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-jps/build.gradle.kts b/plugins/android-extensions/android-extensions-jps/build.gradle.kts index 4aa39c892f7..7fb8d78f14e 100644 --- a/plugins/android-extensions/android-extensions-jps/build.gradle.kts +++ b/plugins/android-extensions/android-extensions-jps/build.gradle.kts @@ -10,7 +10,7 @@ dependencies { compile(project(":compiler:util")) compile(project(":jps-plugin")) compile(project(":plugins:android-extensions-compiler")) - compileOnly(intellijDep()) { includeJars("openapi", "jps-builders") } + compileOnly(intellijDep()) { includeJars("openapi", "jps-builders", "jps-model", "jdom") } compileOnly(intellijPluginDep("android")) { includeJars("jps/android-jps-plugin") } compile(intellijPluginDep("android")) { includeJars("jps/android-jps-plugin") } diff --git a/plugins/android-extensions/android-extensions-jps/src/KotlinAndroidJpsPlugin.kt b/plugins/android-extensions/android-extensions-jps/src/KotlinAndroidJpsPlugin.kt index ecdf408efa2..4a3be042ca6 100644 --- a/plugins/android-extensions/android-extensions-jps/src/KotlinAndroidJpsPlugin.kt +++ b/plugins/android-extensions/android-extensions-jps/src/KotlinAndroidJpsPlugin.kt @@ -17,7 +17,7 @@ package org.jetbrains.kotlin.android.jps import com.intellij.util.PathUtil -import org.jetbrains.jps.android.AndroidJpsUtil +import org.jetbrains.jps.android.model.base.AndroidExtensionsDataProvider import org.jetbrains.jps.incremental.CompileContext import org.jetbrains.jps.incremental.ModuleBuildTarget import org.jetbrains.jps.model.module.JpsModule @@ -37,23 +37,22 @@ class KotlinAndroidJpsPlugin : KotlinJpsCompilerArgumentsProvider { return if (resPath != null && applicationId != null) { listOf( - getPluginOptionString(pluginId, VARIANT_OPTION_NAME, "main;$resPath"), - getPluginOptionString(pluginId, PACKAGE_OPTION_NAME, applicationId)) - } - else emptyList() + getPluginOptionString(pluginId, VARIANT_OPTION_NAME, "main;$resPath"), + getPluginOptionString(pluginId, PACKAGE_OPTION_NAME, applicationId) + ) + } else emptyList() } private fun isAndroidModuleWithoutGradle(module: JpsModule): Boolean { - val androidFacet = AndroidJpsUtil.getExtension(module) ?: return false - return !androidFacet.isGradleProject + val androidFacet = AndroidExtensionsDataProvider.getExtension(module) ?: return false + return !androidFacet.isGradleProject() } private fun hasAndroidJpsPlugin(): Boolean { try { Class.forName(ANDROID_JPS_UTIL_CLASS_FQNAME) return true - } - catch (e: ClassNotFoundException) { + } catch (e: ClassNotFoundException) { return false } } @@ -78,35 +77,31 @@ class KotlinAndroidJpsPlugin : KotlinJpsCompilerArgumentsProvider { } listOf(compilerPluginJar.absolutePath) - } - else emptyList() + } else emptyList() } private fun getAndroidResPath(module: JpsModule): String? { - val extension = AndroidJpsUtil.getExtension(module) ?: return null - return AndroidJpsUtil.getResourceDirForCompilationPath(extension)?.absolutePath + return AndroidExtensionsDataProvider.getExtension(module)?.getResourceDirForCompilationPath()?.absolutePath } private fun getAndroidManifest(module: JpsModule): File? { - val extension = AndroidJpsUtil.getExtension(module) ?: return null - return AndroidJpsUtil.getManifestFileForCompilationPath(extension) + return AndroidExtensionsDataProvider.getExtension(module)?.getManifestFileForCompilationPath() } companion object { - private val ANDROID_JPS_UTIL_CLASS_FQNAME = "org.jetbrains.jps.android.AndroidJpsUtil" + private const val ANDROID_JPS_UTIL_CLASS_FQNAME = "org.jetbrains.jps.android.AndroidJpsUtil" - private val JAR_FILE_NAME = "android-extensions-compiler.jar" - private val ANDROID_COMPILER_PLUGIN_ID = "org.jetbrains.kotlin.android" + private const val JAR_FILE_NAME = "android-extensions-compiler.jar" + private const val ANDROID_COMPILER_PLUGIN_ID = "org.jetbrains.kotlin.android" - private val VARIANT_OPTION_NAME = "variant" - private val PACKAGE_OPTION_NAME = "package" + private const val VARIANT_OPTION_NAME = "variant" + private const val PACKAGE_OPTION_NAME = "package" private fun getApplicationPackageFromManifest(manifestFile: File): String? { - try { - return manifestFile.parseXml().documentElement.getAttribute("package") - } - catch (e: Exception) { - return null + return try { + manifestFile.parseXml().documentElement.getAttribute("package") + } catch (e: Exception) { + null } } diff --git a/plugins/android-extensions/android-extensions-jps/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension b/plugins/android-extensions/android-extensions-jps/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension new file mode 100644 index 00000000000..544242116a5 --- /dev/null +++ b/plugins/android-extensions/android-extensions-jps/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension @@ -0,0 +1 @@ +org.jetbrains.jps.android.model.base.impl.AndroidExtensionDataProviderJpsModelSerializerExtension \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-jps/src/extensions/AndroidExtensionsDataProvider.kt b/plugins/android-extensions/android-extensions-jps/src/extensions/AndroidExtensionsDataProvider.kt new file mode 100644 index 00000000000..460d0e7aca0 --- /dev/null +++ b/plugins/android-extensions/android-extensions-jps/src/extensions/AndroidExtensionsDataProvider.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.jps.android.model.base + +import org.jetbrains.jps.model.JpsElement +import org.jetbrains.jps.model.ex.JpsElementChildRoleBase +import org.jetbrains.jps.model.module.JpsModule +import java.io.File + +interface AndroidExtensionsDataProvider : JpsElement { + companion object { + val KIND: JpsElementChildRoleBase = + JpsElementChildRoleBase.create("android extensions data provider") + + fun getExtension(module: JpsModule): AndroidExtensionsDataProvider? { + return module.container.getChild(KIND) + } + } + + fun isGradleProject(): Boolean + fun getResourceDirForCompilationPath(): File? + fun getManifestFileForCompilationPath(): File? +} + diff --git a/plugins/android-extensions/android-extensions-jps/src/extensions/impl/AndroidExtensionDataProviderJpsModelSerializerExtension.kt b/plugins/android-extensions/android-extensions-jps/src/extensions/impl/AndroidExtensionDataProviderJpsModelSerializerExtension.kt new file mode 100644 index 00000000000..ededa793730 --- /dev/null +++ b/plugins/android-extensions/android-extensions-jps/src/extensions/impl/AndroidExtensionDataProviderJpsModelSerializerExtension.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.jps.android.model.base.impl + +import org.jdom.Element +import org.jetbrains.jps.android.model.base.AndroidExtensionsDataProvider +import org.jetbrains.jps.model.module.JpsModule +import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension + +class AndroidExtensionDataProviderJpsModelSerializerExtension : JpsModelSerializerExtension() { + override fun loadModuleOptions(module: JpsModule, rootElement: Element) { + module.container.setChild(AndroidExtensionsDataProvider.KIND, AndroidExtensionsDataProviderImpl()) + } +} \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-jps/src/extensions/impl/AndroidExtensionsDataProviderImpl.kt b/plugins/android-extensions/android-extensions-jps/src/extensions/impl/AndroidExtensionsDataProviderImpl.kt new file mode 100644 index 00000000000..e2b1b2a02ea --- /dev/null +++ b/plugins/android-extensions/android-extensions-jps/src/extensions/impl/AndroidExtensionsDataProviderImpl.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.jps.android.model.base.impl + +import org.jetbrains.jps.android.AndroidJpsUtil +import org.jetbrains.jps.android.model.base.AndroidExtensionsDataProvider +import org.jetbrains.jps.model.ex.JpsElementBase +import org.jetbrains.jps.model.module.JpsModule +import java.io.File + +class AndroidExtensionsDataProviderImpl : JpsElementBase(), + AndroidExtensionsDataProvider { + private val module + get() = super.getParent() as JpsModule + + override fun applyChanges(modified: AndroidExtensionsDataProviderImpl) { + fireElementChanged() + } + + override fun createCopy(): AndroidExtensionsDataProviderImpl { + return AndroidExtensionsDataProviderImpl() + } + + private val androidExtension + get() = AndroidJpsUtil.getExtension(module) + + override fun isGradleProject(): Boolean { + return androidExtension?.isGradleProject ?: false + } + + override fun getResourceDirForCompilationPath(): File? { + val androidExtension = this.androidExtension ?: return null + return AndroidJpsUtil.getResourceDirForCompilationPath(androidExtension) + } + + override fun getManifestFileForCompilationPath(): File? { + val androidExtension = this.androidExtension ?: return null + return AndroidJpsUtil.getManifestFileForCompilationPath(androidExtension) + } +} \ No newline at end of file