forked from bazelbuild/rules_scala
-
Notifications
You must be signed in to change notification settings - Fork 0
/
scala_doc.bzl
124 lines (104 loc) · 4.76 KB
/
scala_doc.bzl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""Scaladoc support"""
load("@io_bazel_rules_scala//scala/private:common.bzl", "collect_plugin_paths")
ScaladocAspectInfo = provider(fields = [
"src_files",
"compile_jars",
"plugins",
])
def _scaladoc_intransitive_aspect_impl(target, ctx):
"""Build scaladocs only for the provided targets."""
return _scaladoc_aspect_impl(target, ctx, transitive = False)
def _scaladoc_aspect_impl(target, ctx, transitive = True):
"""Collect source files and compile_jars from JavaInfo-returning deps."""
# We really only care about visited targets with srcs, so only look at those.
if hasattr(ctx.rule.attr, "srcs"):
# Collect only Java and Scala sources enumerated in visited targets, including src_files in deps.
direct_deps = [file for file in ctx.rule.files.srcs if file.extension.lower() in ["java", "scala"]]
# Sometimes we only want to generate scaladocs for a single target and not all of its
# dependencies
if transitive:
transitive_deps = [dep[ScaladocAspectInfo].src_files for dep in ctx.rule.attr.deps if ScaladocAspectInfo in dep]
else:
transitive_deps = []
src_files = depset(direct = direct_deps, transitive = transitive_deps)
# Collect compile_jars from visited targets' deps.
compile_jars = depset(
direct = [file for file in ctx.rule.files.deps],
transitive = (
[dep[JavaInfo].compile_jars for dep in ctx.rule.attr.deps if JavaInfo in dep] +
[dep[ScaladocAspectInfo].compile_jars for dep in ctx.rule.attr.deps if ScaladocAspectInfo in dep]
),
)
plugins = depset()
if hasattr(ctx.rule.attr, "plugins"):
plugins = depset(direct = ctx.rule.attr.plugins)
return [ScaladocAspectInfo(
src_files = src_files,
compile_jars = compile_jars,
plugins = plugins,
)]
else:
return []
_scaladoc_transitive_aspect = aspect(
implementation = _scaladoc_aspect_impl,
attr_aspects = ["deps"],
required_aspect_providers = [
[JavaInfo],
],
)
scaladoc_intransitive_aspect = aspect(
implementation = _scaladoc_intransitive_aspect_impl,
attr_aspects = ["deps"],
required_aspect_providers = [
[JavaInfo],
],
)
def _scala_doc_impl(ctx):
# scaladoc warns if you don't have the output directory already created, which is annoying.
output_path = ctx.actions.declare_directory("{}.html".format(ctx.attr.name))
# Collect all source files and compile_jars to pass to scaladoc by way of an aspect.
src_files = depset(transitive = [dep[ScaladocAspectInfo].src_files for dep in ctx.attr.deps])
compile_jars = depset(transitive = [dep[ScaladocAspectInfo].compile_jars for dep in ctx.attr.deps])
# Get the 'real' paths to the plugin jars.
plugins = collect_plugin_paths(depset(transitive = [dep[ScaladocAspectInfo].plugins for dep in ctx.attr.deps]).to_list())
# Construct the full classpath depset since we need to add compiler plugins too.
classpath = depset(transitive = [plugins, compile_jars])
# Construct scaladoc args, which also include scalac args.
# See `scaladoc -help` for more information.
args = ctx.actions.args()
args.set_param_file_format("multiline")
args.use_param_file(param_file_arg = "@%s", use_always = True)
args.add("-usejavacp")
args.add("-nowarn") # turn off warnings for now since they can obscure actual errors for large scala_doc targets
args.add_all(ctx.attr.scalacopts)
args.add("-d", output_path.path)
args.add_all(plugins, format_each = "-Xplugin:%s")
args.add_joined("-classpath", classpath, join_with = ctx.configuration.host_path_separator)
args.add_all(src_files)
# Run the scaladoc tool!
ctx.actions.run(
inputs = depset(transitive = [src_files, classpath]),
outputs = [output_path],
executable = ctx.attr._scaladoc.files_to_run.executable,
mnemonic = "ScalaDoc",
progress_message = "scaladoc {}".format(ctx.label),
arguments = [args],
)
return [DefaultInfo(files = depset(direct = [output_path]))]
def make_scala_doc_rule(aspect = _scaladoc_transitive_aspect):
return rule(
attrs = {
"deps": attr.label_list(
aspects = [aspect],
providers = [JavaInfo],
),
"scalacopts": attr.string_list(),
"_scaladoc": attr.label(
cfg = "exec",
executable = True,
default = Label("//src/scala/io/bazel/rules_scala/scaladoc_support:scaladoc_generator"),
),
},
doc = "Generate Scaladoc HTML documentation for source files in from the given dependencies.",
implementation = _scala_doc_impl,
)