# shared/resolvers/scope.resolver.ts

> 47 lines of code and 11 definitions.

Tree: Governance tree
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/governance#file-governance-shared-resolvers-scope-resolver-ts
Source text: https://banes-lab.com/source/governance/shared/resolvers/scope.resolver.ts.txt

Listed in [shared/resolvers](https://banes-lab.com/api/source/governance/shared/resolvers.md), after [shared/resolvers/location.resolver.ts](https://banes-lab.com/source/governance/shared/resolvers/location.resolver.ts.md).

## Definitions

- `variableInit` (lexical_declaration, line 46, exported)
- `isWriteNode` (lexical_declaration, line 4)
- `declaratorInit` (lexical_declaration, line 28)
- `lastWrittenValue` (lexical_declaration, line 38)
- `asWriteNode` (lexical_declaration, line 8, exported)
- `findVariable` (lexical_declaration, line 12, exported)
- `scope` (lexical_declaration, line 17, exported)
- `declarator` (lexical_declaration, line 30)
- `written` (lexical_declaration, line 39)
- `value` (lexical_declaration, line 40)
- `variable` (lexical_declaration, line 51, exported)

## Used by

- [rules/eslint/no-raw-file-write.eslint.rule.ts](https://banes-lab.com/source/governance/rules/eslint/no-raw-file-write.eslint.rule.ts.md)

## Source

```typescript
import type { Rule, Scope } from "eslint";
import type { WriteNode } from "../../types/generator.types.ts";

const isWriteNode = function isWriteNode(value: unknown): value is WriteNode {
    return value !== null && typeof value === "object" && "type" in value;
};

export const asWriteNode = function asWriteNode(value: unknown): WriteNode | null {
    return isWriteNode(value) ? value : null;
};

export const findVariable = function findVariable(
    context: Rule.RuleContext,
    node: Rule.Node,
    name: string,
): Scope.Variable | null {
    let scope: Scope.Scope | null = context.sourceCode.getScope(node);
    while (scope !== null) {
        const variable = scope.variables.find((entry) => entry.name === name);
        if (variable) {
            return variable;
        }
        scope = scope.upper;
    }
    return null;
};

const declaratorInit = function declaratorInit(variable: Scope.Variable): WriteNode | null {
    for (const def of variable.defs) {
        const declarator = asWriteNode(def.node);
        if (declarator?.type === "VariableDeclarator") {
            return declarator.init ?? null;
        }
    }
    return null;
};

const lastWrittenValue = function lastWrittenValue(variable: Scope.Variable): WriteNode | null {
    const written = variable.references.flatMap((reference) => {
        const value = asWriteNode(reference.writeExpr);
        return value === null ? [] : [value];
    });
    return written.at(-1) ?? null;
};

export const variableInit = function variableInit(
    context: Rule.RuleContext,
    node: Rule.Node,
    name: string,
): WriteNode | null {
    const variable = findVariable(context, node, name);
    return variable === null ? null : (lastWrittenValue(variable) ?? declaratorInit(variable));
};
```
