Skip to content

Commit 51f659f

Browse files
committed
checkpoint: pre-yolo 20260404-155212
1 parent a8f264a commit 51f659f

6 files changed

Lines changed: 117 additions & 116 deletions

File tree

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ public DetectorResult detect(DetectorContext ctx) {
6767
List<CodeNode> nodes = new ArrayList<>();
6868
List<CodeEdge> edges = new ArrayList<>();
6969

70-
String currentTable = null;
7170
String currentTableId = null;
7271

7372
for (IndexedLine il : iterLines(content)) {
@@ -79,7 +78,6 @@ public DetectorResult detect(DetectorContext ctx) {
7978
m = TABLE_RE.matcher(line);
8079
if (m.find()) {
8180
String tableName = m.group(1);
82-
currentTable = tableName;
8381
currentTableId = "sql:" + filepath + ":table:" + tableName;
8482

8583
CodeNode node = new CodeNode(currentTableId, NodeKind.ENTITY, tableName);
@@ -104,7 +102,6 @@ public DetectorResult detect(DetectorContext ctx) {
104102
node.setLineStart(lineNum);
105103
node.setProperties(Map.of("entity_type", "view"));
106104
nodes.add(node);
107-
currentTable = null;
108105
currentTableId = null;
109106
continue;
110107
}
@@ -136,7 +133,6 @@ public DetectorResult detect(DetectorContext ctx) {
136133
node.setLineStart(lineNum);
137134
node.setProperties(Map.of("entity_type", "procedure"));
138135
nodes.add(node);
139-
currentTable = null;
140136
currentTableId = null;
141137
continue;
142138
}

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

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
@Component
3636
public class ClassHierarchyDetector extends AbstractJavaParserDetector {
3737

38+
private static final String PROP_INTERFACES = "interfaces";
39+
private static final String PROP_IS_ABSTRACT = "is_abstract";
40+
private static final String PROP_IS_FINAL = "is_final";
41+
private static final String PROP_VISIBILITY = "visibility";
42+
3843
// ---- Regex patterns for fallback ----
3944
private static final Pattern CLASS_DECL_RE = Pattern.compile(
4045
"(public\\s+|protected\\s+|private\\s+)?(abstract\\s+)?(final\\s+)?class\\s+(\\w+)"
@@ -100,9 +105,9 @@ private DetectorResult detectWithAst(CompilationUnit cu, DetectorContext ctx) {
100105
}
101106

102107
Map<String, Object> props = new LinkedHashMap<>();
103-
props.put("visibility", visibility);
104-
props.put("is_abstract", isAbstract);
105-
props.put("is_final", isFinal);
108+
props.put(PROP_VISIBILITY, visibility);
109+
props.put(PROP_IS_ABSTRACT, isAbstract);
110+
props.put(PROP_IS_FINAL, isFinal);
106111

107112
// Extended types
108113
List<String> extendedTypes = new ArrayList<>();
@@ -111,7 +116,7 @@ private DetectorResult detectWithAst(CompilationUnit cu, DetectorContext ctx) {
111116
}
112117
if (!extendedTypes.isEmpty()) {
113118
if (isInterface) {
114-
props.put("interfaces", extendedTypes);
119+
props.put(PROP_INTERFACES, extendedTypes);
115120
} else {
116121
props.put("superclass", extendedTypes.get(0));
117122
}
@@ -123,7 +128,7 @@ private DetectorResult detectWithAst(CompilationUnit cu, DetectorContext ctx) {
123128
implementedTypes.add(impl.getNameAsString());
124129
}
125130
if (!implementedTypes.isEmpty()) {
126-
props.put("interfaces", implementedTypes);
131+
props.put(PROP_INTERFACES, implementedTypes);
127132
}
128133

129134
CodeNode node = new CodeNode();
@@ -189,10 +194,10 @@ private DetectorResult detectWithAst(CompilationUnit cu, DetectorContext ctx) {
189194
}
190195

191196
Map<String, Object> props = new LinkedHashMap<>();
192-
props.put("visibility", visibility);
193-
props.put("is_abstract", false);
194-
props.put("is_final", false);
195-
if (!interfaces.isEmpty()) props.put("interfaces", interfaces);
197+
props.put(PROP_VISIBILITY, visibility);
198+
props.put(PROP_IS_ABSTRACT, false);
199+
props.put(PROP_IS_FINAL, false);
200+
if (!interfaces.isEmpty()) props.put(PROP_INTERFACES, interfaces);
196201

197202
CodeNode node = new CodeNode();
198203
node.setId(nodeId);
@@ -229,9 +234,9 @@ private DetectorResult detectWithAst(CompilationUnit cu, DetectorContext ctx) {
229234
: "package-private";
230235

231236
Map<String, Object> props = new LinkedHashMap<>();
232-
props.put("visibility", visibility);
233-
props.put("is_abstract", false);
234-
props.put("is_final", false);
237+
props.put(PROP_VISIBILITY, visibility);
238+
props.put(PROP_IS_ABSTRACT, false);
239+
props.put(PROP_IS_FINAL, false);
235240

236241
CodeNode node = new CodeNode();
237242
node.setId(nodeId);
@@ -278,11 +283,11 @@ private DetectorResult detectWithRegex(DetectorContext ctx) {
278283
NodeKind kind = isAbstract ? NodeKind.ABSTRACT_CLASS : NodeKind.CLASS;
279284

280285
Map<String, Object> props = new LinkedHashMap<>();
281-
props.put("visibility", visibility);
282-
props.put("is_abstract", isAbstract);
283-
props.put("is_final", isFinal);
286+
props.put(PROP_VISIBILITY, visibility);
287+
props.put(PROP_IS_ABSTRACT, isAbstract);
288+
props.put(PROP_IS_FINAL, isFinal);
284289
if (superclass != null) props.put("superclass", superclass);
285-
if (!interfaces.isEmpty()) props.put("interfaces", interfaces);
290+
if (!interfaces.isEmpty()) props.put(PROP_INTERFACES, interfaces);
286291

287292
CodeNode node = new CodeNode();
288293
node.setId(nodeId);
@@ -322,10 +327,10 @@ private DetectorResult detectWithRegex(DetectorContext ctx) {
322327

323328
String nodeId = ctx.filePath() + ":" + name;
324329
Map<String, Object> props = new LinkedHashMap<>();
325-
props.put("visibility", visibility);
326-
props.put("is_abstract", false);
327-
props.put("is_final", false);
328-
if (!extended.isEmpty()) props.put("interfaces", extended);
330+
props.put(PROP_VISIBILITY, visibility);
331+
props.put(PROP_IS_ABSTRACT, false);
332+
props.put(PROP_IS_FINAL, false);
333+
if (!extended.isEmpty()) props.put(PROP_INTERFACES, extended);
329334

330335
CodeNode node = new CodeNode();
331336
node.setId(nodeId);
@@ -357,10 +362,10 @@ private DetectorResult detectWithRegex(DetectorContext ctx) {
357362

358363
String nodeId = ctx.filePath() + ":" + name;
359364
Map<String, Object> props = new LinkedHashMap<>();
360-
props.put("visibility", visibility);
361-
props.put("is_abstract", false);
362-
props.put("is_final", false);
363-
if (!interfaces.isEmpty()) props.put("interfaces", interfaces);
365+
props.put(PROP_VISIBILITY, visibility);
366+
props.put(PROP_IS_ABSTRACT, false);
367+
props.put(PROP_IS_FINAL, false);
368+
if (!interfaces.isEmpty()) props.put(PROP_INTERFACES, interfaces);
364369

365370
CodeNode node = new CodeNode();
366371
node.setId(nodeId);
@@ -391,9 +396,9 @@ private DetectorResult detectWithRegex(DetectorContext ctx) {
391396

392397
String nodeId = ctx.filePath() + ":" + name;
393398
Map<String, Object> props = new LinkedHashMap<>();
394-
props.put("visibility", visibility);
395-
props.put("is_abstract", false);
396-
props.put("is_final", false);
399+
props.put(PROP_VISIBILITY, visibility);
400+
props.put(PROP_IS_ABSTRACT, false);
401+
props.put(PROP_IS_FINAL, false);
397402

398403
CodeNode node = new CodeNode();
399404
node.setId(nodeId);

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

Lines changed: 82 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -88,47 +88,15 @@ private DetectorResult detectWithAst(CompilationUnit cu, DetectorContext ctx) {
8888
List<CodeEdge> edges = new ArrayList<>();
8989

9090
cu.findAll(ClassOrInterfaceDeclaration.class).forEach(classDecl -> {
91-
// Only process @Entity annotated classes
9291
boolean isEntity = classDecl.getAnnotations().stream()
9392
.anyMatch(a -> "Entity".equals(a.getNameAsString()));
9493
if (!isEntity) return;
9594

9695
String className = classDecl.getNameAsString();
9796
String fqn = resolveFqn(cu, className);
9897
int classLine = classDecl.getBegin().map(p -> p.line).orElse(1);
99-
100-
// Extract table name from @Table annotation
101-
String tableName = className.toLowerCase();
102-
for (AnnotationExpr ann : classDecl.getAnnotations()) {
103-
if ("Table".equals(ann.getNameAsString())) {
104-
String name = extractAnnotationStringAttr(ann, "name");
105-
if (name == null) {
106-
// Try bare value
107-
name = extractAnnotationValue(ann);
108-
}
109-
if (name != null) tableName = name;
110-
}
111-
}
112-
113-
// Extract columns from fields
114-
List<Map<String, String>> columns = new ArrayList<>();
115-
for (FieldDeclaration field : classDecl.getFields()) {
116-
for (VariableDeclarator var : field.getVariables()) {
117-
String fieldName = var.getNameAsString();
118-
String fieldType = var.getTypeAsString();
119-
120-
// Check for @Column annotation
121-
for (AnnotationExpr ann : field.getAnnotations()) {
122-
if ("Column".equals(ann.getNameAsString())) {
123-
String colName = extractAnnotationStringAttr(ann, "name");
124-
if (colName == null) colName = fieldName;
125-
columns.add(Map.of("name", colName, "field", fieldName, "type", fieldType));
126-
} else if ("Id".equals(ann.getNameAsString())) {
127-
columns.add(Map.of("name", fieldName, "field", fieldName, "type", fieldType));
128-
}
129-
}
130-
}
131-
}
98+
String tableName = extractTableName(classDecl, className);
99+
List<Map<String, String>> columns = extractColumns(classDecl);
132100

133101
String entityId = ctx.filePath() + ":" + className;
134102
Map<String, Object> properties = new LinkedHashMap<>();
@@ -148,59 +116,92 @@ private DetectorResult detectWithAst(CompilationUnit cu, DetectorContext ctx) {
148116
nodes.add(node);
149117
DetectorDbHelper.addDbEdge(entityId, ctx.registry(), nodes, edges);
150118

151-
// Extract relationship edges from fields
152-
for (FieldDeclaration field : classDecl.getFields()) {
153-
for (AnnotationExpr ann : field.getAnnotations()) {
154-
String annName = ann.getNameAsString();
155-
if (!RELATIONSHIP_ANNOTATIONS.contains(annName)) continue;
119+
extractRelationshipEdges(classDecl, entityId, edges);
120+
});
156121

157-
String relType = RELATIONSHIP_TYPES.get(annName);
122+
return DetectorResult.of(nodes, edges);
123+
}
158124

159-
// Resolve target entity
160-
String targetEntity = extractAnnotationStringAttr(ann, "targetEntity");
161-
if (targetEntity != null && targetEntity.endsWith(".class")) {
162-
targetEntity = targetEntity.replace(".class", "");
163-
}
125+
private String extractTableName(ClassOrInterfaceDeclaration classDecl, String className) {
126+
for (AnnotationExpr ann : classDecl.getAnnotations()) {
127+
if (!"Table".equals(ann.getNameAsString())) continue;
128+
String name = extractAnnotationStringAttr(ann, "name");
129+
if (name == null) name = extractAnnotationValue(ann);
130+
if (name != null) return name;
131+
}
132+
return className.toLowerCase();
133+
}
164134

165-
if (targetEntity == null) {
166-
// Try to resolve from field type / generic type argument
167-
for (VariableDeclarator var : field.getVariables()) {
168-
Type type = var.getType();
169-
if (type.isClassOrInterfaceType()) {
170-
ClassOrInterfaceType cit = type.asClassOrInterfaceType();
171-
if (cit.getTypeArguments().isPresent()) {
172-
// Generic type like List<Order> -> Order
173-
var typeArgs = cit.getTypeArguments().get();
174-
if (!typeArgs.isEmpty()) {
175-
targetEntity = typeArgs.get(0).asString();
176-
}
177-
} else {
178-
targetEntity = cit.getNameAsString();
179-
}
180-
break;
181-
}
182-
}
183-
}
135+
private List<Map<String, String>> extractColumns(ClassOrInterfaceDeclaration classDecl) {
136+
List<Map<String, String>> columns = new ArrayList<>();
137+
for (FieldDeclaration field : classDecl.getFields()) {
138+
for (VariableDeclarator var : field.getVariables()) {
139+
addColumnFromAnnotations(field, var.getNameAsString(), var.getTypeAsString(), columns);
140+
}
141+
}
142+
return columns;
143+
}
184144

185-
if (targetEntity != null) {
186-
String mappedBy = extractAnnotationStringAttr(ann, "mappedBy");
187-
Map<String, Object> edgeProps = new LinkedHashMap<>();
188-
edgeProps.put("relationship_type", relType);
189-
if (mappedBy != null) edgeProps.put("mapped_by", mappedBy);
190-
191-
CodeEdge edge = new CodeEdge();
192-
edge.setId(entityId + "->maps_to->*:" + targetEntity);
193-
edge.setKind(EdgeKind.MAPS_TO);
194-
edge.setSourceId(entityId);
195-
edge.setTarget(new CodeNode("*:" + targetEntity, NodeKind.ENTITY, targetEntity));
196-
edge.setProperties(edgeProps);
197-
edges.add(edge);
198-
}
199-
}
145+
private void addColumnFromAnnotations(FieldDeclaration field, String fieldName,
146+
String fieldType, List<Map<String, String>> columns) {
147+
for (AnnotationExpr ann : field.getAnnotations()) {
148+
if ("Column".equals(ann.getNameAsString())) {
149+
String colName = extractAnnotationStringAttr(ann, "name");
150+
if (colName == null) colName = fieldName;
151+
columns.add(Map.of("name", colName, "field", fieldName, "type", fieldType));
152+
} else if ("Id".equals(ann.getNameAsString())) {
153+
columns.add(Map.of("name", fieldName, "field", fieldName, "type", fieldType));
200154
}
201-
});
155+
}
156+
}
202157

203-
return DetectorResult.of(nodes, edges);
158+
private void extractRelationshipEdges(ClassOrInterfaceDeclaration classDecl,
159+
String entityId, List<CodeEdge> edges) {
160+
for (FieldDeclaration field : classDecl.getFields()) {
161+
for (AnnotationExpr ann : field.getAnnotations()) {
162+
String annName = ann.getNameAsString();
163+
if (!RELATIONSHIP_ANNOTATIONS.contains(annName)) continue;
164+
165+
String relType = RELATIONSHIP_TYPES.get(annName);
166+
String targetEntity = resolveTargetEntity(ann, field);
167+
if (targetEntity == null) continue;
168+
169+
String mappedBy = extractAnnotationStringAttr(ann, "mappedBy");
170+
Map<String, Object> edgeProps = new LinkedHashMap<>();
171+
edgeProps.put("relationship_type", relType);
172+
if (mappedBy != null) edgeProps.put("mapped_by", mappedBy);
173+
174+
CodeEdge edge = new CodeEdge();
175+
edge.setId(entityId + "->maps_to->*:" + targetEntity);
176+
edge.setKind(EdgeKind.MAPS_TO);
177+
edge.setSourceId(entityId);
178+
edge.setTarget(new CodeNode("*:" + targetEntity, NodeKind.ENTITY, targetEntity));
179+
edge.setProperties(edgeProps);
180+
edges.add(edge);
181+
}
182+
}
183+
}
184+
185+
private String resolveTargetEntity(AnnotationExpr ann, FieldDeclaration field) {
186+
String targetEntity = extractAnnotationStringAttr(ann, "targetEntity");
187+
if (targetEntity != null && targetEntity.endsWith(".class")) {
188+
targetEntity = targetEntity.replace(".class", "");
189+
}
190+
if (targetEntity != null) return targetEntity;
191+
192+
for (VariableDeclarator var : field.getVariables()) {
193+
Type type = var.getType();
194+
if (!type.isClassOrInterfaceType()) continue;
195+
ClassOrInterfaceType cit = type.asClassOrInterfaceType();
196+
if (cit.getTypeArguments().isPresent()) {
197+
var typeArgs = cit.getTypeArguments().get();
198+
if (!typeArgs.isEmpty()) return typeArgs.get(0).asString();
199+
} else {
200+
return cit.getNameAsString();
201+
}
202+
break;
203+
}
204+
return null;
204205
}
205206

206207
private String extractAnnotationStringAttr(AnnotationExpr ann, String attrName) {

src/main/java/io/github/randomcodespace/iq/detector/python/CeleryTaskDetector.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ protected DetectorResult detectWithAst(ParseTree tree, DetectorContext ctx) {
6060
List<CodeEdge> edges = new ArrayList<>();
6161
String filePath = ctx.filePath();
6262
String moduleName = ctx.moduleName();
63-
String text = ctx.content();
6463

6564
// Walk for decorated functions (task definitions)
6665
ParseTreeWalker.DEFAULT.walk(new Python3ParserBaseListener() {

src/main/java/io/github/randomcodespace/iq/detector/python/PythonStructuresDetector.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,12 @@ public void enterImport_from(Python3Parser.Import_fromContext importCtx) {
148148
// from os.path import join
149149
StringBuilder fromModule = new StringBuilder();
150150
if (importCtx.DOT() != null) {
151-
for (var dot : importCtx.DOT()) {
151+
for (var ignored : importCtx.DOT()) {
152152
fromModule.append(".");
153153
}
154154
}
155155
if (importCtx.ELLIPSIS() != null) {
156-
for (var ellipsis : importCtx.ELLIPSIS()) {
156+
for (var ignored : importCtx.ELLIPSIS()) {
157157
fromModule.append("...");
158158
}
159159
}

src/test/java/io/github/randomcodespace/iq/analyzer/StructuredParserTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void parsesNestedYaml() {
6969
@Test
7070
void invalidYamlReturnsNull() {
7171
// SnakeYAML is quite lenient, but truly broken input should not crash
72-
Object result = parser.parse("yaml", ":::\n---\n{{invalid", "bad.yaml");
72+
parser.parse("yaml", ":::\n---\n{{invalid", "bad.yaml");
7373
// May return null or a partial parse — just don't throw
7474
// (SnakeYAML treats many things as strings, so this might not be null)
7575
}

0 commit comments

Comments
 (0)