Skip to content
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

feat: add support for selecting language ID in COBOL LS cli #2332

Merged
Merged
Show file tree
Hide file tree
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
176 changes: 160 additions & 16 deletions server/engine/src/main/java/org/eclipse/lsp/cobol/cli/Cli.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,32 @@
import org.eclipse.lsp.cobol.common.benchmark.BenchmarkSession;
import org.eclipse.lsp.cobol.common.benchmark.Measurement;
import org.eclipse.lsp.cobol.common.copybook.CopybookProcessingMode;
import org.eclipse.lsp.cobol.common.dialects.TrueDialectService;
import org.eclipse.lsp.cobol.common.copybook.CopybookService;
import org.eclipse.lsp.cobol.common.dialects.CobolLanguageId;
import org.eclipse.lsp.cobol.common.error.SyntaxError;
import org.eclipse.lsp.cobol.common.mapping.ExtendedDocument;
import org.eclipse.lsp.cobol.common.mapping.ExtendedText;
import org.eclipse.lsp.cobol.common.message.MessageService;
import org.eclipse.lsp.cobol.core.engine.analysis.AnalysisContext;
import org.eclipse.lsp.cobol.core.engine.dialects.DialectService;
import org.eclipse.lsp.cobol.common.pipeline.Pipeline;
import org.eclipse.lsp.cobol.common.pipeline.PipelineResult;
import org.eclipse.lsp.cobol.common.pipeline.StageResult;
import org.eclipse.lsp.cobol.core.engine.analysis.AnalysisContext;
import org.eclipse.lsp.cobol.core.engine.dialects.DialectService;
import org.eclipse.lsp.cobol.core.engine.processor.AstProcessor;
import org.eclipse.lsp.cobol.core.engine.symbols.SymbolsRepository;
import org.eclipse.lsp.cobol.core.preprocessor.delegates.GrammarPreprocessor;
import org.eclipse.lsp.cobol.core.semantics.CopybooksRepository;
import org.eclipse.lsp.cobol.dialects.TrueDialectServiceImpl;
import org.eclipse.lsp.cobol.dialects.hp.HpCleanupStage;
import org.eclipse.lsp.cobol.dialects.hp.HpCopybookProcessingStage;
import org.eclipse.lsp.cobol.dialects.ibm.*;
import org.eclipse.lsp.cobol.common.dialects.CobolLanguageId;
import org.eclipse.lsp.cobol.dialects.ibm.experimental.ExperimentalParserStage;
import org.eclipse.lsp.cobol.service.settings.CachingConfigurationService;
import org.eclipse.lsp.cobol.service.settings.layout.CodeLayoutStore;
import org.eclipse.lsp4j.Location;
import picocli.CommandLine;

