137 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Linting"""
 | |
| 
 | |
| load(
 | |
|     "@io_tweag_rules_haskell//haskell:providers.bzl",
 | |
|     "HaskellInfo",
 | |
|     "HaskellLibraryInfo",
 | |
|     "HaskellLintInfo",
 | |
| )
 | |
| load(":private/context.bzl", "haskell_context", "render_env")
 | |
| load(":private/packages.bzl", "expose_packages", "pkg_info_to_compile_flags")
 | |
| load(
 | |
|     ":private/path_utils.bzl",
 | |
|     "target_unique_name",
 | |
| )
 | |
| load(":providers.bzl", "get_libs_for_ghc_linker")
 | |
| load(":private/set.bzl", "set")
 | |
| 
 | |
| def _collect_lint_logs(deps):
 | |
|     lint_logs = set.empty()
 | |
|     for dep in deps:
 | |
|         if HaskellLintInfo in dep:
 | |
|             set.mutable_union(lint_logs, dep[HaskellLintInfo].outputs)
 | |
|     return lint_logs
 | |
| 
 | |
| def _haskell_lint_rule_impl(ctx):
 | |
|     return [DefaultInfo(
 | |
|         files = set.to_depset(_collect_lint_logs(ctx.attr.deps)),
 | |
|     )]
 | |
| 
 | |
| def _haskell_lint_aspect_impl(target, ctx):
 | |
|     hs = haskell_context(ctx, ctx.rule.attr)
 | |
| 
 | |
|     if HaskellInfo not in target:
 | |
|         return []
 | |
| 
 | |
|     hs_info = target[HaskellInfo]
 | |
|     lib_info = target[HaskellLibraryInfo] if HaskellLibraryInfo in target else None
 | |
| 
 | |
|     args = ctx.actions.args()
 | |
| 
 | |
|     args.add_all([
 | |
|         "-O0",
 | |
|         "-v0",
 | |
|         "-fno-code",
 | |
|         "-Wall",
 | |
|         "-Werror",
 | |
|         "-Wcompat",
 | |
|         "-Wincomplete-record-updates",
 | |
|         "-Wincomplete-uni-patterns",
 | |
|         "-Wredundant-constraints",
 | |
|         "-Wnoncanonical-monad-instances",
 | |
|         "--make",
 | |
|     ])
 | |
| 
 | |
|     args.add_all(pkg_info_to_compile_flags(expose_packages(
 | |
|         hs_info,
 | |
|         lib_info,
 | |
|         use_direct = False,
 | |
|         use_my_pkg_id = None,
 | |
|         custom_package_databases = None,
 | |
|         version = ctx.rule.attr.version,
 | |
|     )))
 | |
| 
 | |
|     sources = set.to_list(hs_info.source_files)
 | |
| 
 | |
|     args.add_all(sources)
 | |
| 
 | |
|     lint_log = ctx.actions.declare_file(
 | |
|         target_unique_name(hs, "lint-log"),
 | |
|     )
 | |
| 
 | |
|     # Transitive library dependencies for runtime.
 | |
|     (library_deps, ld_library_deps, _ghc_env) = get_libs_for_ghc_linker(
 | |
|         hs,
 | |
|         hs_info.transitive_cc_dependencies,
 | |
|     )
 | |
| 
 | |
|     ctx.actions.run_shell(
 | |
|         inputs = depset(transitive = [
 | |
|             depset(sources),
 | |
|             set.to_depset(hs_info.package_databases),
 | |
|             set.to_depset(hs_info.interface_dirs),
 | |
|             set.to_depset(hs_info.dynamic_libraries),
 | |
|             depset(library_deps),
 | |
|             depset(ld_library_deps),
 | |
|             depset([hs.tools.ghc]),
 | |
|         ]),
 | |
|         outputs = [lint_log],
 | |
|         mnemonic = "HaskellLint",
 | |
|         progress_message = "HaskellLint {}".format(ctx.label),
 | |
|         command = """
 | |
|         {env}
 | |
|         {ghc} "$@" > {output} 2>&1 || rc=$? && cat {output} && exit $rc
 | |
|         """.format(
 | |
|             ghc = hs.tools.ghc.path,
 | |
|             output = lint_log.path,
 | |
|             # XXX Workaround
 | |
|             # https://github.com/bazelbuild/bazel/issues/5980.
 | |
|             env = render_env(hs.env),
 | |
|         ),
 | |
|         arguments = [args],
 | |
|         use_default_shell_env = True,
 | |
|     )
 | |
| 
 | |
|     lint_info = HaskellLintInfo(outputs = set.singleton(lint_log))
 | |
|     output_files = OutputGroupInfo(default = [lint_log])
 | |
| 
 | |
|     return [lint_info, output_files]
 | |
| 
 | |
| haskell_lint_aspect = aspect(
 | |
|     _haskell_lint_aspect_impl,
 | |
|     attr_aspects = ["deps"],
 | |
|     toolchains = ["@io_tweag_rules_haskell//haskell:toolchain"],
 | |
| )
 | |
| 
 | |
| haskell_lint = rule(
 | |
|     _haskell_lint_rule_impl,
 | |
|     attrs = {
 | |
|         "deps": attr.label_list(
 | |
|             aspects = [haskell_lint_aspect],
 | |
|             doc = "List of Haskell targets to lint.",
 | |
|         ),
 | |
|     },
 | |
|     toolchains = ["@io_tweag_rules_haskell//haskell:toolchain"],
 | |
| )
 | |
| """Check source code of targets in `deps` using a restrictive set of GHC
 | |
| flags.
 | |
| 
 | |
| The following flags will be used:
 | |
| 
 | |
| * `-Wall`
 | |
| * `-Werror`
 | |
| * `-Wcompat`
 | |
| * `-Wincomplete-record-updates`
 | |
| * `-Wincomplete-uni-patterns`
 | |
| * `-Wredundant-constraints`
 | |
| """
 |