@mka-rainmaker/ama 0.1.1 → 0.2.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.
Files changed (65) hide show
  1. package/README.md +36 -2
  2. package/dist/analyzers/baseline/analyzer.d.ts +19 -0
  3. package/dist/analyzers/baseline/analyzer.d.ts.map +1 -1
  4. package/dist/analyzers/baseline/analyzer.js +10 -0
  5. package/dist/analyzers/baseline/analyzer.js.map +1 -1
  6. package/dist/analyzers/baseline/go.d.ts.map +1 -1
  7. package/dist/analyzers/baseline/go.js +67 -0
  8. package/dist/analyzers/baseline/go.js.map +1 -1
  9. package/dist/analyzers/baseline/java.d.ts.map +1 -1
  10. package/dist/analyzers/baseline/java.js +84 -0
  11. package/dist/analyzers/baseline/java.js.map +1 -1
  12. package/dist/analyzers/baseline/php.d.ts.map +1 -1
  13. package/dist/analyzers/baseline/php.js +56 -0
  14. package/dist/analyzers/baseline/php.js.map +1 -1
  15. package/dist/analyzers/baseline/python.d.ts.map +1 -1
  16. package/dist/analyzers/baseline/python.js +257 -0
  17. package/dist/analyzers/baseline/python.js.map +1 -1
  18. package/dist/analyzers/baseline/rust.d.ts.map +1 -1
  19. package/dist/analyzers/baseline/rust.js +80 -0
  20. package/dist/analyzers/baseline/rust.js.map +1 -1
  21. package/dist/analyzers/sidecar/protocol.d.ts +22 -22
  22. package/dist/analyzers/typescript/analyzer.d.ts.map +1 -1
  23. package/dist/analyzers/typescript/analyzer.js +51 -1
  24. package/dist/analyzers/typescript/analyzer.js.map +1 -1
  25. package/dist/api.d.ts +34 -0
  26. package/dist/api.d.ts.map +1 -0
  27. package/dist/api.js +38 -0
  28. package/dist/api.js.map +1 -0
  29. package/dist/cli/agents.d.ts +37 -0
  30. package/dist/cli/agents.d.ts.map +1 -0
  31. package/dist/cli/agents.js +86 -0
  32. package/dist/cli/agents.js.map +1 -0
  33. package/dist/cli/commands/install.d.ts +20 -0
  34. package/dist/cli/commands/install.d.ts.map +1 -0
  35. package/dist/cli/commands/install.js +117 -0
  36. package/dist/cli/commands/install.js.map +1 -0
  37. package/dist/cli/index.d.ts.map +1 -1
  38. package/dist/cli/index.js +3 -0
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/graph/index.d.ts +2 -1
  41. package/dist/graph/index.d.ts.map +1 -1
  42. package/dist/graph/index.js +2 -1
  43. package/dist/graph/index.js.map +1 -1
  44. package/dist/graph/prisma-link.d.ts +9 -4
  45. package/dist/graph/prisma-link.d.ts.map +1 -1
  46. package/dist/graph/prisma-link.js +25 -10
  47. package/dist/graph/prisma-link.js.map +1 -1
  48. package/dist/graph/python-calls.d.ts +14 -0
  49. package/dist/graph/python-calls.d.ts.map +1 -0
  50. package/dist/graph/python-calls.js +0 -0
  51. package/dist/graph/python-calls.js.map +1 -0
  52. package/dist/graph/types.d.ts +1 -1
  53. package/dist/graph/types.d.ts.map +1 -1
  54. package/dist/indexer/indexer.d.ts.map +1 -1
  55. package/dist/indexer/indexer.js +12 -1
  56. package/dist/indexer/indexer.js.map +1 -1
  57. package/dist/mcp/server.d.ts +7 -1
  58. package/dist/mcp/server.d.ts.map +1 -1
  59. package/dist/mcp/server.js +66 -30
  60. package/dist/mcp/server.js.map +1 -1
  61. package/dist/query/service.d.ts +3 -0
  62. package/dist/query/service.d.ts.map +1 -1
  63. package/dist/query/service.js +18 -2
  64. package/dist/query/service.js.map +1 -1
  65. package/package.json +10 -1
package/README.md CHANGED
@@ -18,7 +18,7 @@ Every answer reports **which tier produced it**, so partial coverage never quiet
18
18
  And because it's built for agents:
