From 591c026764377c003bfbbb7d0af9b3c68b127142 Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Tue, 14 Sep 2021 17:42:02 +0200 Subject: [PATCH 01/15] Next dev cycle --- coverage-report/pom.xml | 16 ++++++++-------- database-parser/pom.xml | 2 +- listing-parser/pom.xml | 2 +- openedge-checks/pom.xml | 6 +++--- openedge-plugin/pom.xml | 8 ++++---- pom.xml | 2 +- profiler-parser/pom.xml | 2 +- proparse/pom.xml | 4 ++-- rcode-reader/pom.xml | 2 +- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/coverage-report/pom.xml b/coverage-report/pom.xml index 6e184d972..f9be460cd 100644 --- a/coverage-report/pom.xml +++ b/coverage-report/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers coverage-report - 2.14.2 + 2.14.3-SNAPSHOT JaCoCo report Fake module for code coverage report in SonarQube @@ -20,37 +20,37 @@ eu.rssw.openedge.rcode rcode-reader - 2.14.2 + 2.14.3-SNAPSHOT eu.rssw.sonar.openedge sonar-openedge-plugin - 2.14.2 + 2.14.3-SNAPSHOT eu.rssw.openedge.parsers proparse - 2.14.2 + 2.14.3-SNAPSHOT eu.rssw.openedge.parsers profiler-parser - 2.14.2 + 2.14.3-SNAPSHOT eu.rssw.openedge.parsers database-parser - 2.14.2 + 2.14.3-SNAPSHOT eu.rssw.openedge.parsers listing-parser - 2.14.2 + 2.14.3-SNAPSHOT eu.rssw.openedge.checks openedge-checks - 2.14.2 + 2.14.3-SNAPSHOT diff --git a/database-parser/pom.xml b/database-parser/pom.xml index 2c96eed5c..f538f7ee2 100644 --- a/database-parser/pom.xml +++ b/database-parser/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers database-parser - 2.14.2 + 2.14.3-SNAPSHOT OpenEdge database definition lexer and parser OpenEdge dump files parser diff --git a/listing-parser/pom.xml b/listing-parser/pom.xml index f2af8b8a1..28c1f0fb2 100644 --- a/listing-parser/pom.xml +++ b/listing-parser/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers listing-parser - 2.14.2 + 2.14.3-SNAPSHOT OpenEdge listing so-called parser OpenEdge listing files parser diff --git a/openedge-checks/pom.xml b/openedge-checks/pom.xml index 58dda7b57..5ed5c5c3b 100644 --- a/openedge-checks/pom.xml +++ b/openedge-checks/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.checks openedge-checks - 2.14.2 + 2.14.3-SNAPSHOT OpenEdge checks OpenEdge checks @@ -55,12 +55,12 @@ eu.rssw.openedge.parsers database-parser - 2.14.2 + 2.14.3-SNAPSHOT eu.rssw.openedge.parsers proparse - 2.14.2 + 2.14.3-SNAPSHOT org.testng diff --git a/openedge-plugin/pom.xml b/openedge-plugin/pom.xml index 64ba69ee0..8c76d4022 100644 --- a/openedge-plugin/pom.xml +++ b/openedge-plugin/pom.xml @@ -4,7 +4,7 @@ eu.rssw.sonar.openedge sonar-openedge-plugin - 2.14.2 + 2.14.3-SNAPSHOT sonar-plugin OpenEdge plugin for SonarQube @@ -60,17 +60,17 @@ eu.rssw.openedge.checks openedge-checks - 2.14.2 + 2.14.3-SNAPSHOT eu.rssw.openedge.parsers listing-parser - 2.14.2 + 2.14.3-SNAPSHOT eu.rssw.openedge.parsers profiler-parser - 2.14.2 + 2.14.3-SNAPSHOT commons-io diff --git a/pom.xml b/pom.xml index 0e4496a7d..5a605efd8 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge pom - 2.14.2 + 2.14.3-SNAPSHOT OpenEdge plugin for SonarQube http://www.riverside-software.fr/ Open source code analysis for OpenEdge diff --git a/profiler-parser/pom.xml b/profiler-parser/pom.xml index 055af5ef5..d9931e98b 100644 --- a/profiler-parser/pom.xml +++ b/profiler-parser/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers profiler-parser - 2.14.2 + 2.14.3-SNAPSHOT OpenEdge profiler output lexer and parser OpenEdge profiler files parser diff --git a/proparse/pom.xml b/proparse/pom.xml index 5d12a2483..b9b9b6062 100644 --- a/proparse/pom.xml +++ b/proparse/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers proparse - 2.14.2 + 2.14.3-SNAPSHOT Proparse ABL code parser @@ -55,7 +55,7 @@ eu.rssw.openedge.rcode rcode-reader - 2.14.2 + 2.14.3-SNAPSHOT org.antlr diff --git a/rcode-reader/pom.xml b/rcode-reader/pom.xml index 832c29fe8..aec23195c 100644 --- a/rcode-reader/pom.xml +++ b/rcode-reader/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.rcode rcode-reader - 2.14.2 + 2.14.3-SNAPSHOT rcode-reader rcode reader From 434c6f0883c0847c44ec7d9d155b86d70b0f1bfd Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Wed, 15 Sep 2021 17:12:34 +0200 Subject: [PATCH 02/15] Minor refactor to superStatement --- .../main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 b/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 index 102b03c6d..459d825df 100644 --- a/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 +++ b/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 @@ -3212,7 +3212,8 @@ stopStatement: ; superStatement: - SUPER LEFTPAREN ( parameter ( COMMA parameter )* )? RIGHTPAREN statementEnd + // Only for SUPER(...) in FUNCTION ; SUPER() in a class is handled by exprt2ParenCall2 + SUPER parameterListNoRoot statementEnd // TODO Use parameterList ; streamNameOrHandle: From 09f663e18de5b2a3a843977daef85f3e6b87c2f3 Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Wed, 15 Sep 2021 17:05:09 +0200 Subject: [PATCH 03/15] THIS-OBJECT(...) and SUPER(...) have to be flagged as expressions Issue #907 --- .../prorefactor/proparse/JPNodeVisitor.java | 4 +- .../prorefactor/core/TreeParser03Test.java | 37 +++++++++++++++++-- .../test/resources/treeparser03/test36.cls | 4 ++ .../test/resources/treeparser03/test37.cls | 24 ++++++++++++ 4 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 proparse/src/test/resources/treeparser03/test37.cls diff --git a/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java b/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java index 0b8e88ede..9553f670a 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java +++ b/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java @@ -2538,7 +2538,7 @@ public Builder visitStopStatement(StopStatementContext ctx) { @Override public Builder visitSuperStatement(SuperStatementContext ctx) { - return createTree(ctx, ABLNodeType.METHOD_REF).setStatement().setRuleNode(ctx); + return createTree(ctx, ABLNodeType.METHOD_REF).setStatement().setExpression(true).setRuleNode(ctx); } @Override @@ -2648,7 +2648,7 @@ public Builder visitTextPhrase(TextPhraseContext ctx) { @Override public Builder visitThisObjectStatement(ThisObjectStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createTree(ctx, ABLNodeType.METHOD_REF).setStatement().setExpression(true).setRuleNode(ctx); } @Override diff --git a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java index 4835dc76d..1a9eeac5a 100644 --- a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java +++ b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java @@ -1292,10 +1292,41 @@ public void testSuper02() throws JAXBException, IOException { assertNotNull(unit.getTopNode()); assertNotNull(unit.getRootScope()); List list = unit.getTopNode().query(ABLNodeType.SUPER); - assertEquals(list.size(), 2); + assertEquals(list.size(), 3); assertEquals(list.get(0).getParent().getNodeType(), ABLNodeType.METHOD_REF); - assertEquals(list.get(1).getParent().getNodeType(), ABLNodeType.SYSTEM_HANDLE_REF); - assertEquals(list.get(1).getParent().getParent().getNodeType(), ABLNodeType.METHOD_REF); + assertTrue(list.get(0).getParent().isExpression()); + assertTrue(list.get(0).getParent().isStateHead()); + assertEquals(list.get(1).getParent().getNodeType(), ABLNodeType.METHOD_REF); + assertTrue(list.get(1).getParent().isExpression()); + assertTrue(list.get(1).getParent().isStateHead()); + assertEquals(list.get(2).getParent().getNodeType(), ABLNodeType.SYSTEM_HANDLE_REF); + assertTrue(list.get(2).getParent().isExpression()); + assertEquals(list.get(2).getParent().getParent().getNodeType(), ABLNodeType.METHOD_REF); + assertTrue(list.get(2).getParent().getParent().isExpression()); + assertFalse(list.get(2).getParent().getParent().isStateHead()); + } + + @Test + public void testThisObject01() throws JAXBException, IOException { + ParseUnit unit = new ParseUnit(new File("src/test/resources/treeparser03/test37.cls"), session); + assertNull(unit.getTopNode()); + unit.treeParser01(); + assertFalse(unit.hasSyntaxError()); + assertNotNull(unit.getTopNode()); + assertNotNull(unit.getRootScope()); + List list = unit.getTopNode().query(ABLNodeType.THISOBJECT); + assertEquals(list.size(), 3); + assertEquals(list.get(0).getParent().getNodeType(), ABLNodeType.METHOD_REF); + assertTrue(list.get(0).getParent().isExpression()); + assertTrue(list.get(0).getParent().isStateHead()); + assertEquals(list.get(1).getParent().getNodeType(), ABLNodeType.METHOD_REF); + assertTrue(list.get(1).getParent().isExpression()); + assertTrue(list.get(1).getParent().isStateHead()); + assertEquals(list.get(2).getParent().getNodeType(), ABLNodeType.SYSTEM_HANDLE_REF); + assertTrue(list.get(2).getParent().isExpression()); + assertEquals(list.get(2).getParent().getParent().getNodeType(), ABLNodeType.METHOD_REF); + assertTrue(list.get(2).getParent().getParent().isExpression()); + assertFalse(list.get(2).getParent().getParent().isStateHead()); } } diff --git a/proparse/src/test/resources/treeparser03/test36.cls b/proparse/src/test/resources/treeparser03/test36.cls index 40a3a1174..fc818b4d2 100644 --- a/proparse/src/test/resources/treeparser03/test36.cls +++ b/proparse/src/test/resources/treeparser03/test36.cls @@ -4,6 +4,10 @@ class rssw.Test36: super(). end constructor. + constructor Test36(xx as int): + super(xx). + end constructor. + method public void method1(): define variable lcFoo as character no-undo. assign lcFoo = super:method1(). diff --git a/proparse/src/test/resources/treeparser03/test37.cls b/proparse/src/test/resources/treeparser03/test37.cls new file mode 100644 index 000000000..f04b145ef --- /dev/null +++ b/proparse/src/test/resources/treeparser03/test37.cls @@ -0,0 +1,24 @@ +class rssw.Test37: + + constructor Test37(): + this-object(1). + end constructor. + + constructor Test37(xx as int): + this-object(xx, 2). + end constructor. + + constructor Test37(xx as int, yy as int): + super(xx, yy). + end constructor. + + method public void method1(): + define variable lcFoo as character no-undo. + assign lcFoo = this-object:method2(). + end method. + + method public void method2(): + // Nothing here + end method. + +end class. From daefc717cf6b55103ef050a12b37f99daad73caa Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Mon, 20 Sep 2021 09:51:21 +0200 Subject: [PATCH 04/15] Expression engine minor refactor Add JPNode#asIExpression() + inheritance chain from ExpressionNode + JPNode#queryExpressions() now returns List --- .../java/org/prorefactor/core/JPNode.java | 22 ++++- .../core/JPNodeExpressionQuery.java | 12 ++- .../core/nodetypes/ArrayReferenceNode.java | 16 +--- .../nodetypes/AttributeReferenceNode.java | 21 +---- .../core/nodetypes/BuiltinFunctionNode.java | 29 +++--- .../core/nodetypes/ConstantNode.java | 15 +-- .../core/nodetypes/EnteredFunction.java | 36 +++++++ .../core/nodetypes/ExpressionNode.java | 19 ++-- .../core/nodetypes/FieldRefNode.java | 15 +-- .../core/nodetypes/IExpression.java | 14 +++ .../prorefactor/core/nodetypes/IfNode.java | 1 - .../core/nodetypes/InUIReferenceNode.java | 17 +--- .../core/nodetypes/LocalMethodCallNode.java | 19 +--- .../core/nodetypes/MethodCallNode.java | 21 +---- .../core/nodetypes/NamedMemberArrayNode.java | 19 +--- .../core/nodetypes/NamedMemberNode.java | 19 +--- .../core/nodetypes/NewTypeNode.java | 15 +-- .../nodetypes/SingleArgumentExpression.java | 19 ++-- .../core/nodetypes/SystemHandleNode.java | 19 ++-- .../nodetypes/TwoArgumentsExpression.java | 19 ++-- .../core/nodetypes/UserFunctionCallNode.java | 23 ++--- .../core/nodetypes/WidgetNode.java | 17 +--- .../prorefactor/core/TreeParser03Test.java | 16 ++-- .../proparse/ExpressionEngineTest.java | 94 ++++++++----------- 24 files changed, 217 insertions(+), 300 deletions(-) create mode 100644 proparse/src/main/java/org/prorefactor/core/nodetypes/EnteredFunction.java diff --git a/proparse/src/main/java/org/prorefactor/core/JPNode.java b/proparse/src/main/java/org/prorefactor/core/JPNode.java index b26457f27..a17c0ea63 100644 --- a/proparse/src/main/java/org/prorefactor/core/JPNode.java +++ b/proparse/src/main/java/org/prorefactor/core/JPNode.java @@ -30,8 +30,9 @@ import org.prorefactor.core.nodetypes.BlockNode; import org.prorefactor.core.nodetypes.BuiltinFunctionNode; import org.prorefactor.core.nodetypes.ConstantNode; -import org.prorefactor.core.nodetypes.ExpressionNode; +import org.prorefactor.core.nodetypes.EnteredFunction; import org.prorefactor.core.nodetypes.FieldRefNode; +import org.prorefactor.core.nodetypes.IExpression; import org.prorefactor.core.nodetypes.IfNode; import org.prorefactor.core.nodetypes.InUIReferenceNode; import org.prorefactor.core.nodetypes.LocalMethodCallNode; @@ -432,7 +433,7 @@ public List queryStateHead() { /** * Get an array of all expressions */ - public List queryExpressions() { + public List queryExpressions() { JPNodeExpressionQuery query = new JPNodeExpressionQuery(); walk2(query); @@ -530,10 +531,20 @@ public int getState2() { return attrGet(IConstants.STATE2); } - public boolean isExpression() { + /** + * @return True is node is an expression + */ + public boolean isIExpression() { return false; } + /** + * @return Cast to IExpression if isIExpression is true, otherwise null + */ + public IExpression asIExpression() { + return null; + } + /** * @return Secondary node type, i.e. VARIABLE in DEFINE VARIABLE statement. Can be null */ @@ -1151,6 +1162,9 @@ private JPNode build(ParseUnit unit, ParserSupport support, JPNode up, int num) case FIELD_REF: node = new FieldRefNode(tok, up, num, hasChildren); break; + case ENTERED_FUNC: + node = new EnteredFunction(tok, up, num, hasChildren); + break; case STAR: case MULTIPLY: case SLASH: @@ -1179,7 +1193,7 @@ private JPNode build(ParseUnit unit, ParserSupport support, JPNode up, int num) node = new TwoArgumentsExpression(tok, up, num, hasChildren); break; default: - node = new ExpressionNode(tok, up, num, hasChildren); + throw new IllegalStateException("Invalid Expression node: " + tok.getNodeType()); } } else { switch (tok.getNodeType()) { diff --git a/proparse/src/main/java/org/prorefactor/core/JPNodeExpressionQuery.java b/proparse/src/main/java/org/prorefactor/core/JPNodeExpressionQuery.java index 3da06322c..4db7714be 100644 --- a/proparse/src/main/java/org/prorefactor/core/JPNodeExpressionQuery.java +++ b/proparse/src/main/java/org/prorefactor/core/JPNodeExpressionQuery.java @@ -17,18 +17,20 @@ import java.util.ArrayList; import java.util.List; -class JPNodeExpressionQuery implements ICallback> { - private final List result = new ArrayList<>(); +import org.prorefactor.core.nodetypes.IExpression; + +class JPNodeExpressionQuery implements ICallback> { + private final List result = new ArrayList<>(); @Override - public List getResult() { + public List getResult() { return result; } @Override public boolean visitNode(JPNode node) { - if (node.isExpression()) { - result.add(node); + if (node.isIExpression()) { + result.add(node.asIExpression()); return false; } else return true; diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/ArrayReferenceNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/ArrayReferenceNode.java index c94281f1f..10f8ee8a1 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/ArrayReferenceNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/ArrayReferenceNode.java @@ -19,7 +19,10 @@ import eu.rssw.pct.elements.DataType; -public class ArrayReferenceNode extends JPNode implements IExpression { +/** + * Expression node: <expr>[expr] + */ +public class ArrayReferenceNode extends ExpressionNode { public ArrayReferenceNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); @@ -27,16 +30,7 @@ public ArrayReferenceNode(ProToken t, JPNode parent, int num, boolean hasChildre @Override public DataType getDataType() { - return ((IExpression) getDirectChildren().get(0)).getDataType(); + return getDirectChildren().get(0).asIExpression().getDataType(); } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } } diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/AttributeReferenceNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/AttributeReferenceNode.java index 0e0e4a6fa..28e95abb3 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/AttributeReferenceNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/AttributeReferenceNode.java @@ -25,13 +25,12 @@ import eu.rssw.pct.elements.IVariableElement; import eu.rssw.pct.elements.PrimitiveDataType; -public class AttributeReferenceNode extends JPNode implements IExpression { +/** + * Expression node: <expr>:attributeName + */ +public class AttributeReferenceNode extends ExpressionNode { private String attributeName = ""; - public AttributeReferenceNode(ProToken t, JPNode parent, int num, boolean hasChildren) { - this(t, parent, num, hasChildren, ""); - } - public AttributeReferenceNode(ProToken t, JPNode parent, int num, boolean hasChildren, String attributeName) { super(t, parent, num, hasChildren); this.attributeName = Strings.nullToEmpty(attributeName); @@ -53,7 +52,7 @@ public DataType getDataType() { return DataType.NOT_COMPUTED; // Left-Handle expression has to be a class - IExpression expr = (IExpression) getFirstChild(); + IExpression expr = getFirstChild().asIExpression(); if (expr.getDataType().getPrimitive() == PrimitiveDataType.CLASS) { ITypeInfo info = root.getParserSupport().getProparseSession().getTypeInfo(expr.getDataType().getClassName()); if (info != null) { @@ -73,14 +72,4 @@ public DataType getDataType() { return DataType.NOT_COMPUTED; } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - } diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/BuiltinFunctionNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/BuiltinFunctionNode.java index 97bd7a404..594528f39 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/BuiltinFunctionNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/BuiltinFunctionNode.java @@ -22,36 +22,29 @@ import eu.rssw.pct.elements.DataType; -public class BuiltinFunctionNode extends JPNode implements IExpression { +/** + * Expression node: funcName(parameters) + */ +public class BuiltinFunctionNode extends ExpressionNode { public BuiltinFunctionNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - public DataType getAddIntervalDataType() { - List nodes = getFirstChild().queryExpressions(); + List nodes = getFirstChild().queryExpressions(); if (nodes.size() != 3) { return DataType.DATE; } - return ((IExpression) nodes.get(0)).getDataType(); + return nodes.get(0).getDataType(); } public DataType getIfDataType() { - List nodes = getFirstChild().queryExpressions(); + List nodes = getFirstChild().queryExpressions(); if (nodes.size() != 3) { return DataType.NOT_COMPUTED; } - return ((IExpression) nodes.get(1)).getDataType(); + return nodes.get(1).getDataType(); } public DataType getCastDataType() { @@ -63,10 +56,10 @@ public DataType getCastDataType() { } public DataType getMinMaxDataType() { - List nodes = getFirstChild().queryExpressions(); + List nodes = getFirstChild().queryExpressions(); boolean hasDecimal = false; - for (JPNode node : nodes) { - if( ((IExpression) node).getDataType() == DataType.DECIMAL) + for (IExpression node : nodes) { + if (node.getDataType() == DataType.DECIMAL) hasDecimal = true; } return hasDecimal ? DataType.DECIMAL : DataType.INTEGER; diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/ConstantNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/ConstantNode.java index df5ea3c84..3e62383e6 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/ConstantNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/ConstantNode.java @@ -19,22 +19,15 @@ import eu.rssw.pct.elements.DataType; -public class ConstantNode extends JPNode implements IExpression { +/** + * Expression node: constant (such as TRUE) + */ +public class ConstantNode extends ExpressionNode { public ConstantNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - @Override public DataType getDataType() { switch (getFirstChild().getNodeType()) { diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/EnteredFunction.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/EnteredFunction.java new file mode 100644 index 000000000..a3575050a --- /dev/null +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/EnteredFunction.java @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2015-2021 Riverside Software + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 + * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt + * + * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 + ********************************************************************************/ +package org.prorefactor.core.nodetypes; + +import org.prorefactor.core.JPNode; +import org.prorefactor.core.ProToken; + +import eu.rssw.pct.elements.DataType; + +/** + * Expression node: <field> NOT? ENTERED + */ +public class EnteredFunction extends ExpressionNode { + + public EnteredFunction(ProToken t, JPNode parent, int num, boolean hasChildren) { + super(t, parent, num, hasChildren); + } + + @Override + public DataType getDataType() { + return getDirectChildren().get(0).asIExpression().getDataType(); + } + +} diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/ExpressionNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/ExpressionNode.java index a9fb7b0bb..4aa98f38e 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/ExpressionNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/ExpressionNode.java @@ -24,23 +24,28 @@ import eu.rssw.pct.elements.ITypeInfo; import eu.rssw.pct.elements.IVariableElement; -public class ExpressionNode extends JPNode implements IExpression { +public abstract class ExpressionNode extends JPNode implements IExpression { - public ExpressionNode(ProToken t, JPNode parent, int num, boolean hasChildren) { + ExpressionNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); } @Override - public boolean isExpression() { + public boolean isIExpression() { return true; } + @Override + public IExpression asIExpression() { + return this; + } + @Override public JPNode asJPNode() { return this; } - public static DataType getStandardAttributeDataType(String id) { + static DataType getStandardAttributeDataType(String id) { switch (id) { case "ACCELERATOR": case "ACTOR": @@ -720,7 +725,7 @@ public static DataType getStandardAttributeDataType(String id) { } } - public static DataType getStandardMethodDataType(String id) { + static DataType getStandardMethodDataType(String id) { switch (id) { case "ADD-NEW-FIELD": return DataType.LOGICAL; @@ -730,7 +735,7 @@ public static DataType getStandardMethodDataType(String id) { } } - public static DataType getObjectMethodDataType(IProparseEnvironment session, ITypeInfo info, String methodName) { + static DataType getObjectMethodDataType(IProparseEnvironment session, ITypeInfo info, String methodName) { while (info != null) { for (IMethodElement m : info.getMethods()) { if (m.getName().equalsIgnoreCase(methodName)) @@ -741,7 +746,7 @@ public static DataType getObjectMethodDataType(IProparseEnvironment session, ITy return DataType.NOT_COMPUTED; } - public static DataType getObjectAttributeDataType(IProparseEnvironment session, ITypeInfo info, String methodName, boolean firstLevel) { + static DataType getObjectAttributeDataType(IProparseEnvironment session, ITypeInfo info, String methodName, boolean firstLevel) { while (info != null) { for (IPropertyElement prop : info.getProperties()) { if (prop.getName().equalsIgnoreCase(methodName)) diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java index 0a3e28e71..50503aa5e 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java @@ -23,7 +23,10 @@ import eu.rssw.pct.elements.DataType; -public class FieldRefNode extends JPNode implements IExpression { +/** + * Expression node: ID where ID is a variable, field name, ... + */ +public class FieldRefNode extends ExpressionNode { private ContextQualifier qualifier; public FieldRefNode(ProToken t, JPNode parent, int num, boolean hasChildren) { @@ -50,16 +53,6 @@ public DataType getDataType() { return DataType.NOT_COMPUTED; } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - /** * We very often need to reference the ID node for a Field_ref node. The Field_ref node is a synthetic node - it * doesn't have any text. If we want the field/variable name, or the file/line/column, then we probably want to get diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/IExpression.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/IExpression.java index 763e89d63..97ca2180f 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/IExpression.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/IExpression.java @@ -1,3 +1,17 @@ +/******************************************************************************** + * Copyright (c) 2015-2021 Riverside Software + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 + * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt + * + * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 + ********************************************************************************/ package org.prorefactor.core.nodetypes; import javax.annotation.Nonnull; diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java index 5e4952bb5..cae2e4a87 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2003-2015 John Green * Copyright (c) 2015-2021 Riverside Software * * This program and the accompanying materials are made available under the diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/InUIReferenceNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/InUIReferenceNode.java index 089f924c0..918b4942c 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/InUIReferenceNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/InUIReferenceNode.java @@ -19,7 +19,10 @@ import eu.rssw.pct.elements.DataType; -public class InUIReferenceNode extends JPNode implements IExpression { +/** + * Expression node: <expr> IN FRAME frame-name + */ +public class InUIReferenceNode extends ExpressionNode { public InUIReferenceNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); @@ -27,17 +30,7 @@ public InUIReferenceNode(ProToken t, JPNode parent, int num, boolean hasChildren @Override public DataType getDataType() { - return ((IExpression) getDirectChildren().get(0)).getDataType(); - } - - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; + return getDirectChildren().get(0).asIExpression().getDataType(); } } diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/LocalMethodCallNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/LocalMethodCallNode.java index 61dcae513..254139e96 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/LocalMethodCallNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/LocalMethodCallNode.java @@ -23,13 +23,12 @@ import eu.rssw.pct.elements.IMethodElement; import eu.rssw.pct.elements.ITypeInfo; -public class LocalMethodCallNode extends JPNode implements IExpression { +/** + * Expression node: methodName(parameters) (only in classes) + */ +public class LocalMethodCallNode extends ExpressionNode { private String methodName = ""; - public LocalMethodCallNode(ProToken t, JPNode parent, int num, boolean hasChildren) { - this(t, parent, num, hasChildren, ""); - } - public LocalMethodCallNode(ProToken t, JPNode parent, int num, boolean hasChildren, String methodName) { super(t, parent, num, hasChildren); this.methodName = Strings.nullToEmpty(methodName); @@ -39,16 +38,6 @@ public String getMethodName() { return methodName; } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - @Override public DataType getDataType() { ProgramRootNode root = getTopLevelParent(); diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/MethodCallNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/MethodCallNode.java index 949e7891f..0e7b5a11a 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/MethodCallNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/MethodCallNode.java @@ -23,13 +23,12 @@ import eu.rssw.pct.elements.ITypeInfo; import eu.rssw.pct.elements.PrimitiveDataType; -public class MethodCallNode extends JPNode implements IExpression { +/** + * Expression node: <expr>:methodName(parameters) + */ +public class MethodCallNode extends ExpressionNode { private String methodName = ""; - public MethodCallNode(ProToken t, JPNode parent, int num, boolean hasChildren) { - this(t, parent, num, hasChildren, ""); - } - public MethodCallNode(ProToken t, JPNode parent, int num, boolean hasChildren, String methodName) { super(t, parent, num, hasChildren); this.methodName = Strings.nullToEmpty(methodName); @@ -39,16 +38,6 @@ public String getMethodName() { return methodName; } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - @Override public DataType getDataType() { if (getFirstChild() instanceof SystemHandleNode) { @@ -60,7 +49,7 @@ public DataType getDataType() { return DataType.NOT_COMPUTED; // Left-Handle expression has to be a class - IExpression expr = (IExpression) getFirstChild(); + IExpression expr = getFirstChild().asIExpression(); if (expr.getDataType().getPrimitive() == PrimitiveDataType.CLASS) { ITypeInfo info = root.getParserSupport().getProparseSession().getTypeInfo(expr.getDataType().getClassName()); return ExpressionNode.getObjectMethodDataType(root.getParserSupport().getProparseSession(), info, methodName); diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/NamedMemberArrayNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/NamedMemberArrayNode.java index e81243855..4845d7f5f 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/NamedMemberArrayNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/NamedMemberArrayNode.java @@ -19,13 +19,12 @@ import com.google.common.base.Strings; -public class NamedMemberArrayNode extends JPNode implements IExpression { +/** + * Expression node: <expr>::namedMember(expr) + */ +public class NamedMemberArrayNode extends ExpressionNode { private String namedMember = ""; - public NamedMemberArrayNode(ProToken t, JPNode parent, int num, boolean hasChildren) { - this(t, parent, num, hasChildren, ""); - } - public NamedMemberArrayNode(ProToken t, JPNode parent, int num, boolean hasChildren, String namedMember) { super(t, parent, num, hasChildren); this.namedMember = Strings.nullToEmpty(namedMember); @@ -35,14 +34,4 @@ public String getNamedMember() { return namedMember; } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - } diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/NamedMemberNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/NamedMemberNode.java index 2d21ae342..be8cbe955 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/NamedMemberNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/NamedMemberNode.java @@ -19,13 +19,12 @@ import com.google.common.base.Strings; -public class NamedMemberNode extends JPNode implements IExpression { +/** + * Expression node: <expr>::namedMember + */ +public class NamedMemberNode extends ExpressionNode { private String namedMember = ""; - public NamedMemberNode(ProToken t, JPNode parent, int num, boolean hasChildren) { - this(t, parent, num, hasChildren, ""); - } - public NamedMemberNode(ProToken t, JPNode parent, int num, boolean hasChildren, String namedMember) { super(t, parent, num, hasChildren); this.namedMember = Strings.nullToEmpty(namedMember); @@ -35,14 +34,4 @@ public String getNamedMember() { return namedMember; } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - } diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/NewTypeNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/NewTypeNode.java index eaa9a699b..ea7eab820 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/NewTypeNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/NewTypeNode.java @@ -19,22 +19,15 @@ import eu.rssw.pct.elements.DataType; -public class NewTypeNode extends JPNode implements IExpression { +/** + * Expression node: NEW typeName(parameters) + */ +public class NewTypeNode extends ExpressionNode { public NewTypeNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - @Override public DataType getDataType() { TypeNameNode typeNameNode = (TypeNameNode) getFirstChild().getNextSibling(); diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/SingleArgumentExpression.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/SingleArgumentExpression.java index cb30682f6..16e1e5819 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/SingleArgumentExpression.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/SingleArgumentExpression.java @@ -19,7 +19,10 @@ import eu.rssw.pct.elements.DataType; -public class SingleArgumentExpression extends JPNode implements IExpression { +/** + * Expression node: [+|-|NOT]expr or parenthesis + */ +public class SingleArgumentExpression extends ExpressionNode { public SingleArgumentExpression(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); @@ -30,9 +33,9 @@ public DataType getDataType() { switch (getNodeType()) { case UNARY_PLUS: case UNARY_MINUS: - return ((IExpression) getFirstChild()).getDataType(); + return getFirstChild().asIExpression().getDataType(); case PAREN_EXPR: - return ((IExpression) getFirstChild().getNextSibling()).getDataType(); + return getFirstChild().getNextSibling().asIExpression().getDataType(); case NOT: return DataType.LOGICAL; default: @@ -40,14 +43,4 @@ public DataType getDataType() { } } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - } diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/SystemHandleNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/SystemHandleNode.java index 60194bb29..dc711b016 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/SystemHandleNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/SystemHandleNode.java @@ -20,28 +20,21 @@ import eu.rssw.pct.elements.DataType; import eu.rssw.pct.elements.ITypeInfo; -public class SystemHandleNode extends JPNode implements IExpression { +/** + * Expression node: syshandle + */ +public class SystemHandleNode extends ExpressionNode { public SystemHandleNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - @Override public DataType getDataType() { return DataType.HANDLE; } - public DataType getAttributeDataType(String id) { + DataType getAttributeDataType(String id) { switch (getFirstChild().getNodeType()) { case ACTIVEFORM: return getActiveFormAttributeDataType(id); @@ -54,7 +47,7 @@ public DataType getAttributeDataType(String id) { } } - public DataType getMethodDataType(String id) { + DataType getMethodDataType(String id) { switch (getFirstChild().getNodeType()) { case ACTIVEFORM: case CLIPBOARD: diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/TwoArgumentsExpression.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/TwoArgumentsExpression.java index accd5467d..e3d12e805 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/TwoArgumentsExpression.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/TwoArgumentsExpression.java @@ -19,7 +19,10 @@ import eu.rssw.pct.elements.DataType; -public class TwoArgumentsExpression extends JPNode implements IExpression { +/** + * Expression node: <expr> [+|-|*|/|...] <expr> + */ +public class TwoArgumentsExpression extends ExpressionNode { public TwoArgumentsExpression(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); } @@ -31,8 +34,8 @@ public boolean hasProparseDirective(String directive) { @Override public DataType getDataType() { - DataType left = ((IExpression) getDirectChildren().get(0)).getDataType(); - DataType right = ((IExpression) getDirectChildren().get(1)).getDataType(); + DataType left = getDirectChildren().get(0).asIExpression().getDataType(); + DataType right = getDirectChildren().get(1).asIExpression().getDataType(); switch (getNodeType()) { case PLUS: @@ -70,16 +73,6 @@ public DataType getDataType() { } } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - private DataType handlePlus(DataType left, DataType right) { if ((left == DataType.LONGCHAR) || (right == DataType.LONGCHAR)) return DataType.LONGCHAR; diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/UserFunctionCallNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/UserFunctionCallNode.java index 55f56e303..8aac41d20 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/UserFunctionCallNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/UserFunctionCallNode.java @@ -22,32 +22,21 @@ import eu.rssw.pct.elements.DataType; -public class UserFunctionCallNode extends JPNode implements IExpression { +/** + * Expression node: functionName(parameters) (only in procedures) + */ +public class UserFunctionCallNode extends ExpressionNode { private String functionName = ""; - public UserFunctionCallNode(ProToken t, JPNode parent, int num, boolean hasChildren) { - this(t, parent, num, hasChildren, ""); - } - - public UserFunctionCallNode(ProToken t, JPNode parent, int num, boolean hasChildren, String functinoName) { + public UserFunctionCallNode(ProToken t, JPNode parent, int num, boolean hasChildren, String functionName) { super(t, parent, num, hasChildren); - this.functionName = Strings.nullToEmpty(functinoName); + this.functionName = Strings.nullToEmpty(functionName); } public String getFunctionName() { return functionName; } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - @Override public DataType getDataType() { ProgramRootNode root = getTopLevelParent(); diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/WidgetNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/WidgetNode.java index 18e725bc0..71141a945 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/WidgetNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/WidgetNode.java @@ -20,28 +20,21 @@ import eu.rssw.pct.elements.DataType; -public class WidgetNode extends JPNode implements IExpression { +/** + * Expression node: widget + */ +public class WidgetNode extends ExpressionNode { public WidgetNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); } - @Override - public boolean isExpression() { - return true; - } - - @Override - public JPNode asJPNode() { - return this; - } - @Override public DataType getDataType() { return DataType.HANDLE; } - public DataType getMethodDataType(String id) { + DataType getMethodDataType(String id) { return DataType.NOT_COMPUTED; } diff --git a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java index 1a9eeac5a..e919a4461 100644 --- a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java +++ b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java @@ -1294,15 +1294,15 @@ public void testSuper02() throws JAXBException, IOException { List list = unit.getTopNode().query(ABLNodeType.SUPER); assertEquals(list.size(), 3); assertEquals(list.get(0).getParent().getNodeType(), ABLNodeType.METHOD_REF); - assertTrue(list.get(0).getParent().isExpression()); + assertTrue(list.get(0).getParent().isIExpression()); assertTrue(list.get(0).getParent().isStateHead()); assertEquals(list.get(1).getParent().getNodeType(), ABLNodeType.METHOD_REF); - assertTrue(list.get(1).getParent().isExpression()); + assertTrue(list.get(1).getParent().isIExpression()); assertTrue(list.get(1).getParent().isStateHead()); assertEquals(list.get(2).getParent().getNodeType(), ABLNodeType.SYSTEM_HANDLE_REF); - assertTrue(list.get(2).getParent().isExpression()); + assertTrue(list.get(2).getParent().isIExpression()); assertEquals(list.get(2).getParent().getParent().getNodeType(), ABLNodeType.METHOD_REF); - assertTrue(list.get(2).getParent().getParent().isExpression()); + assertTrue(list.get(2).getParent().getParent().isIExpression()); assertFalse(list.get(2).getParent().getParent().isStateHead()); } @@ -1317,15 +1317,15 @@ public void testThisObject01() throws JAXBException, IOException { List list = unit.getTopNode().query(ABLNodeType.THISOBJECT); assertEquals(list.size(), 3); assertEquals(list.get(0).getParent().getNodeType(), ABLNodeType.METHOD_REF); - assertTrue(list.get(0).getParent().isExpression()); + assertTrue(list.get(0).getParent().isIExpression()); assertTrue(list.get(0).getParent().isStateHead()); assertEquals(list.get(1).getParent().getNodeType(), ABLNodeType.METHOD_REF); - assertTrue(list.get(1).getParent().isExpression()); + assertTrue(list.get(1).getParent().isIExpression()); assertTrue(list.get(1).getParent().isStateHead()); assertEquals(list.get(2).getParent().getNodeType(), ABLNodeType.SYSTEM_HANDLE_REF); - assertTrue(list.get(2).getParent().isExpression()); + assertTrue(list.get(2).getParent().isIExpression()); assertEquals(list.get(2).getParent().getParent().getNodeType(), ABLNodeType.METHOD_REF); - assertTrue(list.get(2).getParent().getParent().isExpression()); + assertTrue(list.get(2).getParent().getParent().isIExpression()); assertFalse(list.get(2).getParent().getParent().isStateHead()); } diff --git a/proparse/src/test/java/org/prorefactor/proparse/ExpressionEngineTest.java b/proparse/src/test/java/org/prorefactor/proparse/ExpressionEngineTest.java index 2cc37a1b3..464e95be1 100644 --- a/proparse/src/test/java/org/prorefactor/proparse/ExpressionEngineTest.java +++ b/proparse/src/test/java/org/prorefactor/proparse/ExpressionEngineTest.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.util.List; -import org.prorefactor.core.JPNode; import org.prorefactor.core.nodetypes.AttributeReferenceNode; import org.prorefactor.core.nodetypes.BuiltinFunctionNode; import org.prorefactor.core.nodetypes.IExpression; @@ -83,9 +82,8 @@ public void testNamedMember01() { ParseUnit unit = new ParseUnit(new ByteArrayInputStream( "define temp-table tt1 field fld1 as int. define buffer b1 for tt1. buffer b1::fld1.".getBytes()), session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - assertTrue(nodes.get(0).isExpression()); NamedMemberNode exp = (NamedMemberNode) nodes.get(0); assertEquals(exp.getNamedMember(), "fld1"); assertEquals(exp.getDataType(), DataType.NOT_COMPUTED); @@ -98,9 +96,8 @@ public void testNamedMemberArray01() { "define temp-table tt1 field fld1 as int extent. define buffer b1 for tt1. buffer b1::fld1(1).".getBytes()), session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - assertTrue(nodes.get(0).isExpression()); NamedMemberArrayNode exp = (NamedMemberArrayNode) nodes.get(0); assertEquals(exp.getNamedMember(), "fld1"); assertEquals(exp.getDataType(), DataType.NOT_COMPUTED); @@ -123,10 +120,9 @@ public void testMethod01() { ParseUnit unit = new ParseUnit(new ByteArrayInputStream("session:get-printers().".getBytes()), session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); - assertEquals(exp.getDataType(), DataType.CHARACTER); + assertEquals(nodes.get(0).getDataType(), DataType.CHARACTER); } @Test @@ -134,10 +130,9 @@ public void testMethod02() { ParseUnit unit = new ParseUnit(new ByteArrayInputStream("compiler:get-row().".getBytes()), session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); - assertEquals(exp.getDataType(), DataType.INTEGER); + assertEquals(nodes.get(0).getDataType(), DataType.INTEGER); } @Test @@ -177,12 +172,12 @@ public void testSideEffect() { ParseUnit unit = new ParseUnit(new ByteArrayInputStream("etime(true). recid(customer).".getBytes()), session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 2); - IExpression exp1 = (IExpression) nodes.get(0); + IExpression exp1 = nodes.get(0); assertTrue(exp1 instanceof BuiltinFunctionNode); assertTrue(((BuiltinFunctionNode) exp1).hasSideEffect()); - IExpression exp2 = (IExpression) nodes.get(1); + IExpression exp2 = nodes.get(1); assertTrue(exp2 instanceof BuiltinFunctionNode); assertFalse(((BuiltinFunctionNode) exp2).hasSideEffect()); } @@ -193,9 +188,9 @@ public void testFunction01() { new ByteArrayInputStream("function f1 returns char () forwards. message f1().".getBytes()), session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType(), DataType.CHARACTER); } @@ -206,9 +201,9 @@ public void testNewObject01() { session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType().getPrimitive(), PrimitiveDataType.CLASS); assertEquals(exp.getDataType().getClassName(), "Progress.Lang.Object"); } @@ -219,9 +214,9 @@ public void testNewObject02() { "def var xx as Progress.Lang.Object. message new Progress.Lang.Object():toString().".getBytes()), session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType().getPrimitive(), PrimitiveDataType.CHARACTER); } @@ -232,9 +227,9 @@ public void testNewObject03() { session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType().getPrimitive(), PrimitiveDataType.LOGICAL); } @@ -244,9 +239,9 @@ public void testIfExpr01() { session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType().getPrimitive(), PrimitiveDataType.CHARACTER); } @@ -256,9 +251,9 @@ public void testIfExpr02() { session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType().getPrimitive(), PrimitiveDataType.INTEGER); } @@ -330,9 +325,9 @@ public void testObjectAttribute01() { new ByteArrayInputStream("def var xx as Progress.Lang.Object. message xx:Next-Sibling.".getBytes()), session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType().getPrimitive(), PrimitiveDataType.CLASS); assertEquals(exp.getDataType().getClassName(), "Progress.Lang.Object"); } @@ -344,27 +339,23 @@ public void testObjectAttribute02() { session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 4); - assertTrue(nodes.get(0).isExpression()); assertTrue(nodes.get(0) instanceof AttributeReferenceNode); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType(), DataType.CHARACTER); - assertTrue(nodes.get(1).isExpression()); assertTrue(nodes.get(1) instanceof AttributeReferenceNode); - IExpression exp2 = (IExpression) nodes.get(1); + IExpression exp2 = nodes.get(1); assertEquals(exp2.getDataType(), DataType.LONGCHAR); - assertTrue(nodes.get(2).isExpression()); assertTrue(nodes.get(2) instanceof AttributeReferenceNode); - IExpression exp3 = (IExpression) nodes.get(2); + IExpression exp3 = nodes.get(2); assertEquals(exp3.getDataType().getPrimitive(), PrimitiveDataType.CLASS); - assertTrue(nodes.get(3).isExpression()); assertTrue(nodes.get(3) instanceof AttributeReferenceNode); - IExpression exp4 = (IExpression) nodes.get(3); + IExpression exp4 = nodes.get(3); assertEquals(exp4.getDataType().getPrimitive(), PrimitiveDataType.CLASS); } @@ -376,17 +367,15 @@ public void testObjectMethod() { session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 2); - assertTrue(nodes.get(0).isExpression()); assertTrue(nodes.get(0) instanceof MethodCallNode); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType(), DataType.CHARACTER); - assertTrue(nodes.get(1).isExpression()); assertTrue(nodes.get(1) instanceof MethodCallNode); - IExpression exp2 = (IExpression) nodes.get(1); + IExpression exp2 = nodes.get(1); assertEquals(exp2.getDataType(), DataType.NOT_COMPUTED); } @@ -396,16 +385,14 @@ public void testObjectMethod02() { "class rssw.pct: method void m1(): toString(). foobar(). end method. end class.".getBytes()), session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 2); - assertTrue(nodes.get(0).isExpression()); assertTrue(nodes.get(0) instanceof LocalMethodCallNode); LocalMethodCallNode exp = (LocalMethodCallNode) nodes.get(0); assertEquals(exp.getMethodName(), "toString"); assertEquals(exp.getDataType(), DataType.CHARACTER); - assertTrue(nodes.get(1).isExpression()); assertTrue(nodes.get(1) instanceof LocalMethodCallNode); LocalMethodCallNode exp2 = (LocalMethodCallNode) nodes.get(1); assertEquals(exp2.getMethodName(), "foobar"); @@ -419,16 +406,14 @@ public void testObjectMethod03() { session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 3); - assertTrue(nodes.get(0).isExpression()); assertTrue(nodes.get(0) instanceof MethodCallNode); MethodCallNode exp = (MethodCallNode) nodes.get(0); assertEquals(exp.getMethodName(), "m2"); assertEquals(exp.getDataType(), DataType.INT64); - assertTrue(nodes.get(1).isExpression()); assertTrue(nodes.get(1) instanceof MethodCallNode); MethodCallNode exp2 = (MethodCallNode) nodes.get(1); assertEquals(exp2.getMethodName(), "toString"); @@ -442,16 +427,14 @@ public void testFunctions() { session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 2); - assertTrue(nodes.get(0).isExpression()); assertTrue(nodes.get(0) instanceof UserFunctionCallNode); UserFunctionCallNode exp = (UserFunctionCallNode) nodes.get(0); assertEquals(exp.getFunctionName(), "f1"); assertEquals(exp.getDataType(), DataType.CHARACTER); - assertTrue(nodes.get(1).isExpression()); assertTrue(nodes.get(1) instanceof UserFunctionCallNode); UserFunctionCallNode exp2 = (UserFunctionCallNode) nodes.get(1); assertEquals(exp2.getFunctionName(), "f2"); @@ -464,9 +447,9 @@ public void testHandleAttribute() { session); unit.treeParser01(); - List nodes = unit.getTopNode().queryExpressions(); + List nodes = unit.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType().getPrimitive(), PrimitiveDataType.LOGICAL); } @@ -474,10 +457,9 @@ private void testSimpleExpression(String code, DataType expected) { ParseUnit unit01 = new ParseUnit(new ByteArrayInputStream(code.getBytes()), session); unit01.treeParser01(); - List nodes = unit01.getTopNode().queryExpressions(); + List nodes = unit01.getTopNode().queryExpressions(); assertEquals(nodes.size(), 1); - assertTrue(nodes.get(0).isExpression()); - IExpression exp = (IExpression) nodes.get(0); + IExpression exp = nodes.get(0); assertEquals(exp.getDataType().getPrimitive(), expected.getPrimitive()); if (expected.getPrimitive() == PrimitiveDataType.CLASS) assertEquals(exp.getDataType().getClassName(), expected.getClassName()); From c6d2d813bbe37159750e9d4dcb8d90ab8df0c33b Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Tue, 21 Sep 2021 08:42:01 +0200 Subject: [PATCH 05/15] Improve getNextNode() implementation --- .../main/java/org/prorefactor/core/JPNode.java | 15 +++++++++++++-- .../java/org/prorefactor/core/JPNodeTest.java | 9 +++++++++ .../prorefactor/core/TreeParserBlocksTest.java | 9 +++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/proparse/src/main/java/org/prorefactor/core/JPNode.java b/proparse/src/main/java/org/prorefactor/core/JPNode.java index a17c0ea63..5e69a85c5 100644 --- a/proparse/src/main/java/org/prorefactor/core/JPNode.java +++ b/proparse/src/main/java/org/prorefactor/core/JPNode.java @@ -281,10 +281,21 @@ public JPNode nextNode() { } /** - * @return First child if there is one, otherwise next sibling + * @return First child if there is one, otherwise next sibling, otherwise parent's next sibling, or null if last node */ public JPNode getNextNode() { - return children == null || children.isEmpty() ? getNextSibling() : children.get(0); + if ((children != null) && !children.isEmpty()) + return children.get(0); + + JPNode tmp = parent; + int num = childNum; + while ((tmp.children.size() <= num + 1)) { + if (tmp.parent == null) + return null; + num = tmp.childNum; + tmp = tmp.parent; + } + return tmp.children.get(num + 1); } /** diff --git a/proparse/src/test/java/org/prorefactor/core/JPNodeTest.java b/proparse/src/test/java/org/prorefactor/core/JPNodeTest.java index 5f73215f2..808dcf1dd 100644 --- a/proparse/src/test/java/org/prorefactor/core/JPNodeTest.java +++ b/proparse/src/test/java/org/prorefactor/core/JPNodeTest.java @@ -166,6 +166,15 @@ public void testStatements() { assertEquals(msgStmts.get(0).query(ABLNodeType.VIEWAS).size(), 1); assertEquals(msgStmts.get(1).query(ABLNodeType.VIEWAS).size(), 1); assertEquals(msgStmts.get(2).query(ABLNodeType.VIEWAS).size(), 1); + + // Test getNextNode() + JPNode tmp = unit.getTopNode(); + int count = 0; + while (tmp != null) { + count++; + tmp = tmp.getNextNode(); + } + assertEquals(count, 33); } @Test diff --git a/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java b/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java index 9280ef9ae..eb2191273 100644 --- a/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java +++ b/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java @@ -188,6 +188,15 @@ public void test02() { assertEquals(currSubStmt2.getLine(), 10); assertNull(currSubStmt2.getPreviousStatement()); assertNull(currSubStmt2.getNextStatement()); + + // Test getNextNode() + JPNode tmp = unit.getTopNode(); + int count = 0; + while (tmp != null) { + count++; + tmp = tmp.getNextNode(); + } + assertEquals(count, 42); } @Test From 0bdd9b8570d735d2ea58a0f9cedb728de0a46d2c Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Mon, 20 Sep 2021 11:25:11 +0200 Subject: [PATCH 06/15] Remove (unneeded) strong dependency on BlockNode --- .../java/org/prorefactor/core/IConstants.java | 7 ---- .../AbstractBlockProparseListener.java | 35 +++++++++-------- .../org/prorefactor/treeparser/Block.java | 10 ++--- .../prorefactor/treeparser/FrameStack.java | 3 +- .../treeparser/TreeParserBlocks.java | 38 +++++++++---------- 5 files changed, 42 insertions(+), 51 deletions(-) diff --git a/proparse/src/main/java/org/prorefactor/core/IConstants.java b/proparse/src/main/java/org/prorefactor/core/IConstants.java index 8fb1b6865..92954d007 100644 --- a/proparse/src/main/java/org/prorefactor/core/IConstants.java +++ b/proparse/src/main/java/org/prorefactor/core/IConstants.java @@ -81,13 +81,6 @@ public class IConstants { * without referencing its value (i.e. no buffer scope). */ public static final int BUFFERSCOPE = -212; - /** - * A valid value for setLink() and getLink(). You should not use this directly. Only JPNodes of subtype BlockNode will - * have this set, so use BlockNode.getBlock instead. - * - * @see org.prorefactor.core.nodetypes.BlockNode - */ - public static final int BLOCK = -214; /** * A valid value for setLink() and getLink(). */ diff --git a/proparse/src/main/java/org/prorefactor/treeparser/AbstractBlockProparseListener.java b/proparse/src/main/java/org/prorefactor/treeparser/AbstractBlockProparseListener.java index 1f2fcdd82..f78c1a908 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/AbstractBlockProparseListener.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/AbstractBlockProparseListener.java @@ -3,7 +3,6 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTreeProperty; import org.prorefactor.core.JPNode; -import org.prorefactor.core.nodetypes.BlockNode; import org.prorefactor.proparse.antlr4.Proparse.CanFindFunctionContext; import org.prorefactor.proparse.antlr4.Proparse.CatchStatementContext; import org.prorefactor.proparse.antlr4.Proparse.ConstructorStatementContext; @@ -49,7 +48,7 @@ public abstract class AbstractBlockProparseListener extends ProparseBaseListener ParseTreeProperty nameResolution = new ParseTreeProperty<>(); @Inject - public AbstractBlockProparseListener(ParseUnit unit) { + AbstractBlockProparseListener(ParseUnit unit) { this.unit = unit; this.support = unit.getSupport(); this.refSession = unit.getSession(); @@ -57,7 +56,7 @@ public AbstractBlockProparseListener(ParseUnit unit) { } @Inject - public AbstractBlockProparseListener(AbstractBlockProparseListener listener) { + AbstractBlockProparseListener(AbstractBlockProparseListener listener) { this.unit = listener.unit; this.support = unit.getSupport(); this.refSession = unit.getSession(); @@ -81,7 +80,7 @@ public void enterProgram(ProgramContext ctx) { @Override public void enterCatchStatement(CatchStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); } @@ -94,7 +93,7 @@ public void exitCatchStatement(CatchStatementContext ctx) { @Override public void enterConstructorStatement(ConstructorStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); currentRoutine = currentScope.getRoutine(); @@ -109,7 +108,7 @@ public void exitConstructorStatement(ConstructorStatementContext ctx) { @Override public void enterCanFindFunction(CanFindFunctionContext ctx) { - BlockNode node = (BlockNode) support.getNode(ctx); + JPNode node = support.getNode(ctx); currentBlock = node.getBlock(); currentScope = currentBlock.getSymbolScope(); } @@ -146,7 +145,7 @@ public void exitDefinePropertyAccessorSetBlock(DefinePropertyAccessorSetBlockCon @Override public void enterDestructorStatement(DestructorStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); currentRoutine = currentScope.getRoutine(); @@ -161,7 +160,7 @@ public void exitDestructorStatement(DestructorStatementContext ctx) { @Override public void enterDoStatement(DoStatementContext ctx) { - currentBlock = ((BlockNode) support.getNode(ctx)).getBlock(); + currentBlock = support.getNode(ctx).getBlock(); } @Override @@ -171,7 +170,7 @@ public void exitDoStatement(DoStatementContext ctx) { @Override public void enterForStatement(ForStatementContext ctx) { - currentBlock = ((BlockNode) support.getNode(ctx)).getBlock(); + currentBlock = support.getNode(ctx).getBlock(); } @Override @@ -181,7 +180,7 @@ public void exitForStatement(ForStatementContext ctx) { @Override public void enterFunctionStatement(FunctionStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); currentRoutine = currentScope.getRoutine(); @@ -196,7 +195,7 @@ public void exitFunctionStatement(FunctionStatementContext ctx) { @Override public void enterExternalFunctionStatement(ExternalFunctionStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); currentRoutine = currentScope.getRoutine(); @@ -211,7 +210,7 @@ public void exitExternalFunctionStatement(ExternalFunctionStatementContext ctx) @Override public void enterMethodStatement(MethodStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); currentRoutine = currentScope.getRoutine(); @@ -226,7 +225,7 @@ public void exitMethodStatement(MethodStatementContext ctx) { @Override public void enterExternalProcedureStatement(ExternalProcedureStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); currentRoutine = currentScope.getRoutine(); @@ -241,7 +240,7 @@ public void exitExternalProcedureStatement(ExternalProcedureStatementContext ctx @Override public void enterProcedureStatement(ProcedureStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); currentRoutine = currentScope.getRoutine(); @@ -256,7 +255,7 @@ public void exitProcedureStatement(ProcedureStatementContext ctx) { @Override public void enterOnStatement(OnStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); } @@ -269,7 +268,7 @@ public void exitOnStatement(OnStatementContext ctx) { @Override public void enterRepeatStatement(RepeatStatementContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); } @@ -280,7 +279,7 @@ public void exitRepeatStatement(RepeatStatementContext ctx) { @Override public void enterTriggerOn(TriggerOnContext ctx) { - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = blockNode.getBlock(); currentScope = currentBlock.getSymbolScope(); } @@ -292,7 +291,7 @@ public void exitTriggerOn(TriggerOnContext ctx) { } public void propGetSetBegin(JPNode propAST) { - currentBlock = ((BlockNode) propAST).getBlock(); + currentBlock = propAST.getBlock(); currentScope = currentBlock.getSymbolScope(); currentRoutine = currentScope.getRoutine(); } diff --git a/proparse/src/main/java/org/prorefactor/treeparser/Block.java b/proparse/src/main/java/org/prorefactor/treeparser/Block.java index de5bbda74..b707025bc 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/Block.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/Block.java @@ -23,7 +23,7 @@ import java.util.Set; import org.prorefactor.core.ABLNodeType; -import org.prorefactor.core.nodetypes.BlockNode; +import org.prorefactor.core.JPNode; import org.prorefactor.core.nodetypes.RecordNameNode; import org.prorefactor.core.schema.IField; import org.prorefactor.proparse.antlr4.Proparse; @@ -38,7 +38,7 @@ * scopes. */ public class Block { - private final BlockNode blockStatementNode; + private final JPNode blockStatementNode; private List frames = new ArrayList<>(); private Set bufferScopes = new HashSet<>(); private Frame defaultFrame = null; @@ -49,7 +49,7 @@ public class Block { private TreeParserSymbolScope symbolScope; /** For constructing nested blocks */ - public Block(Block parent, BlockNode node) { + public Block(Block parent, JPNode node) { this.blockStatementNode = node; this.parentScopeBlock = parent; this.parentBlock = parent; @@ -62,7 +62,7 @@ public Block(Block parent, BlockNode node) { * @param symbolScope * @param node Is the Program_root if this is the program root block. */ - public Block(TreeParserSymbolScope symbolScope, BlockNode node, Block parentBlock) { + public Block(TreeParserSymbolScope symbolScope, JPNode node, Block parentBlock) { this.blockStatementNode = node; this.symbolScope = symbolScope; this.parentBlock = parentBlock; @@ -281,7 +281,7 @@ public List getFrames() { * Get the node for this block. Returns a node of one of these types: * Program_root/DO/FOR/REPEAT/EDITING/PROCEDURE/FUNCTION/ON/TRIGGERS. */ - public BlockNode getNode() { + public JPNode getNode() { return blockStatementNode; } diff --git a/proparse/src/main/java/org/prorefactor/treeparser/FrameStack.java b/proparse/src/main/java/org/prorefactor/treeparser/FrameStack.java index 348e8c7b2..75ce4834f 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/FrameStack.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/FrameStack.java @@ -24,7 +24,6 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.JPNode; -import org.prorefactor.core.nodetypes.BlockNode; import org.prorefactor.core.nodetypes.FieldRefNode; import org.prorefactor.core.nodetypes.RecordNameNode; import org.prorefactor.core.schema.Field; @@ -262,7 +261,7 @@ void nodeOfBlock(JPNode blockNode, Block currentBlock) { JPNode frameIDNode = containerTypeNode.nextNode(); assert frameIDNode.getType() == Proparse.ID; Frame frame = frameRefSet(frameIDNode, currentBlock.getSymbolScope()); - frame.setFrameScopeBlockExplicitDefault(((BlockNode) blockNode).getBlock()); + frame.setFrameScopeBlockExplicitDefault(blockNode.getBlock()); blockNode.setFieldContainer(frame); containerForCurrentStatement = frame; } diff --git a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java index 6ba4a1cec..4eeb79124 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java @@ -110,7 +110,7 @@ public void enterProgram(ProgramContext ctx) { throw new IllegalStateException("TreeParser has already been executed..."); } - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = pushBlock(new Block(rootScope, blockNode, null)); rootScope.setRootBlock(currentBlock); blockNode.setBlock(currentBlock); @@ -160,7 +160,7 @@ public void exitCatchStatement(CatchStatementContext ctx) { @Override public void enterConstructorStatement(ConstructorStatementContext ctx) { - newRoutine((BlockNode) support.getNode(ctx), "", ABLNodeType.CONSTRUCTOR); + newRoutine(support.getNode(ctx), "", ABLNodeType.CONSTRUCTOR); } @Override @@ -172,7 +172,7 @@ public void exitConstructorStatement(ConstructorStatementContext ctx) { @Override public void enterCanFindFunction(CanFindFunctionContext ctx) { // ...create a can-find scope and block (assigns currentBlock)... - scopeAdd((BlockNode) support.getNode(ctx)); + scopeAdd(support.getNode(ctx)); } @Override @@ -183,7 +183,7 @@ public void exitCanFindFunction(CanFindFunctionContext ctx) { @Override public void enterDefinePropertyAccessorGetBlock(DefinePropertyAccessorGetBlockContext ctx) { if (ctx.codeBlock() != null) { - BlockNode node = (BlockNode) support.getNode(ctx); + JPNode node = support.getNode(ctx); newRoutine(node, node.getText(), node.getNodeType()); } } @@ -191,7 +191,7 @@ public void enterDefinePropertyAccessorGetBlock(DefinePropertyAccessorGetBlockCo @Override public void enterDefinePropertyAccessorSetBlock(DefinePropertyAccessorSetBlockContext ctx) { if (ctx.codeBlock() != null) { - BlockNode node = (BlockNode) support.getNode(ctx); + JPNode node = support.getNode(ctx); newRoutine(node, node.getText(), node.getNodeType()); } } @@ -210,7 +210,7 @@ public void exitDefinePropertyAccessorSetBlock(DefinePropertyAccessorSetBlockCon @Override public void enterDestructorStatement(DestructorStatementContext ctx) { - newRoutine((BlockNode) support.getNode(ctx), "", ABLNodeType.DESTRUCTOR); + newRoutine(support.getNode(ctx), "", ABLNodeType.DESTRUCTOR); } @Override @@ -258,8 +258,8 @@ public void enterFunctionStatement(FunctionStatementContext ctx) { Routine fwdRoutine = forwardScope != null ? forwardScope.getRoutine() : null; TreeParserSymbolScope definingScope = currentScope; - BlockNode blockNode = (BlockNode) support.getNode(ctx); - newRoutine((BlockNode) support.getNode(ctx), ctx.id.getText(), ABLNodeType.FUNCTION); + JPNode blockNode = support.getNode(ctx); + newRoutine(blockNode, ctx.id.getText(), ABLNodeType.FUNCTION); if ((ctx.datatype().getStart().getType() == ABLNodeType.CLASS.getType()) || (ctx.datatype().getStop().getType() == ABLNodeType.TYPE_NAME.getType())) { currentRoutine.setReturnDatatypeNode(new DataType(ctx.datatype().getStop().getText())); @@ -300,7 +300,7 @@ public void exitFunctionStatement(FunctionStatementContext ctx) { public void enterExternalFunctionStatement(ExternalFunctionStatementContext ctx) { if (LOG.isTraceEnabled()) LOG.trace("{}> New external function definition '{}'", indent(), ctx.id.getText()); - newRoutine((BlockNode) support.getNode(ctx), ctx.id.getText(), ABLNodeType.FUNCTION); + newRoutine(support.getNode(ctx), ctx.id.getText(), ABLNodeType.FUNCTION); if ((ctx.datatype().getStart().getType() == ABLNodeType.CLASS.getType()) || (ctx.datatype().getStop().getType() == ABLNodeType.TYPE_NAME.getType())) { @@ -318,7 +318,7 @@ public void exitExternalFunctionStatement(ExternalFunctionStatementContext ctx) @Override public void enterMethodStatement(MethodStatementContext ctx) { - newRoutine((BlockNode) support.getNode(ctx), ctx.id.getText(), ABLNodeType.METHOD); + newRoutine(support.getNode(ctx), ctx.id.getText(), ABLNodeType.METHOD); if (ctx.VOID() != null) { currentRoutine.setReturnDatatypeNode(DataType.VOID); @@ -343,7 +343,7 @@ public void exitMethodStatement(MethodStatementContext ctx) { @Override public void enterExternalProcedureStatement(ExternalProcedureStatementContext ctx) { - newRoutine((BlockNode) support.getNode(ctx), ctx.filename().getText(), ABLNodeType.PROCEDURE); + newRoutine(support.getNode(ctx), ctx.filename().getText(), ABLNodeType.PROCEDURE); } @Override @@ -354,7 +354,7 @@ public void exitExternalProcedureStatement(ExternalProcedureStatementContext ctx @Override public void enterProcedureStatement(ProcedureStatementContext ctx) { - newRoutine((BlockNode) support.getNode(ctx), ctx.filename().getText(), ABLNodeType.PROCEDURE); + newRoutine(support.getNode(ctx), ctx.filename().getText(), ABLNodeType.PROCEDURE); } @Override @@ -365,7 +365,7 @@ public void exitProcedureStatement(ProcedureStatementContext ctx) { @Override public void enterOnStatement(OnStatementContext ctx) { - scopeAdd((BlockNode) support.getNode(ctx)); + scopeAdd(support.getNode(ctx)); } @Override @@ -385,7 +385,7 @@ public void exitRepeatStatement(RepeatStatementContext ctx) { @Override public void enterTriggerOn(TriggerOnContext ctx) { - scopeAdd((BlockNode) support.getNode(ctx)); + scopeAdd(support.getNode(ctx)); } @Override @@ -397,7 +397,7 @@ public void exitTriggerOn(TriggerOnContext ctx) { // INTERNAL METHODS // ****************** - private void newRoutine(BlockNode blockNode, String routineName, ABLNodeType routineType) { + private void newRoutine(JPNode blockNode, String routineName, ABLNodeType routineType) { TreeParserSymbolScope definingScope = currentScope; scopeAdd(blockNode); @@ -435,7 +435,7 @@ private Block popBlock() { private void blockBegin(ParseTree ctx) { if (LOG.isTraceEnabled()) LOG.trace("{}> Creating new block", indent()); - BlockNode blockNode = (BlockNode) support.getNode(ctx); + JPNode blockNode = support.getNode(ctx); currentBlock = pushBlock(new Block(currentBlock, blockNode)); blockNode.setBlock(currentBlock); } @@ -446,7 +446,7 @@ private void blockEnd() { currentBlock = popBlock(); } - private void scopeAdd(BlockNode blockNode) { + private void scopeAdd(JPNode blockNode) { if (LOG.isTraceEnabled()) LOG.trace("{}> Creating new scope for block {}", indent(), blockNode.getNodeType()); @@ -522,8 +522,8 @@ private void enterNewStatement(@Nonnull JPNode node) { } node.setInBlock(currentBlock); - if (currentBlock.getNode().getFirstStatement() == null) - currentBlock.getNode().setFirstStatement(node); + if (((BlockNode) currentBlock.getNode()).getFirstStatement() == null) + ((BlockNode) currentBlock.getNode()).setFirstStatement(node); // Assign annotations to statement JPNode prev = node.getPreviousStatement(); From 239d73ff81526fae4a689eae8abb4f146dce3ae3 Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Mon, 20 Sep 2021 13:19:30 +0200 Subject: [PATCH 07/15] Remove attribute map in JPNode --- .../java/org/prorefactor/core/JPNode.java | 85 ++++++++++--------- .../core/nodetypes/FieldRefNode.java | 9 ++ .../core/nodetypes/RecordNameNode.java | 22 ----- .../proparse/support/JPNodeLister.java | 6 +- .../proparse/support/TreeNodeLister.java | 8 +- .../org/prorefactor/treeparser/ParseUnit.java | 2 +- .../TreeParserVariableDefinition.java | 14 +-- .../prorefactor/core/TreeParser03Test.java | 7 +- .../core/util/AttributedWriter.java | 5 +- 9 files changed, 72 insertions(+), 86 deletions(-) diff --git a/proparse/src/main/java/org/prorefactor/core/JPNode.java b/proparse/src/main/java/org/prorefactor/core/JPNode.java index 5e69a85c5..1ae923e2f 100644 --- a/proparse/src/main/java/org/prorefactor/core/JPNode.java +++ b/proparse/src/main/java/org/prorefactor/core/JPNode.java @@ -16,10 +16,8 @@ import java.util.ArrayList; import java.util.EnumSet; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.function.Predicate; import javax.annotation.Nullable; @@ -76,13 +74,19 @@ public class JPNode { private Block inBlock; // Annotations found on statements (and blocks) private List annotations; + private boolean statement; + private int state2; // Fields are usually set in TreeParser private Symbol symbol; private FieldContainer container; private BufferScope bufferScope; - private Map attrMap; + private boolean operator; + private boolean inlineVar; + private int storeType; + private boolean abbrev; + private boolean invalidUseIndex; protected JPNode(ProToken token, JPNode parent, int num, boolean hasChildren) { this.token = token; @@ -509,37 +513,43 @@ public JPNode findDirectChild(int nodeType) { // Various attributes management // ***************************** - public int attrGet(int key) { - if ((attrMap != null) && attrMap.containsKey(key)) { - return attrMap.get(key); - } - switch (key) { - case IConstants.ABBREVIATED: - return isAbbreviated() ? 1 : 0; - default: - return 0; - } - } - - public void attrSet(Integer key, int val) { - if (attrMap == null) - initAttrMap(); - attrMap.put(key, val); - } - /** * Mark a node as "operator" */ public void setOperator() { - attrSet(IConstants.OPERATOR, IConstants.TRUE); + this.operator = true; } public boolean isOperator() { - return attrGet(IConstants.OPERATOR) == IConstants.TRUE; + return operator; } public int getState2() { - return attrGet(IConstants.STATE2); + return state2; + } + + public boolean isInlineVar() { + return inlineVar; + } + + public int getStoreType() { + return storeType; + } + + public void setStoreType(int storeType) { + this.storeType = storeType; + } + + public void setAbbrev(boolean abbrev) { + this.abbrev = abbrev; + } + + public void setInvalidUseIndex(boolean invalidUseIndex) { + this.invalidUseIndex = invalidUseIndex; + } + + public boolean isInvalidUseIndex() { + return invalidUseIndex; } /** @@ -570,14 +580,14 @@ public ABLNodeType getNodeType2() { /** Mark a node as a "statement head" */ public void setStatementHead() { - attrSet(IConstants.STATEHEAD, IConstants.TRUE); + this.statement = true; } /** Mark a node as a "statement head" */ public void setStatementHead(int state2) { - attrSet(IConstants.STATEHEAD, IConstants.TRUE); + this.statement = true; if (state2 != 0) - attrSet(IConstants.STATE2, state2); + this.state2 = state2; } /** Certain nodes will have a link to a Symbol, set by TreeParser. */ @@ -741,16 +751,8 @@ public String getAnnotationName() { return annName.toString(); } - - - private void initAttrMap() { - if (attrMap == null) { - attrMap = new HashMap<>(); - } - } - public boolean isAbbreviated() { - return token.isAbbreviated(); + return token.isAbbreviated() || abbrev; } /** @@ -769,10 +771,9 @@ public boolean isNatural() { /** Does this node have the Proparse STATEHEAD attribute? */ public boolean isStateHead() { - return attrGet(IConstants.STATEHEAD) == IConstants.TRUE; + return statement; } - /** * Used by TreeParser in order to assign Symbol to the right node * Never returns null @@ -1254,17 +1255,17 @@ private JPNode build(ParseUnit unit, ParserSupport support, JPNode up, int num) if (operator) node.setOperator(); if (inline) - node.attrSet(IConstants.INLINE_VAR_DEF, IConstants.TRUE); + node.inlineVar = true; if (tabletype != null) { switch (tabletype) { case DBTABLE: - node.attrSet(IConstants.STORETYPE, IConstants.ST_DBTABLE); + node.storeType = IConstants.ST_DBTABLE; break; case TTABLE: - node.attrSet(IConstants.STORETYPE, IConstants.ST_TTABLE); + node.storeType = IConstants.ST_TTABLE; break; case WTABLE: - node.attrSet(IConstants.STORETYPE, IConstants.ST_WTABLE); + node.storeType = IConstants.ST_WTABLE; break; case VARIABLE: // Never happens diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java index 50503aa5e..db1d7bda2 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java @@ -28,6 +28,7 @@ */ public class FieldRefNode extends ExpressionNode { private ContextQualifier qualifier; + private boolean unqualifiedField; public FieldRefNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); @@ -41,6 +42,14 @@ public ContextQualifier getQualifier() { return qualifier; } + public void setUnqualifiedField(boolean unqualifiedField) { + this.unqualifiedField = unqualifiedField; + } + + public boolean isUnqualifiedField() { + return unqualifiedField; + } + /** * Returns null if symbol is null or is a graphical component */ diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/RecordNameNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/RecordNameNode.java index 8e12c21d7..a6bf12575 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/RecordNameNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/RecordNameNode.java @@ -15,12 +15,8 @@ ********************************************************************************/ package org.prorefactor.core.nodetypes; -import javax.annotation.Nonnull; - -import org.prorefactor.core.IConstants; import org.prorefactor.core.JPNode; import org.prorefactor.core.ProToken; -import org.prorefactor.proparse.support.SymbolScope.FieldType; import org.prorefactor.treeparser.ContextQualifier; import org.prorefactor.treeparser.symbols.Symbol; import org.prorefactor.treeparser.symbols.TableBuffer; @@ -87,22 +83,4 @@ public boolean hasTableBuffer() { return getSymbol() instanceof TableBuffer; } - /** Set the 'store type' attribute on a RECORD_NAME node. */ - public void setStoreType(@Nonnull FieldType tabletype) { - switch (tabletype) { - case DBTABLE: - attrSet(IConstants.STORETYPE, IConstants.ST_DBTABLE); - break; - case TTABLE: - attrSet(IConstants.STORETYPE, IConstants.ST_TTABLE); - break; - case WTABLE: - attrSet(IConstants.STORETYPE, IConstants.ST_WTABLE); - break; - case VARIABLE: - // Never happens - break; - } - } - } diff --git a/proparse/src/main/java/org/prorefactor/proparse/support/JPNodeLister.java b/proparse/src/main/java/org/prorefactor/proparse/support/JPNodeLister.java index b8e1d4e92..1d4ea5184 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/support/JPNodeLister.java +++ b/proparse/src/main/java/org/prorefactor/proparse/support/JPNodeLister.java @@ -18,7 +18,6 @@ import java.io.PrintWriter; import java.util.Arrays; -import org.prorefactor.core.IConstants; import org.prorefactor.core.JPNode; /** @@ -87,9 +86,8 @@ private void printline(JPNode node, int level, char spacer, boolean showLine, bo if (showFileName) ofile.append(Integer.toString(node.getFileIndex())).append(spacer); if (showStore) { - int storetype = node.attrGet(IConstants.STORETYPE); - if (storetype != 0) - ofile.append(Integer.toString(storetype)).append(spacer); + if (node.getStoreType() != 0) + ofile.append(Integer.toString(node.getStoreType())).append(spacer); } ofile.append(getExtraInfo(node, spacer)); ofile.println(); diff --git a/proparse/src/main/java/org/prorefactor/proparse/support/TreeNodeLister.java b/proparse/src/main/java/org/prorefactor/proparse/support/TreeNodeLister.java index 40bde76f2..c15f18cb8 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/support/TreeNodeLister.java +++ b/proparse/src/main/java/org/prorefactor/proparse/support/TreeNodeLister.java @@ -86,12 +86,12 @@ private void printAttributes(JPNode node, int tabs) throws IOException { return; ofile.write(String.format("%3s %s", tabs, java.nio.CharBuffer.allocate(tabs).toString().replace('\0', ' '))); ofile.write(node.getNodeType() + (node.isStateHead() ? "^ " : " ") + (node.isStateHead() && node.getState2() != 0 ? node.getState2() : "")); - if (node.attrGet(IConstants.OPERATOR) == IConstants.TRUE) + if (node.isOperator()) ofile.write("*OP* "); - if (node.attrGet(IConstants.INLINE_VAR_DEF) == IConstants.TRUE) + if (node.isInlineVar()) ofile.write("*IN* "); - if (node.attrGet(IConstants.STORETYPE) > 0) - ofile.write("StoreType " + node.attrGet(IConstants.STORETYPE) + " "); + if (node.getStoreType() > 0) + ofile.write("StoreType " + node.getStoreType() + " "); if ((node.getNodeType() == ABLNodeType.ID) || (node.getNodeType() == ABLNodeType.TYPE_NAME)) { ofile.write("["); ofile.write(node.getText().replace('\'', ' ').replace('"', ' ')); diff --git a/proparse/src/main/java/org/prorefactor/treeparser/ParseUnit.java b/proparse/src/main/java/org/prorefactor/treeparser/ParseUnit.java index ed72c746d..767a858a4 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/ParseUnit.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/ParseUnit.java @@ -407,7 +407,7 @@ private static boolean isReferenceAssociatedToRecordNode(RecordNameNode recNode, return false; // On the same table if ((recNode.getTableBuffer() == null) || !tableName.equalsIgnoreCase(recNode.getTableBuffer().getTargetFullName()) - || (recNode.attrGet(IConstants.STORETYPE) != tableType)) + || (recNode.getStoreType() != tableType)) return false; // Does this statement have multiple RecordName nodes pointing to the same table ? // If so, we discard the Reference as it's currently not possible to assign to the right object diff --git a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserVariableDefinition.java b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserVariableDefinition.java index 7b8d19a38..d850c0847 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserVariableDefinition.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserVariableDefinition.java @@ -1990,7 +1990,7 @@ private void recordNodeSymbol(RecordNameNode node, TableBuffer buffer) { String[] nameParts = nodeText.split("\\."); int tableNameLen = nameParts[nameParts.length - 1].length(); if (table.getName().length() > tableNameLen) - node.attrSet(IConstants.ABBREVIATED, 1); + node.setAbbrev(true); } } @@ -2209,7 +2209,7 @@ private void defineUseIndex(JPNode recNode, JPNode idNode, String name) { currDefTable.getTable().add(new Index(currDefTable.getTable(), idx.getName(), idx.isUnique(), idx.isPrimary())); } else { // Mark idNode as INVALID_INDEX - idNode.attrSet(IConstants.INVALID_USEINDEX, IConstants.TRUE); + idNode.setInvalidUseIndex(true); } currDefTableUseIndex = true; } @@ -2331,7 +2331,7 @@ private void field(ParseTree ctx, FieldRefNode refNode, JPNode idNode, String na JPNode stmtNode = refNode.getStatement(); // Check if this is a Field_ref being "inline defined" // If so, we define it right now. - if (refNode.attrGet(IConstants.INLINE_VAR_DEF) == 1) + if (refNode.isInlineVar()) addToSymbolScope(defineVariable(ctx, refNode, name, Variable.Type.VARIABLE)); if (cq == ContextQualifier.STATIC) { // Nothing with static for now, but at least we don't check for external tables @@ -2378,9 +2378,9 @@ private void field(ParseTree ctx, FieldRefNode refNode, JPNode idNode, String na return; if (result.isUnqualified()) - refNode.attrSet(IConstants.UNQUALIFIED_FIELD, IConstants.TRUE); + refNode.setUnqualifiedField(true); if (result.isAbbreviated()) - refNode.attrSet(IConstants.ABBREVIATED, IConstants.TRUE); + refNode.setAbbrev(true); // Buffer attributes if (result.getBufferScope() != null) { @@ -2390,9 +2390,9 @@ private void field(ParseTree ctx, FieldRefNode refNode, JPNode idNode, String na refNode.setSymbol((Symbol) result.getSymbol()); if (result.getSymbol() instanceof FieldBuffer) { FieldBuffer fb = (FieldBuffer) result.getSymbol(); - refNode.attrSet(IConstants.STORETYPE, fb.getField().getTable().getStoretype()); + refNode.setStoreType(fb.getField().getTable().getStoretype()); } else { - refNode.attrSet(IConstants.STORETYPE, IConstants.ST_VAR); + refNode.setStoreType(IConstants.ST_VAR); } } diff --git a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java index e919a4461..d69013629 100644 --- a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java +++ b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java @@ -98,13 +98,12 @@ public void test03() { for (JPNode node : unit.getTopNode().query(ABLNodeType.DEFINE)) { if ((node.getState2() == ABLNodeType.TEMPTABLE.getType()) && "myTT2".equals(node.getNextNode().getNextNode().getText())) { - assertEquals(node.query(ABLNodeType.USEINDEX).get(0).getNextNode().attrGet(IConstants.INVALID_USEINDEX), - IConstants.TRUE); + assertTrue(node.query(ABLNodeType.USEINDEX).get(0).getNextNode().isInvalidUseIndex()); found1 = true; } if ((node.getState2() == ABLNodeType.TEMPTABLE.getType()) && "myTT3".equals(node.getNextNode().getNextNode().getText())) { - assertEquals(node.query(ABLNodeType.USEINDEX).get(0).getNextNode().attrGet(IConstants.INVALID_USEINDEX), 0); + assertFalse(node.query(ABLNodeType.USEINDEX).get(0).getNextNode().isInvalidUseIndex()); found2 = true; } } @@ -489,7 +488,7 @@ public void test21() { unit.treeParser01(); assertFalse(unit.hasSyntaxError()); JPNode node = unit.getTopNode().findDirectChild(ABLNodeType.DEFINE); - assertEquals(ABLNodeType.VARIABLE.getType(), node.attrGet(IConstants.STATE2)); + assertEquals(node.getState2(), ABLNodeType.VARIABLE.getType()); } @Test diff --git a/proparse/src/test/java/org/prorefactor/core/util/AttributedWriter.java b/proparse/src/test/java/org/prorefactor/core/util/AttributedWriter.java index 84ce982a8..4e49a0ba8 100644 --- a/proparse/src/test/java/org/prorefactor/core/util/AttributedWriter.java +++ b/proparse/src/test/java/org/prorefactor/core/util/AttributedWriter.java @@ -25,6 +25,7 @@ import org.prorefactor.core.IConstants; import org.prorefactor.core.JPNode; import org.prorefactor.core.ProToken; +import org.prorefactor.core.nodetypes.FieldRefNode; import org.prorefactor.core.nodetypes.TwoArgumentsExpression; import org.prorefactor.refactor.RefactorSession; import org.prorefactor.treeparser.Block; @@ -86,9 +87,9 @@ private void getAttributesForSymbol(JPNode node, StringBuffer nodeComments) { nodeComments.append(symbol.getScope().depth()); nodeComments.append(":"); nodeComments.append(symbol.fullName()); - if ((node.getNodeType() != ABLNodeType.DEFINE) && (node.attrGet(IConstants.ABBREVIATED) > 0)) + if ((node.getNodeType() != ABLNodeType.DEFINE) && node.isAbbreviated()) nodeComments.append(" abbrev"); - if (node.attrGet(IConstants.UNQUALIFIED_FIELD) > 0) + if ((node instanceof FieldRefNode) && ((FieldRefNode) node).isUnqualifiedField()) nodeComments.append(" unqualfield"); } From e2be896f8a950a0e93bec617b070374ec321fb28 Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Mon, 20 Sep 2021 18:17:15 +0200 Subject: [PATCH 08/15] Improve object mapping of statement flow --- .../openedge/checks/MultiLineIssue.java | 5 +- .../prorefactor/proparse/antlr4/Proparse.g4 | 5 +- .../java/org/prorefactor/core/JPNode.java | 209 ++++++------------ .../{BlockNode.java => CanFindNode.java} | 17 +- .../core/nodetypes/FieldRefNode.java | 28 +++ .../core/nodetypes/IStatement.java | 68 ++++++ .../core/nodetypes/IStatementBlock.java | 39 ++++ .../prorefactor/core/nodetypes/IfNode.java | 24 +- .../core/nodetypes/NonStatementBlockNode.java | 78 +++++++ .../core/nodetypes/ProgramRootNode.java | 4 +- .../core/nodetypes/RecordNameNode.java | 19 ++ .../core/nodetypes/StatementBlockNode.java | 73 ++++++ .../core/nodetypes/StatementNode.java | 113 ++++++++++ .../prorefactor/proparse/JPNodeVisitor.java | 43 ++-- .../proparse/support/JPNodeLister.java | 9 +- .../proparse/support/TreeNodeLister.java | 15 +- .../prorefactor/treeparser/FrameStack.java | 8 +- .../treeparser/TreeParserBlocks.java | 53 +++-- .../java/org/prorefactor/core/BugFixTest.java | 10 +- .../org/prorefactor/core/ClassesTest.java | 8 +- .../java/org/prorefactor/core/ParserTest.java | 20 +- .../prorefactor/core/TreeParser03Test.java | 14 +- .../core/TreeParserBlocksTest.java | 191 +++++++++------- .../core/util/TP01FramesTreeLister.java | 11 +- 24 files changed, 718 insertions(+), 346 deletions(-) rename proparse/src/main/java/org/prorefactor/core/nodetypes/{BlockNode.java => CanFindNode.java} (70%) create mode 100644 proparse/src/main/java/org/prorefactor/core/nodetypes/IStatement.java create mode 100644 proparse/src/main/java/org/prorefactor/core/nodetypes/IStatementBlock.java create mode 100644 proparse/src/main/java/org/prorefactor/core/nodetypes/NonStatementBlockNode.java create mode 100644 proparse/src/main/java/org/prorefactor/core/nodetypes/StatementBlockNode.java create mode 100644 proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java diff --git a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/checks/MultiLineIssue.java b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/checks/MultiLineIssue.java index 8ef7a79a2..d20060ff6 100644 --- a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/checks/MultiLineIssue.java +++ b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/checks/MultiLineIssue.java @@ -31,8 +31,9 @@ public class MultiLineIssue extends OpenEdgeProparseCheck { @Override public void execute(InputFile file, ParseUnit unit) { - NewIssue issue = createIssue(file, unit.getTopNode().getFirstStatement(), "First statement", true); - addLocation(issue, file, unit.getTopNode().getFirstStatement().getNextStatement(), "... and next one", false); + NewIssue issue = createIssue(file, unit.getTopNode().getFirstStatement().asJPNode(), "First statement", true); + addLocation(issue, file, unit.getTopNode().getFirstStatement().getNextStatement().asJPNode(), "... and next one", + false); issue.save(); } diff --git a/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 b/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 index 459d825df..7b6a6bd4b 100644 --- a/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 +++ b/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 @@ -2350,9 +2350,12 @@ hideStatement: ifStatement: // Plplt. Progress compiles this fine: DO: IF FALSE THEN END. // i.e. you don't have to have anything after the THEN or the ELSE. - IF expression THEN blockOrStatement ifElse? + IF expression ifThen ifElse? ; +ifThen: + THEN blockOrStatement; + ifElse: ELSE blockOrStatement ; diff --git a/proparse/src/main/java/org/prorefactor/core/JPNode.java b/proparse/src/main/java/org/prorefactor/core/JPNode.java index 1ae923e2f..96656aa21 100644 --- a/proparse/src/main/java/org/prorefactor/core/JPNode.java +++ b/proparse/src/main/java/org/prorefactor/core/JPNode.java @@ -25,12 +25,14 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.prorefactor.core.nodetypes.ArrayReferenceNode; import org.prorefactor.core.nodetypes.AttributeReferenceNode; -import org.prorefactor.core.nodetypes.BlockNode; import org.prorefactor.core.nodetypes.BuiltinFunctionNode; +import org.prorefactor.core.nodetypes.CanFindNode; import org.prorefactor.core.nodetypes.ConstantNode; import org.prorefactor.core.nodetypes.EnteredFunction; import org.prorefactor.core.nodetypes.FieldRefNode; import org.prorefactor.core.nodetypes.IExpression; +import org.prorefactor.core.nodetypes.IStatement; +import org.prorefactor.core.nodetypes.IStatementBlock; import org.prorefactor.core.nodetypes.IfNode; import org.prorefactor.core.nodetypes.InUIReferenceNode; import org.prorefactor.core.nodetypes.LocalMethodCallNode; @@ -38,9 +40,12 @@ import org.prorefactor.core.nodetypes.NamedMemberArrayNode; import org.prorefactor.core.nodetypes.NamedMemberNode; import org.prorefactor.core.nodetypes.NewTypeNode; +import org.prorefactor.core.nodetypes.NonStatementBlockNode; import org.prorefactor.core.nodetypes.ProgramRootNode; import org.prorefactor.core.nodetypes.RecordNameNode; import org.prorefactor.core.nodetypes.SingleArgumentExpression; +import org.prorefactor.core.nodetypes.StatementBlockNode; +import org.prorefactor.core.nodetypes.StatementNode; import org.prorefactor.core.nodetypes.SystemHandleNode; import org.prorefactor.core.nodetypes.TwoArgumentsExpression; import org.prorefactor.core.nodetypes.TypeNameNode; @@ -67,25 +72,13 @@ public class JPNode { @Nullable private final List children; - // Only for statement nodes: previous and next statement - private JPNode previousStatement; - private JPNode nextStatement; - // Only for statement nodes and block nodes: enclosing block - private Block inBlock; - // Annotations found on statements (and blocks) - private List annotations; - private boolean statement; - private int state2; - // Fields are usually set in TreeParser private Symbol symbol; private FieldContainer container; private BufferScope bufferScope; private boolean operator; - private boolean inlineVar; - private int storeType; - private boolean abbrev; + // TODO Create subtype for USE-INDEX nodes private boolean invalidUseIndex; protected JPNode(ProToken token, JPNode parent, int num, boolean hasChildren) { @@ -524,26 +517,6 @@ public boolean isOperator() { return operator; } - public int getState2() { - return state2; - } - - public boolean isInlineVar() { - return inlineVar; - } - - public int getStoreType() { - return storeType; - } - - public void setStoreType(int storeType) { - this.storeType = storeType; - } - - public void setAbbrev(boolean abbrev) { - this.abbrev = abbrev; - } - public void setInvalidUseIndex(boolean invalidUseIndex) { this.invalidUseIndex = invalidUseIndex; } @@ -566,30 +539,6 @@ public IExpression asIExpression() { return null; } - /** - * @return Secondary node type, i.e. VARIABLE in DEFINE VARIABLE statement. Can be null - */ - @Nullable - public ABLNodeType getNodeType2() { - int state2 = getState2(); - if (state2 == 0) - return null; - else - return ABLNodeType.getNodeType(state2); - } - - /** Mark a node as a "statement head" */ - public void setStatementHead() { - this.statement = true; - } - - /** Mark a node as a "statement head" */ - public void setStatementHead(int state2) { - this.statement = true; - if (state2 != 0) - this.state2 = state2; - } - /** Certain nodes will have a link to a Symbol, set by TreeParser. */ public Symbol getSymbol() { return symbol; @@ -752,7 +701,7 @@ public String getAnnotationName() { } public boolean isAbbreviated() { - return token.isAbbreviated() || abbrev; + return token.isAbbreviated(); } /** @@ -771,7 +720,27 @@ public boolean isNatural() { /** Does this node have the Proparse STATEHEAD attribute? */ public boolean isStateHead() { - return statement; + return isStatement(); + } + + public boolean isStatement() { + return false; + } + + public boolean isIStatement() { + return false; + } + + public boolean isIStatementBlock() { + return false; + } + + public IStatement asIStatement() { + return null; + } + + public IStatementBlock asIStatementBlock() { + return null; } /** @@ -914,52 +883,8 @@ public String allLeadingHiddenText() { return ret.toString(); } - public void setPreviousStatement(JPNode previousStatement) { - this.previousStatement = previousStatement; - } - - public JPNode getPreviousStatement() { - return previousStatement; - } - - public void setNextStatement(JPNode nextStatement) { - this.nextStatement = nextStatement; - } - - public JPNode getNextStatement() { - return nextStatement; - } - - public void setInBlock(Block inBlock) { - this.inBlock = inBlock; - } - - public void addAnnotation(String annotation) { - if (annotations == null) - annotations = new ArrayList<>(); - annotations.add(annotation); - } - - public List getAnnotations() { - return annotations; - } - public boolean hasAnnotation(String str) { - if (isStateHead()) { - if ((annotations != null) && annotations.contains(str)) - return true; - else if ((inBlock != null) && (inBlock.getNode() != null)) - return inBlock.getNode().hasAnnotation(str); - - else - return false; - } else { - return getStatement().hasAnnotation(str); - } - } - - public Block getEnclosingBlock() { - return inBlock; + return getStatement().hasAnnotation(str); } public static class Builder { @@ -974,8 +899,8 @@ public static class Builder { private String className; private boolean inline; private String xtra1; - private String xtra2; private boolean expression; + private boolean block; public Builder(ProToken tok) { this.tok = tok; @@ -1073,13 +998,13 @@ public Builder setExtraField1(String xtra1) { return this; } - public Builder setExtraField2(String xtra2) { - this.xtra2 = xtra2; + public Builder setExpression(boolean expression) { + this.expression = expression; return this; } - public Builder setExpression(boolean expression) { - this.expression = expression; + public Builder setBlock(boolean block) { + this.block = block; return this; } @@ -1213,65 +1138,55 @@ private JPNode build(ParseUnit unit, ParserSupport support, JPNode up, int num) throw new IllegalStateException("Empty node can't generate JPNode"); case RECORD_NAME: node = new RecordNameNode(tok, up, num, hasChildren); + if (tabletype != null) { + switch (tabletype) { + case DBTABLE: + ((RecordNameNode) node).setStoreType(IConstants.ST_DBTABLE); + break; + case TTABLE: + ((RecordNameNode) node).setStoreType(IConstants.ST_TTABLE); + break; + case WTABLE: + ((RecordNameNode) node).setStoreType(IConstants.ST_WTABLE); + break; + case VARIABLE: + // Never happens + break; + } + } break; case FIELD_REF: node = new FieldRefNode(tok, up, num, hasChildren); + if (inline) + ((FieldRefNode) node).setInlineVar(true); break; case PROGRAM_ROOT: node = new ProgramRootNode(tok, up, num, hasChildren, unit); break; - case FOR: - // FOR in 'DEFINE BUFFER x FOR y' is not a BlockNode - node = stmt ? new BlockNode(tok, up, num, hasChildren) : new JPNode(tok, up, num, hasChildren); - break; case TYPE_NAME: node = new TypeNameNode(tok, up, num, hasChildren, className); break; - case DO: - case REPEAT: - case FUNCTION: - case PROCEDURE: - case CONSTRUCTOR: - case DESTRUCTOR: - case METHOD: case CANFIND: - case CATCH: - case ON: - case PROPERTY_GETTER: - case PROPERTY_SETTER: - node = new BlockNode(tok, up, num, hasChildren); + node = new CanFindNode(tok, up, num, hasChildren); break; case IF: node = new IfNode(tok, up, num, hasChildren); break; default: - node = new JPNode(tok, up, num, hasChildren); + if (stmt && block) + node = new StatementBlockNode(tok, up, num, hasChildren, stmt2); + else if (stmt) + node = new StatementNode(tok, up, num, hasChildren, stmt2); + else if (block) + node = new NonStatementBlockNode(tok, up, num, hasChildren); + else + node = new JPNode(tok, up, num, hasChildren); break; } } - if (stmt) - node.setStatementHead(stmt2 == null ? 0 : stmt2.getType()); if (operator) node.setOperator(); - if (inline) - node.inlineVar = true; - if (tabletype != null) { - switch (tabletype) { - case DBTABLE: - node.storeType = IConstants.ST_DBTABLE; - break; - case TTABLE: - node.storeType = IConstants.ST_TTABLE; - break; - case WTABLE: - node.storeType = IConstants.ST_WTABLE; - break; - case VARIABLE: - // Never happens - break; - } - } if ((ctx != null) && (support != null)) support.pushNode(ctx, node); diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/BlockNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/CanFindNode.java similarity index 70% rename from proparse/src/main/java/org/prorefactor/core/nodetypes/BlockNode.java rename to proparse/src/main/java/org/prorefactor/core/nodetypes/CanFindNode.java index 40ea2911a..e56b15bf1 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/BlockNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/CanFindNode.java @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2003-2015 John Green * Copyright (c) 2015-2021 Riverside Software * * This program and the accompanying materials are made available under the @@ -23,25 +22,15 @@ import org.prorefactor.treeparser.Block; /** - * Specialized type of JPNode for those token types: DO, FOR, REPEAT, FUNCTION, PROCEDURE, CONSTRUCTOR, DESTRUCTOR, - * METHOD, CANFIND, CATCH, ON, PROPERTY_GETTER, PROPERTY_SETTER + * Specialized type of JPNode for CANFIND */ -public class BlockNode extends JPNode { +public class CanFindNode extends JPNode { private Block block; - private JPNode firstStatement; - public BlockNode(ProToken t, JPNode parent, int num, boolean hasChildren) { + public CanFindNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); } - public void setFirstStatement(JPNode firstStatement) { - this.firstStatement = firstStatement; - } - - public JPNode getFirstStatement() { - return firstStatement; - } - @Nullable @Override public Block getBlock() { diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java index db1d7bda2..fdac0f469 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/FieldRefNode.java @@ -28,7 +28,10 @@ */ public class FieldRefNode extends ExpressionNode { private ContextQualifier qualifier; + private int storeType; private boolean unqualifiedField; + private boolean inlineVar; + private boolean abbrev; public FieldRefNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); @@ -50,6 +53,31 @@ public boolean isUnqualifiedField() { return unqualifiedField; } + public void setInlineVar(boolean inlineVar) { + this.inlineVar = inlineVar; + } + + public boolean isInlineVar() { + return inlineVar; + } + + public int getStoreType() { + return storeType; + } + + public void setStoreType(int storeType) { + this.storeType = storeType; + } + + public void setAbbrev(boolean abbrev) { + this.abbrev = abbrev; + } + + @Override + public boolean isAbbreviated() { + return abbrev; + } + /** * Returns null if symbol is null or is a graphical component */ diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatement.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatement.java new file mode 100644 index 000000000..9b9b678f2 --- /dev/null +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatement.java @@ -0,0 +1,68 @@ +/******************************************************************************** + * Copyright (c) 2015-2021 Riverside Software + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 + * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt + * + * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 + ********************************************************************************/ +package org.prorefactor.core.nodetypes; + +import java.util.List; + +import javax.annotation.Nullable; + +import org.prorefactor.core.ABLNodeType; +import org.prorefactor.core.JPNode; + +public interface IStatement { + /** + * @return True only if node is a non-synthetic statement. Different from isIStatement(). + */ + boolean isStatement(); + + /** + * @return Secondary node type, i.e. VARIABLE in DEFINE VARIABLE statement. Can be null + */ + @Nullable + ABLNodeType getNodeType2(); + + /** + * @return Statement immediately before this one in the code flow. Null if first statement of block. + */ + @Nullable + IStatement getPreviousStatement(); + + /** + * @return Statement immediately following this one in the code flow + */ + @Nullable + IStatement getNextStatement(); + + /** + * @return Block this statement belongs to. Null when called on ProgramRootNode + */ + @Nullable + IStatementBlock getParentStatement(); + + /** + * @return Annotation list of current statement + */ + List getAnnotations(); + + void setPreviousStatement(IStatement statement); + + void setNextStatement(IStatement statement); + + void setParentStatement(IStatementBlock statement); + + void addAnnotation(String annotation); + + JPNode asJPNode(); +} diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatementBlock.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatementBlock.java new file mode 100644 index 000000000..cdb113dcc --- /dev/null +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatementBlock.java @@ -0,0 +1,39 @@ +/******************************************************************************** + * Copyright (c) 2015-2021 Riverside Software + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 + * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt + * + * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 + ********************************************************************************/ +package org.prorefactor.core.nodetypes; + +import javax.annotation.Nullable; + +import org.prorefactor.core.JPNode; + +public interface IStatementBlock { + /** + * @return First child of a block statement + */ + @Nullable + IStatement getFirstStatement(); + + /** + * @return Block this statement belongs to. Null when called on ProgramRootNode. + */ + @Nullable + IStatementBlock getParentStatement(); + + void setFirstStatement(IStatement statement); + + void setParentStatement(IStatementBlock statement); + + JPNode asJPNode(); +} diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java index cae2e4a87..726d945a4 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java @@ -22,29 +22,29 @@ /** * Specialized type of JPNode for IF statement */ -public class IfNode extends JPNode { - private JPNode ifStatement; - private JPNode elseStatement; +public class IfNode extends StatementBlockNode { + private IStatementBlock thenNode; + private IStatementBlock elseNode; public IfNode(ProToken t, JPNode parent, int num, boolean hasChildren) { - super(t, parent, num, hasChildren); + super(t, parent, num, hasChildren, null); } - public void setIfStatement(JPNode ifStatement) { - this.ifStatement = ifStatement; + public void setThenNode(IStatementBlock statement) { + this.thenNode = statement; } - public JPNode getIfStatement() { - return ifStatement; + public IStatementBlock getThenNode() { + return thenNode; } - public void setElseStatement(JPNode elseStatement) { - this.elseStatement = elseStatement; + public void setElseNode(IStatementBlock statement) { + this.elseNode = statement; } @Nullable - public JPNode getElseStatement() { - return elseStatement; + public IStatementBlock getElseNode() { + return elseNode; } } diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/NonStatementBlockNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/NonStatementBlockNode.java new file mode 100644 index 000000000..8ea7d2ee5 --- /dev/null +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/NonStatementBlockNode.java @@ -0,0 +1,78 @@ +/******************************************************************************** + * Copyright (c) 2015-2021 Riverside Software + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 + * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt + * + * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 + ********************************************************************************/ +package org.prorefactor.core.nodetypes; + +import org.prorefactor.core.JPNode; +import org.prorefactor.core.ProToken; +import org.prorefactor.treeparser.Block; + +/** + * Specialized type of JPNode for those token types: PROPERTY_GETTER, PROPERTY_SETTER, THEN, ELSE + */ +public class NonStatementBlockNode extends JPNode implements IStatementBlock { + private Block block; + private IStatement firstStatement; + private IStatementBlock parentStatement; + + public NonStatementBlockNode(ProToken t, JPNode parent, int num, boolean hasChildren) { + super(t, parent, num, hasChildren); + } + + @Override + public void setFirstStatement(IStatement firstStatement) { + this.firstStatement = firstStatement; + } + + @Override + public IStatement getFirstStatement() { + return firstStatement; + } + + @Override + public IStatementBlock getParentStatement() { + return parentStatement; + } + + @Override + public void setParentStatement(IStatementBlock statement) { + this.parentStatement = statement; + } + + @Override + public Block getBlock() { + return block; + } + + @Override + public void setBlock(Block block) { + this.block = block; + } + + @Override + public JPNode asJPNode() { + return this; + } + + @Override + public boolean isIStatementBlock() { + return true; + } + + @Override + public IStatementBlock asIStatementBlock() { + return this; + } + +} diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/ProgramRootNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/ProgramRootNode.java index 3d6510a43..cec6b2e9a 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/ProgramRootNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/ProgramRootNode.java @@ -20,7 +20,7 @@ import org.prorefactor.proparse.support.ParserSupport; import org.prorefactor.treeparser.ParseUnit; -public class ProgramRootNode extends BlockNode { +public class ProgramRootNode extends NonStatementBlockNode { private final ParseUnit unit; public ProgramRootNode(ProToken t, JPNode parent, int num, boolean hasChildren, ParseUnit unit) { @@ -40,5 +40,5 @@ public ParseUnit getParseUnit() { public ParserSupport getParserSupport() { return unit.getSupport(); } - + } diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/RecordNameNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/RecordNameNode.java index a6bf12575..9ec456ab7 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/RecordNameNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/RecordNameNode.java @@ -28,6 +28,8 @@ public class RecordNameNode extends JPNode { private boolean wholeIndex; private String searchIndexName = ""; private ContextQualifier qualifier; + private int storeType; + private boolean abbrev; public RecordNameNode(ProToken t, JPNode parent, int num, boolean hasChildren) { super(t, parent, num, hasChildren); @@ -67,6 +69,23 @@ public void setSearchIndexName(String indexName) { this.searchIndexName = indexName; } + public int getStoreType() { + return storeType; + } + + public void setStoreType(int storeType) { + this.storeType = storeType; + } + + public void setAbbrev(boolean abbrev) { + this.abbrev = abbrev; + } + + @Override + public boolean isAbbreviated() { + return abbrev; + } + @Override public void setTableBuffer(TableBuffer buffer) { setSymbol(buffer); diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementBlockNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementBlockNode.java new file mode 100644 index 000000000..e2154eb8a --- /dev/null +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementBlockNode.java @@ -0,0 +1,73 @@ +/******************************************************************************** + * Copyright (c) 2015-2021 Riverside Software + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 + * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt + * + * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 + ********************************************************************************/ +package org.prorefactor.core.nodetypes; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.prorefactor.core.ABLNodeType; +import org.prorefactor.core.JPNode; +import org.prorefactor.core.ProToken; +import org.prorefactor.treeparser.Block; + +/** + * Specialized type of JPNode for those token types: DO, FOR, REPEAT, FUNCTION, PROCEDURE, CONSTRUCTOR, DESTRUCTOR, + * METHOD, CATCH, ON + */ +public class StatementBlockNode extends StatementNode implements IStatementBlock { + private Block block; + private IStatement firstStatement; + + public StatementBlockNode(ProToken t, JPNode parent, int num, boolean hasChildren, ABLNodeType state2) { + super(t, parent, num, hasChildren, state2); + } + + @Override + public IStatement getFirstStatement() { + return firstStatement; + } + + @Override + public void setFirstStatement(IStatement firstStatement) { + this.firstStatement = firstStatement; + } + + @Nullable + @Override + public Block getBlock() { + return block; + } + + @Override + public void setBlock(@Nonnull Block block) { + this.block = block; + } + + @Override + public boolean hasBlock() { + return block != null; + } + + @Override + public boolean isIStatementBlock() { + return true; + } + + @Override + public IStatementBlock asIStatementBlock() { + return this; + } + +} diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java new file mode 100644 index 000000000..ed1499900 --- /dev/null +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java @@ -0,0 +1,113 @@ +/******************************************************************************** + * Copyright (c) 2015-2021 Riverside Software + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 + * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt + * + * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 + ********************************************************************************/ +package org.prorefactor.core.nodetypes; + +import java.util.ArrayList; +import java.util.List; + +import org.prorefactor.core.ABLNodeType; +import org.prorefactor.core.JPNode; +import org.prorefactor.core.ProToken; + +public class StatementNode extends JPNode implements IStatement { + private IStatement previousStatement; + private IStatement nextStatement; + private IStatementBlock parentStatement; + private List annotations; + private ABLNodeType state2; + + public StatementNode(ProToken t, JPNode parent, int num, boolean hasChildren, ABLNodeType state2) { + super(t, parent, num, hasChildren); + this.state2 = state2; + } + + @Override + public IStatement getPreviousStatement() { + return previousStatement; + } + + @Override + public IStatement getNextStatement() { + return nextStatement; + } + + @Override + public IStatementBlock getParentStatement() { + return parentStatement; + } + + @Override + public ABLNodeType getNodeType2() { + return state2; + } + + @Override + public boolean isStatement() { + return true; + } + + @Override + public boolean isIStatement() { + return true; + } + + @Override + public JPNode asJPNode() { + return this; + } + + @Override + public IStatement asIStatement() { + return this; + } + + @Override + public void setPreviousStatement(IStatement statement) { + this.previousStatement = statement; + } + + @Override + public void setNextStatement(IStatement statement) { + this.nextStatement = statement; + } + + @Override + public void setParentStatement(IStatementBlock statement) { + this.parentStatement = statement; + } + + @Override + public List getAnnotations() { + return annotations; + } + + @Override + public void addAnnotation(String annotation) { + if (annotations == null) + annotations = new ArrayList<>(); + annotations.add(annotation); + } + + @Override + public boolean hasAnnotation(String str) { + if ((annotations != null) && annotations.contains(str)) + return true; + else if (parentStatement != null) + return parentStatement.asJPNode().hasAnnotation(str); + else + return false; + } + +} diff --git a/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java b/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java index 9553f670a..745becf1a 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java +++ b/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java @@ -814,7 +814,7 @@ public Builder visitCaseEnd(CaseEndContext ctx) { @Override public Builder visitCatchStatement(CatchStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -1011,7 +1011,7 @@ public Builder visitConnectStatement(ConnectStatementContext ctx) { @Override public Builder visitConstructorStatement(ConstructorStatementContext ctx) { - Builder holder = createStatementTreeFromFirstNode(ctx); + Builder holder = createStatementTreeFromFirstNode(ctx).setBlock(true); Builder typeName = holder.getDown(); if (typeName.getNodeType() != ABLNodeType.TYPE_NAME) typeName = typeName.getRight(); @@ -1269,12 +1269,12 @@ public Builder visitDefinePropertyStatement(DefinePropertyStatementContext ctx) @Override public Builder visitDefinePropertyAccessorGetBlock(DefinePropertyAccessorGetBlockContext ctx) { - return createTree(ctx, ABLNodeType.PROPERTY_GETTER).setRuleNode(ctx); + return createTree(ctx, ABLNodeType.PROPERTY_GETTER).setRuleNode(ctx).setBlock(true); } @Override public Builder visitDefinePropertyAccessorSetBlock(DefinePropertyAccessorSetBlockContext ctx) { - return createTree(ctx, ABLNodeType.PROPERTY_SETTER).setRuleNode(ctx); + return createTree(ctx, ABLNodeType.PROPERTY_SETTER).setRuleNode(ctx).setBlock(true); } @Override @@ -1499,7 +1499,7 @@ public Builder visitDelimiterConstant(DelimiterConstantContext ctx) { @Override public Builder visitDestructorStatement(DestructorStatementContext ctx) { - Builder holder = createStatementTreeFromFirstNode(ctx); + Builder holder = createStatementTreeFromFirstNode(ctx).setBlock(true); Builder typeName = holder.getDown(); if (typeName.getNodeType() != ABLNodeType.TYPE_NAME) typeName = typeName.getRight(); @@ -1552,7 +1552,7 @@ public Builder visitDisplayWith(DisplayWithContext ctx) { @Override public Builder visitDoStatement(DoStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -1685,7 +1685,7 @@ public Builder visitFontExpression(FontExpressionContext ctx) { @Override public Builder visitForStatement(ForStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -1766,12 +1766,12 @@ public Builder visitFromPos(FromPosContext ctx) { @Override public Builder visitFunctionStatement(FunctionStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override public Builder visitExternalFunctionStatement(ExternalFunctionStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -1852,9 +1852,14 @@ public Builder visitIfStatement(IfStatementContext ctx) { return createStatementTreeFromFirstNode(ctx); } + @Override + public Builder visitIfThen(IfThenContext ctx) { + return createTreeFromFirstNode(ctx).setBlock(true); + } + @Override public Builder visitIfElse(IfElseContext ctx) { - return createTreeFromFirstNode(ctx); + return createTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -2036,7 +2041,7 @@ public Builder visitMessageOption(MessageOptionContext ctx) { @Override public Builder visitMethodStatement(MethodStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -2082,7 +2087,7 @@ public Builder visitNullPhrase(NullPhraseContext ctx) { @Override public Builder visitOnStatement(OnStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -2196,14 +2201,14 @@ public Builder visitProcedureExpression(ProcedureExpressionContext ctx) { @Override public Builder visitProcedureStatement(ProcedureStatementContext ctx) { - Builder holder = createStatementTreeFromFirstNode(ctx); + Builder holder = createStatementTreeFromFirstNode(ctx).setBlock(true); holder.getDown().changeType(ABLNodeType.ID); return holder; } @Override public Builder visitExternalProcedureStatement(ExternalProcedureStatementContext ctx) { - Builder holder = createStatementTreeFromFirstNode(ctx); + Builder holder = createStatementTreeFromFirstNode(ctx).setBlock(true); holder.getDown().changeType(ABLNodeType.ID); holder.getDown().getRight().moveRightToDown(); @@ -2327,7 +2332,7 @@ public Builder visitReadkeyStatement(ReadkeyStatementContext ctx) { @Override public Builder visitRepeatStatement(RepeatStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -2538,7 +2543,8 @@ public Builder visitStopStatement(StopStatementContext ctx) { @Override public Builder visitSuperStatement(SuperStatementContext ctx) { - return createTree(ctx, ABLNodeType.METHOD_REF).setStatement().setExpression(true).setRuleNode(ctx); + Builder builder = createTree(ctx, ABLNodeType.METHOD_REF).setExpression(true); + return new Builder(ABLNodeType.EXPR_STATEMENT).setStatement().setDown(builder).setRuleNode(ctx); } @Override @@ -2648,7 +2654,8 @@ public Builder visitTextPhrase(TextPhraseContext ctx) { @Override public Builder visitThisObjectStatement(ThisObjectStatementContext ctx) { - return createTree(ctx, ABLNodeType.METHOD_REF).setStatement().setExpression(true).setRuleNode(ctx); + Builder builder = createTree(ctx, ABLNodeType.METHOD_REF).setExpression(true); + return new Builder(ABLNodeType.EXPR_STATEMENT).setStatement().setDown(builder).setRuleNode(ctx); } @Override @@ -2698,7 +2705,7 @@ public Builder visitTriggerBlock(TriggerBlockContext ctx) { @Override public Builder visitTriggerOn(TriggerOnContext ctx) { - return createTreeFromFirstNode(ctx).setRuleNode(ctx); + return createTreeFromFirstNode(ctx).setRuleNode(ctx).setBlock(true); } @Override diff --git a/proparse/src/main/java/org/prorefactor/proparse/support/JPNodeLister.java b/proparse/src/main/java/org/prorefactor/proparse/support/JPNodeLister.java index 1d4ea5184..f0a11809e 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/support/JPNodeLister.java +++ b/proparse/src/main/java/org/prorefactor/proparse/support/JPNodeLister.java @@ -18,7 +18,10 @@ import java.io.PrintWriter; import java.util.Arrays; +import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.JPNode; +import org.prorefactor.core.nodetypes.FieldRefNode; +import org.prorefactor.core.nodetypes.RecordNameNode; /** * Prints out the structure of a JPNode AST. Prints nodes one per line, using indentation to show the tree structure. @@ -86,8 +89,10 @@ private void printline(JPNode node, int level, char spacer, boolean showLine, bo if (showFileName) ofile.append(Integer.toString(node.getFileIndex())).append(spacer); if (showStore) { - if (node.getStoreType() != 0) - ofile.append(Integer.toString(node.getStoreType())).append(spacer); + if ((node.getNodeType() == ABLNodeType.FIELD_REF) && ((FieldRefNode) node).getStoreType() != 0) + ofile.append(Integer.toString(((FieldRefNode) node).getStoreType())).append(spacer); + if ((node.getNodeType() == ABLNodeType.RECORD_NAME) && ((RecordNameNode) node).getStoreType() != 0) + ofile.append(Integer.toString(((RecordNameNode) node).getStoreType())).append(spacer); } ofile.append(getExtraInfo(node, spacer)); ofile.println(); diff --git a/proparse/src/main/java/org/prorefactor/proparse/support/TreeNodeLister.java b/proparse/src/main/java/org/prorefactor/proparse/support/TreeNodeLister.java index c15f18cb8..d48365247 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/support/TreeNodeLister.java +++ b/proparse/src/main/java/org/prorefactor/proparse/support/TreeNodeLister.java @@ -20,8 +20,9 @@ import java.util.Set; import org.prorefactor.core.ABLNodeType; -import org.prorefactor.core.IConstants; import org.prorefactor.core.JPNode; +import org.prorefactor.core.nodetypes.FieldRefNode; +import org.prorefactor.core.nodetypes.RecordNameNode; import org.prorefactor.core.nodetypes.TypeNameNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -85,13 +86,17 @@ private void printAttributes(JPNode node, int tabs) throws IOException { if (node.getNodeType() == ABLNodeType.EOF_ANTLR4) return; ofile.write(String.format("%3s %s", tabs, java.nio.CharBuffer.allocate(tabs).toString().replace('\0', ' '))); - ofile.write(node.getNodeType() + (node.isStateHead() ? "^ " : " ") + (node.isStateHead() && node.getState2() != 0 ? node.getState2() : "")); + ofile.write(node.getNodeType() + (node.isStateHead() ? "^ " : " ")); + if (node.isIStatement() && node.asIStatement().getNodeType2() != null) + ofile.write(node.asIStatement().getNodeType2().toString()); if (node.isOperator()) ofile.write("*OP* "); - if (node.isInlineVar()) + if ((node.getNodeType() == ABLNodeType.FIELD_REF) && ((FieldRefNode) node).isInlineVar()) ofile.write("*IN* "); - if (node.getStoreType() > 0) - ofile.write("StoreType " + node.getStoreType() + " "); + if ((node.getNodeType() == ABLNodeType.FIELD_REF) && ((FieldRefNode) node).getStoreType() != 0) + ofile.write("StoreType " + ((FieldRefNode) node).getStoreType()); + if ((node.getNodeType() == ABLNodeType.RECORD_NAME) && ((RecordNameNode) node).getStoreType() != 0) + ofile.write("StoreType " + ((RecordNameNode) node).getStoreType()); if ((node.getNodeType() == ABLNodeType.ID) || (node.getNodeType() == ABLNodeType.TYPE_NAME)) { ofile.write("["); ofile.write(node.getText().replace('\'', ' ').replace('"', ' ')); diff --git a/proparse/src/main/java/org/prorefactor/treeparser/FrameStack.java b/proparse/src/main/java/org/prorefactor/treeparser/FrameStack.java index 75ce4834f..04ea7fdf3 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/FrameStack.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/FrameStack.java @@ -211,7 +211,7 @@ FieldLookupResult inputFieldLookup(FieldRefNode fieldRefNode, TreeParserSymbolSc tempType = tempNode.getType(); } if (tempType == Proparse.BROWSE || tempType == Proparse.FRAME) { - fieldContainer = (FieldContainer) tempNode.nextNode().getSymbol(); + fieldContainer = (FieldContainer) tempNode.getNextNode().getSymbol(); fieldOrVariable = fieldContainer.lookupFieldOrVar(inputName); } else { for (Frame frame : frameMRU) { @@ -258,7 +258,7 @@ void nodeOfBlock(JPNode blockNode, Block currentBlock) { return; // No such thing as DO WITH BROWSE... assert containerTypeNode.getType() == Proparse.FRAME; - JPNode frameIDNode = containerTypeNode.nextNode(); + JPNode frameIDNode = containerTypeNode.getNextNode(); assert frameIDNode.getType() == Proparse.ID; Frame frame = frameRefSet(frameIDNode, currentBlock.getSymbolScope()); frame.setFrameScopeBlockExplicitDefault(blockNode.getBlock()); @@ -303,7 +303,7 @@ void nodeOfInitializingStatement(ParseTree stateNode2, JPNode stateNode, Block c JPNode containerTypeNode = getContainerTypeNode(stateNode); JPNode idNode = null; if (containerTypeNode != null) { - idNode = containerTypeNode.nextNode(); + idNode = containerTypeNode.getNextNode(); assert idNode.getType() == Proparse.ID; } if (containerTypeNode != null && containerTypeNode.getType() == Proparse.BROWSE) { @@ -327,7 +327,7 @@ void nodeOfInitializingStatement(ParseTree stateNode2, JPNode stateNode, Block c void simpleFrameInitStatement(ParseTree headNode2, JPNode headNode, JPNode frameIDNode, Block currentBlock) { LOG.trace("Enter FrameStack#simpleFrameInitStatement"); - Frame frame = (Frame) frameIDNode.nextNode().getSymbol(); + Frame frame = (Frame) frameIDNode.getNextNode().getSymbol(); assert frame != null; initializeFrame(frame, currentBlock); headNode.setFieldContainer(frame); diff --git a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java index 4eeb79124..e7a214642 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java @@ -25,8 +25,10 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.JPNode; -import org.prorefactor.core.nodetypes.BlockNode; +import org.prorefactor.core.nodetypes.IStatement; +import org.prorefactor.core.nodetypes.IStatementBlock; import org.prorefactor.core.nodetypes.IfNode; +import org.prorefactor.core.nodetypes.ProgramRootNode; import org.prorefactor.proparse.antlr4.Proparse; import org.prorefactor.proparse.antlr4.Proparse.CanFindFunctionContext; import org.prorefactor.proparse.antlr4.Proparse.CatchStatementContext; @@ -72,7 +74,7 @@ public class TreeParserBlocks extends ProparseBaseListener { private final TreeParserRootSymbolScope rootScope; private Routine rootRoutine; - private JPNode lastStatement; + private IStatement lastStatement; private int currentLevel; private boolean inIfStmt; private boolean inElseStmt; @@ -422,12 +424,16 @@ private Block pushBlock(Block block) { private Block popBlock() { if (LOG.isTraceEnabled()) LOG.trace("{}> Popping block from stack", indent()); + Block bb = blockStack.remove(blockStack.size() - 1); - lastStatement = bb.getNode(); - if (lastStatement.getParent().getNodeType() == ABLNodeType.IF) { - lastStatement = lastStatement.getParent(); - } else if (lastStatement.getParent().getNodeType() == ABLNodeType.ELSE) { - lastStatement = lastStatement.getParent().getParent(); + lastStatement = bb.getNode().asIStatement(); + + if (lastStatement != null) { + if (lastStatement.asJPNode().getParent().getNodeType() == ABLNodeType.THEN) { + lastStatement = lastStatement.getParentStatement().getParentStatement().asJPNode().asIStatement(); + } else if (lastStatement.asJPNode().getParent().getNodeType() == ABLNodeType.ELSE) { + lastStatement = lastStatement.asJPNode().getParent().getParent().asIStatement(); + } } return blockStack.get(blockStack.size() - 1); } @@ -491,8 +497,8 @@ public void enterEveryRule(ParserRuleContext ctx) { LOG.trace("{}> {}", indent(), Proparse.ruleNames[ctx.getRuleIndex()]); JPNode node = support.getNode(ctx); - if ((node != null) && node.isStateHead()) { - enterNewStatement(node); + if ((node != null) && node.isStatement() && !(node instanceof ProgramRootNode)) { + enterNewStatement(node.asIStatement()); } } @@ -506,12 +512,18 @@ private String indent() { } // Attach current statement to the previous one - private void enterNewStatement(@Nonnull JPNode node) { - if (inIfStmt && (node != lastStatement) && (lastStatement instanceof IfNode)) { - ((IfNode) lastStatement).setIfStatement(node); + private void enterNewStatement(@Nonnull IStatement node) { + if ((inIfStmt || inElseStmt) && (node != lastStatement) && (lastStatement instanceof IfNode)) { + IfNode ifNode = (IfNode) lastStatement; + IStatementBlock thenElseNode = node.asJPNode().getParent().asIStatementBlock(); + if (inIfStmt) + ifNode.setThenNode(thenElseNode); + else + ifNode.setElseNode(thenElseNode); + node.setParentStatement(thenElseNode); + thenElseNode.setFirstStatement(node); + thenElseNode.setParentStatement(ifNode); inIfStmt = false; - } else if (inElseStmt && (node != lastStatement) && (lastStatement instanceof IfNode)) { - ((IfNode) lastStatement).setElseStatement(node); inElseStmt = false; } else { if ((lastStatement != null) && (node != lastStatement)) { @@ -519,16 +531,17 @@ private void enterNewStatement(@Nonnull JPNode node) { node.setPreviousStatement(lastStatement); } lastStatement = node; + node.setParentStatement(currentBlock.getNode().asIStatementBlock()); } - node.setInBlock(currentBlock); - if (((BlockNode) currentBlock.getNode()).getFirstStatement() == null) - ((BlockNode) currentBlock.getNode()).setFirstStatement(node); + if (currentBlock.getNode().asIStatementBlock().getFirstStatement() == null) { + currentBlock.getNode().asIStatementBlock().setFirstStatement(node); + } // Assign annotations to statement - JPNode prev = node.getPreviousStatement(); - while ((prev != null) && (prev.getNodeType() == ABLNodeType.ANNOTATION)) { - node.addAnnotation(prev.getText()); + IStatement prev = node.getPreviousStatement(); + while ((prev != null) && (prev.asJPNode().getNodeType() == ABLNodeType.ANNOTATION)) { + node.addAnnotation(prev.asJPNode().getText()); prev = prev.getPreviousStatement(); } } diff --git a/proparse/src/test/java/org/prorefactor/core/BugFixTest.java b/proparse/src/test/java/org/prorefactor/core/BugFixTest.java index 63e64c047..8363737d1 100644 --- a/proparse/src/test/java/org/prorefactor/core/BugFixTest.java +++ b/proparse/src/test/java/org/prorefactor/core/BugFixTest.java @@ -450,17 +450,17 @@ public void testCreateComObject() { List list = unit.getTopNode().query(ABLNodeType.CREATE); // COM automation assertEquals(list.get(0).getLine(), 3); - assertEquals(list.get(0).getNodeType2(), ABLNodeType.AUTOMATION_OBJECT); + assertEquals(list.get(0).asIStatement().getNodeType2(), ABLNodeType.AUTOMATION_OBJECT); assertEquals(list.get(1).getLine(), 4); - assertEquals(list.get(1).getNodeType2(), ABLNodeType.AUTOMATION_OBJECT); + assertEquals(list.get(1).asIStatement().getNodeType2(), ABLNodeType.AUTOMATION_OBJECT); // Widgets assertEquals(list.get(2).getLine(), 8); - assertEquals(list.get(2).getNodeType2(), ABLNodeType.WIDGET); + assertEquals(list.get(2).asIStatement().getNodeType2(), ABLNodeType.WIDGET); assertEquals(list.get(3).getLine(), 12); - assertEquals(list.get(3).getNodeType2(), ABLNodeType.WIDGET); + assertEquals(list.get(3).asIStatement().getNodeType2(), ABLNodeType.WIDGET); // Ambiguous assertEquals(list.get(4).getLine(), 15); - assertEquals(list.get(4).getNodeType2(), ABLNodeType.WIDGET); + assertEquals(list.get(4).asIStatement().getNodeType2(), ABLNodeType.WIDGET); } @Test diff --git a/proparse/src/test/java/org/prorefactor/core/ClassesTest.java b/proparse/src/test/java/org/prorefactor/core/ClassesTest.java index dd6df7f22..50f93434e 100644 --- a/proparse/src/test/java/org/prorefactor/core/ClassesTest.java +++ b/proparse/src/test/java/org/prorefactor/core/ClassesTest.java @@ -56,12 +56,12 @@ public void test01() { assertTrue(unit.getTopNode().query(ABLNodeType.ANNOTATION).size() == 1); assertEquals(unit.getTopNode().query(ABLNodeType.ANNOTATION).get(0).getAnnotationName(), "Progress.Lang.Deprecated"); - JPNode method = unit.getTopNode().query(ABLNodeType.ANNOTATION).get(0).getNextStatement(); + JPNode method = unit.getTopNode().query(ABLNodeType.ANNOTATION).get(0).asIStatement().getNextStatement().asJPNode(); assertNotNull(method); assertEquals(method.getNodeType(), ABLNodeType.METHOD); - assertNotNull(method.getAnnotations()); - assertEquals(method.getAnnotations().size(), 1); - assertEquals(method.getAnnotations().get(0), "@Progress.Lang.Deprecated"); + assertNotNull(method.asIStatement().getAnnotations()); + assertEquals(method.asIStatement().getAnnotations().size(), 1); + assertEquals(method.asIStatement().getAnnotations().get(0), "@Progress.Lang.Deprecated"); assertTrue(method.hasAnnotation("@Progress.Lang.Deprecated")); assertFalse(method.hasAnnotation("@Progress.Deprecated")); JPNode inMethodStmt = method.getFirstDirectChild(ABLNodeType.CODE_BLOCK).queryStateHead(ABLNodeType.RETURN).get(0); diff --git a/proparse/src/test/java/org/prorefactor/core/ParserTest.java b/proparse/src/test/java/org/prorefactor/core/ParserTest.java index 9da13f69d..fa3560bea 100644 --- a/proparse/src/test/java/org/prorefactor/core/ParserTest.java +++ b/proparse/src/test/java/org/prorefactor/core/ParserTest.java @@ -377,7 +377,7 @@ public void testCreateWidgetPool() { assertFalse(unit.hasSyntaxError()); assertNull(session.getSchema().lookupTable("widget-pool")); assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.CREATE).size(), 1); - assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.CREATE).get(0).getState2(), ABLNodeType.WIDGETPOOL.getType()); + assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.CREATE).get(0).asIStatement().getNodeType2(), ABLNodeType.WIDGETPOOL); assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.MESSAGE).size(), 1); // widget-pool table available, statement is still about creating a widget-pool @@ -389,7 +389,7 @@ public void testCreateWidgetPool() { ParseUnit unit2 = new ParseUnit(new ByteArrayInputStream("create widget-pool. message 'hello'.".getBytes()), "", session2); unit2.treeParser01(); assertEquals(unit2.getTopNode().queryStateHead(ABLNodeType.CREATE).size(), 1); - assertEquals(unit2.getTopNode().queryStateHead(ABLNodeType.CREATE).get(0).getState2(), ABLNodeType.WIDGETPOOL.getType()); + assertEquals(unit2.getTopNode().queryStateHead(ABLNodeType.CREATE).get(0).asIStatement().getNodeType2(), ABLNodeType.WIDGETPOOL); assertEquals(unit2.getTopNode().queryStateHead(ABLNodeType.MESSAGE).size(), 1); } @@ -409,8 +409,8 @@ public void testExpression01() { unit.treeParser01(); assertFalse(unit.hasSyntaxError()); assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).size(), 2); - assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(0).getState2(), ABLNodeType.IMAGE.getType()); - assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(1).getState2(), ABLNodeType.FRAME.getType()); + assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(0).asIStatement().getNodeType2(), ABLNodeType.IMAGE); + assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(1).asIStatement().getNodeType2(), ABLNodeType.FRAME); assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.EXPR_STATEMENT).size(), 1); assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.EXPR_STATEMENT).get(0).query(ABLNodeType.FRAME).size(), 1); @@ -424,13 +424,13 @@ public void testExpression02() { unit.treeParser01(); assertFalse(unit.hasSyntaxError()); assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).size(), 3); - assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(0).getState2(), - ABLNodeType.VARIABLE.getType()); - assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(1).getState2(), - ABLNodeType.VARIABLE.getType()); - assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(2).getState2(), ABLNodeType.FRAME.getType()); + assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(0).asIStatement().getNodeType2(), + ABLNodeType.VARIABLE); + assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(1).asIStatement().getNodeType2(), + ABLNodeType.VARIABLE); + assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).get(2).asIStatement().getNodeType2(), ABLNodeType.FRAME); assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.CREATE).size(), 1); - assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.CREATE).get(0).getState2(), ABLNodeType.WIDGET.getType()); + assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.CREATE).get(0).asIStatement().getNodeType2(), ABLNodeType.WIDGET); assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.EXPR_STATEMENT).size(), 1); } diff --git a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java index d69013629..ccfa40eb2 100644 --- a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java +++ b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java @@ -96,12 +96,12 @@ public void test03() { boolean found1 = false; boolean found2 = false; for (JPNode node : unit.getTopNode().query(ABLNodeType.DEFINE)) { - if ((node.getState2() == ABLNodeType.TEMPTABLE.getType()) + if ((node.asIStatement().getNodeType2() == ABLNodeType.TEMPTABLE) && "myTT2".equals(node.getNextNode().getNextNode().getText())) { assertTrue(node.query(ABLNodeType.USEINDEX).get(0).getNextNode().isInvalidUseIndex()); found1 = true; } - if ((node.getState2() == ABLNodeType.TEMPTABLE.getType()) + if ((node.asIStatement().getNodeType2() == ABLNodeType.TEMPTABLE) && "myTT3".equals(node.getNextNode().getNextNode().getText())) { assertFalse(node.query(ABLNodeType.USEINDEX).get(0).getNextNode().isInvalidUseIndex()); found2 = true; @@ -488,7 +488,7 @@ public void test21() { unit.treeParser01(); assertFalse(unit.hasSyntaxError()); JPNode node = unit.getTopNode().findDirectChild(ABLNodeType.DEFINE); - assertEquals(node.getState2(), ABLNodeType.VARIABLE.getType()); + assertEquals(node.asIStatement().getNodeType2(), ABLNodeType.VARIABLE); } @Test @@ -1294,10 +1294,10 @@ public void testSuper02() throws JAXBException, IOException { assertEquals(list.size(), 3); assertEquals(list.get(0).getParent().getNodeType(), ABLNodeType.METHOD_REF); assertTrue(list.get(0).getParent().isIExpression()); - assertTrue(list.get(0).getParent().isStateHead()); + assertTrue(list.get(0).getParent().getParent().isStateHead()); assertEquals(list.get(1).getParent().getNodeType(), ABLNodeType.METHOD_REF); assertTrue(list.get(1).getParent().isIExpression()); - assertTrue(list.get(1).getParent().isStateHead()); + assertTrue(list.get(1).getParent().getParent().isStateHead()); assertEquals(list.get(2).getParent().getNodeType(), ABLNodeType.SYSTEM_HANDLE_REF); assertTrue(list.get(2).getParent().isIExpression()); assertEquals(list.get(2).getParent().getParent().getNodeType(), ABLNodeType.METHOD_REF); @@ -1317,10 +1317,10 @@ public void testThisObject01() throws JAXBException, IOException { assertEquals(list.size(), 3); assertEquals(list.get(0).getParent().getNodeType(), ABLNodeType.METHOD_REF); assertTrue(list.get(0).getParent().isIExpression()); - assertTrue(list.get(0).getParent().isStateHead()); + assertTrue(list.get(0).getParent().getParent().isStateHead()); assertEquals(list.get(1).getParent().getNodeType(), ABLNodeType.METHOD_REF); assertTrue(list.get(1).getParent().isIExpression()); - assertTrue(list.get(1).getParent().isStateHead()); + assertTrue(list.get(1).getParent().getParent().isStateHead()); assertEquals(list.get(2).getParent().getNodeType(), ABLNodeType.SYSTEM_HANDLE_REF); assertTrue(list.get(2).getParent().isIExpression()); assertEquals(list.get(2).getParent().getParent().getNodeType(), ABLNodeType.METHOD_REF); diff --git a/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java b/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java index eb2191273..c9a6c85b0 100644 --- a/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java +++ b/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java @@ -23,8 +23,9 @@ import java.io.File; -import org.prorefactor.core.nodetypes.BlockNode; +import org.prorefactor.core.nodetypes.IStatement; import org.prorefactor.core.nodetypes.IfNode; +import org.prorefactor.core.nodetypes.StatementBlockNode; import org.prorefactor.core.util.UnitTestModule; import org.prorefactor.refactor.RefactorSession; import org.prorefactor.treeparser.ParseUnit; @@ -52,74 +53,83 @@ public void test01() { assertNotNull(unit.getTopNode()); assertNotNull(unit.getRootScope()); - JPNode currStmt = unit.getTopNode().getFirstStatement(); + IStatement currStmt = unit.getTopNode().getFirstStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.DEFINE); - assertEquals(currStmt.getLine(), 1); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.DEFINE); + assertEquals(currStmt.asJPNode().getLine(), 1); + assertEquals(currStmt.getParentStatement(), unit.getTopNode()); assertNull(currStmt.getPreviousStatement()); assertNotNull(currStmt.getNextStatement()); - JPNode prevStmt = currStmt; + IStatement prevStmt = currStmt; currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.DEFINE); - assertEquals(currStmt.getLine(), 2); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.DEFINE); + assertEquals(currStmt.asJPNode().getLine(), 2); + assertEquals(currStmt.getParentStatement(), unit.getTopNode()); assertEquals(currStmt.getPreviousStatement(), prevStmt); assertNotNull(currStmt.getNextStatement()); prevStmt = currStmt; currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.DEFINE); - assertEquals(currStmt.getLine(), 3); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.DEFINE); + assertEquals(currStmt.asJPNode().getLine(), 3); + assertEquals(currStmt.getParentStatement(), unit.getTopNode()); assertEquals(currStmt.getPreviousStatement(), prevStmt); assertNotNull(currStmt.getNextStatement()); prevStmt = currStmt; currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.MESSAGE); - assertEquals(currStmt.getLine(), 5); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.MESSAGE); + assertEquals(currStmt.asJPNode().getLine(), 5); + assertEquals(currStmt.getParentStatement(), unit.getTopNode()); assertEquals(currStmt.getPreviousStatement(), prevStmt); assertNotNull(currStmt.getNextStatement()); prevStmt = currStmt; currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.MESSAGE); - assertEquals(currStmt.getLine(), 6); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.MESSAGE); + assertEquals(currStmt.asJPNode().getLine(), 6); + assertEquals(currStmt.getParentStatement(), unit.getTopNode()); assertEquals(currStmt.getPreviousStatement(), prevStmt); assertNotNull(currStmt.getNextStatement()); prevStmt = currStmt; currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.PROCEDURE); - assertEquals(currStmt.getLine(), 8); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.PROCEDURE); + assertEquals(currStmt.asJPNode().getLine(), 8); + assertEquals(currStmt.getParentStatement(), unit.getTopNode()); + assertTrue(currStmt.asJPNode().isIStatementBlock()); assertEquals(currStmt.getPreviousStatement(), prevStmt); assertNotNull(currStmt.getNextStatement()); - assertTrue(currStmt instanceof BlockNode); - JPNode currSubStmt = ((BlockNode) currStmt).getFirstStatement(); + IStatement currSubStmt = currStmt.asJPNode().asIStatementBlock().getFirstStatement(); assertNotNull(currSubStmt); - assertEquals(currSubStmt.getNodeType(), ABLNodeType.DISPLAY); - assertEquals(currSubStmt.getLine(), 9); + assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.DISPLAY); + assertEquals(currSubStmt.asJPNode().getLine(), 9); + assertEquals(currSubStmt.getParentStatement(), currStmt); assertNull(currSubStmt.getPreviousStatement()); assertNotNull(currSubStmt.getNextStatement()); - JPNode prevSubStmt = currSubStmt; + IStatement prevSubStmt = currSubStmt; currSubStmt = currSubStmt.getNextStatement(); assertNotNull(currSubStmt); - assertEquals(currSubStmt.getNodeType(), ABLNodeType.DISPLAY); - assertEquals(currSubStmt.getLine(), 10); + assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.DISPLAY); + assertEquals(currSubStmt.asJPNode().getLine(), 10); + assertEquals(currSubStmt.getParentStatement(), currStmt); assertEquals(currSubStmt.getPreviousStatement(), prevSubStmt); assertNull(currSubStmt.getNextStatement()); prevStmt = currStmt; currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.MESSAGE); - assertEquals(currStmt.getLine(), 13); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.MESSAGE); + assertEquals(currStmt.asJPNode().getLine(), 13); + assertEquals(currStmt.getParentStatement(), unit.getTopNode()); assertEquals(currStmt.getPreviousStatement(), prevStmt); assertNull(currStmt.getNextStatement()); } @@ -133,59 +143,68 @@ public void test02() { assertNotNull(unit.getTopNode()); assertNotNull(unit.getRootScope()); - JPNode stmt1 = unit.getTopNode().getFirstStatement(); + IStatement stmt1 = unit.getTopNode().getFirstStatement(); assertNotNull(stmt1); - assertEquals(stmt1.getNodeType(), ABLNodeType.IF); - assertEquals(stmt1.getLine(), 1); + assertEquals(stmt1.asJPNode().getNodeType(), ABLNodeType.IF); + assertEquals(stmt1.asJPNode().getLine(), 1); + assertEquals(stmt1.getParentStatement(), unit.getTopNode()); + assertEquals(unit.getTopNode().getFirstStatement(), stmt1); assertNull(stmt1.getPreviousStatement()); assertNotNull(stmt1.getNextStatement()); - JPNode stmt2 = stmt1.getNextStatement(); + IStatement stmt2 = stmt1.getNextStatement(); assertNotNull(stmt2); - assertEquals(stmt2.getNodeType(), ABLNodeType.IF); - assertEquals(stmt2.getLine(), 6); + assertEquals(stmt2.asJPNode().getNodeType(), ABLNodeType.IF); + assertEquals(stmt2.asJPNode().getLine(), 6); + assertEquals(stmt2.getParentStatement(), unit.getTopNode()); assertEquals(stmt2.getPreviousStatement(), stmt1); assertNull(stmt2.getNextStatement()); - JPNode currSubStmt = ((IfNode) stmt1).getIfStatement(); + IStatement currSubStmt = ((IfNode) stmt1).getThenNode().getFirstStatement(); assertNotNull(currSubStmt); - assertEquals(currSubStmt.getNodeType(), ABLNodeType.MESSAGE); - assertEquals(currSubStmt.getLine(), 2); + assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.MESSAGE); + assertEquals(currSubStmt.asJPNode().getLine(), 2); + assertEquals(currSubStmt.getParentStatement().getParentStatement(), stmt1); assertNull(currSubStmt.getPreviousStatement()); assertNull(currSubStmt.getNextStatement()); - currSubStmt = ((IfNode) stmt1).getElseStatement(); + currSubStmt = ((IfNode) stmt1).getElseNode().getFirstStatement(); assertNotNull(currSubStmt); - assertEquals(currSubStmt.getNodeType(), ABLNodeType.MESSAGE); - assertEquals(currSubStmt.getLine(), 4); + assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.MESSAGE); + assertEquals(currSubStmt.asJPNode().getLine(), 4); + assertEquals(currSubStmt.getParentStatement().getParentStatement(), stmt1); assertNull(currSubStmt.getPreviousStatement()); assertNull(currSubStmt.getNextStatement()); - currSubStmt = ((IfNode) stmt2).getIfStatement(); + currSubStmt = ((IfNode) stmt2).getThenNode().getFirstStatement(); assertNotNull(currSubStmt); - assertEquals(currSubStmt.getNodeType(), ABLNodeType.DO); - assertEquals(currSubStmt.getLine(), 6); + assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.DO); + assertEquals(currSubStmt.asJPNode().getLine(), 6); + assertEquals(currSubStmt.getParentStatement().getParentStatement(), stmt2); assertNull(currSubStmt.getPreviousStatement()); assertNull(currSubStmt.getNextStatement()); - JPNode currSubStmt2 = ((BlockNode) currSubStmt).getFirstStatement(); + IStatement currSubStmt2 = ((StatementBlockNode) currSubStmt).getFirstStatement(); assertNotNull(currSubStmt2); - assertEquals(currSubStmt2.getNodeType(), ABLNodeType.MESSAGE); - assertEquals(currSubStmt2.getLine(), 7); + assertEquals(currSubStmt2.asJPNode().getNodeType(), ABLNodeType.MESSAGE); + assertEquals(currSubStmt2.asJPNode().getLine(), 7); + assertEquals(currSubStmt2.getParentStatement(), currSubStmt); assertNull(currSubStmt2.getPreviousStatement()); assertNull(currSubStmt2.getNextStatement()); - currSubStmt = ((IfNode) stmt2).getElseStatement(); + currSubStmt = ((IfNode) stmt2).getElseNode().getFirstStatement(); assertNotNull(currSubStmt); - assertEquals(currSubStmt.getNodeType(), ABLNodeType.DO); - assertEquals(currSubStmt.getLine(), 9); + assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.DO); + assertEquals(currSubStmt.asJPNode().getLine(), 9); + assertEquals(currSubStmt.getParentStatement().getParentStatement(), stmt2); assertNull(currSubStmt.getPreviousStatement()); assertNull(currSubStmt.getNextStatement()); - currSubStmt2 = ((BlockNode) currSubStmt).getFirstStatement(); + currSubStmt2 = ((StatementBlockNode) currSubStmt).getFirstStatement(); assertNotNull(currSubStmt2); - assertEquals(currSubStmt2.getNodeType(), ABLNodeType.MESSAGE); - assertEquals(currSubStmt2.getLine(), 10); + assertEquals(currSubStmt2.asJPNode().getNodeType(), ABLNodeType.MESSAGE); + assertEquals(currSubStmt2.asJPNode().getLine(), 10); + assertEquals(currSubStmt2.getParentStatement(), currSubStmt); assertNull(currSubStmt2.getPreviousStatement()); assertNull(currSubStmt2.getNextStatement()); @@ -208,76 +227,76 @@ public void test03() { assertNotNull(unit.getTopNode()); assertNotNull(unit.getRootScope()); - JPNode currStmt = unit.getTopNode().getFirstStatement(); + IStatement currStmt = unit.getTopNode().getFirstStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.DEFINE); - assertEquals(currStmt.getLine(), 1); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.DEFINE); + assertEquals(currStmt.asJPNode().getLine(), 1); assertNull(currStmt.getPreviousStatement()); assertNotNull(currStmt.getNextStatement()); - JPNode prevStmt = currStmt; + IStatement prevStmt = currStmt; currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.PROCEDURE); - assertEquals(currStmt.getLine(), 3); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.PROCEDURE); + assertEquals(currStmt.asJPNode().getLine(), 3); assertEquals(currStmt.getPreviousStatement(), prevStmt); assertNotNull(currStmt.getNextStatement()); prevStmt = currStmt; currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.DO); - assertEquals(currStmt.getLine(), 15); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.DO); + assertEquals(currStmt.asJPNode().getLine(), 15); assertEquals(currStmt.getPreviousStatement(), prevStmt); assertNull(currStmt.getNextStatement()); - JPNode subNode1 = ((BlockNode) prevStmt).getFirstStatement(); + IStatement subNode1 = ((StatementBlockNode) prevStmt).getFirstStatement(); assertNotNull(subNode1); - assertEquals(subNode1.getNodeType(), ABLNodeType.DO); - assertEquals(subNode1.getLine(), 4); + assertEquals(subNode1.asJPNode().getNodeType(), ABLNodeType.DO); + assertEquals(subNode1.asJPNode().getLine(), 4); assertNull(subNode1.getPreviousStatement()); assertNull(subNode1.getNextStatement()); - JPNode subNode2 = ((BlockNode) subNode1).getFirstStatement(); + IStatement subNode2 = ((StatementBlockNode) subNode1).getFirstStatement(); assertNotNull(subNode2); - assertEquals(subNode2.getNodeType(), ABLNodeType.DO); - assertEquals(subNode2.getLine(), 5); + assertEquals(subNode2.asJPNode().getNodeType(), ABLNodeType.DO); + assertEquals(subNode2.asJPNode().getLine(), 5); assertNull(subNode2.getPreviousStatement()); assertNotNull(subNode2.getNextStatement()); subNode2 = subNode2.getNextStatement(); assertNotNull(subNode2); - assertEquals(subNode2.getNodeType(), ABLNodeType.MESSAGE); - assertEquals(subNode2.getLine(), 11); + assertEquals(subNode2.asJPNode().getNodeType(), ABLNodeType.MESSAGE); + assertEquals(subNode2.asJPNode().getLine(), 11); assertNotNull(subNode2.getPreviousStatement()); assertNull(subNode2.getNextStatement()); - JPNode subNode3 = ((BlockNode) subNode2.getPreviousNode()).getFirstStatement(); + IStatement subNode3 = subNode2.asJPNode().getPreviousNode().asIStatementBlock().getFirstStatement(); assertNotNull(subNode3); - assertEquals(subNode3.getNodeType(), ABLNodeType.DISPLAY); - assertEquals(subNode3.getLine(), 6); + assertEquals(subNode3.asJPNode().getNodeType(), ABLNodeType.DISPLAY); + assertEquals(subNode3.asJPNode().getLine(), 6); assertNull(subNode3.getPreviousStatement()); assertNotNull(subNode3.getNextStatement()); subNode3 = subNode3.getNextStatement(); assertNotNull(subNode3); - assertEquals(subNode3.getNodeType(), ABLNodeType.DO); - assertEquals(subNode3.getLine(), 7); + assertEquals(subNode3.asJPNode().getNodeType(), ABLNodeType.DO); + assertEquals(subNode3.asJPNode().getLine(), 7); assertNotNull(subNode3.getPreviousStatement()); assertNull(subNode3.getNextStatement()); - JPNode subNode4 = ((BlockNode) subNode3).getFirstStatement(); + IStatement subNode4 = ((StatementBlockNode) subNode3).getFirstStatement(); assertNotNull(subNode4); - assertEquals(subNode4.getNodeType(), ABLNodeType.MESSAGE); - assertEquals(subNode4.getLine(), 8); + assertEquals(subNode4.asJPNode().getNodeType(), ABLNodeType.MESSAGE); + assertEquals(subNode4.asJPNode().getLine(), 8); assertNull(subNode4.getPreviousStatement()); assertNull(subNode4.getNextStatement()); // Back to the last DO - JPNode subNode5 = ((BlockNode) currStmt).getFirstStatement(); + IStatement subNode5 = ((StatementBlockNode) currStmt).getFirstStatement(); assertNotNull(subNode5); - assertEquals(subNode5.getNodeType(), ABLNodeType.CREATE); - assertEquals(subNode5.getLine(), 16); + assertEquals(subNode5.asJPNode().getNodeType(), ABLNodeType.CREATE); + assertEquals(subNode5.asJPNode().getLine(), 16); assertNull(subNode5.getPreviousStatement()); assertNotNull(subNode5.getNextStatement()); } @@ -291,38 +310,38 @@ public void test04() { assertNotNull(unit.getTopNode()); assertNotNull(unit.getRootScope()); - JPNode currStmt = unit.getTopNode().getFirstStatement(); + IStatement currStmt = unit.getTopNode().getFirstStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.FUNCTION); - assertEquals(currStmt.getLine(), 2); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.FUNCTION); + assertEquals(currStmt.asJPNode().getLine(), 2); assertNull(currStmt.getPreviousStatement()); assertNotNull(currStmt.getNextStatement()); currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.DISPLAY); - assertEquals(currStmt.getLine(), 5); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.DISPLAY); + assertEquals(currStmt.asJPNode().getLine(), 5); assertNotNull(currStmt.getPreviousStatement()); assertNotNull(currStmt.getNextStatement()); currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.DISPLAY); - assertEquals(currStmt.getLine(), 6); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.DISPLAY); + assertEquals(currStmt.asJPNode().getLine(), 6); assertNotNull(currStmt.getPreviousStatement()); assertNotNull(currStmt.getNextStatement()); currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.DISPLAY); - assertEquals(currStmt.getLine(), 7); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.DISPLAY); + assertEquals(currStmt.asJPNode().getLine(), 7); assertNotNull(currStmt.getPreviousStatement()); assertNotNull(currStmt.getNextStatement()); currStmt = currStmt.getNextStatement(); assertNotNull(currStmt); - assertEquals(currStmt.getNodeType(), ABLNodeType.FUNCTION); - assertEquals(currStmt.getLine(), 10); + assertEquals(currStmt.asJPNode().getNodeType(), ABLNodeType.FUNCTION); + assertEquals(currStmt.asJPNode().getLine(), 10); assertNotNull(currStmt.getPreviousStatement()); assertNull(currStmt.getNextStatement()); } diff --git a/proparse/src/test/java/org/prorefactor/core/util/TP01FramesTreeLister.java b/proparse/src/test/java/org/prorefactor/core/util/TP01FramesTreeLister.java index 2b531124f..911516495 100644 --- a/proparse/src/test/java/org/prorefactor/core/util/TP01FramesTreeLister.java +++ b/proparse/src/test/java/org/prorefactor/core/util/TP01FramesTreeLister.java @@ -19,13 +19,10 @@ import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.JPNode; -import org.prorefactor.core.nodetypes.BlockNode; import org.prorefactor.core.nodetypes.FieldRefNode; import org.prorefactor.proparse.support.JPNodeLister; -import org.prorefactor.treeparser.Block; import org.prorefactor.treeparser.symbols.FieldContainer; import org.prorefactor.treeparser.symbols.Symbol; -import org.prorefactor.treeparser.symbols.widgets.Frame; public class TP01FramesTreeLister extends JPNodeLister { @@ -44,8 +41,8 @@ private void appendName(StringBuffer buff, FieldContainer container) { protected String getExtraInfo(JPNode node, char spacer) { StringBuffer buff = new StringBuffer(); // buff.append(indent(1)); - if (node instanceof BlockNode) - blockNode(buff, (BlockNode) node, spacer); + /* if (node instanceof BlockNode) + blockNode(buff, (BlockNode) node, spacer); */ if (node instanceof FieldRefNode) { fieldRefNode(buff, (FieldRefNode) node, spacer); fieldContainer(buff, node, spacer); @@ -55,7 +52,7 @@ protected String getExtraInfo(JPNode node, char spacer) { return buff.toString(); } - private void blockNode(StringBuffer buff, BlockNode blockNode, char spacer) { + /*private void blockNode(StringBuffer buff, BlockNode blockNode, char spacer) { Block block = blockNode.getBlock(); if (block.getDefaultFrame() != null) { buff @@ -70,7 +67,7 @@ private void blockNode(StringBuffer buff, BlockNode blockNode, char spacer) { buff.append(" "); appendName(buff, frame); } - } + }*/ private void fieldContainer(StringBuffer buff, JPNode node, char spacer) { FieldContainer fieldContainer = node.getFieldContainer(); From 972f8219b61bc8c716e9d58effc4af54bc8e1961 Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Tue, 21 Sep 2021 11:39:00 +0200 Subject: [PATCH 09/15] Temporary fix: bring back JPNode#getState2() --- proparse/src/main/java/org/prorefactor/core/JPNode.java | 8 ++++++++ .../org/prorefactor/core/nodetypes/StatementNode.java | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/proparse/src/main/java/org/prorefactor/core/JPNode.java b/proparse/src/main/java/org/prorefactor/core/JPNode.java index 96656aa21..147c055a7 100644 --- a/proparse/src/main/java/org/prorefactor/core/JPNode.java +++ b/proparse/src/main/java/org/prorefactor/core/JPNode.java @@ -723,6 +723,14 @@ public boolean isStateHead() { return isStatement(); } + /** + * @deprecated Use JPNode()#asIStatement()#getNodeType2() + */ + @Deprecated + public int getState2() { + return 0; + } + public boolean isStatement() { return false; } diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java index ed1499900..a7ef49e1b 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java @@ -53,6 +53,11 @@ public ABLNodeType getNodeType2() { return state2; } + @Override + public int getState2() { + return state2 != null ? state2.getType() : 0; + } + @Override public boolean isStatement() { return true; From d6341effd5e7386c2b50b5140ad15b73dd1af7d3 Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Tue, 21 Sep 2021 12:15:14 +0200 Subject: [PATCH 10/15] IStatement#getEnclosingBlock() --- .../org/prorefactor/core/nodetypes/IStatement.java | 5 +++++ .../prorefactor/core/nodetypes/StatementNode.java | 12 ++++++++++++ .../org/prorefactor/treeparser/TreeParserBlocks.java | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatement.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatement.java index 9b9b678f2..a1c4fc4a0 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatement.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/IStatement.java @@ -20,6 +20,7 @@ import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.JPNode; +import org.prorefactor.treeparser.Block; public interface IStatement { /** @@ -56,6 +57,10 @@ public interface IStatement { */ List getAnnotations(); + Block getEnclosingBlock(); + + void setInBlock(Block inBlock); + void setPreviousStatement(IStatement statement); void setNextStatement(IStatement statement); diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java index a7ef49e1b..6d64c4285 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/StatementNode.java @@ -20,6 +20,7 @@ import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.JPNode; import org.prorefactor.core.ProToken; +import org.prorefactor.treeparser.Block; public class StatementNode extends JPNode implements IStatement { private IStatement previousStatement; @@ -27,6 +28,7 @@ public class StatementNode extends JPNode implements IStatement { private IStatementBlock parentStatement; private List annotations; private ABLNodeType state2; + private Block inBlock; public StatementNode(ProToken t, JPNode parent, int num, boolean hasChildren, ABLNodeType state2) { super(t, parent, num, hasChildren); @@ -115,4 +117,14 @@ else if (parentStatement != null) return false; } + @Override + public Block getEnclosingBlock() { + return inBlock; + } + + @Override + public void setInBlock(Block inBlock) { + this.inBlock = inBlock; + } + } diff --git a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java index e7a214642..60ed42446 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java @@ -533,7 +533,7 @@ private void enterNewStatement(@Nonnull IStatement node) { lastStatement = node; node.setParentStatement(currentBlock.getNode().asIStatementBlock()); } - + node.setInBlock(currentBlock); if (currentBlock.getNode().asIStatementBlock().getFirstStatement() == null) { currentBlock.getNode().asIStatementBlock().setFirstStatement(node); } From 8deeb73efee06faa3601a7fb9e524e590df59a48 Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Tue, 21 Sep 2021 13:28:29 +0200 Subject: [PATCH 11/15] Fix issue with labeled blocks in IF statement --- .../prorefactor/treeparser/TreeParserBlocks.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java index 60ed42446..84aa859f8 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java @@ -515,14 +515,17 @@ private String indent() { private void enterNewStatement(@Nonnull IStatement node) { if ((inIfStmt || inElseStmt) && (node != lastStatement) && (lastStatement instanceof IfNode)) { IfNode ifNode = (IfNode) lastStatement; - IStatementBlock thenElseNode = node.asJPNode().getParent().asIStatementBlock(); + JPNode thenElseNode = node.asJPNode().getParent(); + if (thenElseNode.getNodeType() == ABLNodeType.BLOCK_LABEL) + thenElseNode = thenElseNode.getParent(); + IStatementBlock thenElseBlock = thenElseNode.asIStatementBlock(); if (inIfStmt) - ifNode.setThenNode(thenElseNode); + ifNode.setThenNode(thenElseBlock); else - ifNode.setElseNode(thenElseNode); - node.setParentStatement(thenElseNode); - thenElseNode.setFirstStatement(node); - thenElseNode.setParentStatement(ifNode); + ifNode.setElseNode(thenElseBlock); + node.setParentStatement(thenElseBlock); + thenElseBlock.setFirstStatement(node); + thenElseBlock.setParentStatement(ifNode); inIfStmt = false; inElseStmt = false; } else { From 4aa6a1707ad7ef7024f9a7956c81dcd67b567912 Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Tue, 21 Sep 2021 18:15:56 +0200 Subject: [PATCH 12/15] Back with a much cleaner implementation of StatementFlow --- .../prorefactor/proparse/antlr4/Proparse.g4 | 10 +- .../java/org/prorefactor/core/JPNode.java | 8 +- .../prorefactor/core/nodetypes/IfNode.java | 50 --- .../core/nodetypes/NonStatementBlockNode.java | 5 + .../prorefactor/proparse/JPNodeVisitor.java | 18 +- .../org/prorefactor/treeparser/Block.java | 4 + .../treeparser/TreeParserBlocks.java | 358 +++++++++--------- .../java/org/prorefactor/core/ParserTest.java | 2 +- .../prorefactor/core/StatementFlowTest.java | 80 ++++ .../core/TreeParserBlocksTest.java | 10 +- .../core/util/StatementFlowWriter.java | 85 +++++ .../resources/treeparser06-expect/test01.p | 49 +++ .../src/test/resources/treeparser06/test01.p | 33 ++ 13 files changed, 459 insertions(+), 253 deletions(-) delete mode 100644 proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java create mode 100644 proparse/src/test/java/org/prorefactor/core/StatementFlowTest.java create mode 100644 proparse/src/test/java/org/prorefactor/core/util/StatementFlowWriter.java create mode 100644 proparse/src/test/resources/treeparser06-expect/test01.p create mode 100644 proparse/src/test/resources/treeparser06/test01.p diff --git a/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 b/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 index 7b6a6bd4b..c9c346837 100644 --- a/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 +++ b/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 @@ -880,15 +880,15 @@ caseSensitiveOrNot: ; caseStatement: - CASE expression blockColon caseBlock caseOtherwise? (EOF | caseEnd statementEnd) + CASE expression blockColon caseWhen* caseOtherwise? (EOF | caseEnd statementEnd) ; -caseBlock: - caseWhen* +caseWhen: + WHEN caseExpression caseWhenThen ; -caseWhen: - WHEN caseExpression THEN blockOrStatement +caseWhenThen: + THEN blockOrStatement ; caseExpression: diff --git a/proparse/src/main/java/org/prorefactor/core/JPNode.java b/proparse/src/main/java/org/prorefactor/core/JPNode.java index 147c055a7..7d145427d 100644 --- a/proparse/src/main/java/org/prorefactor/core/JPNode.java +++ b/proparse/src/main/java/org/prorefactor/core/JPNode.java @@ -33,7 +33,6 @@ import org.prorefactor.core.nodetypes.IExpression; import org.prorefactor.core.nodetypes.IStatement; import org.prorefactor.core.nodetypes.IStatementBlock; -import org.prorefactor.core.nodetypes.IfNode; import org.prorefactor.core.nodetypes.InUIReferenceNode; import org.prorefactor.core.nodetypes.LocalMethodCallNode; import org.prorefactor.core.nodetypes.MethodCallNode; @@ -806,6 +805,10 @@ public int naturalSize() { return sz; } + public String getPositionString() { + return String.format("F%d/%d:%d", getFileIndex(), getLine(), getColumn()); + } + @Override public String toString() { StringBuilder buff = new StringBuilder(); @@ -1177,9 +1180,6 @@ private JPNode build(ParseUnit unit, ParserSupport support, JPNode up, int num) case CANFIND: node = new CanFindNode(tok, up, num, hasChildren); break; - case IF: - node = new IfNode(tok, up, num, hasChildren); - break; default: if (stmt && block) node = new StatementBlockNode(tok, up, num, hasChildren, stmt2); diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java deleted file mode 100644 index 726d945a4..000000000 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/IfNode.java +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2015-2021 Riverside Software - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 - * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt - * - * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 - ********************************************************************************/ -package org.prorefactor.core.nodetypes; - -import javax.annotation.Nullable; - -import org.prorefactor.core.JPNode; -import org.prorefactor.core.ProToken; - -/** - * Specialized type of JPNode for IF statement - */ -public class IfNode extends StatementBlockNode { - private IStatementBlock thenNode; - private IStatementBlock elseNode; - - public IfNode(ProToken t, JPNode parent, int num, boolean hasChildren) { - super(t, parent, num, hasChildren, null); - } - - public void setThenNode(IStatementBlock statement) { - this.thenNode = statement; - } - - public IStatementBlock getThenNode() { - return thenNode; - } - - public void setElseNode(IStatementBlock statement) { - this.elseNode = statement; - } - - @Nullable - public IStatementBlock getElseNode() { - return elseNode; - } - -} diff --git a/proparse/src/main/java/org/prorefactor/core/nodetypes/NonStatementBlockNode.java b/proparse/src/main/java/org/prorefactor/core/nodetypes/NonStatementBlockNode.java index 8ea7d2ee5..57ba41013 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/NonStatementBlockNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/NonStatementBlockNode.java @@ -50,6 +50,11 @@ public void setParentStatement(IStatementBlock statement) { this.parentStatement = statement; } + @Override + public boolean hasBlock() { + return block != null; + } + @Override public Block getBlock() { return block; diff --git a/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java b/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java index 745becf1a..b1badbcd5 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java +++ b/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java @@ -779,17 +779,17 @@ public Builder visitCasesensNot(CasesensNotContext ctx) { @Override public Builder visitCaseStatement(CaseStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override - public Builder visitCaseBlock(CaseBlockContext ctx) { - return createTree(ctx, ABLNodeType.CODE_BLOCK); + public Builder visitCaseWhen(CaseWhenContext ctx) { + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override - public Builder visitCaseWhen(CaseWhenContext ctx) { - return createTreeFromFirstNode(ctx); + public Builder visitCaseWhenThen(CaseWhenThenContext ctx) { + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -804,7 +804,7 @@ public Builder visitCaseExprTerm(CaseExprTermContext ctx) { @Override public Builder visitCaseOtherwise(CaseOtherwiseContext ctx) { - return createTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override @@ -1849,17 +1849,17 @@ public Builder visitHideStatement(HideStatementContext ctx) { @Override public Builder visitIfStatement(IfStatementContext ctx) { - return createStatementTreeFromFirstNode(ctx); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override public Builder visitIfThen(IfThenContext ctx) { - return createTreeFromFirstNode(ctx).setBlock(true); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override public Builder visitIfElse(IfElseContext ctx) { - return createTreeFromFirstNode(ctx).setBlock(true); + return createStatementTreeFromFirstNode(ctx).setBlock(true); } @Override diff --git a/proparse/src/main/java/org/prorefactor/treeparser/Block.java b/proparse/src/main/java/org/prorefactor/treeparser/Block.java index b707025bc..8fcb4ec5e 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/Block.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/Block.java @@ -470,4 +470,8 @@ public Block setDefaultFrameImplicit(Frame frame) { } } + @Override + public String toString() { + return "Block associated to " + blockStatementNode.toString(); + } } diff --git a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java index 84aa859f8..7cdd09690 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserBlocks.java @@ -27,9 +27,7 @@ import org.prorefactor.core.JPNode; import org.prorefactor.core.nodetypes.IStatement; import org.prorefactor.core.nodetypes.IStatementBlock; -import org.prorefactor.core.nodetypes.IfNode; import org.prorefactor.core.nodetypes.ProgramRootNode; -import org.prorefactor.proparse.antlr4.Proparse; import org.prorefactor.proparse.antlr4.Proparse.CanFindFunctionContext; import org.prorefactor.proparse.antlr4.Proparse.CatchStatementContext; import org.prorefactor.proparse.antlr4.Proparse.ClassStatementContext; @@ -42,8 +40,6 @@ import org.prorefactor.proparse.antlr4.Proparse.ExternalProcedureStatementContext; import org.prorefactor.proparse.antlr4.Proparse.ForStatementContext; import org.prorefactor.proparse.antlr4.Proparse.FunctionStatementContext; -import org.prorefactor.proparse.antlr4.Proparse.IfElseContext; -import org.prorefactor.proparse.antlr4.Proparse.IfStatementContext; import org.prorefactor.proparse.antlr4.Proparse.InterfaceStatementContext; import org.prorefactor.proparse.antlr4.Proparse.MethodStatementContext; import org.prorefactor.proparse.antlr4.Proparse.OnStatementContext; @@ -74,10 +70,7 @@ public class TreeParserBlocks extends ProparseBaseListener { private final TreeParserRootSymbolScope rootScope; private Routine rootRoutine; - private IStatement lastStatement; private int currentLevel; - private boolean inIfStmt; - private boolean inElseStmt; private Block currentBlock; private TreeParserSymbolScope currentScope; @@ -93,6 +86,11 @@ public class TreeParserBlocks extends ProparseBaseListener { private List blockStack = new ArrayList<>(); private Map funcForwards = new HashMap<>(); + private IStatementBlock currStmtBlock; + private IStatement lastStatement; + private List stmtStack = new ArrayList<>(); + private List stmtBlockStack = new ArrayList<>(); + @Inject public TreeParserBlocks(ParseUnit unit) { this.unit = unit; @@ -112,19 +110,18 @@ public void enterProgram(ProgramContext ctx) { throw new IllegalStateException("TreeParser has already been executed..."); } - JPNode blockNode = support.getNode(ctx); - currentBlock = pushBlock(new Block(rootScope, blockNode, null)); + JPNode programRootNode = support.getNode(ctx); + currentBlock = pushBlock(new Block(rootScope, programRootNode, null)); rootScope.setRootBlock(currentBlock); - blockNode.setBlock(currentBlock); + programRootNode.setBlock(currentBlock); - Routine routine = new Routine("", rootScope, rootScope); - routine.setProgressType(ABLNodeType.PROGRAM_ROOT); - routine.setDefinitionNode(blockNode); - blockNode.setSymbol(routine); + rootRoutine = new Routine("", rootScope, rootScope); + rootRoutine.setProgressType(ABLNodeType.PROGRAM_ROOT); + rootRoutine.setDefinitionNode(programRootNode); + programRootNode.setSymbol(rootRoutine); - rootScope.add(routine); - currentRoutine = routine; - rootRoutine = routine; + rootScope.add(rootRoutine); + currentRoutine = rootRoutine; } @Override @@ -150,64 +147,51 @@ public void enterInterfaceStatement(InterfaceStatementContext ctx) { rootScope.setInterface(true); } - @Override - public void enterCatchStatement(CatchStatementContext ctx) { - blockBegin(ctx); - } - - @Override - public void exitCatchStatement(CatchStatementContext ctx) { - blockEnd(); - } - - @Override - public void enterConstructorStatement(ConstructorStatementContext ctx) { - newRoutine(support.getNode(ctx), "", ABLNodeType.CONSTRUCTOR); - } - - @Override - public void exitConstructorStatement(ConstructorStatementContext ctx) { - scopeClose(); - currentRoutine = rootRoutine; - } - - @Override - public void enterCanFindFunction(CanFindFunctionContext ctx) { - // ...create a can-find scope and block (assigns currentBlock)... - scopeAdd(support.getNode(ctx)); - } - - @Override - public void exitCanFindFunction(CanFindFunctionContext ctx) { - scopeClose(); - } + // ******** + // ROUTINES + // ******** @Override public void enterDefinePropertyAccessorGetBlock(DefinePropertyAccessorGetBlockContext ctx) { + JPNode node = support.getNode(ctx); if (ctx.codeBlock() != null) { - JPNode node = support.getNode(ctx); newRoutine(node, node.getText(), node.getNodeType()); } } @Override public void enterDefinePropertyAccessorSetBlock(DefinePropertyAccessorSetBlockContext ctx) { + JPNode node = support.getNode(ctx); if (ctx.codeBlock() != null) { - JPNode node = support.getNode(ctx); newRoutine(node, node.getText(), node.getNodeType()); } } @Override public void exitDefinePropertyAccessorGetBlock(DefinePropertyAccessorGetBlockContext ctx) { - if (ctx.codeBlock() != null) - propGetSetEnd(); + if (ctx.codeBlock() != null) { + scopeClose(); + currentRoutine = rootRoutine; + } } @Override public void exitDefinePropertyAccessorSetBlock(DefinePropertyAccessorSetBlockContext ctx) { - if (ctx.codeBlock() != null) - propGetSetEnd(); + if (ctx.codeBlock() != null) { + scopeClose(); + currentRoutine = rootRoutine; + } + } + + @Override + public void enterConstructorStatement(ConstructorStatementContext ctx) { + newRoutine(support.getNode(ctx), "", ABLNodeType.CONSTRUCTOR); + } + + @Override + public void exitConstructorStatement(ConstructorStatementContext ctx) { + scopeClose(); + currentRoutine = rootRoutine; } @Override @@ -222,33 +206,47 @@ public void exitDestructorStatement(DestructorStatementContext ctx) { } @Override - public void enterDoStatement(DoStatementContext ctx) { - blockBegin(ctx); + public void enterMethodStatement(MethodStatementContext ctx) { + newRoutine(support.getNode(ctx), ctx.id.getText(), ABLNodeType.METHOD); + + if (ctx.VOID() != null) { + currentRoutine.setReturnDatatypeNode(DataType.VOID); + } else if (ctx.datatype().CLASS() != null) { + currentRoutine.setReturnDatatypeNode(new DataType(ctx.datatype().getStop().getText())); + } else if (ctx.datatype().datatypeVar().typeName() != null) { + currentRoutine.setReturnDatatypeNode(new DataType(ctx.datatype().getStop().getText())); + } else { + currentRoutine.setReturnDatatypeNode( + ABLNodeType.getDataType(support.getNode(ctx.datatype().datatypeVar()).getType())); + } } @Override - public void exitDoStatement(DoStatementContext ctx) { - blockEnd(); + public void exitMethodStatement(MethodStatementContext ctx) { + scopeClose(); + currentRoutine = rootRoutine; } @Override - public void enterForStatement(ForStatementContext ctx) { - blockBegin(ctx); + public void enterProcedureStatement(ProcedureStatementContext ctx) { + newRoutine(support.getNode(ctx), ctx.filename().getText(), ABLNodeType.PROCEDURE); } @Override - public void exitForStatement(ForStatementContext ctx) { - blockEnd(); + public void exitProcedureStatement(ProcedureStatementContext ctx) { + scopeClose(); + currentRoutine = rootRoutine; } @Override - public void enterIfStatement(IfStatementContext ctx) { - inIfStmt = true; + public void enterExternalProcedureStatement(ExternalProcedureStatementContext ctx) { + newRoutine(support.getNode(ctx), ctx.filename().getText(), ABLNodeType.PROCEDURE); } @Override - public void enterIfElse(IfElseContext ctx) { - inElseStmt = true; + public void exitExternalProcedureStatement(ExternalProcedureStatementContext ctx) { + scopeClose(); + currentRoutine = rootRoutine; } @Override @@ -318,81 +316,83 @@ public void exitExternalFunctionStatement(ExternalFunctionStatementContext ctx) currentRoutine = rootRoutine; } - @Override - public void enterMethodStatement(MethodStatementContext ctx) { - newRoutine(support.getNode(ctx), ctx.id.getText(), ABLNodeType.METHOD); + // ****** + // Scopes + // ****** - if (ctx.VOID() != null) { - currentRoutine.setReturnDatatypeNode(DataType.VOID); - } else { - if (ctx.datatype().CLASS() != null) { - currentRoutine.setReturnDatatypeNode(new DataType(ctx.datatype().getStop().getText())); - } else { - if (ctx.datatype().datatypeVar().typeName() != null) { - currentRoutine.setReturnDatatypeNode(new DataType(ctx.datatype().getStop().getText())); - } else - currentRoutine.setReturnDatatypeNode( - ABLNodeType.getDataType(support.getNode(ctx.datatype().datatypeVar()).getType())); - } - } + @Override + public void enterCanFindFunction(CanFindFunctionContext ctx) { + // ...create a can-find scope and block (assigns currentBlock)... + scopeAdd(support.getNode(ctx)); } @Override - public void exitMethodStatement(MethodStatementContext ctx) { + public void exitCanFindFunction(CanFindFunctionContext ctx) { scopeClose(); - currentRoutine = rootRoutine; } @Override - public void enterExternalProcedureStatement(ExternalProcedureStatementContext ctx) { - newRoutine(support.getNode(ctx), ctx.filename().getText(), ABLNodeType.PROCEDURE); + public void enterOnStatement(OnStatementContext ctx) { + scopeAdd(support.getNode(ctx)); } @Override - public void exitExternalProcedureStatement(ExternalProcedureStatementContext ctx) { + public void exitOnStatement(OnStatementContext ctx) { scopeClose(); - currentRoutine = rootRoutine; } @Override - public void enterProcedureStatement(ProcedureStatementContext ctx) { - newRoutine(support.getNode(ctx), ctx.filename().getText(), ABLNodeType.PROCEDURE); + public void enterTriggerOn(TriggerOnContext ctx) { + scopeAdd(support.getNode(ctx)); } @Override - public void exitProcedureStatement(ProcedureStatementContext ctx) { + public void exitTriggerOn(TriggerOnContext ctx) { scopeClose(); - currentRoutine = rootRoutine; } + // ****** + // Blocks + // ****** + @Override - public void enterOnStatement(OnStatementContext ctx) { - scopeAdd(support.getNode(ctx)); + public void enterCatchStatement(CatchStatementContext ctx) { + blockBegin(ctx); } @Override - public void exitOnStatement(OnStatementContext ctx) { - scopeClose(); + public void exitCatchStatement(CatchStatementContext ctx) { + blockEnd(); } @Override - public void enterRepeatStatement(RepeatStatementContext ctx) { + public void enterDoStatement(DoStatementContext ctx) { blockBegin(ctx); } @Override - public void exitRepeatStatement(RepeatStatementContext ctx) { + public void exitDoStatement(DoStatementContext ctx) { blockEnd(); } @Override - public void enterTriggerOn(TriggerOnContext ctx) { - scopeAdd(support.getNode(ctx)); + public void enterForStatement(ForStatementContext ctx) { + blockBegin(ctx); } @Override - public void exitTriggerOn(TriggerOnContext ctx) { - scopeClose(); + public void exitForStatement(ForStatementContext ctx) { + blockEnd(); + } + + @Override + public void enterRepeatStatement(RepeatStatementContext ctx) { + blockBegin(ctx); + } + + @Override + public void exitRepeatStatement(RepeatStatementContext ctx) { + blockEnd(); } // ****************** @@ -400,15 +400,49 @@ public void exitTriggerOn(TriggerOnContext ctx) { // ****************** private void newRoutine(JPNode blockNode, String routineName, ABLNodeType routineType) { + if (LOG.isTraceEnabled()) + LOG.trace("{}> Creating new routine '{}'", indent(), routineName); + TreeParserSymbolScope definingScope = currentScope; scopeAdd(blockNode); - Routine r = new Routine(routineName, definingScope, currentScope); - r.setProgressType(routineType); - r.setDefinitionNode(blockNode); - blockNode.setSymbol(r); - definingScope.add(r); - currentRoutine = r; + currentRoutine = new Routine(routineName, definingScope, currentScope); + currentRoutine.setProgressType(routineType).setDefinitionNode(blockNode); + blockNode.setSymbol(currentRoutine); + definingScope.add(currentRoutine); + } + + private void scopeAdd(JPNode blockNode) { + if (LOG.isTraceEnabled()) + LOG.trace("{}> Creating new scope for block {}", indent(), blockNode.getNodeType()); + + currentScope = currentScope.addScope(); + currentBlock = pushBlock(new Block(currentScope, blockNode, currentBlock)); + currentScope.setRootBlock(currentBlock); + blockNode.setBlock(currentBlock); + } + + private void scopeClose() { + if (LOG.isTraceEnabled()) + LOG.trace("{}> End of scope", indent()); + + currentScope = currentScope.getParentScope(); + blockEnd(); + } + + /** + * In the case of a function definition that comes some time after a function forward declaration, we want to use the + * scope that was created with the forward declaration, because it is the scope that has all of the parameter + * definitions. We have to do this because the definition itself may have left out the parameter list - it's not + * required - it just uses the parameter list from the declaration. + */ + private void scopeSwap(TreeParserSymbolScope scope) { + if (LOG.isTraceEnabled()) + LOG.trace("{}> Swapping scope...", indent()); + + currentScope = scope; + blockEnd(); // pop the unused block from the stack + currentBlock = pushBlock(scope.getRootBlock()); } private Block pushBlock(Block block) { @@ -416,8 +450,6 @@ private Block pushBlock(Block block) { LOG.trace("{}> Pushing block '{}' to stack", indent(), block); blockStack.add(block); - lastStatement = null; - return block; } @@ -425,22 +457,12 @@ private Block popBlock() { if (LOG.isTraceEnabled()) LOG.trace("{}> Popping block from stack", indent()); - Block bb = blockStack.remove(blockStack.size() - 1); - lastStatement = bb.getNode().asIStatement(); + blockStack.remove(blockStack.size() - 1); - if (lastStatement != null) { - if (lastStatement.asJPNode().getParent().getNodeType() == ABLNodeType.THEN) { - lastStatement = lastStatement.getParentStatement().getParentStatement().asJPNode().asIStatement(); - } else if (lastStatement.asJPNode().getParent().getNodeType() == ABLNodeType.ELSE) { - lastStatement = lastStatement.asJPNode().getParent().getParent().asIStatement(); - } - } return blockStack.get(blockStack.size() - 1); } private void blockBegin(ParseTree ctx) { - if (LOG.isTraceEnabled()) - LOG.trace("{}> Creating new block", indent()); JPNode blockNode = support.getNode(ctx); currentBlock = pushBlock(new Block(currentBlock, blockNode)); blockNode.setBlock(currentBlock); @@ -452,93 +474,71 @@ private void blockEnd() { currentBlock = popBlock(); } - private void scopeAdd(JPNode blockNode) { - if (LOG.isTraceEnabled()) - LOG.trace("{}> Creating new scope for block {}", indent(), blockNode.getNodeType()); - - currentScope = currentScope.addScope(); - currentBlock = pushBlock(new Block(currentScope, blockNode, currentBlock)); - currentScope.setRootBlock(currentBlock); - blockNode.setBlock(currentBlock); - } - - private void scopeClose() { + private void statementBlockBegin(IStatementBlock stmt) { if (LOG.isTraceEnabled()) - LOG.trace("{}> End of scope", indent()); + LOG.trace("{}> New statement block {} ", indent(), stmt.asJPNode()); - currentScope = currentScope.getParentScope(); - blockEnd(); + stmtStack.add(lastStatement); + lastStatement = null; + if (currStmtBlock != null) + stmtBlockStack.add(currStmtBlock); + currStmtBlock = stmt; } - /** - * In the case of a function definition that comes some time after a function forward declaration, we want to use the - * scope that was created with the forward declaration, because it is the scope that has all of the parameter - * definitions. We have to do this because the definition itself may have left out the parameter list - it's not - * required - it just uses the parameter list from the declaration. - */ - private void scopeSwap(TreeParserSymbolScope scope) { + private void statementBlockEnd() { if (LOG.isTraceEnabled()) - LOG.trace("{}> Swapping scope...", indent()); - - currentScope = scope; - blockEnd(); // pop the unused block from the stack - currentBlock = pushBlock(scope.getRootBlock()); - } + LOG.trace("{}> End statement block - Back to '{}' - Last statement '{}'", indent(), + stmtBlockStack.get(stmtBlockStack.size() - 1), stmtStack.get(stmtStack.size() - 1)); - private void propGetSetEnd() { - scopeClose(); - currentRoutine = rootRoutine; + currStmtBlock = stmtBlockStack.remove(stmtBlockStack.size() - 1); + lastStatement = stmtStack.remove(stmtStack.size() - 1); } @Override public void enterEveryRule(ParserRuleContext ctx) { currentLevel++; - if (LOG.isTraceEnabled()) - LOG.trace("{}> {}", indent(), Proparse.ruleNames[ctx.getRuleIndex()]); JPNode node = support.getNode(ctx); - if ((node != null) && node.isStatement() && !(node instanceof ProgramRootNode)) { + if ((node != null) && node.isStatement()) { enterNewStatement(node.asIStatement()); } + if ((node != null) && node.isIStatementBlock()) { + statementBlockBegin(node.asIStatementBlock()); + } } @Override public void exitEveryRule(ParserRuleContext ctx) { currentLevel--; + + JPNode node = support.getNode(ctx); + if ((node != null) && node.isIStatementBlock() && !(node instanceof ProgramRootNode)) { + if (LOG.isTraceEnabled()) + LOG.trace("{}> PopStatementBlock {}", indent(), node); + + statementBlockEnd(); + } } private String indent() { - return java.nio.CharBuffer.allocate(currentLevel).toString().replace('\0', ' '); + return java.nio.CharBuffer.allocate(currentLevel).toString().replace('\0', '-'); } // Attach current statement to the previous one private void enterNewStatement(@Nonnull IStatement node) { - if ((inIfStmt || inElseStmt) && (node != lastStatement) && (lastStatement instanceof IfNode)) { - IfNode ifNode = (IfNode) lastStatement; - JPNode thenElseNode = node.asJPNode().getParent(); - if (thenElseNode.getNodeType() == ABLNodeType.BLOCK_LABEL) - thenElseNode = thenElseNode.getParent(); - IStatementBlock thenElseBlock = thenElseNode.asIStatementBlock(); - if (inIfStmt) - ifNode.setThenNode(thenElseBlock); - else - ifNode.setElseNode(thenElseBlock); - node.setParentStatement(thenElseBlock); - thenElseBlock.setFirstStatement(node); - thenElseBlock.setParentStatement(ifNode); - inIfStmt = false; - inElseStmt = false; - } else { - if ((lastStatement != null) && (node != lastStatement)) { - lastStatement.setNextStatement(node); - node.setPreviousStatement(lastStatement); - } - lastStatement = node; - node.setParentStatement(currentBlock.getNode().asIStatementBlock()); + if (LOG.isTraceEnabled()) + LOG.trace("{}> NewStatement {}", indent(), node); + + if ((lastStatement != null) && (node != lastStatement)) { + lastStatement.setNextStatement(node); + node.setPreviousStatement(lastStatement); } + lastStatement = node; + node.setParentStatement(currStmtBlock); + node.setInBlock(currentBlock); - if (currentBlock.getNode().asIStatementBlock().getFirstStatement() == null) { - currentBlock.getNode().asIStatementBlock().setFirstStatement(node); + if (currStmtBlock.getFirstStatement() == null) { + currStmtBlock.setFirstStatement(node); } // Assign annotations to statement diff --git a/proparse/src/test/java/org/prorefactor/core/ParserTest.java b/proparse/src/test/java/org/prorefactor/core/ParserTest.java index fa3560bea..b6a99e9e8 100644 --- a/proparse/src/test/java/org/prorefactor/core/ParserTest.java +++ b/proparse/src/test/java/org/prorefactor/core/ParserTest.java @@ -240,7 +240,7 @@ public void testInputFunction() { unit.parse(); assertFalse(unit.hasSyntaxError()); assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.ON).size(), 1); - assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.IF).get(0).queryStateHead().size(), 2); + assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.IF).get(0).queryStateHead(ABLNodeType.DO).size(), 1); } @Test diff --git a/proparse/src/test/java/org/prorefactor/core/StatementFlowTest.java b/proparse/src/test/java/org/prorefactor/core/StatementFlowTest.java new file mode 100644 index 000000000..de5cf949a --- /dev/null +++ b/proparse/src/test/java/org/prorefactor/core/StatementFlowTest.java @@ -0,0 +1,80 @@ +/******************************************************************************** + * Copyright (c) 2015-2021 Riverside Software + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 + * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt + * + * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 + ********************************************************************************/ +package org.prorefactor.core; + +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +import org.prorefactor.core.util.StatementFlowWriter; +import org.prorefactor.core.util.UnitTestModule; +import org.prorefactor.refactor.RefactorSession; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +public class StatementFlowTest { + + private RefactorSession session; + + private final static String SOURCEDIR = "src/test/resources/treeparser06/"; + private final static String TARGETDIR = "target/test-temp/treeparser06/"; + private final static String EXPECTDIR = "src/test/resources/treeparser06-expect/"; + + @BeforeTest + public void setUp() { + Injector injector = Guice.createInjector(new UnitTestModule()); + session = injector.getInstance(RefactorSession.class); + session.getSchema().createAlias("foo", "sports2000"); + new File(TARGETDIR).mkdirs(); + } + + @Test + public void test01() throws IOException { + genericTest("test01.p"); + } + + private void genericTest(String name) throws IOException { + StatementFlowWriter writer = new StatementFlowWriter(); + writer.write(SOURCEDIR + name, new File(TARGETDIR + name), session); + try (FileReader r1 = new FileReader(EXPECTDIR + name); + FileReader r2 = new FileReader(TARGETDIR + name); + BufferedReader br1 = new BufferedReader(r1); + BufferedReader br2 = new BufferedReader(r2)) { + assertTrue(contentEquals(br1, br2)); + } catch (IOException caught) { + fail("Unable to find output file", caught); + } + } + + protected static boolean contentEquals(BufferedReader r1, BufferedReader r2) throws IOException { + String s1 = r1.readLine(); + String s2 = r2.readLine(); + while (s1 != null) { + if (!s1.equals(s2)) + return false; + s1 = r1.readLine(); + s2 = r2.readLine(); + } + + return true; + } +} diff --git a/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java b/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java index c9a6c85b0..b41031558 100644 --- a/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java +++ b/proparse/src/test/java/org/prorefactor/core/TreeParserBlocksTest.java @@ -24,7 +24,6 @@ import java.io.File; import org.prorefactor.core.nodetypes.IStatement; -import org.prorefactor.core.nodetypes.IfNode; import org.prorefactor.core.nodetypes.StatementBlockNode; import org.prorefactor.core.util.UnitTestModule; import org.prorefactor.refactor.RefactorSession; @@ -160,7 +159,7 @@ public void test02() { assertEquals(stmt2.getPreviousStatement(), stmt1); assertNull(stmt2.getNextStatement()); - IStatement currSubStmt = ((IfNode) stmt1).getThenNode().getFirstStatement(); + IStatement currSubStmt = stmt1.asJPNode().asIStatementBlock().getFirstStatement().asJPNode().asIStatementBlock().getFirstStatement(); assertNotNull(currSubStmt); assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.MESSAGE); assertEquals(currSubStmt.asJPNode().getLine(), 2); @@ -168,7 +167,7 @@ public void test02() { assertNull(currSubStmt.getPreviousStatement()); assertNull(currSubStmt.getNextStatement()); - currSubStmt = ((IfNode) stmt1).getElseNode().getFirstStatement(); + currSubStmt = stmt1.asJPNode().asIStatementBlock().getFirstStatement().getNextStatement().asJPNode().asIStatementBlock().getFirstStatement(); assertNotNull(currSubStmt); assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.MESSAGE); assertEquals(currSubStmt.asJPNode().getLine(), 4); @@ -176,7 +175,7 @@ public void test02() { assertNull(currSubStmt.getPreviousStatement()); assertNull(currSubStmt.getNextStatement()); - currSubStmt = ((IfNode) stmt2).getThenNode().getFirstStatement(); + currSubStmt = stmt2.asJPNode().asIStatementBlock().getFirstStatement().asJPNode().asIStatementBlock().getFirstStatement(); assertNotNull(currSubStmt); assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.DO); assertEquals(currSubStmt.asJPNode().getLine(), 6); @@ -192,7 +191,7 @@ public void test02() { assertNull(currSubStmt2.getPreviousStatement()); assertNull(currSubStmt2.getNextStatement()); - currSubStmt = ((IfNode) stmt2).getElseNode().getFirstStatement(); + currSubStmt = stmt2.asJPNode().asIStatementBlock().getFirstStatement().getNextStatement().asJPNode().asIStatementBlock().getFirstStatement(); assertNotNull(currSubStmt); assertEquals(currSubStmt.asJPNode().getNodeType(), ABLNodeType.DO); assertEquals(currSubStmt.asJPNode().getLine(), 9); @@ -345,4 +344,5 @@ public void test04() { assertNotNull(currStmt.getPreviousStatement()); assertNull(currStmt.getNextStatement()); } + } diff --git a/proparse/src/test/java/org/prorefactor/core/util/StatementFlowWriter.java b/proparse/src/test/java/org/prorefactor/core/util/StatementFlowWriter.java new file mode 100644 index 000000000..7e3813aa7 --- /dev/null +++ b/proparse/src/test/java/org/prorefactor/core/util/StatementFlowWriter.java @@ -0,0 +1,85 @@ +/******************************************************************************** + * Copyright (c) 2015-2021 Riverside Software + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0 + * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt + * + * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0 + ********************************************************************************/ +package org.prorefactor.core.util; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import org.prorefactor.core.JPNode; +import org.prorefactor.core.nodetypes.IStatement; +import org.prorefactor.core.nodetypes.IStatementBlock; +import org.prorefactor.refactor.RefactorSession; +import org.prorefactor.treeparser.ParseUnit; +import org.prorefactor.treeparser.TreeParserSymbolScope; + +public class StatementFlowWriter { + + BufferedWriter writer = null; + + /** + * Parse and write a source file, with comments detailing some of the node attributes added by TreeParser01. + * + * @param inName Name of the compile unit's source file. + * @param outName Name of the file to write out to. + * @throws IOException + */ + public void write(String inName, File outName, RefactorSession session) throws IOException { + try { + ParseUnit pu = new ParseUnit(new File(inName), session); + pu.treeParser01(); + writer = new BufferedWriter(new FileWriter(outName)); + walker(pu.getTopNode().asIStatementBlock(), null, 0); + writer.newLine(); + } finally { + if (writer != null) + writer.close(); + } + } + + private void walker(IStatementBlock node, TreeParserSymbolScope scope, int level) throws IOException { + writeNode(node.asJPNode(), scope, level); + + IStatement ch = node.getFirstStatement(); + while (ch != null) { + if (ch.asJPNode().isIStatementBlock()) { + walker(ch.asJPNode().asIStatementBlock(), node.asJPNode().hasBlock() ? node.asJPNode().getBlock().getSymbolScope() : scope, level + 2); + } else { + writeNode(ch.asJPNode(), scope, level + 2); + } + ch = ch.getNextStatement(); + } + } + + private void writeNode(JPNode node, TreeParserSymbolScope scope, int level) throws IOException { + writer.write(indent(level)); + writer.write(node.getNodeType().toString()); + writer.write(" "); + writer.write(node.getPositionString()); + + if (node.hasBlock()) { + writer.write(" -- Block"); + if (node.hasBlock() && (node.getBlock().getSymbolScope() != scope)) + writer.write(" -- Scope"); + } + writer.newLine(); + } + + private String indent(int level) { + return java.nio.CharBuffer.allocate(level).toString().replace('\0', ' '); + } + +} diff --git a/proparse/src/test/resources/treeparser06-expect/test01.p b/proparse/src/test/resources/treeparser06-expect/test01.p new file mode 100644 index 000000000..a945d5269 --- /dev/null +++ b/proparse/src/test/resources/treeparser06-expect/test01.p @@ -0,0 +1,49 @@ +PROGRAM_ROOT F0/0:0 -- Block -- Scope + PROCEDURE F0/1:1 -- Block -- Scope + IF F0/2:3 + THEN F0/2:11 + DO F0/2:16 -- Block + IF F0/3:5 + THEN F0/3:33 + DO F0/3:38 -- Block + MESSAGE F0/4:7 + ELSE F0/6:5 + MESSAGE F0/6:10 + MESSAGE F0/8:3 + DEFINE F0/11:1 + CASE F0/12:3 + WHEN F0/13:5 + THEN F0/13:12 + RETURN F0/13:17 + WHEN F0/14:5 + THEN F0/14:12 + RETURN F0/14:17 + WHEN F0/15:5 + THEN F0/15:12 + DO F0/15:17 -- Block + MESSAGE F0/16:7 + RETURN F0/17:7 + OTHERWISE F0/19:5 + RETURN F0/19:15 + IF F0/22:1 + THEN F0/22:9 + CASE F0/23:3 + WHEN F0/24:5 + THEN F0/24:12 + RETURN F0/24:17 + WHEN F0/25:5 + THEN F0/25:12 + RETURN F0/25:17 + OTHERWISE F0/26:5 + RETURN F0/26:15 + ELSE F0/28:1 + CASE F0/29:3 + WHEN F0/30:5 + THEN F0/30:12 + RETURN F0/30:17 + WHEN F0/31:5 + THEN F0/31:12 + RETURN F0/31:17 + OTHERWISE F0/32:5 + RETURN F0/32:15 + diff --git a/proparse/src/test/resources/treeparser06/test01.p b/proparse/src/test/resources/treeparser06/test01.p new file mode 100644 index 000000000..8c2afa2e0 --- /dev/null +++ b/proparse/src/test/resources/treeparser06/test01.p @@ -0,0 +1,33 @@ +procedure p1: + if true then do: + if can-find(first customer) then do: + message "1". + end. + else message "2". + end. + message "2". +end. + +def var xx as int. + case xx: + when 1 then return '0'. + when 2 then return '1'. + when 3 then do: + message 'xx'. + return '2'. + end. + otherwise return '-1'. + end case. + +if true then + case xx: + when 1 then return 0. + when 2 then return 1. + otherwise return -1. + end case. +else + case xx: + when 1 then return 0. + when 2 then return 1. + otherwise return -1. + end case. From cf03cd3fc1a502f557190a54e9685df3688dc41e Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Wed, 22 Sep 2021 13:16:49 +0200 Subject: [PATCH 13/15] Temporary fix: THEN and ELSE excluded from JPNode#queryStateHead() --- proparse/src/main/java/org/prorefactor/core/JPNodeQuery.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proparse/src/main/java/org/prorefactor/core/JPNodeQuery.java b/proparse/src/main/java/org/prorefactor/core/JPNodeQuery.java index 54fb52c11..94324f967 100644 --- a/proparse/src/main/java/org/prorefactor/core/JPNodeQuery.java +++ b/proparse/src/main/java/org/prorefactor/core/JPNodeQuery.java @@ -61,7 +61,7 @@ public boolean visitNode(JPNode node) { if (mainFileOnly && (node.getFileIndex() > 0)) return true; - if (stateHeadOnly && !node.isStateHead()) + if (stateHeadOnly && (!node.isStateHead() || (node.getNodeType() == ABLNodeType.THEN) || (node.getNodeType() == ABLNodeType.ELSE))) return true; if (findTypes.isEmpty() || findTypes.contains(node.getNodeType())) { From f8355594add08fe13a012d742881a051cf460b5c Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Wed, 22 Sep 2021 14:36:24 +0200 Subject: [PATCH 14/15] Test case for issue #911 --- .../org/prorefactor/core/PreprocessorVariablesTest.java | 9 +++++++++ .../test/resources/data/preprocessor/preprocessor24.i | 2 ++ .../test/resources/data/preprocessor/preprocessor24.p | 1 + 3 files changed, 12 insertions(+) create mode 100644 proparse/src/test/resources/data/preprocessor/preprocessor24.i create mode 100644 proparse/src/test/resources/data/preprocessor/preprocessor24.p diff --git a/proparse/src/test/java/org/prorefactor/core/PreprocessorVariablesTest.java b/proparse/src/test/java/org/prorefactor/core/PreprocessorVariablesTest.java index f747a3c77..c77659cb4 100644 --- a/proparse/src/test/java/org/prorefactor/core/PreprocessorVariablesTest.java +++ b/proparse/src/test/java/org/prorefactor/core/PreprocessorVariablesTest.java @@ -97,4 +97,13 @@ public void test08() { Assert.assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.DEFINE).size(), 0); } + @Test(enabled = false) + public void test24() { + // Valid ABL code, but not recognized by Proparse (issue #911) + ParseUnit unit = new ParseUnit(new File(SRC_DIR, "preprocessor24.p"), session); + unit.parse(); + assertFalse(unit.hasSyntaxError()); + Assert.assertEquals(unit.getTopNode().queryStateHead(ABLNodeType.MESSAGE).size(), 2); + } + } diff --git a/proparse/src/test/resources/data/preprocessor/preprocessor24.i b/proparse/src/test/resources/data/preprocessor/preprocessor24.i new file mode 100644 index 000000000..6198c4858 --- /dev/null +++ b/proparse/src/test/resources/data/preprocessor/preprocessor24.i @@ -0,0 +1,2 @@ +message {¶m}. +message "Hello". diff --git a/proparse/src/test/resources/data/preprocessor/preprocessor24.p b/proparse/src/test/resources/data/preprocessor/preprocessor24.p new file mode 100644 index 000000000..8eee7f50c --- /dev/null +++ b/proparse/src/test/resources/data/preprocessor/preprocessor24.p @@ -0,0 +1 @@ +{ preprocessor/preprocessor24.i ¶m = ~""x(16)~"":U }. From bc6d3253e975495de1e247dd8d13b087d637373b Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Wed, 22 Sep 2021 16:40:30 +0200 Subject: [PATCH 15/15] Prepare 2.14.3 --- coverage-report/pom.xml | 16 ++++++++-------- database-parser/pom.xml | 2 +- listing-parser/pom.xml | 2 +- openedge-checks/pom.xml | 6 +++--- openedge-plugin/pom.xml | 8 ++++---- pom.xml | 2 +- profiler-parser/pom.xml | 2 +- proparse/pom.xml | 4 ++-- rcode-reader/pom.xml | 2 +- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/coverage-report/pom.xml b/coverage-report/pom.xml index f9be460cd..04e860c44 100644 --- a/coverage-report/pom.xml +++ b/coverage-report/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers coverage-report - 2.14.3-SNAPSHOT + 2.14.3 JaCoCo report Fake module for code coverage report in SonarQube @@ -20,37 +20,37 @@ eu.rssw.openedge.rcode rcode-reader - 2.14.3-SNAPSHOT + 2.14.3 eu.rssw.sonar.openedge sonar-openedge-plugin - 2.14.3-SNAPSHOT + 2.14.3 eu.rssw.openedge.parsers proparse - 2.14.3-SNAPSHOT + 2.14.3 eu.rssw.openedge.parsers profiler-parser - 2.14.3-SNAPSHOT + 2.14.3 eu.rssw.openedge.parsers database-parser - 2.14.3-SNAPSHOT + 2.14.3 eu.rssw.openedge.parsers listing-parser - 2.14.3-SNAPSHOT + 2.14.3 eu.rssw.openedge.checks openedge-checks - 2.14.3-SNAPSHOT + 2.14.3 diff --git a/database-parser/pom.xml b/database-parser/pom.xml index f538f7ee2..626086002 100644 --- a/database-parser/pom.xml +++ b/database-parser/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers database-parser - 2.14.3-SNAPSHOT + 2.14.3 OpenEdge database definition lexer and parser OpenEdge dump files parser diff --git a/listing-parser/pom.xml b/listing-parser/pom.xml index 28c1f0fb2..2b6c1bba0 100644 --- a/listing-parser/pom.xml +++ b/listing-parser/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers listing-parser - 2.14.3-SNAPSHOT + 2.14.3 OpenEdge listing so-called parser OpenEdge listing files parser diff --git a/openedge-checks/pom.xml b/openedge-checks/pom.xml index 5ed5c5c3b..c8ebd5549 100644 --- a/openedge-checks/pom.xml +++ b/openedge-checks/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.checks openedge-checks - 2.14.3-SNAPSHOT + 2.14.3 OpenEdge checks OpenEdge checks @@ -55,12 +55,12 @@ eu.rssw.openedge.parsers database-parser - 2.14.3-SNAPSHOT + 2.14.3 eu.rssw.openedge.parsers proparse - 2.14.3-SNAPSHOT + 2.14.3 org.testng diff --git a/openedge-plugin/pom.xml b/openedge-plugin/pom.xml index 8c76d4022..1b8e040a2 100644 --- a/openedge-plugin/pom.xml +++ b/openedge-plugin/pom.xml @@ -4,7 +4,7 @@ eu.rssw.sonar.openedge sonar-openedge-plugin - 2.14.3-SNAPSHOT + 2.14.3 sonar-plugin OpenEdge plugin for SonarQube @@ -60,17 +60,17 @@ eu.rssw.openedge.checks openedge-checks - 2.14.3-SNAPSHOT + 2.14.3 eu.rssw.openedge.parsers listing-parser - 2.14.3-SNAPSHOT + 2.14.3 eu.rssw.openedge.parsers profiler-parser - 2.14.3-SNAPSHOT + 2.14.3 commons-io diff --git a/pom.xml b/pom.xml index 5a605efd8..07444a1be 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge pom - 2.14.3-SNAPSHOT + 2.14.3 OpenEdge plugin for SonarQube http://www.riverside-software.fr/ Open source code analysis for OpenEdge diff --git a/profiler-parser/pom.xml b/profiler-parser/pom.xml index d9931e98b..48af9e4ce 100644 --- a/profiler-parser/pom.xml +++ b/profiler-parser/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers profiler-parser - 2.14.3-SNAPSHOT + 2.14.3 OpenEdge profiler output lexer and parser OpenEdge profiler files parser diff --git a/proparse/pom.xml b/proparse/pom.xml index b9b9b6062..3b50b8224 100644 --- a/proparse/pom.xml +++ b/proparse/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.parsers proparse - 2.14.3-SNAPSHOT + 2.14.3 Proparse ABL code parser @@ -55,7 +55,7 @@ eu.rssw.openedge.rcode rcode-reader - 2.14.3-SNAPSHOT + 2.14.3 org.antlr diff --git a/rcode-reader/pom.xml b/rcode-reader/pom.xml index aec23195c..3a331c3ad 100644 --- a/rcode-reader/pom.xml +++ b/rcode-reader/pom.xml @@ -4,7 +4,7 @@ eu.rssw.openedge.rcode rcode-reader - 2.14.3-SNAPSHOT + 2.14.3 rcode-reader rcode reader