Skip to content

chore: improve cli error handling #2345

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,139 +40,144 @@
*/
@CommandLine.Command(name = "analysis", description = "analyse cobol source")
public class CliAnalysis implements Callable<Integer> {
@CommandLine.ParentCommand
private Cli parent;

@CommandLine.Option(
names = {"-s", "--source"},
required = true,
description = "The COBOL program file.")
private File src;

@CommandLine.ArgGroup(multiplicity = "1")
private Args args;

@CommandLine.Option(
description = "Supported dialect values: ${COMPLETION-CANDIDATES}",
names = {"-d", "--dialect"},
defaultValue = "COBOL")
private CobolLanguageId dialect;

@Override
public Integer call() throws Exception {
if (args.workspaceConfig != null)
parent.initProcessorGroupsReader(args.workspaceConfig.workspace);

Injector diCtx = Guice.createInjector(new CliModule());
CliClientProvider cliClientProvider = diCtx.getInstance(CliClientProvider.class);

cliClientProvider.setCpyPaths(createCopybooksPaths());
cliClientProvider.setCpyExt(createCopybooksExtensions());
JsonObject result = new JsonObject();

Cli.Result analysisResult = parent.runAnalysis(src, dialect, diCtx, true);
parent.addTiming(result, analysisResult.ctx.getBenchmarkSession());
JsonArray diagnostics = new JsonArray();
analysisResult
.ctx
.getAccumulatedErrors()
.forEach(
err -> {
JsonObject diagnostic = CliUtils.diagnosticToJson(err);
diagnostics.add(diagnostic);
});
result.add("diagnostics", diagnostics);
result.addProperty("uri", analysisResult.ctx.getExtendedDocument().getUri());
result.addProperty("language", analysisResult.ctx.getLanguageId().getId());
result.addProperty("lines", String.valueOf(analysisResult.ctx.getExtendedDocument().toString().split("\n").length));
result.addProperty("size", String.valueOf(analysisResult.ctx.getExtendedDocument().toString().length()));
collectGcAndMemoryStats(result);
System.out.println(CliUtils.GSON.toJson(result));
return 0;
}

private void collectGcAndMemoryStats(JsonObject result) {
long totalGarbageCollections = 0;
long garbageCollectionTime = 0;

for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) {
long count = gc.getCollectionCount();
if (count >= 0) {
totalGarbageCollections += count;
}
long time = gc.getCollectionTime();
if (time >= 0) {
garbageCollectionTime += time;
}
}
result.addProperty("gc.count", totalGarbageCollections);
// milliseconds to seconds
result.addProperty("gc.time", garbageCollectionTime * 0.001);

List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
long total = 0;
for (MemoryPoolMXBean memoryPoolMXBean : pools) {
if (memoryPoolMXBean.getType() == MemoryType.HEAP) {
long peakUsed = memoryPoolMXBean.getPeakUsage().getUsed();
total = total + peakUsed;
}
}
result.addProperty("memory.heap_peak", total / 1024 / 1024);
}
@CommandLine.ParentCommand
private Cli parent;

/**
* WorkspaceConfig options
*/
static class WorkspaceConfig {
@CommandLine.Option(
description = "Path to workspace folder.",
names = {"-ws", "--workspace"})
private Path workspace;
}

/**
* explicit config options
*/
static class ExplicitConfig {
@CommandLine.Option(
names = {"-cf", "--copybook-folder"},
description = "Path to the copybook folder.")
private File[] cpyPaths = {};
names = {"-s", "--source"},
required = true,
description = "The COBOL program file.")
private File src;

@CommandLine.ArgGroup(multiplicity = "1")
private Args args;

@CommandLine.Option(
names = {"-ce", "--copybook-extension"},
description = "List of copybook paths.")
private String[] cpyExt = {"", ".cpy"};
}

/**
* options for analysis command
*/
static class Args {
@CommandLine.ArgGroup(exclusive = false)
ExplicitConfig explicitConfig;

@CommandLine.ArgGroup(exclusive = false)
WorkspaceConfig workspaceConfig;
}

