gitnexus 1.6.3-rc.25 → 1.6.3-rc.27

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.
@@ -1,27 +1,71 @@
1
1
  import PHP from 'tree-sitter-php';
2
2
  import { compilePatterns, runCompiledPatterns, unquoteLiteral, } from '../tree-sitter-scanner.js';
3
3
  /**
4
- * PHP HTTP plugin — Laravel `Route::get/post/...` declarations.
4
+ * PHP HTTP plugin.
5
+ *
6
+ * Providers:
7
+ * - Laravel `Route::get/post/...`
8
+ *
9
+ * Consumers (string-literal URLs only):
10
+ * - Laravel HTTP client: `Http::get/post/put/delete/patch($url)`
11
+ * - Guzzle / generic object method: `$client->get/post/...($url)`
12
+ * - `file_get_contents($url)`
5
13
  *
6
14
  * The pipeline already uses `PHP.php_only` for ingesting plain `.php`
7
15
  * files (see `core/tree-sitter/parser-loader.ts`), and we do the same
8
16
  * here so Laravel route files are parsed with the right grammar dialect.
17
+ *
18
+ * Scope notes: consumer patterns match string literals only. URLs built
19
+ * via binary concatenation (`$base . '/path'`), `sprintf`, or config
20
+ * lookup (`config('services.foo.base').'/path'`) are intentionally left
21
+ * for a follow-up — they require constant-folding the surrounding
22
+ * scope to be meaningful.
9
23
  */
