Port extraction quality improvements from PR #15
- Fix arrow function extraction: explicitly call extractFunction() for arrow functions/function expressions in variable declarations instead of silently skipping them (all 6 arrow function tests now pass) - Best-candidate resolution: collect candidates from all strategies and return highest confidence match instead of first match - Fix graph traversal 'both' direction: correctly determine next node for mixed incoming/outgoing edges in BFS and DFS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
d80900f653
commit
94c8d5ccaa
@@ -1294,9 +1294,10 @@ export class TreeSitterExtractor {
|
|||||||
|
|
||||||
if (nameNode) {
|
if (nameNode) {
|
||||||
const name = getNodeText(nameNode, this.source);
|
const name = getNodeText(nameNode, this.source);
|
||||||
// Skip if it looks like a function (arrow function or function expression)
|
// Arrow functions / function expressions: extract as function instead of variable
|
||||||
if (valueNode && (valueNode.type === 'arrow_function' || valueNode.type === 'function_expression')) {
|
if (valueNode && (valueNode.type === 'arrow_function' || valueNode.type === 'function_expression')) {
|
||||||
continue; // Already handled by function extraction
|
this.extractFunction(valueNode);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capture first 100 chars of initializer for context (stored in signature for searchability)
|
// Capture first 100 chars of initializer for context (stored in signature for searchability)
|
||||||
|
|||||||
@@ -85,7 +85,9 @@ export class GraphTraverser {
|
|||||||
const adjacentEdges = this.getAdjacentEdges(node.id, opts.direction, opts.edgeKinds);
|
const adjacentEdges = this.getAdjacentEdges(node.id, opts.direction, opts.edgeKinds);
|
||||||
|
|
||||||
for (const adjEdge of adjacentEdges) {
|
for (const adjEdge of adjacentEdges) {
|
||||||
const nextNodeId = opts.direction === 'incoming' ? adjEdge.source : adjEdge.target;
|
// Determine next node: for 'both' direction, edges can be either
|
||||||
|
// incoming or outgoing, so pick whichever end is not the current node
|
||||||
|
const nextNodeId = adjEdge.source === node.id ? adjEdge.target : adjEdge.source;
|
||||||
|
|
||||||
if (visited.has(nextNodeId)) {
|
if (visited.has(nextNodeId)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -169,7 +171,9 @@ export class GraphTraverser {
|
|||||||
const adjacentEdges = this.getAdjacentEdges(node.id, opts.direction, opts.edgeKinds);
|
const adjacentEdges = this.getAdjacentEdges(node.id, opts.direction, opts.edgeKinds);
|
||||||
|
|
||||||
for (const edge of adjacentEdges) {
|
for (const edge of adjacentEdges) {
|
||||||
const nextNodeId = opts.direction === 'incoming' ? edge.source : edge.target;
|
// Determine next node: for 'both' direction, edges can be either
|
||||||
|
// incoming or outgoing, so pick whichever end is not the current node
|
||||||
|
const nextNodeId = edge.source === node.id ? edge.target : edge.source;
|
||||||
|
|
||||||
if (visited.has(nextNodeId)) {
|
if (visited.has(nextNodeId)) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
+14
-5
@@ -246,27 +246,36 @@ export class ReferenceResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strategy 1: Try framework-specific resolution first
|
const candidates: ResolvedRef[] = [];
|
||||||
|
|
||||||
|
// Strategy 1: Try framework-specific resolution
|
||||||
for (const framework of this.frameworks) {
|
for (const framework of this.frameworks) {
|
||||||
const result = framework.resolve(ref, this.context);
|
const result = framework.resolve(ref, this.context);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
if (result.confidence >= 0.9) return result; // High confidence, return immediately
|
||||||
|
candidates.push(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strategy 2: Try import-based resolution
|
// Strategy 2: Try import-based resolution
|
||||||
const importResult = resolveViaImport(ref, this.context);
|
const importResult = resolveViaImport(ref, this.context);
|
||||||
if (importResult) {
|
if (importResult) {
|
||||||
return importResult;
|
if (importResult.confidence >= 0.9) return importResult;
|
||||||
|
candidates.push(importResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strategy 3: Try name matching
|
// Strategy 3: Try name matching
|
||||||
const nameResult = matchReference(ref, this.context);
|
const nameResult = matchReference(ref, this.context);
|
||||||
if (nameResult) {
|
if (nameResult) {
|
||||||
return nameResult;
|
candidates.push(nameResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
if (candidates.length === 0) return null;
|
||||||
|
|
||||||
|
// Return highest confidence candidate
|
||||||
|
return candidates.reduce((best, curr) =>
|
||||||
|
curr.confidence > best.confidence ? curr : best
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user