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

fix: fix variable definitions inside embedded copybooks #2418

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
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ public void addChild(Node node) {
children.add(node);
}


/**
* Add a child node to this node and updates the child parent link.
*
* @param index index of insertion
* @param node a child node.
*/
public void addChildAt(int index, Node node) {
node.setParent(this);
children.add(index, node);
}

/**
* Remove a child node.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,8 @@ private List<VariableDefinitionNode> unwrapVariables(Node node) {

copybooks.sort(Comparator.comparingInt(c -> c.getLocality().getRange().getStart().getLine()));

List<CopyNode> allCopybooks =
copybooks.stream()
.flatMap(Node::getDepthFirstStream)
.filter(n -> n.getNodeType() == NodeType.COPY)
.map(CopyNode.class::cast)
.collect(Collectors.toList());

int index = 0;
for (CopyNode copyNode : allCopybooks) {
for (CopyNode copyNode : copybooks) {
index = insertCopybook(variables, index, copyNode);
}

Expand Down Expand Up @@ -181,8 +174,7 @@ private static boolean adjustCopyNodeChild(CopyNode copyNode, List<Node> variabl
String variableNodeUri = variable.getLocality().getUri();
String copybookNodeUri = copyNode.getUri();
if (variableNodeUri.equals(copybookNodeUri)) {
copyNode.addChild(variable);
variables.remove(variable);
adjustVariableNodeInsideCopyNode(copyNode, variables, i, variable);
areNodesAdjusted = true;
} else {
break;
Expand All @@ -191,7 +183,36 @@ private static boolean adjustCopyNodeChild(CopyNode copyNode, List<Node> variabl
return areNodesAdjusted;
}

private static boolean canInsertCopyNodeAtIndex(
private static void adjustVariableNodeInsideCopyNode(CopyNode copyNode, List<Node> variables, int i, Node variable) {
if (variable instanceof VariableDefinitionNode) {
int insertIndex;
for (insertIndex = 0; insertIndex < copyNode.getChildren().size(); insertIndex++) {
Node node = copyNode.getChildren().get(insertIndex);
if (node instanceof CopyNode) {
adjustCopyNodeChild((CopyNode) node, variables, i);
}
Locality copybNodeChildLocality = node.getLocality();
Locality variableLocality = variable.getLocality();
if (RangeUtils.isBefore(variableLocality.getRange().getStart(), copybNodeChildLocality.getRange().getStart())) {
break;
}
}
if (!isVariableNodeAlreadyPresentIn(copyNode, (VariableDefinitionNode) variable)) {
copyNode.addChildAt(insertIndex, variable);
variables.remove(variable);
}
}
}

private static boolean isVariableNodeAlreadyPresentIn(CopyNode copyNode, VariableDefinitionNode variable) {
return copyNode.getChildren().stream()
.filter(VariableDefinitionNode.class::isInstance)
.map(VariableDefinitionNode.class::cast)
.anyMatch(n -> n.getLocality().equals(variable.getLocality())
&& n.getVariableName().equals(variable.getVariableName()));
}

private static boolean canInsertCopyNodeAtIndex(
CopyNode copyNode, int index, List<Node> variables) {
String copybookLocalityUri = copyNode.getLocality().getUri();
Range copybookLocalityRange = copyNode.getLocality().getRange();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class TestSameCopybooksWithDifferentCases {

private static final String STRUCT1 =
" 02 {$*PARENT2}.\n"
+ " 03 {$*CHILD1} PIC 9 VALUE IS '0'.\n"
+ " 03 {$*CHILD2} PIC 9 VALUE IS '1'.\n"
+ " 03 {$*CHILD3} PIC 9 VALUE IS '2'.";
+ " 03 {$*CHILD1} PIC 9 VALUE IS 0.\n"
+ " 03 {$*CHILD2} PIC 9 VALUE IS 1.\n"
+ " 03 {$*CHILD3} PIC 9 VALUE IS 2.";

private static final String CPY_NAME = "STRUCT1";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,27 @@ class TestWithCopybook {
+ " {#*bug-test2}.\n"
+ " move 0 to {$test1}.";

public static final String TEXT7 =
" IDENTIFICATION DIVISION.\n"
+ " PROGRAM-ID. ABCDEF.\n"
+ " DATA DIVISION.\n"
+ " WORKING-STORAGE SECTION.\n"
+ " copy {~AMAZE}. \n"
+ " copy {~AMAZE2}. \n"
+ " PROCEDURE DIVISION.\n";

public static final String AMAZE_TEXT =
" 01 {$*CHK-PARMS}.\n" + "P#1325 07 {$*CHECK} PIC 9(09) COMP SYNC.\n";

public static final String AMAZE2_TEXT =
"001600 01 {$*META-TABLE}.\n"
+ "001700 05 {$*META-FIELD} OCCURS 12500 TIMES.\n"
+ "FMC COPY {~AMAZE3}.\n"
+ " 01 {$*TEST-ULTI} pic x.";

public static final String AMAZE3_TEXT =
"\n" + " 10 {$*META-FIELD-NAME} PIC X(35).\n";

private static final String COPYBOOK_CONTENT = " 01 {$*VAR} PIC S9(4) COMP.";

@Test
Expand Down Expand Up @@ -151,4 +172,15 @@ void testCopybookSubstitutionOnACobolLinePartially5() {
ImmutableList.of(new CobolText("BUG0", " \"scenario 4\"\n")),
ImmutableMap.of());
}

@Test
void testEmbeddedCopybooks() {
UseCaseEngine.runTest(
TEXT7,
ImmutableList.of(
new CobolText("AMAZE", AMAZE_TEXT),
new CobolText("AMAZE2", AMAZE2_TEXT),
new CobolText("AMAZE3", AMAZE3_TEXT)),
ImmutableMap.of());
}
}
Loading