19
19
 
20
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.
21
+ - **Cheaper and faster.** Fewer tool calls and fewer tokens per question, because one graph query replaces a pile of file reads — see [benchmarks](docs/benchmarks/README.md) (a focused, single-call answer vs. grep-then-read; methodology + honest caveats there).
22
22
 
23
23
  ## Install
24
24
 
@@ -34,7 +34,15 @@ npm install -g @mka-rainmaker/ama
34
34
 
35
35
  ### Configure your coding agent
36
36
 
37
- Every MCP client spawns the same stdio command `ama mcp` only the config location differs.
37
+ **Fastestlet Ama wire itself in:**
38
+
39
+ ```bash
40
+ ama install # detects Claude Code / Cursor / Windsurf / Codex and writes their MCP config
41
+ ama install --dry-run # preview what it would change, writing nothing
42
+ ama uninstall # remove it again
43
+ ```
44
+
45
+ Or configure manually — every MCP client spawns the same stdio command (`ama mcp`), only the config location differs.
38
46
 
39
47
  **Claude Code** — add it with one command:
40
48
 
@@ -66,6 +74,16 @@ claude mcp add ama -- ama mcp
66
74
  { "mcpServers": { "ama": { "command": "npx", "args": ["-y", "@mka-rainmaker/ama", "mcp"] } } }
67
75
  ```
68
76
 
77
+ ### Fewer tools, lower token cost
78
+
79
+ Ama exposes 27 tools by default. To trade that for a small high-signal set, set
80
+ `AMA_MCP_TOOLS` on the server — `minimal` (just `explore` + indexing), or a comma-separated
81
+ list of tool names (the indexing tools are always included):
82
+
83
+ ```json
84
+ { "mcpServers": { "ama": { "command": "ama", "args": ["mcp"], "env": { "AMA_MCP_TOOLS": "minimal" } } } }
85
+ ```
86
+
69
87
  ### Quick start
70
88
 
71
89
  Once connected, point Ama at a repo and start asking graph questions:
@@ -84,6 +102,22 @@ ama --help # list commands
84
102
  ama mcp # run the MCP server over stdio (what coding agents spawn)
85
103
  ```
86
104
 
105
+ ### Programmatic API
106
+
107
+ Embed Ama as a library — index a repo and query its graph from your own code (the same surface the MCP server and CLI use):
108
+
109
+ ```ts
110
+ import { index } from "@mka-rainmaker/ama";
111
+
112
+ const ama = await index("/path/to/repo");
113
+ ama.searchSymbol("createServer"); // GraphNode[]
114
+ ama.findCallers("createServer"); // who calls it
115
+ ama.impactAnalysis("AmaSession"); // transitive blast radius
116
+ ama.close(); // release resources when done
117
+ ```
118
+
119
+ `index(root)` returns a transport-free `AmaSession` (aliased `Ama`) with the full query surface; `open(root)` reuses a persisted index. See [`src/api.ts`](src/api.ts) for the exported types.
120
+
87
121
  ## What's in 0.1
88
122
 
89
123
  - **Deep TypeScript analysis** via the TypeScript Compiler API — types, overloads, generics, imports/re-exports, inheritance, interface dispatch, cross-file binding, and call graphs.
@@ -1,4 +1,5 @@
1
1
  import type Parser from "web-tree-sitter";
2
+ import { type GraphEdge, type GraphNode } from "../../graph/index.js";
2
3
  import type { AnalysisResult, Analyzer } from "../types.js";
3
4
  import { type SymbolRule } from "./walk.js";
4
5
  export type { SymbolRule };
@@ -25,6 +26,24 @@ export interface LanguageSpec {
25
26
  * module-qualified path; path-based languages can ignore it. (ama-8nr, ama-9yu)
26
27
  */
27
28
  readonly resolveImports?: (node: Parser.SyntaxNode, importerRel: string, root: string) => string[][] | undefined;
29
+ /**
30
+ * Optional route detector: walk the CST for framework route registrations and return Route
31
+ * nodes plus their handler `References` edges. Baseline tier — a heuristic, syntactic match
32
+ * on decorator/call patterns (e.g. Python's `@app.get("/x")`). (ama-bvg)
33
+ */
34
+ readonly collectRoutes?: (root: Parser.SyntaxNode, rel: string) => {
35
+ nodes: GraphNode[];
36
+ edges: GraphEdge[];
37
+ };
38
+ /**
39
+ * Optional call detector: walk the CST for call sites and return heuristic `Calls` edges.
40
+ * Baseline tier — name-based resolution within the file (no types), so callers/callees and
41
+ * blast-radius work for languages without a deep analyzer. (ama-bnj)
42
+ */
43
+ readonly collectCalls?: (root: Parser.SyntaxNode, rel: string) => {
44
+ nodes: GraphNode[];
45
+ edges: GraphEdge[];
46
+ };
28
47
  }
