Skip to content

Commit 91c032e

Browse files
authored
Merge pull request #32 from RandomCodeSpace/fix/sonar-issues
2 parents 541fc81 + 3482b22 commit 91c032e

15 files changed

Lines changed: 74 additions & 53 deletions

File tree

src/main/java/io/github/randomcodespace/iq/CodeIqApplication.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,9 @@ public static void main(String[] args) {
9393
graphDbPath = root.resolve(".osscodeiq/graph.db");
9494
}
9595

96-
if (java.nio.file.Files.isDirectory(graphDbPath)) {
97-
// Enriched Neo4j graph exists -- point Neo4j config to it
98-
System.setProperty("codeiq.graph.path", graphDbPath.toString());
99-
} else {
100-
// No enriched graph -- Neo4j will start with an empty db,
101-
// GraphBootstrapper will auto-load from H2 cache if available
102-
System.setProperty("codeiq.graph.path", graphDbPath.toString());
103-
}
96+
// Point Neo4j config to the graph path (enriched or new empty db).
97+
// GraphBootstrapper will auto-load from H2 cache if no enriched graph exists.
98+
System.setProperty("codeiq.graph.path", graphDbPath.toString());
10499
} else if (isIndex) {
105100
app.setAdditionalProfiles("indexing");
106101
// Index command: no web server, no Neo4j

src/main/java/io/github/randomcodespace/iq/analyzer/Analyzer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,10 @@ private String getGitHead(Path repoPath) {
12971297
if (exitCode == 0 && sha.length() >= 7) {
12981298
return sha;
12991299
}
1300+
} catch (InterruptedException e) {
1301+
Thread.currentThread().interrupt();
1302+
log.debug("Could not determine git HEAD", e);
1303+
return null;
13001304
} catch (Exception e) {
13011305
log.debug("Could not determine git HEAD", e);
13021306
}

src/main/java/io/github/randomcodespace/iq/analyzer/FileDiscovery.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ private boolean isGitRepo(Path root) {
106106
int exitCode = process.waitFor();
107107
process.getInputStream().close();
108108
return exitCode == 0;
109-
} catch (IOException | InterruptedException e) {
109+
} catch (InterruptedException e) {
110+
Thread.currentThread().interrupt();
111+
return false;
112+
} catch (IOException e) {
110113
return false;
111114
}
112115
}
@@ -152,7 +155,11 @@ private List<DiscoveredFile> discoverViaGit(Path root) {
152155
}
153156
return result;
154157

155-
} catch (IOException | InterruptedException e) {
158+
} catch (InterruptedException e) {
159+
Thread.currentThread().interrupt();
160+
log.warn("git ls-files failed, falling back to filesystem walk", e);
161+
return discoverViaWalk(root);
162+
} catch (IOException e) {
156163
log.warn("git ls-files failed, falling back to filesystem walk", e);
157164
return discoverViaWalk(root);
158165
}

src/main/java/io/github/randomcodespace/iq/api/TopologyController.java

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.nio.file.Path;
2121
import java.util.List;
2222
import java.util.Map;
23+
import java.util.concurrent.atomic.AtomicReference;
2324

