-
-
Notifications
You must be signed in to change notification settings - Fork 287
/
Copy pathscala_doc.bzl
134 lines (110 loc) · 5.21 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
125
126
127
128
129
130
131
132
133
134
"""Scaladoc support"""
load("//scala/private:common.bzl", "collect_plugin_paths")
load("//scala:providers.bzl", "ScalaInfo")
ScaladocAspectInfo = provider(fields = [
"src_files", #depset[File]
"compile_jars", #depset[File]
"macro_classpath", #depset[File]
"plugins", #depset[Target]
])
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."""
src_files = depset()
plugins = depset()
compile_jars = depset()
# 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.
src_files = depset([file for file in ctx.rule.files.srcs if file.extension.lower() in ["java", "scala"]])
compile_jars = target[JavaInfo].transitive_compile_time_jars
if hasattr(ctx.rule.attr, "plugins"):
plugins = depset(ctx.rule.attr.plugins)
macro_classpath = []
for dependency in ctx.rule.attr.deps:
if ScalaInfo in dependency and dependency[ScalaInfo].contains_macros:
macro_classpath.append(dependency[JavaInfo].transitive_runtime_jars)
# Sometimes we only want to generate scaladocs for a single target and not all of its
# dependencies
transitive_srcs = depset()
transitive_plugins = depset()
if transitive:
for dep in ctx.rule.attr.deps:
if ScaladocAspectInfo in dep:
aspec_info = dep[ScaladocAspectInfo]
transitive_srcs = aspec_info.src_files
transitive_plugins = aspec_info.plugins
return [ScaladocAspectInfo(
src_files = depset(transitive = [src_files, transitive_srcs]),
compile_jars = depset(transitive = [compile_jars]),
macro_classpath = depset(transitive = macro_classpath),
plugins = depset(transitive = [plugins, transitive_plugins]),
)]
_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])
# See the documentation for `collect_jars` in `scala/private/common.bzl` to understand why this is prepended to the
# classpath
macro_classpath = depset(transitive = [dep[ScaladocAspectInfo].macro_classpath 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 = [macro_classpath, 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 = "//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,
)