Skip to content

Commit f7390b7

Browse files
fix(intelligence): GoLanguageExtractor duplicate IMPORTS edges (RAN-170)
collectImportPaths() used an ArrayList allowing duplicate paths when a file has both a block import and a single-line import for the same package path. Switch to LinkedHashSet for deduplication (insertion order preserved), then return a new ArrayList to maintain the List<String> contract. Added test: extract_duplicateImportBothStyles_noDuplicateEdges verifies that a file with both import styles for the same package produces exactly one IMPORTS edge. Co-Authored-By: Paperclip <noreply@paperclip.ing>
1 parent eb049ce commit f7390b7

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

src/main/java/io/github/randomcodespace/iq/intelligence/extractor/go/GoLanguageExtractor.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212

1313
import java.util.ArrayList;
1414
import java.util.LinkedHashMap;
15+
import java.util.LinkedHashSet;
1516
import java.util.List;
1617
import java.util.Map;
18+
import java.util.Set;
1719
import java.util.regex.Matcher;
1820
import java.util.regex.Pattern;
1921

@@ -104,7 +106,7 @@ private List<CodeEdge> extractImportEdges(DetectorContext ctx, CodeNode node,
104106
}
105107

106108
private List<String> collectImportPaths(String content) {
107-
List<String> paths = new ArrayList<>();
109+
Set<String> paths = new LinkedHashSet<>();
108110

109111
Matcher block = IMPORT_BLOCK.matcher(content);
110112
if (block.find()) {
@@ -119,7 +121,7 @@ private List<String> collectImportPaths(String content) {
119121
paths.add(single.group(1));
120122
}
121123

122-
return paths;
124+
return new ArrayList<>(paths);
123125
}
124126

125127
/**

src/test/java/io/github/randomcodespace/iq/intelligence/extractor/go/GoLanguageExtractorTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,36 @@ void extract_confidence_isPartial() {
9797
assertThat(result.confidence()).isEqualTo(CapabilityLevel.PARTIAL);
9898
}
9999

100+
@Test
101+
void extract_duplicateImportBothStyles_noDuplicateEdges() {
102+
CodeNode source = node("go:main.go:fn:main", NodeKind.METHOD, "main");
103+
CodeNode target = node("go:handler.go:module:handler", NodeKind.MODULE, "handler");
104+
105+
Map<String, CodeNode> registry = Map.of(target.getLabel(), target);
106+
107+
// File has both a block import and a single-line import for the same package.
108+
// collectImportPaths() must deduplicate so only one IMPORTS edge is produced.
109+
String content = """
110+
package main
111+
112+
import (
113+
"myapp/handler"
114+
)
115+
import "myapp/handler"
116+
117+
func main() {
118+
handler.Handle()
119+
}
120+
""";
121+
122+
DetectorContext ctx = new DetectorContext("main.go", "go", content, registry, null);
123+
LanguageExtractionResult result = extractor.extract(ctx, source);
124+
125+
assertThat(result.symbolReferences()).hasSize(1);
126+
assertThat(result.symbolReferences().get(0).getKind()).isEqualTo(EdgeKind.IMPORTS);
127+
assertThat(result.symbolReferences().get(0).getTarget().getId()).isEqualTo(target.getId());
128+
}
129+
100130
@Test
101131
void extract_determinism_sameTwice() {
102132
CodeNode source = node("go:a.go:fn:run", NodeKind.METHOD, "run");

0 commit comments

Comments
 (0)