29
48
  /**
30
49
  * A language-agnostic, syntactic (tier `baseline`) analyzer driven by a
@@ -1 +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"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAU,MAAM,sBAAsB,CAAC;AAC9E,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;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CACvB,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,GAAG,EAAE,MAAM,KACR;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC;IAEhD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CACtB,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,GAAG,EAAE,MAAM,KACR;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC;CACjD;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;IAwDrE;oFACgF;IAChF,OAAO,CAAC,cAAc;CAkBvB"}
@@ -51,6 +51,16 @@ export class BaselineAnalyzer {
51
51
  walkSymbols(tree.rootNode, this.spec.symbols, rel, id, "", fileNodes, fileEdges);
52
52
  if (this.spec.resolveImports)
53
53
  this.collectImports(tree.rootNode, rel, root, id, fileEdges);
54
+ if (this.spec.collectRoutes) {
55
+ const routes = this.spec.collectRoutes(tree.rootNode, rel);
56
+ fileNodes.push(...routes.nodes);
57
+ fileEdges.push(...routes.edges);
58
+ }
59
+ if (this.spec.collectCalls) {
60
+ const calls = this.spec.collectCalls(tree.rootNode, rel);
61
+ fileNodes.push(...calls.nodes);
62
+ fileEdges.push(...calls.edges);
63
+ }
54
64
  nodes.push(...fileNodes);
55
65
  edges.push(...fileEdges);
56
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/analyzer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/analyzer.ts"],"names":[],"mappings":"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"}
@@ -1 +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"}
1
+ {"version":3,"file":"go.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/go.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAgHlD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAAE,YAcpB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
+ import { symbolId } from "../../graph/index.js";
3
4
  import { nearestConfig, parentDir } from "./config.js";
4
5
  /** Cache for the nearest `go.mod`'s declared module path, by importer directory. */
5
6
  const goModuleCache = new Map();
@@ -41,6 +42,71 @@ function goImports(node, importerRel, root) {
41
42
  .filter((f) => f.endsWith(".go") && !f.endsWith("_test.go"))
42
43
  .map((f) => [pkgDir ? `${pkgDir}/${f}` : f]);
43
44
  }