2425
/**
2526
* REST API controller for service topology queries.
@@ -32,8 +33,8 @@ public class TopologyController {
3233
private final TopologyService topologyService;
3334
private final GraphStore graphStore;
3435
private final CodeIqConfig config;
35-
private volatile List<CodeNode> cachedNodes;
36-
private volatile List<CodeEdge> cachedEdges;
36+
private final AtomicReference<List<CodeNode>> cachedNodes = new AtomicReference<>();
37+
private final AtomicReference<List<CodeEdge>> cachedEdges = new AtomicReference<>();
3738

3839
public TopologyController(TopologyService topologyService,
3940
@Autowired(required = false) GraphStore graphStore,
@@ -65,15 +66,16 @@ private boolean hasNeo4jData() {
6566
* Load data from Neo4j if available, otherwise from H2 cache.
6667
*/
6768
private synchronized void ensureDataLoaded() {
68-
if (cachedNodes != null) return;
69+
if (cachedNodes.get() != null) return;
6970

7071
// Try Neo4j first (has enriched data with SERVICE nodes)
7172
if (hasNeo4jData()) {
72-
cachedNodes = graphStore.findAll();
73+
List<CodeNode> nodes = graphStore.findAll();
74+
cachedNodes.set(nodes);
7375
// Collect edges from all nodes' relationship lists
74-
cachedEdges = cachedNodes.stream()
76+
cachedEdges.set(nodes.stream()
7577
.flatMap(n -> n.getEdges().stream())
76-
.toList();
78+
.toList());
7779
return;
7880
}
7981

@@ -83,89 +85,91 @@ private synchronized void ensureDataLoaded() {
8385
Path h2File = root.resolve(config.getCacheDir()).resolve("analysis-cache.mv.db");
8486
if (!Files.exists(h2File)) return;
8587
try (AnalysisCache cache = new AnalysisCache(cachePath)) {
86-
cachedNodes = cache.loadAllNodes();
87-
cachedEdges = cache.loadAllEdges();
88+
cachedNodes.set(cache.loadAllNodes());
89+
cachedEdges.set(cache.loadAllEdges());
8890
}
8991
}
9092

9193
/**
9294
* Invalidate the in-memory cache (e.g. after re-analysis).
9395
*/
9496
public synchronized void invalidateCache() {
95-
cachedNodes = null;
96-
cachedEdges = null;
97+
cachedNodes.set(null);
98+
cachedEdges.set(null);
9799
neo4jHasData = null;
98100
}
99101

100102
@GetMapping
101103
public Map<String, Object> getTopology() {
102104
ensureDataLoaded();
103-
requireCache();
104-
return topologyService.getTopology(cachedNodes, cachedEdges);
105+
List<CodeNode> nodes = requireCache();
106+
return topologyService.getTopology(nodes, cachedEdges.get());
105107
}
106108

107109
@GetMapping("/services/{name}")
108110
public Map<String, Object> serviceDetail(@PathVariable String name) {
109111
ensureDataLoaded();
110-
requireCache();
111-
return topologyService.serviceDetail(name, cachedNodes, cachedEdges);
112+
List<CodeNode> nodes = requireCache();
113+
return topologyService.serviceDetail(name, nodes, cachedEdges.get());
112114
}
113115

114116
@GetMapping("/services/{name}/deps")
115117
public Map<String, Object> serviceDependencies(@PathVariable String name) {
116118
ensureDataLoaded();
117-
requireCache();
118-
return topologyService.serviceDependencies(name, cachedNodes, cachedEdges);
119+
List<CodeNode> nodes = requireCache();
120+
return topologyService.serviceDependencies(name, nodes, cachedEdges.get());
119121
}
120122

121123
@GetMapping("/services/{name}/dependents")
122124
public Map<String, Object> serviceDependents(@PathVariable String name) {
123125
ensureDataLoaded();
124-
requireCache();
125-
return topologyService.serviceDependents(name, cachedNodes, cachedEdges);
126+
List<CodeNode> nodes = requireCache();
127+
return topologyService.serviceDependents(name, nodes, cachedEdges.get());
126128
}
127129

128130
@GetMapping("/blast-radius/{nodeId}")
129131
public Map<String, Object> blastRadius(@PathVariable String nodeId) {
130132
ensureDataLoaded();
131-
requireCache();
132-
return topologyService.blastRadius(nodeId, cachedNodes, cachedEdges);
133+
List<CodeNode> nodes = requireCache();
134+
return topologyService.blastRadius(nodeId, nodes, cachedEdges.get());
133135
}
134136

135137
@GetMapping("/path")
136138
public List<Map<String, Object>> findPath(
137139
@RequestParam("from") String source,
138140
@RequestParam("to") String target) {
139141
ensureDataLoaded();
140-
requireCache();
141-
return topologyService.findPath(source, target, cachedNodes, cachedEdges);
142+
List<CodeNode> nodes = requireCache();
143+
return topologyService.findPath(source, target, nodes, cachedEdges.get());
142144
}
143145

144146
@GetMapping("/bottlenecks")
145147
public List<Map<String, Object>> findBottlenecks() {
146148
ensureDataLoaded();
147-
requireCache();
148-
return topologyService.findBottlenecks(cachedNodes, cachedEdges);
149+
List<CodeNode> nodes = requireCache();
150+
return topologyService.findBottlenecks(nodes, cachedEdges.get());
149151
}
150152

151153
@GetMapping("/circular")
152154
public List<List<String>> findCircularDeps() {
153155
ensureDataLoaded();
154-
requireCache();
155-
return topologyService.findCircularDeps(cachedNodes, cachedEdges);
156+
List<CodeNode> nodes = requireCache();
157+
return topologyService.findCircularDeps(nodes, cachedEdges.get());
156158
}
157159

158160
@GetMapping("/dead")
159161
public List<Map<String, Object>> findDeadServices() {
160162
ensureDataLoaded();
161-
requireCache();
162-
return topologyService.findDeadServices(cachedNodes, cachedEdges);
163+
List<CodeNode> nodes = requireCache();
164+
return topologyService.findDeadServices(nodes, cachedEdges.get());
163165
}
164166

165-
private void requireCache() {
166-
if (cachedNodes == null) {
167+
private List<CodeNode> requireCache() {
168+
List<CodeNode> nodes = cachedNodes.get();
169+
if (nodes == null) {
167170
throw new ResponseStatusException(HttpStatus.NOT_FOUND,
168171
"No analysis cache found. Run analyze first.");
169172
}
173+
return nodes;
170174
}
171175
}

src/main/java/io/github/randomcodespace/iq/cli/BundleCommand.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ private int bundleSourceFiles(Path root, ZipOutputStream zos) {
382382
}
383383
return count;
384384
}
385+
} catch (InterruptedException e) {
386+
Thread.currentThread().interrupt();
385387
} catch (Exception ignored) {
386388
// Not a git repo or git not available
387389
}