/**
* The Cli class represents a Command Line Interface (CLI) for interacting with the application.
*/
/** The Cli class represents a Command Line Interface (CLI) for interacting with the application. */
@CommandLine.Command(description = "COBOL Analysis CLI tools.")
@Slf4j
public class Cli implements Callable<Integer> {
Expand Down Expand Up @@ -85,6 +87,11 @@ private enum Action {
description = "List of copybook paths.")
private String[] cpyExt = {"", ".cpy"};

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

/**
* Prints the file name to the console and returns result code.
*
Expand All @@ -94,7 +101,7 @@ private enum Action {
@Override
public Integer call() throws Exception {
Injector diCtx = Guice.createInjector(new CliModule());
Pipeline<AnalysisContext> pipeline = setupPipeline(diCtx, action);
Pipeline<AnalysisContext> pipeline = setupPipeline(diCtx, action, dialect);

CliClientProvider cliClientProvider = diCtx.getInstance(CliClientProvider.class);
if (cpyPaths != null) {
Expand All @@ -103,7 +110,8 @@ public Integer call() throws Exception {
cliClientProvider.setCpyExt(Arrays.asList(cpyExt));

// Cleaning up
CleanerPreprocessor preprocessor = diCtx.getInstance(TrueDialectService.class).getPreprocessor(CobolLanguageId.COBOL);
CleanerPreprocessor preprocessor =
diCtx.getInstance(TrueDialectServiceImpl.class).getPreprocessor(dialect);
BenchmarkService benchmarkService = diCtx.getInstance(BenchmarkService.class);

if (src == null) {
Expand All @@ -117,7 +125,10 @@ public Integer call() throws Exception {
new AnalysisContext(
new ExtendedDocument(resultWithErrors.getResult(), text),
createAnalysisConfiguration(),
benchmarkService.startSession(), documentUri, text, CobolLanguageId.COBOL);
benchmarkService.startSession(),
documentUri,
text,
dialect);
ctx.getAccumulatedErrors().addAll(resultWithErrors.getErrors());
PipelineResult pipelineResult = pipeline.run(ctx);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Expand All @@ -134,7 +145,7 @@ public Integer call() throws Exception {
JsonObject diagnostic = toJson(err, gson);
diagnostics.add(diagnostic);
});
// result.add("diagnostics", diagnostics);
result.add("diagnostics", diagnostics);
break;
case list_copybooks:
StageResult<CopybooksRepository> copybooksResult =
Expand Down Expand Up @@ -177,8 +188,9 @@ private JsonObject toJson(SyntaxError syntaxError, Gson gson) {

private void addTiming(JsonObject result, BenchmarkSession benchmarkSession) {
JsonObject tObj = new JsonObject();
benchmarkSession.getMeasurements()
.forEach(m -> tObj.add(m.getId(), new JsonPrimitive(m.getTime() / 1_000_000_000.0)));
benchmarkSession
.getMeasurements()
.forEach(m -> tObj.add(m.getId(), new JsonPrimitive(m.getTime() / 1_000_000_000.0)));
result.add("timings", tObj);
benchmarkSession.getMeasurements().stream()
.map(Measurement::getTime)
Expand All @@ -190,21 +202,153 @@ private static AnalysisConfig createAnalysisConfiguration() {
return AnalysisConfig.defaultConfig(CopybookProcessingMode.ENABLED);
}

private static Pipeline<AnalysisContext> setupPipeline(Injector diCtx, Action action) {
private static Pipeline<AnalysisContext> setupPipeline(
Injector diCtx, Action action, CobolLanguageId dialect) {
DialectService dialectService = diCtx.getInstance(DialectService.class);
MessageService messageService = diCtx.getInstance(MessageService.class);
GrammarPreprocessor grammarPreprocessor = diCtx.getInstance(GrammarPreprocessor.class);
ParseTreeListener parseTreeListener = diCtx.getInstance(ParseTreeListener.class);
SymbolsRepository symbolsRepository = diCtx.getInstance(SymbolsRepository.class);
SubroutineService subroutineService = diCtx.getInstance(SubroutineService.class);
CleanerPreprocessor preprocessor =
diCtx.getInstance(TrueDialectServiceImpl.class).getPreprocessor(dialect);
CachingConfigurationService cachingConfigurationService =
diCtx.getInstance(CachingConfigurationService.class);
AstProcessor astProcessor = diCtx.getInstance(AstProcessor.class);
CodeLayoutStore layoutStore = diCtx.getInstance(CodeLayoutStore.class);

CleanerPreprocessor preprocessor = diCtx.getInstance(TrueDialectService.class).getPreprocessor(CobolLanguageId.COBOL);
CopybookService copybookService = diCtx.getInstance(CopybookService.class);

Pipeline<AnalysisContext> pipeline = new Pipeline<>();
switch (dialect) {
case COBOL:
return getPipelineForCobolDialect(
action,
pipeline,
preprocessor,
messageService,
dialectService,
grammarPreprocessor,
parseTreeListener,
symbolsRepository,
subroutineService,
cachingConfigurationService,
astProcessor,
layoutStore);
case EXPERIMENTAL_COBOL:
return getPipelineForExpCobol(
action,
pipeline,
preprocessor,
messageService,
dialectService,
grammarPreprocessor,
parseTreeListener,
symbolsRepository,
subroutineService,
cachingConfigurationService,
astProcessor,
layoutStore);
case HP_COBOL:
return getPipelineForHpCobol(
action,
pipeline,
preprocessor,
messageService,
copybookService,
grammarPreprocessor,
dialectService,
parseTreeListener,
symbolsRepository,
subroutineService,
cachingConfigurationService,
astProcessor,
layoutStore);
default:
return pipeline;
}
}

private static Pipeline<AnalysisContext> getPipelineForHpCobol(
Action action,
Pipeline<AnalysisContext> pipeline,
CleanerPreprocessor preprocessor,
MessageService messageService,
CopybookService copybookService,
GrammarPreprocessor grammarPreprocessor,
DialectService dialectService,
ParseTreeListener parseTreeListener,
SymbolsRepository symbolsRepository,
SubroutineService subroutineService,
CachingConfigurationService cachingConfigurationService,
AstProcessor astProcessor,
CodeLayoutStore layoutStore) {
pipeline.add(new HpCleanupStage(preprocessor));
pipeline.add(new CompilerDirectivesStage(messageService));
pipeline.add(new HpCopybookProcessingStage(messageService, copybookService));
pipeline.add(new PreprocessorStage(grammarPreprocessor, preprocessor));
if (action == Action.analysis) {
pipeline.add(new ImplicitDialectProcessingStage(dialectService));
pipeline.add(new ParserStage(messageService, parseTreeListener));
pipeline.add(
new TransformTreeStage(
symbolsRepository,
messageService,
subroutineService,
cachingConfigurationService,
dialectService,
astProcessor,
layoutStore));
}
return pipeline;
}

private static Pipeline<AnalysisContext> getPipelineForExpCobol(
Action action,
Pipeline<AnalysisContext> pipeline,
CleanerPreprocessor preprocessor,
MessageService messageService,
DialectService dialectService,
GrammarPreprocessor grammarPreprocessor,
ParseTreeListener parseTreeListener,
SymbolsRepository symbolsRepository,
SubroutineService subroutineService,
CachingConfigurationService cachingConfigurationService,
AstProcessor astProcessor,
CodeLayoutStore layoutStore) {
pipeline.add(new IbmCleanupStage(preprocessor));
pipeline.add(new CompilerDirectivesStage(messageService));
pipeline.add(new DialectProcessingStage(dialectService, preprocessor));
pipeline.add(new PreprocessorStage(grammarPreprocessor, preprocessor));
if (action == Action.analysis) {
pipeline.add(new ImplicitDialectProcessingStage(dialectService));
pipeline.add(new ExperimentalParserStage(messageService, parseTreeListener));
pipeline.add(
new TransformTreeStage(
symbolsRepository,
messageService,
subroutineService,
cachingConfigurationService,
dialectService,
astProcessor,
layoutStore));
}
return pipeline;
}

private static Pipeline<AnalysisContext> getPipelineForCobolDialect(
Action action,
Pipeline<AnalysisContext> pipeline,
CleanerPreprocessor preprocessor,
MessageService messageService,
DialectService dialectService,
GrammarPreprocessor grammarPreprocessor,
ParseTreeListener parseTreeListener,
SymbolsRepository symbolsRepository,
SubroutineService subroutineService,
CachingConfigurationService cachingConfigurationService,
AstProcessor astProcessor,
CodeLayoutStore layoutStore) {
pipeline.add(new IbmCleanupStage(preprocessor));
pipeline.add(new CompilerDirectivesStage(messageService));
pipeline.add(new DialectProcessingStage(dialectService, preprocessor));
pipeline.add(new PreprocessorStage(grammarPreprocessor, preprocessor));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@
import org.eclipse.lsp.cobol.common.ResultWithErrors;
import org.eclipse.lsp.cobol.common.mapping.ExtendedDocument;
import org.eclipse.lsp.cobol.common.mapping.ExtendedText;
import org.eclipse.lsp.cobol.core.engine.analysis.AnalysisContext;
import org.eclipse.lsp.cobol.common.pipeline.Stage;
import org.eclipse.lsp.cobol.common.pipeline.StageResult;
import org.eclipse.lsp.cobol.core.engine.analysis.AnalysisContext;

/**
* Cleanup preprocessor pipeline stage
*/
class HpCleanupStage implements Stage<AnalysisContext, Void, Void> {
public class HpCleanupStage implements Stage<AnalysisContext, Void, Void> {

private final CleanerPreprocessor preprocessor;

HpCleanupStage(CleanerPreprocessor preprocessor) {
public HpCleanupStage(CleanerPreprocessor preprocessor) {
this.preprocessor = preprocessor;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
* Resolving and inserting copybooks into the extended source stage
*/
@RequiredArgsConstructor
class HpCopybookProcessingStage implements Stage<AnalysisContext, DialectOutcome, Void> {
public class HpCopybookProcessingStage implements Stage<AnalysisContext, DialectOutcome, Void> {

private final MessageService messageService;
private final CopybookService copybookService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
* Parser stage
*/
@RequiredArgsConstructor
class ExperimentalParserStage implements Stage<AnalysisContext, ParserStageResult, DialectOutcome> {
public class ExperimentalParserStage implements Stage<AnalysisContext, ParserStageResult, DialectOutcome> {
private final MessageService messageService;
private final ParseTreeListener treeListener;

Expand Down
Loading