Skip to content
This repository has been archived by the owner on Aug 5, 2024. It is now read-only.

[feature] Go support #507

Draft
wants to merge 41 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
eb905a5
Obtain some info from target
edokimok Dec 11, 2023
d2ccd3f
[feature] create go build target | #BAZEL-784 Done
zortenburger Dec 14, 2023
36aab51
[feature] obtain sdk info from targets in aspects | #BAZEL-785
maclick Dec 14, 2023
1e79bd5
mock go sdk path
maclick Dec 14, 2023
4e218de
[feature] create go language plugin | #BAZEL-787
zortenburger Jan 9, 2024
f8a75e1
fix go extension test
zortenburger Jan 9, 2024
bc4b68f
Merge branch 'master' into go-support
maclick Jan 20, 2024
919bf1c
remove rules_go dependency
maclick Jan 20, 2024
72b9e32
set sdk home path properly
maclick Jan 21, 2024
0a60ae4
store sdk home path as go base dir
maclick Jan 24, 2024
d47ee32
Merge remote-tracking branch 'jetbrains/master' into go-support
maclick Feb 22, 2024
cbd25f1
adapt to new code
maclick Feb 22, 2024
7eec540
ooops, commited too fast
maclick Feb 22, 2024
68ce191
add go as a workspace target
maclick Mar 28, 2024
43614e3
requested changes
maclick Mar 28, 2024
63e2c77
Merge remote-tracking branch 'jetbrains/master' into go-support
maclick Mar 28, 2024
0b37581
Merge remote-tracking branch 'refs/remotes/jetbrains/master' into for…
maclick Apr 11, 2024
ffe2ba2
go tests should also be included as workspace targets
maclick Apr 11, 2024
f48904c
GO E2E test (#1)
maclick Apr 14, 2024
259e562
Add goImportPath to Library
edokimok Apr 11, 2024
25e772e
WIP, working importpath, empty root
edokimok Apr 18, 2024
519b15a
Add default value in LibraryItem
edokimok Apr 18, 2024
2f7b4ae
Merge branch 'refs/heads/master' into fork/go-support
maclick Apr 21, 2024
8a58145
fix buildifier for go e2e test project
maclick Apr 21, 2024
5faf42f
fix buildifier for go e2e test project (again)
maclick Apr 21, 2024
b9f50bc
fix tests
maclick Apr 21, 2024
50f03f4
Add goImportPath to Library
edokimok Apr 11, 2024
384242e
WIP, working importpath, empty root
edokimok Apr 18, 2024
d68e840
Add default value in LibraryItem
edokimok Apr 18, 2024
b1d9db4
inherit build target root directory from its sources
maclick Apr 24, 2024
b647526
Merge remote-tracking branch 'origin/libraries' into libraries
edokimok Apr 25, 2024
45cc62b
Green code!
edokimok Apr 25, 2024
539afb8
Fix indentation
edokimok Apr 25, 2024
6d72bc7
Minor fixes
edokimok Apr 25, 2024
4030fdf
Fix more indentation
edokimok Apr 25, 2024
e509bba
External dependencies (#2)
edokimok May 7, 2024
52029e4
Change go rules to template (#3)
maclick May 7, 2024
c983d1e
Merge remote-tracking branch 'refs/remotes/jetbrains/master' into go-…
maclick May 7, 2024
2b9f450
Merge remote-tracking branch 'refs/remotes/upstream/master' into backup
edokimok May 23, 2024
58713f8
Rebase go aspects
edokimok May 23, 2024
ef65da8
Merge remote-tracking branch 'zortenburger/go-support' into backup
edokimok May 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions aspects/rules/go/go_info.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
load("//aspects:utils/utils.bzl", "create_proto", "create_struct", "file_location")
load("@io_bazel_rules_go//go:def.bzl", "go_context")

def extract_sdk(ctx):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's put an _ to mark that's "private" and put the definition below its usage - so just put it under the extract_go_info

go = go_context(ctx)
if go == None:
return None
return file_location(go.sdk.go)

def extract_go_info(target, ctx, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you also need to check is it a go target (we usually check is there a language provider in the target, if not then we return None, None)

importpath = getattr(ctx.rule.attr, "importpath", [])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

importpath is a string, so the default fallback should be an empty string (or none)

sdk_home_path = extract_sdk(ctx)

go_target_info = create_struct(
importpath = importpath,
sdk_home_path = sdk_home_path,
)

return create_proto(target, ctx, go_target_info, "go_target_info"), None
2 changes: 1 addition & 1 deletion docs/dev/ASPECTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

### The `extensions.bzl` file
The server generates the `extensions.bzl` file on each sync according to a list of external rules relevant to the project.
See `server/src/main/kotlin/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspEnvironmentManager.kt` for the implementation.
See `server/src/main/kotlin/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspLanguageExtensionsGenerator.kt` for the implementation.

The file itself contains a declaration of functions invoked in `core.bzl`. Each function is supposed to provide language-specific data.
9 changes: 9 additions & 0 deletions protocol/src/main/kotlin/org/jetbrains/bsp/GoBuildTarget.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.jetbrains.bsp

import java.net.URI

data class GoBuildTarget(
val sdkHomePath: URI?,
val importPath: String?,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question is: can target have no import path?

)

Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.jetbrains.bsp.bazel.server.sync.TargetKindResolver
import org.jetbrains.bsp.bazel.server.sync.languages.LanguagePluginsService
import org.jetbrains.bsp.bazel.server.sync.languages.android.AndroidLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.cpp.CppLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.go.GoLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.java.JavaLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.java.JdkResolver
import org.jetbrains.bsp.bazel.server.sync.languages.java.JdkVersionResolver
Expand Down Expand Up @@ -120,6 +121,7 @@ class BazelBspServer(
val pythonLanguagePlugin = PythonLanguagePlugin(bazelPathsResolver)
val rustLanguagePlugin = RustLanguagePlugin(bazelPathsResolver)
val androidLanguagePlugin = AndroidLanguagePlugin(javaLanguagePlugin, bazelPathsResolver)
val goLanguagePlugin = GoLanguagePlugin(bazelPathsResolver)

return LanguagePluginsService(
scalaLanguagePlugin,
Expand All @@ -129,7 +131,8 @@ class BazelBspServer(
thriftLanguagePlugin,
pythonLanguagePlugin,
rustLanguagePlugin,
androidLanguagePlugin
androidLanguagePlugin,
goLanguagePlugin
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.jetbrains.bsp.bazel.server.bsp.managers

import java.nio.file.Paths
import java.util.Properties
import kotlin.io.path.writeText
import org.apache.velocity.app.VelocityEngine
import org.jetbrains.bsp.bazel.bazelrunner.BazelRelease
import org.jetbrains.bsp.bazel.commons.Constants
import org.jetbrains.bsp.bazel.server.bsp.utils.InternalAspectsResolver
import java.nio.file.Paths
import java.util.Properties
import kotlin.io.path.writeText

enum class Language(private val fileName: String, val ruleNames: List<String>, val functions: List<String>, val isTemplate: Boolean) {
Java("//aspects:rules/java/java_info.bzl", listOf(), listOf("extract_java_toolchain", "extract_java_runtime"), false),
Expand All @@ -16,7 +16,8 @@ enum class Language(private val fileName: String, val ruleNames: List<String>, v
Cpp("//aspects:rules/cpp/cpp_info.bzl", listOf("rules_cc"), listOf("extract_cpp_info"), false),
Kotlin("//aspects:rules/kt/kt_info.bzl", listOf("io_bazel_rules_kotlin", "rules_kotlin"), listOf("extract_kotlin_info"), true),
Rust("//aspects:rules/rust/rust_info.bzl", listOf("rules_rust"), listOf("extract_rust_crate_info"), false),
Android("//aspects:rules/android/android_info.bzl", listOf(), listOf("extract_android_info"), false);
Android("//aspects:rules/android/android_info.bzl", listOf(), listOf("extract_android_info"), false),
Go("//aspects:rules/go/go_info.bzl", listOf("io_bazel_rules_go"), listOf("extract_go_info"), false);

fun toLoadStatement(): String =
this.functions.joinToString(
Expand Down Expand Up @@ -83,6 +84,7 @@ class BazelBspLanguageExtensionsGenerator(internalAspectsResolver: InternalAspec
Language.Kotlin -> """"@${it.ruleName}//kotlin/internal:kt_toolchain_type""""
Language.Rust -> """"@${it.ruleName}//rust:toolchain_type""""
Language.Android -> getAndroidToolchain()
Language.Go -> """"@io_bazel_rules_go//go:toolchain""""
else -> null
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@ class BazelProjectMapper(
it.relativePath.endsWith(".scala") ||
it.relativePath.endsWith(".py") ||
it.relativePath.endsWith(".sh") ||
it.relativePath.endsWith(".rs")
it.relativePath.endsWith(".rs") ||
it.relativePath.endsWith(".go")
}

private fun isWorkspaceTarget(target: TargetInfo): Boolean =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.runBlocking
import org.jetbrains.bsp.bazel.info.BspTargetInfo.AndroidTargetInfo
import org.jetbrains.bsp.bazel.info.BspTargetInfo.CppTargetInfo
import org.jetbrains.bsp.bazel.info.BspTargetInfo.GoTargetInfo
import org.jetbrains.bsp.bazel.info.BspTargetInfo.JavaRuntimeInfo
import org.jetbrains.bsp.bazel.info.BspTargetInfo.JavaToolchainInfo
import org.jetbrains.bsp.bazel.info.BspTargetInfo.JvmTargetInfo
Expand Down Expand Up @@ -125,6 +126,12 @@ class TargetInfoReader {
targetInfoBuilder.setAndroidTargetInfo(info)
}

"go_target_info" -> {
val builder: GoTargetInfo.Builder = readFromFile(path, GoTargetInfo.newBuilder())
val info = builder.build()
targetInfoBuilder.setGoTargetInfo(info)
}

"general" -> {
val builder: TargetInfo.Builder = readFromFile(path, TargetInfo.newBuilder())
val info = builder.buildPartial()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.jetbrains.bsp.bazel.info.BspTargetInfo
import org.jetbrains.bsp.bazel.server.sync.languages.android.AndroidLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.cpp.CppLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.cpp.CppModule
import org.jetbrains.bsp.bazel.server.sync.languages.go.GoLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.java.JavaLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.kotlin.KotlinLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.python.PythonLanguagePlugin
Expand All @@ -23,6 +24,7 @@ class LanguagePluginsService(
val pythonLanguagePlugin: PythonLanguagePlugin,
val rustLanguagePlugin: RustLanguagePlugin,
private val androidLanguagePlugin: AndroidLanguagePlugin,
val goLanguagePlugin: GoLanguagePlugin,
) {
private val emptyLanguagePlugin: EmptyLanguagePlugin = EmptyLanguagePlugin()

Expand All @@ -33,6 +35,7 @@ class LanguagePluginsService(
thriftLanguagePlugin.prepareSync(targetInfos)
pythonLanguagePlugin.prepareSync(targetInfos)
rustLanguagePlugin.prepareSync(targetInfos)
goLanguagePlugin.prepareSync(targetInfos)
}

fun getPlugin(languages: Set<Language>): LanguagePlugin<*> =
Expand All @@ -45,6 +48,7 @@ class LanguagePluginsService(
languages.contains(Language.THRIFT) -> thriftLanguagePlugin
languages.contains(Language.PYTHON) -> pythonLanguagePlugin
languages.contains(Language.RUST) -> rustLanguagePlugin
languages.contains(Language.GO) -> goLanguagePlugin
else -> emptyLanguagePlugin
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.jetbrains.bsp.bazel.server.sync.languages.go

import ch.epfl.scala.bsp4j.BuildTarget
import org.jetbrains.bsp.GoBuildTarget
import org.jetbrains.bsp.bazel.info.BspTargetInfo
import org.jetbrains.bsp.bazel.server.paths.BazelPathsResolver
import org.jetbrains.bsp.bazel.server.sync.languages.LanguagePlugin
import java.net.URI
import kotlin.io.path.toPath

class GoLanguagePlugin(
private val bazelPathsResolver: BazelPathsResolver
) : LanguagePlugin<GoModule>() {
override fun applyModuleData(moduleData: GoModule, buildTarget: BuildTarget) {
val goBuildTarget = with(moduleData) {
GoBuildTarget(
sdkHomePath = sdkHomePath,
importPath = importPath,
)
}

buildTarget.dataKind = "go"
buildTarget.data = goBuildTarget
}

override fun resolveModule(targetInfo: BspTargetInfo.TargetInfo): GoModule? {
if (!targetInfo.hasGoTargetInfo()) return null

val goTargetInfo = targetInfo.goTargetInfo
return GoModule(
sdkHomePath = calculateSdkURI(goTargetInfo.sdkHomePath),
importPath = goTargetInfo.importpath,
)
}

private fun calculateSdkURI(sdk: BspTargetInfo.FileLocation?): URI? =
sdk?.takeUnless { it.relativePath.isNullOrEmpty() }
?.let {
val goBinaryPath = bazelPathsResolver.resolveUri(it).toPath()
val goSdkDir = goBinaryPath.parent.parent
goSdkDir.toUri()
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new line

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.jetbrains.bsp.bazel.server.sync.languages.go

import org.jetbrains.bsp.bazel.server.sync.languages.LanguageData
import java.net.URI

data class GoModule (
val sdkHomePath: URI?,
val importPath: String?,
): LanguageData
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new line

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ enum class Language(
hashSetOf(JAVA.id),
// This should be removed once https://github.com/bazelbuild/rules_kotlin/issues/273 is fixed
"@@rules_kotlin.*//third_party:android_sdk".toRegex(),
);
),
GO("go", hashSetOf(".go"));

val allNames: Set<String> = dependentNames + id

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ message AndroidTargetInfo {
string kotlin_target_id = 5;
}

message GoTargetInfo {
string importpath = 1;
FileLocation sdk_home_path = 2;
}

message TargetInfo {
string id = 10;
string kind = 20;
Expand All @@ -122,4 +127,5 @@ message TargetInfo {
PythonTargetInfo python_target_info = 8000;
RustCrateInfo rust_crate_info = 9000;
AndroidTargetInfo android_target_info = 10000;
GoTargetInfo go_target_info = 11000;
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,24 @@ class BazelBspLanguageExtensionsGeneratorTest {
EXTENSIONS=[extract_java_toolchain,extract_java_runtime,extract_jvm_info,extract_python_info,extract_cpp_info]
TOOLCHAINS=["@bazel_tools//tools/jdk:runtime_toolchain_type"]
""".replace(" ", "").replace("\n", "")
private val goFileContent =
""" load("//aspects:rules/java/java_info.bzl","extract_java_toolchain","extract_java_runtime")
load("//aspects:rules/jvm/jvm_info.bzl","extract_jvm_info")
load("//aspects:rules/python/python_info.bzl","extract_python_info")
load("//aspects:rules/go/go_info.bzl","extract_go_info")
EXTENSIONS=[extract_java_toolchain,extract_java_runtime,extract_jvm_info,extract_python_info,extract_go_info]
TOOLCHAINS=["@bazel_tools//tools/jdk:runtime_toolchain_type","@io_bazel_rules_go//go:toolchain"]
""".replace(" ", "").replace("\n", "")
private val allExtensionsFileContent =
""" load("//aspects:rules/java/java_info.bzl","extract_java_toolchain","extract_java_runtime")
load("//aspects:rules/jvm/jvm_info.bzl","extract_jvm_info")
load("//aspects:rules/python/python_info.bzl","extract_python_info")
load("//aspects:rules/cpp/cpp_info.bzl","extract_cpp_info")
load("//aspects:rules/kt/kt_info.bzl","extract_kotlin_info")
load("//aspects:rules/scala/scala_info.bzl","extract_scala_info","extract_scala_toolchain_info")
EXTENSIONS=[extract_java_toolchain,extract_java_runtime,extract_jvm_info,extract_python_info,extract_cpp_info,extract_kotlin_info,extract_scala_info,extract_scala_toolchain_info]
TOOLCHAINS=["@bazel_tools//tools/jdk:runtime_toolchain_type","@io_bazel_rules_kotlin//kotlin/internal:kt_toolchain_type","@io_bazel_rules_scala//scala:toolchain_type"]
load("//aspects:rules/go/go_info.bzl","extract_go_info")
EXTENSIONS=[extract_java_toolchain,extract_java_runtime,extract_jvm_info,extract_python_info,extract_cpp_info,extract_kotlin_info,extract_scala_info,extract_scala_toolchain_info,extract_go_info]
TOOLCHAINS=["@bazel_tools//tools/jdk:runtime_toolchain_type","@io_bazel_rules_kotlin//kotlin/internal:kt_toolchain_type","@io_bazel_rules_scala//scala:toolchain_type","@io_bazel_rules_go//go:toolchain"]
""".replace(" ", "").replace("\n", "")
private val defaultRuleLanguages =
listOf(
Expand Down Expand Up @@ -117,13 +126,32 @@ class BazelBspLanguageExtensionsGeneratorTest {
fileContent shouldBeEqual cppFileContent
}

@Test
fun `should create the extensions dot bzl file with one import and one toolchain (go)`() {
// given
val ruleLanguages = defaultRuleLanguages + listOf(
RuleLanguage("io_bazel_rules_go", Language.Go)
)
BazelExternalRulesQueryMock(listOf("io_bazel_rules_go"))
val bazelBspLanguageExtensionsGenerator =
BazelBspLanguageExtensionsGenerator(internalAspectsResolverMock, bazelRelease)

// when
bazelBspLanguageExtensionsGenerator.generateLanguageExtensions(ruleLanguages)

// then
val fileContent = getExtensionsFileContent()
fileContent shouldBeEqual goFileContent
}

@Test
fun `should create the extensions dot bzl file with all possible imports and toolchains`() {
// given
val ruleLanguages = defaultRuleLanguages + listOf(
RuleLanguage("rules_cc", Language.Cpp),
RuleLanguage("io_bazel_rules_kotlin", Language.Kotlin),
RuleLanguage("io_bazel_rules_scala", Language.Scala),
RuleLanguage("io_bazel_rules_go", Language.Go)
)
val bazelBspLanguageExtensionsGenerator =
BazelBspLanguageExtensionsGenerator(internalAspectsResolverMock, bazelRelease)
Expand All @@ -143,6 +171,7 @@ class BazelBspLanguageExtensionsGeneratorTest {
RuleLanguage("rules_cc", Language.Cpp),
RuleLanguage("io_bazel_rules_kotlin", Language.Kotlin),
RuleLanguage("io_bazel_rules_scala", Language.Scala),
RuleLanguage("io_bazel_rules_go", Language.Go)
)
val emptyBazelBspLanguageExtensionsGenerator =
BazelBspLanguageExtensionsGenerator(internalAspectsResolverMock, bazelRelease)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.jetbrains.bsp.bazel.bazelrunner.orLatestSupported
import org.jetbrains.bsp.bazel.server.paths.BazelPathsResolver
import org.jetbrains.bsp.bazel.server.sync.languages.android.AndroidLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.cpp.CppLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.go.GoLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.java.JavaLanguagePlugin
import org.jetbrains.bsp.bazel.server.sync.languages.java.JdkResolver
import org.jetbrains.bsp.bazel.server.sync.languages.java.JdkVersionResolver
Expand Down Expand Up @@ -51,6 +52,7 @@ class LanguagePluginServiceTest {
val pythonLanguagePlugin = PythonLanguagePlugin(bazelPathsResolver)
val rustLanguagePlugin = RustLanguagePlugin(bazelPathsResolver)
val androidLanguagePlugin = AndroidLanguagePlugin(javaLanguagePlugin, bazelPathsResolver)
val goLanguagePlugin = GoLanguagePlugin(bazelPathsResolver)
languagePluginsService = LanguagePluginsService(
scalaLanguagePlugin,
javaLanguagePlugin,
Expand All @@ -59,7 +61,8 @@ class LanguagePluginServiceTest {
thriftLanguagePlugin,
pythonLanguagePlugin,
rustLanguagePlugin,
androidLanguagePlugin
androidLanguagePlugin,
goLanguagePlugin
)
}

Expand Down Expand Up @@ -138,6 +141,18 @@ class LanguagePluginServiceTest {
// then
plugin shouldNotBe null
}

@Test
fun `should return GoLanguagePlugin for Go Language`() {
// given
val languages: Set<Language> = hashSetOf(Language.GO)

// when
val plugin = languagePluginsService.getPlugin(languages) as? GoLanguagePlugin

// then
plugin shouldNotBe null
}
}

@Test
Expand Down