Skip to content

Commit 6db4f0b

Browse files
authored
fix: Fix group variables for sql statements (#2001)
1 parent cee3b08 commit 6db4f0b

File tree

4 files changed

+127
-13
lines changed

4 files changed

+127
-13
lines changed

server/engine/src/main/antlr4/org/eclipse/lsp/cobol/core/parser/Db2SqlLexer.g4

+1-1
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ DATELITERAL: '\'' (DIGIT DIGIT DIGIT DIGIT '-' DIGIT DIGIT '-' DIGIT DIGIT | //y
823823
DIGIT DIGIT '-' DIGIT DIGIT '-' DIGIT DIGIT DIGIT DIGIT) TIMESTAMPLITERAL? '\'';//yyyy-mm-dd
824824

825825
INTEGERLITERAL : DIGIT+ ;
826-
IDENTIFIER : [a-zA-Z0-9][_a-zA-Z0-9]*;
826+
IDENTIFIER : [a-zA-Z0-9][_a-zA-Z0-9-]*;
827827
COPYBOOK_IDENTIFIER : [a-zA-Z0-9#@$][_a-zA-Z0-9#@$]*;
828828

829829
fragment BXNUMBER :

server/engine/src/main/java/org/eclipse/lsp/cobol/core/engine/analysis/Db2SqlVisitor.java

+22-12
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,11 @@ public List<Node> visitDbs_host_names_var(Db2SqlParser.Dbs_host_names_varContext
7272
@Override
7373
public List<Node> visitDbs_host_name_container(Db2SqlParser.Dbs_host_name_containerContext ctx) {
7474
if (isVariableUsage(ctx.getParent())) {
75-
return addTreeNode(
76-
ctx,
77-
locality -> new VariableUsageNode(VisitorHelper.getName(ctx), locality)
78-
);
75+
return addVariableUsageNodes(ctx);
7976
}
8077
return ImmutableList.of();
8178
}
8279

83-
@Override
84-
public List<Node> visitDbs_sql_identifier(Db2SqlParser.Dbs_sql_identifierContext ctx) {
85-
return addTreeNode(
86-
ctx,
87-
locality -> new VariableUsageNode(VisitorHelper.getName(ctx), locality)
88-
);
89-
}
90-
9180
// NOTE: Visitor is not managed by Guice DI, so can't use annotation here.
9281
@Override
9382
public List<Node> visitChildren(RuleNode node) {
@@ -160,4 +149,25 @@ private List<Node> addTreeNode(ParserRuleContext ctx, Function<Locality, Node> n
160149
visitChildren(ctx).forEach(node::addChild);
161150
return ImmutableList.of(node);
162151
}
152+
153+
private List<Node> addVariableUsageNodes(ParserRuleContext ctx) {
154+
String name = VisitorHelper.getName(ctx);
155+
boolean hasColumn = name.startsWith(":");
156+
if (hasColumn) {
157+
name = name.substring(1);
158+
}
159+
160+
if (Db2SqlVisitorHelper.isGroupName(name)) {
161+
Locality locality = VisitorHelper.buildNameRangeLocality(ctx, name, programUri);
162+
locality.setRange(RangeUtils.shiftRangeWithPosition(new Position(position.getLine(),
163+
position.getCharacter() + (hasColumn ? 1 : 0)), locality.getRange()));
164+
165+
return Db2SqlVisitorHelper.generateGroupNodes(name, locality);
166+
}
167+
String finalName = name;
168+
return addTreeNode(
169+
ctx,
170+
locality -> new VariableUsageNode(finalName, locality)
171+
);
172+
}
163173
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2023 Broadcom.
3+
* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
4+
*
5+
* This program and the accompanying materials are made
6+
* available under the terms of the Eclipse Public License 2.0
7+
* which is available at https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Broadcom, Inc. - initial API and implementation
13+
*
14+
*/
15+
package org.eclipse.lsp.cobol.core.engine.analysis;
16+
17+
import com.google.common.collect.ImmutableList;
18+
import lombok.experimental.UtilityClass;
19+
import org.eclipse.lsp.cobol.common.model.Locality;
20+
import org.eclipse.lsp.cobol.common.model.tree.Node;
21+
import org.eclipse.lsp.cobol.common.model.tree.variable.QualifiedReferenceNode;
22+
import org.eclipse.lsp.cobol.common.model.tree.variable.VariableUsageNode;
23+
import org.eclipse.lsp4j.Position;
24+
import org.eclipse.lsp4j.Range;
25+
26+
import java.util.List;
27+
28+
/**
29+
* Helper class for Db2SqlVisitor
30+
*/
31+
@UtilityClass
32+
class Db2SqlVisitorHelper {
33+
34+
public boolean isGroupName(String name) {
35+
return name.contains(".");
36+
}
37+
38+
public String[] splitNames(String name) {
39+
return name.split("\\.");
40+
}
41+
42+
public Range[] splitRange(Range range, String[] names) {
43+
Range[] result = new Range[names.length];
44+
int pos = range.getStart().getCharacter();
45+
int line = range.getStart().getLine();
46+
for (int i = 0; i < names.length; i++) {
47+
result[i] = new Range(new Position(line, pos), new Position(line, pos + names[i].length()));
48+
pos += names[i].length() + 1;
49+
}
50+
return result;
51+
}
52+
53+
public List<Node> generateGroupNodes(String name, Locality locality) {
54+
String[] names = splitNames(name);
55+
Range[] ranges = splitRange(locality.getRange(), names);
56+
57+
QualifiedReferenceNode groupNode = new QualifiedReferenceNode(locality);
58+
for (int i = ranges.length - 1; i >= 0; i--) {
59+
Locality nodeLocality = locality.toBuilder().range(ranges[i]).build();
60+
groupNode.addChild(new VariableUsageNode(names[i], nodeLocality));
61+
}
62+
return ImmutableList.of(groupNode);
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2023 Broadcom.
3+
* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
4+
*
5+
* This program and the accompanying materials are made
6+
* available under the terms of the Eclipse Public License 2.0
7+
* which is available at https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Broadcom, Inc. - initial API and implementation
13+
*
14+
*/
15+
package org.eclipse.lsp.cobol.usecases;
16+
17+
import com.google.common.collect.ImmutableList;
18+
import com.google.common.collect.ImmutableMap;
19+
import org.eclipse.lsp.cobol.test.engine.UseCaseEngine;
20+
import org.junit.jupiter.api.Test;
21+
22+
/**
23+
* Tests Group Variable usage in the EXEC SQL block
24+
*/
25+
class TestSqlGroupVariableUsage {
26+
27+
private static final String TEXT = " IDENTIFICATION DIVISION.\n"
28+
+ " PROGRAM-ID. SM106A.\n"
29+
+ " DATA DIVISION.\n"
30+
+ " WORKING-STORAGE SECTION. \n"
31+
+ " 01 {$*INP} PIC X(9).\n"
32+
+ " 01 {$*A}.\n"
33+
+ " 05 {$*BBB} PIC X(9).\n"
34+
+ " PROCEDURE DIVISION.\n"
35+
+ " EXEC SQL SELECT :{$INP} INTO :{$A}.{$BBB} FROM CACHE END-EXEC.\n";
36+
@Test
37+
void test() {
38+
UseCaseEngine.runTest(TEXT, ImmutableList.of(), ImmutableMap.of());
39+
}
40+
}

0 commit comments

Comments
 (0)