tools/core/validators/declaration.validator.ts

tools/core/validators/declaration.validator.ts is a file in Coordination Surface. 122 lines of code and 36 definitions.

import { fieldOf } from "../readers/json.reader.ts";
import { lifetime } from "../../../config/surface.config.ts";

const DECLARE = "function ";

const OPEN = "(";

const BODY_OPEN = "{";

const BODY_CLOSE = "}";

interface AxisConsumer {
    readonly name: string;
    readonly line: number;
    readonly asserted: string;
    readonly read: readonly string[];
}

const axisNames = function axisNames(): string[] {
    return Object.keys(lifetime.values);
};

const axisValues = function axisValues(axis: string): readonly string[] {
    const values = fieldOf(lifetime.values, axis);
    return Array.isArray(values) ? values.filter((value): value is string => typeof value === "string") : [];
};

const lowered = function lowered(text: string): string {
    let out = "";
    for (const character of text) {
        const code = character.codePointAt(0) ?? 0;
        out += code >= 65 && code <= 90 ? String.fromCharCode(code + 32) : character;
    }
    return out;
};

const STEM = 5;

const assertedAxis = function assertedAxis(name: string): string | null {
    const held = lowered(name);

    for (const axis of axisNames()) {
        const stem = lowered(axis).slice(0, STEM);
        if (stem.length > 0 && held.includes(stem)) {
            return axis;
        }

        for (const value of axisValues(axis)) {
            const word = lowered(value).split("-").join("");
            if (word.length > 0 && held.includes(word)) {
                return axis;
            }
        }
    }

    return null;
};

const QUOTES = new Set(['"', "'", "`"]);

const nextOpen = function nextOpen(open: string, character: string): string {
    if (!QUOTES.has(character)) {
        return open;
    }
    if (open.length === 0) {
        return character;
    }
    return open === character ? "" : open;
};

const quotedAt = function quotedAt(line: string, index: number): boolean {
    let open = "";
    for (let cursor = 0; cursor < index; cursor += 1) {
        open = nextOpen(open, line.charAt(cursor));
    }
    return open.length > 0;
};

const declaredNameAt = function declaredNameAt(line: string): string | null {
    const at = line.indexOf(DECLARE);
    if (at === -1) {
        return null;
    }
    if (quotedAt(line, at)) {
        return null;
    }

    const rest = line.slice(at + DECLARE.length);
    const open = rest.indexOf(OPEN);
    if (open <= 0) {
        return null;
    }

    const name = rest.slice(0, open).trim();
    return name.length === 0 || name.includes(" ") ? null : name;
};

const bodyOf = function bodyOf(lines: readonly string[], from: number): string {
    let depth = 0;
    let seen = false;
    let out = "";

    for (let index = from; index < lines.length; index += 1) {
        const line = lines[index] ?? "";
        out += `${line}\n`;

        for (const character of line) {
            if (character === BODY_OPEN) {
                depth += 1;
                seen = true;
            }
            if (character === BODY_CLOSE) {
                depth -= 1;
            }
        }

        if (seen && depth <= 0) {
            return out;
        }
    }

    return out;
};

const consumerAt = function consumerAt(
    lines: readonly string[],
    index: number,
    reaches: readonly string[],
): AxisConsumer[] {
    const name = declaredNameAt(lines[index] ?? "");
    const asserted = name === null ? null : assertedAxis(name);
    if (name === null || asserted === null) {
        return [];
    }

    const body = bodyOf(lines, index);
    if (!reaches.some((token) => body.includes(token))) {
        return [];
    }

    return [{ asserted, line: index + 1, name, read: axisNames().filter((axis) => body.includes(`.${axis}`)) }];
};

export const axisConsumers = function axisConsumers(source: string, reaches: readonly string[]): AxisConsumer[] {
    const lines = source.split("\n");
    return [...lines.keys()].flatMap((index) => consumerAt(lines, index, reaches));
};

export const silentOnItsOwnAxis = function silentOnItsOwnAxis(consumer: AxisConsumer): boolean {
    return !consumer.read.includes(consumer.asserted);
};