gitnexus 1.4.8 → 1.4.10
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/README.md +7 -0
- package/dist/cli/index-repo.d.ts +15 -0
- package/dist/cli/index-repo.js +115 -0
- package/dist/cli/index.js +11 -2
- package/dist/cli/setup.js +12 -9
- package/dist/cli/wiki.d.ts +4 -0
- package/dist/cli/wiki.js +174 -53
- package/dist/config/supported-languages.d.ts +7 -5
- package/dist/config/supported-languages.js +6 -4
- package/dist/core/graph/graph.js +9 -1
- package/dist/core/graph/types.d.ts +10 -2
- package/dist/core/ingestion/call-processor.d.ts +18 -1
- package/dist/core/ingestion/call-processor.js +297 -38
- package/dist/core/ingestion/call-routing.d.ts +3 -18
- package/dist/core/ingestion/call-routing.js +0 -19
- package/dist/core/ingestion/cobol/cobol-copy-expander.d.ts +57 -0
- package/dist/core/ingestion/cobol/cobol-copy-expander.js +385 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +210 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +1509 -0
- package/dist/core/ingestion/cobol/jcl-parser.d.ts +68 -0
- package/dist/core/ingestion/cobol/jcl-parser.js +217 -0
- package/dist/core/ingestion/cobol/jcl-processor.d.ts +33 -0
- package/dist/core/ingestion/cobol/jcl-processor.js +229 -0
- package/dist/core/ingestion/cobol-processor.d.ts +54 -0
- package/dist/core/ingestion/cobol-processor.js +1186 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +17 -0
- package/dist/core/ingestion/entry-point-scoring.js +18 -4
- package/dist/core/ingestion/export-detection.d.ts +47 -8
- package/dist/core/ingestion/export-detection.js +29 -50
- package/dist/core/ingestion/field-extractor.d.ts +29 -0
- package/dist/core/ingestion/field-extractor.js +25 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.js +108 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.js +73 -0
- package/dist/core/ingestion/field-extractors/configs/dart.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/dart.js +76 -0
- package/dist/core/ingestion/field-extractors/configs/go.d.ts +11 -0
- package/dist/core/ingestion/field-extractors/configs/go.js +64 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +44 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.js +134 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.js +118 -0
- package/dist/core/ingestion/field-extractors/configs/php.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/php.js +67 -0
- package/dist/core/ingestion/field-extractors/configs/python.d.ts +12 -0
- package/dist/core/ingestion/field-extractors/configs/python.js +91 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.d.ts +16 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.js +75 -0
- package/dist/core/ingestion/field-extractors/configs/rust.d.ts +9 -0
- package/dist/core/ingestion/field-extractors/configs/rust.js +55 -0
- package/dist/core/ingestion/field-extractors/configs/swift.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/swift.js +63 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +60 -0
- package/dist/core/ingestion/field-extractors/generic.d.ts +46 -0
- package/dist/core/ingestion/field-extractors/generic.js +111 -0
- package/dist/core/ingestion/field-extractors/typescript.d.ts +77 -0
- package/dist/core/ingestion/field-extractors/typescript.js +291 -0
- package/dist/core/ingestion/field-types.d.ts +59 -0
- package/dist/core/ingestion/field-types.js +2 -0
- package/dist/core/ingestion/framework-detection.d.ts +87 -0
- package/dist/core/ingestion/framework-detection.js +65 -2
- package/dist/core/ingestion/heritage-processor.js +15 -17
- package/dist/core/ingestion/import-processor.d.ts +9 -10
- package/dist/core/ingestion/import-processor.js +59 -14
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.d.ts +6 -9
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.js +20 -2
- package/dist/core/ingestion/import-resolvers/dart.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/dart.js +44 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.d.ts +4 -5
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.js +17 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.d.ts +9 -1
- package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.js +56 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/php.d.ts +6 -10
- package/dist/core/ingestion/{resolvers → import-resolvers}/php.js +7 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.d.ts +9 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.js +35 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.js +7 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.js +41 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.d.ts +15 -7
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.js +22 -3
- package/dist/core/ingestion/import-resolvers/swift.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/swift.js +23 -0
- package/dist/core/ingestion/import-resolvers/types.d.ts +44 -0
- package/dist/core/ingestion/import-resolvers/types.js +6 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.d.ts +0 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +0 -9
- package/dist/core/ingestion/language-config.d.ts +4 -1
- package/dist/core/ingestion/language-provider.d.ts +121 -0
- package/dist/core/ingestion/language-provider.js +24 -0
- package/dist/core/ingestion/languages/c-cpp.d.ts +12 -0
- package/dist/core/ingestion/languages/c-cpp.js +71 -0
- package/dist/core/ingestion/languages/cobol.d.ts +1 -0
- package/dist/core/ingestion/languages/cobol.js +26 -0
- package/dist/core/ingestion/languages/csharp.d.ts +8 -0
- package/dist/core/ingestion/languages/csharp.js +49 -0
- package/dist/core/ingestion/languages/dart.d.ts +12 -0
- package/dist/core/ingestion/languages/dart.js +58 -0
- package/dist/core/ingestion/languages/go.d.ts +11 -0
- package/dist/core/ingestion/languages/go.js +28 -0
- package/dist/core/ingestion/languages/index.d.ts +38 -0
- package/dist/core/ingestion/languages/index.js +63 -0
- package/dist/core/ingestion/languages/java.d.ts +9 -0
- package/dist/core/ingestion/languages/java.js +29 -0
- package/dist/core/ingestion/languages/kotlin.d.ts +9 -0
- package/dist/core/ingestion/languages/kotlin.js +53 -0
- package/dist/core/ingestion/languages/php.d.ts +8 -0
- package/dist/core/ingestion/languages/php.js +145 -0
- package/dist/core/ingestion/languages/python.d.ts +12 -0
- package/dist/core/ingestion/languages/python.js +39 -0
- package/dist/core/ingestion/languages/ruby.d.ts +9 -0
- package/dist/core/ingestion/languages/ruby.js +44 -0
- package/dist/core/ingestion/languages/rust.d.ts +12 -0
- package/dist/core/ingestion/languages/rust.js +44 -0
- package/dist/core/ingestion/languages/swift.d.ts +12 -0
- package/dist/core/ingestion/languages/swift.js +133 -0
- package/dist/core/ingestion/languages/typescript.d.ts +10 -0
- package/dist/core/ingestion/languages/typescript.js +60 -0
- package/dist/core/ingestion/mro-processor.js +14 -15
- package/dist/core/ingestion/{named-binding-extraction.d.ts → named-binding-processor.d.ts} +0 -9
- package/dist/core/ingestion/named-binding-processor.js +42 -0
- package/dist/core/ingestion/named-bindings/csharp.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/csharp.js +37 -0
- package/dist/core/ingestion/named-bindings/java.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/java.js +29 -0
- package/dist/core/ingestion/named-bindings/kotlin.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/kotlin.js +36 -0
- package/dist/core/ingestion/named-bindings/php.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/php.js +61 -0
- package/dist/core/ingestion/named-bindings/python.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/python.js +49 -0
- package/dist/core/ingestion/named-bindings/rust.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/rust.js +64 -0
- package/dist/core/ingestion/named-bindings/types.d.ts +16 -0
- package/dist/core/ingestion/named-bindings/types.js +6 -0
- package/dist/core/ingestion/named-bindings/typescript.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/typescript.js +58 -0
- package/dist/core/ingestion/parsing-processor.d.ts +5 -1
- package/dist/core/ingestion/parsing-processor.js +115 -16
- package/dist/core/ingestion/pipeline.js +925 -424
- package/dist/core/ingestion/resolution-context.js +1 -1
- package/dist/core/ingestion/route-extractors/expo.d.ts +1 -0
- package/dist/core/ingestion/route-extractors/expo.js +36 -0
- package/dist/core/ingestion/route-extractors/middleware.d.ts +47 -0
- package/dist/core/ingestion/route-extractors/middleware.js +143 -0
- package/dist/core/ingestion/route-extractors/nextjs.d.ts +3 -0
- package/dist/core/ingestion/route-extractors/nextjs.js +76 -0
- package/dist/core/ingestion/route-extractors/php.d.ts +7 -0
- package/dist/core/ingestion/route-extractors/php.js +21 -0
- package/dist/core/ingestion/route-extractors/response-shapes.d.ts +20 -0
- package/dist/core/ingestion/route-extractors/response-shapes.js +290 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +8 -7
- package/dist/core/ingestion/tree-sitter-queries.js +231 -9
- package/dist/core/ingestion/type-env.d.ts +14 -17
- package/dist/core/ingestion/type-env.js +66 -14
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +1 -1
- package/dist/core/ingestion/type-extractors/csharp.js +1 -1
- package/dist/core/ingestion/type-extractors/dart.d.ts +15 -0
- package/dist/core/ingestion/type-extractors/dart.js +371 -0
- package/dist/core/ingestion/type-extractors/jvm.js +1 -1
- package/dist/core/ingestion/type-extractors/shared.d.ts +1 -13
- package/dist/core/ingestion/type-extractors/shared.js +9 -102
- package/dist/core/ingestion/type-extractors/swift.js +334 -4
- package/dist/core/ingestion/type-extractors/types.d.ts +3 -1
- package/dist/core/ingestion/{ast-helpers.d.ts → utils/ast-helpers.d.ts} +16 -13
- package/dist/core/ingestion/{ast-helpers.js → utils/ast-helpers.js} +111 -32
- package/dist/core/ingestion/{call-analysis.js → utils/call-analysis.js} +37 -0
- package/dist/core/ingestion/utils/event-loop.d.ts +5 -0
- package/dist/core/ingestion/utils/event-loop.js +5 -0
- package/dist/core/ingestion/utils/language-detection.d.ts +9 -0
- package/dist/core/ingestion/utils/language-detection.js +70 -0
- package/dist/core/ingestion/utils/verbose.d.ts +1 -0
- package/dist/core/ingestion/utils/verbose.js +7 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +43 -2
- package/dist/core/ingestion/workers/parse-worker.js +361 -150
- package/dist/core/lbug/csv-generator.js +34 -1
- package/dist/core/lbug/lbug-adapter.js +6 -0
- package/dist/core/lbug/schema.d.ts +5 -3
- package/dist/core/lbug/schema.js +39 -2
- package/dist/core/tree-sitter/parser-loader.js +7 -1
- package/dist/core/wiki/cursor-client.d.ts +31 -0
- package/dist/core/wiki/cursor-client.js +127 -0
- package/dist/core/wiki/generator.d.ts +28 -9
- package/dist/core/wiki/generator.js +115 -18
- package/dist/core/wiki/graph-queries.d.ts +4 -0
- package/dist/core/wiki/graph-queries.js +7 -1
- package/dist/core/wiki/llm-client.d.ts +2 -0
- package/dist/core/wiki/llm-client.js +8 -4
- package/dist/core/wiki/prompts.d.ts +3 -3
- package/dist/core/wiki/prompts.js +6 -0
- package/dist/mcp/core/lbug-adapter.d.ts +5 -0
- package/dist/mcp/core/lbug-adapter.js +11 -1
- package/dist/mcp/local/local-backend.d.ts +16 -5
- package/dist/mcp/local/local-backend.js +711 -74
- package/dist/mcp/tools.js +71 -2
- package/dist/storage/repo-manager.d.ts +3 -0
- package/package.json +14 -14
- package/dist/core/ingestion/import-resolution.d.ts +0 -101
- package/dist/core/ingestion/import-resolution.js +0 -251
- package/dist/core/ingestion/named-binding-extraction.js +0 -373
- package/dist/core/ingestion/resolvers/index.d.ts +0 -18
- package/dist/core/ingestion/resolvers/index.js +0 -13
- package/dist/core/ingestion/type-extractors/index.d.ts +0 -22
- package/dist/core/ingestion/type-extractors/index.js +0 -31
- package/dist/core/ingestion/utils.d.ts +0 -20
- package/dist/core/ingestion/utils.js +0 -242
- package/scripts/patch-tree-sitter-swift.cjs +0 -74
- /package/dist/core/ingestion/{call-analysis.d.ts → utils/call-analysis.d.ts} +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// gitnexus/src/core/ingestion/field-extractors/configs/go.ts
|
|
2
|
+
import { SupportedLanguages } from '../../../../config/supported-languages.js';
|
|
3
|
+
import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
4
|
+
/**
|
|
5
|
+
* Go field extraction config.
|
|
6
|
+
*
|
|
7
|
+
* Go struct fields live inside type_declaration > type_spec > struct_type >
|
|
8
|
+
* field_declaration_list > field_declaration.
|
|
9
|
+
*
|
|
10
|
+
* Visibility in Go is based on the first character: uppercase = exported (public),
|
|
11
|
+
* lowercase = unexported (package).
|
|
12
|
+
*/
|
|
13
|
+
export const goConfig = {
|
|
14
|
+
language: SupportedLanguages.Go,
|
|
15
|
+
typeDeclarationNodes: [
|
|
16
|
+
'type_declaration',
|
|
17
|
+
],
|
|
18
|
+
fieldNodeTypes: ['field_declaration'],
|
|
19
|
+
bodyNodeTypes: ['field_declaration_list'],
|
|
20
|
+
defaultVisibility: 'package',
|
|
21
|
+
extractName(node) {
|
|
22
|
+
// field_declaration > name:(field_identifier)
|
|
23
|
+
const name = node.childForFieldName('name');
|
|
24
|
+
if (name)
|
|
25
|
+
return name.text;
|
|
26
|
+
// fallback: first field_identifier child
|
|
27
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
28
|
+
const child = node.namedChild(i);
|
|
29
|
+
if (child?.type === 'field_identifier')
|
|
30
|
+
return child.text;
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
},
|
|
34
|
+
extractType(node) {
|
|
35
|
+
// field_declaration > type:(type_identifier | pointer_type | ...)
|
|
36
|
+
const typeNode = node.childForFieldName('type');
|
|
37
|
+
if (typeNode)
|
|
38
|
+
return extractSimpleTypeName(typeNode) ?? typeNode.text?.trim();
|
|
39
|
+
// fallback: second named child is usually the type
|
|
40
|
+
if (node.namedChildCount >= 2) {
|
|
41
|
+
const t = node.namedChild(1);
|
|
42
|
+
if (t)
|
|
43
|
+
return extractSimpleTypeName(t) ?? t.text?.trim();
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
},
|
|
47
|
+
extractVisibility(node) {
|
|
48
|
+
const name = node.childForFieldName('name');
|
|
49
|
+
const text = name?.text;
|
|
50
|
+
if (text && text.length > 0) {
|
|
51
|
+
const first = text.charAt(0);
|
|
52
|
+
return first === first.toUpperCase() && first !== first.toLowerCase()
|
|
53
|
+
? 'public'
|
|
54
|
+
: 'package';
|
|
55
|
+
}
|
|
56
|
+
return 'package';
|
|
57
|
+
},
|
|
58
|
+
isStatic(_node) {
|
|
59
|
+
return false; // Go has no static fields
|
|
60
|
+
},
|
|
61
|
+
isReadonly(_node) {
|
|
62
|
+
return false; // Go fields are not readonly
|
|
63
|
+
},
|
|
64
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared AST-walking helpers used by multiple language configs.
|
|
3
|
+
* Keeps individual config files small.
|
|
4
|
+
*/
|
|
5
|
+
import type { SyntaxNode } from '../../utils/ast-helpers.js';
|
|
6
|
+
import type { FieldVisibility } from '../../field-types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Check whether any child of `node` (named or unnamed) has .text matching
|
|
9
|
+
* one of the given `keywords`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function hasKeyword(node: SyntaxNode, keyword: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Check whether a named child of type `modifierType` contains `keyword`.
|
|
14
|
+
* Useful for languages that group modifiers under a wrapper node
|
|
15
|
+
* (e.g. Java 'modifiers', Kotlin 'modifiers').
|
|
16
|
+
*/
|
|
17
|
+
export declare function hasModifier(node: SyntaxNode, modifierType: string, keyword: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Return the first matching visibility keyword found either as a direct keyword
|
|
20
|
+
* child or inside a modifier wrapper node.
|
|
21
|
+
*/
|
|
22
|
+
export declare function findVisibility(node: SyntaxNode, keywords: ReadonlySet<FieldVisibility>, defaultVis: FieldVisibility, modifierNodeType?: string): FieldVisibility;
|
|
23
|
+
/**
|
|
24
|
+
* Extract the text of the first named child whose type is in `types`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function firstChildText(node: SyntaxNode, types: ReadonlySet<string>): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Extract the first named child node whose type is in `types`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function firstChildOfType(node: SyntaxNode, types: ReadonlySet<string>): SyntaxNode | null;
|
|
31
|
+
/**
|
|
32
|
+
* Get type text from a named field on the node, using extractSimpleTypeName.
|
|
33
|
+
* Falls back to raw .text of the field child if extractSimpleTypeName returns undefined.
|
|
34
|
+
*/
|
|
35
|
+
export declare function typeFromField(node: SyntaxNode, fieldName: string): string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Walk named children looking for a type_annotation node and extract its type.
|
|
38
|
+
*/
|
|
39
|
+
export declare function typeFromAnnotation(node: SyntaxNode): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Find the first descendant (depth-first, one level) matching one of the given types
|
|
42
|
+
* and return its text via extractSimpleTypeName.
|
|
43
|
+
*/
|
|
44
|
+
export declare function typeFromDescendant(node: SyntaxNode, types: ReadonlySet<string>): string | undefined;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// gitnexus/src/core/ingestion/field-extractors/configs/helpers.ts
|
|
2
|
+
import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Modifier scanning
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
/**
|
|
7
|
+
* Check whether any child of `node` (named or unnamed) has .text matching
|
|
8
|
+
* one of the given `keywords`.
|
|
9
|
+
*/
|
|
10
|
+
export function hasKeyword(node, keyword) {
|
|
11
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
12
|
+
const child = node.child(i);
|
|
13
|
+
if (child && child.text.trim() === keyword)
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Check whether a named child of type `modifierType` contains `keyword`.
|
|
20
|
+
* Useful for languages that group modifiers under a wrapper node
|
|
21
|
+
* (e.g. Java 'modifiers', Kotlin 'modifiers').
|
|
22
|
+
*/
|
|
23
|
+
export function hasModifier(node, modifierType, keyword) {
|
|
24
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
25
|
+
const child = node.namedChild(i);
|
|
26
|
+
if (child && child.type === modifierType) {
|
|
27
|
+
for (let j = 0; j < child.childCount; j++) {
|
|
28
|
+
const mod = child.child(j);
|
|
29
|
+
if (mod && mod.text.trim() === keyword)
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Return the first matching visibility keyword found either as a direct keyword
|
|
38
|
+
* child or inside a modifier wrapper node.
|
|
39
|
+
*/
|
|
40
|
+
export function findVisibility(node, keywords, defaultVis, modifierNodeType) {
|
|
41
|
+
// Direct keyword children
|
|
42
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
43
|
+
const child = node.child(i);
|
|
44
|
+
const text = child?.text.trim();
|
|
45
|
+
if (text && keywords.has(text))
|
|
46
|
+
return text;
|
|
47
|
+
}
|
|
48
|
+
// Modifier wrapper
|
|
49
|
+
if (modifierNodeType) {
|
|
50
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
51
|
+
const child = node.namedChild(i);
|
|
52
|
+
if (child && child.type === modifierNodeType) {
|
|
53
|
+
for (let j = 0; j < child.childCount; j++) {
|
|
54
|
+
const mod = child.child(j);
|
|
55
|
+
const modText = mod?.text.trim();
|
|
56
|
+
if (modText && keywords.has(modText))
|
|
57
|
+
return modText;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return defaultVis;
|
|
63
|
+
}
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Name and type extraction
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
/**
|
|
68
|
+
* Extract the text of the first named child whose type is in `types`.
|
|
69
|
+
*/
|
|
70
|
+
export function firstChildText(node, types) {
|
|
71
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
72
|
+
const child = node.namedChild(i);
|
|
73
|
+
if (child && types.has(child.type))
|
|
74
|
+
return child.text;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Extract the first named child node whose type is in `types`.
|
|
80
|
+
*/
|
|
81
|
+
export function firstChildOfType(node, types) {
|
|
82
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
83
|
+
const child = node.namedChild(i);
|
|
84
|
+
if (child && types.has(child.type))
|
|
85
|
+
return child;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get type text from a named field on the node, using extractSimpleTypeName.
|
|
91
|
+
* Falls back to raw .text of the field child if extractSimpleTypeName returns undefined.
|
|
92
|
+
*/
|
|
93
|
+
export function typeFromField(node, fieldName) {
|
|
94
|
+
const typeNode = node.childForFieldName(fieldName);
|
|
95
|
+
if (!typeNode)
|
|
96
|
+
return undefined;
|
|
97
|
+
return extractSimpleTypeName(typeNode) ?? typeNode.text?.trim();
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Walk named children looking for a type_annotation node and extract its type.
|
|
101
|
+
*/
|
|
102
|
+
export function typeFromAnnotation(node) {
|
|
103
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
104
|
+
const child = node.namedChild(i);
|
|
105
|
+
if (child && child.type === 'type_annotation') {
|
|
106
|
+
const inner = child.firstNamedChild;
|
|
107
|
+
if (inner)
|
|
108
|
+
return extractSimpleTypeName(inner) ?? inner.text?.trim();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Find the first descendant (depth-first, one level) matching one of the given types
|
|
115
|
+
* and return its text via extractSimpleTypeName.
|
|
116
|
+
*/
|
|
117
|
+
export function typeFromDescendant(node, types) {
|
|
118
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
119
|
+
const child = node.namedChild(i);
|
|
120
|
+
if (!child)
|
|
121
|
+
continue;
|
|
122
|
+
if (types.has(child.type)) {
|
|
123
|
+
return extractSimpleTypeName(child) ?? child.text?.trim();
|
|
124
|
+
}
|
|
125
|
+
// one more level
|
|
126
|
+
for (let j = 0; j < child.namedChildCount; j++) {
|
|
127
|
+
const grandchild = child.namedChild(j);
|
|
128
|
+
if (grandchild && types.has(grandchild.type)) {
|
|
129
|
+
return extractSimpleTypeName(grandchild) ?? grandchild.text?.trim();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// gitnexus/src/core/ingestion/field-extractors/configs/jvm.ts
|
|
2
|
+
import { SupportedLanguages } from '../../../../config/supported-languages.js';
|
|
3
|
+
import { findVisibility, hasKeyword, hasModifier, typeFromField } from './helpers.js';
|
|
4
|
+
import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Java
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
const JAVA_VIS = new Set(['public', 'private', 'protected']);
|
|
9
|
+
export const javaConfig = {
|
|
10
|
+
language: SupportedLanguages.Java,
|
|
11
|
+
typeDeclarationNodes: [
|
|
12
|
+
'class_declaration',
|
|
13
|
+
'interface_declaration',
|
|
14
|
+
'enum_declaration',
|
|
15
|
+
'record_declaration',
|
|
16
|
+
],
|
|
17
|
+
fieldNodeTypes: ['field_declaration'],
|
|
18
|
+
bodyNodeTypes: ['class_body', 'interface_body', 'enum_body'],
|
|
19
|
+
defaultVisibility: 'package',
|
|
20
|
+
extractName(node) {
|
|
21
|
+
// field_declaration > declarator:(variable_declarator name:(identifier))
|
|
22
|
+
const declarator = node.childForFieldName('declarator');
|
|
23
|
+
if (declarator) {
|
|
24
|
+
const name = declarator.childForFieldName('name');
|
|
25
|
+
return name?.text;
|
|
26
|
+
}
|
|
27
|
+
// fallback: walk children for variable_declarator
|
|
28
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
29
|
+
const child = node.namedChild(i);
|
|
30
|
+
if (child?.type === 'variable_declarator') {
|
|
31
|
+
const name = child.childForFieldName('name');
|
|
32
|
+
return name?.text;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
},
|
|
37
|
+
extractType(node) {
|
|
38
|
+
// field_declaration > type:(type_identifier|generic_type|...)
|
|
39
|
+
const t = typeFromField(node, 'type');
|
|
40
|
+
if (t)
|
|
41
|
+
return t;
|
|
42
|
+
// fallback: first named child that looks like a type
|
|
43
|
+
const first = node.firstNamedChild;
|
|
44
|
+
if (first && first.type !== 'modifiers') {
|
|
45
|
+
return extractSimpleTypeName(first) ?? first.text?.trim();
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
},
|
|
49
|
+
extractVisibility(node) {
|
|
50
|
+
return findVisibility(node, JAVA_VIS, 'package', 'modifiers');
|
|
51
|
+
},
|
|
52
|
+
isStatic(node) {
|
|
53
|
+
return hasKeyword(node, 'static') || hasModifier(node, 'modifiers', 'static');
|
|
54
|
+
},
|
|
55
|
+
isReadonly(node) {
|
|
56
|
+
return hasKeyword(node, 'final') || hasModifier(node, 'modifiers', 'final');
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Kotlin
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
const KOTLIN_VIS = new Set(['public', 'private', 'protected', 'internal']);
|
|
63
|
+
export const kotlinConfig = {
|
|
64
|
+
language: SupportedLanguages.Kotlin,
|
|
65
|
+
typeDeclarationNodes: [
|
|
66
|
+
'class_declaration',
|
|
67
|
+
'object_declaration',
|
|
68
|
+
],
|
|
69
|
+
fieldNodeTypes: ['property_declaration'],
|
|
70
|
+
bodyNodeTypes: ['class_body'],
|
|
71
|
+
defaultVisibility: 'public',
|
|
72
|
+
extractName(node) {
|
|
73
|
+
// property_declaration > variable_declaration > simple_identifier
|
|
74
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
75
|
+
const child = node.namedChild(i);
|
|
76
|
+
if (child?.type === 'variable_declaration') {
|
|
77
|
+
for (let j = 0; j < child.namedChildCount; j++) {
|
|
78
|
+
const ident = child.namedChild(j);
|
|
79
|
+
if (ident?.type === 'simple_identifier')
|
|
80
|
+
return ident.text;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (child?.type === 'simple_identifier')
|
|
84
|
+
return child.text;
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
},
|
|
88
|
+
extractType(node) {
|
|
89
|
+
// property_declaration may have a user_type or type_identifier under variable_declaration
|
|
90
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
91
|
+
const child = node.namedChild(i);
|
|
92
|
+
if (child?.type === 'variable_declaration') {
|
|
93
|
+
for (let j = 0; j < child.namedChildCount; j++) {
|
|
94
|
+
const t = child.namedChild(j);
|
|
95
|
+
if (t && (t.type === 'user_type' || t.type === 'type_identifier'
|
|
96
|
+
|| t.type === 'nullable_type' || t.type === 'generic_type')) {
|
|
97
|
+
return extractSimpleTypeName(t) ?? t.text?.trim();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (child?.type === 'user_type' || child?.type === 'nullable_type') {
|
|
102
|
+
return extractSimpleTypeName(child) ?? child.text?.trim();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return undefined;
|
|
106
|
+
},
|
|
107
|
+
extractVisibility(node) {
|
|
108
|
+
return findVisibility(node, KOTLIN_VIS, 'public', 'modifiers');
|
|
109
|
+
},
|
|
110
|
+
isStatic(_node) {
|
|
111
|
+
// Kotlin doesn't have static; companion object members are handled separately
|
|
112
|
+
return false;
|
|
113
|
+
},
|
|
114
|
+
isReadonly(node) {
|
|
115
|
+
// 'val' = readonly, 'var' = mutable
|
|
116
|
+
return hasKeyword(node, 'val');
|
|
117
|
+
},
|
|
118
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FieldExtractionConfig } from '../generic.js';
|
|
2
|
+
/**
|
|
3
|
+
* PHP field extraction config.
|
|
4
|
+
*
|
|
5
|
+
* Handles property_declaration inside class/interface/trait bodies.
|
|
6
|
+
* tree-sitter-php uses 'declaration_list' for the class body.
|
|
7
|
+
*/
|
|
8
|
+
export declare const phpConfig: FieldExtractionConfig;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// gitnexus/src/core/ingestion/field-extractors/configs/php.ts
|
|
2
|
+
import { SupportedLanguages } from '../../../../config/supported-languages.js';
|
|
3
|
+
import { findVisibility, hasKeyword } from './helpers.js';
|
|
4
|
+
import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
5
|
+
const PHP_VIS = new Set(['public', 'private', 'protected']);
|
|
6
|
+
/**
|
|
7
|
+
* PHP field extraction config.
|
|
8
|
+
*
|
|
9
|
+
* Handles property_declaration inside class/interface/trait bodies.
|
|
10
|
+
* tree-sitter-php uses 'declaration_list' for the class body.
|
|
11
|
+
*/
|
|
12
|
+
export const phpConfig = {
|
|
13
|
+
language: SupportedLanguages.PHP,
|
|
14
|
+
typeDeclarationNodes: [
|
|
15
|
+
'class_declaration',
|
|
16
|
+
'interface_declaration',
|
|
17
|
+
'trait_declaration',
|
|
18
|
+
],
|
|
19
|
+
fieldNodeTypes: ['property_declaration'],
|
|
20
|
+
bodyNodeTypes: ['declaration_list'],
|
|
21
|
+
defaultVisibility: 'public',
|
|
22
|
+
extractName(node) {
|
|
23
|
+
// property_declaration > property_element > variable_name ($varName)
|
|
24
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
25
|
+
const child = node.namedChild(i);
|
|
26
|
+
if (child?.type === 'property_element') {
|
|
27
|
+
const varName = child.childForFieldName('name')
|
|
28
|
+
?? child.firstNamedChild;
|
|
29
|
+
if (varName) {
|
|
30
|
+
// strip leading $ from PHP variable names
|
|
31
|
+
const text = varName.text;
|
|
32
|
+
return text.startsWith('$') ? text.slice(1) : text;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// fallback: variable_name direct child
|
|
36
|
+
if (child?.type === 'variable_name') {
|
|
37
|
+
const text = child.text;
|
|
38
|
+
return text.startsWith('$') ? text.slice(1) : text;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
},
|
|
43
|
+
extractType(node) {
|
|
44
|
+
// property_declaration may have a type before the property_element
|
|
45
|
+
// tree-sitter-php: type can be union_type, named_type, optional_type, primitive_type
|
|
46
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
47
|
+
const child = node.namedChild(i);
|
|
48
|
+
if (!child)
|
|
49
|
+
continue;
|
|
50
|
+
if (child.type === 'union_type' || child.type === 'named_type'
|
|
51
|
+
|| child.type === 'optional_type' || child.type === 'primitive_type'
|
|
52
|
+
|| child.type === 'intersection_type' || child.type === 'nullable_type') {
|
|
53
|
+
return extractSimpleTypeName(child) ?? child.text?.trim();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
},
|
|
58
|
+
extractVisibility(node) {
|
|
59
|
+
return findVisibility(node, PHP_VIS, 'public');
|
|
60
|
+
},
|
|
61
|
+
isStatic(node) {
|
|
62
|
+
return hasKeyword(node, 'static');
|
|
63
|
+
},
|
|
64
|
+
isReadonly(node) {
|
|
65
|
+
return hasKeyword(node, 'readonly');
|
|
66
|
+
},
|
|
67
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FieldExtractionConfig } from '../generic.js';
|
|
2
|
+
/**
|
|
3
|
+
* Python field extraction config.
|
|
4
|
+
*
|
|
5
|
+
* Python class fields appear as:
|
|
6
|
+
* - Annotated assignments: `name: str = ""`
|
|
7
|
+
* - Plain assignments in __init__: `self.name = value`
|
|
8
|
+
*
|
|
9
|
+
* For AST-level extraction we handle expression_statement containing
|
|
10
|
+
* assignment or type nodes inside a class body block.
|
|
11
|
+
*/
|
|
12
|
+
export declare const pythonConfig: FieldExtractionConfig;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// gitnexus/src/core/ingestion/field-extractors/configs/python.ts
|
|
2
|
+
import { SupportedLanguages } from '../../../../config/supported-languages.js';
|
|
3
|
+
import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
4
|
+
/**
|
|
5
|
+
* Python field extraction config.
|
|
6
|
+
*
|
|
7
|
+
* Python class fields appear as:
|
|
8
|
+
* - Annotated assignments: `name: str = ""`
|
|
9
|
+
* - Plain assignments in __init__: `self.name = value`
|
|
10
|
+
*
|
|
11
|
+
* For AST-level extraction we handle expression_statement containing
|
|
12
|
+
* assignment or type nodes inside a class body block.
|
|
13
|
+
*/
|
|
14
|
+
export const pythonConfig = {
|
|
15
|
+
language: SupportedLanguages.Python,
|
|
16
|
+
typeDeclarationNodes: ['class_definition'],
|
|
17
|
+
fieldNodeTypes: ['expression_statement'],
|
|
18
|
+
bodyNodeTypes: ['block'],
|
|
19
|
+
defaultVisibility: 'public',
|
|
20
|
+
extractName(node) {
|
|
21
|
+
// expression_statement wrapping an assignment or type
|
|
22
|
+
const inner = node.firstNamedChild;
|
|
23
|
+
if (!inner)
|
|
24
|
+
return undefined;
|
|
25
|
+
// Annotated assignment: name: str = "default"
|
|
26
|
+
// tree-sitter node: type (expression_statement (type (identifier) (type) ...))
|
|
27
|
+
if (inner.type === 'type') {
|
|
28
|
+
const ident = inner.childForFieldName('name') ?? inner.firstNamedChild;
|
|
29
|
+
return ident?.type === 'identifier' ? ident.text : undefined;
|
|
30
|
+
}
|
|
31
|
+
// assignment: x = 5 (class variable)
|
|
32
|
+
if (inner.type === 'assignment') {
|
|
33
|
+
const left = inner.childForFieldName('left');
|
|
34
|
+
if (left?.type === 'identifier')
|
|
35
|
+
return left.text;
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
},
|
|
39
|
+
extractType(node) {
|
|
40
|
+
const inner = node.firstNamedChild;
|
|
41
|
+
if (!inner)
|
|
42
|
+
return undefined;
|
|
43
|
+
// Annotated assignment with value: `name: str = "default"`
|
|
44
|
+
// AST: expression_statement > type > [identifier, type, ...]
|
|
45
|
+
if (inner.type === 'type') {
|
|
46
|
+
const typeNode = inner.childForFieldName('type') ?? inner.namedChild(1);
|
|
47
|
+
if (typeNode)
|
|
48
|
+
return extractSimpleTypeName(typeNode) ?? typeNode.text?.trim();
|
|
49
|
+
}
|
|
50
|
+
// Annotation without value: `address: Address`
|
|
51
|
+
// AST: expression_statement > assignment > [identifier, type]
|
|
52
|
+
if (inner.type === 'assignment') {
|
|
53
|
+
for (let i = 0; i < inner.childCount; i++) {
|
|
54
|
+
const child = inner.child(i);
|
|
55
|
+
if (child?.type === 'type') {
|
|
56
|
+
const typeId = child.firstNamedChild;
|
|
57
|
+
if (typeId)
|
|
58
|
+
return extractSimpleTypeName(typeId) ?? typeId.text?.trim();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
},
|
|
64
|
+
extractVisibility(node) {
|
|
65
|
+
const inner = node.firstNamedChild;
|
|
66
|
+
let name;
|
|
67
|
+
if (inner?.type === 'type') {
|
|
68
|
+
const ident = inner.childForFieldName('name') ?? inner.firstNamedChild;
|
|
69
|
+
name = ident?.text;
|
|
70
|
+
}
|
|
71
|
+
else if (inner?.type === 'assignment') {
|
|
72
|
+
const left = inner.childForFieldName('left');
|
|
73
|
+
name = left?.text;
|
|
74
|
+
}
|
|
75
|
+
if (!name)
|
|
76
|
+
return 'public';
|
|
77
|
+
if (name.startsWith('__') && !name.endsWith('__'))
|
|
78
|
+
return 'private';
|
|
79
|
+
if (name.startsWith('_'))
|
|
80
|
+
return 'protected';
|
|
81
|
+
return 'public';
|
|
82
|
+
},
|
|
83
|
+
isStatic(_node) {
|
|
84
|
+
// Reports syntactic static keyword — Python class variables don't use explicit static keyword.
|
|
85
|
+
// Instance variables (self.x) live in __init__ and are not extracted here.
|
|
86
|
+
return false;
|
|
87
|
+
},
|
|
88
|
+
isReadonly(_node) {
|
|
89
|
+
return false;
|
|
90
|
+
},
|
|
91
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FieldExtractionConfig } from '../generic.js';
|
|
2
|
+
/**
|
|
3
|
+
* Ruby field extraction config.
|
|
4
|
+
*
|
|
5
|
+
* Ruby is unusual: there are no field declarations in the traditional sense.
|
|
6
|
+
* Fields are instance variables (@var) created by assignment, or declared
|
|
7
|
+
* via attr_accessor / attr_reader / attr_writer calls.
|
|
8
|
+
*
|
|
9
|
+
* We detect:
|
|
10
|
+
* - `call` nodes for attr_accessor / attr_reader / attr_writer
|
|
11
|
+
* (their arguments are symbol names → field names)
|
|
12
|
+
*
|
|
13
|
+
* For simplicity we focus on attr_* calls in the class body.
|
|
14
|
+
* Instance variable assignments (self.x = ...) would require deeper analysis.
|
|
15
|
+
*/
|
|
16
|
+
export declare const rubyConfig: FieldExtractionConfig;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// gitnexus/src/core/ingestion/field-extractors/configs/ruby.ts
|
|
2
|
+
import { SupportedLanguages } from '../../../../config/supported-languages.js';
|
|
3
|
+
/**
|
|
4
|
+
* Collect all field names declared by an `attr_accessor`, `attr_reader`, or
|
|
5
|
+
* `attr_writer` call node. A single call may list multiple symbols:
|
|
6
|
+
* attr_accessor :foo, :bar, :baz
|
|
7
|
+
*/
|
|
8
|
+
function extractAttrNames(node) {
|
|
9
|
+
const method = node.childForFieldName('method');
|
|
10
|
+
if (!method)
|
|
11
|
+
return [];
|
|
12
|
+
const methodName = method.text;
|
|
13
|
+
if (methodName !== 'attr_accessor' && methodName !== 'attr_reader'
|
|
14
|
+
&& methodName !== 'attr_writer') {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
const args = node.childForFieldName('arguments');
|
|
18
|
+
if (!args)
|
|
19
|
+
return [];
|
|
20
|
+
const names = [];
|
|
21
|
+
for (let i = 0; i < args.namedChildCount; i++) {
|
|
22
|
+
const arg = args.namedChild(i);
|
|
23
|
+
if (!arg)
|
|
24
|
+
continue;
|
|
25
|
+
// simple_symbol text is :name — strip the leading colon
|
|
26
|
+
const text = arg.text;
|
|
27
|
+
names.push(text.startsWith(':') ? text.slice(1) : text);
|
|
28
|
+
}
|
|
29
|
+
return names;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Ruby field extraction config.
|
|
33
|
+
*
|
|
34
|
+
* Ruby is unusual: there are no field declarations in the traditional sense.
|
|
35
|
+
* Fields are instance variables (@var) created by assignment, or declared
|
|
36
|
+
* via attr_accessor / attr_reader / attr_writer calls.
|
|
37
|
+
*
|
|
38
|
+
* We detect:
|
|
39
|
+
* - `call` nodes for attr_accessor / attr_reader / attr_writer
|
|
40
|
+
* (their arguments are symbol names → field names)
|
|
41
|
+
*
|
|
42
|
+
* For simplicity we focus on attr_* calls in the class body.
|
|
43
|
+
* Instance variable assignments (self.x = ...) would require deeper analysis.
|
|
44
|
+
*/
|
|
45
|
+
export const rubyConfig = {
|
|
46
|
+
language: SupportedLanguages.Ruby,
|
|
47
|
+
typeDeclarationNodes: ['class'],
|
|
48
|
+
fieldNodeTypes: ['call'],
|
|
49
|
+
bodyNodeTypes: ['body_statement'],
|
|
50
|
+
defaultVisibility: 'public',
|
|
51
|
+
extractName(node) {
|
|
52
|
+
// Returns the first symbol name for interface compatibility.
|
|
53
|
+
// Use extractNames to obtain all names from a single attr_* call.
|
|
54
|
+
return extractAttrNames(node)[0];
|
|
55
|
+
},
|
|
56
|
+
extractNames(node) {
|
|
57
|
+
return extractAttrNames(node);
|
|
58
|
+
},
|
|
59
|
+
extractType(_node) {
|
|
60
|
+
// Ruby is dynamically typed; no type annotations in standard Ruby
|
|
61
|
+
return undefined;
|
|
62
|
+
},
|
|
63
|
+
extractVisibility(_node) {
|
|
64
|
+
// attr_accessor/attr_writer fields are effectively public
|
|
65
|
+
// attr_reader fields are read-only from outside but still public
|
|
66
|
+
return 'public';
|
|
67
|
+
},
|
|
68
|
+
isStatic(_node) {
|
|
69
|
+
return false;
|
|
70
|
+
},
|
|
71
|
+
isReadonly(node) {
|
|
72
|
+
const method = node.childForFieldName('method');
|
|
73
|
+
return method?.text === 'attr_reader';
|
|
74
|
+
},
|
|
75
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FieldExtractionConfig } from '../generic.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rust field extraction config.
|
|
4
|
+
*
|
|
5
|
+
* Handles struct fields (named and tuple variants are out of scope).
|
|
6
|
+
* Visibility: `pub` keyword = public, otherwise private (crate-private).
|
|
7
|
+
* All fields are immutable by default in Rust (mutability is on the binding).
|
|
8
|
+
*/
|
|
9
|
+
export declare const rustConfig: FieldExtractionConfig;
|