From 231aaa0a72b21abcbb02d9e8c1654ac9c15602e6 Mon Sep 17 00:00:00 2001 From: Perry Nguyen Date: Mon, 18 Jul 2016 10:38:28 -0700 Subject: [PATCH] Add aar support when importing sbt-android --- .../scala/org/jetbrains/sbt/CreateTasks.scala | 2 +- .../org/jetbrains/sbt/StructureKeys.scala | 2 +- .../AndroidSdkPluginExtractor.scala | 27 ++++++++++++++++--- .../sbt/extractors/ProjectExtractor.scala | 20 +++++++++++--- .../org/jetbrains/sbt/structure/data.scala | 5 +++- .../sbt/structure/dataSerializers.scala | 2 +- 6 files changed, 46 insertions(+), 12 deletions(-) diff --git a/extractor/src/main/scala/org/jetbrains/sbt/CreateTasks.scala b/extractor/src/main/scala/org/jetbrains/sbt/CreateTasks.scala index f6601901..ac9faff5 100644 --- a/extractor/src/main/scala/org/jetbrains/sbt/CreateTasks.scala +++ b/extractor/src/main/scala/org/jetbrains/sbt/CreateTasks.scala @@ -18,7 +18,7 @@ object CreateTasks extends (State => State) with SbtStateOps { UtilityTasks.acceptedProjects, StructureKeys.extractProjects <<= (Keys.state, StructureKeys.acceptedProjects) flatMap { (state, acceptedProjects) => - StructureKeys.extractProject.forAllProjects(state, acceptedProjects).map(_.values.toSeq) + StructureKeys.extractProject.forAllProjects(state, acceptedProjects).map(_.values.toSeq.flatten) }, StructureKeys.extractRepository <<= RepositoryExtractor.taskDef, diff --git a/extractor/src/main/scala/org/jetbrains/sbt/StructureKeys.scala b/extractor/src/main/scala/org/jetbrains/sbt/StructureKeys.scala index 5e790cca..fb8007f7 100644 --- a/extractor/src/main/scala/org/jetbrains/sbt/StructureKeys.scala +++ b/extractor/src/main/scala/org/jetbrains/sbt/StructureKeys.scala @@ -18,7 +18,7 @@ object StructureKeys { lazy val extractAndroid = TaskKey[Option[AndroidData]]("ss-extract-android") lazy val extractBuild = TaskKey[BuildData]("ss-extract-build") lazy val extractDependencies = TaskKey[DependencyData]("ss-extract-dependencies") - lazy val extractProject = TaskKey[ProjectData]("ss-extract-project") + lazy val extractProject = TaskKey[Seq[ProjectData]]("ss-extract-project") lazy val extractProjects = TaskKey[Seq[ProjectData]]("ss-extract-projects") lazy val extractRepository = TaskKey[Option[RepositoryData]]("ss-extract-repository") diff --git a/extractor/src/main/scala/org/jetbrains/sbt/extractors/AndroidSdkPluginExtractor.scala b/extractor/src/main/scala/org/jetbrains/sbt/extractors/AndroidSdkPluginExtractor.scala index 85ef3ea5..a5903278 100644 --- a/extractor/src/main/scala/org/jetbrains/sbt/extractors/AndroidSdkPluginExtractor.scala +++ b/extractor/src/main/scala/org/jetbrains/sbt/extractors/AndroidSdkPluginExtractor.scala @@ -5,7 +5,7 @@ package extractors import java.io.File -import org.jetbrains.sbt.structure.{ApkLib, AndroidData} +import org.jetbrains.sbt.structure.{Aar, ApkLib, AndroidData, BuildData, ConfigurationData, DependencyData, DirectoryData, ProjectData} import sbt._ import sbt.Project.Initialize @@ -27,6 +27,8 @@ object AndroidSdkPluginExtractor extends SbtStateOps with TaskOps { .flatMap(_.in(projectRef).find(state)) val apklibsAsAnyTaskOpt = findTaskKeyIn(keys, "apklibs") .flatMap(_.in(projectRef).find(state)) + val aarsAsAnyTaskOpt = findTaskKeyIn(keys, "aars") + .flatMap(_.in(projectRef).find(state)) val androidTaskOpt = for { manifestTask <- manifestFileTaskOpt @@ -34,7 +36,7 @@ object AndroidSdkPluginExtractor extends SbtStateOps with TaskOps { isLibrary <- Keys.libraryProject.in(projectRef).find(state) layoutAsAny <- layoutAsAnyOpt apklibsAsAnyTask <- apklibsAsAnyTaskOpt - targetVersionTask <- targetVersionTaskOpt + aarsAsAnyTask <- aarsAsAnyTaskOpt proguardConfigTask <- Keys.proguardConfig.in(projectRef).find(state) proguardOptionsTask <- Keys.proguardOptions.in(projectRef).find(state) } yield { @@ -44,14 +46,16 @@ object AndroidSdkPluginExtractor extends SbtStateOps with TaskOps { proguardConfig <- proguardConfigTask proguardOptions <- proguardOptionsTask apklibsAsAny <- apklibsAsAnyTask + aarsAsAny <- aarsAsAnyTask } yield { try { - val layout = layoutAsAny.asInstanceOf[ProjectLayout] + val layout = layoutAsAny.asInstanceOf[ProjectLayout] val apklibs = apklibsAsAny.asInstanceOf[Seq[LibraryDependency]] + val aars = aarsAsAny.asInstanceOf[Seq[LibraryDependency]].map(libraryDepToAar(targetVersion) _) Some(AndroidData(targetVersion, manifest, apk, layout.res, layout.assets, layout.gen, layout.libs, isLibrary, proguardConfig ++ proguardOptions, - apklibs.map(libraryDepToApkLib))) + apklibs.map(libraryDepToApkLib), aars)) } catch { case _ : NoSuchMethodException => None } @@ -79,14 +83,17 @@ object AndroidSdkPluginExtractor extends SbtStateOps with TaskOps { def res: File def assets: File def gen: File + def bin: File def libs: File def sources: File + def resources: File def manifest: File } private type LibraryDependency = { def layout: ProjectLayout def getName: String + def getJarFile: File } private def findSettingKeyIn(keys: Seq[sbt.ScopedKey[_]], label: String): Option[SettingKey[Any]] = @@ -103,6 +110,18 @@ object AndroidSdkPluginExtractor extends SbtStateOps with TaskOps { ApkLib(fixedLibName, lib.layout.base, lib.layout.manifest, lib.layout.sources, lib.layout.res, lib.layout.libs, lib.layout.gen) } + private def libraryDepToAar(targetSdkVersion: String)(lib: LibraryDependency): Aar = { + val fixedLibName = lib.getName.split(File.separatorChar).last + val android = AndroidData(targetSdkVersion, lib.layout.manifest, lib.layout.base, + lib.layout.res, lib.layout.assets, lib.layout.gen, lib.layout.libs, + true, Nil, Nil, Nil) + val project = ProjectData(fixedLibName, fixedLibName, "sbt-android-synthetic-organization", "0.1-SNAPSHOT-sbt-android", + lib.layout.base, Nil, lib.layout.bin, BuildData(Nil, Nil, Nil, Nil), + ConfigurationData("compile", Seq(DirectoryData(lib.layout.sources, true)), Seq(DirectoryData(lib.layout.resources, true)), Nil, lib.getJarFile) :: Nil, None, None, Some(android), + DependencyData(Nil, Nil, Nil), Set.empty, None) + Aar(fixedLibName, project) + } + private def isInAndroidScope(key: ScopedKey[_]) = key.scope.config match { case Select(k) => k.name == Android.name case _ => false diff --git a/extractor/src/main/scala/org/jetbrains/sbt/extractors/ProjectExtractor.scala b/extractor/src/main/scala/org/jetbrains/sbt/extractors/ProjectExtractor.scala index 631d7531..0af89f22 100644 --- a/extractor/src/main/scala/org/jetbrains/sbt/extractors/ProjectExtractor.scala +++ b/extractor/src/main/scala/org/jetbrains/sbt/extractors/ProjectExtractor.scala @@ -3,7 +3,7 @@ package extractors import org.jetbrains.sbt.structure._ import sbt.Project.Initialize -import sbt._ +import sbt.{Configuration => _, _} /** * @author Nikolay Obedin @@ -36,15 +36,27 @@ class ProjectExtractor(projectRef: ProjectRef, play2: Option[Play2Data]) { - private[extractors] def extract: ProjectData = { + private[extractors] def extract: Seq[ProjectData] = { val resolvers = fullResolvers.collect { case MavenRepository(name, root) => ResolverData(name, root) }.toSet val configurations = mergeConfigurations(sourceConfigurations.flatMap(extractConfiguration)) - ProjectData(projectRef.id, name, organization, version, base, + val projectData = ProjectData(projectRef.id, name, organization, version, base, basePackages, target, build, configurations, extractJava, extractScala, android, dependencies, resolvers, play2) + android.fold(Seq(projectData)) { a => + val deps = a.aars.map(aar => ProjectDependencyData(aar.name, Configuration.Compile :: Nil)) + // add aar module dependencies + val updatedProject = projectData.copy(dependencies = dependencies.copy(projects = projectData.dependencies.projects ++ deps)) + updatedProject +: a.aars.map(_.project.copy( + java = projectData.java, + scala = projectData.scala, + build = projectData.build, + resolvers = projectData.resolvers, + dependencies = projectData.dependencies + )) + } } private def extractConfiguration(configuration: sbt.Configuration): Option[ConfigurationData] = @@ -91,7 +103,7 @@ class ProjectExtractor(projectRef: ProjectRef, object ProjectExtractor extends SbtStateOps with TaskOps { - def taskDef: Initialize[Task[ProjectData]] = + def taskDef: Initialize[Task[Seq[ProjectData]]] = ( sbt.Keys.state , sbt.Keys.thisProjectRef , StructureKeys.sbtStructureOpts diff --git a/shared/src/main/scala/org/jetbrains/sbt/structure/data.scala b/shared/src/main/scala/org/jetbrains/sbt/structure/data.scala index 4cefd2a6..944ac863 100644 --- a/shared/src/main/scala/org/jetbrains/sbt/structure/data.scala +++ b/shared/src/main/scala/org/jetbrains/sbt/structure/data.scala @@ -164,7 +164,10 @@ case class AndroidData(targetVersion: String, libs: File, isLibrary: Boolean, proguardConfig: Seq[String], - apklibs: Seq[ApkLib]) + apklibs: Seq[ApkLib], + aars: Seq[Aar]) + +case class Aar(name: String, project: ProjectData) /** * Information about certain apklib used in Android project diff --git a/shared/src/main/scala/org/jetbrains/sbt/structure/dataSerializers.scala b/shared/src/main/scala/org/jetbrains/sbt/structure/dataSerializers.scala index f59e3722..84478f5d 100644 --- a/shared/src/main/scala/org/jetbrains/sbt/structure/dataSerializers.scala +++ b/shared/src/main/scala/org/jetbrains/sbt/structure/dataSerializers.scala @@ -298,7 +298,7 @@ trait DataSerializers { val apklibs = (what \ "apkLib").deserialize[ApkLib] Right(AndroidData(version, file(manifestPath), file(apkPath), file(resPath), file(assetsPath), file(genPath), - file(libsPath), isLibrary, proguardConfig, apklibs)) + file(libsPath), isLibrary, proguardConfig, apklibs, Nil)) } }