@ton-ai-core/vibecode-linter
Version:
Advanced TypeScript linter with Git integration, dependency analysis, and comprehensive error reporting
136 lines • 4.65 kB
JavaScript
// CHANGE: Extract pure priority and grouping utilities using Effect pipe
// WHY: FCIS — move deterministic computations into CORE; demonstrate pipe usage
// QUOTE(ТЗ): "CORE: Исключительно чистые функции, неизменяемые данные"
// QUOTE(ТЗ): "pipe() - композиция функций для функциональной парадигмы"
// SOURCE: https://effect.website/docs/guides/essentials/pipeline
// PURITY: CORE
// INVARIANT: No side effects; functions are total and deterministic
// COMPLEXITY: O(n) where n = |messages| for grouping, O(1) for level/name
import { pipe } from "effect";
/**
* Get rule id from lint message in a pure, cross-source way.
*
* @pure true
* @invariant m.source ∈ {typescript, eslint, biome} (guaranteed by type system)
* @complexity O(1)
*/
export function ruleIdOfCore(m) {
// CHANGE: Simplify by leveraging type system guarantees
// WHY: LintMessageWithFile union type ensures source is always one of three values
// INVARIANT: ∀ m: LintMessageWithFile. m.source ∈ {typescript, eslint, biome}
if (m.source === "typescript")
return m.code;
// Type system guarantees m.source is "eslint" or "biome" here
const { ruleId } = m;
return typeof ruleId === "string" && ruleId.length > 0 ? ruleId : "unknown";
}
/**
* Compute numeric priority level for a message using provided mapping.
*
* @pure true
* @invariant result ∈ [0, 5]
* @complexity O(1) - Map lookup
* @default 2 (error) if not mapped
*/
export function getPriorityLevel(m, ruleLevelMap) {
if (ruleLevelMap === null)
return 2;
const ruleId = ruleIdOfCore(m);
const explicit = ruleLevelMap.explicitRules.get(ruleId);
if (explicit !== undefined)
return explicit.level;
const { allLevel } = ruleLevelMap;
if (allLevel !== undefined)
return allLevel.level;
return 2;
}
/**
* Compute human-readable priority name for a message using provided mapping.
*
* @pure true
* @invariant result.length > 0
* @complexity O(1) - Map lookup
* @default "Critical Compiler Errors" if not mapped
*/
export function getPriorityName(m, ruleLevelMap) {
if (ruleLevelMap === null)
return "Critical Compiler Errors";
const ruleId = ruleIdOfCore(m);
const explicit = ruleLevelMap.explicitRules.get(ruleId);
if (explicit !== undefined)
return explicit.name;
const { allLevel } = ruleLevelMap;
if (allLevel !== undefined)
return allLevel.name;
return "Critical Compiler Errors";
}
/**
* Group messages by numeric level using pipe for composability.
*
* @pure true
* @invariant result.size <= messages.length
* @complexity O(n) где n = messages.length
*
* @example
* ```ts
* import { pipe } from "effect";
*
* const grouped = groupByLevel(messages, config);
* // Uses pipe internally for functional composition
* ```
*/
export function groupByLevel(messages, ruleLevelMap) {
// CHANGE: Use functional reduce instead of imperative for loop
// WHY: More composable and mathematically provable
// FORMAT THEOREM: ∀ messages: groupByLevel(messages) = reduce(messages, groupByKey)
// PURITY: CORE
// INVARIANT: No mutations of input, deterministic output
// COMPLEXITY: O(n)
return messages.reduce((byLevel, m) => {
const level = getPriorityLevel(m, ruleLevelMap);
const arr = byLevel.get(level);
if (arr === undefined) {
byLevel.set(level, [m]);
}
else {
arr.push(m);
}
return byLevel;
}, new Map());
}
/**
* Group top messages (first 15) by section name using pipe.
*
* @pure true
* @invariant result.size <= 15
* @complexity O(min(n, 15)) где n = messages.length
*
* @example
* ```ts
* // Functional composition with pipe
* const sections = pipe(
* messages,
* msgs => msgs.slice(0, 15),
* msgs => groupBySections(msgs, config)
* );
* ```
*/
export const groupBySections = (messages, ruleLevelMap) => pipe(messages,
// CHANGE: Use pipe for functional composition
// WHY: Demonstrates pipe usage for data transformations
// FORMAT THEOREM: pipe(data, f, g) = g(f(data))
// PURITY: CORE
// INVARIANT: ∀ messages: result.size <= 15
// COMPLEXITY: O(min(n, 15))
(msgs) => msgs.slice(0, 15), (topMsgs) => topMsgs.reduce((sections, m) => {
const section = getPriorityName(m, ruleLevelMap);
const arr = sections.get(section);
if (arr === undefined) {
sections.set(section, [m]);
}
else {
arr.push(m);
}
return sections;
}, new Map()));
//# sourceMappingURL=priority.js.map