@mka-rainmaker/ama 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +149 -0
- package/dist/analyzers/baseline/analyzer.d.ts +47 -0
- package/dist/analyzers/baseline/analyzer.d.ts.map +1 -0
- package/dist/analyzers/baseline/analyzer.js +84 -0
- package/dist/analyzers/baseline/analyzer.js.map +1 -0
- package/dist/analyzers/baseline/c.d.ts +12 -0
- package/dist/analyzers/baseline/c.d.ts.map +1 -0
- package/dist/analyzers/baseline/c.js +56 -0
- package/dist/analyzers/baseline/c.js.map +1 -0
- package/dist/analyzers/baseline/config.d.ts +21 -0
- package/dist/analyzers/baseline/config.d.ts.map +1 -0
- package/dist/analyzers/baseline/config.js +32 -0
- package/dist/analyzers/baseline/config.js.map +1 -0
- package/dist/analyzers/baseline/csharp.d.ts +9 -0
- package/dist/analyzers/baseline/csharp.d.ts.map +1 -0
- package/dist/analyzers/baseline/csharp.js +107 -0
- package/dist/analyzers/baseline/csharp.js.map +1 -0
- package/dist/analyzers/baseline/go.d.ts +11 -0
- package/dist/analyzers/baseline/go.d.ts.map +1 -0
- package/dist/analyzers/baseline/go.js +66 -0
- package/dist/analyzers/baseline/go.js.map +1 -0
- package/dist/analyzers/baseline/java.d.ts +9 -0
- package/dist/analyzers/baseline/java.d.ts.map +1 -0
- package/dist/analyzers/baseline/java.js +50 -0
- package/dist/analyzers/baseline/java.js.map +1 -0
- package/dist/analyzers/baseline/javascript.d.ts +10 -0
- package/dist/analyzers/baseline/javascript.d.ts.map +1 -0
- package/dist/analyzers/baseline/javascript.js +55 -0
- package/dist/analyzers/baseline/javascript.js.map +1 -0
- package/dist/analyzers/baseline/kotlin.d.ts +11 -0
- package/dist/analyzers/baseline/kotlin.d.ts.map +1 -0
- package/dist/analyzers/baseline/kotlin.js +67 -0
- package/dist/analyzers/baseline/kotlin.js.map +1 -0
- package/dist/analyzers/baseline/paths.d.ts +6 -0
- package/dist/analyzers/baseline/paths.d.ts.map +1 -0
- package/dist/analyzers/baseline/paths.js +17 -0
- package/dist/analyzers/baseline/paths.js.map +1 -0
- package/dist/analyzers/baseline/php.d.ts +11 -0
- package/dist/analyzers/baseline/php.d.ts.map +1 -0
- package/dist/analyzers/baseline/php.js +76 -0
- package/dist/analyzers/baseline/php.js.map +1 -0
- package/dist/analyzers/baseline/python.d.ts +10 -0
- package/dist/analyzers/baseline/python.d.ts.map +1 -0
- package/dist/analyzers/baseline/python.js +63 -0
- package/dist/analyzers/baseline/python.js.map +1 -0
- package/dist/analyzers/baseline/rust.d.ts +10 -0
- package/dist/analyzers/baseline/rust.d.ts.map +1 -0
- package/dist/analyzers/baseline/rust.js +45 -0
- package/dist/analyzers/baseline/rust.js.map +1 -0
- package/dist/analyzers/baseline/swift.d.ts +11 -0
- package/dist/analyzers/baseline/swift.d.ts.map +1 -0
- package/dist/analyzers/baseline/swift.js +19 -0
- package/dist/analyzers/baseline/swift.js.map +1 -0
- package/dist/analyzers/baseline/treesitter.d.ts +11 -0
- package/dist/analyzers/baseline/treesitter.d.ts.map +1 -0
- package/dist/analyzers/baseline/treesitter.js +87 -0
- package/dist/analyzers/baseline/treesitter.js.map +1 -0
- package/dist/analyzers/baseline/walk.d.ts +26 -0
- package/dist/analyzers/baseline/walk.d.ts.map +1 -0
- package/dist/analyzers/baseline/walk.js +76 -0
- package/dist/analyzers/baseline/walk.js.map +1 -0
- package/dist/analyzers/registry.d.ts +19 -0
- package/dist/analyzers/registry.d.ts.map +1 -0
- package/dist/analyzers/registry.js +43 -0
- package/dist/analyzers/registry.js.map +1 -0
- package/dist/analyzers/sfc/analyzer.d.ts +17 -0
- package/dist/analyzers/sfc/analyzer.d.ts.map +1 -0
- package/dist/analyzers/sfc/analyzer.js +141 -0
- package/dist/analyzers/sfc/analyzer.js.map +1 -0
- package/dist/analyzers/sidecar/analyzer.d.ts +29 -0
- package/dist/analyzers/sidecar/analyzer.d.ts.map +1 -0
- package/dist/analyzers/sidecar/analyzer.js +114 -0
- package/dist/analyzers/sidecar/analyzer.js.map +1 -0
- package/dist/analyzers/sidecar/protocol.d.ts +508 -0
- package/dist/analyzers/sidecar/protocol.d.ts.map +1 -0
- package/dist/analyzers/sidecar/protocol.js +102 -0
- package/dist/analyzers/sidecar/protocol.js.map +1 -0
- package/dist/analyzers/types.d.ts +46 -0
- package/dist/analyzers/types.d.ts.map +1 -0
- package/dist/analyzers/types.js +2 -0
- package/dist/analyzers/types.js.map +1 -0
- package/dist/analyzers/typescript/analyzer.d.ts +126 -0
- package/dist/analyzers/typescript/analyzer.d.ts.map +1 -0
- package/dist/analyzers/typescript/analyzer.js +1600 -0
- package/dist/analyzers/typescript/analyzer.js.map +1 -0
- package/dist/cli/commands/cycles.d.ts +6 -0
- package/dist/cli/commands/cycles.d.ts.map +1 -0
- package/dist/cli/commands/cycles.js +27 -0
- package/dist/cli/commands/cycles.js.map +1 -0
- package/dist/cli/commands/files.d.ts +6 -0
- package/dist/cli/commands/files.d.ts.map +1 -0
- package/dist/cli/commands/files.js +33 -0
- package/dist/cli/commands/files.js.map +1 -0
- package/dist/cli/commands/impact.d.ts +18 -0
- package/dist/cli/commands/impact.d.ts.map +1 -0
- package/dist/cli/commands/impact.js +113 -0
- package/dist/cli/commands/impact.js.map +1 -0
- package/dist/cli/commands/lifecycle.d.ts +5 -0
- package/dist/cli/commands/lifecycle.d.ts.map +1 -0
- package/dist/cli/commands/lifecycle.js +83 -0
- package/dist/cli/commands/lifecycle.js.map +1 -0
- package/dist/cli/commands/query.d.ts +31 -0
- package/dist/cli/commands/query.d.ts.map +1 -0
- package/dist/cli/commands/query.js +187 -0
- package/dist/cli/commands/query.js.map +1 -0
- package/dist/cli/commands/search.d.ts +21 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +160 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/commands/status.d.ts +6 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +63 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +6 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +57 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/emit.d.ts +9 -0
- package/dist/cli/emit.d.ts.map +1 -0
- package/dist/cli/emit.js +10 -0
- package/dist/cli/emit.js.map +1 -0
- package/dist/cli/index.d.ts +37 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +128 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/paths.d.ts +7 -0
- package/dist/cli/paths.d.ts.map +1 -0
- package/dist/cli/paths.js +10 -0
- package/dist/cli/paths.js.map +1 -0
- package/dist/cli/query-runner.d.ts +13 -0
- package/dist/cli/query-runner.d.ts.map +1 -0
- package/dist/cli/query-runner.js +33 -0
- package/dist/cli/query-runner.js.map +1 -0
- package/dist/graph/dispatch.d.ts +17 -0
- package/dist/graph/dispatch.d.ts.map +1 -0
- package/dist/graph/dispatch.js +82 -0
- package/dist/graph/dispatch.js.map +1 -0
- package/dist/graph/id.d.ts +19 -0
- package/dist/graph/id.d.ts.map +1 -0
- package/dist/graph/id.js +17 -0
- package/dist/graph/id.js.map +1 -0
- package/dist/graph/index.d.ts +6 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +4 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/types.d.ts +71 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +52 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/indexer/debouncer.d.ts +32 -0
- package/dist/indexer/debouncer.d.ts.map +1 -0
- package/dist/indexer/debouncer.js +81 -0
- package/dist/indexer/debouncer.js.map +1 -0
- package/dist/indexer/ignore.d.ts +55 -0
- package/dist/indexer/ignore.d.ts.map +1 -0
- package/dist/indexer/ignore.js +170 -0
- package/dist/indexer/ignore.js.map +1 -0
- package/dist/indexer/indexer.d.ts +112 -0
- package/dist/indexer/indexer.d.ts.map +1 -0
- package/dist/indexer/indexer.js +392 -0
- package/dist/indexer/indexer.js.map +1 -0
- package/dist/indexer/watcher.d.ts +50 -0
- package/dist/indexer/watcher.d.ts.map +1 -0
- package/dist/indexer/watcher.js +86 -0
- package/dist/indexer/watcher.js.map +1 -0
- package/dist/mcp/build-info.d.ts +16 -0
- package/dist/mcp/build-info.d.ts.map +1 -0
- package/dist/mcp/build-info.js +54 -0
- package/dist/mcp/build-info.js.map +1 -0
- package/dist/mcp/http.d.ts +18 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/http.js +145 -0
- package/dist/mcp/http.js.map +1 -0
- package/dist/mcp/server.d.ts +22 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +401 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/session.d.ts +155 -0
- package/dist/mcp/session.d.ts.map +1 -0
- package/dist/mcp/session.js +319 -0
- package/dist/mcp/session.js.map +1 -0
- package/dist/query/service.d.ts +329 -0
- package/dist/query/service.d.ts.map +1 -0
- package/dist/query/service.js +959 -0
- package/dist/query/service.js.map +1 -0
- package/dist/runtime/entrypoint.d.ts +11 -0
- package/dist/runtime/entrypoint.d.ts.map +1 -0
- package/dist/runtime/entrypoint.js +22 -0
- package/dist/runtime/entrypoint.js.map +1 -0
- package/dist/runtime/quiet-sqlite-warning.d.ts +14 -0
- package/dist/runtime/quiet-sqlite-warning.d.ts.map +1 -0
- package/dist/runtime/quiet-sqlite-warning.js +26 -0
- package/dist/runtime/quiet-sqlite-warning.js.map +1 -0
- package/dist/runtime/wasm-tier.d.ts +2 -0
- package/dist/runtime/wasm-tier.d.ts.map +1 -0
- package/dist/runtime/wasm-tier.js +54 -0
- package/dist/runtime/wasm-tier.js.map +1 -0
- package/dist/store/memory.d.ts +54 -0
- package/dist/store/memory.d.ts.map +1 -0
- package/dist/store/memory.js +210 -0
- package/dist/store/memory.js.map +1 -0
- package/dist/store/sqlite.d.ts +38 -0
- package/dist/store/sqlite.d.ts.map +1 -0
- package/dist/store/sqlite.js +298 -0
- package/dist/store/sqlite.js.map +1 -0
- package/dist/store/types.d.ts +76 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +2 -0
- package/dist/store/types.js.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mykhaylo Katruk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Ama 🐶
|
|
2
|
+
|
|
3
|
+
**Ama** is a local-first **code-intelligence server** that speaks the [Model Context Protocol (MCP)](https://modelcontextprotocol.io). It parses a codebase into a queryable knowledge graph of symbols and their relationships, then hands that graph to AI coding agents — so an agent can answer *"who calls this?"*, *"what breaks if I change this?"*, and *"show me this function and its callers"* in a **single tool call** instead of dozens of file reads.
|
|
4
|
+
|
|
5
|
+
Named after a puppy: small, eager, and a little smarter every day.
|
|
6
|
+
|
|
7
|
+
> Status: **0.1.** Deep TypeScript analysis plus syntactic baseline coverage for 13 more languages, 27 MCP tools, an `ama` CLI, and persistent incremental indexing — all able to index Ama's own source cleanly as the built-in regression test. Deep-tier .NET/Java analyzers (behind the sidecar protocol) are next.
|
|
8
|
+
|
|
9
|
+
## Why Ama
|
|
10
|
+
|
|
11
|
+
Most code-graph tools parse every language the same way: one fast, syntactic pass that sees *shapes* but not *meaning*. Ama takes a different bet — **use each language's real compiler when one exists.**
|
|
12
|
+
|
|
13
|
+
- **Deep tier — language-specific semantic analysis.** TypeScript via the TypeScript Compiler API today; .NET via Roslyn and Java via its native tooling next. This resolves types, overloads, generics, imports/re-exports, interface dispatch, and cross-file symbol binding that a purely syntactic parser cannot.
|
|
14
|
+
- **Baseline tier — universal syntactic analysis for breadth.** Every other language still gets parsed for structure, so the whole repo is navigable from day one.
|
|
15
|
+
|
|
16
|
+
Every answer reports **which tier produced it**, so partial coverage never quietly masquerades as complete.
|
|
17
|
+
|
|
18
|
+
And because it's built for agents:
|
|
19
|
+
|
|
20
|
+
- **100% local.** No external APIs, no API keys, no telemetry. Your code never leaves your machine.
|
|
21
|
+
- **Cheaper and faster.** Fewer tool calls and fewer tokens per question, because one graph query replaces a pile of file reads.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
> Requires **Node.js 24+**.
|
|
26
|
+
|
|
27
|
+
Ama runs as a local MCP server your coding agent launches over stdio. Install it once, then point your agent at `ama mcp`:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g @mka-rainmaker/ama
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
(Or skip the global install and use `npx -y @mka-rainmaker/ama mcp` as the command below.)
|
|
34
|
+
|
|
35
|
+
### Configure your coding agent
|
|
36
|
+
|
|
37
|
+
Every MCP client spawns the same stdio command — `ama mcp` — only the config location differs.
|
|
38
|
+
|
|
39
|
+
**Claude Code** — add it with one command:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
claude mcp add ama -- ama mcp
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
…or add it to a project `.mcp.json`:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{ "mcpServers": { "ama": { "command": "ama", "args": ["mcp"] } } }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Cursor** — `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{ "mcpServers": { "ama": { "command": "ama", "args": ["mcp"] } } }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Windsurf** — `~/.codeium/windsurf/mcp_config.json`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{ "mcpServers": { "ama": { "command": "ama", "args": ["mcp"] } } }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Any other MCP client** — spawn `ama mcp` over stdio. If you didn't install globally, run it via `npx`:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{ "mcpServers": { "ama": { "command": "npx", "args": ["-y", "@mka-rainmaker/ama", "mcp"] } } }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Quick start
|
|
70
|
+
|
|
71
|
+
Once connected, point Ama at a repo and start asking graph questions:
|
|
72
|
+
|
|
73
|
+
1. **`index_repository("/path/to/your/project")`** — builds the graph (run this first).
|
|
74
|
+
2. **`search_symbol`**, **`find_callers`**, **`find_callees`**, **`get_code_snippet`**, **`impact_analysis`**, … — query it.
|
|
75
|
+
|
|
76
|
+
Ama re-indexes changed files automatically while connected. Call `index_status()` to see what's indexed and the per-language coverage + tier.
|
|
77
|
+
|
|
78
|
+
### CLI
|
|
79
|
+
|
|
80
|
+
The same package ships an `ama` CLI mirroring the query surface, for one-shot use and scripting (e.g. `git diff --name-only | ama affected`):
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
ama --help # list commands
|
|
84
|
+
ama mcp # run the MCP server over stdio (what coding agents spawn)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## What's in 0.1
|
|
88
|
+
|
|
89
|
+
- **Deep TypeScript analysis** via the TypeScript Compiler API — types, overloads, generics, imports/re-exports, inheritance, interface dispatch, cross-file binding, and call graphs.
|
|
90
|
+
- **Baseline breadth** for 13 more languages via tree-sitter: C, C++, C#, Go, Java, JavaScript, Kotlin, PHP, Python, Rust, Swift, and Vue/Svelte single-file components.
|
|
91
|
+
- **27 MCP tools** — search, call graph, references, type usage, inheritance/overrides, imports/importers, routes → handlers, code snippets, plus higher-order `explore`, `impact_analysis`, and `search_code` — each tagging the tier that produced it.
|
|
92
|
+
- **Persistent indexing** (SQLite + full-text search) with **incremental re-indexing**: edits are picked up automatically while connected.
|
|
93
|
+
- **Cross-project queries** — index several repos in one session and target any of them by path.
|
|
94
|
+
- **An `ama` CLI** for one-shot queries and scripting.
|
|
95
|
+
|
|
96
|
+
## Next
|
|
97
|
+
|
|
98
|
+
- **Deep-tier .NET (Roslyn) and Java analyzers** behind the sidecar protocol (the protocol + harness ship in 0.1; the analyzers need their language toolchains).
|
|
99
|
+
- More baseline languages and richer framework awareness.
|
|
100
|
+
|
|
101
|
+
## How it works
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
source files ──▶ analyzer (deep | baseline) ──▶ graph (nodes + edges) ──▶ store ──▶ query ──▶ MCP tools
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
- **Graph model** — language-agnostic `nodes` (File, Module, Class, Interface, Enum, Function, Method, …) and `edges` (Defines, Calls, Inherits, Implements, UsesType, Imports, References, …). Each symbol gets a stable, location-independent id.
|
|
108
|
+
- **Analyzers** — pluggable per language, each declaring its tier (`deep` or `baseline`). The TypeScript deep analyzer is the reference implementation.
|
|
109
|
+
- **Store** — in-memory, or SQLite with full-text search for persistence.
|
|
110
|
+
- **Query service** — search, call-graph traversal, code snippets, and impact analysis.
|
|
111
|
+
- **MCP server** — exposes the query surface over stdio.
|
|
112
|
+
|
|
113
|
+
## MCP tools
|
|
114
|
+
|
|
115
|
+
| Tool | What it does |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `index_repository(path)` | Build the graph for a directory or project. Run first. |
|
|
118
|
+
| `index_status()` | What's indexed: node/edge counts, per-language coverage + tier. |
|
|
119
|
+
| `search_symbol(query)` / `search_code(query)` | Find symbols by name, or search snippet text. |
|
|
120
|
+
| `find_callers` / `find_callees` | Who calls a function/method, and what it calls. |
|
|
121
|
+
| `find_referrers` / `find_imports` / `find_importers` | Where a symbol is used / what a file imports / who imports it. |
|
|
122
|
+
| `impact_analysis(symbol)` | Transitive blast radius for change/test selection. |
|
|
123
|
+
| `explore(question)` | Relevant symbols, a relationship map, and blast radius in one call. |
|
|
124
|
+
| `get_code_snippet(symbol)` / `file_skeleton(file)` | A symbol's source, or a file's symbol outline. |
|
|
125
|
+
|
|
126
|
+
…and more (overrides, interfaces, type users, routes → handlers, circular imports). Call `get_graph_schema()` for the full node/edge model, or `ama --help` for the CLI.
|
|
127
|
+
|
|
128
|
+
## How Ama is built
|
|
129
|
+
|
|
130
|
+
Ama improves itself by **dogfooding**: each change is made by using Ama's own tools on Ama's own source, and is only considered done once Ama can **re-index itself cleanly** — that self-index is the project's built-in regression test. Lessons learned along the way are recorded in [`docs/insights/`](docs/insights/README.md) so they compound over time. See [`docs/SELF_IMPROVEMENT_LOOP.md`](docs/SELF_IMPROVEMENT_LOOP.md) for the workflow and [`AGENTS.md`](AGENTS.md) for contributor and agent conventions.
|
|
131
|
+
|
|
132
|
+
## Development
|
|
133
|
+
|
|
134
|
+
> Requires **Node.js 24+**.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
git clone https://github.com/mka-rainmaker/ama.git
|
|
138
|
+
cd ama
|
|
139
|
+
npm install
|
|
140
|
+
npm run build # compile TypeScript to dist/
|
|
141
|
+
npm test # run the test suite (vitest)
|
|
142
|
+
npm run typecheck # type-check without emitting
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The backlog is tracked with [beads](https://github.com/steveyegge/beads) (`bd ready` to see what's actionable).
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
[MIT](LICENSE) © 2026 Mykhaylo Katruk
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type Parser from "web-tree-sitter";
|
|
2
|
+
import type { AnalysisResult, Analyzer } from "../types.js";
|
|
3
|
+
import { type SymbolRule } from "./walk.js";
|
|
4
|
+
export type { SymbolRule };
|
|
5
|
+
/**
|
|
6
|
+
* Describes a language for the {@link BaselineAnalyzer}: which extensions it
|
|
7
|
+
* owns, which bundled tree-sitter grammar to parse with, and which CST node
|
|
8
|
+
* types are symbols. Deep semantics (calls, types) are out of scope — baseline
|
|
9
|
+
* is syntactic breadth: files and the symbols they define.
|
|
10
|
+
*/
|
|
11
|
+
export interface LanguageSpec {
|
|
12
|
+
readonly language: string;
|
|
13
|
+
readonly extensions: readonly string[];
|
|
14
|
+
/** Key into the bundled grammar registry (see {@link parse}). */
|
|
15
|
+
readonly grammar: string;
|
|
16
|
+
/** CST node type → how to emit a symbol for it. */
|
|
17
|
+
readonly symbols: Readonly<Record<string, SymbolRule>>;
|
|
18
|
+
/**
|
|
19
|
+
* Optional import resolver: given an import CST node, the importing file's
|
|
20
|
+
* repo-relative path, and the index root, return each imported module as an
|
|
21
|
+
* ordered list of candidate repo-relative file paths — the analyzer emits a
|
|
22
|
+
* File→File `Imports` edge to the first candidate that exists on disk. Returns
|
|
23
|
+
* `undefined` for a non-import node, `[]` for an unresolvable (stdlib/third-party)
|
|
24
|
+
* import. `root` lets a config-aware language (Go's `go.mod`) resolve a
|
|
25
|
+
* module-qualified path; path-based languages can ignore it. (ama-8nr, ama-9yu)
|
|
26
|
+
*/
|
|
27
|
+
readonly resolveImports?: (node: Parser.SyntaxNode, importerRel: string, root: string) => string[][] | undefined;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A language-agnostic, syntactic (tier `baseline`) analyzer driven by a
|
|
31
|
+
* {@link LanguageSpec}. It parses each file with tree-sitter and walks the CST,
|
|
32
|
+
* emitting a File node plus a node for every symbol the spec recognizes, with a
|
|
33
|
+
* `Defines` edge from the enclosing symbol (or the file) and a dotted
|
|
34
|
+
* qualified name for nested symbols. One instance handles one language.
|
|
35
|
+
*/
|
|
36
|
+
export declare class BaselineAnalyzer implements Analyzer {
|
|
37
|
+
private readonly spec;
|
|
38
|
+
readonly tier = "baseline";
|
|
39
|
+
readonly language: string;
|
|
40
|
+
readonly extensions: readonly string[];
|
|
41
|
+
constructor(spec: LanguageSpec);
|
|
42
|
+
analyze(root: string, files: string[]): Promise<AnalysisResult>;
|
|
43
|
+
/** Walk the CST for import statements and emit a File→File `Imports` edge to
|
|
44
|
+
* each imported module that resolves (by path) to a file on disk. (ama-8nr) */
|
|
45
|
+
private collectImports;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,KAAK,UAAU,EAAe,MAAM,WAAW,CAAC;AAEzD,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACvD;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CACxB,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,KACT,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,QAAQ;IAKnC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJjC,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEV,IAAI,EAAE,YAAY;IAKzC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IA8CrE;oFACgF;IAChF,OAAO,CAAC,cAAc;CAkBvB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { fileId } from "../../graph/index.js";
|
|
4
|
+
import { parse } from "./treesitter.js";
|
|
5
|
+
import { walkSymbols } from "./walk.js";
|
|
6
|
+
/**
|
|
7
|
+
* A language-agnostic, syntactic (tier `baseline`) analyzer driven by a
|
|
8
|
+
* {@link LanguageSpec}. It parses each file with tree-sitter and walks the CST,
|
|
9
|
+
* emitting a File node plus a node for every symbol the spec recognizes, with a
|
|
10
|
+
* `Defines` edge from the enclosing symbol (or the file) and a dotted
|
|
11
|
+
* qualified name for nested symbols. One instance handles one language.
|
|
12
|
+
*/
|
|
13
|
+
export class BaselineAnalyzer {
|
|
14
|
+
spec;
|
|
15
|
+
tier = "baseline";
|
|
16
|
+
language;
|
|
17
|
+
extensions;
|
|
18
|
+
constructor(spec) {
|
|
19
|
+
this.spec = spec;
|
|
20
|
+
this.language = spec.language;
|
|
21
|
+
this.extensions = spec.extensions;
|
|
22
|
+
}
|
|
23
|
+
async analyze(root, files) {
|
|
24
|
+
const nodes = [];
|
|
25
|
+
const edges = [];
|
|
26
|
+
for (const rel of files) {
|
|
27
|
+
// Per-file isolation: a single unreadable or unparseable file must not lose
|
|
28
|
+
// the whole language's batch — finer than the indexer's per-analyzer catch
|
|
29
|
+
// (ama-m8k.9). Build into local arrays and merge only on success, so a
|
|
30
|
+
// mid-walk throw leaves no partial nodes behind. (ama-eww)
|
|
31
|
+
try {
|
|
32
|
+
const code = fs.readFileSync(path.join(root, rel), "utf8");
|
|
33
|
+
const tree = await parse(this.spec.grammar, code);
|
|
34
|
+
// A web-tree-sitter Tree holds WASM memory; free it once walked so a large
|
|
35
|
+
// index doesn't accumulate one tree per file. `finally` covers a throw in
|
|
36
|
+
// walk. The extracted GraphNodes are plain copies, valid after delete. (ama-5o1)
|
|
37
|
+
try {
|
|
38
|
+
const id = fileId(rel);
|
|
39
|
+
const fileNodes = [
|
|
40
|
+
{
|
|
41
|
+
id,
|
|
42
|
+
kind: "File",
|
|
43
|
+
name: path.basename(rel),
|
|
44
|
+
file: rel,
|
|
45
|
+
qualifiedName: "",
|
|
46
|
+
tier: "baseline",
|
|
47
|
+
range: { startLine: 1, endLine: tree.rootNode.endPosition.row + 1 },
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
const fileEdges = [];
|
|
51
|
+
walkSymbols(tree.rootNode, this.spec.symbols, rel, id, "", fileNodes, fileEdges);
|
|
52
|
+
if (this.spec.resolveImports)
|
|
53
|
+
this.collectImports(tree.rootNode, rel, root, id, fileEdges);
|
|
54
|
+
nodes.push(...fileNodes);
|
|
55
|
+
edges.push(...fileEdges);
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
tree.delete();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
console.error(`[ama] ${this.spec.language} analyzer failed on ${rel}; skipping it. ` +
|
|
63
|
+
`${err instanceof Error ? err.message : String(err)}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { nodes, edges };
|
|
67
|
+
}
|
|
68
|
+
/** Walk the CST for import statements and emit a File→File `Imports` edge to
|
|
69
|
+
* each imported module that resolves (by path) to a file on disk. (ama-8nr) */
|
|
70
|
+
collectImports(node, importerRel, root, fileNodeId, edges) {
|
|
71
|
+
const groups = this.spec.resolveImports?.(node, importerRel, root);
|
|
72
|
+
if (groups) {
|
|
73
|
+
for (const candidates of groups) {
|
|
74
|
+
const target = candidates.find((c) => fs.existsSync(path.join(root, c)));
|
|
75
|
+
if (target)
|
|
76
|
+
edges.push({ from: fileNodeId, to: fileId(target), kind: "Imports" });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
for (const child of node.namedChildren) {
|
|
80
|
+
this.collectImports(child, importerRel, root, fileNodeId, edges);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LanguageSpec } from "./analyzer.js";
|
|
2
|
+
/**
|
|
3
|
+
* Baseline (syntactic) specs for C and C++. Both share a grammar family: structs,
|
|
4
|
+
* unions, enums, and typedefs carry a `name` field, while a `function_definition`
|
|
5
|
+
* nests its name in a `declarator` chain — the analyzer's `symbolName` drills that
|
|
6
|
+
* for us. C++ adds classes and namespaces; a method defined inline is a
|
|
7
|
+
* `function_definition` inside the class body, so it surfaces as a Function
|
|
8
|
+
* qualified under its class (e.g. `Sample.square`). (ama-s8q.9)
|
|
9
|
+
*/
|
|
10
|
+
export declare const cSpec: LanguageSpec;
|
|
11
|
+
export declare const cppSpec: LanguageSpec;
|
|
12
|
+
//# sourceMappingURL=c.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"c.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/c.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAiBlD;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,YAYnB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,YAerB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
/** Resolve a C/C++ `#include "foo.h"` to its header file. The quoted form is
|
|
3
|
+
* relative to the including file's directory (and resolved on disk, like JS/Python
|
|
4
|
+
* relative imports), so it's single-file-reindex-safe; the angle form `#include <…>`
|
|
5
|
+
* is a system/include-path header (external) and resolves to nothing. (ama-ftg) */
|
|
6
|
+
function includeImports(node, importerRel) {
|
|
7
|
+
if (node.type !== "preproc_include")
|
|
8
|
+
return undefined;
|
|
9
|
+
const lit = node.namedChildren.find((c) => c.type === "string_literal");
|
|
10
|
+
if (!lit)
|
|
11
|
+
return []; // `#include <…>` (system_lib_string) — external
|
|
12
|
+
const content = lit.namedChildren.find((c) => c.type === "string_content");
|
|
13
|
+
const includePath = (content?.text ?? lit.text.replace(/^"|"$/g, "")).trim();
|
|
14
|
+
if (!includePath)
|
|
15
|
+
return [];
|
|
16
|
+
// join() normalizes `..`, so `#include "../inc/x.h"` from `src/a.c` → `inc/x.h`.
|
|
17
|
+
return [[path.posix.join(path.posix.dirname(importerRel), includePath)]];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Baseline (syntactic) specs for C and C++. Both share a grammar family: structs,
|
|
21
|
+
* unions, enums, and typedefs carry a `name` field, while a `function_definition`
|
|
22
|
+
* nests its name in a `declarator` chain — the analyzer's `symbolName` drills that
|
|
23
|
+
* for us. C++ adds classes and namespaces; a method defined inline is a
|
|
24
|
+
* `function_definition` inside the class body, so it surfaces as a Function
|
|
25
|
+
* qualified under its class (e.g. `Sample.square`). (ama-s8q.9)
|
|
26
|
+
*/
|
|
27
|
+
export const cSpec = {
|
|
28
|
+
language: "c",
|
|
29
|
+
extensions: [".c"],
|
|
30
|
+
grammar: "c",
|
|
31
|
+
symbols: {
|
|
32
|
+
function_definition: { kind: "Function" },
|
|
33
|
+
struct_specifier: { kind: "Class" },
|
|
34
|
+
union_specifier: { kind: "Class" },
|
|
35
|
+
enum_specifier: { kind: "Enum" },
|
|
36
|
+
type_definition: { kind: "TypeAlias" },
|
|
37
|
+
},
|
|
38
|
+
resolveImports: includeImports,
|
|
39
|
+
};
|
|
40
|
+
export const cppSpec = {
|
|
41
|
+
language: "cpp",
|
|
42
|
+
// `.h` routes here: the C++ grammar is a superset, so it parses C headers too.
|
|
43
|
+
extensions: [".cpp", ".cc", ".cxx", ".hpp", ".hh", ".h"],
|
|
44
|
+
grammar: "cpp",
|
|
45
|
+
symbols: {
|
|
46
|
+
function_definition: { kind: "Function" },
|
|
47
|
+
struct_specifier: { kind: "Class" },
|
|
48
|
+
union_specifier: { kind: "Class" },
|
|
49
|
+
enum_specifier: { kind: "Enum" },
|
|
50
|
+
type_definition: { kind: "TypeAlias" },
|
|
51
|
+
class_specifier: { kind: "Class" },
|
|
52
|
+
namespace_definition: { kind: "Module" },
|
|
53
|
+
},
|
|
54
|
+
resolveImports: includeImports,
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=c.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"c.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/c.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC;;;oFAGoF;AACpF,SAAS,cAAc,CAAC,IAAuB,EAAE,WAAmB;IAClE,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB;QAAE,OAAO,SAAS,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;IACxE,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC,CAAC,gDAAgD;IACrE,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;IAC3E,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7E,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAC5B,iFAAiF;IACjF,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAiB;IACjC,QAAQ,EAAE,GAAG;IACb,UAAU,EAAE,CAAC,IAAI,CAAC;IAClB,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE;QACP,mBAAmB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;QACzC,gBAAgB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACnC,eAAe,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QAClC,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QAChC,eAAe,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;KACvC;IACD,cAAc,EAAE,cAAc;CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAiB;IACnC,QAAQ,EAAE,KAAK;IACf,+EAA+E;IAC/E,UAAU,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC;IACxD,OAAO,EAAE,KAAK;IACd,OAAO,EAAE;QACP,mBAAmB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;QACzC,gBAAgB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACnC,eAAe,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QAClC,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QAChC,eAAe,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QACtC,eAAe,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QAClC,oBAAoB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KACzC;IACD,cAAc,EAAE,cAAc;CAC/B,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** The repo-relative parent directory of a repo-relative path, with the repo root as
|
|
2
|
+
* `""` (not `"."`). */
|
|
3
|
+
export declare function parentDir(rel: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* The nearest project-config file at or above `dirRel` (walking up to the index root),
|
|
6
|
+
* parsed by `read` into a value, paired with the repo-relative directory it was found in
|
|
7
|
+
* — so a baseline analyzer resolves imports whether the index root *is* the package or
|
|
8
|
+
* merely contains it (a monorepo / Ama's own fixtures). `read(absDir)` returns the parsed
|
|
9
|
+
* config for that directory or `undefined` if there's none there. Results (including
|
|
10
|
+
* "none found") are memoized in `cache` per absolute directory, so a package isn't
|
|
11
|
+
* re-walked once per import. Shared by Go (`go.mod`), PHP (`composer.json`), and C#
|
|
12
|
+
* (`.csproj`). (ama-9yu, ama-x96, ama-66z)
|
|
13
|
+
*/
|
|
14
|
+
export declare function nearestConfig<T>(root: string, dirRel: string, read: (absDir: string) => T | undefined, cache: Map<string, {
|
|
15
|
+
dir: string;
|
|
16
|
+
value: T;
|
|
17
|
+
} | null>): {
|
|
18
|
+
dir: string;
|
|
19
|
+
value: T;
|
|
20
|
+
} | null;
|
|
21
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/config.ts"],"names":[],"mappings":"AAEA;wBACwB;AACxB,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,GAAG,SAAS,EACvC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG,IAAI,CAAC,GACnD;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG,IAAI,CAWlC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
/** The repo-relative parent directory of a repo-relative path, with the repo root as
|
|
3
|
+
* `""` (not `"."`). */
|
|
4
|
+
export function parentDir(rel) {
|
|
5
|
+
const p = path.posix.dirname(rel);
|
|
6
|
+
return p === "." ? "" : p;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The nearest project-config file at or above `dirRel` (walking up to the index root),
|
|
10
|
+
* parsed by `read` into a value, paired with the repo-relative directory it was found in
|
|
11
|
+
* — so a baseline analyzer resolves imports whether the index root *is* the package or
|
|
12
|
+
* merely contains it (a monorepo / Ama's own fixtures). `read(absDir)` returns the parsed
|
|
13
|
+
* config for that directory or `undefined` if there's none there. Results (including
|
|
14
|
+
* "none found") are memoized in `cache` per absolute directory, so a package isn't
|
|
15
|
+
* re-walked once per import. Shared by Go (`go.mod`), PHP (`composer.json`), and C#
|
|
16
|
+
* (`.csproj`). (ama-9yu, ama-x96, ama-66z)
|
|
17
|
+
*/
|
|
18
|
+
export function nearestConfig(root, dirRel, read, cache) {
|
|
19
|
+
const absDir = path.join(root, dirRel);
|
|
20
|
+
const cached = cache.get(absDir);
|
|
21
|
+
if (cached !== undefined)
|
|
22
|
+
return cached;
|
|
23
|
+
let result = null;
|
|
24
|
+
const value = read(absDir);
|
|
25
|
+
if (value !== undefined)
|
|
26
|
+
result = { dir: dirRel, value };
|
|
27
|
+
else if (dirRel !== "" && dirRel !== ".")
|
|
28
|
+
result = nearestConfig(root, parentDir(dirRel), read, cache);
|
|
29
|
+
cache.set(absDir, result);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;wBACwB;AACxB,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,MAAc,EACd,IAAuC,EACvC,KAAoD;IAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACxC,IAAI,MAAM,GAAqC,IAAI,CAAC;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;SACpD,IAAI,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK,GAAG;QACtC,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/D,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1B,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LanguageSpec } from "./analyzer.js";
|
|
2
|
+
/**
|
|
3
|
+
* Baseline (syntactic) spec for C#. Like Java, every kind has its own CST node
|
|
4
|
+
* type. Structs and records are value/data types with members, mapped to Class
|
|
5
|
+
* (the graph has no dedicated struct/record kind); methods nest under their
|
|
6
|
+
* type's body (e.g. `Sample.Square`).
|
|
7
|
+
*/
|
|
8
|
+
export declare const csharpSpec: LanguageSpec;
|
|
9
|
+
//# sourceMappingURL=csharp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csharp.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/csharp.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA2FlD;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,YAaxB,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { nearestConfig, parentDir } from "./config.js";
|
|
4
|
+
import { ancestorDirs } from "./paths.js";
|
|
5
|
+
/** Cache for the nearest `.csproj`'s root namespace, by importer directory. */
|
|
6
|
+
const csprojCache = new Map();
|
|
7
|
+
/** The C# root namespace declared by a `.csproj` in `absDir` — its `<RootNamespace>`, or
|
|
8
|
+
* (the C# default) the project file's base name. Undefined when `absDir` holds no
|
|
9
|
+
* `.csproj`, so the walk-up continues. (ama-66z) */
|
|
10
|
+
function readCsprojRootNamespace(absDir) {
|
|
11
|
+
let entries;
|
|
12
|
+
try {
|
|
13
|
+
entries = fs.readdirSync(absDir, { withFileTypes: true });
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const proj = entries.find((e) => e.isFile() && e.name.endsWith(".csproj"));
|
|
19
|
+
if (!proj)
|
|
20
|
+
return undefined;
|
|
21
|
+
try {
|
|
22
|
+
const content = fs.readFileSync(path.join(absDir, proj.name), "utf8");
|
|
23
|
+
return (content.match(/<RootNamespace>\s*([^<\s]+)\s*<\/RootNamespace>/)?.[1] ??
|
|
24
|
+
proj.name.replace(/\.csproj$/i, ""));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return proj.name.replace(/\.csproj$/i, ""); // unreadable body — default to the file name
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** The `.cs` files directly in repo-relative `rel` (excluding the importer), one
|
|
31
|
+
* File→File candidate group each — or undefined if `rel` isn't a directory or holds no
|
|
32
|
+
* `.cs` files. */
|
|
33
|
+
function csFilesIn(root, rel, importerRel) {
|
|
34
|
+
let entries;
|
|
35
|
+
try {
|
|
36
|
+
entries = fs.readdirSync(path.join(root, rel), { withFileTypes: true });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return undefined; // not a directory on disk
|
|
40
|
+
}
|
|
41
|
+
const files = entries
|
|
42
|
+
.filter((e) => e.isFile() && e.name.endsWith(".cs"))
|
|
43
|
+
.map((e) => (rel ? `${rel}/${e.name}` : e.name))
|
|
44
|
+
.filter((f) => f !== importerRel);
|
|
45
|
+
return files.length > 0 ? files.map((f) => [f]) : undefined;
|
|
46
|
+
}
|
|
47
|
+
/** Resolve a C# `using A.B.C;` to the source files of that namespace. C# has no 1:1
|
|
48
|
+
* namespace→file mapping: a namespace is a *set* of files, conventionally a directory,
|
|
49
|
+
* so a `using` links to every `.cs` file in the matching directory — the "package =
|
|
50
|
+
* directory" shape Go has. Two strategies, precise first: (1) if the namespace is under
|
|
51
|
+
* the nearest `.csproj`'s root namespace (`<RootNamespace>`, else the project file
|
|
52
|
+
* name), map it *exactly* to that project's directory tree — avoiding a coincidental
|
|
53
|
+
* match at a closer ancestor. (2) Otherwise (a namespace from another project, or no
|
|
54
|
+
* `.csproj`), ancestor-scan from the importer's own directory upward, trying
|
|
55
|
+
* progressively shorter suffixes of the dotted name — longest (most specific) first —
|
|
56
|
+
* and take the first directory holding `.cs` files; this favors recall. `using Alias =
|
|
57
|
+
* …` and framework namespaces resolve to nothing. (ama-7e3, ama-66z) */
|
|
58
|
+
function csharpImports(node, importerRel, root) {
|
|
59
|
+
if (node.type !== "using_directive")
|
|
60
|
+
return undefined;
|
|
61
|
+
if (node.namedChildren.some((c) => c.type === "name_equals"))
|
|
62
|
+
return []; // `using Alias = …;`
|
|
63
|
+
const name = node.namedChildren.find((c) => c.type === "qualified_name" || c.type === "identifier");
|
|
64
|
+
if (!name)
|
|
65
|
+
return [];
|
|
66
|
+
// (1) Precise: a namespace under this project's root namespace maps to an exact dir.
|
|
67
|
+
const proj = nearestConfig(root, parentDir(importerRel), readCsprojRootNamespace, csprojCache);
|
|
68
|
+
if (proj && (name.text === proj.value || name.text.startsWith(`${proj.value}.`))) {
|
|
69
|
+
const sub = name.text === proj.value ? "" : name.text.slice(proj.value.length + 1);
|
|
70
|
+
const exact = [proj.dir, sub.replace(/\./g, "/")].filter(Boolean).join("/");
|
|
71
|
+
const files = csFilesIn(root, exact, importerRel);
|
|
72
|
+
if (files)
|
|
73
|
+
return files;
|
|
74
|
+
}
|
|
75
|
+
// (2) Heuristic fallback: ancestor-scan + progressively shorter suffixes (recall).
|
|
76
|
+
const segments = name.text.split(".");
|
|
77
|
+
for (const ancestor of ancestorDirs(importerRel)) {
|
|
78
|
+
for (let len = segments.length; len >= 1; len--) {
|
|
79
|
+
const rel = [ancestor, ...segments.slice(segments.length - len)].filter(Boolean).join("/");
|
|
80
|
+
const files = csFilesIn(root, rel, importerRel);
|
|
81
|
+
if (files)
|
|
82
|
+
return files;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return []; // a framework/NuGet namespace, or none on disk
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Baseline (syntactic) spec for C#. Like Java, every kind has its own CST node
|
|
89
|
+
* type. Structs and records are value/data types with members, mapped to Class
|
|
90
|
+
* (the graph has no dedicated struct/record kind); methods nest under their
|
|
91
|
+
* type's body (e.g. `Sample.Square`).
|
|
92
|
+
*/
|
|
93
|
+
export const csharpSpec = {
|
|
94
|
+
language: "csharp",
|
|
95
|
+
extensions: [".cs"],
|
|
96
|
+
grammar: "csharp",
|
|
97
|
+
symbols: {
|
|
98
|
+
class_declaration: { kind: "Class" },
|
|
99
|
+
interface_declaration: { kind: "Interface" },
|
|
100
|
+
struct_declaration: { kind: "Class" },
|
|
101
|
+
record_declaration: { kind: "Class" },
|
|
102
|
+
enum_declaration: { kind: "Enum" },
|
|
103
|
+
method_declaration: { kind: "Method" },
|
|
104
|
+
},
|
|
105
|
+
resolveImports: csharpImports,
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=csharp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csharp.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/csharp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LanguageSpec } from "./analyzer.js";
|
|
2
|
+
/**
|
|
3
|
+
* Baseline (syntactic) spec for Go. Go declares named types with a single
|
|
4
|
+
* `type_spec` node regardless of whether the body is a struct, interface, or
|
|
5
|
+
* alias — so it uses {@link SymbolRule.kindByChild} to refine: a `struct_type`
|
|
6
|
+
* child → Class, an `interface_type` child → Interface, else a TypeAlias.
|
|
7
|
+
* Methods are top-level `method_declaration`s (the receiver isn't a container),
|
|
8
|
+
* so they surface as Methods named for the function, not qualified by the type.
|
|
9
|
+
*/
|
|
10
|
+
export declare const goSpec: LanguageSpec;
|
|
11
|
+
//# sourceMappingURL=go.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"go.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/go.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA6ClD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAAE,YAapB,CAAC"}
|