daml/bazel_tools/hlint.bzl
gleber aa70c7f64e
Enforce consistent formatting of BUILD files. (#412)
* Add buildifier targets.

The tool allows to check and format BUILD files in the repo.

To check if files are well formatted, run:

    bazel run //:buildifier

To fix badly-formatted files run:

    bazel run //:buildifier-fix

* Cleanup dade-copyright-headers formatting.

* Fix dade-copyright-headers on files with just the copyright.

* Run buildifier automatically on CI via 'fmt.sh'.

* Reformat all BUILD files with buildifier.

Excludes autogenerated Bazel files.
2019-04-12 13:10:16 +02:00

99 lines
3.0 KiB
Python

# Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
# Highly inspired by https://github.com/tweag/rules_haskell/blob/master/haskell/lint.bzl
# but that code has a bug that it doesn't demand lint outputs recursively
#
# Use:
# haskell_hlint(
# name = "haskell-app@hlint",
# deps = ["haskell-app"],
# )
HaskellHLintInfo = provider(
doc = "Provider that collects files produced by linters",
fields = {
"outputs": "List of linter log files.",
},
)
def _collect_hlint_logs(deps):
res = []
for dep in deps:
if HaskellHLintInfo in dep:
res.extend(dep[HaskellHLintInfo].outputs)
return res
def _haskell_hlint_rule_impl(ctx):
return [DefaultInfo(
files = depset(_collect_hlint_logs(ctx.attr.deps)),
)]
def _haskell_hlint_aspect_impl(target, ctx):
inputFiles = []
inputPaths = []
if hasattr(ctx.rule.attr, "srcs"):
for src in ctx.rule.attr.srcs:
for f in src.files:
# We want to only do native Haskell source files, which
# seems to involve ignoring these generated paths
# (the f.is_source almost always returns True)
if all([
f.path.endswith(".hs"),
f.path.startswith("external/") == False,
f.path.startswith("bazel-out/") == False,
f.path.startswith("nix/") == False,
]):
inputFiles.append(f)
inputPaths.append(f.path)
if len(inputFiles) == 0:
return []
output = ctx.actions.declare_file(target.label.name + ".html")
args = ["--hint=" + ctx.files._hlint_yaml[0].path] + inputPaths + ["--report=" + output.path] + ["--verbose"]
# print(args)
ctx.actions.run(
inputs = ctx.files._hlint_yaml + inputFiles,
outputs = [output],
mnemonic = "HaskellHLint",
progress_message = "HaskellHLint {}".format(ctx.label),
executable = ctx.executable._hlint,
arguments = args,
)
outputs = [output]
for dep in ctx.rule.attr.deps:
if HaskellHLintInfo in dep:
outputs.extend(dep[HaskellHLintInfo].outputs)
lint_info = HaskellHLintInfo(outputs = outputs)
output_files = OutputGroupInfo(default = outputs)
return [lint_info, output_files]
haskell_hlint_aspect = aspect(
_haskell_hlint_aspect_impl,
attr_aspects = ["deps"],
attrs = {
"_hlint": attr.label(
executable = True,
cfg = "host",
allow_single_file = True,
default = Label("@hlint_nix//:bin/hlint"),
),
"_hlint_yaml": attr.label(
allow_single_file = True,
default = Label("//:.hlint.yaml"),
),
},
)
haskell_hlint = rule(
_haskell_hlint_rule_impl,
attrs = {
"deps": attr.label_list(
aspects = [haskell_hlint_aspect],
doc = "List of Haskell targets to lint.",
),
},
)