# tools/core/predicates/source.predicate.ts

> 112 lines of code and 31 definitions.

Tree: Coordination tree
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-tools-core-predicates-source-predicate-ts
Source text: https://banes-lab.com/assets/sources/source.0d9e59770a5d54702ee85af30c0bbde8a3d1a6123ec3f9286cd0694a03720211.generated.txt

## Definitions

- `skipped` (lexical_declaration, line 41)
- `containsInCode` (lexical_declaration, line 121, exported)
- `isIdentifierChar` (lexical_declaration, line 101)
- `declaresProperty` (lexical_declaration, line 137, exported)
- `scanCode` (lexical_declaration, line 85)
- `commentStep` (lexical_declaration, line 45)
- `quoteStep` (lexical_declaration, line 55)
- `reachesRegexLiteral` (lexical_declaration, line 125, exported)
- `codeStep` (lexical_declaration, line 68)
- `memberCallOpensHere` (lexical_declaration, line 105)
- `memberCallFollows` (lexical_declaration, line 113)
- `filesystemImports` (lexical_declaration, line 11, exported)
- `stepOf` (lexical_declaration, line 79)
- `QUOTES` (lexical_declaration, line 3)
- `ESCAPE` (lexical_declaration, line 5)
- `DECLARATION_TAILS` (lexical_declaration, line 7)
- `FILESYSTEM_IMPORT_TAIL` (lexical_declaration, line 9)
- `Mode` (type_alias_declaration, line 18)
- `Scan` (interface_declaration, line 20)
- `Step` (interface_declaration, line 26)
- `CODE` (lexical_declaration, line 32)
- `OPENERS` (lexical_declaration, line 34)
- `BLOCK_CLOSE` (lexical_declaration, line 39)
- `opener` (lexical_declaration, line 69)
- `char` (lexical_declaration, line 80)
- `pair` (lexical_declaration, line 81)
- `scan` (lexical_declaration, line 86)
- `index` (lexical_declaration, line 87)
- `step` (lexical_declaration, line 90)
- `cursor` (lexical_declaration, line 114)
- `next` (lexical_declaration, line 127, exported)

## Uses

- [tools/core/predicates/token.predicate.ts](https://banes-lab.com/source/coordination/tools/core/predicates/token.predicate.ts.md)

## Used by

- [tools/core/validators/governance.validator.ts](https://banes-lab.com/source/coordination/tools/core/validators/governance.validator.ts.md)
- [tools/core/validators/writer.validator.ts](https://banes-lab.com/source/coordination/tools/core/validators/writer.validator.ts.md)
- [tools/rules/governance.rule.ts](https://banes-lab.com/source/coordination/tools/rules/governance.rule.ts.md)

## Source

```typescript
import { isWordCharacter } from "./token.predicate.ts";

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

const ESCAPE = "\\";

const DECLARATION_TAILS = [":", "(", ",", " }", "\n"];

const FILESYSTEM_IMPORT_TAIL = `"node:fs";`;

export const filesystemImports = function filesystemImports(source: string): string[] {
    return source
        .split("\n")
        .map((line) => line.trim())
        .filter((line) => line.startsWith("import ") && line.endsWith(FILESYSTEM_IMPORT_TAIL));
};

type Mode = "block" | "code" | "line" | "quote";

interface Scan {
    readonly mode: Mode;
    readonly quote: string;
    readonly escaped: boolean;
}

interface Step {
    readonly next: Scan;
    readonly width: number;
    readonly code: boolean;
}

const CODE: Scan = { escaped: false, mode: "code", quote: "" };

const OPENERS = new Map<string, Mode>([
    ["//", "line"],
    ["/*", "block"],
]);

const BLOCK_CLOSE = "*/";

const skipped = function skipped(next: Scan, width: number): Step {
    return { code: false, next, width };
};

const commentStep = function commentStep(scan: Scan, pair: string): Step | null {
    if (scan.mode === "line") {
        return skipped(pair.startsWith("\n") ? CODE : scan, 1);
    }
    if (scan.mode === "block") {
        return pair === BLOCK_CLOSE ? skipped(CODE, 2) : skipped(scan, 1);
    }
    return null;
};

const quoteStep = function quoteStep(scan: Scan, char: string): Step | null {
    if (scan.escaped) {
        return skipped({ ...scan, escaped: false }, 1);
    }
    if (char === ESCAPE) {
        return skipped({ ...scan, escaped: true }, 1);
    }
    if (scan.mode === "quote") {
        return skipped(char === scan.quote ? CODE : scan, 1);
    }
    return null;
};

const codeStep = function codeStep(char: string, pair: string): Step {
    const opener = OPENERS.get(pair);
    if (opener !== undefined) {
        return skipped({ escaped: false, mode: opener, quote: "" }, 2);
    }
    if (QUOTES.has(char)) {
        return skipped({ escaped: false, mode: "quote", quote: char }, 1);
    }
    return { code: true, next: CODE, width: 1 };
};

const stepOf = function stepOf(scan: Scan, source: string, index: number): Step {
    const char = source.charAt(index);
    const pair = source.slice(index, index + 2);
    return commentStep(scan, pair) ?? quoteStep(scan, char) ?? codeStep(char, pair);
};

const scanCode = function scanCode(source: string, at: (index: number, char: string) => boolean): boolean {
    let scan = CODE;
    let index = 0;

    while (index < source.length) {
        const step = stepOf(scan, source, index);
        if (step.code && at(index, source.charAt(index))) {
            return true;
        }
        scan = step.next;
        index += step.width;
    }

    return false;
};

const isIdentifierChar = function isIdentifierChar(char: string): boolean {
    return isWordCharacter(char) || char === "$";
};

const memberCallOpensHere = function memberCallOpensHere(source: string, index: number): boolean {
    let cursor = index - 1;
    while (cursor >= 0 && isIdentifierChar(source.charAt(cursor))) {
        cursor -= 1;
    }
    return cursor !== index - 1 && source.charAt(cursor) === ".";
};

const memberCallFollows = function memberCallFollows(source: string, index: number): boolean {
    let cursor = index + 1;
    while (cursor < source.length && isIdentifierChar(source.charAt(cursor))) {
        cursor += 1;
    }
    return cursor !== index + 1 && source.charAt(cursor) === "(";
};

export const containsInCode = function containsInCode(source: string, needle: string): boolean {
    return scanCode(source, (index) => source.startsWith(needle, index));
};

export const reachesRegexLiteral = function reachesRegexLiteral(source: string): boolean {
    return scanCode(source, (index, char) => {
        const next = source.charAt(index + 1);

        if (char === "(" && next === "/" && source.charAt(index + 2) !== "/") {
            return memberCallOpensHere(source, index);
        }

        return char === "/" && next === "." && memberCallFollows(source, index + 1);
    });
};

export const declaresProperty = function declaresProperty(source: string, name: string): boolean {
    return DECLARATION_TAILS.some((tail) => containsInCode(source, `${name}${tail}`));
};
```
