# core/producers/tool.staticcheck.producer.ts

> 64 lines of code and 13 definitions.

Tree: GovLab Quality
Language: typescript
Layer: application
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-producers-tool-staticcheck-producer-ts
Source text: https://banes-lab.com/source/quality/core/producers/tool.staticcheck.producer.ts.txt

Listed in [core/producers](https://banes-lab.com/api/source/quality/core/producers.md), after [core/producers/tool.sqlfluff.producer.ts](https://banes-lab.com/source/quality/core/producers/tool.sqlfluff.producer.ts.md) and before [core/producers/tool.yamllint.producer.ts](https://banes-lab.com/source/quality/core/producers/tool.yamllint.producer.ts.md).

## Definitions

- `isUpperAscii` (lexical_declaration, line 17)
- `prefixOf` (lexical_declaration, line 21)
- `ruleOf` (lexical_declaration, line 32)
- `produce` (lexical_declaration, line 55)
- `TOOL` (lexical_declaration, line 7)
- `DOCS` (lexical_declaration, line 8)
- `FAMILY` (lexical_declaration, line 9)
- `text` (lexical_declaration, line 33)
- `space` (lexical_declaration, line 34)
- `code` (lexical_declaration, line 35)
- `prefix` (lexical_declaration, line 39)
- `version` (lexical_declaration, line 56)
- `rules` (lexical_declaration, line 57)

## Contained in

- [core/producers](https://banes-lab.com/anatomy/quality/folder-quality-core-producers.md)

## Uses

- [core/aggregators/catalog.aggregator.ts](https://banes-lab.com/source/quality/core/aggregators/catalog.aggregator.ts.md)

## Linked from

- [core/aggregators](https://banes-lab.com/anatomy/quality/folder-quality-core-aggregators.md)
- [core/producers](https://banes-lab.com/anatomy/quality/folder-quality-core-producers.md)

## Source

```typescript
import type { CatalogProduct, CatalogRule } from "#types/catalog.types";
import { commandOutput, commandVersion } from "#core/adapters/invocation.adapter";
import { byRuleId } from "#core/comparators/rule.comparator";
import { defineProducer } from "#core/registries/producer.registry";
import { tallyBy } from "#core/aggregators/catalog.aggregator";

const TOOL = "staticcheck";
const DOCS = "https://staticcheck.dev/docs/checks/#";
const FAMILY: ReadonlyMap<string, string> = new Map([
    ["QF", "quickfix"],
    ["S", "simplifications"],
    ["SA", "bugs"],
    ["ST", "style"],
    ["U", "unused"],
]);

const isUpperAscii = function isUpperAscii(ch: string | undefined): boolean {
    return typeof ch === "string" && ch >= "A" && ch <= "Z";
};

const prefixOf = function prefixOf(code: string): string {
    let prefix = "";
    for (const ch of code) {
        if (!isUpperAscii(ch)) {
            break;
        }
        prefix += ch;
    }
    return prefix;
};

const ruleOf = function ruleOf(line: string, version: string): CatalogRule[] {
    const text = line.trim();
    const space = text.indexOf(" ");
    const code = space === -1 ? "" : text.slice(0, space);
    if (!isUpperAscii(code[0])) {
        return [];
    }
    const prefix = prefixOf(code);
    return [
        {
            canonical: null,
            category: FAMILY.get(prefix) ?? prefix,
            description: text.slice(space + 1).trim(),
            ecosystem: "go",
            name: code,
            ruleId: code,
            tool: TOOL,
            toolVersion: version,
            url: `${DOCS}${code}`,
        },
    ];
};

const produce = async function produce(): Promise<CatalogProduct[]> {
    const version = commandVersion(TOOL, ["-version"]);
    const rules = commandOutput(TOOL, ["-list-checks"])
        .split("\n")
        .flatMap((line) => ruleOf(line, version))
        .toSorted(byRuleId);
    return [
        {
            rules,
            source: TOOL,
            summary: { byCategory: tallyBy(rules, "category"), tool: TOOL, toolVersion: version, total: rules.length },
        },
    ];
};

defineProducer({ name: TOOL, produce, refresh: "manual" });
```
