@aurelienbbn/agentlint
Version:
Stateless, deterministic CLI that bridges traditional linters and AI-assisted code review
1 lines • 8.08 kB
Source Map (JSON)
{"version":3,"file":"node-yh9mLvnE.mjs","names":["#inner","#children","#parent"],"sources":["../src/domain/flag.ts","../src/domain/node.ts"],"sourcesContent":["/**\n * Flag types — what rules produce when they detect patterns.\n *\n * {@link FlagOptions} is the rule-author API (passed to `context.flag()`).\n * {@link FlagRecord} is the enriched internal record used by the reporter.\n *\n * @module\n * @since 0.1.0\n */\n\nimport { Schema } from \"effect\";\nimport type { AgentReviewNode } from \"./node.js\";\n\n/**\n * Options passed to `context.flag()` by rule visitors.\n *\n * @since 0.1.0\n * @category models\n */\nexport interface FlagOptions {\n /** The AST node that triggered the match. */\n readonly node: AgentReviewNode;\n /** Short one-liner displayed next to file:line in output. */\n readonly message: string;\n /**\n * Override `meta.instruction` for this specific match.\n * Appears inline in per-match notes.\n */\n readonly instruction?: string | undefined;\n /** Hint toward the fix. Not a command - just a nudge. */\n readonly suggest?: string | undefined;\n}\n\n/**\n * Enriched flag record after processing — ready for the reporter.\n *\n * Uses `Schema.Class` for structural equality AND runtime validation\n * on construction — invalid fields throw a clear `ParseError`.\n *\n * @since 0.1.0\n * @category models\n */\nexport class FlagRecord extends Schema.Class<FlagRecord>(\"FlagRecord\")({\n ruleName: Schema.String,\n filename: Schema.String,\n /** 1-based line number. */\n line: Schema.Number,\n /** 1-based column number. */\n col: Schema.Number,\n message: Schema.String,\n sourceSnippet: Schema.String,\n /** 7-char hex hash for stable match identification. */\n hash: Schema.String,\n instruction: Schema.UndefinedOr(Schema.String),\n suggest: Schema.UndefinedOr(Schema.String),\n}) {}\n","/**\n * Lazy wrapper around tree-sitter's `Node`.\n *\n * Provides a stable public API that keeps the tree-sitter dependency\n * out of the consumer-facing surface. Children and parent are wrapped\n * on first access — nodes that are never inspected cost nothing.\n *\n * @module\n * @since 0.1.0\n */\n\nimport { Schema } from \"effect\";\nimport type { Node as TSNode } from \"web-tree-sitter\";\n\n/**\n * 0-indexed position in source text.\n *\n * Defined as a `Schema.Struct` so positions can be decoded and\n * validated from external sources if needed.\n *\n * @since 0.1.0\n * @category models\n */\nexport const Position = Schema.Struct({\n row: Schema.Number,\n column: Schema.Number,\n});\n\n/** @since 0.1.0 */\nexport type Position = Schema.Schema.Type<typeof Position>;\n\n/**\n * Read-only view of a syntax tree node.\n *\n * One universal type — no per-kind subtypes. Rules narrow via\n * `node.type` string checks and field accessors.\n *\n * @since 0.1.0\n * @category models\n */\nexport interface AgentReviewNode {\n /** tree-sitter grammar node type (e.g. `\"function_declaration\"`, `\"comment\"`) */\n readonly type: string;\n /** Full source text covered by this node. */\n readonly text: string;\n /** 0-indexed start position. */\n readonly startPosition: Position;\n /** 0-indexed end position. */\n readonly endPosition: Position;\n /** Whether this is a named node in the grammar. */\n readonly isNamed: boolean;\n /** Direct child nodes (lazily wrapped). */\n readonly children: ReadonlyArray<AgentReviewNode>;\n /** Parent node, or null for the root. */\n readonly parent: AgentReviewNode | null;\n /** Number of direct children. */\n readonly childCount: number;\n\n /** Get a child by its grammar field name (e.g. `\"name\"`, `\"body\"`). */\n childByFieldName(name: string): AgentReviewNode | null;\n /** All direct children matching the given node type. */\n childrenByType(type: string): ReadonlyArray<AgentReviewNode>;\n /** Recursively collect all descendants matching the given node type. */\n descendantsOfType(type: string): ReadonlyArray<AgentReviewNode>;\n}\n\n/**\n * Private implementation of {@link AgentReviewNode}.\n *\n * Wraps a tree-sitter `Node` and lazily creates child/parent wrappers\n * on first access. Nodes that are never traversed incur zero allocation.\n *\n * @since 0.1.0\n * @category internals\n */\nclass AgentReviewNodeImpl implements AgentReviewNode {\n readonly #inner: TSNode;\n #children: ReadonlyArray<AgentReviewNode> | undefined;\n #parent: AgentReviewNode | null | undefined;\n\n constructor(inner: TSNode) {\n this.#inner = inner;\n }\n\n get type(): string {\n return this.#inner.type;\n }\n\n get text(): string {\n return this.#inner.text;\n }\n\n get startPosition(): Position {\n return this.#inner.startPosition;\n }\n\n get endPosition(): Position {\n return this.#inner.endPosition;\n }\n\n get isNamed(): boolean {\n return this.#inner.isNamed;\n }\n\n get childCount(): number {\n return this.#inner.childCount;\n }\n\n get children(): ReadonlyArray<AgentReviewNode> {\n if (this.#children === undefined) {\n const result: AgentReviewNode[] = [];\n for (const c of this.#inner.children) {\n if (c !== null) result.push(new AgentReviewNodeImpl(c));\n }\n this.#children = result;\n }\n return this.#children;\n }\n\n get parent(): AgentReviewNode | null {\n if (this.#parent === undefined) {\n const p = this.#inner.parent;\n this.#parent = p ? new AgentReviewNodeImpl(p) : null;\n }\n return this.#parent;\n }\n\n childByFieldName(name: string): AgentReviewNode | null {\n const child = this.#inner.childForFieldName(name);\n return child ? new AgentReviewNodeImpl(child) : null;\n }\n\n childrenByType(type: string): ReadonlyArray<AgentReviewNode> {\n const result: AgentReviewNode[] = [];\n for (const c of this.#inner.children) {\n if (c !== null && c.type === type) result.push(new AgentReviewNodeImpl(c));\n }\n return result;\n }\n\n descendantsOfType(type: string): ReadonlyArray<AgentReviewNode> {\n const result: AgentReviewNode[] = [];\n for (const c of this.#inner.descendantsOfType(type)) {\n if (c !== null) result.push(new AgentReviewNodeImpl(c));\n }\n return result;\n }\n}\n\n/**\n * Wrap a raw tree-sitter node in the public {@link AgentReviewNode} interface.\n *\n * This is the only bridge between the internal tree-sitter dependency\n * and the consumer-facing API. All child/parent nodes are lazily wrapped\n * on access.\n *\n * @since 0.1.0\n * @category constructors\n */\nexport function wrapNode(inner: TSNode): AgentReviewNode {\n return new AgentReviewNodeImpl(inner);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0CA,IAAa,aAAb,cAAgC,OAAO,MAAkB,aAAa,CAAC;CACrE,UAAU,OAAO;CACjB,UAAU,OAAO;CAEjB,MAAM,OAAO;CAEb,KAAK,OAAO;CACZ,SAAS,OAAO;CAChB,eAAe,OAAO;CAEtB,MAAM,OAAO;CACb,aAAa,OAAO,YAAY,OAAO,OAAO;CAC9C,SAAS,OAAO,YAAY,OAAO,OAAO;CAC3C,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;AChCH,MAAa,WAAW,OAAO,OAAO;CACpC,KAAK,OAAO;CACZ,QAAQ,OAAO;CAChB,CAAC;;;;;;;;;;AAiDF,IAAM,sBAAN,MAAM,oBAA+C;CACnD;CACA;CACA;CAEA,YAAY,OAAe;AACzB,QAAA,QAAc;;CAGhB,IAAI,OAAe;AACjB,SAAO,MAAA,MAAY;;CAGrB,IAAI,OAAe;AACjB,SAAO,MAAA,MAAY;;CAGrB,IAAI,gBAA0B;AAC5B,SAAO,MAAA,MAAY;;CAGrB,IAAI,cAAwB;AAC1B,SAAO,MAAA,MAAY;;CAGrB,IAAI,UAAmB;AACrB,SAAO,MAAA,MAAY;;CAGrB,IAAI,aAAqB;AACvB,SAAO,MAAA,MAAY;;CAGrB,IAAI,WAA2C;AAC7C,MAAI,MAAA,aAAmB,KAAA,GAAW;GAChC,MAAM,SAA4B,EAAE;AACpC,QAAK,MAAM,KAAK,MAAA,MAAY,SAC1B,KAAI,MAAM,KAAM,QAAO,KAAK,IAAI,oBAAoB,EAAE,CAAC;AAEzD,SAAA,WAAiB;;AAEnB,SAAO,MAAA;;CAGT,IAAI,SAAiC;AACnC,MAAI,MAAA,WAAiB,KAAA,GAAW;GAC9B,MAAM,IAAI,MAAA,MAAY;AACtB,SAAA,SAAe,IAAI,IAAI,oBAAoB,EAAE,GAAG;;AAElD,SAAO,MAAA;;CAGT,iBAAiB,MAAsC;EACrD,MAAM,QAAQ,MAAA,MAAY,kBAAkB,KAAK;AACjD,SAAO,QAAQ,IAAI,oBAAoB,MAAM,GAAG;;CAGlD,eAAe,MAA8C;EAC3D,MAAM,SAA4B,EAAE;AACpC,OAAK,MAAM,KAAK,MAAA,MAAY,SAC1B,KAAI,MAAM,QAAQ,EAAE,SAAS,KAAM,QAAO,KAAK,IAAI,oBAAoB,EAAE,CAAC;AAE5E,SAAO;;CAGT,kBAAkB,MAA8C;EAC9D,MAAM,SAA4B,EAAE;AACpC,OAAK,MAAM,KAAK,MAAA,MAAY,kBAAkB,KAAK,CACjD,KAAI,MAAM,KAAM,QAAO,KAAK,IAAI,oBAAoB,EAAE,CAAC;AAEzD,SAAO;;;;;;;;;;;;;AAcX,SAAgB,SAAS,OAAgC;AACvD,QAAO,IAAI,oBAAoB,MAAM"}