|
1 | 1 | load("util:batch.star", "make_batches")
|
2 | 2 | load("util:tarif.star", "tarif")
|
3 | 3 |
|
4 |
| -# Defines a check that searches for banned strings in files. |
5 |
| -# Also defines a target `strings` that the user can override from the provided default. |
6 | 4 | def banned_strings_check(
|
7 | 5 | name: str,
|
8 | 6 | description: str,
|
9 | 7 | strings: list[str],
|
10 | 8 | files: list[str] = ["file/all"]):
|
11 |
| - prefix = native.current_label().prefix() |
| 9 | + # Register an option to allow the user to override the banned strings. |
12 | 10 | native.option(name = "strings", default = strings)
|
13 | 11 |
|
14 |
| - def impl(ctx: CheckContext, targets: CheckTargets): |
15 |
| - re = regex.Regex("|".join([regex.escape(word) for word in ctx.inputs().strings])) |
16 |
| - paths = [file.path for file in targets.files] |
17 |
| - for batch in make_batches(paths): |
18 |
| - description = "{prefix} ({num_files} files)".format(prefix = prefix, num_files = len(batch)) |
19 |
| - ctx.spawn(description = description, weight = len(batch)).then(run, ctx, re, batch) |
20 |
| - |
21 |
| - def run(ctx: CheckContext, re: regex.Regex, batch: list[str]): |
22 |
| - results = [] |
23 |
| - for file in batch: |
24 |
| - abspath = fs.join(ctx.paths().workspace_dir, file) |
25 |
| - data = fs.try_read_file(abspath) |
26 |
| - if data == None: |
27 |
| - # Skip files that are not UTF-8 encoded. |
28 |
| - continue |
29 |
| - line_index = lines.LineIndex(data) |
30 |
| - for match in re.finditer(data): |
31 |
| - line_col = line_index.line_col(match.start(0)) |
32 |
| - result = tarif.Result( |
33 |
| - level = tarif.LEVEL_WARNING, |
34 |
| - message = "{description}: `{content}'".format(description = description, content = match.group(0)), |
35 |
| - path = file, |
36 |
| - rule_id = "found", |
37 |
| - location = tarif.Location( |
38 |
| - line = line_col.line + 1, |
39 |
| - column = line_col.col + 1, |
40 |
| - ), |
41 |
| - ) |
42 |
| - results.append(result) |
43 |
| - res = tarif.Tarif(results = results) |
44 |
| - ctx.add_tarif(json.encode(res)) |
45 |
| - |
| 12 | + config = BannedStringsConfig( |
| 13 | + label = native.current_label().relative_to(":" + name), |
| 14 | + description = description, |
| 15 | + strings = strings, |
| 16 | + ) |
46 | 17 | native.check(
|
47 | 18 | name = name,
|
48 |
| - description = "Evaluating {}.{}".format(prefix, name), |
49 |
| - impl = impl, |
| 19 | + description = "Evaluating {}.{}".format(native.current_label().prefix(), name), |
| 20 | + impl = lambda ctx, targets: _impl(ctx, targets, config), |
50 | 21 | files = files,
|
51 | 22 | inputs = {
|
52 | 23 | "strings": ":strings",
|
53 | 24 | },
|
54 | 25 | )
|
| 26 | + |
| 27 | +BannedStringsConfig = record( |
| 28 | + label = label.Label, |
| 29 | + description = str, |
| 30 | + strings = list[str], |
| 31 | +) |
| 32 | + |
| 33 | +def _impl(ctx: CheckContext, targets: CheckTargets, config: BannedStringsConfig): |
| 34 | + # Build a regex from the banned strings provided in the config. |
| 35 | + regex_obj = regex.Regex("|".join([regex.escape(word) for word in config.strings])) |
| 36 | + paths = [file.path for file in targets.files] |
| 37 | + |
| 38 | + # Batch the file paths and spawn a job for each batch. |
| 39 | + for batch in make_batches(paths): |
| 40 | + batch_description = "{prefix} ({num_files} files)".format(prefix = config.label.prefix(), num_files = len(batch)) |
| 41 | + ctx.spawn(description = batch_description, weight = len(batch)).then( |
| 42 | + _run, |
| 43 | + ctx, |
| 44 | + regex_obj, |
| 45 | + batch, |
| 46 | + batch_description, |
| 47 | + config, |
| 48 | + ) |
| 49 | + |
| 50 | +def _run(ctx: CheckContext, re_obj: regex.Regex, batch: list[str], batch_description: str, config: BannedStringsConfig): |
| 51 | + results = [] |
| 52 | + for file in batch: |
| 53 | + abspath = fs.join(ctx.paths().workspace_dir, file) |
| 54 | + data = fs.try_read_file(abspath) |
| 55 | + if data == None: |
| 56 | + # Skip files that are not UTF-8 encoded. |
| 57 | + continue |
| 58 | + |
| 59 | + line_index = lines.LineIndex(data) |
| 60 | + for match in re_obj.finditer(data): |
| 61 | + start_line_col = line_index.line_col(match.start(0)) |
| 62 | + end_line_col = line_index.line_col(match.end(0)) |
| 63 | + start_location = tarif.Location( |
| 64 | + line = start_line_col.line + 1, |
| 65 | + column = start_line_col.col + 1, |
| 66 | + ) |
| 67 | + end_location = tarif.Location( |
| 68 | + line = end_line_col.line + 1, |
| 69 | + column = end_line_col.col + 1, |
| 70 | + ) |
| 71 | + region = tarif.LocationRegion( |
| 72 | + start = start_location, |
| 73 | + end = end_location, |
| 74 | + ) |
| 75 | + result = tarif.Result( |
| 76 | + level = tarif.LEVEL_WARNING, |
| 77 | + message = "{desc}: `{content}'".format(desc = batch_description, content = match.group(0)), |
| 78 | + path = file, |
| 79 | + rule_id = "found", |
| 80 | + location = start_location, |
| 81 | + regions = [region], |
| 82 | + ) |
| 83 | + results.append(result) |
| 84 | + res = tarif.Tarif(results = results) |
| 85 | + ctx.add_tarif(json.encode(res)) |
0 commit comments