45
+ /** Gin/chi/echo HTTP-verb router methods — `r.GET("/x", h)`. (ama-a2r) */
46
+ const GO_ROUTE_METHODS = new Set(["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"]);
47
+ /** Normalize a Go route path: chi/mux `{id}` → `:id` (Gin's `:id` is already the shared form);
48
+ * ensure a leading slash. (ama-a2r) */
49
+ function normalizeGoRoutePath(p) {
50
+ const s = p.replace(/\{([^}]+)\}/g, ":$1");
51
+ return s.startsWith("/") ? s : `/${s}`;
52
+ }
53
+ /** The first string-literal argument (interpreted or raw) of an argument_list, unquoted. */
54
+ function goStringArg(args) {
55
+ if (!args)
56
+ return undefined;
57
+ for (const a of args.namedChildren) {
58
+ if (a.type === "interpreted_string_literal" || a.type === "raw_string_literal") {
59
+ return a.text.replace(/^[`"]|[`"]$/g, "");
60
+ }
61
+ }
62
+ return undefined;
63
+ }
64
+ function* eachCall(node) {
65
+ if (node.type === "call_expression")
66
+ yield node;
67
+ for (const c of node.namedChildren)
68
+ yield* eachCall(c);
69
+ }
70
+ /** Detect Gin/chi/echo-style routes: `r.GET("/path", handler)` — a call whose function is a
71
+ * selector with an HTTP-verb field and a string first arg — becomes a `METHOD /path` Route,
72
+ * referencing the handler when it's a plain identifier in the same file. (ama-a2r) */
73
+ function goRoutes(root, rel) {
74
+ const nodes = [];
75
+ const edges = [];
76
+ for (const call of eachCall(root)) {
77
+ const fn = call.childForFieldName("function");
78
+ if (fn?.type !== "selector_expression")
79
+ continue;
80
+ const verb = fn.childForFieldName("field")?.text?.toUpperCase();
81
+ if (!verb || !GO_ROUTE_METHODS.has(verb))
82
+ continue;
83
+ const args = call.childForFieldName("arguments");
84
+ const raw = goStringArg(args);
85
+ if (raw === undefined)
86
+ continue;
87
+ const name = `${verb} ${normalizeGoRoutePath(raw)}`;
88
+ const routeId = symbolId({ file: rel, qualifiedName: name });
89
+ nodes.push({
90
+ id: routeId,
91
+ kind: "Route",
92
+ name,
93
+ file: rel,
94
+ qualifiedName: name,
95
+ tier: "baseline",
96
+ range: { startLine: call.startPosition.row + 1, endLine: call.endPosition.row + 1 },
97
+ });
98
+ const handler = args?.namedChildren.find((a, i) => i > 0 && a.type === "identifier");
99
+ if (handler) {
100
+ edges.push({
101
+ from: routeId,
102
+ to: symbolId({ file: rel, qualifiedName: handler.text }),
103
+ kind: "References",
104
+ provenance: "heuristic",
105
+ });
106
+ }
107
+ }
108
+ return { nodes, edges };
109
+ }
44
110
  /**
45
111
  * Baseline (syntactic) spec for Go. Go declares named types with a single
46
112
  * `type_spec` node regardless of whether the body is a struct, interface, or
@@ -62,5 +128,6 @@ export const goSpec = {
62
128
  },
63
129
  },
64
130
  resolveImports: goImports,
131
+ collectRoutes: goRoutes,
65
132
  };
66
133
  //# sourceMappingURL=go.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"go.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/go.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEvD,oFAAoF;AACpF,MAAM,aAAa,GAAG,IAAI,GAAG,EAAiD,CAAC;AAE/E,0FAA0F;AAC1F,SAAS,YAAY,CAAC,MAAc;IAClC,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7F,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC,CAAC,qDAAqD;IACzE,CAAC;AACH,CAAC;AAED;;;;;yBAKyB;AACzB,SAAS,SAAS,CAChB,IAAuB,EACvB,WAAmB,EACnB,IAAY;IAEZ,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa;QAAE,OAAO,SAAS,CAAC;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,4BAA4B,CAAC,CAAC;IACpF,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,WAAW,CAAC,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;IACrF,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC7F,MAAM,GAAG,GAAG,UAAU,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;SAC3D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,MAAM,GAAiB;IAClC,QAAQ,EAAE,IAAI;IACd,UAAU,EAAE,CAAC,KAAK,CAAC;IACnB,OAAO,EAAE,IAAI;IACb,OAAO,EAAE;QACP,oBAAoB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;QAC1C,kBAAkB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtC,SAAS,EAAE;YACT,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE;SACnE;KACF;IACD,cAAc,EAAE,SAAS;CAC1B,CAAC"}
1
+ {"version":3,"file":"go.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/go.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"java.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/java.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAiClD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,YAWtB,CAAC"}
1
+ {"version":3,"file":"java.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/java.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA0HlD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,YAYtB,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { symbolId } from "../../graph/index.js";
1
2
  import { ancestorDirs } from "./paths.js";
2
3
  /** Try a repo-relative file under every ancestor directory of the importer. A
3
4
  * package import gives a *source-root-relative* path (`com/example/Foo.java`)
@@ -29,6 +30,88 @@ function javaImports(node, importerRel) {
29
30
  const file = `${segments.slice(0, classEnd + 1).join("/")}.java`;
30
31
  return [ancestorCandidates(importerRel, file)];
31
32
  }
33
+ /** Spring method-mapping annotations → HTTP verb. `@RequestMapping` is the class-level prefix. */
34
+ const JAVA_MAPPING_VERBS = new Map([
35
+ ["GetMapping", "GET"],
36
+ ["PostMapping", "POST"],
37
+ ["PutMapping", "PUT"],
38
+ ["DeleteMapping", "DELETE"],
39
+ ["PatchMapping", "PATCH"],
40
+ ]);
41
+ function firstOfType(node, type) {
42
+ if (node.type === type)
43
+ return node;
44
+ for (const c of node.namedChildren) {
45
+ const found = firstOfType(c, type);
46
+ if (found)
47
+ return found;
48
+ }
49
+ return undefined;
50
+ }
51
+ function* eachClass(node) {
52
+ if (node.type === "class_declaration")
53
+ yield node;
54
+ for (const c of node.namedChildren)
55
+ yield* eachClass(c);
56
+ }
57
+ /** The string argument of an `@Annotation("x")`, or undefined for a marker annotation. */
58
+ function annotationArg(ann) {
59
+ return firstOfType(ann, "string_fragment")?.text;
60
+ }
61
+ /** Combine a Spring class prefix and a method sub-path into a normalized `:param` route. */
62
+ function joinJavaRoutePath(prefix, sub) {
63
+ const norm = (s) => s.replace(/\{([^}]+)\}/g, ":$1");
64
+ const segs = [norm(prefix), norm(sub)].flatMap((s) => s.split("/")).filter(Boolean);
65
+ return `/${segs.join("/")}`;
66
+ }
67
+ /** Detect Spring MVC routes: a class `@RequestMapping("/prefix")` prefixes each method's
68
+ * `@GetMapping`/`@PostMapping`/… (path or marker) to form a `METHOD /prefix/path` Route that
69
+ * references the method (`Class.method`). (ama-a2r) */
70
+ function javaRoutes(root, rel) {
71
+ const nodes = [];
72
+ const edges = [];
73
+ const annotationsOf = (node) => (node.namedChildren.find((c) => c.type === "modifiers")?.namedChildren ?? []).filter((a) => a.type === "annotation" || a.type === "marker_annotation");
74
+ for (const cls of eachClass(root)) {
75
+ const className = cls.childForFieldName("name")?.text;
76
+ const prefix = annotationsOf(cls).find((a) => a.childForFieldName("name")?.text === "RequestMapping") ??
77
+ null;
78
+ const classPrefix = prefix ? (annotationArg(prefix) ?? "") : "";
79
+ const body = cls.childForFieldName("body");
80
+ for (const member of body?.namedChildren ?? []) {
81
+ if (member.type !== "method_declaration")
82
+ continue;
83
+ const mapping = annotationsOf(member)
84
+ .map((a) => ({
85
+ verb: JAVA_MAPPING_VERBS.get(a.childForFieldName("name")?.text ?? ""),
86
+ ann: a,
87
+ }))
88
+ .find((m) => m.verb);
89
+ if (!mapping?.verb)
90
+ continue;
91
+ const methodName = member.childForFieldName("name")?.text;
92
+ const name = `${mapping.verb} ${joinJavaRoutePath(classPrefix, annotationArg(mapping.ann) ?? "")}`;
93
+ const routeId = symbolId({ file: rel, qualifiedName: name });
94
+ nodes.push({
95
+ id: routeId,
96
+ kind: "Route",
97
+ name,
98
+ file: rel,
99
+ qualifiedName: name,
100
+ tier: "baseline",
101
+ range: { startLine: member.startPosition.row + 1, endLine: member.endPosition.row + 1 },
102
+ });
103
+ if (className && methodName) {
104
+ edges.push({
105
+ from: routeId,
106
+ to: symbolId({ file: rel, qualifiedName: `${className}.${methodName}` }),
107
+ kind: "References",
108
+ provenance: "heuristic",
109
+ });
110
+ }
111
+ }
112
+ }
113
+ return { nodes, edges };
114
+ }
32
115
  /**
33
116
  * Baseline (syntactic) spec for Java. Java gives every kind its own CST node
34
117
  * type — class/interface/enum declarations and methods — so each maps directly
@@ -46,5 +129,6 @@ export const javaSpec = {
46
129
  method_declaration: { kind: "Method" },
47
130
  },
48
131
  resolveImports: javaImports,
132
+ collectRoutes: javaRoutes,
49
133
  };
50
134
  //# sourceMappingURL=java.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"java.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/java.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;+EAI+E;AAC/E,SAAS,kBAAkB,CAAC,WAAmB,EAAE,IAAY;IAC3D,OAAO,YAAY,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;8BAM8B;AAC9B,SAAS,WAAW,CAAC,IAAuB,EAAE,WAAmB;IAC/D,IAAI,IAAI,CAAC,IAAI,KAAK,oBAAoB;QAAE,OAAO,SAAS,CAAC;IACzD,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC,CAAC,kBAAkB;IACxF,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CACjE,CAAC;IACF,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC,CAAC,oDAAoD;IACjF,MAAM,IAAI,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;IACjE,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAiB;IACpC,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,CAAC,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM;IACf,OAAO,EAAE;QACP,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACpC,qBAAqB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QAC5C,gBAAgB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QAClC,kBAAkB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KACvC;IACD,cAAc,EAAE,WAAW;CAC5B,CAAC"}
1
+ {"version":3,"file":"java.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/java.ts"],"names":[],"mappings":"AACA,OAAO,EAAkC,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;+EAI+E;AAC/E,SAAS,kBAAkB,CAAC,WAAmB,EAAE,IAAY;IAC3D,OAAO,YAAY,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;8BAM8B;AAC9B,SAAS,WAAW,CAAC,IAAuB,EAAE,WAAmB;IAC/D,IAAI,IAAI,CAAC,IAAI,KAAK,oBAAoB;QAAE,OAAO,SAAS,CAAC;IACzD,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC,CAAC,kBAAkB;IACxF,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CACjE,CAAC;IACF,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC,CAAC,oDAAoD;IACjF,MAAM,IAAI,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;IACjE,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,kGAAkG;AAClG,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,CAAC,YAAY,EAAE,KAAK,CAAC;IACrB,CAAC,aAAa,EAAE,MAAM,CAAC;IACvB,CAAC,YAAY,EAAE,KAAK,CAAC;IACrB,CAAC,eAAe,EAAE,QAAQ,CAAC;IAC3B,CAAC,cAAc,EAAE,OAAO,CAAC;CAC1B,CAAC,CAAC;AAEH,SAAS,WAAW,CAAC,IAAuB,EAAE,IAAY;IACxD,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACnC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,QAAQ,CAAC,CAAC,SAAS,CAAC,IAAuB;IACzC,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB;QAAE,MAAM,IAAI,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa;QAAE,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,0FAA0F;AAC1F,SAAS,aAAa,CAAC,GAAsB;IAC3C,OAAO,WAAW,CAAC,GAAG,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC;AACnD,CAAC;AAED,4FAA4F;AAC5F,SAAS,iBAAiB,CAAC,MAAc,EAAE,GAAW;IACpD,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpF,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC9B,CAAC;AAED;;wDAEwD;AACxD,SAAS,UAAU,CACjB,IAAuB,EACvB,GAAW;IAEX,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,MAAM,aAAa,GAAG,CAAC,IAAuB,EAAE,EAAE,CAChD,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,MAAM,CAClF,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,mBAAmB,CACjE,CAAC;IACJ,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;QACtD,MAAM,MAAM,GACV,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,IAAI,KAAK,gBAAgB,CAAC;YACtF,IAAI,CAAC;QACP,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,GAAG,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC3C,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,aAAa,IAAI,EAAE,EAAE,CAAC;YAC/C,IAAI,MAAM,CAAC,IAAI,KAAK,oBAAoB;gBAAE,SAAS;YACnD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC;iBAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACX,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;gBACrE,GAAG,EAAE,CAAC;aACP,CAAC,CAAC;iBACF,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,OAAO,EAAE,IAAI;gBAAE,SAAS;YAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;YAC1D,MAAM,IAAI,GAAG,GAAG,OAAO,CAAC,IAAI,IAAI,iBAAiB,CAAC,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACnG,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7D,KAAK,CAAC,IAAI,CAAC;gBACT,EAAE,EAAE,OAAO;gBACX,IAAI,EAAE,OAAO;gBACb,IAAI;gBACJ,IAAI,EAAE,GAAG;gBACT,aAAa,EAAE,IAAI;gBACnB,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,EAAE;aACxF,CAAC,CAAC;YACH,IAAI,SAAS,IAAI,UAAU,EAAE,CAAC;gBAC5B,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE,OAAO;oBACb,EAAE,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,SAAS,IAAI,UAAU,EAAE,EAAE,CAAC;oBACxE,IAAI,EAAE,YAAY;oBAClB,UAAU,EAAE,WAAW;iBACxB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAiB;IACpC,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,CAAC,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM;IACf,OAAO,EAAE;QACP,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACpC,qBAAqB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QAC5C,gBAAgB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QAClC,kBAAkB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KACvC;IACD,cAAc,EAAE,WAAW;IAC3B,aAAa,EAAE,UAAU;CAC1B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"php.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/php.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAqDlD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,YAarB,CAAC"}
1
+ {"version":3,"file":"php.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/php.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA6GlD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,YAcrB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
+ import { symbolId } from "../../graph/index.js";
3
4
  import { nearestConfig, parentDir } from "./config.js";
4
5
  /** Cache for the nearest composer.json's PSR-4 `[prefix, baseDir]` map, by directory. */
5
6
  const composerCache = new Map();
@@ -51,6 +52,60 @@ function phpImports(node, importerRel, root) {
51
52
  const file = [composer.dir, best.base, `${relPath}.php`].filter(Boolean).join("/");
52
53
  return [[file]];
53
54
  }
55
+ /** Laravel `Route` facade HTTP-verb methods — `Route::get('/x', ...)`. (ama-a2r) */
56
+ const PHP_ROUTE_METHODS = new Set(["get", "post", "put", "delete", "patch", "options", "head"]);
57
+ /** Normalize a Laravel route path: `{id}` → `:id`; ensure a leading slash. (ama-a2r) */
58
+ function normalizePhpRoutePath(p) {
59
+ const s = p.replace(/\{([^}]+)\}/g, ":$1");
60
+ return s.startsWith("/") ? s : `/${s}`;
61
+ }
62
+ function firstOfType(node, type) {
63
+ if (node.type === type)
64
+ return node;
65
+ for (const c of node.namedChildren) {
66
+ const found = firstOfType(c, type);
67
+ if (found)
68
+ return found;
69
+ }
70
+ return undefined;
71
+ }
72
+ function* eachScopedCall(node) {
73
+ if (node.type === "scoped_call_expression")
74
+ yield node;
75
+ for (const c of node.namedChildren)
76
+ yield* eachScopedCall(c);
77
+ }
78
+ /** Detect Laravel routes: `Route::<verb>('/path', handler)` — a static call on the `Route`
79
+ * facade with an HTTP-verb method and a string first arg — becomes a `METHOD /path` Route.
80
+ * Scoped to the `Route` facade so unrelated static calls (`Cache::get`) don't match. The
81
+ * handler is usually a controller reference (array/string), not a same-file function, so no
82
+ * handler edge is emitted. (ama-a2r) */
83
+ function phpRoutes(root, rel) {
84
+ const nodes = [];
85
+ for (const call of eachScopedCall(root)) {
86
+ const scope = call.childForFieldName("scope")?.text ?? call.namedChild(0)?.text;
87
+ const method = call.childForFieldName("name")?.text?.toLowerCase();
88
+ if (scope !== "Route" || !method || !PHP_ROUTE_METHODS.has(method))
89
+ continue;
90
+ const firstArg = call
91
+ .childForFieldName("arguments")
92
+ ?.namedChildren.find((c) => c.type === "argument");
93
+ const raw = firstArg && firstOfType(firstArg, "string_content")?.text;
94
+ if (!raw)
95
+ continue;
96
+ const name = `${method.toUpperCase()} ${normalizePhpRoutePath(raw)}`;
97
+ nodes.push({
98
+ id: symbolId({ file: rel, qualifiedName: name }),
99
+ kind: "Route",
100
+ name,
101
+ file: rel,
102
+ qualifiedName: name,
103
+ tier: "baseline",
104
+ range: { startLine: call.startPosition.row + 1, endLine: call.endPosition.row + 1 },
105
+ });
106
+ }
107
+ return { nodes, edges: [] };
108
+ }
54
109
  /**
55
110
  * Baseline (syntactic) spec for PHP. Each top-level construct has its own CST
56
111
  * node type — class/interface/trait/enum declarations, free functions, and
@@ -72,5 +127,6 @@ export const phpSpec = {
72
127
  method_declaration: { kind: "Method" },
73
128
  },
74
129
  resolveImports: phpImports,
130
+ collectRoutes: phpRoutes,
75
131
  };
76
132
  //# sourceMappingURL=php.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"php.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/php.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"php.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/php.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/python.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAwClD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,YASxB,CAAC"}
1
+ {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/python.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAqSlD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,YAWxB,CAAC"}