summaryrefslogtreecommitdiff
path: root/rules/lint
diff options
context:
space:
mode:
Diffstat (limited to 'rules/lint')
-rw-r--r--rules/lint/RULES292
-rw-r--r--rules/lint/TARGETS3
-rwxr-xr-xrules/lint/call_lint45
-rwxr-xr-xrules/lint/call_summary36
4 files changed, 376 insertions, 0 deletions
diff --git a/rules/lint/RULES b/rules/lint/RULES
new file mode 100644
index 0000000..add3cdb
--- /dev/null
+++ b/rules/lint/RULES
@@ -0,0 +1,292 @@
+{ "defaults":
+ { "doc":
+ [ "A rule to provide default paths common to all lint targets."
+ , ""
+ , "While lint targets bring their own host directory via the"
+ , "field \"config\", it can still be necessary to bring some"
+ , "default paths, e.g., for finding the compiler, or the interpreter"
+ , "for the runner."
+ ]
+ , "string_fields": ["PATH"]
+ , "target_fields": ["base"]
+ , "field_doc":
+ { "base": ["Other targets to inherit values from."]
+ , "PATH":
+ [ "Paths for looking up system tools."
+ , "Specifying this field extends values from \"base\"."
+ ]
+ }
+ , "imports": {"base-provides-++": ["CC", "defaults-base-provides-++"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "PATH"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "FIELD", "name": "PATH"}
+ , { "type": "let*"
+ , "bindings": [["provider", "PATH"]]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ }
+ ]
+ }
+ }
+ ]
+ ]
+ , "body": {"type": "RESULT", "provides": {"type": "env", "vars": ["PATH"]}}
+ }
+ }
+, "targets":
+ { "doc":
+ [ "Run a given linter on the lint information provided by the given targets."
+ ]
+ , "target_fields": ["linter", "config", "summarizer", "targets"]
+ , "string_fields": ["name"]
+ , "tainted": ["lint"]
+ , "field_doc":
+ { "linter":
+ [ "Single artifact running the lint checks."
+ , ""
+ , "This program is invoked with"
+ , "- argv[1] the file to lint, and"
+ , "- argv[2:] the original command line."
+ , "This invocation happens in an environment with"
+ , "- CONFIG pointing to the directory with all the artifacts given"
+ , " by the field \"config\", and"
+ , "- OUT pointing to a directory to which files with the lint result"
+ , " can be written."
+ , "- META pointing to a json file containing"
+ , " - at key \"direct deps artifact names\" a list of all input"
+ , " artifacts that come from the target itself or are runfiles of a"
+ , " direct dependency."
+ , " - at key \"extra outs\" a list of extra output artifacts that the"
+ , " command might produce, such as DWARF objects if debug fission is"
+ , " enabled."
+ , "- TMPDIR pointing to a directory location that can be used to"
+ , " create additional temporary files."
+ , "It is supposed to indicate by the exit code whether the file to lint"
+ , "complies with the given linting policy, with 0 meaning"
+ , "compliant."
+ , "Stdout and stderr, as well as the directory ${OUT} can be used to"
+ , "provide additional information."
+ ]
+ , "config": ["Any configuration or other files needed by the linter."]
+ , "summarizer":
+ [ "Single artifact generating a summary of the individual lint results."
+ , "It will be called in a directory where all subdirectories"
+ , "except . and .. represent the results of the individual lint"
+ , "actions. Those are given as"
+ , " - a file \"result\" with content \"PASS\" if and only if the lint"
+ , " action exited 0,"
+ , " - files \"stdout\" and \"stderr\" with stdout and stderr of the lint"
+ , " action, and"
+ , " - a directory \"out\" with the additional information provided by the"
+ , " lint action."
+ , "The summarizer is required to indicate the overall result by the exit"
+ , "code, produce a human-readable summary on stdout, and optionally"
+ , "additional information in the directory ${OUT}."
+ ]
+ , "call_lint": ["Launcher for the linter"]
+ , "call_summary": ["Launcher for the summarizer"]
+ , "name":
+ [ "Name of the kind of lint check performed, to be reported"
+ , "when an action is failing."
+ ]
+ }
+ , "implicit":
+ { "defaults": ["defaults"]
+ , "call_lint": ["call_lint"]
+ , "call_summary": ["call_summary"]
+ }
+ , "config_transitions": {"targets": [{"type": "'", "$1": {"LINT": true}}]}
+ , "anonymous":
+ {"lint": {"target": "targets", "provider": "lint", "rule_map": {}}}
+ , "imports":
+ { "stage": ["", "stage_singleton_field"]
+ , "artifacts": ["", "field_artifacts"]
+ , "default-PATH": ["CC", "default-PATH"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "linter"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "linter"], ["location", "linter"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "runner"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "call_lint"], ["location", "runner"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "config"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "config"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ ]
+ , [ "PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1": {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ }
+ ]
+ , ["name", {"type": "join", "$1": {"type": "FIELD", "name": "name"}}]
+ , [ "lint results"
+ , { "type": "foreach"
+ , "range": {"type": "FIELD", "name": "lint"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "src"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "_"}
+ , "provider": "src"
+ }
+ ]
+ , [ "cmd"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "_"}
+ , "provider": "cmd"
+ }
+ ]
+ , [ "src input"
+ , { "type": "DEP_ARTIFACTS"
+ , "dep": {"type": "var", "name": "_"}
+ }
+ ]
+ , [ "direct deps artifact names"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "_"}
+ , "provider": "direct deps artifact names"
+ }
+ ]
+ , [ "extra outs"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "_"}
+ , "provider": "extra outs"
+ }
+ ]
+ ]
+ , "body":
+ { "type": "TREE"
+ , "$1":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "runner"}
+ , {"type": "var", "name": "linter"}
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "src input"}
+ }
+ , { "type": "to_subdir"
+ , "subdir": "config"
+ , "$1": {"type": "var", "name": "config"}
+ }
+ , { "type": "singleton_map"
+ , "key": "meta.json"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "json_encode"
+ , "$1":
+ { "type": "env"
+ , "vars":
+ ["direct deps artifact names", "extra outs"]
+ }
+ }
+ }
+ }
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ ["./runner", {"type": "var", "name": "src"}]
+ , {"type": "var", "name": "cmd"}
+ ]
+ }
+ , "env": {"type": "env", "vars": ["PATH"]}
+ , "outs": ["stdout", "stderr", "result"]
+ , "out_dirs": ["out"]
+ , "may_fail": ["lint"]
+ , "fail_message":
+ { "type": "join"
+ , "$1":
+ [ "lint "
+ , {"type": "var", "name": "name"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "name"}
+ , "then": " failed for "
+ , "else": "failed for "
+ }
+ , {"type": "var", "name": "src"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ , [ "lint results"
+ , {"type": "nub_right", "$1": {"type": "var", "name": "lint results"}}
+ ]
+ , [ "summary input"
+ , {"type": "enumerate", "$1": {"type": "var", "name": "lint results"}}
+ ]
+ , [ "summarizer"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "summarizer"], ["location", "summarizer"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "runner"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "call_summary"], ["location", "runner"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "summary"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "runner"}
+ , {"type": "var", "name": "summarizer"}
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "summary input"}
+ }
+ ]
+ }
+ , "cmd": ["./runner"]
+ , "outs": ["report", "result"]
+ , "out_dirs": ["out"]
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "summary"}
+ , { "type": "singleton_map"
+ , "key": "work"
+ , "value":
+ {"type": "TREE", "$1": {"type": "var", "name": "summary input"}}
+ }
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/rules/lint/TARGETS b/rules/lint/TARGETS
new file mode 100644
index 0000000..de52b00
--- /dev/null
+++ b/rules/lint/TARGETS
@@ -0,0 +1,3 @@
+{ "defaults":
+ {"type": "defaults", "base": [["CC", "defaults"], ["shell", "defaults"]]}
+}
diff --git a/rules/lint/call_lint b/rules/lint/call_lint
new file mode 100755
index 0000000..850812e
--- /dev/null
+++ b/rules/lint/call_lint
@@ -0,0 +1,45 @@
+#!/bin/sh
+# Copyright 2024 Huawei Cloud Computing Technology Co., Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# ensure all required outputs are present
+touch stdout
+touch stderr
+RESULT=UNKNOWN
+echo "${RESULT}" > result
+
+mkdir -p out
+export OUT="$(pwd)/out"
+mkdir -p config
+export CONFIG="$(pwd)/config"
+export META="$(pwd)/meta.json"
+mkdir scratch
+export TMPDIR=$(realpath scratch)
+
+cd work
+
+if ../linter "$@" > ../stdout 2> ../stderr
+then
+ RESULT=PASS
+else
+ RESULT=FAIL
+fi
+
+echo "${RESULT}" > ../result
+
+if [ "${RESULT}" '!=' PASS ]
+then
+ exit 1;
+fi
diff --git a/rules/lint/call_summary b/rules/lint/call_summary
new file mode 100755
index 0000000..9686d0a
--- /dev/null
+++ b/rules/lint/call_summary
@@ -0,0 +1,36 @@
+#!/bin/sh
+# Copyright 2024 Huawei Cloud Computing Technology Co., Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# ensure all required outputs are present
+touch report
+RESULT=UNKNOWN
+echo "${RESULT}" > result
+
+mkdir -p out
+export OUT="$(pwd)/out"
+
+cd work
+
+if ../summarizer > ../report
+then
+ RESULT=PASS
+else
+ RESULT=FAIL
+fi
+
+echo "${RESULT}" > ../result
+
+exit 0