private List<File> createCopybooksPaths() {
if (args.workspaceConfig != null && parent.processorGroupsResolver != null) {
return parent
.processorGroupsResolver
.resolveCopybooksPaths(src.toPath(), args.workspaceConfig.workspace)
.stream()
.map(Path::toFile)
.collect(Collectors.toList());
description = "Supported dialect values: ${COMPLETION-CANDIDATES}",
names = {"-d", "--dialect"},
defaultValue = "COBOL")
private CobolLanguageId dialect;

@Override
public Integer call() throws Exception {
if (args.workspaceConfig != null)
parent.initProcessorGroupsReader(args.workspaceConfig.workspace);

Injector diCtx = Guice.createInjector(new CliModule());
CliClientProvider cliClientProvider = diCtx.getInstance(CliClientProvider.class);

cliClientProvider.setCpyPaths(createCopybooksPaths());
cliClientProvider.setCpyExt(createCopybooksExtensions());
JsonObject result = new JsonObject();
result.addProperty("uri", src.toURI().toString());
try {
Cli.Result analysisResult = parent.runAnalysis(src, dialect, diCtx, true);
parent.addTiming(result, analysisResult.ctx.getBenchmarkSession());
JsonArray diagnostics = new JsonArray();
analysisResult
.ctx
.getAccumulatedErrors()
.forEach(
err -> {
JsonObject diagnostic = CliUtils.diagnosticToJson(err);
diagnostics.add(diagnostic);
});
result.add("diagnostics", diagnostics);
result.addProperty("language", analysisResult.ctx.getLanguageId().getId());
result.addProperty("lines", String.valueOf(analysisResult.ctx.getExtendedDocument().toString().split("\n").length));
result.addProperty("size", String.valueOf(analysisResult.ctx.getExtendedDocument().toString().length()));
collectGcAndMemoryStats(result);
System.out.println(CliUtils.GSON.toJson(result));
return 0;
} catch (Exception e) {
result.addProperty("crash", e.getMessage() != null && e.getMessage().isEmpty() ? "error" : e.getMessage());
System.out.println(CliUtils.GSON.toJson(result));
return 1;
}
}

private void collectGcAndMemoryStats(JsonObject result) {
long totalGarbageCollections = 0;
long garbageCollectionTime = 0;

for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) {
long count = gc.getCollectionCount();
if (count >= 0) {
totalGarbageCollections += count;
}
long time = gc.getCollectionTime();
if (time >= 0) {
garbageCollectionTime += time;
}
}
result.addProperty("gc.count", totalGarbageCollections);
// milliseconds to seconds
result.addProperty("gc.time", garbageCollectionTime * 0.001);

List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
long total = 0;
for (MemoryPoolMXBean memoryPoolMXBean : pools) {
if (memoryPoolMXBean.getType() == MemoryType.HEAP) {
long peakUsed = memoryPoolMXBean.getPeakUsage().getUsed();
total = total + peakUsed;
}
}
result.addProperty("memory.heap_peak", total / 1024 / 1024);
}

/**
* WorkspaceConfig options
*/
static class WorkspaceConfig {
@CommandLine.Option(
description = "Path to workspace folder.",
names = {"-ws", "--workspace"})
private Path workspace;
}

/**
* explicit config options
*/
static class ExplicitConfig {
@CommandLine.Option(
names = {"-cf", "--copybook-folder"},
description = "Path to the copybook folder.")
private File[] cpyPaths = {};

@CommandLine.Option(
names = {"-ce", "--copybook-extension"},
description = "List of copybook paths.")
private String[] cpyExt = {"", ".cpy"};
}

/**
* options for analysis command
*/
static class Args {
@CommandLine.ArgGroup(exclusive = false)
ExplicitConfig explicitConfig;

@CommandLine.ArgGroup(exclusive = false)
WorkspaceConfig workspaceConfig;
}

private List<File> createCopybooksPaths() {
if (args.workspaceConfig != null && parent.processorGroupsResolver != null) {
return parent
.processorGroupsResolver
.resolveCopybooksPaths(src.toPath(), args.workspaceConfig.workspace)
.stream()
.map(Path::toFile)
.collect(Collectors.toList());
}
return Arrays.asList(args.explicitConfig.cpyPaths);
}
return Arrays.asList(args.explicitConfig.cpyPaths);
}

private List<String> createCopybooksExtensions() {
if (args.workspaceConfig != null && parent.processorGroupsResolver != null) {
return parent.processorGroupsResolver.resolveCopybooksExtensions(
src.toPath(), args.workspaceConfig.workspace);
private List<String> createCopybooksExtensions() {
if (args.workspaceConfig != null && parent.processorGroupsResolver != null) {
return parent.processorGroupsResolver.resolveCopybooksExtensions(
src.toPath(), args.workspaceConfig.workspace);
}
return Arrays.asList(args.explicitConfig.cpyExt);
}
return Arrays.asList(args.explicitConfig.cpyExt);
}
}
Loading