projscan 1.0.0 → 1.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.
Files changed (32) hide show
  1. package/README.md +18 -3
  2. package/dist/core/fixSuggest.js +50 -0
  3. package/dist/core/fixSuggest.js.map +1 -1
  4. package/dist/core/languages/LanguageAdapter.d.ts +1 -1
  5. package/dist/core/languages/registry.js +2 -1
  6. package/dist/core/languages/registry.js.map +1 -1
  7. package/dist/core/languages/rustAdapter.d.ts +2 -0
  8. package/dist/core/languages/rustAdapter.js +165 -0
  9. package/dist/core/languages/rustAdapter.js.map +1 -0
  10. package/dist/core/languages/rustCallSites.d.ts +17 -0
  11. package/dist/core/languages/rustCallSites.js +60 -0
  12. package/dist/core/languages/rustCallSites.js.map +1 -0
  13. package/dist/core/languages/rustCyclomatic.d.ts +24 -0
  14. package/dist/core/languages/rustCyclomatic.js +67 -0
  15. package/dist/core/languages/rustCyclomatic.js.map +1 -0
  16. package/dist/core/languages/rustExports.d.ts +25 -0
  17. package/dist/core/languages/rustExports.js +74 -0
  18. package/dist/core/languages/rustExports.js.map +1 -0
  19. package/dist/core/languages/rustFunctions.d.ts +27 -0
  20. package/dist/core/languages/rustFunctions.js +131 -0
  21. package/dist/core/languages/rustFunctions.js.map +1 -0
  22. package/dist/core/languages/rustImports.d.ts +31 -0
  23. package/dist/core/languages/rustImports.js +196 -0
  24. package/dist/core/languages/rustImports.js.map +1 -0
  25. package/dist/core/languages/rustManifests.d.ts +26 -0
  26. package/dist/core/languages/rustManifests.js +99 -0
  27. package/dist/core/languages/rustManifests.js.map +1 -0
  28. package/dist/core/languages/treeSitterLoader.js +2 -1
  29. package/dist/core/languages/treeSitterLoader.js.map +1 -1
  30. package/dist/grammars/tree-sitter-rust.wasm +0 -0
  31. package/dist/tool-manifest.json +2 -2
  32. package/package.json +4 -2
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Top-level Rust items that may carry a `pub` visibility modifier and are
3
+ * worth exposing as exports. Items are private by default; only `pub` items
4
+ * are exports.
5
+ */
6
+ const EXPORT_NODE_TO_KIND = {
7
+ function_item: 'function',
8
+ function_signature_item: 'function',
9
+ struct_item: 'class',
10
+ union_item: 'class',
11
+ enum_item: 'enum',
12
+ trait_item: 'interface',
13
+ type_item: 'type',
14
+ const_item: 'variable',
15
+ static_item: 'variable',
16
+ mod_item: 'unknown',
17
+ };
18
+ /**
19
+ * Extract public top-level items from a tree-sitter-rust AST. We descend
20
+ * into `mod foo { ... }` blocks because `pub fn` declared inside an inline
21
+ * module is still part of the crate's surface; the qualified name reported
22
+ * is the bare item name (the module is captured separately as its own
23
+ * export).
24
+ *
25
+ * Visibility detection: any direct child of type `visibility_modifier`
26
+ * (which includes `pub`, `pub(crate)`, `pub(super)`, `pub(in path::to)`)
27
+ * counts as exported. We do NOT distinguish between `pub` and `pub(crate)`
28
+ * here — both are public to the crate's consumers in the graph sense.
29
+ */
30
+ export function extractRustExports(root) {
31
+ const exports = [];
32
+ walk(root, (n) => {
33
+ const kind = EXPORT_NODE_TO_KIND[n.type];
34
+ if (!kind)
35
+ return;
36
+ if (!hasPublicVisibility(n))
37
+ return;
38
+ const name = nameOf(n);
39
+ if (!name)
40
+ return;
41
+ exports.push({
42
+ name,
43
+ kind,
44
+ typeOnly: false,
45
+ line: n.startPosition.row + 1,
46
+ });
47
+ });
48
+ return exports;
49
+ }
50
+ function hasPublicVisibility(node) {
51
+ for (const c of node.namedChildren) {
52
+ if (c.type === 'visibility_modifier')
53
+ return true;
54
+ }
55
+ return false;
56
+ }
57
+ function nameOf(node) {
58
+ if (node.childForFieldName) {
59
+ const id = node.childForFieldName('name');
60
+ if (id)
61
+ return id.text;
62
+ }
63
+ for (const c of node.namedChildren) {
64
+ if (c.type === 'identifier' || c.type === 'type_identifier')
65
+ return c.text;
66
+ }
67
+ return null;
68
+ }
69
+ function walk(node, visit) {
70
+ visit(node);
71
+ for (const child of node.namedChildren)
72
+ walk(child, visit);
73
+ }
74
+ //# sourceMappingURL=rustExports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rustExports.js","sourceRoot":"","sources":["../../../src/core/languages/rustExports.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,MAAM,mBAAmB,GAA+B;IACtD,aAAa,EAAE,UAAU;IACzB,uBAAuB,EAAE,UAAU;IACnC,WAAW,EAAE,OAAO;IACpB,UAAU,EAAE,OAAO;IACnB,SAAS,EAAE,MAAM;IACjB,UAAU,EAAE,WAAW;IACvB,SAAS,EAAE,MAAM;IACjB,UAAU,EAAE,UAAU;IACtB,WAAW,EAAE,UAAU;IACvB,QAAQ,EAAE,SAAS;CACpB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;QACf,MAAM,IAAI,GAAG,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;YAAE,OAAO;QACpC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,OAAO,CAAC,IAAI,CAAC;YACX,IAAI;YACJ,IAAI;YACJ,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,IAAI,KAAK,qBAAqB;YAAE,OAAO,IAAI,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,MAAM,CAAC,IAAY;IAC1B,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC,IAAI,CAAC;IACzB,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,iBAAiB;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC;IAC7E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,KAA0B;IACpD,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa;QAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { FunctionInfo } from '../ast.js';
2
+ interface TsNode {
3
+ type: string;
4
+ text: string;
5
+ startPosition: {
6
+ row: number;
7
+ column: number;
8
+ };
9
+ endPosition: {
10
+ row: number;
11
+ column: number;
12
+ };
13
+ namedChildren: TsNode[];
14
+ childForFieldName?: (name: string) => TsNode | null;
15
+ }
16
+ /**
17
+ * Per-function McCabe CC for Rust. Walks `function_item` nodes (free
18
+ * functions and trait/impl methods). Methods inside `impl SomeType { fn m() }`
19
+ * are named `SomeType.m`; trait methods inside `trait Foo { fn bar() }` are
20
+ * named `Foo.bar`. Free functions stay bare (`do_it`).
21
+ *
22
+ * Closures and async blocks are NOT extracted as separate functions in 1.1
23
+ * (analogous to Go func literals); their decision points fold into the
24
+ * enclosing function.
25
+ */
26
+ export declare function extractRustFunctions(root: TsNode): FunctionInfo[];
27
+ export {};
@@ -0,0 +1,131 @@
1
+ const RUST_DECISION_NODES = new Set([
2
+ 'if_expression',
3
+ 'for_expression',
4
+ 'while_expression',
5
+ 'loop_expression',
6
+ 'try_expression',
7
+ ]);
8
+ /**
9
+ * Per-function McCabe CC for Rust. Walks `function_item` nodes (free
10
+ * functions and trait/impl methods). Methods inside `impl SomeType { fn m() }`
11
+ * are named `SomeType.m`; trait methods inside `trait Foo { fn bar() }` are
12
+ * named `Foo.bar`. Free functions stay bare (`do_it`).
13
+ *
14
+ * Closures and async blocks are NOT extracted as separate functions in 1.1
15
+ * (analogous to Go func literals); their decision points fold into the
16
+ * enclosing function.
17
+ */
18
+ export function extractRustFunctions(root) {
19
+ const out = [];
20
+ walk(root, null, out);
21
+ return out;
22
+ }
23
+ function walk(node, ownerName, out) {
24
+ // `impl SomeType { … }` and `impl Trait for SomeType { … }` — methods inside
25
+ // are scoped by the impl's type.
26
+ if (node.type === 'impl_item') {
27
+ const type = node.childForFieldName ? node.childForFieldName('type') : null;
28
+ const name = type?.text ?? ownerName;
29
+ const body = node.childForFieldName ? node.childForFieldName('body') : null;
30
+ if (body) {
31
+ for (const child of body.namedChildren)
32
+ walk(child, name, out);
33
+ }
34
+ return;
35
+ }
36
+ // `trait Foo { fn bar() }` — methods inside scope by the trait name.
37
+ if (node.type === 'trait_item') {
38
+ const tname = node.childForFieldName ? node.childForFieldName('name') : null;
39
+ const traitName = tname?.text ?? ownerName;
40
+ const body = node.childForFieldName ? node.childForFieldName('body') : null;
41
+ if (body) {
42
+ for (const child of body.namedChildren)
43
+ walk(child, traitName, out);
44
+ }
45
+ return;
46
+ }
47
+ // `mod foo { … }` — keep the same ownerName but recurse so nested fns
48
+ // outside an impl/trait still get extracted.
49
+ if (node.type === 'mod_item') {
50
+ const body = node.childForFieldName ? node.childForFieldName('body') : null;
51
+ if (body) {
52
+ for (const child of body.namedChildren)
53
+ walk(child, ownerName, out);
54
+ }
55
+ return;
56
+ }
57
+ if (node.type === 'function_item' || node.type === 'function_signature_item') {
58
+ const nameNode = node.childForFieldName ? node.childForFieldName('name') : findChild(node, 'identifier');
59
+ const baseName = nameNode?.text ?? '<anonymous>';
60
+ const fnName = ownerName ? `${ownerName}.${baseName}` : baseName;
61
+ const line = node.startPosition.row + 1;
62
+ const endLine = node.endPosition.row + 1;
63
+ const cc = countDecisions(node);
64
+ out.push({ name: fnName, line, endLine, cyclomaticComplexity: cc });
65
+ return;
66
+ }
67
+ for (const child of node.namedChildren)
68
+ walk(child, ownerName, out);
69
+ }
70
+ function countDecisions(fnNode) {
71
+ let count = 0;
72
+ const body = fnNode.childForFieldName ? fnNode.childForFieldName('body') : null;
73
+ if (!body)
74
+ return 1;
75
+ walkSkipNested(body, (n) => {
76
+ if (RUST_DECISION_NODES.has(n.type)) {
77
+ count++;
78
+ return;
79
+ }
80
+ if (n.type === 'match_arm') {
81
+ // Mirror the file-level rust cyclomatic check: skip the `_ =>` arm
82
+ // (wrapped in `match_pattern` with `_` as anonymous content), count
83
+ // any other arm.
84
+ const arm = n.namedChildren[0];
85
+ if (!arm) {
86
+ count++;
87
+ return;
88
+ }
89
+ if (arm.type === 'wildcard_pattern')
90
+ return;
91
+ if (arm.type === 'match_pattern') {
92
+ const inner = arm.namedChildren[0];
93
+ if (!inner) {
94
+ if (arm.text.trim() === '_')
95
+ return;
96
+ count++;
97
+ return;
98
+ }
99
+ if (inner.type === 'wildcard_pattern')
100
+ return;
101
+ }
102
+ count++;
103
+ return;
104
+ }
105
+ if (n.type === 'binary_expression' && /(\s|^)(\|\||&&)(\s|$)/.test(n.text)) {
106
+ count++;
107
+ }
108
+ });
109
+ return count + 1;
110
+ }
111
+ function walkSkipNested(node, visit) {
112
+ visit(node);
113
+ for (const child of node.namedChildren) {
114
+ if (child.type === 'function_item' ||
115
+ child.type === 'function_signature_item' ||
116
+ child.type === 'closure_expression') {
117
+ // Skip: nested fns and closures emit their own entries (or, in the case
118
+ // of closures, fold into the parent — but their decision points should
119
+ // not double-count into the parent's CC).
120
+ continue;
121
+ }
122
+ walkSkipNested(child, visit);
123
+ }
124
+ }
125
+ function findChild(node, type) {
126
+ for (const c of node.namedChildren)
127
+ if (c.type === type)
128
+ return c;
129
+ return null;
130
+ }
131
+ //# sourceMappingURL=rustFunctions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rustFunctions.js","sourceRoot":"","sources":["../../../src/core/languages/rustFunctions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { AstImport } from '../ast.js';
2
+ interface TsNode {
3
+ type: string;
4
+ text: string;
5
+ startPosition: {
6
+ row: number;
7
+ column: number;
8
+ };
9
+ namedChildren: TsNode[];
10
+ childForFieldName?: (name: string) => TsNode | null;
11
+ }
12
+ /**
13
+ * Extract Rust `use` statements from a tree-sitter-rust AST.
14
+ *
15
+ * Handled forms:
16
+ * use foo::bar; → source = "foo::bar"
17
+ * use foo::bar::Baz; → source = "foo::bar::Baz"
18
+ * use foo::bar as baz; → source = "foo::bar", specifier = "baz"
19
+ * use foo::{bar, baz}; → two imports, sources "foo::bar" and "foo::baz"
20
+ * use foo::{bar::Baz, qux::*}; → emits each leaf path
21
+ * use crate::foo::bar; → source = "crate::foo::bar"
22
+ * use self::foo; → source = "self::foo"
23
+ * use super::foo; → source = "super::foo"
24
+ * pub use foo::bar; → re-export, kind = 'reexport'
25
+ *
26
+ * NOT handled (acceptable for graph-construction purposes):
27
+ * - Macro-imported items (`#[macro_use] extern crate ...`)
28
+ * - `extern crate` declarations (legacy Rust 2015 syntax)
29
+ */
30
+ export declare function extractRustImports(root: TsNode): AstImport[];
31
+ export {};
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Extract Rust `use` statements from a tree-sitter-rust AST.
3
+ *
4
+ * Handled forms:
5
+ * use foo::bar; → source = "foo::bar"
6
+ * use foo::bar::Baz; → source = "foo::bar::Baz"
7
+ * use foo::bar as baz; → source = "foo::bar", specifier = "baz"
8
+ * use foo::{bar, baz}; → two imports, sources "foo::bar" and "foo::baz"
9
+ * use foo::{bar::Baz, qux::*}; → emits each leaf path
10
+ * use crate::foo::bar; → source = "crate::foo::bar"
11
+ * use self::foo; → source = "self::foo"
12
+ * use super::foo; → source = "super::foo"
13
+ * pub use foo::bar; → re-export, kind = 'reexport'
14
+ *
15
+ * NOT handled (acceptable for graph-construction purposes):
16
+ * - Macro-imported items (`#[macro_use] extern crate ...`)
17
+ * - `extern crate` declarations (legacy Rust 2015 syntax)
18
+ */
19
+ export function extractRustImports(root) {
20
+ const imports = [];
21
+ walk(root, (n) => {
22
+ if (n.type !== 'use_declaration')
23
+ return;
24
+ const isReexport = hasPublicVisibility(n);
25
+ const argNode = pickUseArgument(n);
26
+ if (!argNode)
27
+ return;
28
+ expandUsePath(argNode, [], (source, alias) => {
29
+ imports.push({
30
+ source,
31
+ kind: isReexport ? 'reexport' : 'static',
32
+ specifiers: alias ? [alias] : [],
33
+ typeOnly: false,
34
+ line: n.startPosition.row + 1,
35
+ });
36
+ });
37
+ });
38
+ return imports;
39
+ }
40
+ function hasPublicVisibility(node) {
41
+ for (const c of node.namedChildren) {
42
+ if (c.type === 'visibility_modifier')
43
+ return true;
44
+ }
45
+ return false;
46
+ }
47
+ /**
48
+ * `use_declaration` wraps a path expression. tree-sitter-rust may use
49
+ * `argument` as the field name; if not we fall back to the first non-trivia
50
+ * named child that looks like a path or `use_*` form.
51
+ */
52
+ function pickUseArgument(use) {
53
+ if (use.childForFieldName) {
54
+ const arg = use.childForFieldName('argument');
55
+ if (arg)
56
+ return arg;
57
+ }
58
+ for (const c of use.namedChildren) {
59
+ if (c.type === 'visibility_modifier')
60
+ continue;
61
+ if (c.type === 'scoped_identifier' ||
62
+ c.type === 'scoped_use_list' ||
63
+ c.type === 'use_list' ||
64
+ c.type === 'use_as_clause' ||
65
+ c.type === 'use_wildcard' ||
66
+ c.type === 'identifier' ||
67
+ c.type === 'crate' ||
68
+ c.type === 'self') {
69
+ return c;
70
+ }
71
+ }
72
+ return null;
73
+ }
74
+ /**
75
+ * Walk a use-path subtree and emit one `(source, alias?)` pair per leaf.
76
+ * `prefix` accumulates the `::`-separated segments already consumed on the
77
+ * way down. Each leaf calls `emit(source, alias?)`.
78
+ */
79
+ function expandUsePath(node, prefix, emit) {
80
+ switch (node.type) {
81
+ case 'scoped_use_list': {
82
+ // `foo::bar::{...}` — left side is the path prefix, right side is the brace list.
83
+ let path = node.childForFieldName ? node.childForFieldName('path') : null;
84
+ let list = node.childForFieldName ? node.childForFieldName('list') : null;
85
+ if (!path && !list) {
86
+ // Fields not available on this grammar version — walk children:
87
+ // first non-list child is the prefix, the use_list child is the list.
88
+ for (const c of node.namedChildren) {
89
+ if (c.type === 'use_list' && !list)
90
+ list = c;
91
+ else if (!path)
92
+ path = c;
93
+ }
94
+ }
95
+ const newPrefix = [...prefix];
96
+ if (path)
97
+ collectPathSegments(path, newPrefix);
98
+ if (list) {
99
+ for (const child of list.namedChildren) {
100
+ expandUsePath(child, newPrefix, emit);
101
+ }
102
+ }
103
+ return;
104
+ }
105
+ case 'use_list': {
106
+ // Bare `{a, b, c}` (uncommon at top level; usually wrapped in scoped_use_list).
107
+ for (const child of node.namedChildren) {
108
+ expandUsePath(child, prefix, emit);
109
+ }
110
+ return;
111
+ }
112
+ case 'use_as_clause': {
113
+ // `foo::bar as baz`
114
+ let pathNode = node.childForFieldName ? node.childForFieldName('path') : null;
115
+ let aliasNode = node.childForFieldName ? node.childForFieldName('alias') : null;
116
+ if (!pathNode || !aliasNode) {
117
+ // First non-trivia child is the path; the second (or last) is the alias.
118
+ const named = node.namedChildren;
119
+ if (named.length >= 2) {
120
+ if (!pathNode)
121
+ pathNode = named[0];
122
+ if (!aliasNode)
123
+ aliasNode = named[named.length - 1];
124
+ }
125
+ }
126
+ const segs = [...prefix];
127
+ if (pathNode)
128
+ collectPathSegments(pathNode, segs);
129
+ emit(segs.join('::'), aliasNode?.text);
130
+ return;
131
+ }
132
+ case 'use_wildcard': {
133
+ // `foo::*`
134
+ // The wildcard form has the path as a child (scoped_identifier or identifier).
135
+ const segs = [...prefix];
136
+ for (const c of node.namedChildren)
137
+ collectPathSegments(c, segs);
138
+ segs.push('*');
139
+ emit(segs.join('::'));
140
+ return;
141
+ }
142
+ case 'scoped_identifier':
143
+ case 'identifier':
144
+ case 'crate':
145
+ case 'self':
146
+ case 'super': {
147
+ const segs = [...prefix];
148
+ collectPathSegments(node, segs);
149
+ emit(segs.join('::'));
150
+ return;
151
+ }
152
+ default: {
153
+ // Unknown wrapper - try to descend.
154
+ for (const c of node.namedChildren)
155
+ expandUsePath(c, prefix, emit);
156
+ }
157
+ }
158
+ }
159
+ /** Append the `::`-separated segments of a path expression to `out`. */
160
+ function collectPathSegments(node, out) {
161
+ if (node.type === 'identifier' ||
162
+ node.type === 'type_identifier' ||
163
+ node.type === 'crate' ||
164
+ node.type === 'self' ||
165
+ node.type === 'super') {
166
+ out.push(node.text);
167
+ return;
168
+ }
169
+ if (node.type === 'scoped_identifier') {
170
+ // tree-sitter-rust may or may not expose `path`/`name` as fields depending
171
+ // on version. Try fields first; if neither is set, walk all named children.
172
+ const path = node.childForFieldName ? node.childForFieldName('path') : null;
173
+ const name = node.childForFieldName ? node.childForFieldName('name') : null;
174
+ if (path || name) {
175
+ if (path)
176
+ collectPathSegments(path, out);
177
+ if (name)
178
+ collectPathSegments(name, out);
179
+ return;
180
+ }
181
+ for (const c of node.namedChildren)
182
+ collectPathSegments(c, out);
183
+ return;
184
+ }
185
+ // Fallback: text-split (rare path types).
186
+ const text = node.text.replace(/\s+/g, '');
187
+ for (const seg of text.split('::'))
188
+ if (seg)
189
+ out.push(seg);
190
+ }
191
+ function walk(node, visit) {
192
+ visit(node);
193
+ for (const child of node.namedChildren)
194
+ walk(child, visit);
195
+ }
196
+ //# sourceMappingURL=rustImports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rustImports.js","sourceRoot":"","sources":["../../../src/core/languages/rustImports.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { FileEntry } from '../../types.js';
2
+ export interface RustProjectInfo {
3
+ /**
4
+ * Crate name from `[package] name = "..."` in Cargo.toml. Local imports
5
+ * starting with this name (or `crate::`, `self::`, `super::`) resolve into
6
+ * the repo. For workspace members, this is the member's own crate name.
7
+ */
8
+ crateName: string;
9
+ /** Absolute directory containing Cargo.toml. Imports resolve relative to its `src/`. */
10
+ crateRoot: string;
11
+ /** When the manifest is `[workspace]`, the relative paths of member crates. Empty for single-crate. */
12
+ workspaceMembers: string[];
13
+ }
14
+ /**
15
+ * Find the closest Cargo.toml and read the crate name. Mirrors goManifests
16
+ * shape: tries repo root first, then walks up from any directory containing
17
+ * a `.rs` file. Returns null when no Cargo.toml exists; .rs files outside
18
+ * any crate are valid (snippets, build-script outputs) but their `use`
19
+ * imports can't be resolved to local files.
20
+ *
21
+ * Workspace handling: a `[workspace]`-only Cargo.toml has no `[package]`
22
+ * name. We surface that as `crateName = ""` plus a populated
23
+ * `workspaceMembers` so the adapter can route imports against each member's
24
+ * own Cargo.toml as needed.
25
+ */
26
+ export declare function detectRustProject(rootPath: string, files: FileEntry[]): Promise<RustProjectInfo | null>;
@@ -0,0 +1,99 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ /**
4
+ * Find the closest Cargo.toml and read the crate name. Mirrors goManifests
5
+ * shape: tries repo root first, then walks up from any directory containing
6
+ * a `.rs` file. Returns null when no Cargo.toml exists; .rs files outside
7
+ * any crate are valid (snippets, build-script outputs) but their `use`
8
+ * imports can't be resolved to local files.
9
+ *
10
+ * Workspace handling: a `[workspace]`-only Cargo.toml has no `[package]`
11
+ * name. We surface that as `crateName = ""` plus a populated
12
+ * `workspaceMembers` so the adapter can route imports against each member's
13
+ * own Cargo.toml as needed.
14
+ */
15
+ export async function detectRustProject(rootPath, files) {
16
+ // 1) Try repo root.
17
+ const rootCargo = await readCargo(path.join(rootPath, 'Cargo.toml'));
18
+ if (rootCargo) {
19
+ return {
20
+ crateName: rootCargo.name ?? '',
21
+ crateRoot: rootPath,
22
+ workspaceMembers: rootCargo.workspaceMembers,
23
+ };
24
+ }
25
+ // 2) Walk up from .rs file directories to find any Cargo.toml.
26
+ const candidates = new Set();
27
+ for (const f of files) {
28
+ if (!f.relativePath.endsWith('.rs'))
29
+ continue;
30
+ let dir = path.posix.dirname(f.relativePath);
31
+ while (dir && dir !== '.' && dir !== '/') {
32
+ candidates.add(dir);
33
+ dir = path.posix.dirname(dir);
34
+ }
35
+ }
36
+ const sorted = [...candidates].sort((a, b) => a.length - b.length);
37
+ for (const dir of sorted) {
38
+ const cargo = await readCargo(path.join(rootPath, dir, 'Cargo.toml'));
39
+ if (cargo) {
40
+ return {
41
+ crateName: cargo.name ?? '',
42
+ crateRoot: path.join(rootPath, dir),
43
+ workspaceMembers: cargo.workspaceMembers,
44
+ };
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+ async function readCargo(absPath) {
50
+ let content;
51
+ try {
52
+ content = await fs.readFile(absPath, 'utf-8');
53
+ }
54
+ catch {
55
+ return null;
56
+ }
57
+ // Tiny TOML reader: scan section headers and a few keys. Cargo.toml is
58
+ // small and structurally simple; we don't need a full TOML parser.
59
+ let section = '';
60
+ let name = null;
61
+ const workspaceMembers = [];
62
+ let inMembersArray = false;
63
+ for (const raw of content.split('\n')) {
64
+ const line = raw.replace(/#.*$/, '').trim();
65
+ if (!line)
66
+ continue;
67
+ const sec = /^\[([^\]]+)\]$/.exec(line);
68
+ if (sec) {
69
+ section = sec[1].trim();
70
+ inMembersArray = false;
71
+ continue;
72
+ }
73
+ if (section === 'package' && /^name\s*=/.test(line)) {
74
+ const m = /^name\s*=\s*"([^"]+)"/.exec(line);
75
+ if (m)
76
+ name = m[1];
77
+ }
78
+ if (section === 'workspace') {
79
+ // members = [ "crate-a", "crate-b", ... ] OR members = [ \n "..." \n ]
80
+ if (/^members\s*=\s*\[/.test(line)) {
81
+ inMembersArray = !line.includes(']');
82
+ const inline = /\[([^\]]*)\]/.exec(line);
83
+ if (inline) {
84
+ for (const m of inline[1].matchAll(/"([^"]+)"/g))
85
+ workspaceMembers.push(m[1]);
86
+ }
87
+ continue;
88
+ }
89
+ if (inMembersArray) {
90
+ for (const m of line.matchAll(/"([^"]+)"/g))
91
+ workspaceMembers.push(m[1]);
92
+ if (line.includes(']'))
93
+ inMembersArray = false;
94
+ }
95
+ }
96
+ }
97
+ return { name, workspaceMembers };
98
+ }
99
+ //# sourceMappingURL=rustManifests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rustManifests.js","sourceRoot":"","sources":["../../../src/core/languages/rustManifests.ts"],"names":[],"mappings":"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"}
@@ -25,7 +25,8 @@ function grammarDirs() {
25
25
  const nodeModulesGo = path.join(repoRoot, 'node_modules', 'tree-sitter-go');
26
26
  const nodeModulesJava = path.join(repoRoot, 'node_modules', 'tree-sitter-java');
27
27
  const nodeModulesRuby = path.join(repoRoot, 'node_modules', 'tree-sitter-ruby');
28
- return [distDir, nodeModulesWebTs, nodeModulesPy, nodeModulesGo, nodeModulesJava, nodeModulesRuby];
28
+ const nodeModulesRust = path.join(repoRoot, 'node_modules', 'tree-sitter-rust');
29
+ return [distDir, nodeModulesWebTs, nodeModulesPy, nodeModulesGo, nodeModulesJava, nodeModulesRuby, nodeModulesRust];
29
30
  }
30
31
  function findWasm(filename) {
31
32
  for (const dir of grammarDirs()) {
@@ -1 +1 @@
1
- {"version":3,"file":"treeSitterLoader.js","sourceRoot":"","sources":["../../../src/core/languages/treeSitterLoader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"treeSitterLoader.js","sourceRoot":"","sources":["../../../src/core/languages/treeSitterLoader.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "projscan",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "mcpProtocolVersion": "2025-03-26",
5
- "generatedAt": "2026-05-04T15:48:46.404Z",
5
+ "generatedAt": "2026-05-04T18:40:38.688Z",
6
6
  "toolCount": 20,
7
7
  "tools": [
8
8
  {