Skip to content

Commit e69da66

Browse files
authored
Make scaladoc rule handle transient deps better (and add some tests) (#1584)
* fix scaladoc rule to handle transient deps better Also Refactors and tests * lint fixes
1 parent d4e00e4 commit e69da66

File tree

8 files changed

+171
-32
lines changed

8 files changed

+171
-32
lines changed

scala/private/rules/scala_doc.bzl

+31-32
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
load("@io_bazel_rules_scala//scala/private:common.bzl", "collect_plugin_paths")
44

55
ScaladocAspectInfo = provider(fields = [
6-
"src_files",
7-
"compile_jars",
8-
"plugins",
6+
"src_files", #depset[File]
7+
"compile_jars", #depset[File]
8+
"plugins", #depset[Target]
99
])
1010

1111
def _scaladoc_intransitive_aspect_impl(target, ctx):
@@ -15,40 +15,39 @@ def _scaladoc_intransitive_aspect_impl(target, ctx):
1515
def _scaladoc_aspect_impl(target, ctx, transitive = True):
1616
"""Collect source files and compile_jars from JavaInfo-returning deps."""
1717

18+
src_files = depset()
19+
plugins = depset()
20+
compile_jars = depset()
21+
1822
# We really only care about visited targets with srcs, so only look at those.
1923
if hasattr(ctx.rule.attr, "srcs"):
2024
# Collect only Java and Scala sources enumerated in visited targets, including src_files in deps.
21-
direct_deps = [file for file in ctx.rule.files.srcs if file.extension.lower() in ["java", "scala"]]
22-
23-
# Sometimes we only want to generate scaladocs for a single target and not all of its
24-
# dependencies
25-
if transitive:
26-
transitive_deps = [dep[ScaladocAspectInfo].src_files for dep in ctx.rule.attr.deps if ScaladocAspectInfo in dep]
27-
else:
28-
transitive_deps = []
29-
30-
src_files = depset(direct = direct_deps, transitive = transitive_deps)
31-
32-
# Collect compile_jars from visited targets' deps.
33-
compile_jars = depset(
34-
direct = [file for file in ctx.rule.files.deps],
35-
transitive = (
36-
[dep[JavaInfo].compile_jars for dep in ctx.rule.attr.deps if JavaInfo in dep] +
37-
[dep[ScaladocAspectInfo].compile_jars for dep in ctx.rule.attr.deps if ScaladocAspectInfo in dep]
38-
),
39-
)
25+
src_files = depset([file for file in ctx.rule.files.srcs if file.extension.lower() in ["java", "scala"]])
26+
27+
compile_jars = target[JavaInfo].transitive_compile_time_jars
4028

41-
plugins = depset()
4229
if hasattr(ctx.rule.attr, "plugins"):
43-
plugins = depset(direct = ctx.rule.attr.plugins)
44-
45-
return [ScaladocAspectInfo(
46-
src_files = src_files,
47-
compile_jars = compile_jars,
48-
plugins = plugins,
49-
)]
50-
else:
51-
return []
30+
plugins = depset(ctx.rule.attr.plugins)
31+
32+
# Sometimes we only want to generate scaladocs for a single target and not all of its
33+
# dependencies
34+
transitive_srcs = depset()
35+
transitive_compile_jars = depset()
36+
transitive_plugins = depset()
37+
38+
if transitive:
39+
for dep in ctx.rule.attr.deps:
40+
if ScaladocAspectInfo in dep:
41+
aspec_info = dep[ScaladocAspectInfo]
42+
transitive_srcs = aspec_info.src_files
43+
transitive_compile_jars = aspec_info.compile_jars
44+
transitive_plugins = aspec_info.plugins
45+
46+
return [ScaladocAspectInfo(
47+
src_files = depset(transitive = [src_files, transitive_srcs]),
48+
compile_jars = depset(transitive = [compile_jars, transitive_compile_jars]),
49+
plugins = depset(transitive = [plugins, transitive_plugins]),
50+
)]
5251

5352
_scaladoc_transitive_aspect = aspect(
5453
implementation = _scaladoc_aspect_impl,

test/shell/test_scaladoc.sh

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# shellcheck source=./test_runner.sh
2+
3+
dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
4+
. "${dir}"/test_runner.sh
5+
. "${dir}"/test_helper.sh
6+
runner=$(get_test_runner "${1:-local}")
7+
8+
_check_file_existence() {
9+
local filepath=$1
10+
local expect=$2 #1 for yes, 0 for no
11+
12+
if [[ -f "$filepath" ]] ; then
13+
if [[ $expect == 0 ]]; then
14+
echo "Error: Unexpected scaladoc file found: ${filepath} "
15+
exit 1;
16+
fi
17+
else
18+
if [[ $expect == 1 ]]; then
19+
echo "Error: Expected scaladoc file not found: ${filepath} "
20+
exit 1;
21+
fi
22+
fi
23+
}
24+
25+
test_scaladoc_transitive() {
26+
#Verify that docs are generated for B AND A. (B depends on A).
27+
set -e
28+
29+
bazel build //test_expect_failure/scaladoc:scaladoc_transitive --extra_toolchains=//test/toolchains:ast_plus_one_deps_unused_deps_warn
30+
31+
local scaladoc_outpath="$(bazel cquery //test_expect_failure/scaladoc:scaladoc_transitive --extra_toolchains=//test/toolchains:ast_plus_one_deps_unused_deps_warn --output=files)"
32+
33+
_check_file_existence ${scaladoc_outpath}/"B$.html" 1
34+
_check_file_existence ${scaladoc_outpath}/"A$.html" 1
35+
}
36+
37+
test_scaladoc_intransitive() {
38+
#Verify that docs only generated for B. (B depends on A)
39+
40+
set -e
41+
42+
bazel build //test_expect_failure/scaladoc:scaladoc_intransitive --extra_toolchains=//test/toolchains:ast_plus_one_deps_unused_deps_warn
43+
44+
local scaladoc_outpath="$(bazel cquery //test_expect_failure/scaladoc:scaladoc_intransitive --extra_toolchains=//test/toolchains:ast_plus_one_deps_unused_deps_warn --output=files)"
45+
46+
_check_file_existence ${scaladoc_outpath}/"B$.html" 1
47+
_check_file_existence ${scaladoc_outpath}/"A$.html" 0
48+
}
49+
50+
test_scaladoc_works_with_transitive_external_deps() {
51+
#Tests absense of a bug where scaladoc rule wasn't handling transitive dependencies that aren't scala_xxxx (i.e. don't hav a srcs attribute)
52+
#Note: need to use a plus-one toolchain to enable transitive deps.
53+
54+
set -e
55+
56+
#Just make sure it builds correctly
57+
bazel build //test_expect_failure/scaladoc:scaladoc_C --extra_toolchains=//test/toolchains:ast_plus_one_deps_unused_deps_warn
58+
59+
}
60+
61+
$runner test_scaladoc_intransitive
62+
$runner test_scaladoc_transitive
63+
$runner test_scaladoc_works_with_transitive_external_deps

test_expect_failure/scaladoc/A.scala

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
object A {
3+
def main() {
4+
println("hi")
5+
}
6+
}

test_expect_failure/scaladoc/B.scala

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object B {
2+
def myfunc() {
3+
A.main()
4+
}
5+
}

test_expect_failure/scaladoc/BUILD

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
load("scaladoc.bzl", "scala_doc_intransitive")
2+
load("//scala:scala.bzl", "scala_doc", "scala_library")
3+
load("//scala:scala_import.bzl", "scala_import")
4+
5+
package(default_testonly = 1)
6+
7+
scala_library(
8+
name = "A",
9+
srcs = ["A.scala"],
10+
deps = [],
11+
)
12+
13+
#B depends on A
14+
scala_library(
15+
name = "B",
16+
srcs = ["B.scala"],
17+
deps = ["A"],
18+
)
19+
20+
#Simulate A & B as if they were imported libraries (in particular they are targets that do not have srcs attribute)
21+
scala_import(
22+
name = "ImportedA",
23+
jars = ["A"],
24+
)
25+
26+
scala_import(
27+
name = "ImportedB",
28+
jars = ["B"],
29+
deps = ["ImportedA"],
30+
)
31+
32+
#Setup this scala_library target so that it has dependency on a transitive external lib.
33+
scala_library(
34+
name = "C",
35+
srcs = ["C.scala"],
36+
deps = [
37+
"ImportedB",
38+
#For the test, don't include ImportedA here... we want it to be loaded transitively
39+
],
40+
)
41+
42+
scala_doc(
43+
name = "scaladoc_transitive",
44+
deps = ["B"],
45+
)
46+
47+
scala_doc_intransitive(
48+
name = "scaladoc_intransitive",
49+
deps = ["B"],
50+
)
51+
52+
scala_doc(
53+
name = "scaladoc_C",
54+
deps = ["C"],
55+
)

test_expect_failure/scaladoc/C.scala

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//import cats.syntax.all._
2+
3+
object C {
4+
def myfunc() = {
5+
A.main() //Call into A, which is a transitive dependency of this lib
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
load("//scala:scala.bzl", "make_scala_doc_rule", "scaladoc_intransitive_aspect")
2+
3+
scala_doc_intransitive = make_scala_doc_rule(scaladoc_intransitive_aspect) #Only scaladoc specified deps

test_rules_scala.sh

+1
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,4 @@ $runner bazel build //test_statsfile:SimpleNoStatsFile_statsfile --extra_toolcha
5757
. "${test_dir}"/test_inherited_environment.sh
5858
. "${test_dir}"/test_persistent_worker.sh
5959
. "${test_dir}"/test_semanticdb.sh
60+
. "${test_dir}"/test_scaladoc.sh

0 commit comments

Comments
 (0)