From 0a080293c0daaf0f57c3ab324573e28cb9c7281b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93lafur=20P=C3=A1ll=20Geirsson?= Date: Mon, 18 Oct 2021 12:18:39 +0200 Subject: [PATCH 1/2] Add support for Kotlin Gradle projects Previously, running `lsif-java index` in a Gradle project only indexed Java and Scala sources. Now, we also index Kotlin sources. --- build.sbt | 5 +- .../buildtools/GradleBuildTool.scala | 38 ++++++++++- .../buildtools/GradleJavaToolchains.scala | 48 ++++++++++---- project/build.properties | 2 +- .../scala/tests/GradleBuildToolSuite.scala | 65 +++++++++++++++++++ 5 files changed, 140 insertions(+), 18 deletions(-) diff --git a/build.sbt b/build.sbt index 627669f2..01c63748 100644 --- a/build.sbt +++ b/build.sbt @@ -18,7 +18,7 @@ lazy val V = def scala3 = "3.0.1" def metals = "0.10.6-M1" def scalameta = "4.4.26" - def semanticdbKotlinc = "0.0.2" + def semanticdbKotlinc = "0.1.0" def testcontainers = "0.39.3" def requests = "0.6.5" } @@ -409,7 +409,8 @@ lazy val javaOnlySettings = List[Def.Setting[_]]( lazy val testSettings = List( (publish / skip) := true, autoScalaLibrary := true, - testFrameworks := List(new TestFramework("munit.Framework")), + testFrameworks := List(TestFrameworks.MUnit), + testOptions ++= List(Tests.Argument(TestFrameworks.MUnit, "-b")), libraryDependencies ++= List( "org.scalameta" %% "munit" % "0.7.29", diff --git a/lsif-java/src/main/scala/com/sourcegraph/lsif_java/buildtools/GradleBuildTool.scala b/lsif-java/src/main/scala/com/sourcegraph/lsif_java/buildtools/GradleBuildTool.scala index 1b018eed..350fbe93 100644 --- a/lsif-java/src/main/scala/com/sourcegraph/lsif_java/buildtools/GradleBuildTool.scala +++ b/lsif-java/src/main/scala/com/sourcegraph/lsif_java/buildtools/GradleBuildTool.scala @@ -84,9 +84,20 @@ class GradleBuildTool(index: IndexCommand) extends BuildTool("Gradle", index) { index.finalBuildCommand( List[Option[String]]( Some("clean"), - Some("compileTestJava"), + if (toolchains.isJavaEnabled) + Some("compileTestJava") + else + None, if (toolchains.isScalaEnabled) Some("compileTestScala") + else + None, + if (toolchains.isKotlinEnabled) + Some("compileTestKotlin") + else + None, + if (toolchains.isKotlinMultiplatformEnabled) + Some("compileTestKotlinJvm") else None ).flatten @@ -131,6 +142,7 @@ class GradleBuildTool(index: IndexCommand) extends BuildTool("Gradle", index) { else "" val dependenciesPath = targetroot.resolve("dependencies.txt") + val kotlinSemanticdbVersion = BuildInfo.semanticdbKotlincVersion Files.deleteIfExists(dependenciesPath) val script = s"""|allprojects { @@ -141,6 +153,9 @@ class GradleBuildTool(index: IndexCommand) extends BuildTool("Gradle", index) { | boolean isScalaEnabled = project.plugins.any { | it.getClass().getName().endsWith("org.gradle.api.plugins.scala.ScalaPlugin") | } + | boolean isKotlinEnabled = project.plugins.any { + | it.getClass().getName().startsWith("org.jetbrains.kotlin.gradle.plugin") + | } | if (isJavaEnabled) { | tasks.withType(JavaCompile) { | options.fork = true @@ -179,6 +194,25 @@ class GradleBuildTool(index: IndexCommand) extends BuildTool("Gradle", index) { | } | } | } + | if (isKotlinEnabled) { + | tasks.configureEach { + | if (it.getClass().getName().contains("KotlinCompile")) { + | try { + | def semanticdbKotlincDependency = "com.sourcegraph:semanticdb-kotlinc:$kotlinSemanticdbVersion" + | def semanticdbKotlinc = project.configurations.detachedConfiguration(dependencies.create(semanticdbKotlincDependency)).files[0] + | kotlinOptions { + | freeCompilerArgs << "-Xplugin=" + semanticdbKotlinc + | freeCompilerArgs << "-P" + | freeCompilerArgs << "plugin:semanticdb-kotlinc:sourceroot=$sourceroot" + | freeCompilerArgs << "-P" + | freeCompilerArgs << "plugin:semanticdb-kotlinc:targetroot=$targetroot" + | } + | } catch (Throwable e) { + | e.printStackTrace() + | } + | } + | } + | } | } | task $lsifJavaDependencies { | def depsOut = java.nio.file.Paths.get('$dependenciesPath') @@ -236,7 +270,7 @@ class GradleBuildTool(index: IndexCommand) extends BuildTool("Gradle", index) { | } | return null |} - | """.stripMargin + |""".stripMargin Files.write( tmp.resolve("init-script.gradle"), script.getBytes(StandardCharsets.UTF_8) diff --git a/lsif-java/src/main/scala/com/sourcegraph/lsif_java/buildtools/GradleJavaToolchains.scala b/lsif-java/src/main/scala/com/sourcegraph/lsif_java/buildtools/GradleJavaToolchains.scala index 81ae6bc9..39b52550 100644 --- a/lsif-java/src/main/scala/com/sourcegraph/lsif_java/buildtools/GradleJavaToolchains.scala +++ b/lsif-java/src/main/scala/com/sourcegraph/lsif_java/buildtools/GradleJavaToolchains.scala @@ -14,7 +14,10 @@ case class GradleJavaToolchains( tool: GradleBuildTool, index: IndexCommand, gradleVersion: Option[String], + isJavaEnabled: Boolean, isScalaEnabled: Boolean, + isKotlinEnabled: Boolean, + isKotlinMultiplatformEnabled: Boolean, gradleCommand: String, tmp: Path ) { @@ -56,7 +59,11 @@ object GradleJavaToolchains { ): GradleJavaToolchains = { val scriptPath = tmp.resolve("java-toolchains.gradle") val toolchainsPath = tmp.resolve("java-toolchains.txt") + val javaEnabledPath = tmp.resolve("java-enabled.txt") val scalaEnabledPath = tmp.resolve("scala-enabled.txt") + val kotlinEnabledPath = tmp.resolve("kotlin-enabled.txt") + val kotlinMultiplatformEnabledPath = tmp + .resolve("kotlin-multiplatform-enabled.txt") val gradleVersionPath = tmp.resolve("gradle-version.txt") val taskName = "lsifDetectJavaToolchains" val script = @@ -70,12 +77,21 @@ object GradleJavaToolchains { |} catch (Exception e) { | // Ignore errors. |} + | + |def lsifJavaAppendLine(path, line) { + | java.nio.file.Files.write( + | java.nio.file.Paths.get(path), + | [line], + | java.nio.file.StandardOpenOption.APPEND, + | java.nio.file.StandardOpenOption.CREATE) + |} + | |allprojects { | task $taskName { | def toolchainsOut = java.nio.file.Paths.get('$toolchainsPath') | doLast { - | tasks.withType(JavaCompile) { - | try { + | try { + | tasks.withType(JavaCompile) { | def lines = new ArrayList() | def path = javaCompiler.get().getExecutablePath() | def version = javaCompiler.get().getMetadata().getLanguageVersion().asInt() @@ -85,19 +101,21 @@ object GradleJavaToolchains { | [line], | java.nio.file.StandardOpenOption.APPEND, | java.nio.file.StandardOpenOption.CREATE) - | } catch (Exception e) { - | // Ignore errors. + | lsifJavaAppendLine(toolchainsOut, line) | } + | } catch (Exception e) { + | // Ignore errors. | } - | boolean isScalaEnabled = project.plugins.any { - | it.getClass().getName().endsWith("org.gradle.api.plugins.scala.ScalaPlugin") - | } - | if (isScalaEnabled) { - | java.nio.file.Files.write( - | java.nio.file.Paths.get('$scalaEnabledPath'), - | ["true"], - | java.nio.file.StandardOpenOption.APPEND, - | java.nio.file.StandardOpenOption.CREATE) + | project.plugins.each { + | def name = it.getClass().getName() + | if (name.endsWith("org.gradle.api.plugins.JavaPlugin")) + | lsifJavaAppendLine('$javaEnabledPath', 'true') + | if (name.endsWith("org.gradle.api.plugins.scala.ScalaPlugin")) + | lsifJavaAppendLine('$scalaEnabledPath', 'true') + | if (name.startsWith("org.jetbrains.kotlin.gradle.plugin")) + | lsifJavaAppendLine('$kotlinEnabledPath', 'true') + | if (name.equals("org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper")) + | lsifJavaAppendLine('$kotlinMultiplatformEnabledPath', 'true') | } | } | } @@ -131,7 +149,11 @@ object GradleJavaToolchains { tool, index, gradleVersion = gradleVersion, + isJavaEnabled = Files.isRegularFile(javaEnabledPath), isScalaEnabled = Files.isRegularFile(scalaEnabledPath), + isKotlinEnabled = Files.isRegularFile(kotlinEnabledPath), + isKotlinMultiplatformEnabled = Files + .isRegularFile(kotlinMultiplatformEnabledPath), gradleCommand = gradleCommand, tmp = tmp ) diff --git a/project/build.properties b/project/build.properties index 19479ba4..10fd9eee 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.2 +sbt.version=1.5.5 diff --git a/tests/buildTools/src/test/scala/tests/GradleBuildToolSuite.scala b/tests/buildTools/src/test/scala/tests/GradleBuildToolSuite.scala index f29edbd2..fe4b8fc8 100644 --- a/tests/buildTools/src/test/scala/tests/GradleBuildToolSuite.scala +++ b/tests/buildTools/src/test/scala/tests/GradleBuildToolSuite.scala @@ -262,4 +262,69 @@ class GradleBuildToolSuite extends BaseBuildToolSuite { 4 ) + checkBuild( + "kotlin", + """|/build.gradle + |plugins { + | id 'org.jetbrains.kotlin.jvm' version '1.5.31' + |} + |repositories { + | mavenCentral() + |} + |/src/main/java/foo/JExample.java + |package foo; + |public class JExample {} + |/src/main/kotlin/foo/Example.kt + |package foo + |object Example {} + |/src/test/java/foo/JExampleSuite.java + |package foo; + |public class JExampleSuite {} + |/src/test/kotlin/foo/ExampleSuite.kt + |package foo + |class ExampleSuite {} + |""".stripMargin, + 4 + ) + + List("jvm()" -> 2, "jvm { withJava() }" -> 4).foreach { + case (jvmSettings, expectedSemanticdbFiles) => + checkBuild( + s"kotlin-multiplatform-$jvmSettings", + s"""|/build.gradle + |plugins { + | id 'org.jetbrains.kotlin.multiplatform' version '1.5.31' + |} + |repositories { + | mavenCentral() + |} + |kotlin { + | ${jvmSettings} + | sourceSets { + | jvmTest { + | dependencies { + | implementation kotlin("test-junit") + | } + | } + | } + |} + |/gradle.properties + |kotlin.mpp.stability.nowarn=true + |/src/jvmMain/java/foo/ExampleJ.java + |package foo; + |public class ExampleJ {} // ignored by multiplatform + |/src/jvmMain/kotlin/foo/Example.kt + |package foo + |object Example {} + |/src/jvmTest/java/foo/ExampleJSuite.java + |package foo; + |class ExampleJSuite {} // ignored by multiplatform + |/src/commonTest/kotlin/foo/ExampleJvmSuite.kt + |package foo + |class ExampleJvmSuite {} + |""".stripMargin, + expectedSemanticdbFiles + ) + } + } From f681907176e994dc4274a5a4577d9304264cd23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93lafur=20P=C3=A1ll=20Geirsson?= Date: Mon, 18 Oct 2021 19:35:33 +0200 Subject: [PATCH 2/2] Update snapshots --- .../src/main/generated/com/airbnb/epoxy/EpoxyRecyclerView.kt | 1 + .../main/generated/com/airbnb/epoxy/EpoxyVisibilityTracker.kt | 1 + .../src/main/generated/com/airbnb/epoxy/ModelGroupHolder.kt | 1 + .../generated/com/airbnb/epoxy/preload/EpoxyModelPreloader.kt | 1 + .../main/generated/com/airbnb/epoxy/preload/EpoxyPreloader.kt | 2 ++ 5 files changed, 6 insertions(+) diff --git a/tests/snapshots/src/main/generated/com/airbnb/epoxy/EpoxyRecyclerView.kt b/tests/snapshots/src/main/generated/com/airbnb/epoxy/EpoxyRecyclerView.kt index 04dc10c7..fb8501ec 100644 --- a/tests/snapshots/src/main/generated/com/airbnb/epoxy/EpoxyRecyclerView.kt +++ b/tests/snapshots/src/main/generated/com/airbnb/epoxy/EpoxyRecyclerView.kt @@ -1142,6 +1142,7 @@ open class EpoxyRecyclerView @JvmOverloads constructor( } companion object { +// ^^^^^^^^^ definition com/airbnb/epoxy/EpoxyRecyclerView#Companion# private const val DEFAULT_ADAPTER_REMOVAL_DELAY_MS = 2000 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition com/airbnb/epoxy/EpoxyRecyclerView#Companion#DEFAULT_ADAPTER_REMOVAL_DELAY_MS. // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition com/airbnb/epoxy/EpoxyRecyclerView#Companion#getDEFAULT_ADAPTER_REMOVAL_DELAY_MS(). diff --git a/tests/snapshots/src/main/generated/com/airbnb/epoxy/EpoxyVisibilityTracker.kt b/tests/snapshots/src/main/generated/com/airbnb/epoxy/EpoxyVisibilityTracker.kt index 13599a09..daf6f5d6 100644 --- a/tests/snapshots/src/main/generated/com/airbnb/epoxy/EpoxyVisibilityTracker.kt +++ b/tests/snapshots/src/main/generated/com/airbnb/epoxy/EpoxyVisibilityTracker.kt @@ -1085,6 +1085,7 @@ class EpoxyVisibilityTracker { } companion object { +// ^^^^^^^^^ definition com/airbnb/epoxy/EpoxyVisibilityTracker#Companion# private const val TAG = "EpoxyVisibilityTracker" // ^^^ definition com/airbnb/epoxy/EpoxyVisibilityTracker#Companion#TAG. // ^^^ definition com/airbnb/epoxy/EpoxyVisibilityTracker#Companion#getTAG(). diff --git a/tests/snapshots/src/main/generated/com/airbnb/epoxy/ModelGroupHolder.kt b/tests/snapshots/src/main/generated/com/airbnb/epoxy/ModelGroupHolder.kt index 3ec1aeaf..bc6d6f37 100644 --- a/tests/snapshots/src/main/generated/com/airbnb/epoxy/ModelGroupHolder.kt +++ b/tests/snapshots/src/main/generated/com/airbnb/epoxy/ModelGroupHolder.kt @@ -443,6 +443,7 @@ class ModelGroupHolder(private val modelGroupParent: ViewParent) : EpoxyHolder() } companion object { +// ^^^^^^^^^ definition com/airbnb/epoxy/ModelGroupHolder#Companion# private val HELPER_ADAPTER = HelperAdapter() // ^^^^^^^^^^^^^^ definition com/airbnb/epoxy/ModelGroupHolder#Companion#HELPER_ADAPTER. diff --git a/tests/snapshots/src/main/generated/com/airbnb/epoxy/preload/EpoxyModelPreloader.kt b/tests/snapshots/src/main/generated/com/airbnb/epoxy/preload/EpoxyModelPreloader.kt index 67447b0b..6c77616f 100644 --- a/tests/snapshots/src/main/generated/com/airbnb/epoxy/preload/EpoxyModelPreloader.kt +++ b/tests/snapshots/src/main/generated/com/airbnb/epoxy/preload/EpoxyModelPreloader.kt @@ -95,6 +95,7 @@ abstract class EpoxyModelPreloader, U : ViewMetadata?, P : Pre ) companion object { +// ^^^^^^^^^ definition com/airbnb/epoxy/preload/EpoxyModelPreloader#Companion# /** * Helper to create a [EpoxyModelPreloader]. diff --git a/tests/snapshots/src/main/generated/com/airbnb/epoxy/preload/EpoxyPreloader.kt b/tests/snapshots/src/main/generated/com/airbnb/epoxy/preload/EpoxyPreloader.kt index 614d86f2..513be4a1 100644 --- a/tests/snapshots/src/main/generated/com/airbnb/epoxy/preload/EpoxyPreloader.kt +++ b/tests/snapshots/src/main/generated/com/airbnb/epoxy/preload/EpoxyPreloader.kt @@ -517,6 +517,7 @@ class EpoxyPreloader

private constructor( } companion object { +// ^^^^^^^^^ definition com/airbnb/epoxy/preload/EpoxyPreloader#Companion# /** * @@ -709,6 +710,7 @@ class ViewData( interface ViewMetadata { // ^^^^^^^^^^^^ definition com/airbnb/epoxy/preload/ViewMetadata# companion object { +// ^^^^^^^^^ definition com/airbnb/epoxy/preload/ViewMetadata#Companion# fun getDefault(view: View): ViewMetadata? { // ^^^^^^^^^^ definition com/airbnb/epoxy/preload/ViewMetadata#Companion#getDefault(). // ^^^^ definition com/airbnb/epoxy/preload/ViewMetadata#Companion#getDefault().(view)