10
- const LARAVEL_PATTERNS = compilePatterns({
11
- name: 'php-laravel',
24
+ const LARAVEL_ROUTE_SPEC = {
25
+ meta: {},
26
+ query: `
27
+ (scoped_call_expression
28
+ scope: (name) @scope (#eq? @scope "Route")
29
+ name: (name) @method (#match? @method "^(get|post|put|delete|patch)$")
30
+ arguments: (arguments . (argument (string) @path)))
31
+ `,
32
+ };
33
+ const HTTP_FACADE_SPEC = {
34
+ meta: {},
35
+ query: `
36
+ (scoped_call_expression
37
+ scope: (name) @scope (#eq? @scope "Http")
38
+ name: (name) @method (#match? @method "^(get|post|put|delete|patch)$")
39
+ arguments: (arguments . (argument (string) @path)))
40
+ `,
41
+ };
42
+ const GUZZLE_MEMBER_SPEC = {
43
+ meta: {},
44
+ query: `
45
+ (member_call_expression
46
+ name: (name) @method (#match? @method "^(get|post|put|delete|patch)$")
47
+ arguments: (arguments . (argument (string) @path)))
48
+ `,
49
+ };
50
+ const FILE_GET_CONTENTS_SPEC = {
51
+ meta: {},
52
+ query: `
53
+ (function_call_expression
54
+ function: (name) @fn (#eq? @fn "file_get_contents")
55
+ arguments: (arguments . (argument (string) @path)))
56
+ `,
57
+ };
58
+ const mk = (spec, suffix) => compilePatterns({
59
+ name: `php-${suffix}`,
12
60
  language: PHP.php_only,
13
- patterns: [
14
- {
15
- meta: {},
16
- query: `
17
- (scoped_call_expression
18
- scope: (name) @scope (#eq? @scope "Route")
19
- name: (name) @method (#match? @method "^(get|post|put|delete|patch)$")
20
- arguments: (arguments . (argument (string) @path)))
21
- `,
22
- },
23
- ],
61
+ patterns: [spec],
24
62
  });
63
+ const PHP_PATTERNS = {
64
+ laravelRoute: mk(LARAVEL_ROUTE_SPEC, 'laravel-route'),
65
+ httpFacade: mk(HTTP_FACADE_SPEC, 'http-facade'),
66
+ guzzleMember: mk(GUZZLE_MEMBER_SPEC, 'guzzle-member'),
67
+ fileGetContents: mk(FILE_GET_CONTENTS_SPEC, 'file-get-contents'),
68
+ };
25
69
  /**
26
70
  * Extract the inner text of a PHP `string` node. The tree-sitter-php
27
71
  * grammar wraps single / double-quoted literals differently depending
@@ -30,12 +74,9 @@ const LARAVEL_PATTERNS = compilePatterns({
30
74
  * child nodes.
31
75
  */
32
76
  function phpStringText(node) {
33
- // Most single-quoted strings expose their inner content through the
34
- // full node text (including quotes), which unquoteLiteral strips.
35
77
  const direct = unquoteLiteral(node.text);
36
78
  if (direct !== null && direct !== node.text)
37
79
  return direct;
38
- // Fall back to child string_content / string_value node if present.
39
80
  for (const child of node.children) {
40
81
  if (child.type === 'string_content' || child.type === 'string_value') {
41
82
  return child.text;
@@ -43,12 +84,29 @@ function phpStringText(node) {
43
84
  }
44
85
  return direct;
45
86
  }
87
+ /**
88
+ * HTTP client helpers (`Http::`, Guzzle) are almost always called with
89
+ * a path relative to a configured base URL, or a full URL. File paths
90
+ * are rare. Accept both relative (`/api/...`) and absolute (`http(s)://`).
91
+ */
92
+ function isHttpClientPath(path) {
93
+ return path.startsWith('/') || path.startsWith('http://') || path.startsWith('https://');
94
+ }
95
+ /**
96
+ * `file_get_contents` is used for both HTTP and filesystem reads. Only
97
+ * emit a consumer contract when the URL is an absolute HTTP(S) URL to
98
+ * avoid false positives for local file paths and stream wrappers
99
+ * (`php://input`, `file://`, `data:`, ...).
100
+ */
101
+ function isHttpUrlLiteral(path) {
102
+ return path.startsWith('http://') || path.startsWith('https://');
103
+ }
46
104
  export const PHP_HTTP_PLUGIN = {
47
105
  name: 'php-http',
48
106
  language: PHP.php_only,
49
107
  scan(tree) {
50
108
  const out = [];
51
- for (const match of runCompiledPatterns(LARAVEL_PATTERNS, tree)) {
109
+ for (const match of runCompiledPatterns(PHP_PATTERNS.laravelRoute, tree)) {
52
110
  const methodNode = match.captures.method;
53
111
  const pathNode = match.captures.path;
54
112
  if (!methodNode || !pathNode)
@@ -65,6 +123,56 @@ export const PHP_HTTP_PLUGIN = {
65
123
  confidence: 0.8,
66
124
  });
67
125
  }
126
+ for (const match of runCompiledPatterns(PHP_PATTERNS.httpFacade, tree)) {
127
+ const methodNode = match.captures.method;
128
+ const pathNode = match.captures.path;
129
+ if (!methodNode || !pathNode)
130
+ continue;
131
+ const path = phpStringText(pathNode);
132
+ if (path === null || !isHttpClientPath(path))
133
+ continue;
134
+ out.push({
135
+ role: 'consumer',
136
+ framework: 'laravel-http',
137
+ method: methodNode.text.toUpperCase(),
138
+ path,
139
+ name: null,
140
+ confidence: 0.7,
141
+ });
142
+ }
143
+ for (const match of runCompiledPatterns(PHP_PATTERNS.guzzleMember, tree)) {
144
+ const methodNode = match.captures.method;
145
+ const pathNode = match.captures.path;
146
+ if (!methodNode || !pathNode)
147
+ continue;
148
+ const path = phpStringText(pathNode);
149
+ if (path === null || !isHttpClientPath(path))
150
+ continue;
151
+ out.push({
152
+ role: 'consumer',
153
+ framework: 'guzzle',
154
+ method: methodNode.text.toUpperCase(),
155
+ path,
156
+ name: null,
157
+ confidence: 0.7,
158
+ });
159
+ }
160
+ for (const match of runCompiledPatterns(PHP_PATTERNS.fileGetContents, tree)) {
161
+ const pathNode = match.captures.path;
162
+ if (!pathNode)
163
+ continue;
164
+ const path = phpStringText(pathNode);
165
+ if (path === null || !isHttpUrlLiteral(path))
166
+ continue;
167
+ out.push({
168
+ role: 'consumer',
169
+ framework: 'file-get-contents',
170
+ method: 'GET',
171
+ path,
172
+ name: null,
173
+ confidence: 0.7,
174
+ });
175
+ }
68
176
  return out;
69
177
  },
70
178
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.3-rc.25",
3
+ "version": "1.6.3-rc.27",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",