Skip to content

Commit 22c8e02

Browse files
committed
fix(parity): align Scala TS extractor kinds and inheritance with Rust engine (#708)
- trait_definition kind: 'trait' -> 'interface' (matches Rust) - object_definition kind: 'module' -> 'class' (matches Rust) - Inheritance: use found_extends flag to distinguish extends vs implements - Skip function-local val/var in Scala and let/var in Swift extractors - Update test expectations accordingly
1 parent e96ed95 commit 22c8e02

3 files changed

Lines changed: 32 additions & 11 deletions

File tree

src/extractors/scala.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ function handleScalaTraitDef(node: TreeSitterNode, ctx: ExtractorOutput): void {
8383

8484
ctx.definitions.push({
8585
name,
86-
kind: 'trait',
86+
kind: 'interface',
8787
line: node.startPosition.row + 1,
8888
endLine: nodeEndLine(node),
8989
children: children.length > 0 ? children : undefined,
@@ -100,7 +100,7 @@ function handleScalaObjectDef(node: TreeSitterNode, ctx: ExtractorOutput): void
100100

101101
ctx.definitions.push({
102102
name,
103-
kind: 'module',
103+
kind: 'class',
104104
line: node.startPosition.row + 1,
105105
endLine: nodeEndLine(node),
106106
children: children.length > 0 ? children : undefined,
@@ -172,8 +172,9 @@ function handleScalaCallExpression(node: TreeSitterNode, ctx: ExtractorOutput):
172172
}
173173

174174
function handleScalaValVarDef(node: TreeSitterNode, ctx: ExtractorOutput): void {
175-
// Only handle top-level vals/vars
175+
// Only handle top-level vals/vars — skip class members and function-local bindings
176176
if (node.parent?.type === 'template_body') return;
177+
if (node.parent?.type === 'block' || node.parent?.type === 'indented_block') return;
177178
const pattern = node.childForFieldName('pattern');
178179
if (!pattern) return;
179180
const nameNode = pattern.type === 'identifier' ? pattern : findChild(pattern, 'identifier');
@@ -192,15 +193,31 @@ function handleScalaValVarDef(node: TreeSitterNode, ctx: ExtractorOutput): void
192193
function extractScalaInheritance(node: TreeSitterNode, name: string, ctx: ExtractorOutput): void {
193194
const extendsClause = findChild(node, 'extends_clause');
194195
if (!extendsClause) return;
196+
let foundExtends = false;
195197
for (let i = 0; i < extendsClause.childCount; i++) {
196198
const child = extendsClause.child(i);
197199
if (!child) continue;
198-
if (child.type === 'type_identifier' || child.type === 'identifier') {
199-
ctx.classes.push({
200-
name,
201-
extends: child.text,
202-
line: node.startPosition.row + 1,
203-
});
200+
if (
201+
child.type === 'type_identifier' ||
202+
child.type === 'generic_type' ||
203+
child.type === 'identifier'
204+
) {
205+
const typeName = child.type === 'generic_type' ? child.child(0)?.text : child.text;
206+
if (!typeName) continue;
207+
if (!foundExtends) {
208+
ctx.classes.push({
209+
name,
210+
extends: typeName,
211+
line: node.startPosition.row + 1,
212+
});
213+
foundExtends = true;
214+
} else {
215+
ctx.classes.push({
216+
name,
217+
implements: typeName,
218+
line: node.startPosition.row + 1,
219+
});
220+
}
204221
}
205222
}
206223
}

src/extractors/swift.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ function handleSwiftPropertyDecl(node: TreeSitterNode, ctx: ExtractorOutput): vo
273273
) {
274274
return;
275275
}
276+
// Skip function-local let/var bindings
277+
if (node.parent?.type === 'statements' || node.parent?.type === 'function_body') {
278+
return;
279+
}
276280
const pattern = findChild(node, 'pattern');
277281
if (!pattern) return;
278282
const nameNode = findChild(pattern, 'simple_identifier');

tests/parsers/scala.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ describe('Scala parser', () => {
4444
it('extracts trait definitions', () => {
4545
const symbols = parseScala(`trait Serializable { def serialize(): String }`);
4646
expect(symbols.definitions).toContainEqual(
47-
expect.objectContaining({ name: 'Serializable', kind: 'trait', line: 1 }),
47+
expect.objectContaining({ name: 'Serializable', kind: 'interface', line: 1 }),
4848
);
4949
});
5050

5151
it('extracts object definitions', () => {
5252
const symbols = parseScala(`object Config { }`);
5353
expect(symbols.definitions).toContainEqual(
54-
expect.objectContaining({ name: 'Config', kind: 'module', line: 1 }),
54+
expect.objectContaining({ name: 'Config', kind: 'class', line: 1 }),
5555
);
5656
});
5757

0 commit comments

Comments
 (0)