src/main/java/io/github/randomcodespace/iq/detector/config/GitHubActionsDetector.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,12 @@ public DetectorResult detect(DetectorContext ctx) {
7878
// YAML parses bare "on" as Boolean.TRUE
7979
Object onTriggers = data.get("on");
8080
if (onTriggers == null) {
81-
onTriggers = data.get(Boolean.TRUE);
81+
// SnakeYAML may parse bare 'on' key as Boolean.TRUE — search by entry value
82+
onTriggers = data.entrySet().stream()
83+
.filter(e -> Boolean.TRUE.equals(e.getKey()))
84+
.map(java.util.Map.Entry::getValue)
85+
.findFirst()
86+
.orElse(null);
8287
}
8388
if (onTriggers == null) {
8489
onTriggers = data.get("true");

src/main/java/io/github/randomcodespace/iq/detector/csharp/CSharpStructuresDetector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ protected DetectorResult detectWithRegex(DetectorContext ctx) {
211211
String path = httpPath != null ? httpPath : "";
212212
String fullPath;
213213
if (finalClassRoute != null) {
214-
fullPath = "/" + finalClassRoute.replaceAll("^/+|/+$", "");
214+
fullPath = "/" + finalClassRoute.replaceAll("(^/+|/+$)", "");
215215
if (!path.isEmpty()) fullPath = fullPath + "/" + path.replaceAll("^/+", "");
216216
} else {
217217
fullPath = !path.isEmpty() ? "/" + path.replaceAll("^/+", "") : "/";

src/main/java/io/github/randomcodespace/iq/detector/java/GrpcServiceDetector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class GrpcServiceDetector extends AbstractRegexDetector {
3535
private static final Pattern METHOD_RE = Pattern.compile(
3636
"public\\s+(?:void|[\\w<>\\[\\]]+)\\s+(\\w+)\\s*\\(\\s*(\\w+)");
3737
private static final Pattern GRPC_STUB_RE = Pattern.compile(
38-
"(\\w+)Grpc\\.new(?:Blocking|Future|)Stub\\s*\\(");
38+
"(\\w+)Grpc\\.new(?:Blocking|Future)?Stub\\s*\\(");
3939

4040
@Override
4141
public String getName() {

src/main/java/io/github/randomcodespace/iq/detector/java/JdbcDetector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class JdbcDetector extends AbstractRegexDetector {
3333
private static final Pattern DRIVER_MANAGER_RE = Pattern.compile(
3434
"DriverManager\\s*\\.\\s*getConnection\\s*\\(\\s*\"(jdbc:[^\"]+)\"");
3535
private static final Pattern JDBC_TEMPLATE_RE = Pattern.compile(
36-
"(?:private|protected|public|final|\\s)+"
36+
"(?:private|protected|public|final)\\s+"
3737
+ "(?:final\\s+)?"
3838
+ "(JdbcTemplate|NamedParameterJdbcTemplate|JdbcClient)"
3939
+ "\\s+\\w+");

src/main/java/io/github/randomcodespace/iq/detector/java/JpaEntityDetector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ private DetectorResult detectWithAst(CompilationUnit cu, DetectorContext ctx) {
176176
} else {
177177
targetEntity = cit.getNameAsString();
178178
}
179+
break;
179180
}
180-
break;
181181
}
182182
}
183183

0 commit comments

Comments
 (0)