diff --git a/server/engine/src/main/java/org/eclipse/lsp/cobol/dialects/ibm/TransformTreeStage.java b/server/engine/src/main/java/org/eclipse/lsp/cobol/dialects/ibm/TransformTreeStage.java index deb8045776..9a65e70e1a 100644 --- a/server/engine/src/main/java/org/eclipse/lsp/cobol/dialects/ibm/TransformTreeStage.java +++ b/server/engine/src/main/java/org/eclipse/lsp/cobol/dialects/ibm/TransformTreeStage.java @@ -96,10 +96,23 @@ private void addDialectsNode(AnalysisContext context, Node rootNode) { dialectNode.getLocality().getUri(), dialectNode.getLocality().getRange().getStart()); - nodeByPosition.orElse(rootNode).addChild(dialectNode); + addChild(nodeByPosition.orElse(rootNode), dialectNode); } } + private void addChild(Node node, Node dialectNode) { + int index = 0; + for (Node child : node.getChildren()) { + if (child.getLocality().getUri().equals(dialectNode.getLocality().getUri()) + && (child.getLocality().getRange().getStart().getLine() >= dialectNode.getLocality().getRange().getStart().getLine())) { + break; + } + index++; + } + dialectNode.setParent(node); + node.getChildren().add(index, dialectNode); + } + private void addCopyNodes(AnalysisContext context, Node rootNode) { for (Map.Entry copybook : context.getCopybooksRepository().getUsages().entries()) { String name = copybook.getKey(); diff --git a/server/engine/src/test/java/org/eclipse/lsp/cobol/usecases/TestImplicitDialectsPosition.java b/server/engine/src/test/java/org/eclipse/lsp/cobol/usecases/TestImplicitDialectsPosition.java new file mode 100644 index 0000000000..7aa8cbfc34 --- /dev/null +++ b/server/engine/src/test/java/org/eclipse/lsp/cobol/usecases/TestImplicitDialectsPosition.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2024 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.AnalysisResult; +import org.eclipse.lsp.cobol.common.model.NodeType; +import org.eclipse.lsp.cobol.common.model.tree.Node; +import org.eclipse.lsp.cobol.implicitDialects.cics.nodes.ExecCicsHandleNode; +import org.eclipse.lsp.cobol.test.engine.UseCaseEngine; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** Tests the CICS implicit dialect node position **/ +class TestImplicitDialectsPosition { + + private static final String TEXT = " IDENTIFICATION DIVISION.\n" + + " PROGRAM-ID. CBACT01C.\n" + + " PROCEDURE DIVISION.\n" + + " IF 2 > 1 THEN\n" + + " EXEC CICS HANDLE ABEND LABEL({#HANDLE-ABEND})\n" + + " END-EXEC.\n" + + " GO TO {#HANDLE-ABEND}\n" + + " END-IF.\n" + + " {#*HANDLE-ABEND}.\n"; + + private static final String TEXT_WITH_COPY = " IDENTIFICATION DIVISION.\n" + + " PROGRAM-ID. CBACT01C.\n" + + " PROCEDURE DIVISION.\n" + + " IF 2 > 1 \n" + + " PERFORM {#HANDLE-ABEND}\n" + + " COPY {~COPY1}.\n" + + " DISPLAY '1'\n" + + " END-IF.\n" + + " {#*HANDLE-ABEND}.\n"; + + private static final String COPY1 = " EXEC CICS HANDLE ABEND LABEL({#HANDLE-ABEND}) END-EXEC\n"; + + @Test + void test() { + AnalysisResult result = UseCaseEngine.runTest(TEXT, ImmutableList.of(), ImmutableMap.of()); + Node ifNode = result.getRootNode().getDepthFirstStream() + .filter(n -> n.getNodeType() == NodeType.IF) + .findFirst() + .orElse(null); + + assertNotNull(ifNode); + Node execCicsNode = ifNode.getChildren().get(2); + assertTrue(execCicsNode instanceof ExecCicsHandleNode); + } + +// @Test +// void testCopy() { +// AnalysisResult result = UseCaseEngine.runTest(TEXT_WITH_COPY, +// ImmutableList.of(new CobolText("COPY1", COPY1)), +// ImmutableMap.of()); +// Node ifNode = result.getRootNode().getDepthFirstStream() +// .filter(n -> n.getNodeType() == NodeType.IF) +// .findFirst() +// .orElse(null); +// +// assertNotNull(ifNode); +// Node execCicsNode = ifNode.getChildren().get(3); +// assertTrue(execCicsNode instanceof ExecCicsHandleNode); +// } + +} diff --git a/server/engine/src/test/resources/cfast/case_execCicsHandleAbendEx.cbl b/server/engine/src/test/resources/cfast/case_execCicsHandleAbendEx.cbl new file mode 100644 index 0000000000..6c2571e30c --- /dev/null +++ b/server/engine/src/test/resources/cfast/case_execCicsHandleAbendEx.cbl @@ -0,0 +1,10 @@ + IDENTIFICATION DIVISION. + PROGRAM-ID. CBACT01C. + PROCEDURE DIVISION. + IF A > B THEN + EXEC CICS HANDLE ABEND LABEL(HANDLE-ABEND) + END-EXEC. + GO TO CALCULATION. + END-IF. + + HANDLE-ABEND. \ No newline at end of file diff --git a/server/engine/src/test/resources/cfast/case_execCicsHandleAbendEx.result.json b/server/engine/src/test/resources/cfast/case_execCicsHandleAbendEx.result.json new file mode 100644 index 0000000000..c0b0215c46 --- /dev/null +++ b/server/engine/src/test/resources/cfast/case_execCicsHandleAbendEx.result.json @@ -0,0 +1,94 @@ +[ + { + "name": "CBACT01C", + "type": "program", + "location": { + "uri": "fake/path", + "start": { + "line": 3, + "character": 8 + }, + "end": { + "line": 7, + "character": 32 + } + }, + "children": [ + { + "type": "if", + "location": { + "uri": "fake/path", + "start": { + "line": 4, + "character": 12 + }, + "end": { + "line": 7, + "character": 31 + } + } + }, + { + "handleType": "LABEL", + "value": "HANDLE-ABEND", + "type": "execcicshandle", + "location": { + "uri": "fake/path", + "start": { + "line": 5, + "character": 14 + }, + "end": { + "line": 6, + "character": 23 + } + } + }, + { + "type": "endexec", + "location": { + "uri": "fake/path", + "start": { + "line": 5, + "character": 14 + }, + "end": { + "line": 6, + "character": 23 + } + } + }, + { + "targetName": [ + "CALCULATION" + ], + "type": "goto", + "location": { + "uri": "fake/path", + "start": { + "line": 7, + "character": 14 + }, + "end": { + "line": 7, + "character": 31 + } + } + }, + { + "type": "endif", + "location": { + "uri": "fake/path", + "start": { + "line": 4, + "character": 12 + }, + "end": { + "line": 7, + "character": 31 + } + } + } + ] + } +] \ No newline at end of file