diff --git a/clients/cobol-lsp-vscode-extension/syntaxes/COBOL.tmLanguage.json b/clients/cobol-lsp-vscode-extension/syntaxes/COBOL.tmLanguage.json index e334b48d22..ce6be49dbc 100644 --- a/clients/cobol-lsp-vscode-extension/syntaxes/COBOL.tmLanguage.json +++ b/clients/cobol-lsp-vscode-extension/syntaxes/COBOL.tmLanguage.json @@ -164,7 +164,7 @@ } }, "cobol-general-keyword": { - "match": "(? visitJsonStatement(CobolParser.JsonStatementContext ctx) { return addTreeNode(ctx, StatementNode::new); } + @Override + public java.util.List visitDataDescriptionEntryWithCompilerDirective(DataDescriptionEntryWithCompilerDirectiveContext ctx) { + if (ctx.stop.getType() != CobolLexer.JAVA_SHAREABLE_OFF) { + SyntaxError error = SyntaxError.syntaxError() + .errorSource(ErrorSource.PARSING) + .location(getTokenEndLocality(ctx.stop).toOriginalLocation()) + .suggestion(messageService.getMessage("CompilerDirectives.missingJavaShareableOff")) + .severity(ErrorSeverity.ERROR) + .build(); + errors.add(error); + } + return addTreeNode(ctx, StatementNode::new); + } + private ProcedureName parseProcedureName(CobolParser.ProcedureNameContext procedureNameContext) { if (procedureNameContext == null) { return null; @@ -1747,6 +1761,18 @@ protected void areaBWarning(ParserRuleContext ctx) { } } + private Locality getTokenEndLocality(Token token) { + return Locality.builder() + .uri(extendedDocument.getUri()) + .range(buildTokenEndRange(token)) + .build(); + } + + private Range buildTokenEndRange(Token token) { + Position p = new Position(token.getLine() - 1, token.getCharPositionInLine() + token.getStopIndex() - token.getStartIndex() + 1); + return new Range(p, p); + } + private boolean startsInAreaA(Range r) { final int charPosition = r.getStart().getCharacter(); final int areaBStartIndex = programLayout.getSequenceLength() + programLayout.getIndicatorLength() + programLayout.getAreaALength(); diff --git a/server/engine/src/main/resources/LanguageKeywords.txt b/server/engine/src/main/resources/LanguageKeywords.txt index ba6c7afca2..3cd725c0a8 100644 --- a/server/engine/src/main/resources/LanguageKeywords.txt +++ b/server/engine/src/main/resources/LanguageKeywords.txt @@ -1597,6 +1597,8 @@ JAR= JAVA= JAVACORE= JAVAHOME= +JAVA-CALLABLE= +JAVA-SHAREABLE= JCT= JIDERR= JIS= diff --git a/server/engine/src/main/resources/resourceBundles/messages_en.properties b/server/engine/src/main/resources/resourceBundles/messages_en.properties index ec1fa2d267..021529d063 100644 --- a/server/engine/src/main/resources/resourceBundles/messages_en.properties +++ b/server/engine/src/main/resources/resourceBundles/messages_en.properties @@ -24,6 +24,7 @@ Communications.noSyntaxError=No syntax errors detected in %s Communications.syntaxAnalysisInProgress=%s : Syntax analysis in progress Communications.syntaxAnalysisInProgressTitle=Analyzing %s CompilerDirectivesTransformation.sequenceNumber=The first character of the sequence number must be numeric. +CompilerDirectives.missingJavaShareableOff=Missing token JAVA-SHAREABLE OFF for the JAVA-SHAREABLE block ContinuationLineTransformation.compilerDirectiveContinued=Compiler directives cannot be continued on another line ContinuationLineTransformation.continuationLineContentAreaA=A continuation line cannot contain values in the Content Area A ContinuationLineTransformation.periodRequired=IGYDS1082-E A period was required. diff --git a/server/engine/src/test/java/org/eclipse/lsp/cobol/usecases/TestCompilerDirectives.java b/server/engine/src/test/java/org/eclipse/lsp/cobol/usecases/TestCompilerDirectives.java new file mode 100644 index 0000000000..ebf09538a0 --- /dev/null +++ b/server/engine/src/test/java/org/eclipse/lsp/cobol/usecases/TestCompilerDirectives.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025 Broadcom. + * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + * + */ + +package org.eclipse.lsp.cobol.usecases; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import org.eclipse.lsp.cobol.common.error.ErrorSource; +import org.eclipse.lsp.cobol.test.engine.UseCaseEngine; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.DiagnosticSeverity; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.Range; +import org.junit.jupiter.api.Test; + +/** + * Test for compiler directives + */ +class TestCompilerDirectives { + private static final String TEXT = + " IDENTIFICATION DIVISION.\n" + + " PROGRAM-ID. TEST1.\n" + + " DATA DIVISION.\n" + + " WORKING-STORAGE SECTION.\n" + + " JAVA-SHAREABLE ON\n" + + " 01 G1.\n" + + " 03 N1 PIC S9(9) COMP-5.\n" + + " 03 G1SUB.\n" + + " 05 S1 PIC X(20).\n" + + " JAVA-SHAREABLE OFF\n" + + " 01 {$*TESTW} pic x(9).\n" + + " JAVA-CALLABLE\n" + + " PROCEDURE DIVISION.\n" + + " DISPLAY {$TESTW}.\n" + + " GOBACK.\n"; + + private static final String TEXT_ERROR = + " IDENTIFICATION DIVISION.\n" + + " PROGRAM-ID. TEST1.\n" + + " DATA DIVISION.\n" + + " WORKING-STORAGE SECTION.\n" + + " JAVA-SHAREABLE ON\n" + + " 01 N1 PIC S9(9) COMP-5.\n" + + " {JAVA-SHAREABLE|error1|error2}\n" + + " JAVA-CALLABLE\n" + + " PROCEDURE DIVISION.\n" + + " GOBACK.\n"; + @Test + void test() { + UseCaseEngine.runTest(TEXT, ImmutableList.of(), ImmutableMap.of()); + } + + @Test + void testError() { + UseCaseEngine.runTest( + TEXT_ERROR, + ImmutableList.of(), + ImmutableMap.of( + "error1", + new Diagnostic( + new Range(new Position(6, 21), new Position(6, 21)), + "Missing token JAVA-SHAREABLE OFF for the JAVA-SHAREABLE block", + DiagnosticSeverity.Error, + ErrorSource.PARSING.getText()), + "error2", + new Diagnostic( + new Range(), + "Extraneous input 'JAVA-SHAREABLE'", + DiagnosticSeverity.Error, + ErrorSource.PARSING.getText())), + ImmutableList.of()); + } +} diff --git a/server/parser/src/main/antlr4/org/eclipse/lsp/cobol/core/CobolLexer.g4 b/server/parser/src/main/antlr4/org/eclipse/lsp/cobol/core/CobolLexer.g4 index 8e70051e18..2eb2a9d668 100644 --- a/server/parser/src/main/antlr4/org/eclipse/lsp/cobol/core/CobolLexer.g4 +++ b/server/parser/src/main/antlr4/org/eclipse/lsp/cobol/core/CobolLexer.g4 @@ -587,6 +587,9 @@ INVALID : I N V A L I D ; INVD : I N V D; INVDATA : I N V D A T A; IS : I S ; +JAVA_CALLABLE : J A V A MINUSCHAR C A L L A B L E; +JAVA_SHAREABLE_OFF :J A V A MINUSCHAR S H A R E A B L E [ \t\f\r\n]+ O F F; +JAVA_SHAREABLE_ON :J A V A MINUSCHAR S H A R E A B L E [ \t\f\r\n]+ O N; JSON : J S O N ; JUST : J U S T ; JUSTIFIED : J U S T I F I E D ; diff --git a/server/parser/src/main/antlr4/org/eclipse/lsp/cobol/core/CobolParser.g4 b/server/parser/src/main/antlr4/org/eclipse/lsp/cobol/core/CobolParser.g4 index 6893d5a1c2..89a7c64659 100644 --- a/server/parser/src/main/antlr4/org/eclipse/lsp/cobol/core/CobolParser.g4 +++ b/server/parser/src/main/antlr4/org/eclipse/lsp/cobol/core/CobolParser.g4 @@ -576,7 +576,8 @@ dataDescriptionEntryForWorkingStorageSection ; dataDescriptionEntryForWorkingStorageAndLinkageSection - : dataDescriptionEntry + : dataDescriptionEntryWithCompilerDirective + | dataDescriptionEntry ; dataDescriptionEntry @@ -587,6 +588,10 @@ dataDescriptionEntry | dialectDescriptionEntry ; +dataDescriptionEntryWithCompilerDirective + : JAVA_SHAREABLE_ON dataDescriptionEntry* JAVA_SHAREABLE_OFF + ; + dataDescriptionEntryFormat1 : levelNumber entryName? (dataGroupUsageClause | dataRedefinesClause | dataExternalClause | dataGlobalClause | dataPictureClause | dataUsageClause | dataValueClause @@ -766,7 +771,11 @@ thruToken // --- procedure division -------------------------------------------------------------------- procedureDivision - : PROCEDURE DIVISION procedureDivisionUsingClause? procedureDivisionGivingClause? dot_fs procedureDeclaratives? procedureDivisionBody + : procedureDivisionCompilerDirectives? PROCEDURE DIVISION procedureDivisionUsingClause? procedureDivisionGivingClause? dot_fs procedureDeclaratives? procedureDivisionBody + ; + +procedureDivisionCompilerDirectives + : JAVA_CALLABLE ; procedureDivisionUsingClause