Analyze an RPG Codebase
The analyzer module sits on top of symbol resolution and produces editor-oriented artifacts:
- a dependency graph (files, procedures/subroutines, and edges such as COPY, CALL, EXSR, prototype→implementation)
- a sequence-diagram catalog (PlantUML per procedure / subroutine)
- a go-to-definition catalog of navigable
ReferenceByNamefeatures
Add Dependencies
- Kotlin
- Java
repositories {
mavenLocal()
mavenCentral()
flatDir {
dirs("deps")
}
}
dependencies {
implementation(files("deps/rpgparser-2.2.0-all.jar"))
implementation(files("deps/rpgparser-symbol-resolution-2.2.0.jar"))
implementation(files("deps/rpgparser-analyzer-2.2.0.jar"))
implementation("com.strumenta.kolasu:kolasu-codebase:1.5.107")
implementation("com.strumenta.kolasu:kolasu-semantics:1.5.107")
}
repositories {
mavenLocal()
mavenCentral()
flatDir {
dirs("deps")
}
}
dependencies {
implementation(files("deps/rpgparser-2.2.0-all.jar"))
implementation(files("deps/rpgparser-symbol-resolution-2.2.0.jar"))
implementation(files("deps/rpgparser-analyzer-2.2.0.jar"))
implementation "com.strumenta.kolasu:kolasu-javalib:1.5.107"
implementation "com.strumenta.kolasu:kolasu-codebase:1.5.107"
implementation "com.strumenta.kolasu:kolasu-semantics:1.5.107"
}
Maven coordinates: com.strumenta:rpg-parser-analyzer (depends on rpg-parser-symbol-resolution).
Run the full analysis suite
The shortest path is Codebase.analyzeForEditor(), which resolves symbols and runs every analyzer pass. You can also construct RPGAnalyzer yourself when you already have an RPGSemanticsAnalysisResult.
- Kotlin
- Java
import com.strumenta.rpgparser.analyzer.RPGAnalyzer
import com.strumenta.rpgparser.analyzer.analyzeForEditor
import com.strumenta.rpgparser.analyzer.model.DependencyKind
import com.strumenta.rpgparser.symbolresolution.rpgCodebase
import com.strumenta.rpgparser.symbolresolution.resolveSymbolsForRPG
import java.io.File
fun analyzeProject(projectDir: File, license: File) {
val codebase = rpgCodebase(projectDir, license)
// Option A — one liner
val result = codebase.analyzeForEditor()
// Option B — resolve first, then analyze
// val analysis = codebase.resolveSymbolsForRPG()
// val result = RPGAnalyzer(analysis).analyze()
println("Behaviors: ${result.dependencyGraph.behaviors.size}")
println("Edges: ${result.dependencyGraph.edges.size}")
result.dependencyGraph.edges
.filter { it.kind == DependencyKind.InvokeSubroutine }
.forEach { edge ->
println("EXSR: ${edge.from.name} → ${edge.to.name}")
}
result.sequenceDiagramCatalog.diagrams.take(3).forEach { diagram ->
println("--- ${diagram.subjectKind} ${diagram.subjectName} (${diagram.moduleName}) ---")
println(diagram.plantUml.take(200) + "…")
}
println("Go-to-definition features: ${result.goToDefinitionCatalog.entries.size}")
}
import com.strumenta.kolasu.ids.CommonNodeIdProvider;
import com.strumenta.rpgparser.analyzer.RPGAnalyzer;
import com.strumenta.rpgparser.analyzer.RPGAnalyzerKt;
import com.strumenta.rpgparser.analyzer.model.DependencyKind;
import com.strumenta.rpgparser.symbolresolution.UtilsKt;
import java.io.File;
public class AnalyzeProject {
public static void analyzeProject(File projectDir, File license) {
var codebase = UtilsKt.rpgCodebase(projectDir, license, "UnnamedCodebase");
var result = RPGAnalyzerKt.analyzeForEditor(codebase, new CommonNodeIdProvider());
System.out.println("Behaviors: " + result.getDependencyGraph().getBehaviors().size());
System.out.println("Edges: " + result.getDependencyGraph().getEdges().size());
result.getDependencyGraph().getEdges().stream()
.filter(edge -> edge.getKind() == DependencyKind.InvokeSubroutine)
.forEach(edge -> System.out.println(
"EXSR: " + edge.getFrom().getName() + " → " + edge.getTo().getName()));
result.getSequenceDiagramCatalog().getDiagrams().stream().limit(3).forEach(diagram -> {
System.out.println("--- " + diagram.getSubjectKind() + " "
+ diagram.getSubjectName() + " ---");
System.out.println(diagram.getPlantUml().substring(0,
Math.min(200, diagram.getPlantUml().length())) + "…");
});
}
}
Dependency kinds
Edges in DependencyGraph use DependencyKind:
| Kind | Meaning |
|---|---|
CopyInclude | /COPY or /INCLUDE between files |
CallProgram | CALL to an external program |
CallProcedure | Bound / prototype procedure call |
InvokeSubroutine | EXSR |
PrototypeImpl | Prototype linked to its Procedure implementation |
Sequence diagrams
Each entry in sequenceDiagramCatalog carries PlantUML text for a procedure or subroutine (including the virtual main routine). Render it with any PlantUML tooling, or use it as a documentation artifact during migration scoping.
Export a LionWeb snapshot
RPGAnalyzer.exportSnapshot() packages go-to-definition, sequence diagrams, and the dependency graph as a ZIP of LionWeb .binpb chunks. This is useful for integration with other tools using LionWeb (an open standard in language engineering).
val analysis = codebase.resolveSymbolsForRPG()
val zipBytes: ByteArray = RPGAnalyzer(analysis).exportSnapshot()
File("rpg-analysis.zip").writeBytes(zipBytes)