autonomous-flow-daemon 1.6.0 → 1.9.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/CHANGELOG.md +85 -85
- package/LICENSE +21 -21
- package/README-ko.md +282 -0
- package/README.md +282 -266
- package/mcp-config.json +10 -10
- package/package.json +4 -2
- package/src/adapters/index.ts +370 -370
- package/src/cli.ts +162 -127
- package/src/commands/benchmark.ts +187 -187
- package/src/commands/correlate.ts +180 -0
- package/src/commands/dashboard.ts +404 -0
- package/src/commands/evolution.ts +84 -1
- package/src/commands/fix.ts +158 -158
- package/src/commands/lang.ts +41 -41
- package/src/commands/plugin.ts +110 -0
- package/src/commands/restart.ts +14 -14
- package/src/commands/score.ts +276 -276
- package/src/commands/start.ts +155 -155
- package/src/commands/status.ts +157 -157
- package/src/commands/stop.ts +68 -68
- package/src/commands/suggest.ts +211 -0
- package/src/commands/sync.ts +329 -16
- package/src/constants.ts +32 -32
- package/src/core/boast.ts +280 -280
- package/src/core/config.ts +49 -49
- package/src/core/correlation-engine.ts +265 -0
- package/src/core/db.ts +145 -117
- package/src/core/discovery.ts +65 -65
- package/src/core/federation.ts +129 -0
- package/src/core/hologram/engine.ts +71 -71
- package/src/core/hologram/fallback.ts +11 -11
- package/src/core/hologram/go-extractor.ts +203 -0
- package/src/core/hologram/incremental.ts +227 -227
- package/src/core/hologram/py-extractor.ts +132 -132
- package/src/core/hologram/rust-extractor.ts +244 -0
- package/src/core/hologram/ts-extractor.ts +406 -320
- package/src/core/hologram/types.ts +27 -25
- package/src/core/hologram.ts +73 -71
- package/src/core/i18n/messages.ts +309 -309
- package/src/core/locale.ts +88 -88
- package/src/core/log-rotate.ts +33 -33
- package/src/core/log-utils.ts +38 -38
- package/src/core/lru-map.ts +61 -61
- package/src/core/notify.ts +74 -74
- package/src/core/plugin-manager.ts +225 -0
- package/src/core/rule-suggestion.ts +127 -0
- package/src/core/validator-generator.ts +224 -0
- package/src/core/workspace.ts +28 -28
- package/src/daemon/client.ts +78 -65
- package/src/daemon/event-batcher.ts +108 -108
- package/src/daemon/guards.ts +13 -13
- package/src/daemon/http-routes.ts +376 -293
- package/src/daemon/mcp-handler.ts +575 -270
- package/src/daemon/mcp-subscriptions.ts +81 -0
- package/src/daemon/mesh.ts +51 -0
- package/src/daemon/server.ts +655 -590
- package/src/daemon/types.ts +121 -100
- package/src/daemon/workspace-map.ts +104 -92
- package/src/platform.ts +60 -60
- package/src/version.ts +15 -15
- package/README.ko.md +0 -266
|
@@ -1,132 +1,132 @@
|
|
|
1
|
-
import type { Node, Tree } from "web-tree-sitter";
|
|
2
|
-
import type { LanguageExtractor, HologramOptions } from "./types";
|
|
3
|
-
|
|
4
|
-
/** Stub a Python function/method body — keep signature + "..." */
|
|
5
|
-
function stubPythonBody(node: Node, source: string): string {
|
|
6
|
-
const body = node.childForFieldName("body");
|
|
7
|
-
if (!body) return node.text;
|
|
8
|
-
return source.slice(node.startIndex, body.startIndex).trimEnd() + " ...";
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/** Extract a Python function definition */
|
|
12
|
-
function extractFunction(node: Node, source: string): string {
|
|
13
|
-
// Decorators
|
|
14
|
-
const decorators = collectDecorators(node, source);
|
|
15
|
-
const sig = stubPythonBody(node, source);
|
|
16
|
-
return decorators + sig;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Extract a Python class with method signatures */
|
|
20
|
-
function extractClass(node: Node, source: string): string {
|
|
21
|
-
const decorators = collectDecorators(node, source);
|
|
22
|
-
const nameNode = node.childForFieldName("name");
|
|
23
|
-
const name = nameNode?.text ?? "?";
|
|
24
|
-
const superclasses = node.childForFieldName("superclasses");
|
|
25
|
-
const sup = superclasses ? superclasses.text : "";
|
|
26
|
-
const body = node.childForFieldName("body");
|
|
27
|
-
|
|
28
|
-
const header = `class ${name}${sup ? `(${sup.replace(/^\(|\)$/g, "")})` : ""}:`;
|
|
29
|
-
|
|
30
|
-
if (!body) return decorators + header;
|
|
31
|
-
|
|
32
|
-
const members: string[] = [];
|
|
33
|
-
for (const child of body.namedChildren) {
|
|
34
|
-
switch (child.type) {
|
|
35
|
-
case "function_definition": {
|
|
36
|
-
const memberDecorators = collectDecorators(child, source);
|
|
37
|
-
members.push(indent(memberDecorators + stubPythonBody(child, source)));
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
|
-
case "expression_statement": {
|
|
41
|
-
// Type-annotated assignments: x: int = 42
|
|
42
|
-
const expr = child.namedChildren[0];
|
|
43
|
-
if (expr?.type === "assignment" || expr?.type === "type") {
|
|
44
|
-
members.push(indent(child.text.split("\n")[0]));
|
|
45
|
-
}
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
case "class_definition": {
|
|
49
|
-
// Nested class — just show header
|
|
50
|
-
const nestedName = child.childForFieldName("name")?.text ?? "?";
|
|
51
|
-
members.push(indent(`class ${nestedName}: ...`));
|
|
52
|
-
break;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (members.length === 0) {
|
|
58
|
-
return decorators + header + "\n ...";
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return decorators + header + "\n" + members.join("\n");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** Collect decorator lines above a node */
|
|
65
|
-
function collectDecorators(node: Node, source: string): string {
|
|
66
|
-
const decorators: string[] = [];
|
|
67
|
-
// In tree-sitter-python, decorators are children of the decorated_definition
|
|
68
|
-
// or are 'decorator' type children of the function/class
|
|
69
|
-
const parent = node.parent;
|
|
70
|
-
if (parent?.type === "decorated_definition") {
|
|
71
|
-
for (const child of parent.namedChildren) {
|
|
72
|
-
if (child.type === "decorator") {
|
|
73
|
-
decorators.push(child.text);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return decorators.length > 0 ? decorators.join("\n") + "\n" : "";
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function indent(s: string): string {
|
|
81
|
-
return s.split("\n").map(line => " " + line).join("\n");
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** Process a single top-level statement */
|
|
85
|
-
function extractTopLevel(node: Node, source: string): string | null {
|
|
86
|
-
switch (node.type) {
|
|
87
|
-
case "import_statement":
|
|
88
|
-
case "import_from_statement":
|
|
89
|
-
return node.text;
|
|
90
|
-
case "function_definition":
|
|
91
|
-
return extractFunction(node, source);
|
|
92
|
-
case "class_definition":
|
|
93
|
-
return extractClass(node, source);
|
|
94
|
-
case "decorated_definition": {
|
|
95
|
-
// Unwrap to get the inner function/class
|
|
96
|
-
const inner = node.namedChildren.find(c =>
|
|
97
|
-
c.type === "function_definition" || c.type === "class_definition");
|
|
98
|
-
if (inner) return extractTopLevel(inner, source);
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
case "expression_statement": {
|
|
102
|
-
// Module-level type annotations or assignments
|
|
103
|
-
const expr = node.namedChildren[0];
|
|
104
|
-
if (expr?.type === "assignment" || expr?.type === "type") {
|
|
105
|
-
return node.text.split("\n")[0];
|
|
106
|
-
}
|
|
107
|
-
// __all__ = [...]
|
|
108
|
-
if (node.text.startsWith("__all__")) {
|
|
109
|
-
return node.text;
|
|
110
|
-
}
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
default:
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export const pyExtractor: LanguageExtractor = {
|
|
119
|
-
extensions: ["py", "pyi"],
|
|
120
|
-
grammarName: "python",
|
|
121
|
-
|
|
122
|
-
extract(tree: Tree, source: string, _options?: HologramOptions): string[] {
|
|
123
|
-
const lines: string[] = [];
|
|
124
|
-
|
|
125
|
-
for (const stmt of tree.rootNode.namedChildren) {
|
|
126
|
-
const line = extractTopLevel(stmt, source);
|
|
127
|
-
if (line) lines.push(line);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return lines;
|
|
131
|
-
},
|
|
132
|
-
};
|
|
1
|
+
import type { Node, Tree } from "web-tree-sitter";
|
|
2
|
+
import type { LanguageExtractor, HologramOptions } from "./types";
|
|
3
|
+
|
|
4
|
+
/** Stub a Python function/method body — keep signature + "..." */
|
|
5
|
+
function stubPythonBody(node: Node, source: string): string {
|
|
6
|
+
const body = node.childForFieldName("body");
|
|
7
|
+
if (!body) return node.text;
|
|
8
|
+
return source.slice(node.startIndex, body.startIndex).trimEnd() + " ...";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Extract a Python function definition */
|
|
12
|
+
function extractFunction(node: Node, source: string): string {
|
|
13
|
+
// Decorators
|
|
14
|
+
const decorators = collectDecorators(node, source);
|
|
15
|
+
const sig = stubPythonBody(node, source);
|
|
16
|
+
return decorators + sig;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Extract a Python class with method signatures */
|
|
20
|
+
function extractClass(node: Node, source: string): string {
|
|
21
|
+
const decorators = collectDecorators(node, source);
|
|
22
|
+
const nameNode = node.childForFieldName("name");
|
|
23
|
+
const name = nameNode?.text ?? "?";
|
|
24
|
+
const superclasses = node.childForFieldName("superclasses");
|
|
25
|
+
const sup = superclasses ? superclasses.text : "";
|
|
26
|
+
const body = node.childForFieldName("body");
|
|
27
|
+
|
|
28
|
+
const header = `class ${name}${sup ? `(${sup.replace(/^\(|\)$/g, "")})` : ""}:`;
|
|
29
|
+
|
|
30
|
+
if (!body) return decorators + header;
|
|
31
|
+
|
|
32
|
+
const members: string[] = [];
|
|
33
|
+
for (const child of body.namedChildren) {
|
|
34
|
+
switch (child.type) {
|
|
35
|
+
case "function_definition": {
|
|
36
|
+
const memberDecorators = collectDecorators(child, source);
|
|
37
|
+
members.push(indent(memberDecorators + stubPythonBody(child, source)));
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
case "expression_statement": {
|
|
41
|
+
// Type-annotated assignments: x: int = 42
|
|
42
|
+
const expr = child.namedChildren[0];
|
|
43
|
+
if (expr?.type === "assignment" || expr?.type === "type") {
|
|
44
|
+
members.push(indent(child.text.split("\n")[0]));
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
case "class_definition": {
|
|
49
|
+
// Nested class — just show header
|
|
50
|
+
const nestedName = child.childForFieldName("name")?.text ?? "?";
|
|
51
|
+
members.push(indent(`class ${nestedName}: ...`));
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (members.length === 0) {
|
|
58
|
+
return decorators + header + "\n ...";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return decorators + header + "\n" + members.join("\n");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Collect decorator lines above a node */
|
|
65
|
+
function collectDecorators(node: Node, source: string): string {
|
|
66
|
+
const decorators: string[] = [];
|
|
67
|
+
// In tree-sitter-python, decorators are children of the decorated_definition
|
|
68
|
+
// or are 'decorator' type children of the function/class
|
|
69
|
+
const parent = node.parent;
|
|
70
|
+
if (parent?.type === "decorated_definition") {
|
|
71
|
+
for (const child of parent.namedChildren) {
|
|
72
|
+
if (child.type === "decorator") {
|
|
73
|
+
decorators.push(child.text);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return decorators.length > 0 ? decorators.join("\n") + "\n" : "";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function indent(s: string): string {
|
|
81
|
+
return s.split("\n").map(line => " " + line).join("\n");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Process a single top-level statement */
|
|
85
|
+
function extractTopLevel(node: Node, source: string): string | null {
|
|
86
|
+
switch (node.type) {
|
|
87
|
+
case "import_statement":
|
|
88
|
+
case "import_from_statement":
|
|
89
|
+
return node.text;
|
|
90
|
+
case "function_definition":
|
|
91
|
+
return extractFunction(node, source);
|
|
92
|
+
case "class_definition":
|
|
93
|
+
return extractClass(node, source);
|
|
94
|
+
case "decorated_definition": {
|
|
95
|
+
// Unwrap to get the inner function/class
|
|
96
|
+
const inner = node.namedChildren.find(c =>
|
|
97
|
+
c.type === "function_definition" || c.type === "class_definition");
|
|
98
|
+
if (inner) return extractTopLevel(inner, source);
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
case "expression_statement": {
|
|
102
|
+
// Module-level type annotations or assignments
|
|
103
|
+
const expr = node.namedChildren[0];
|
|
104
|
+
if (expr?.type === "assignment" || expr?.type === "type") {
|
|
105
|
+
return node.text.split("\n")[0];
|
|
106
|
+
}
|
|
107
|
+
// __all__ = [...]
|
|
108
|
+
if (node.text.startsWith("__all__")) {
|
|
109
|
+
return node.text;
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
default:
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export const pyExtractor: LanguageExtractor = {
|
|
119
|
+
extensions: ["py", "pyi"],
|
|
120
|
+
grammarName: "python",
|
|
121
|
+
|
|
122
|
+
extract(tree: Tree, source: string, _options?: HologramOptions): string[] {
|
|
123
|
+
const lines: string[] = [];
|
|
124
|
+
|
|
125
|
+
for (const stmt of tree.rootNode.namedChildren) {
|
|
126
|
+
const line = extractTopLevel(stmt, source);
|
|
127
|
+
if (line) lines.push(line);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return lines;
|
|
131
|
+
},
|
|
132
|
+
};
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import type { Node, Tree } from "web-tree-sitter";
|
|
2
|
+
import type { LanguageExtractor, HologramOptions } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Collapse multiple whitespace/newlines into a single space.
|
|
6
|
+
*/
|
|
7
|
+
function collapse(s: string): string {
|
|
8
|
+
return s.replace(/\s+/g, " ").trim();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Stub a function body: slice source up to (but not including) the `block` node.
|
|
13
|
+
* Returns `fn signature(…) -> ReturnType {…}`.
|
|
14
|
+
*/
|
|
15
|
+
function stubFnBody(node: Node, source: string): string {
|
|
16
|
+
const block = node.childForFieldName("body") ?? node.namedChildren.find(c => c.type === "block");
|
|
17
|
+
if (!block) return collapse(node.text);
|
|
18
|
+
return collapse(source.slice(node.startIndex, block.startIndex).trimEnd()) + " {…}";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Extract a `use_declaration`:
|
|
23
|
+
* use std::collections::HashMap;
|
|
24
|
+
*/
|
|
25
|
+
function extractUse(node: Node): string {
|
|
26
|
+
return collapse(node.text);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Extract a `mod_item`:
|
|
31
|
+
* mod utils; (external module declaration)
|
|
32
|
+
* mod config { pub fn default() {} } (inline module — show header + {…})
|
|
33
|
+
*/
|
|
34
|
+
function extractMod(node: Node, source: string): string {
|
|
35
|
+
const body = node.namedChildren.find(c => c.type === "declaration_list");
|
|
36
|
+
if (!body) return collapse(node.text); // `mod utils;` — preserve as-is
|
|
37
|
+
// Inline mod: show header only
|
|
38
|
+
return collapse(source.slice(node.startIndex, body.startIndex).trimEnd()) + " {…}";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Extract a `struct_item` with all field declarations.
|
|
43
|
+
*
|
|
44
|
+
* Example output:
|
|
45
|
+
* pub struct Config {
|
|
46
|
+
* pub host: String,
|
|
47
|
+
* pub port: u16,
|
|
48
|
+
* enabled: bool,
|
|
49
|
+
* }
|
|
50
|
+
*/
|
|
51
|
+
function extractStruct(node: Node, source: string): string {
|
|
52
|
+
const fieldList = node.namedChildren.find(c => c.type === "field_declaration_list");
|
|
53
|
+
|
|
54
|
+
// Tuple struct or unit struct — no braced field list
|
|
55
|
+
if (!fieldList) return collapse(node.text);
|
|
56
|
+
|
|
57
|
+
// Build header: everything before the field list
|
|
58
|
+
const header = collapse(source.slice(node.startIndex, fieldList.startIndex).trimEnd());
|
|
59
|
+
|
|
60
|
+
const fields = fieldList.namedChildren
|
|
61
|
+
.filter(c => c.type === "field_declaration")
|
|
62
|
+
.map(f => " " + collapse(f.text) + ",");
|
|
63
|
+
|
|
64
|
+
if (fields.length === 0) return `${header} {}`;
|
|
65
|
+
return `${header} {\n${fields.join("\n")}\n}`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Extract an `enum_item` with all variants.
|
|
70
|
+
*
|
|
71
|
+
* Example output:
|
|
72
|
+
* pub enum Status {
|
|
73
|
+
* Active,
|
|
74
|
+
* Inactive,
|
|
75
|
+
* Error(String),
|
|
76
|
+
* }
|
|
77
|
+
*/
|
|
78
|
+
function extractEnum(node: Node, source: string): string {
|
|
79
|
+
const variantList = node.namedChildren.find(c => c.type === "enum_variant_list");
|
|
80
|
+
if (!variantList) return collapse(node.text);
|
|
81
|
+
|
|
82
|
+
const header = collapse(source.slice(node.startIndex, variantList.startIndex).trimEnd());
|
|
83
|
+
|
|
84
|
+
const variants = variantList.namedChildren
|
|
85
|
+
.filter(c => c.type === "enum_variant")
|
|
86
|
+
.map(v => " " + collapse(v.text) + ",");
|
|
87
|
+
|
|
88
|
+
if (variants.length === 0) return `${header} {}`;
|
|
89
|
+
return `${header} {\n${variants.join("\n")}\n}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Extract a `trait_item` with method signatures (no bodies — traits only contain signatures).
|
|
94
|
+
*
|
|
95
|
+
* Example output:
|
|
96
|
+
* pub trait Handler {
|
|
97
|
+
* fn handle(&self, req: &Request) -> Response;
|
|
98
|
+
* fn name(&self) -> &str;
|
|
99
|
+
* }
|
|
100
|
+
*/
|
|
101
|
+
function extractTrait(node: Node, source: string): string {
|
|
102
|
+
const body = node.namedChildren.find(c => c.type === "declaration_list");
|
|
103
|
+
if (!body) return collapse(node.text);
|
|
104
|
+
|
|
105
|
+
const header = collapse(source.slice(node.startIndex, body.startIndex).trimEnd());
|
|
106
|
+
|
|
107
|
+
const members: string[] = [];
|
|
108
|
+
for (const child of body.namedChildren) {
|
|
109
|
+
switch (child.type) {
|
|
110
|
+
case "function_signature_item":
|
|
111
|
+
// Already a pure signature (no body)
|
|
112
|
+
members.push(" " + collapse(child.text));
|
|
113
|
+
break;
|
|
114
|
+
case "function_item":
|
|
115
|
+
// Default implementation — stub body
|
|
116
|
+
members.push(" " + stubFnBody(child, source));
|
|
117
|
+
break;
|
|
118
|
+
case "type_item":
|
|
119
|
+
// Associated type: `type Output;`
|
|
120
|
+
members.push(" " + collapse(child.text));
|
|
121
|
+
break;
|
|
122
|
+
case "const_item":
|
|
123
|
+
// Associated const: `const N: usize;`
|
|
124
|
+
members.push(" " + collapse(child.text));
|
|
125
|
+
break;
|
|
126
|
+
case "comment":
|
|
127
|
+
break;
|
|
128
|
+
default:
|
|
129
|
+
members.push(" " + collapse(child.text));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (members.length === 0) return `${header} {}`;
|
|
134
|
+
return `${header} {\n${members.join("\n")}\n}`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Extract a `type_item` (type alias).
|
|
139
|
+
* pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
|
140
|
+
*/
|
|
141
|
+
function extractTypeAlias(node: Node): string {
|
|
142
|
+
return collapse(node.text);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Extract an `impl_item` with stubbed method bodies.
|
|
147
|
+
*
|
|
148
|
+
* Handles:
|
|
149
|
+
* impl Config { ... }
|
|
150
|
+
* impl Handler for MyHandler { ... }
|
|
151
|
+
* impl<T: Trait> OtherTrait for Wrapper<T> { ... }
|
|
152
|
+
*
|
|
153
|
+
* Example output:
|
|
154
|
+
* impl Config {
|
|
155
|
+
* pub fn new(host: String, port: u16) -> Self {…}
|
|
156
|
+
* pub fn is_enabled(&self) -> bool {…}
|
|
157
|
+
* }
|
|
158
|
+
*/
|
|
159
|
+
function extractImpl(node: Node, source: string): string {
|
|
160
|
+
const body = node.namedChildren.find(c => c.type === "declaration_list");
|
|
161
|
+
if (!body) return collapse(node.text);
|
|
162
|
+
|
|
163
|
+
const header = collapse(source.slice(node.startIndex, body.startIndex).trimEnd());
|
|
164
|
+
|
|
165
|
+
const methods: string[] = [];
|
|
166
|
+
for (const child of body.namedChildren) {
|
|
167
|
+
switch (child.type) {
|
|
168
|
+
case "function_item":
|
|
169
|
+
methods.push(" " + stubFnBody(child, source));
|
|
170
|
+
break;
|
|
171
|
+
case "type_item":
|
|
172
|
+
// Associated type implementation: `type Output = i32;`
|
|
173
|
+
methods.push(" " + collapse(child.text));
|
|
174
|
+
break;
|
|
175
|
+
case "const_item":
|
|
176
|
+
// Associated const implementation
|
|
177
|
+
methods.push(" " + collapse(child.text));
|
|
178
|
+
break;
|
|
179
|
+
case "comment":
|
|
180
|
+
break;
|
|
181
|
+
default:
|
|
182
|
+
methods.push(" " + collapse(child.text));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (methods.length === 0) return `${header} {}`;
|
|
187
|
+
return `${header} {\n${methods.join("\n")}\n}`;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Extract a standalone `function_item` with stubbed body.
|
|
192
|
+
* pub fn parse_args(args: &[String]) -> Result<Config> {…}
|
|
193
|
+
*/
|
|
194
|
+
function extractFn(node: Node, source: string): string {
|
|
195
|
+
return stubFnBody(node, source);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Process a single top-level item node.
|
|
200
|
+
*/
|
|
201
|
+
function extractTopLevel(node: Node, source: string): string | null {
|
|
202
|
+
switch (node.type) {
|
|
203
|
+
case "use_declaration":
|
|
204
|
+
return extractUse(node);
|
|
205
|
+
case "mod_item":
|
|
206
|
+
return extractMod(node, source);
|
|
207
|
+
case "struct_item":
|
|
208
|
+
return extractStruct(node, source);
|
|
209
|
+
case "enum_item":
|
|
210
|
+
return extractEnum(node, source);
|
|
211
|
+
case "trait_item":
|
|
212
|
+
return extractTrait(node, source);
|
|
213
|
+
case "type_item":
|
|
214
|
+
return extractTypeAlias(node);
|
|
215
|
+
case "impl_item":
|
|
216
|
+
return extractImpl(node, source);
|
|
217
|
+
case "function_item":
|
|
218
|
+
return extractFn(node, source);
|
|
219
|
+
case "comment":
|
|
220
|
+
case "line_comment":
|
|
221
|
+
case "block_comment":
|
|
222
|
+
// Skip top-level comments for compression
|
|
223
|
+
return null;
|
|
224
|
+
default:
|
|
225
|
+
// const_item, static_item, macro_definition, attribute_item, etc. — skip
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export const rustExtractor: LanguageExtractor = {
|
|
231
|
+
extensions: ["rs"],
|
|
232
|
+
grammarName: "rust",
|
|
233
|
+
|
|
234
|
+
extract(tree: Tree, source: string, _options?: HologramOptions): string[] {
|
|
235
|
+
const lines: string[] = [];
|
|
236
|
+
|
|
237
|
+
for (const node of tree.rootNode.namedChildren) {
|
|
238
|
+
const extracted = extractTopLevel(node, source);
|
|
239
|
+
if (extracted) lines.push(extracted);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return lines;
|
|
243
|
+
},
|
|
244
|
+
};
|