From b8c88079ede994450cd8009b43ca9ca9b35213d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ko=C5=82aczkowski?= Date: Fri, 26 Jul 2019 21:49:37 +0200 Subject: [PATCH] Support javac processorpath. Import processorpath from Gradle. Fixes #962 --- backend/src/main/scala/bloop/Compiler.scala | 57 ++++++++++--------- .../src/main/scala/bloop/config/Config.scala | 8 ++- .../src/it/scala/bloop/CommunityBuild.scala | 1 + .../src/main/scala/bloop/data/Project.scala | 2 + .../bloop/engine/tasks/CompileTask.scala | 1 + .../tasks/compilation/CompileBundle.scala | 2 +- frontend/src/test/scala/bloop/DagSpec.scala | 2 +- .../test/scala/bloop/util/TestProject.scala | 1 + .../src/test/scala/bloop/util/TestUtil.scala | 3 +- .../gradle/model/BloopConverter.scala | 7 +++ .../gradle/ConfigGenerationSuite.scala | 42 ++++++++++++++ .../maven/MojoImplementation.scala | 2 +- .../bloop/integrations/mill/MillBloop.scala | 1 + .../bloop/integrations/sbt/SbtBloop.scala | 2 +- 14 files changed, 99 insertions(+), 32 deletions(-) diff --git a/backend/src/main/scala/bloop/Compiler.scala b/backend/src/main/scala/bloop/Compiler.scala index db230a3722..bba33e7c53 100644 --- a/backend/src/main/scala/bloop/Compiler.scala +++ b/backend/src/main/scala/bloop/Compiler.scala @@ -35,31 +35,32 @@ import bloop.CompileMode.Sequential import monix.execution.ExecutionModel case class CompileInputs( - javaInstance: JdkInstance, - scalaInstance: ScalaInstance, - compilerCache: CompilerCache, - sources: Array[AbsolutePath], - classpath: Array[AbsolutePath], - uniqueInputs: UniqueCompileInputs, - //store: IRStore, - out: CompileOutPaths, - baseDirectory: AbsolutePath, - scalacOptions: Array[String], - javacOptions: Array[String], - compileOrder: CompileOrder, - classpathOptions: ClasspathOptions, - previousResult: PreviousResult, - previousCompilerResult: Compiler.Result, - reporter: ZincReporter, - logger: ObservedLogger[Logger], - mode: CompileMode, - dependentResults: Map[File, PreviousResult], - cancelPromise: Promise[Unit], - tracer: BraveTracer, - ioScheduler: Scheduler, - ioExecutor: Executor, - invalidatedClassFilesInDependentProjects: Set[File], - generatedClassFilePathsInDependentProjects: Map[String, File] + javaInstance: JdkInstance, + scalaInstance: ScalaInstance, + compilerCache: CompilerCache, + sources: Array[AbsolutePath], + classpath: Array[AbsolutePath], + processorpath: Array[AbsolutePath], + uniqueInputs: UniqueCompileInputs, + //store: IRStore, + out: CompileOutPaths, + baseDirectory: AbsolutePath, + scalacOptions: Array[String], + javacOptions: Array[String], + compileOrder: CompileOrder, + classpathOptions: ClasspathOptions, + previousResult: PreviousResult, + previousCompilerResult: Compiler.Result, + reporter: ZincReporter, + logger: ObservedLogger[Logger], + mode: CompileMode, + dependentResults: Map[File, PreviousResult], + cancelPromise: Promise[Unit], + tracer: BraveTracer, + ioScheduler: Scheduler, + ioExecutor: Executor, + invalidatedClassFilesInDependentProjects: Set[File], + generatedClassFilePathsInDependentProjects: Map[String, File] ) case class CompileOutPaths( @@ -370,6 +371,10 @@ object Compiler { def getCompilationOptions(inputs: CompileInputs): CompileOptions = { val sources = inputs.sources // Sources are all files val classpath = inputs.classpath.map(_.toFile) + val annotationProcessorOptions = + if (inputs.processorpath.isEmpty) List.empty[String] + else List("-processorpath", inputs.processorpath.mkString(":")) + val javacOptions = inputs.javacOptions ++ annotationProcessorOptions CompileOptions .create() @@ -377,7 +382,7 @@ object Compiler { .withSources(sources.map(_.toFile)) .withClasspath(classpath) .withScalacOptions(inputs.scalacOptions) - .withJavacOptions(inputs.javacOptions) + .withJavacOptions(javacOptions) .withClasspathOptions(inputs.classpathOptions) .withOrder(inputs.compileOrder) } diff --git a/config/src/main/scala/bloop/config/Config.scala b/config/src/main/scala/bloop/config/Config.scala index e7a742c6e6..f17b5af8d2 100644 --- a/config/src/main/scala/bloop/config/Config.scala +++ b/config/src/main/scala/bloop/config/Config.scala @@ -219,6 +219,7 @@ object Config { sources: List[Path], dependencies: List[String], classpath: List[Path], + processorpath: List[Path], out: Path, classesDir: Path, resources: Option[List[Path]], @@ -232,7 +233,7 @@ object Config { object Project { // FORMAT: OFF - private[bloop] val empty: Project = Project("", emptyPath, List(), List(), List(), emptyPath, emptyPath, None, None, None, None, None, None, None) + private[bloop] val empty: Project = Project("", emptyPath, List(), List(), List(), List(), emptyPath, emptyPath, None, None, None, None, None, None, None) // FORMAT: ON def analysisFileName(projectName: String) = s"$projectName-analysis.bin" @@ -253,6 +254,10 @@ object Config { val scalaLibraryJar = Files.createTempFile("scala-library", ".jar") scalaLibraryJar.toFile.deleteOnExit() + val annotationProcessorJar = Files.createTempFile("annotation-processor", ".jar") + annotationProcessorJar.toFile.deleteOnExit() + + // This is like `target` in sbt. val outDir = Files.createTempFile("out", "test") outDir.toFile.deleteOnExit() @@ -274,6 +279,7 @@ object Config { List(sourceFile), List("dummy-2"), List(scalaLibraryJar), + List(annotationProcessorJar), outDir, classesDir, Some(List(outDir.resolve("resource1.xml"))), diff --git a/frontend/src/it/scala/bloop/CommunityBuild.scala b/frontend/src/it/scala/bloop/CommunityBuild.scala index 89ac78981e..e21111b49a 100644 --- a/frontend/src/it/scala/bloop/CommunityBuild.scala +++ b/frontend/src/it/scala/bloop/CommunityBuild.scala @@ -125,6 +125,7 @@ abstract class CommunityBuild(val buildpressHomeDir: AbsolutePath) { dependencies = allProjectsInBuild.map(_.name), scalaInstance = allProjectsInBuild.head.scalaInstance, rawClasspath = Nil, + annotationProcessorPath = Nil, resources = Nil, compileSetup = Config.CompileSetup.empty, genericClassesDir = dummyClassesDir, diff --git a/frontend/src/main/scala/bloop/data/Project.scala b/frontend/src/main/scala/bloop/data/Project.scala index 7597daebc5..b5e155a9d1 100644 --- a/frontend/src/main/scala/bloop/data/Project.scala +++ b/frontend/src/main/scala/bloop/data/Project.scala @@ -22,6 +22,7 @@ final case class Project( dependencies: List[String], scalaInstance: Option[ScalaInstance], rawClasspath: List[AbsolutePath], + annotationProcessorPath: List[AbsolutePath], resources: List[AbsolutePath], compileSetup: Config.CompileSetup, genericClassesDir: AbsolutePath, @@ -166,6 +167,7 @@ object Project { project.dependencies, instance, project.classpath.map(AbsolutePath.apply), + project.processorpath.map(AbsolutePath.apply), resources, setup, AbsolutePath(project.classesDir), diff --git a/frontend/src/main/scala/bloop/engine/tasks/CompileTask.scala b/frontend/src/main/scala/bloop/engine/tasks/CompileTask.scala index 097408de76..4f475040cb 100644 --- a/frontend/src/main/scala/bloop/engine/tasks/CompileTask.scala +++ b/frontend/src/main/scala/bloop/engine/tasks/CompileTask.scala @@ -128,6 +128,7 @@ object CompileTask { state.compilerCache, sources.toArray, classpath, + project.annotationProcessorPath.toArray, bundle.uniqueInputs, compileOut, project.out, diff --git a/frontend/src/main/scala/bloop/engine/tasks/compilation/CompileBundle.scala b/frontend/src/main/scala/bloop/engine/tasks/compilation/CompileBundle.scala index 820ad151a9..a9d1294ff4 100644 --- a/frontend/src/main/scala/bloop/engine/tasks/compilation/CompileBundle.scala +++ b/frontend/src/main/scala/bloop/engine/tasks/compilation/CompileBundle.scala @@ -154,7 +154,7 @@ object CompileBundle { val compileDependenciesData = { tracer.trace("dependency classpath") { _ => CompileDependenciesData.compute( - project.rawClasspath.toArray, + (project.rawClasspath ++ project.annotationProcessorPath).toArray, dependentProducts ) } diff --git a/frontend/src/test/scala/bloop/DagSpec.scala b/frontend/src/test/scala/bloop/DagSpec.scala index 617fbe2400..266a530456 100644 --- a/frontend/src/test/scala/bloop/DagSpec.scala +++ b/frontend/src/test/scala/bloop/DagSpec.scala @@ -21,7 +21,7 @@ class DagSpec { // format: OFF def dummyOrigin = TestUtil.syntheticOriginFor(dummyPath) def dummyProject(name: String, dependencies: List[String]): Project = - Project(name, dummyPath, dependencies, Some(dummyInstance), Nil, Nil, compileOptions, + Project(name, dummyPath, dependencies, Some(dummyInstance), Nil, Nil, Nil, compileOptions, dummyPath, Nil, Nil, Nil, Nil, Config.TestOptions.empty, dummyPath, dummyPath, Project.defaultPlatform(logger), None, None, dummyOrigin) // format: ON diff --git a/frontend/src/test/scala/bloop/util/TestProject.scala b/frontend/src/test/scala/bloop/util/TestProject.scala index 47d0f0331c..b813640e7a 100644 --- a/frontend/src/test/scala/bloop/util/TestProject.scala +++ b/frontend/src/test/scala/bloop/util/TestProject.scala @@ -123,6 +123,7 @@ object TestProject { List(sourceDir.underlying), directDependencies.map(_.config.name), classpath, + List.empty, outDir.underlying, classes.underlying, resources = Some(List(resourceDir.underlying)), diff --git a/frontend/src/test/scala/bloop/util/TestUtil.scala b/frontend/src/test/scala/bloop/util/TestUtil.scala index 5b795164bf..6f30c52579 100644 --- a/frontend/src/test/scala/bloop/util/TestUtil.scala +++ b/frontend/src/test/scala/bloop/util/TestUtil.scala @@ -333,6 +333,7 @@ object TestUtil { dependencies = dependencies.toList, scalaInstance = scalaInstance, rawClasspath = classpath, + annotationProcessorPath = Nil, resources = Nil, compileSetup = Config.CompileSetup.empty.copy(order = compileOrder), genericClassesDir = AbsolutePath(target), @@ -451,7 +452,7 @@ object TestUtil { val classesDir = Files.createDirectory(outDir.resolve("classes")) // format: OFF - val configFileG = bloop.config.Config.File(Config.File.LatestVersion, Config.Project("g", baseDir, Nil, List("g"), Nil, outDir, classesDir, None, None, None, None, None, None, None)) + val configFileG = bloop.config.Config.File(Config.File.LatestVersion, Config.Project("g", baseDir, Nil, List("g"), Nil, Nil, outDir, classesDir, None, None, None, None, None, None, None)) bloop.config.write(configFileG, jsonTargetG) // format: ON diff --git a/integrations/gradle-bloop/src/main/scala/bloop/integrations/gradle/model/BloopConverter.scala b/integrations/gradle-bloop/src/main/scala/bloop/integrations/gradle/model/BloopConverter.scala index a1b8211f51..4567ce4116 100644 --- a/integrations/gradle-bloop/src/main/scala/bloop/integrations/gradle/model/BloopConverter.scala +++ b/integrations/gradle-bloop/src/main/scala/bloop/integrations/gradle/model/BloopConverter.scala @@ -210,6 +210,12 @@ final class BloopConverter(parameters: BloopParameters) { val modules = (nonProjectDependencies.map(artifactToConfigModule(_, project)) ++ additionalArtifacts.map(artifactToConfigModule(_, project))).distinct + val annotationProcessorPaths = + Option(project.getConfiguration("annotationProcessor")) match { + case None => List.empty + case Some(conf) => conf.getResolvedConfiguration.getFiles.asScala.toList.map(_.toPath) + } + for { scalaConfig <- getScalaConfig(project, sourceSet, compileArtifacts) resolution = Config.Resolution(modules) @@ -219,6 +225,7 @@ final class BloopConverter(parameters: BloopParameters) { sources = sources, dependencies = allDependencies, classpath = classpath, + processorpath = annotationProcessorPaths, out = project.getBuildDir.toPath, classesDir = classesDir, resources = if (resources.isEmpty) None else Some(resources), diff --git a/integrations/gradle-bloop/src/test/scala/bloop/integrations/gradle/ConfigGenerationSuite.scala b/integrations/gradle-bloop/src/test/scala/bloop/integrations/gradle/ConfigGenerationSuite.scala index 11a9960b0c..2697c1cf83 100644 --- a/integrations/gradle-bloop/src/test/scala/bloop/integrations/gradle/ConfigGenerationSuite.scala +++ b/integrations/gradle-bloop/src/test/scala/bloop/integrations/gradle/ConfigGenerationSuite.scala @@ -552,6 +552,48 @@ abstract class ConfigGenerationSuite { assert(compileBloopProject("b-test", bloopDir).status.isOk) } + @Test def worksWithAnnotationProcessorDependencies(): Unit = { + val buildFile = testProjectDir.newFile("build.gradle") + testProjectDir.newFolder("src", "main", "scala") + + writeBuildScript( + buildFile, + s""" + |plugins { + | id 'bloop' + |} + | + |apply plugin: 'scala' + |apply plugin: 'bloop' + | + |repositories { + | mavenCentral() + |} + | + |dependencies { + | compile 'org.scala-lang:scala-library:2.12.8' + | compile 'com.google.dagger:dagger:2.2' + | annotationProcessor 'com.google.dagger:dagger-compiler:2.2' + |} + """.stripMargin + ) + + createHelloWorldScalaSource(testProjectDir.getRoot) + + GradleRunner + .create() + .withGradleVersion(gradleVersion) + .withProjectDir(testProjectDir.getRoot) + .withPluginClasspath(getClasspath.asJava) + .withArguments("bloopInstall", "-Si") + .build() + + val projectName = testProjectDir.getRoot.getName + val bloopFile = new File(new File(testProjectDir.getRoot, ".bloop"), projectName + ".json") + val resultConfig = readValidBloopConfig(bloopFile) + assert(resultConfig.project.processorpath.nonEmpty) + } + @Test def encodingOptionGeneratedCorrectly(): Unit = { val buildFile = testProjectDir.newFile("build.gradle") testProjectDir.newFolder("src", "main", "scala") diff --git a/integrations/maven-bloop/src/main/scala/bloop/integrations/maven/MojoImplementation.scala b/integrations/maven-bloop/src/main/scala/bloop/integrations/maven/MojoImplementation.scala index af24d9555f..4b1233cdd9 100644 --- a/integrations/maven-bloop/src/main/scala/bloop/integrations/maven/MojoImplementation.scala +++ b/integrations/maven-bloop/src/main/scala/bloop/integrations/maven/MojoImplementation.scala @@ -131,7 +131,7 @@ object MojoImplementation { val platform = Some(Config.Platform.Jvm(Config.JvmConfig(javaHome, launcher.getJvmArgs().toList), mainClass)) // Resources in Maven require val resources = Some(resources0.asScala.toList.flatMap(a => Option(a.getTargetPath).toList).map(classesDir.resolve)) - val project = Config.Project(name, baseDirectory, sourceDirs, dependencyNames, classpath, out, classesDir, resources, `scala`, java, sbt, test, platform, resolution) + val project = Config.Project(name, baseDirectory, sourceDirs, dependencyNames, classpath, List.empty, out, classesDir, resources, `scala`, java, sbt, test, platform, resolution) Config.File(Config.File.LatestVersion, project) } // FORMAT: ON diff --git a/integrations/mill-bloop/src/main/scala/bloop/integrations/mill/MillBloop.scala b/integrations/mill-bloop/src/main/scala/bloop/integrations/mill/MillBloop.scala index 32b1733d74..5d84edc1b0 100644 --- a/integrations/mill-bloop/src/main/scala/bloop/integrations/mill/MillBloop.scala +++ b/integrations/mill-bloop/src/main/scala/bloop/integrations/mill/MillBloop.scala @@ -102,6 +102,7 @@ object Bloop extends ExternalModule { sources = module.allSources().map(_.path.toNIO).toList, dependencies = module.moduleDeps.map(name).toList, classpath = classpath().map(_.toNIO).toList, + processorpath = List.empty, out = out(module).toNIO, classesDir = classes(module).toNIO, resources = Some(resources()), diff --git a/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala b/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala index 31e1ca90ed..544417cf84 100644 --- a/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala +++ b/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala @@ -869,7 +869,7 @@ object BloopDefaults { val sbt = computeSbtMetadata.value.map(_.config) val project = Config.Project(projectName, baseDirectory, sources, dependenciesAndAggregates, - classpath, out, classesDir, resources, Some(`scala`), Some(java), sbt, Some(testOptions), Some(platform), resolution) + classpath, List.empty, out, classesDir, resources, Some(`scala`), Some(java), sbt, Some(testOptions), Some(platform), resolution) Config.File(Config.File.LatestVersion, project) } // format: ON