Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c242466

Browse files
committed
Kotlin: first support for Kotlin extractor build
1 parent 341816c commit c242466

11 files changed

Lines changed: 254 additions & 9 deletions

File tree

.bazelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@ build:linux --cxxopt=-std=c++20
1414
build:macos --cxxopt=-std=c++20 --cpu=darwin_x86_64
1515
build:windows --cxxopt=/std:c++20 --cxxopt=/Zc:preprocessor
1616

17+
# emitting jdeps does not work when building the 2.0.0+ kotlin extractor
18+
build --@rules_kotlin//kotlin/settings:jvm_emit_jdeps=false
19+
1720
try-import %workspace%/local.bazelrc

MODULE.bazel

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ bazel_dep(name = "bazel_skylib", version = "1.5.0")
2121
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
2222
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
2323
bazel_dep(name = "fmt", version = "10.0.0")
24+
bazel_dep(name = "rules_kotlin", version = "1.9.4")
25+
26+
# we patch `rules_kotlin` to allow passing `-language-version` at a jvm_kt_library level
27+
single_version_override(
28+
module_name = "rules_kotlin",
29+
patch_strip = 1,
30+
patches = ["//java/kotlin-extractor:rules_kotlin.patch"],
31+
)
2432

2533
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
2634
pip.parse(
@@ -48,11 +56,23 @@ node.toolchain(
4856
)
4957
use_repo(node, "nodejs", "nodejs_toolchains")
5058

51-
lfs_files = use_repo_rule("//misc/bazel:lfs.bzl", "lfs_files")
52-
53-
lfs_files(
54-
name = "kotlin_deps",
55-
dir = "//java/kotlin-extractor:deps",
59+
kotlin_extractor_deps = use_extension("//java/kotlin-extractor:extension.bzl", "kotlin_extractor_deps")
60+
use_repo(
61+
kotlin_extractor_deps,
62+
"kotlin_extractor_dep_1.4.32",
63+
"kotlin_extractor_dep_1.5.0",
64+
"kotlin_extractor_dep_1.5.10",
65+
"kotlin_extractor_dep_1.5.20",
66+
"kotlin_extractor_dep_1.5.30",
67+
"kotlin_extractor_dep_1.6.0",
68+
"kotlin_extractor_dep_1.6.20",
69+
"kotlin_extractor_dep_1.7.0",
70+
"kotlin_extractor_dep_1.7.20",
71+
"kotlin_extractor_dep_1.8.0",
72+
"kotlin_extractor_dep_1.9.0-Beta",
73+
"kotlin_extractor_dep_1.9.20-Beta",
74+
"kotlin_extractor_dep_2.0.0-Beta4",
75+
"kotlin_extractor_dep_2.0.255-SNAPSHOT",
5676
)
5777

5878
register_toolchains(

java/kotlin-extractor/BUILD.bazel

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
load(
2+
"//java/kotlin-extractor:versions.bzl",
3+
"VERSIONS",
4+
"get_compatilibity_sources",
5+
"version_less",
6+
)
7+
load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library")
8+
load("@rules_kotlin//kotlin:core.bzl", "kt_javac_options", "kt_kotlinc_options")
9+
10+
py_binary(
11+
name = "generate_dbscheme",
12+
srcs = ["generate_dbscheme.py"],
13+
)
14+
15+
genrule(
16+
name = "generated-dbscheme",
17+
srcs = ["//java:dbscheme"],
18+
outs = ["KotlinExtractorDbScheme.kt"],
19+
cmd = "$(execpath :generate_dbscheme) $< $@",
20+
tools = [":generate_dbscheme"],
21+
)
22+
23+
kt_javac_options(
24+
name = "javac-options",
25+
warn = "off",
26+
)
27+
28+
[
29+
(
30+
kt_kotlinc_options(
31+
name = "kotlinc-options-%s" % v,
32+
include_stdlibs = "none",
33+
jvm_target = "1.8",
34+
language_version = v[:3],
35+
warn = "error",
36+
x_optin = [
37+
"kotlin.RequiresOptIn",
38+
"org.jetbrains.kotlin.ir.symbols.%s" %
39+
("IrSymbolInternals" if version_less(v, "2.0.0") else "UnsafeDuringIrConstructionAPI"),
40+
],
41+
x_suppress_version_warnings = True,
42+
),
43+
kt_jvm_library(
44+
name = "kotlin-extractor-%s" % v,
45+
srcs =
46+
[":generated-dbscheme"] +
47+
glob(
48+
[
49+
"src/**/*.kt",
50+
"src/**/*.java",
51+
],
52+
exclude = ["src/main/kotlin/utils/versions/**"],
53+
) + get_compatilibity_sources(v, "src/main/kotlin/utils/versions"),
54+
javac_opts = ":javac-options",
55+
kotlinc_opts = ":kotlinc-options-%s" % v,
56+
module_name = "codeql-kotlin-extractor",
57+
deps = [
58+
"@kotlin_extractor_dep_%s//:kotlin-compiler" % v,
59+
"@kotlin_extractor_dep_%s//:kotlin-stdlib" % v,
60+
],
61+
),
62+
)
63+
for v in VERSIONS
64+
]

java/kotlin-extractor/deps/BUILD.bazel

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:8739c76e681f900923b900c9df0ef75cf421d39cabb54650c4b9ad19b6a76d85
3+
size 22
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
load("//java/kotlin-extractor:versions.bzl", "VERSIONS")
2+
load("//misc/bazel:lfs.bzl", "lfs_smudge")
3+
4+
_kotlin_dep_build = """
5+
load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_import")
6+
7+
package(default_visibility = ["//visibility:public"])
8+
9+
kt_jvm_import(
10+
name = "kotlin-compiler",
11+
jar = "kotlin-compiler-{version}.jar",
12+
)
13+
14+
kt_jvm_import(
15+
name = "kotlin-compiler-embeddable",
16+
jar = "kotlin-compiler-embeddable-{version}.jar",
17+
)
18+
19+
kt_jvm_import(
20+
name = "kotlin-stdlib",
21+
jar = "kotlin-stdlib-{version}.jar",
22+
)
23+
"""
24+
25+
def _kotlin_dep_impl(repository_ctx):
26+
_, sep, version = repository_ctx.name.rpartition("_")
27+
if not sep:
28+
fail("rule @%s malformed, name should be <prefix>_<kotlin version>")
29+
30+
sources = [
31+
# "empty.jar",
32+
"kotlin-compiler-%s.jar" % version,
33+
"kotlin-compiler-embeddable-%s.jar" % version,
34+
"kotlin-stdlib-%s.jar" % version,
35+
]
36+
sources = [repository_ctx.path(Label("//java/kotlin-extractor/deps:%s" % p)) for p in sources]
37+
lfs_smudge(repository_ctx, sources)
38+
39+
# for some reason rules_kotlin warns about these jars missing, this is to silence those warnings
40+
for jar in (
41+
"annotations-13.0.jar",
42+
"kotlin-stdlib.jar",
43+
"kotlin-reflect.jar",
44+
"kotlin-script-runtime.jar",
45+
"trove4j.jar",
46+
):
47+
repository_ctx.symlink("empty.jar", jar)
48+
repository_ctx.file("BUILD.bazel", _kotlin_dep_build.format(version = version))
49+
50+
_kotlin_dep = repository_rule(implementation = _kotlin_dep_impl)
51+
52+
def _kotlin_deps_impl(module_ctx):
53+
deps = []
54+
for v in VERSIONS:
55+
dep = "kotlin_extractor_dep_%s" % v
56+
_kotlin_dep(name = dep)
57+
deps.append(dep)
58+
return module_ctx.extension_metadata(
59+
root_module_direct_deps = deps,
60+
root_module_direct_dev_deps = [],
61+
)
62+
63+
kotlin_extractor_deps = module_extension(implementation = _kotlin_deps_impl)

java/kotlin-extractor/generate_dbscheme.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
tables = {}
99

1010
dbscheme = sys.argv[1] if len(sys.argv) >= 2 else '../ql/lib/config/semmlecode.dbscheme'
11+
output = sys.argv[2] if len(sys.argv) >= 3 else 'src/main/kotlin/KotlinExtractorDbScheme.kt'
1112

1213
def parse_dbscheme(filename):
1314
with open(filename, 'r') as f:
@@ -152,7 +153,7 @@ def genTable(kt, relname, columns, enum = None, kind = None, num = None, typ = N
152153
kt.write(')\\n")\n')
153154
kt.write('}\n')
154155

155-
with open('src/main/kotlin/KotlinExtractorDbScheme.kt', 'w') as kt:
156+
with open(output, 'w') as kt:
156157
kt.write('/* Generated by ' + sys.argv[0] + ': Do not edit manually. */\n')
157158
kt.write('package com.github.codeql\n')
158159
kt.write('import java.util.Date\n')
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
diff --git a/src/main/starlark/core/options/opts.kotlinc.bzl b/src/main/starlark/core/options/opts.kotlinc.bzl
2+
index 9b15fb8..c0ac2cd 100644
3+
--- a/src/main/starlark/core/options/opts.kotlinc.bzl
4+
+++ b/src/main/starlark/core/options/opts.kotlinc.bzl
5+
@@ -28,6 +28,11 @@ def _map_jvm_target_to_flag(version):
6+
return None
7+
return ["-jvm-target=%s" % version]
8+
9+
+def _map_language_version_to_flag(version):
10+
+ if not version:
11+
+ return None
12+
+ return ["-language-version=%s" % version, "-api-version=%s" % version]
13+
+
14+
_KOPTS_ALL = {
15+
"warn": struct(
16+
args = dict(
17+
@@ -349,6 +354,15 @@ _KOPTS_ALL = {
18+
value_to_flag = None,
19+
map_value_to_flag = _map_jvm_target_to_flag,
20+
),
21+
+ "language_version": struct(
22+
+ args = dict(
23+
+ default = "1.9",
24+
+ doc = "-language-version",
25+
+ ),
26+
+ type = attr.string,
27+
+ value_to_flag = None,
28+
+ map_value_to_flag = _map_language_version_to_flag,
29+
+ ),
30+
}
31+
32+
# Filters out options that are not available in current compiler release

java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,16 @@ public boolean equals(Object obj) {
547547
}
548548
}
549549

550+
@Override
551+
public int hashCode() {
552+
int hash = 7;
553+
hash = 31 * hash + majorVersion;
554+
hash = 31 * hash + minorVersion;
555+
hash = 31 * hash + (int)lastModified;
556+
hash = 31 * hash + (extractorName == null ? 0 : extractorName.hashCode());
557+
return hash;
558+
}
559+
550560
private boolean newerThan(TrapClassVersion tcv) {
551561
// Classes being compiled from source have major version 0 but should take precedence
552562
// over any classes with the same qualified name loaded from the classpath

java/kotlin-extractor/versions.bzl

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
VERSIONS = [
2+
"1.4.32",
3+
"1.5.0",
4+
"1.5.10",
5+
"1.5.20",
6+
"1.5.30",
7+
"1.6.0",
8+
"1.6.20",
9+
"1.7.0",
10+
"1.7.20",
11+
"1.8.0",
12+
"1.9.0-Beta",
13+
"1.9.20-Beta",
14+
"2.0.0-Beta4",
15+
"2.0.255-SNAPSHOT",
16+
]
17+
18+
def _version_to_tuple(v):
19+
v, _, tail = v.partition("-")
20+
v = tuple([int(x) for x in v.split(".")])
21+
return v + (tail,)
22+
23+
def _tuple_to_version(t):
24+
ret = ".".join([str(x) for x in t[:3]])
25+
if t[3]:
26+
ret += "-" + t[3]
27+
return ret
28+
29+
def version_less(lhs, rhs):
30+
return _version_to_tuple(lhs) < _version_to_tuple(rhs)
31+
32+
def _basename(path):
33+
if "/" not in path:
34+
return path
35+
return path[path.rindex("/") + 1:]
36+
37+
def get_compatilibity_sources(version, dir):
38+
prefix = "%s/v_" % dir
39+
available = native.glob(["%s*" % prefix], exclude_directories = 0)
40+
41+
# we want files with the same base name to replace ones for previous versions, hence the map
42+
srcs = {}
43+
for d in available:
44+
compat_version = d[len(prefix):].replace("_", ".")
45+
if version_less(version, compat_version):
46+
break
47+
files = native.glob(["%s/*.kt" % d])
48+
srcs |= {_basename(f): f for f in files}
49+
return srcs.values()

0 commit comments

Comments
 (0)