diff --git a/Jenkinsfile b/Jenkinsfile index aa6f60d37..d5b6ccd8e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,7 +23,7 @@ pipeline { } else if (env.BRANCH_NAME.startsWith("release") || env.BRANCH_NAME.startsWith("hotfix")) { sh "$MVN_HOME/bin/mvn clean javadoc:javadoc install -Dmaven.test.failure.ignore=true -Dgit.commit=\$(git rev-parse --short HEAD)" } else { - sh "$MVN_HOME/bin/mvn clean package -Dmaven.test.failure.ignore=true -Dgit.commit=\$(git rev-parse --short HEAD)" + sh "$MVN_HOME/bin/mvn clean verify -Dmaven.test.failure.ignore=true -Dgit.commit=\$(git rev-parse --short HEAD)" } } } diff --git a/coverage-report/pom.xml b/coverage-report/pom.xml index 093e51b55..9b22f452b 100644 --- a/coverage-report/pom.xml +++ b/coverage-report/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers coverage-report @@ -21,37 +21,37 @@ eu.rssw.openedge.rcode rcode-reader - 2.29.1 + 2.30.0 eu.rssw.sonar.openedge sonar-openedge-plugin - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers proparse - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers profiler-parser - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers database-parser - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers listing-parser - 2.29.1 + 2.30.0 eu.rssw.openedge.checks openedge-checks - 2.29.1 + 2.30.0 diff --git a/database-parser/pom.xml b/database-parser/pom.xml index 560ca36eb..393ed1c14 100644 --- a/database-parser/pom.xml +++ b/database-parser/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers database-parser diff --git a/listing-parser/pom.xml b/listing-parser/pom.xml index c9cc762a6..ad7058880 100644 --- a/listing-parser/pom.xml +++ b/listing-parser/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers listing-parser diff --git a/openedge-checks/pom.xml b/openedge-checks/pom.xml index d88343c2f..7c1d2297b 100644 --- a/openedge-checks/pom.xml +++ b/openedge-checks/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge - 2.29.1 + 2.30.0 eu.rssw.openedge.checks openedge-checks @@ -23,12 +23,12 @@ eu.rssw.openedge.parsers database-parser - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers proparse - 2.29.1 + 2.30.0 org.testng diff --git a/openedge-checks/src/main/java/org/sonar/plugins/openedge/api/checks/OpenEdgeProparseCheck.java b/openedge-checks/src/main/java/org/sonar/plugins/openedge/api/checks/OpenEdgeProparseCheck.java index 91606c07c..63c64dbb9 100644 --- a/openedge-checks/src/main/java/org/sonar/plugins/openedge/api/checks/OpenEdgeProparseCheck.java +++ b/openedge-checks/src/main/java/org/sonar/plugins/openedge/api/checks/OpenEdgeProparseCheck.java @@ -109,7 +109,7 @@ protected NewIssue createIssue(InputFile file, ProToken token, String msg, boole NewIssueLocation location = issue.newLocation().on(targetFile); if (lineNumber > 0) { if (exactLocation) { - location.at(targetFile.newRange(token.getLine(), token.getCharPositionInLine() - 1, token.getEndLine(), + location.at(targetFile.newRange(token.getLine(), token.getCharPositionInLine(), token.getEndLine(), token.getEndCharPositionInLine())); } else { TextRange range = targetFile.selectLine(lineNumber); @@ -168,7 +168,7 @@ protected void addLocation(NewIssue issue, InputFile file, JPNode node, String m int lineNumber = naturalChild.getLine(); if (lineNumber > 0) { if (exactLocation) { - location.at(targetFile.newRange(naturalChild.getLine(), naturalChild.getColumn() - 1, + location.at(targetFile.newRange(naturalChild.getLine(), naturalChild.getColumn(), naturalChild.getEndLine(), naturalChild.getEndColumn())); } else { TextRange range = targetFile.selectLine(lineNumber); diff --git a/openedge-plugin/pom.xml b/openedge-plugin/pom.xml index c01b5fc4b..6ecdcdd5d 100644 --- a/openedge-plugin/pom.xml +++ b/openedge-plugin/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge - 2.29.1 + 2.30.0 eu.rssw.sonar.openedge sonar-openedge-plugin @@ -30,17 +30,17 @@ eu.rssw.openedge.checks openedge-checks - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers listing-parser - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers profiler-parser - 2.29.1 + 2.30.0 org.sonarsource.sonarqube diff --git a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/OpenEdgePlugin.java b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/OpenEdgePlugin.java index 7133a27c7..985909b2e 100644 --- a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/OpenEdgePlugin.java +++ b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/OpenEdgePlugin.java @@ -58,11 +58,8 @@ public void define(Context context) { context.addExtensions(OpenEdge.class, OpenEdgeDB.class, OpenEdgeSettings.class); // Profile and rules - if (context.getRuntime().getProduct() == SonarProduct.SONARQUBE) - context.addExtension(OpenEdgeRulesDefinition.class); - - context.addExtensions(BasicChecksRegistration.class, OpenEdgeProfile.class, OpenEdgeDBProfile.class, - OpenEdgeMetrics.class, OpenEdgeComponents.class); + context.addExtensions(OpenEdgeRulesDefinition.class, BasicChecksRegistration.class, OpenEdgeProfile.class, + OpenEdgeDBProfile.class, OpenEdgeMetrics.class, OpenEdgeComponents.class); // Syntax highlight and simple CPD if (context.getRuntime().getProduct() == SonarProduct.SONARQUBE) { diff --git a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/foundation/CPDCallback.java b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/foundation/CPDCallback.java index f24092894..54480e92f 100644 --- a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/foundation/CPDCallback.java +++ b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/foundation/CPDCallback.java @@ -131,7 +131,7 @@ private void visitCpdNode(JPNode node) { } try { - TextRange range = file.newRange(node.getLine(), node.getColumn() - 1, node.getEndLine(), node.getEndColumn()); + TextRange range = file.newRange(node.getLine(), node.getColumn(), node.getEndLine(), node.getEndColumn()); cpdTokens.addToken(range, str); } catch (IllegalArgumentException | IllegalStateException uncaught) { LOG.debug("Unable to create CPD token at position {}:{} to {}:{} - Cause {}", node.getLine(), node.getColumn(), @@ -143,7 +143,7 @@ private void insertFakeNode(JPNode node) { List children = node.getDirectChildren(); JPNode lastSibling = children.isEmpty() ? node : children.get(children.size() - 1); try { - TextRange range = file.newRange(node.getLine(), node.getColumn() - 1, lastSibling.getEndLine(), lastSibling.getEndColumn() - 1); + TextRange range = file.newRange(node.getLine(), node.getColumn(), lastSibling.getEndLine(), lastSibling.getEndColumn()); cpdTokens.addToken(range, UUID.randomUUID().toString()); } catch (IllegalArgumentException | IllegalStateException uncaught) { LOG.debug("Unable to create CPD token at position {}:{} to {}:{} - Cause {}", node.getLine(), node.getColumn(), diff --git a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeCPDSensor.java b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeCPDSensor.java index ddd2b0e63..a1c9a0c8b 100644 --- a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeCPDSensor.java +++ b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeCPDSensor.java @@ -136,7 +136,7 @@ private static void processToken(InputFile file, NewCpdTokens cpdTokens, ProToke } try { - TextRange range = file.newRange(tok.getLine(), tok.getCharPositionInLine() - 1, tok.getEndLine(), + TextRange range = file.newRange(tok.getLine(), tok.getCharPositionInLine(), tok.getEndLine(), tok.getEndCharPositionInLine()); cpdTokens.addToken(range, str); } catch (IllegalArgumentException | IllegalStateException uncaught) { diff --git a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeCodeColorizer.java b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeCodeColorizer.java index 91f9bd559..ed3e73b63 100644 --- a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeCodeColorizer.java +++ b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeCodeColorizer.java @@ -117,7 +117,7 @@ private void highlightFile(SensorContext context, IProparseEnvironment session, if (textType != null) { try { - TextPointer start = file.newPointer(tok.getLine(), tok.getCharPositionInLine() - 1); + TextPointer start = file.newPointer(tok.getLine(), tok.getCharPositionInLine()); int maxChar = file.selectLine(tok.getEndLine()).end().lineOffset(); TextPointer end = file.newPointer(tok.getEndLine(), maxChar < tok.getEndCharPositionInLine() ? (maxChar > 0 ? maxChar - 1 : 0) : tok.getEndCharPositionInLine()); diff --git a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeProparseSensor.java b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeProparseSensor.java index d19f142f4..03e93b580 100644 --- a/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeProparseSensor.java +++ b/openedge-plugin/src/main/java/org/sonar/plugins/openedge/sensor/OpenEdgeProparseSensor.java @@ -349,8 +349,8 @@ private void parseMainFile(SensorContext context, InputFile file, IProparseEnvir TextPointer end = null; if (InputFileUtils.getRelativePath(file, context.fileSystem()).equals(tok.getFileName())) { try { - strt = file.newPointer(tok.getLine(), tok.getCharPositionInLine() - 1); - end = file.newPointer(tok.getLine(), tok.getCharPositionInLine()); + strt = file.newPointer(tok.getLine(), tok.getCharPositionInLine()); + end = file.newPointer(tok.getLine(), tok.getEndCharPositionInLine()); } catch (IllegalArgumentException uncaught) { // Nothing } diff --git a/openedge-plugin/src/test/java/org/sonar/plugins/openedge/OpenEdgePluginTest.java b/openedge-plugin/src/test/java/org/sonar/plugins/openedge/OpenEdgePluginTest.java index 6a1c755aa..3af0ce6c0 100644 --- a/openedge-plugin/src/test/java/org/sonar/plugins/openedge/OpenEdgePluginTest.java +++ b/openedge-plugin/src/test/java/org/sonar/plugins/openedge/OpenEdgePluginTest.java @@ -49,7 +49,7 @@ public class OpenEdgePluginTest { public void testExtensionsSonarLint() { Plugin.Context context = new Plugin.Context(SONARLINT_RUNTIME); new OpenEdgePlugin().define(context); - assertEquals(context.getExtensions().size(), 26); + assertEquals(context.getExtensions().size(), 27); } @Test diff --git a/pom.xml b/pom.xml index 7503474ae..be05e6f3b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge - 2.29.1 + 2.30.0 pom OpenEdge plugin for SonarQube diff --git a/profiler-parser/pom.xml b/profiler-parser/pom.xml index de701ba90..5bd18e357 100644 --- a/profiler-parser/pom.xml +++ b/profiler-parser/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers profiler-parser diff --git a/proparse/pom.xml b/proparse/pom.xml index af2ea8c92..b18b95d37 100644 --- a/proparse/pom.xml +++ b/proparse/pom.xml @@ -5,7 +5,7 @@ eu.rssw sonar-openedge - 2.29.1 + 2.30.0 eu.rssw.openedge.parsers proparse @@ -22,7 +22,7 @@ eu.rssw.openedge.rcode rcode-reader - 2.29.1 + 2.30.0 org.antlr 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 dc72d43cc..644eedca8 100644 --- a/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 +++ b/proparse/src/main/antlr4/org/prorefactor/proparse/antlr4/Proparse.g4 @@ -755,6 +755,10 @@ widgetname: identifier ; +queryIdentifier: + identifier + ; + identifier: // identifier gets us an ID node for an unqualified (local) reference. // Only an ID or unreservedkeyword can be used as an unqualified reference. @@ -1173,7 +1177,7 @@ clearStatement: ; closeQueryStatement: - CLOSE QUERY identifier statementEnd + CLOSE QUERY queryIdentifier statementEnd ; closeStoredProcedureStatement: @@ -1851,12 +1855,12 @@ definePropertyAccessorSetBlock: defineQueryStatement: DEFINE defineShare? ( PRIVATE | PROTECTED | STATIC )* - QUERY n=identifier + QUERY id=identifier FOR record recordFields? ( COMMA record recordFields? )* ( cacheExpr | SCROLLING | RCODEINFORMATION )* statementEnd - { support.defVar($n.text); } + { support.defVar($id.text); } ; defineRectangleStatement: @@ -2514,7 +2518,7 @@ externalFunctionStatement: ; getStatement: - GET findWhich identifier ( lockHow | NOWAIT )* statementEnd + GET findWhich queryIdentifier ( lockHow | NOWAIT )* statementEnd ; getKeyValueStatement: @@ -2960,7 +2964,7 @@ onAction: ; openQueryStatement: - OPEN QUERY identifier ( FOR | PRESELECT ) multiRecordSearch + OPEN QUERY queryIdentifier ( FOR | PRESELECT ) multiRecordSearch openQueryOption* statementEnd ; @@ -3268,7 +3272,7 @@ releaseObjectStatement: ; repositionStatement: - REPOSITION identifier repositionOption NOERROR? statementEnd + REPOSITION queryIdentifier repositionOption NOERROR? statementEnd ; repositionOption: diff --git a/proparse/src/main/java/org/prorefactor/core/Pair.java b/proparse/src/main/java/org/prorefactor/core/Pair.java deleted file mode 100644 index 4ad410439..000000000 --- a/proparse/src/main/java/org/prorefactor/core/Pair.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * ABL Language Server implementation - * - * This source code is not part of an open-source package. - * Copyright (c) 2021-2024 Riverside Software - * contact@riverside-software.fr - */ -package org.prorefactor.core; - -public class Pair { - private final X o1; - private final Y o2; - - public Pair(X o1, Y o2) { - this.o1 = o1; - this.o2 = o2; - } - - public static Pair of(A x, B y) { - return new Pair<>(x, y); - } - - public X getO1() { - return o1; - } - - public Y getO2() { - return o2; - } -} diff --git a/proparse/src/main/java/org/prorefactor/core/ProToken.java b/proparse/src/main/java/org/prorefactor/core/ProToken.java index d56d7a2ae..5ddab3ad3 100644 --- a/proparse/src/main/java/org/prorefactor/core/ProToken.java +++ b/proparse/src/main/java/org/prorefactor/core/ProToken.java @@ -77,12 +77,6 @@ public int getLine() { return line; } - /** - * The index of the first character of this token relative to the beginning of the line at which it occurs. - * - * IMPORTANT: While the ANTLR4 Token interface specifies that charPositionInLine should start at 0, the ProToken - * implementation starts at 1. This implementation detail might change in the future (if that's not too late). - */ @Override public int getCharPositionInLine() { return charPositionInLine; @@ -150,9 +144,7 @@ public int getEndLine() { } /** - * The index of the last character of this token relative to the beginning of the line at which it occurs. This means - * that the first character of next token will be at this position + 1. Also means that getCharPositionInLine() == - * getEndCharPositionInLine() for single-character tokens. + * Line offset **after** the last character of the token */ public int getEndCharPositionInLine() { return endCharPositionInLine; 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 80164861f..5aad79824 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/ExpressionNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/ExpressionNode.java @@ -19,6 +19,7 @@ import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.JPNode; +import org.prorefactor.core.Pair; import org.prorefactor.core.ProToken; import org.prorefactor.proparse.support.IProparseEnvironment; @@ -733,6 +734,7 @@ static DataType getStandardAttributeDataType(String id) { static DataType getStandardMethodDataType(String id) { switch (id) { case "ADD-NEW-FIELD": + case "ADD-SUPER-PROCEDURE": return DataType.LOGICAL; // TODO Full list default: @@ -740,7 +742,8 @@ static DataType getStandardMethodDataType(String id) { } } - static DataType getObjectMethodDataType(Function provider, JPNode node, ITypeInfo info, String methodName) { + static Pair getObjectMethod(Function provider, JPNode node, ITypeInfo info, + String methodName) { // Create array of dataTypes List paramItems = node.getDirectChildren(ABLNodeType.PARAMETER_ITEM); DataType[] params = new DataType[paramItems.size()]; @@ -755,12 +758,7 @@ static DataType getObjectMethodDataType(Function provider, JP params[zz++] = dt; } - if (info != null) { - IMethodElement methd = info.getMethod(provider, methodName, params); - return methd == null ? DataType.NOT_COMPUTED : methd.getReturnType(); - } else { - return DataType.NOT_COMPUTED; - } + return info == null ? null : info.getMethod(provider, methodName, params); } static DataType getObjectAttributeDataType(IProparseEnvironment session, ITypeInfo info, String propName, 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 33d7b7c85..f8404756f 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/LocalMethodCallNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/LocalMethodCallNode.java @@ -15,19 +15,23 @@ package org.prorefactor.core.nodetypes; import org.prorefactor.core.JPNode; +import org.prorefactor.core.Pair; import org.prorefactor.core.ProToken; import com.google.common.base.Strings; import eu.rssw.pct.elements.BuiltinClasses; import eu.rssw.pct.elements.DataType; +import eu.rssw.pct.elements.IMethodElement; import eu.rssw.pct.elements.ITypeInfo; /** * Expression node: methodName(parameters) (only in classes) */ public class LocalMethodCallNode extends ExpressionNode { - private String methodName = ""; + private final String methodName; + private boolean computed = false; + private Pair method = null; public LocalMethodCallNode(ProToken t, JPNode parent, int num, boolean hasChildren, String methodName) { super(t, parent, num, hasChildren); @@ -38,17 +42,36 @@ public String getMethodName() { return methodName; } - @Override - public DataType getDataType() { + private void compute() { ProgramRootNode root = getTopLevelParent(); - if (root == null) - return DataType.NOT_COMPUTED; + if (root != null) { + ITypeInfo typeInfo = root.getTypeInfo(); + if (root.isClass() && (typeInfo == null)) + typeInfo = BuiltinClasses.PROGRESS_LANG_OBJECT; + method = typeInfo == null ? null : getObjectMethod(root.getTypeInfoProvider(), this, typeInfo, methodName); + } + } + + public synchronized ITypeInfo getTypeInfo() { + if (!computed) { + compute(); + computed = true; + } + return method == null ? null : method.getO1(); + } - ITypeInfo info = root.getTypeInfo(); - if (root.isClass() && (info == null)) - info = BuiltinClasses.PROGRESS_LANG_OBJECT; + public synchronized IMethodElement getMethodElement() { + if (!computed) { + compute(); + computed = true; + } + return method == null ? null : method.getO2(); + } - return getObjectMethodDataType(root.getTypeInfoProvider(), this, info, methodName); + @Override + public DataType getDataType() { + IMethodElement tmp = getMethodElement(); + return tmp == null ? DataType.NOT_COMPUTED : tmp.getReturnType(); } } 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 0bc1f7630..1ab7cce0d 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/MethodCallNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/MethodCallNode.java @@ -16,12 +16,14 @@ import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.JPNode; +import org.prorefactor.core.Pair; import org.prorefactor.core.ProToken; import org.prorefactor.treeparser.symbols.Event; import com.google.common.base.Strings; import eu.rssw.pct.elements.DataType; +import eu.rssw.pct.elements.IMethodElement; import eu.rssw.pct.elements.ITypeInfo; import eu.rssw.pct.elements.PrimitiveDataType; @@ -29,7 +31,10 @@ * Expression node: <expr>:methodName(parameters) */ public class MethodCallNode extends ExpressionNode { - private String methodName = ""; + private final String methodName; + private boolean computed = false; + private Pair method = null; + private DataType returnDataType = DataType.NOT_COMPUTED; public MethodCallNode(ProToken t, JPNode parent, int num, boolean hasChildren, String methodName) { super(t, parent, num, hasChildren); @@ -40,51 +45,103 @@ public String getMethodName() { return methodName; } - @Override - public DataType getDataType() { - ProgramRootNode root = getTopLevelParent(); - if (root == null) - return DataType.NOT_COMPUTED; - - if (getFirstChild() instanceof SystemHandleNode) { - SystemHandleNode shn = (SystemHandleNode) getFirstChild(); - return shn.getMethodDataType(methodName.toUpperCase()); - } else if (getFirstChild() instanceof FieldRefNode) { - if (((FieldRefNode) getFirstChild()).isStaticReference()) { - ITypeInfo info = ((FieldRefNode) getFirstChild()).getStaticReference(); - return getObjectMethodDataType(root.getTypeInfoProvider(), findDirectChild(ABLNodeType.METHOD_PARAM_LIST), info, - methodName); - } else if ((getFirstChild().getSymbol() instanceof Event) - && ("publish".equalsIgnoreCase(methodName) || "subscribe".equalsIgnoreCase(methodName))) { - // Events only have Publish / Subscribe - return DataType.VOID; - } + private void handleSystemHandleNode(SystemHandleNode node, ProgramRootNode root) { + if (node.getFirstChild().getNodeType() == ABLNodeType.THISOBJECT) { + ITypeInfo typeInfo = root.getEnvironment().getTypeInfo(root.getClassName()); + method = typeInfo == null ? null : getObjectMethod(root.getTypeInfoProvider(), + this.findDirectChild(ABLNodeType.METHOD_PARAM_LIST), typeInfo, methodName); + returnDataType = method == null ? DataType.NOT_COMPUTED : method.getO2().getReturnType(); + } else if (node.getFirstChild().getNodeType() == ABLNodeType.SUPER) { + ITypeInfo info = root.getEnvironment().getTypeInfo(root.getClassName()); + info = info == null ? null : root.getEnvironment().getTypeInfo(info.getParentTypeName()); + method = info == null ? null : getObjectMethod(root.getTypeInfoProvider(), + this.findDirectChild(ABLNodeType.METHOD_PARAM_LIST), info, methodName); + returnDataType = method == null ? DataType.NOT_COMPUTED : method.getO2().getReturnType(); + } else { + returnDataType = node.getMethodDataType(methodName.toUpperCase()); } + } - // Left-Handle expression has to be a class - IExpression expr = getFirstChild().asIExpression(); - if (expr != null) { - DataType dataType = expr.getDataType(); - if (dataType.getPrimitive() == PrimitiveDataType.CLASS) { - ITypeInfo info = root.getEnvironment().getTypeInfo(dataType.getClassName()); - return getObjectMethodDataType(getTopLevelParent().getTypeInfoProvider(), - findDirectChild(ABLNodeType.METHOD_PARAM_LIST), info, methodName); - } else if (dataType.getPrimitive() == PrimitiveDataType.HANDLE) { - return getStandardMethodDataType(methodName.toUpperCase()); + private void handleFieldRefNode(FieldRefNode node, ProgramRootNode root) { + if (node.isStaticReference()) { + method = getObjectMethod(root.getTypeInfoProvider(), findDirectChild(ABLNodeType.METHOD_PARAM_LIST), node.getStaticReference(), + methodName); + returnDataType = method == null ? DataType.NOT_COMPUTED : method.getO2().getReturnType(); + } else if ((node.getSymbol() instanceof Event) + && ("publish".equalsIgnoreCase(methodName) || "subscribe".equalsIgnoreCase(methodName))) { + // Events only have Publish / Subscribe + returnDataType = DataType.VOID; + } else if (node.isIExpression()) { + handleExpression(node.asIExpression(), root); + } + } + + private void handleExpression(IExpression expr, ProgramRootNode root) { + DataType dataType = expr.getDataType(); + if (dataType.getPrimitive() == PrimitiveDataType.CLASS) { + ITypeInfo typeInfo = root.getEnvironment().getTypeInfo(dataType.getClassName()); + method = typeInfo == null ? null : getObjectMethod(getTopLevelParent().getTypeInfoProvider(), + findDirectChild(ABLNodeType.METHOD_PARAM_LIST), typeInfo, methodName); + returnDataType = method == null ? DataType.NOT_COMPUTED : method.getO2().getReturnType(); + } else if (dataType.getPrimitive() == PrimitiveDataType.HANDLE) { + returnDataType = getStandardMethodDataType(methodName.toUpperCase()); + } + } + + private void handleNonExpression(JPNode firstChild, ProgramRootNode root) { + // Within constructor: super(...) or this-object(...) + JPNode nextChild = firstChild.getNextSibling(); + if (((firstChild.getNodeType() == ABLNodeType.SUPER) || (firstChild.getNodeType() == ABLNodeType.THISOBJECT)) + && (nextChild.getNodeType() == ABLNodeType.LEFTPAREN)) { + if (root.getTypeInfo() == null) { + returnDataType = new DataType(root.getRootScope().getClassName()); + } else { + returnDataType = new DataType(root.getTypeInfo().getTypeName()); } + } + } + + private void compute() { + // Default + ProgramRootNode root = getTopLevelParent(); + if (root == null) + return; + + JPNode firstChild = getFirstChild(); + if (firstChild instanceof SystemHandleNode) { + handleSystemHandleNode((SystemHandleNode) firstChild, root); + } else if (firstChild instanceof FieldRefNode) { + handleFieldRefNode((FieldRefNode) firstChild, root); + } else if (firstChild.isIExpression()) { + handleExpression(firstChild.asIExpression(), root); } else { - // Within constructor: super(...) or this-object(...) - JPNode firstChild = getFirstChild(); - JPNode nextChild = firstChild.getNextSibling(); - if (((firstChild.getNodeType() == ABLNodeType.SUPER) || (firstChild.getNodeType() == ABLNodeType.THISOBJECT)) - && (nextChild.getNodeType() == ABLNodeType.LEFTPAREN)) { - if (root.getTypeInfo() == null) - return new DataType(root.getRootScope().getClassName()); - else - return new DataType(root.getTypeInfo().getTypeName()); - } + handleNonExpression(firstChild, root); + } + } + + public synchronized ITypeInfo getTypeInfo() { + if (!computed) { + compute(); + computed = true; + } + return method == null ? null : method.getO1(); + } + + @Override + public synchronized DataType getDataType() { + if (!computed) { + compute(); + computed = true; + } + return returnDataType; + } + + public synchronized IMethodElement getMethodElement() { + if (!computed) { + compute(); + computed = true; } - return DataType.NOT_COMPUTED; + return method == null ? null : method.getO2(); } } 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 f8c3f3790..e42baf84c 100644 --- a/proparse/src/main/java/org/prorefactor/core/nodetypes/SystemHandleNode.java +++ b/proparse/src/main/java/org/prorefactor/core/nodetypes/SystemHandleNode.java @@ -16,9 +16,11 @@ import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.JPNode; +import org.prorefactor.core.Pair; import org.prorefactor.core.ProToken; import eu.rssw.pct.elements.DataType; +import eu.rssw.pct.elements.IMethodElement; import eu.rssw.pct.elements.ITypeInfo; /** @@ -299,8 +301,11 @@ private DataType getSuperMethodDataType(String id) { if ((info == null) || (info.getParentTypeName() == null)) return DataType.NOT_COMPUTED; info = root.getEnvironment().getTypeInfo(info.getParentTypeName()); - return getObjectMethodDataType(root.getTypeInfoProvider(), + if (info == null) + return DataType.NOT_COMPUTED; + Pair elem = getObjectMethod(root.getTypeInfoProvider(), this.getParent().findDirectChild(ABLNodeType.METHOD_PARAM_LIST), info, id); + return elem == null ? DataType.NOT_COMPUTED : elem.getO2().getReturnType(); } private DataType getThisObjectAttributeDataType(String id) { @@ -320,8 +325,9 @@ private DataType getThisObjectMethodDataType(String id) { ITypeInfo info = root.getTypeInfo(); if (info == null) return DataType.NOT_COMPUTED; - return getObjectMethodDataType(root.getTypeInfoProvider(), + Pair elem = getObjectMethod(root.getTypeInfoProvider(), this.getParent().findDirectChild(ABLNodeType.METHOD_PARAM_LIST), info, id); + return elem == null ? DataType.NOT_COMPUTED : elem.getO2().getReturnType(); } private DataType getWebContextMethodDataType(String id) { diff --git a/proparse/src/main/java/org/prorefactor/proparse/InputSource.java b/proparse/src/main/java/org/prorefactor/proparse/InputSource.java index 85b5344d5..dfd9da23f 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/InputSource.java +++ b/proparse/src/main/java/org/prorefactor/proparse/InputSource.java @@ -52,7 +52,7 @@ public class InputSource { private final int fileIndex; private final boolean macroExpansion; - private int nextCol = 1; + private int nextCol = 0; private int nextLine = 1; private int currPos; private String currAnalyzeSuspend = null; @@ -122,7 +122,7 @@ public int get() { if (!macroExpansion) { if (currChar == '\n') { nextLine++; - nextCol = 1; + nextCol = 0; } else { nextCol++; } diff --git a/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java b/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java index 6311f9148..c050c4520 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java +++ b/proparse/src/main/java/org/prorefactor/proparse/JPNodeVisitor.java @@ -524,6 +524,11 @@ public Builder visitBlockLabel(BlockLabelContext ctx) { return visitChildren(ctx).changeType(ABLNodeType.BLOCK_LABEL); } + @Override + public Builder visitQueryIdentifier(QueryIdentifierContext ctx) { + return visitChildren(ctx).setRuleNode(ctx); + } + @Override public Builder visitIdentifierUKW(IdentifierUKWContext ctx) { return visitChildren(ctx).changeType(ABLNodeType.ID); diff --git a/proparse/src/main/java/org/prorefactor/proparse/Lexer.java b/proparse/src/main/java/org/prorefactor/proparse/Lexer.java index 10297df8c..ceaa23eef 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/Lexer.java +++ b/proparse/src/main/java/org/prorefactor/proparse/Lexer.java @@ -1236,7 +1236,7 @@ private ProToken makeToken(ABLNodeType type, String text) { .setCharPositionInLine(tokenStartPos.col) // .setEndFileIndex(prevChar.file) // .setEndLine(prevChar.line) // - .setEndCharPositionInLine(prevChar.col) // + .setEndCharPositionInLine(prevChar.col + 1) // .setMacroExpansion(prevMacroExpansion) // .setMacroSourceNum(tokenStartPos.sourceNum) // .setAnalyzeSuspend(getCurrentAnalyzeSuspend()) // @@ -1553,7 +1553,7 @@ private void ppMacroReference() { ppCurrChar = '{'; currentInput = new InputSource(++sourceCounter, refText.substring(1), refPos.file, refPos.line, refPos.col); currentInclude.addInputSource(currentInput); - prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol, "_proparse_"); + prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol + 1, "_proparse_"); } else { // Proparse Directive ppCurrChar = PROPARSE_DIRECTIVE; @@ -1562,7 +1562,7 @@ private void ppMacroReference() { // This will be counted as a source whether picked up here or picked // up as a normal macro ref. ++sourceCounter; - prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol, "_proparse_"); + prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol + 1, "_proparse_"); prepro.getLstListener().macroRefEnd(); } } else if ("{*}".equals(refText)) { @@ -1675,7 +1675,7 @@ else if (cp.chars[cp.pos] == '&') { // include '&' named args // Unlike currline and currcol, currfile is only updated with a push/pop of the input stack. currFile = currentInput.getFileIndex(); currSourceNum = currentInput.getSourceNum(); - prepro.getLstListener().include(refPos.line, refPos.col, currLine, currCol, currFile, includeFilename); + prepro.getLstListener().include(refPos.line, refPos.col, currLine, currCol + 1, currFile, includeFilename); // Add the arguments to the new include object. int argNum = 1; for (IncludeArg incarg : incArgs) { @@ -1699,12 +1699,12 @@ private void ppNewMacroRef(String macroName, FilePos refPos) { // Using this trick: {{&undefined-argument}{&*}} // it is possible to get line breaks into what we // get here as the macroName. See test data bug15.p and bug15.i. - prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol, macroName); + prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol + 1, macroName); ppNewMacroRef2(getArgText(macroName), refPos); } private void ppNewMacroRef(int argNum, FilePos refPos) { - prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol, Integer.toString(argNum)); + prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol + 1, Integer.toString(argNum)); ppNewMacroRef2(getArgText(argNum), refPos); } @@ -1759,22 +1759,18 @@ private int ppPopInput() { * If not a doublequote, we collect characters until we find a whitespace */ private String ppIncludeRefArg(MacroCharPos cp, boolean numberedArg) { - StringBuilder retVal = new StringBuilder(); - boolean gobbleWS = false; - char c = cp.chars[cp.pos]; - - if (!numberedArg) { - if (c == '"') { - gobbleWS = true; - } else { - retVal.append(c); - } - cp.pos++; + // Handle empty string in double quotes followed by space in a different way depending on numberedArg value + if ((cp.pos <= cp.chars.length - 4) && (cp.chars[cp.pos] == '"') && (cp.chars[cp.pos + 1] == '"') + && Character.isWhitespace(cp.chars[cp.pos + 2])) { + cp.pos += 2; + return numberedArg ? "\"" : ""; } + StringBuilder retVal = new StringBuilder(); + boolean gobbleWS = false; // Iterate up to, but not including, closing curly while (cp.pos < cp.chars.length - 1) { - c = cp.chars[cp.pos]; + char c = cp.chars[cp.pos]; switch (c) { case '"': if (cp.chars[cp.pos + 1] == '"') { diff --git a/proparse/src/main/java/org/prorefactor/treeparser/ParseUnit.java b/proparse/src/main/java/org/prorefactor/treeparser/ParseUnit.java index 2222fd46a..8c0dec255 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/ParseUnit.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/ParseUnit.java @@ -45,6 +45,7 @@ import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.prorefactor.core.ABLNodeType; import org.prorefactor.core.IConstants; +import org.prorefactor.core.JPNode; import org.prorefactor.core.JPNodeMetrics; import org.prorefactor.core.nodetypes.ProgramRootNode; import org.prorefactor.core.nodetypes.RecordNameNode; @@ -272,6 +273,40 @@ public String getIncludeFileName(int index) { return MacroLevel.sourceArray(macroGraph); } + /** + * Return total number of ParseTree objects (ANTLR4 output) in this unit + */ + public long getParseTreeSize() { + return sizeOfParseTree(tree); + } + + private static long sizeOfParseTree(ParseTree tree) { + if (tree == null) + return 0L; + long sz = 1; + for (int zz = 0; zz < tree.getChildCount(); zz++) { + sz += sizeOfParseTree(tree.getChild(zz)); + } + return sz; + } + + /** + * Return total number of JPNode in this unit + */ + public long getJPNodeSize() { + return sizeOfJPNode(topNode); + } + + private static long sizeOfJPNode(JPNode tree) { + if (tree == null) + return 0L; + long sz = 1; + for (JPNode n : tree.getDirectChildren()) { + sz += sizeOfJPNode(n); + } + return sz; + } + /** * Returns a TokenSource object for the main file. Include files are not expanded, and preprocessor is not used * diff --git a/proparse/src/main/java/org/prorefactor/treeparser/SymbolFactory.java b/proparse/src/main/java/org/prorefactor/treeparser/SymbolFactory.java index 9db5801a2..93d5bff36 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/SymbolFactory.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/SymbolFactory.java @@ -65,8 +65,7 @@ public static Symbol create(ABLNodeType symbolType, String name, TreeParserSymbo case SUBMENU: return new Submenu(name, scope); default: - assert false : "Unexpected values for SymbolFactory" + " " + symbolType + " " + name; - return null; + throw new IllegalArgumentException("Unexpected " + symbolType + " node type for SymbolFactory#create()"); } } diff --git a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserComputeReferences.java b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserComputeReferences.java index f52265fda..6937009f8 100644 --- a/proparse/src/main/java/org/prorefactor/treeparser/TreeParserComputeReferences.java +++ b/proparse/src/main/java/org/prorefactor/treeparser/TreeParserComputeReferences.java @@ -29,12 +29,16 @@ import org.prorefactor.proparse.antlr4.Proparse.FieldContext; import org.prorefactor.proparse.antlr4.Proparse.ParameterArgDatasetHandleContext; import org.prorefactor.proparse.antlr4.Proparse.ParameterArgTableHandleContext; +import org.prorefactor.proparse.antlr4.Proparse.QueryIdentifierContext; import org.prorefactor.proparse.antlr4.Proparse.RecordContext; import org.prorefactor.proparse.antlr4.Proparse.WidNameContext; import org.prorefactor.treeparser.symbols.FieldBuffer; +import org.prorefactor.treeparser.symbols.Query; import org.prorefactor.treeparser.symbols.TableBuffer; import org.prorefactor.treeparser.symbols.Variable; +import eu.rssw.pct.elements.DataType; + public class TreeParserComputeReferences extends AbstractBlockProparseListener { @Inject @@ -60,7 +64,6 @@ public void exitParameterArgDatasetHandle(ParameterArgDatasetHandleContext ctx) @Override public void enterExprTermAttribute(ExprTermAttributeContext ctx) { ContextQualifier cq = contextQualifiers.get(ctx.attributeName().nonPunctuating()); - if (ctx.expressionTerm() instanceof ExprTermOtherContext) { ExprTermOtherContext ctx2 = (ExprTermOtherContext) ctx.expressionTerm(); if (ctx2.expressionTerm2() instanceof Exprt2FieldContext) { @@ -72,6 +75,15 @@ public void enterExprTermAttribute(ExprTermAttributeContext ctx) { } } + @Override + public void enterQueryIdentifier(QueryIdentifierContext ctx) { + Query qry = currentScope.lookupQuery(ctx.identifier().getText()); + JPNode node = support.getNode(ctx); + if ((node != null) && (qry != null)) { + node.setSymbol(qry); + } + } + @Override public void enterWidName(WidNameContext ctx) { if ((ctx.BUFFER() != null) || (ctx.TEMPTABLE() != null)) { @@ -130,19 +142,25 @@ private void noteReference(JPNode node, ContextQualifier cq) { // Called from expressionTerm rule (expressionTerm2 option) and widattr rule (widattrExprt2 option) // Tries to add references to variables/properties of current class, or references to static classes + // And references to current variables / properties through another object reference private void widattr(Exprt2FieldContext ctx2, ContextQualifier cq, String right) { String clsRef = ctx2.field().getText(); String clsName = rootScope.getClassName(); - if ((clsRef != null) && (clsName != null) && (clsRef.indexOf('.') == -1) && (clsName.indexOf('.') != -1)) - clsName = clsName.substring(clsName.lastIndexOf('.') + 1); - if ((clsRef != null) && (clsName != null) && clsRef.equalsIgnoreCase(clsName)) { - FieldLookupResult result = currentBlock.lookupField(right, true); - if (result == null) - return; + boolean isFullStaticRef = (clsRef != null) && clsRef.equalsIgnoreCase(clsName); + boolean isShortStaticRef = (clsRef != null) && (clsRef.indexOf('.') == -1) && (clsName != null) + && clsRef.equalsIgnoreCase(clsName.substring(clsName.lastIndexOf('.') + 1)); + boolean isStaticRef = isFullStaticRef || isShortStaticRef; - // Variable - if (result.getSymbol() instanceof Variable) { + JPNode fieldNode = support.getNode(ctx2.field()); + boolean isExpr = (fieldNode != null) && fieldNode.isIExpression(); + DataType dt = isExpr ? fieldNode.asIExpression().getDataType() : null; + boolean isRefToCurrentClass = (dt != null) && (dt.getClassName() != null) + && (dt.getClassName().equalsIgnoreCase(rootScope.getClassName())); + + if (isStaticRef || isRefToCurrentClass) { + FieldLookupResult result = currentBlock.lookupField(right, true); + if ((result != null) && (result.getSymbol() instanceof Variable)) { result.getSymbol().noteReference(support.getNode(ctx2.getParent().getParent()), cq); } } diff --git a/proparse/src/test/java/org/prorefactor/core/ClassesTest.java b/proparse/src/test/java/org/prorefactor/core/ClassesTest.java index 035c442bc..9890b5271 100644 --- a/proparse/src/test/java/org/prorefactor/core/ClassesTest.java +++ b/proparse/src/test/java/org/prorefactor/core/ClassesTest.java @@ -151,15 +151,23 @@ public void testThisObject() { Variable prop1 = unit.getRootScope().getVariable("prop1"); Variable prop2 = unit.getRootScope().getVariable("prop2"); Variable var1 = unit.getRootScope().getVariable("var1"); + Variable var2 = unit.getRootScope().getVariable("var2"); + Variable var3 = unit.getRootScope().getVariable("var3"); assertNotNull(prop1); assertNotNull(prop2); assertNotNull(var1); + assertNotNull(var2); + assertNotNull(var3); assertEquals(prop1.getNumReads(), 1); assertEquals(prop1.getNumWrites(), 1); assertEquals(prop2.getNumReads(), 1); assertEquals(prop2.getNumWrites(), 1); assertEquals(var1.getNumReads(), 0); assertEquals(var1.getNumWrites(), 1); + assertEquals(var2.getNumReads(), 0); + assertEquals(var2.getNumWrites(), 2); + assertEquals(var3.getNumReads(), 1); + assertEquals(var3.getNumWrites(), 1); } } diff --git a/proparse/src/test/java/org/prorefactor/core/JPNodeTest.java b/proparse/src/test/java/org/prorefactor/core/JPNodeTest.java index 28e6d6ed5..2b7a06dec 100644 --- a/proparse/src/test/java/org/prorefactor/core/JPNodeTest.java +++ b/proparse/src/test/java/org/prorefactor/core/JPNodeTest.java @@ -53,8 +53,8 @@ * Tests for JPNodeVisitor */ public class JPNodeTest extends AbstractProparseTest { - private final static String SRC_DIR = "src/test/resources/jpnode"; - private final static String TEMP_DIR = "target/nodes-lister/jpnode"; + private static final String SRC_DIR = "src/test/resources/jpnode"; + private static final String TEMP_DIR = "target/nodes-lister/jpnode"; private RefactorSession session; private File tempDir = new File(TEMP_DIR); @@ -177,14 +177,14 @@ public void testDotComment01() { assertTrue(node.getText().startsWith(".message")); assertEquals(node.getLine(), 1); assertEquals(node.getEndLine(), 3); - assertEquals(node.getColumn(), 1); + assertEquals(node.getColumn(), 0); assertEquals(node.getEndColumn(), 27); assertNotNull(node.getFirstChild()); assertEquals(node.getFirstChild().getNodeType(), ABLNodeType.PERIOD); assertEquals(node.getFirstChild().getLine(), 3); assertEquals(node.getFirstChild().getEndLine(), 3); - assertEquals(node.getFirstChild().getColumn(), 29); + assertEquals(node.getFirstChild().getColumn(), 28); assertEquals(node.getFirstChild().getEndColumn(), 29); } @@ -198,14 +198,14 @@ public void testDotComment02() { assertEquals(node.getLine(), 1); assertEquals(node.getEndLine(), 1); - assertEquals(node.getColumn(), 1); + assertEquals(node.getColumn(), 0); assertEquals(node.getEndColumn(), 8); assertNotNull(node.getFirstChild()); assertEquals(node.getFirstChild().getNodeType(), ABLNodeType.PERIOD); assertEquals(node.getFirstChild().getLine(), 1); assertEquals(node.getFirstChild().getEndLine(), 1); - assertEquals(node.getFirstChild().getColumn(), 9); + assertEquals(node.getFirstChild().getColumn(), 8); assertEquals(node.getFirstChild().getEndColumn(), 9); } @@ -267,7 +267,7 @@ public void testFileName01() { assertEquals(node.getFirstChild().getText(), "c:/foo/bar/something.p"); assertEquals(node.getFirstChild().getLine(), 1); assertEquals(node.getFirstChild().getEndLine(), 1); - assertEquals(node.getFirstChild().getColumn(), 9); + assertEquals(node.getFirstChild().getColumn(), 8); assertEquals(node.getFirstChild().getEndColumn(), 30); assertNotNull(node.getFirstChild().getNextSibling()); diff --git a/proparse/src/test/java/org/prorefactor/core/MacroGraphTest.java b/proparse/src/test/java/org/prorefactor/core/MacroGraphTest.java index 3e7b974e1..9fc556967 100644 --- a/proparse/src/test/java/org/prorefactor/core/MacroGraphTest.java +++ b/proparse/src/test/java/org/prorefactor/core/MacroGraphTest.java @@ -28,6 +28,8 @@ import org.prorefactor.core.util.SportsSchema; import org.prorefactor.core.util.UnitTestProparseSettings; import org.prorefactor.macrolevel.IncludeRef; +import org.prorefactor.macrolevel.MacroDef; +import org.prorefactor.macrolevel.MacroDefinitionType; import org.prorefactor.macrolevel.MacroEvent; import org.prorefactor.macrolevel.MacroRef; import org.prorefactor.macrolevel.NamedMacroRef; @@ -38,7 +40,7 @@ import org.testng.annotations.Test; public class MacroGraphTest extends AbstractProparseTest { - private final static String SRC_DIR = "src/test/resources/data/preprocessor"; + private static final String SRC_DIR = "src/test/resources/data/preprocessor"; private RefactorSession session; @@ -135,42 +137,42 @@ public void testMacroGraphPosition() { assertTrue(list.get(0) instanceof IncludeRef); assertEquals(((MacroRef) list.get(0)).getFileIndex(), 1); assertEquals(((MacroRef) list.get(0)).getLine(), 3); - assertEquals(((MacroRef) list.get(0)).getColumn(), 5); + assertEquals(((MacroRef) list.get(0)).getColumn(), 4); assertEquals(((MacroRef) list.get(0)).getEndLine(), 3); assertEquals(((MacroRef) list.get(0)).getEndColumn(), 40); assertTrue(list.get(1) instanceof IncludeRef); assertEquals(((MacroRef) list.get(1)).getFileIndex(), 2); assertEquals(((MacroRef) list.get(1)).getLine(), 20); - assertEquals(((MacroRef) list.get(1)).getColumn(), 1); + assertEquals(((MacroRef) list.get(1)).getColumn(), 0); assertEquals(((MacroRef) list.get(1)).getEndLine(), 20); assertEquals(((MacroRef) list.get(1)).getEndColumn(), 44); assertTrue(list.get(2) instanceof IncludeRef); assertEquals(((MacroRef) list.get(2)).getFileIndex(), 3); assertEquals(((MacroRef) list.get(2)).getLine(), 22); - assertEquals(((MacroRef) list.get(2)).getColumn(), 1); + assertEquals(((MacroRef) list.get(2)).getColumn(), 0); assertEquals(((MacroRef) list.get(2)).getEndLine(), 22); assertEquals(((MacroRef) list.get(2)).getEndColumn(), 36); assertTrue(list.get(3) instanceof IncludeRef); assertEquals(((MacroRef) list.get(3)).getFileIndex(), 3); assertEquals(((MacroRef) list.get(3)).getLine(), 28); - assertEquals(((MacroRef) list.get(3)).getColumn(), 1); + assertEquals(((MacroRef) list.get(3)).getColumn(), 0); assertEquals(((MacroRef) list.get(3)).getEndLine(), 28); assertEquals(((MacroRef) list.get(3)).getEndColumn(), 36); MacroRef ref = (MacroRef) unit.getMacroGraph().macroEventList.get(5); assertEquals(ref.getLine(), 24); assertEquals(ref.getEndLine(), 24); - assertEquals(ref.getColumn(), 1); + assertEquals(ref.getColumn(), 0); assertEquals(ref.getEndColumn(), 49); ref = (MacroRef) unit.getMacroGraph().macroEventList.get(6); assertEquals(ref.getLine(), 25); assertEquals(ref.getEndLine(), 25); - assertEquals(ref.getColumn(), 3); + assertEquals(ref.getColumn(), 2); assertEquals(ref.getEndColumn(), 53); ref = (MacroRef) unit.getMacroGraph().macroEventList.get(7); assertEquals(ref.getLine(), 26); assertEquals(ref.getEndLine(), 27); - assertEquals(ref.getColumn(), 1); + assertEquals(ref.getColumn(), 0); assertEquals(ref.getEndColumn(), 1); } @@ -187,7 +189,7 @@ public void testIncludeParameter01() { IncludeRef ref = (IncludeRef) list.get(0); assertEquals(ref.getLine(), 1); assertEquals(ref.getEndLine(), 3); - assertEquals(ref.getColumn(), 1); + assertEquals(ref.getColumn(), 0); assertEquals(ref.getEndColumn(), 44); assertNotNull(ref.getArgNumber(1)); assertEquals(ref.getArgNumber(1).getName(), "param1"); @@ -211,7 +213,7 @@ public void testIncludeParameter02() { IncludeRef ref = (IncludeRef) list.get(0); assertEquals(ref.getLine(), 1); assertEquals(ref.getEndLine(), 5); - assertEquals(ref.getColumn(), 1); + assertEquals(ref.getColumn(), 0); assertEquals(ref.getEndColumn(), 33); assertNotNull(ref.getArgNumber(1)); assertEquals(ref.getArgNumber(1).getName(), "param1"); @@ -225,4 +227,86 @@ public void testIncludeParameter02() { assertNull(ref.getArgNumber(4)); } + @Test + public void testIncludeParameter03() { + ParseUnit unit = getParseUnit(new File(SRC_DIR, "preprocessor20.p"), session); + unit.parse(); + assertFalse(unit.hasSyntaxError()); + + List list = unit.getMacroGraph().findExternalMacroReferences(); + assertNotNull(list); + assertEquals(list.size(), 3); + + /* First include file */ + IncludeRef ref1 = (IncludeRef) list.get(0); + assertEquals(ref1.getLine(), 6); + assertEquals(ref1.getEndLine(), 6); + assertEquals(ref1.getColumn(), 17); + assertEquals(ref1.getEndColumn(), 58); + assertEquals(ref1.numArgs(), 1); + MacroDef ref1Arg1 = ref1.getArgNumber(1); + assertEquals(ref1Arg1.getType(), MacroDefinitionType.NUMBEREDARG); + assertEquals(ref1Arg1.getValue(), "BAR"); + + /* Second include file */ + IncludeRef ref2 = (IncludeRef) list.get(1); + assertEquals(ref2.getLine(), 2); + assertEquals(ref2.getEndLine(), 8); + assertEquals(ref2.getColumn(), 0); + assertEquals(ref2.getEndColumn(), 7); + assertEquals(ref2.numArgs(), 5); + MacroDef ref2Arg1 = ref2.lookupNamedArg("param1"); + assertEquals(ref2Arg1.getValue(), ""); + MacroDef ref2Arg2 = ref2.lookupNamedArg("param2"); + assertEquals(ref2Arg2.getValue(), ""); + MacroDef ref2Arg3 = ref2.lookupNamedArg("param3"); + assertEquals(ref2Arg3.getValue(), " "); + MacroDef ref2Arg4 = ref2.lookupNamedArg("param4"); + assertEquals(ref2Arg4.getValue(), "XXX BAR BAR XXX "); + MacroDef ref2Arg5 = ref2.lookupNamedArg("param5"); + assertEquals(ref2Arg5.getValue(), " test "); + + /* Third include file */ + IncludeRef ref3 = (IncludeRef) list.get(2); + assertEquals(ref3.getLine(), 9); + assertEquals(ref3.getEndLine(), 9); + assertEquals(ref3.getColumn(), 0); + assertEquals(ref3.getEndColumn(), 82); + assertEquals(ref3.numArgs(), 6); + MacroDef ref3Arg1 = ref3.getArgNumber(1); + assertEquals(ref3Arg1.getValue(), "\""); + MacroDef ref3Arg2 = ref3.getArgNumber(2); + assertEquals(ref3Arg2.getValue(), "value1"); + MacroDef ref3Arg3 = ref3.getArgNumber(3); + assertEquals(ref3Arg3.getValue(), "value2"); + MacroDef ref3Arg4 = ref3.getArgNumber(4); + assertEquals(ref3Arg4.getValue(), "\"value3\":U"); + MacroDef ref3Arg5 = ref3.getArgNumber(5); + assertEquals(ref3Arg5.getValue(), "\"value4\""); + MacroDef ref3Arg6 = ref3.getArgNumber(6); + assertEquals(ref3Arg6.getValue(), " "); + } + + @Test + public void testIncludeParameter04() { + ParseUnit unit = getParseUnit(new File(SRC_DIR, "preprocessor25.p"), session); + unit.parse(); + assertFalse(unit.hasSyntaxError()); + + List list = unit.getMacroGraph().findExternalMacroReferences(); + assertNotNull(list); + assertEquals(list.size(), 1); + + /* First include file */ + IncludeRef ref1 = (IncludeRef) list.get(0); + assertEquals(ref1.getLine(), 1); + assertEquals(ref1.getEndLine(), 1); + assertEquals(ref1.getColumn(), 0); + assertEquals(ref1.getEndColumn(), 56); + assertEquals(ref1.numArgs(), 1); + MacroDef ref1Arg1 = ref1.getArgNumber(1); + assertEquals(ref1Arg1.getType(), MacroDefinitionType.NAMEDARG); + assertEquals(ref1Arg1.getName(), "DefaultValue"); + assertEquals(ref1Arg1.getValue(), "\"-\""); + } } diff --git a/proparse/src/test/java/org/prorefactor/core/MetricsTest.java b/proparse/src/test/java/org/prorefactor/core/MetricsTest.java index d2639e3e5..b7d80be78 100644 --- a/proparse/src/test/java/org/prorefactor/core/MetricsTest.java +++ b/proparse/src/test/java/org/prorefactor/core/MetricsTest.java @@ -44,6 +44,8 @@ public void test01() { assertEquals(unit.getMetrics().getLoc(), 2); assertEquals(unit.getMetrics().getComments(), 6); + assertEquals(unit.getParseTreeSize(), 50); + assertEquals(unit.getJPNodeSize(), 22); } @Test diff --git a/proparse/src/test/java/org/prorefactor/core/ParserTest.java b/proparse/src/test/java/org/prorefactor/core/ParserTest.java index 528ba7f06..051439c0c 100644 --- a/proparse/src/test/java/org/prorefactor/core/ParserTest.java +++ b/proparse/src/test/java/org/prorefactor/core/ParserTest.java @@ -925,7 +925,7 @@ public void testElvis01() { JPNode node1 = unit.getTopNode().query(ABLNodeType.ELVIS).get(0); assertEquals(node1.getLine(), 3); assertEquals(node1.getEndLine(), 3); - assertEquals(node1.getColumn(), 11); + assertEquals(node1.getColumn(), 10); assertEquals(node1.getEndColumn(), 12); assertEquals(node1.getText(), "?:"); } @@ -940,21 +940,21 @@ public void testElvis02() { JPNode node2 = unit.getTopNode().query(ABLNodeType.LEXCOLON).get(0); JPNode node3 = unit.getTopNode().query(ABLNodeType.DISPLAY).get(0); assertEquals(node1.getLine(), 1); - assertEquals(node1.getColumn(), 42); + assertEquals(node1.getColumn(), 41); assertEquals(node1.getEndColumn(), 42); assertEquals(node1.getText(), "?"); assertEquals(node2.getLine(), 1); - assertEquals(node2.getColumn(), 43); + assertEquals(node2.getColumn(), 42); assertEquals(node2.getEndColumn(), 43); assertEquals(node2.getText(), ":"); assertEquals(node3.getLine(), 2); - assertEquals(node3.getColumn(), 3); + assertEquals(node3.getColumn(), 2); assertEquals(node3.getEndColumn(), 9); assertNotNull(node3.getHiddenBefore()); assertNull(node3.getHiddenBefore().getHiddenBefore()); assertEquals(node3.getHiddenBefore().getLine(), 1); assertEquals(node3.getHiddenBefore().getEndLine(), 2); - assertEquals(node3.getHiddenBefore().getCharPositionInLine(), 44); + assertEquals(node3.getHiddenBefore().getCharPositionInLine(), 43); assertEquals(node3.getHiddenBefore().getEndCharPositionInLine(), 2); } diff --git a/proparse/src/test/java/org/prorefactor/core/PreprocessorDirectiveTest.java b/proparse/src/test/java/org/prorefactor/core/PreprocessorDirectiveTest.java index 471a1969f..e5dff76c8 100644 --- a/proparse/src/test/java/org/prorefactor/core/PreprocessorDirectiveTest.java +++ b/proparse/src/test/java/org/prorefactor/core/PreprocessorDirectiveTest.java @@ -37,7 +37,7 @@ import org.testng.annotations.Test; public class PreprocessorDirectiveTest extends AbstractProparseTest { - private final static String SRC_DIR = "src/test/resources/data/preprocessor"; + private static final String SRC_DIR = "src/test/resources/data/preprocessor"; private RefactorSession session; @@ -303,7 +303,7 @@ public void test09() { assertEquals(nmr.getMacroDef(), incRef.macroEventList.get(0)); assertEquals(nmr.getLine(), 4); assertEquals(nmr.getEndLine(), 4); - assertEquals(nmr.getColumn(), 10); + assertEquals(nmr.getColumn(), 9); assertEquals(nmr.getEndColumn(), 17); } @@ -321,7 +321,7 @@ public void test10() { IncludeRef incRef = (IncludeRef) mainFile.macroEventList.get(2); assertEquals(incRef.getLine(), 6); assertEquals(incRef.getEndLine(), 6); - assertEquals(incRef.getColumn(), 4); + assertEquals(incRef.getColumn(), 3); assertEquals(incRef.getEndColumn(), 36); List nodes = unit.getTopNode().query(ABLNodeType.DEFINE); assertEquals(nodes.size(), 1); @@ -330,7 +330,7 @@ public void test10() { assertEquals(nodes.get(0).getEndFileIndex(), 1); assertEquals(nodes.get(0).getLine(), 6); assertEquals(nodes.get(0).getEndLine(), 1); - assertEquals(nodes.get(0).getColumn(), 1); + assertEquals(nodes.get(0).getColumn(), 0); assertEquals(nodes.get(0).getEndColumn(), 3); } @@ -345,11 +345,11 @@ public void test11() { JPNode leftParen = substNode.getNextNode(); JPNode str = leftParen.getNextNode().getFirstChild().getFirstChild(); assertEquals(leftParen.getLine(), 2); - assertEquals(leftParen.getColumn(), 19); + assertEquals(leftParen.getColumn(), 18); assertEquals(leftParen.getEndLine(), 2); assertEquals(leftParen.getEndColumn(), 19); assertEquals(str.getLine(), 2); - assertEquals(str.getColumn(), 20); + assertEquals(str.getColumn(), 19); assertEquals(str.getEndLine(), 2); assertEquals(str.getEndColumn(), 24); @@ -357,11 +357,11 @@ public void test11() { JPNode leftParen2 = substNode2.getNextNode(); JPNode str2 = leftParen2.getNextNode().getFirstChild().getFirstChild(); assertEquals(leftParen2.getLine(), 3); - assertEquals(leftParen2.getColumn(), 19); + assertEquals(leftParen2.getColumn(), 18); assertEquals(leftParen2.getEndLine(), 3); assertEquals(leftParen2.getEndColumn(), 19); assertEquals(str2.getLine(), 3); - assertEquals(str2.getColumn(), 20); + assertEquals(str2.getColumn(), 19); assertEquals(str2.getEndLine(), 3); // FIXME Wrong value, should be 25 assertEquals(str2.getEndColumn(), 20); @@ -372,7 +372,7 @@ public void test11() { JPNode str3 = dispNode.getNextNode().getNextNode().getFirstChild(); assertEquals(str3.getLine(), 4); assertEquals(str3.getEndLine(), 4); - assertEquals(str3.getColumn(), 9); + assertEquals(str3.getColumn(), 8); // FIXME Wrong value, should be 14 assertEquals(str3.getEndColumn(), 9); } diff --git a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java index 80857f172..4a40bde13 100644 --- a/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java +++ b/proparse/src/test/java/org/prorefactor/core/TreeParser03Test.java @@ -38,6 +38,7 @@ import org.prorefactor.treeparser.TreeParserSymbolScope; import org.prorefactor.treeparser.symbols.Event; import org.prorefactor.treeparser.symbols.Modifier; +import org.prorefactor.treeparser.symbols.Query; import org.prorefactor.treeparser.symbols.Routine; import org.prorefactor.treeparser.symbols.Symbol; import org.prorefactor.treeparser.symbols.TableBuffer; @@ -1466,22 +1467,22 @@ public void testTTAsParameter() { assertNotNull(f2prm6.getDefinitionNode()); assertEquals(f2prm1.getDefinitionNode().getNodeType(), ABLNodeType.ID); assertEquals(f2prm1.getDefinitionNode().getLine(), 13); - assertEquals(f2prm1.getDefinitionNode().getColumn(), 5); + assertEquals(f2prm1.getDefinitionNode().getColumn(), 4); assertEquals(f2prm2.getDefinitionNode().getNodeType(), ABLNodeType.ID); assertEquals(f2prm2.getDefinitionNode().getLine(), 14); - assertEquals(f2prm2.getDefinitionNode().getColumn(), 5); + assertEquals(f2prm2.getDefinitionNode().getColumn(), 4); assertEquals(f2prm3.getDefinitionNode().getNodeType(), ABLNodeType.RECORD_NAME); assertEquals(f2prm3.getDefinitionNode().getLine(), 15); - assertEquals(f2prm3.getDefinitionNode().getColumn(), 11); + assertEquals(f2prm3.getDefinitionNode().getColumn(), 10); assertEquals(f2prm4.getDefinitionNode().getNodeType(), ABLNodeType.ID); assertEquals(f2prm4.getDefinitionNode().getLine(), 16); - assertEquals(f2prm4.getDefinitionNode().getColumn(), 18); + assertEquals(f2prm4.getDefinitionNode().getColumn(), 17); assertEquals(f2prm5.getDefinitionNode().getNodeType(), ABLNodeType.ID); assertEquals(f2prm5.getDefinitionNode().getLine(), 17); - assertEquals(f2prm5.getDefinitionNode().getColumn(), 13); + assertEquals(f2prm5.getDefinitionNode().getColumn(), 12); assertEquals(f2prm6.getDefinitionNode().getNodeType(), ABLNodeType.ID); assertEquals(f2prm6.getDefinitionNode().getLine(), 18); - assertEquals(f2prm6.getDefinitionNode().getColumn(), 20); + assertEquals(f2prm6.getDefinitionNode().getColumn(), 19); } @@ -1537,4 +1538,21 @@ public void test41() { assertEquals(nodes.get(2).asIExpression().getDataType(), DataType.DECIMAL); } + @Test + public void test42() { + ParseUnit unit = getParseUnit(new File("src/test/resources/treeparser03/test42.p"), session); + assertNull(unit.getTopNode()); + unit.treeParser01(); + assertFalse(unit.hasSyntaxError()); + assertNotNull(unit.getTopNode()); + assertNotNull(unit.getRootScope()); + + assertNull(unit.getRootScope().lookupQuery("qry00")); + Query qry = unit.getRootScope().lookupQuery("qry"); + assertNotNull(qry); + List list = unit.getTopNode().query(ABLNodeType.ID); + assertEquals(list.size(), 4); + assertFalse(list.stream().anyMatch(it -> it.getSymbol() == null)); + assertFalse(list.stream().anyMatch(it -> it.getSymbol().getNodeType() != ABLNodeType.QUERY)); + } } diff --git a/proparse/src/test/java/org/prorefactor/proparse/ABLLexerTest.java b/proparse/src/test/java/org/prorefactor/proparse/ABLLexerTest.java index 5320b8343..1ae96d969 100644 --- a/proparse/src/test/java/org/prorefactor/proparse/ABLLexerTest.java +++ b/proparse/src/test/java/org/prorefactor/proparse/ABLLexerTest.java @@ -458,7 +458,7 @@ public void testQuotedStringPosition01() { ProToken tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.DO); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 2); @@ -473,7 +473,7 @@ public void testQuotedStringPosition01() { tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.QSTRING); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 15); + assertEquals(tok.getCharPositionInLine(), 14); assertEquals(tok.getEndLine(), 1); // The important test here, end column has to be 16 even when followed by ':' assertEquals(tok.getEndCharPositionInLine(), 16); @@ -482,7 +482,7 @@ public void testQuotedStringPosition01() { tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.LEXCOLON); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 17); + assertEquals(tok.getCharPositionInLine(), 16); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 17); } @@ -494,7 +494,7 @@ public void testQuotedStringPosition02() { ProToken tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.DO); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 2); @@ -510,7 +510,7 @@ public void testQuotedStringPosition02() { tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.QSTRING); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 15); + assertEquals(tok.getCharPositionInLine(), 14); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 16); @@ -520,7 +520,7 @@ public void testQuotedStringPosition02() { tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.LEXCOLON); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 18); + assertEquals(tok.getCharPositionInLine(), 17); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 18); } @@ -532,13 +532,13 @@ public void testQuotedStringPosition03() { ProToken tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.QSTRING); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 10); tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.PERIOD); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 11); + assertEquals(tok.getCharPositionInLine(), 10); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 11); } @@ -550,13 +550,13 @@ public void testQuotedStringPosition04() { ProToken tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.QSTRING); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 6); tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.PERIOD); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 7); + assertEquals(tok.getCharPositionInLine(), 6); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 7); } @@ -568,13 +568,13 @@ public void testQuotedStringPosition05() { ProToken tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.QSTRING); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 8); tok = (ProToken) lexer.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.PERIOD); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 9); + assertEquals(tok.getCharPositionInLine(), 8); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 9); } @@ -686,7 +686,7 @@ public void testWritableTokens() { assertNotNull(tok); assertTrue(tok instanceof WritableProToken); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 3); + assertEquals(tok.getCharPositionInLine(), 2); WritableProToken tok2 = (WritableProToken) tok; tok2.setLine(5); tok2.setCharPositionInLine(4); diff --git a/proparse/src/test/java/org/prorefactor/proparse/ExpressionEngineTest.java b/proparse/src/test/java/org/prorefactor/proparse/ExpressionEngineTest.java index 9c536aaf5..028160222 100644 --- a/proparse/src/test/java/org/prorefactor/proparse/ExpressionEngineTest.java +++ b/proparse/src/test/java/org/prorefactor/proparse/ExpressionEngineTest.java @@ -18,6 +18,7 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import java.io.FileReader; @@ -47,7 +48,6 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import eu.rssw.pct.RCodeInfo.InvalidRCodeException; import eu.rssw.pct.elements.DataType; import eu.rssw.pct.elements.ParameterMode; import eu.rssw.pct.elements.PrimitiveDataType; @@ -61,43 +61,9 @@ public class ExpressionEngineTest extends AbstractProparseTest { private RefactorSession session; @BeforeMethod - public void setUp() throws IOException, InvalidRCodeException { + public void setUp() throws IOException { session = new RefactorSession(new UnitTestProparseSettings(), new SportsSchema()); - // For testObjectAttribute02 - TypeInfo typeInfo01 = new TypeInfo("rssw.test.Class02", false, false, "Progress.Lang.Object", ""); - typeInfo01.addProperty(new PropertyElement("p1", false, DataType.CHARACTER)); - typeInfo01.addVariable(new VariableElement("v1", DataType.LONGCHAR)); - session.injectTypeInfo(typeInfo01); - - // For testObjectMethod03 - TypeInfo typeInfo02 = new TypeInfo("rssw.test.Class03", false, false, "Progress.Lang.Object", ""); - typeInfo02.addMethod(new MethodElement("m1", false, DataType.VOID)); - typeInfo02.addMethod(new MethodElement("m2", false, DataType.INT64)); - session.injectTypeInfo(typeInfo02); - - // For testStaticMethod - TypeInfo typeInfo03 = new TypeInfo("rssw.test.Class04", false, false, "Progress.Lang.Object", ""); - typeInfo03.addMethod(new MethodElement("m1", true, DataType.CHARACTER)); - typeInfo03.addMethod(new MethodElement("m2", true, DataType.INTEGER)); - typeInfo03.addMethod(new MethodElement("m2", true, DataType.INT64, // - new Parameter(1, "prm1", 0, ParameterMode.INPUT, DataType.INTEGER))); - session.injectTypeInfo(typeInfo03); - - // Overloaded methods - TypeInfo typeInfo04 = new TypeInfo("rssw.test.Class05", false, false, "Progress.Lang.Object", ""); - typeInfo04.addMethod(new MethodElement("over01", true, DataType.CHARACTER)); - typeInfo04.addMethod(new MethodElement("over01", true, DataType.VOID, new Parameter(1, "prm1", 0, ParameterMode.INPUT, DataType.INTEGER))); - typeInfo04.addMethod(new MethodElement("over01", true, DataType.INTEGER, new Parameter(1, "prm1", 0, ParameterMode.INPUT, DataType.CHARACTER))); - typeInfo04.addMethod(new MethodElement("over01", true, DataType.INT64, // - new Parameter(1, "prm1", 0, ParameterMode.INPUT, DataType.CHARACTER), // - new Parameter(2, "prm2", 0, ParameterMode.INPUT, DataType.CHARACTER))); - session.injectTypeInfo(typeInfo04); - - // For catalog - TypeInfo typeInfo05 = new TypeInfo("rssw.MyTestClassCatalog", false, false, "System.Windows.Forms.Control", ""); - session.injectTypeInfo(typeInfo05); - // Inject content of catalog.json try (Reader reader = new FileReader("src/test/resources/catalog.json")) { session.injectClassesFromCatalog(reader); @@ -368,6 +334,14 @@ public void testObjectAttribute01() { assertEquals(exp.getDataType().getClassName(), "Progress.Lang.Object"); } + @BeforeMethod(dependsOnMethods = "setUp") + public void beforeObjectAttribute02() { + TypeInfo typeInfo = new TypeInfo("rssw.test.Class02", false, false, "Progress.Lang.Object", ""); + typeInfo.addProperty(new PropertyElement("p1", false, DataType.CHARACTER)); + typeInfo.addVariable(new VariableElement("v1", DataType.LONGCHAR)); + session.injectTypeInfo(typeInfo); + } + @Test public void testObjectAttribute02() { ParseUnit unit = getParseUnit( @@ -437,6 +411,16 @@ public void testEnumValues02() { assertEquals(exp2.getDataType().getClassName(), "Progress.Reflect.AccessMode"); } + @BeforeMethod(dependsOnMethods = "setUp") + public void beforeStaticMethod() { + TypeInfo typeInfo = new TypeInfo("rssw.test.Class04", false, false, "Progress.Lang.Object", ""); + typeInfo.addMethod(new MethodElement("m1", true, DataType.CHARACTER)); + typeInfo.addMethod(new MethodElement("m2", true, DataType.INTEGER)); + typeInfo.addMethod(new MethodElement("m2", true, DataType.INT64, // + new Parameter(1, "prm1", 0, ParameterMode.INPUT, DataType.INTEGER))); + session.injectTypeInfo(typeInfo); + } + @Test public void testStaticMethod01() { String sourceCode = "message rssw.test.Class04:m1(). " @@ -492,10 +476,17 @@ public void testObjectMethod() { assertEquals(exp2.getDataType(), DataType.NOT_COMPUTED); } + @BeforeMethod(dependsOnMethods = "setUp") + public void beforeObjectMethod02() { + TypeInfo typeInfo = new TypeInfo("rssw.pct.Class02", false, false, "Progress.Lang.Object", ""); + typeInfo.addMethod(new MethodElement("m1", false, DataType.VOID)); + session.injectTypeInfo(typeInfo); + } + @Test public void testObjectMethod02() { - ParseUnit unit = getParseUnit("class rssw.pct: method void m1(): toString(). foobar(). end method. end class.", - session); + ParseUnit unit = getParseUnit( + "class rssw.pct.Class02: method void m1(): toString(). foobar(). end method. end class.", session); unit.treeParser01(); List nodes = unit.getTopNode().queryExpressions(); @@ -503,34 +494,113 @@ public void testObjectMethod02() { assertTrue(nodes.get(0) instanceof LocalMethodCallNode); LocalMethodCallNode exp = (LocalMethodCallNode) nodes.get(0); + assertNotNull(exp.getTypeInfo()); + assertNotNull(exp.getMethodElement()); + assertEquals(exp.getTypeInfo().getTypeName(), "Progress.Lang.Object"); assertEquals(exp.getMethodName(), "toString"); assertEquals(exp.getDataType(), DataType.CHARACTER); assertTrue(nodes.get(1) instanceof LocalMethodCallNode); LocalMethodCallNode exp2 = (LocalMethodCallNode) nodes.get(1); + assertNull(exp2.getMethodElement()); + assertNull(exp2.getTypeInfo()); assertEquals(exp2.getMethodName(), "foobar"); assertEquals(exp2.getDataType(), DataType.NOT_COMPUTED); } + @BeforeMethod(dependsOnMethods = "setUp") + public void beforeObjectMethod03() { + TypeInfo typeInfo = new TypeInfo("rssw.test.Class03", false, false, "Progress.Lang.Object", ""); + typeInfo.addMethod(new MethodElement("m1", false, DataType.VOID)); + typeInfo.addMethod(new MethodElement("m2", false, DataType.INT64)); + session.injectTypeInfo(typeInfo); + } + @Test public void testObjectMethod03() { ParseUnit unit = getParseUnit( - "class rssw.test.Class03: method void m1(): this-object:m2(). super:toString(). end method. method int64 m2(): return 0. end method. end class.", + "class rssw.test.Class03: method void m1(): this-object:m2(). super:toString(). super:unknown(). end method. method int64 m2(): return 0. end method. end class.", session); unit.treeParser01(); List nodes = unit.getTopNode().queryExpressions(); - assertEquals(nodes.size(), 3); + assertEquals(nodes.size(), 4); assertTrue(nodes.get(0) instanceof MethodCallNode); MethodCallNode exp = (MethodCallNode) nodes.get(0); + assertNotNull(exp.getMethodElement()); + assertEquals(exp.getTypeInfo().getTypeName(), "rssw.test.Class03"); assertEquals(exp.getMethodName(), "m2"); assertEquals(exp.getDataType(), DataType.INT64); assertTrue(nodes.get(1) instanceof MethodCallNode); MethodCallNode exp2 = (MethodCallNode) nodes.get(1); + assertEquals(exp2.getTypeInfo().getTypeName(), "Progress.Lang.Object"); + assertNotNull(exp2.getMethodElement()); assertEquals(exp2.getMethodName(), "toString"); assertEquals(exp2.getDataType(), DataType.CHARACTER); + + assertTrue(nodes.get(2) instanceof MethodCallNode); + MethodCallNode exp3 = (MethodCallNode) nodes.get(2); + assertNull(exp3.getMethodElement()); + assertNull(exp3.getTypeInfo()); + assertEquals(exp3.getMethodName(), "unknown"); + assertEquals(exp3.getDataType(), DataType.NOT_COMPUTED); + } + + @BeforeMethod(dependsOnMethods = "setUp") + public void beforeObjectMethod04() { + TypeInfo typeInfo = new TypeInfo("rssw.test.Class06", false, false, "Progress.Lang.Object", ""); + typeInfo.addMethod(new MethodElement("m1", false, DataType.VOID)); + typeInfo.addMethod(new MethodElement("m2", false, DataType.HANDLE)); + session.injectTypeInfo(typeInfo); + } + + @Test + public void testObjectMethod04() { + ParseUnit unit = getParseUnit("class rssw.test.Class06: " // + + "method void m1():" // + + " m2():add-super-procedure(xx). " // + + "end method. " // + + "method handle m2():" // + + " return session. " // + + "end method. " // + + "end class.", session); + unit.treeParser01(); + + List nodes = unit.getTopNode().queryExpressions(); + assertEquals(nodes.size(), 2); + + assertTrue(nodes.get(0) instanceof MethodCallNode); + MethodCallNode exp = (MethodCallNode) nodes.get(0); + assertEquals(exp.getMethodName(), "add-super-procedure"); + assertEquals(exp.getDataType(), DataType.LOGICAL); + } + + @Test + public void testObjectMethod05() { + ParseUnit unit = getParseUnit("class rssw.test.Class07: " // + + "constructor Class07():" // + + " this-object(1). " // + + "end constructor. " // + + "constructor Class07(xx as int):" // + + " super(1). " // + + "end constructor. " // + + "end class.", session); + unit.treeParser01(); + + List nodes = unit.getTopNode().queryExpressions(); + assertEquals(nodes.size(), 2); + + assertTrue(nodes.get(0) instanceof MethodCallNode); + MethodCallNode exp = (MethodCallNode) nodes.get(0); + assertNull(exp.getMethodElement()); // Currently not available + assertEquals(exp.getDataType().getClassName(), "rssw.test.Class07"); + + assertTrue(nodes.get(1) instanceof MethodCallNode); + MethodCallNode exp2 = (MethodCallNode) nodes.get(0); + assertNull(exp2.getMethodElement()); // Currently not available + assertEquals(exp2.getDataType().getClassName(), "rssw.test.Class07"); } @Test @@ -720,6 +790,20 @@ public void testArrayGetExpressions02() { assertTrue(((ArrayReferenceNode) exp).getOffsetExpression() instanceof ConstantNode); } + @BeforeMethod(dependsOnMethods = "setUp") + public void beforeOverloadedMethodCall() { + TypeInfo typeInfo = new TypeInfo("rssw.test.Class05", false, false, "Progress.Lang.Object", ""); + typeInfo.addMethod(new MethodElement("over01", true, DataType.CHARACTER)); + typeInfo.addMethod(new MethodElement("over01", true, DataType.VOID, + new Parameter(1, "prm1", 0, ParameterMode.INPUT, DataType.INTEGER))); + typeInfo.addMethod(new MethodElement("over01", true, DataType.INTEGER, + new Parameter(1, "prm1", 0, ParameterMode.INPUT, DataType.CHARACTER))); + typeInfo.addMethod(new MethodElement("over01", true, DataType.INT64, // + new Parameter(1, "prm1", 0, ParameterMode.INPUT, DataType.CHARACTER), // + new Parameter(2, "prm2", 0, ParameterMode.INPUT, DataType.CHARACTER))); + session.injectTypeInfo(typeInfo); + } + @Test public void testOverloadedMethodCall01() { String sourceCode = "def var var1 as rssw.test.Class05. " @@ -835,6 +919,12 @@ public void testEvent01() { assertEquals(exp2.getDataType().getPrimitive(), PrimitiveDataType.VOID); } + @BeforeMethod(dependsOnMethods = "setUp") + public void beforeCatalog01() { + TypeInfo typeInfo = new TypeInfo("rssw.MyTestClassCatalog", false, false, "System.Windows.Forms.Control", ""); + session.injectTypeInfo(typeInfo); + } + @Test public void testCatalog01() { String sourceCode = "class rssw.MyTestClassCatalog inherits System.Windows.Forms.Control: " @@ -854,4 +944,30 @@ public void testCatalog01() { IExpression exp2 = nodes.get(1); assertEquals(exp2.getDataType().getPrimitive(), PrimitiveDataType.INTEGER); } + + @BeforeMethod(dependsOnMethods = "setUp") + public void beforeSignature01() { + TypeInfo typeInfo = new TypeInfo("rssw.test.FooClass01", false, false, "Progress.Lang.Object", ""); + typeInfo.addMethod(new MethodElement("Foo", false, DataType.CHARACTER, // + new Parameter(1, "prm1", 0, ParameterMode.INPUT_OUTPUT, DataType.CHARACTER))); + session.injectTypeInfo(typeInfo); + } + + @Test + public void testSignature01() { + String sourceCode = "class rssw.test.FooClass01:" + + " constructor FooClass01( ):" + + " this-object:Foo('')." + + " end constructor." + + " method public character Foo(input-output pcTest as character):" + + " end method. " + + "end class."; + ParseUnit unit01 = getParseUnit(sourceCode, session); + unit01.treeParser01(); + + List nodes = unit01.getTopNode().queryExpressions(); + assertEquals(nodes.size(), 1); + IExpression exp1 = nodes.get(0); + assertEquals(exp1.getDataType().getPrimitive(), PrimitiveDataType.CHARACTER); + } } diff --git a/proparse/src/test/java/org/prorefactor/proparse/PostLexerTest.java b/proparse/src/test/java/org/prorefactor/proparse/PostLexerTest.java index fc8751c58..480d5a3b6 100644 --- a/proparse/src/test/java/org/prorefactor/proparse/PostLexerTest.java +++ b/proparse/src/test/java/org/prorefactor/proparse/PostLexerTest.java @@ -44,7 +44,7 @@ import com.google.common.base.Charsets; public class PostLexerTest extends AbstractProparseTest { - private final static String SRC_DIR = "src/test/resources/data/lexer"; + private static final String SRC_DIR = "src/test/resources/data/lexer"; private RefactorSession session; @@ -307,7 +307,7 @@ public void testXCode1() { ProToken tok = (ProToken) nextVisibleToken(src); assertEquals(tok.getNodeType(), ABLNodeType.MESSAGE); assertEquals(tok.getLine(), 2); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 2); assertEquals(tok.getEndCharPositionInLine(), 7); @@ -329,7 +329,7 @@ public void testXCode2() { ProToken tok = (ProToken) nextVisibleToken(src); assertEquals(tok.getNodeType(), ABLNodeType.MESSAGE); assertEquals(tok.getLine(), 2); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 2); assertEquals(tok.getEndCharPositionInLine(), 7); @@ -365,7 +365,7 @@ public void testXCode4() { tok = (ProToken) src.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.QSTRING); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 27); + assertEquals(tok.getCharPositionInLine(), 26); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 33); @@ -377,7 +377,7 @@ public void testXCode4() { tok = (ProToken) src.nextToken(); assertEquals(tok.getNodeType(), ABLNodeType.QSTRING); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 72); + assertEquals(tok.getCharPositionInLine(), 71); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 84); } diff --git a/proparse/src/test/java/org/prorefactor/proparse/TokenListTest.java b/proparse/src/test/java/org/prorefactor/proparse/TokenListTest.java index d8e8db837..fd20f61c6 100644 --- a/proparse/src/test/java/org/prorefactor/proparse/TokenListTest.java +++ b/proparse/src/test/java/org/prorefactor/proparse/TokenListTest.java @@ -57,7 +57,7 @@ public void testTokenList02() { assertEquals(tok.getNodeType(), ABLNodeType.ID); assertEquals(tok.getText(), "Progress.Security.PAMStatus"); assertEquals(tok.getLine(), 1); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 1); assertEquals(tok.getEndCharPositionInLine(), 27); assertEquals(tok.getChannel(), 0); @@ -71,7 +71,7 @@ public void testTokenList02() { assertEquals(tok.getNodeType(), ABLNodeType.ID); assertEquals(tok.getText(), "Progress.Security.PAMStatus"); assertEquals(tok.getLine(), 2); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 2); assertEquals(tok.getEndCharPositionInLine(), 27); assertEquals(tok.getChannel(), 0); @@ -86,7 +86,7 @@ public void testTokenList02() { assertEquals(tok.getNodeType(), ABLNodeType.ID); assertEquals(tok.getText(), "Progress.Security.PAMStatus"); assertEquals(tok.getLine(), 3); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 3); assertEquals(tok.getEndCharPositionInLine(), 27); assertEquals(((ProToken) src.nextToken()).getNodeType(), ABLNodeType.WS); @@ -108,7 +108,7 @@ public void testTokenList02() { assertEquals(tok.getNodeType(), ABLNodeType.ID); assertEquals(tok.getText(), "Progress.117x.clsName"); assertEquals(tok.getLine(), 7); - assertEquals(tok.getCharPositionInLine(), 1); + assertEquals(tok.getCharPositionInLine(), 0); assertEquals(tok.getEndLine(), 7); assertEquals(tok.getEndCharPositionInLine(), 21); assertEquals(tok.getChannel(), 0); diff --git a/proparse/src/test/resources/data/preprocessor/preprocessor25-01.i b/proparse/src/test/resources/data/preprocessor/preprocessor25-01.i new file mode 100644 index 000000000..7ce83f216 --- /dev/null +++ b/proparse/src/test/resources/data/preprocessor/preprocessor25-01.i @@ -0,0 +1,3 @@ +DEFINE VARIABLE xxx AS CHARACTER NO-UNDO. + +ASSIGN xxx = {&DefaultValue}. diff --git a/proparse/src/test/resources/data/preprocessor/preprocessor25.p b/proparse/src/test/resources/data/preprocessor/preprocessor25.p new file mode 100644 index 000000000..ab32f804b --- /dev/null +++ b/proparse/src/test/resources/data/preprocessor/preprocessor25.p @@ -0,0 +1 @@ +{ preprocessor/preprocessor25-01.i &DefaultValue=""-"" } diff --git a/proparse/src/test/resources/data/rssw/pct/TestThisObject.cls b/proparse/src/test/resources/data/rssw/pct/TestThisObject.cls index fa181861a..643d48565 100644 --- a/proparse/src/test/resources/data/rssw/pct/TestThisObject.cls +++ b/proparse/src/test/resources/data/rssw/pct/TestThisObject.cls @@ -8,6 +8,8 @@ CLASS rssw.pct.TestThisObject: DEFINE PUBLIC PROPERTY prop2 AS INTEGER NO-UNDO GET. PRIVATE SET. DEFINE PUBLIC PROPERTY prop3 AS Progress.Lang.Object NO-UNDO GET. PRIVATE SET. DEFINE PRIVATE VARIABLE var1 AS MEMPTR NO-UNDO. + DEFINE PRIVATE STATIC VARIABLE var2 AS INTEGER NO-UNDO. + DEFINE PRIVATE VARIABLE var3 AS INTEGER NO-UNDO. METHOD PUBLIC VOID method1(): THIS-OBJECT:prop1 = 123. @@ -20,12 +22,20 @@ CLASS rssw.pct.TestThisObject: END METHOD. METHOD PUBLIC VOID method3(): - prop3:NEXT-SIBLING = 789. + prop3:NEXT-SIBLING = 789. // Yes, that doesn't compile, but we just need a test case MESSAGE prop3:NEXT-SIBLING. END METHOD. METHOD PUBLIC VOID method4(): - COPY-LOB FROM "xxx.txt" TO THIS-OBJECT:var1. + COPY-LOB FROM FILE "xxx.txt" TO THIS-OBJECT:var1. + END METHOD. + + METHOD PUBLIC VOID method5(): + VAR rssw.pct.TestThisObject x2. + rssw.pct.TestThisObject:var2 = 1. + TestThisObject:var2 = 1. + x2:var3 = 0. + message x2:var3. END METHOD. END CLASS. diff --git a/proparse/src/test/resources/treeparser03/test42.p b/proparse/src/test/resources/treeparser03/test42.p new file mode 100644 index 000000000..74add9f3d --- /dev/null +++ b/proparse/src/test/resources/treeparser03/test42.p @@ -0,0 +1,4 @@ +define query qry for customer. +open query qry for each customer. +get first qry. // Missing lock as it's not specified in the open query statement +get next qry. // Ditto diff --git a/proparse/src/test/resources/treeparser06-expect/test01.p b/proparse/src/test/resources/treeparser06-expect/test01.p index a945d5269..9fd45f37b 100644 --- a/proparse/src/test/resources/treeparser06-expect/test01.p +++ b/proparse/src/test/resources/treeparser06-expect/test01.p @@ -1,49 +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 + PROCEDURE F0/1:0 -- Block -- Scope + IF F0/2:2 + THEN F0/2:10 + DO F0/2:15 -- Block + IF F0/3:4 + THEN F0/3:32 + DO F0/3:37 -- Block + MESSAGE F0/4:6 + ELSE F0/6:4 + MESSAGE F0/6:9 + MESSAGE F0/8:2 + DEFINE F0/11:0 + CASE F0/12:2 + WHEN F0/13:4 + THEN F0/13:11 + RETURN F0/13:16 + WHEN F0/14:4 + THEN F0/14:11 + RETURN F0/14:16 + WHEN F0/15:4 + THEN F0/15:11 + DO F0/15:16 -- Block + MESSAGE F0/16:6 + RETURN F0/17:6 + OTHERWISE F0/19:4 + RETURN F0/19:14 + IF F0/22:0 + THEN F0/22:8 + CASE F0/23:2 + WHEN F0/24:4 + THEN F0/24:11 + RETURN F0/24:16 + WHEN F0/25:4 + THEN F0/25:11 + RETURN F0/25:16 + OTHERWISE F0/26:4 + RETURN F0/26:14 + ELSE F0/28:0 + CASE F0/29:2 + WHEN F0/30:4 + THEN F0/30:11 + RETURN F0/30:16 + WHEN F0/31:4 + THEN F0/31:11 + RETURN F0/31:16 + OTHERWISE F0/32:4 + RETURN F0/32:14 diff --git a/proparse/src/test/resources/treeparser06-expect/test02.cls b/proparse/src/test/resources/treeparser06-expect/test02.cls index 5e434de12..9d8a4be87 100644 --- a/proparse/src/test/resources/treeparser06-expect/test02.cls +++ b/proparse/src/test/resources/treeparser06-expect/test02.cls @@ -1,18 +1,18 @@ PROGRAM_ROOT F0/0:0 -- Block -- Scope - CLASS F0/1:1 - DEFINE F0/2:3 - DEFINE F0/3:3 - DEFINE F0/4:3 - CONSTRUCTOR F0/10:3 -- Block -- Scope - MESSAGE F0/11:5 - MESSAGE F0/12:5 - METHOD F0/15:3 -- Block -- Scope - DO F0/16:5 -- Block - MESSAGE F0/17:7 - DO F0/18:7 -- Block - REPEAT F0/19:9 -- Block - MESSAGE F0/20:11 - FINALLY F0/24:5 - MESSAGE F0/25:7 - MESSAGE F0/26:7 + CLASS F0/1:0 + DEFINE F0/2:2 + DEFINE F0/3:2 + DEFINE F0/4:2 + CONSTRUCTOR F0/10:2 -- Block -- Scope + MESSAGE F0/11:4 + MESSAGE F0/12:4 + METHOD F0/15:2 -- Block -- Scope + DO F0/16:4 -- Block + MESSAGE F0/17:6 + DO F0/18:6 -- Block + REPEAT F0/19:8 -- Block + MESSAGE F0/20:10 + FINALLY F0/24:4 + MESSAGE F0/25:6 + MESSAGE F0/26:6 diff --git a/proparse/src/test/resources/treeparser06-expect/test03.p b/proparse/src/test/resources/treeparser06-expect/test03.p index ff7909d24..61e1e3589 100644 --- a/proparse/src/test/resources/treeparser06-expect/test03.p +++ b/proparse/src/test/resources/treeparser06-expect/test03.p @@ -1,9 +1,9 @@ PROGRAM_ROOT F0/0:0 -- Block -- Scope - FOR F0/1:1 -- Block - UPDATE F0/2:5 - DISPLAY F0/4:8 - IF F0/5:8 - THEN F0/5:39 - MESSAGE F0/6:12 - MESSAGE F0/8:5 + FOR F0/1:0 -- Block + UPDATE F0/2:4 + DISPLAY F0/4:7 + IF F0/5:7 + THEN F0/5:38 + MESSAGE F0/6:11 + MESSAGE F0/8:4 diff --git a/proparse/src/test/resources/treeparser06-expect/test04.p b/proparse/src/test/resources/treeparser06-expect/test04.p index 0a7fc0ea0..ccdcdf354 100644 --- a/proparse/src/test/resources/treeparser06-expect/test04.p +++ b/proparse/src/test/resources/treeparser06-expect/test04.p @@ -1,8 +1,8 @@ PROGRAM_ROOT F0/0:0 -- Block -- Scope - ON F0/1:1 -- Block -- Scope - DO F0/2:1 -- Block - FIND F0/3:5 - RUN F0/4:5 - ON F0/7:1 -- Block -- Scope + ON F0/1:0 -- Block -- Scope + DO F0/2:0 -- Block + FIND F0/3:4 + RUN F0/4:4 + ON F0/7:0 -- Block -- Scope EXPR_STATEMENT F0/0:0 diff --git a/rcode-reader/pom.xml b/rcode-reader/pom.xml index 848bc8c92..b00a6b7c3 100644 --- a/rcode-reader/pom.xml +++ b/rcode-reader/pom.xml @@ -5,13 +5,12 @@ eu.rssw sonar-openedge - 2.29.1 + 2.30.0 eu.rssw.openedge.rcode rcode-reader - rcode-reader - rcode reader + RCode Reader diff --git a/rcode-reader/src/main/java/eu/rssw/pct/elements/ITypeInfo.java b/rcode-reader/src/main/java/eu/rssw/pct/elements/ITypeInfo.java index e6711e426..b87cd6783 100644 --- a/rcode-reader/src/main/java/eu/rssw/pct/elements/ITypeInfo.java +++ b/rcode-reader/src/main/java/eu/rssw/pct/elements/ITypeInfo.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.function.Function; +import org.prorefactor.core.Pair; + public interface ITypeInfo { String getTypeName(); @@ -90,7 +92,7 @@ default boolean isAssignableFrom(String clsName, Function pro return isAssignableFrom(info.getParentTypeName(), provider); } - default IMethodElement getExactMatch(Function provider, String method, DataType... parameters) { + default Pair getExactMatch(Function provider, String method, DataType... parameters) { for (IMethodElement elem : getMethods()) { if (method.equalsIgnoreCase(elem.getName()) && (elem.getParameters().length == parameters.length)) { boolean match = true; @@ -98,7 +100,7 @@ default IMethodElement getExactMatch(Function provider, Strin match &= elem.getParameters()[zz].getDataType().equals(parameters[zz]); } if (match) - return elem; + return Pair.of(this, elem); } } ITypeInfo parent = provider.apply(getParentTypeName()); @@ -108,7 +110,7 @@ default IMethodElement getExactMatch(Function provider, Strin return null; } - default IMethodElement getCompatibleMatch(Function provider, String method, DataType... parameters) { + default Pair getCompatibleMatch(Function provider, String method, DataType... parameters) { for (IMethodElement elem : getMethods()) { if (method.equalsIgnoreCase(elem.getName()) && (elem.getParameters().length == parameters.length)) { boolean match = true; @@ -116,7 +118,7 @@ default IMethodElement getCompatibleMatch(Function provider, match &= elem.getParameters()[zz].getDataType().isCompatible(parameters[zz], provider); } if (match) - return elem; + return Pair.of(this, elem); } } ITypeInfo parent = provider.apply(getParentTypeName()); @@ -126,8 +128,8 @@ default IMethodElement getCompatibleMatch(Function provider, return null; } - default IMethodElement getMethod(Function provider, String method, DataType... parameters) { - IMethodElement exactMatch = getExactMatch(provider, method, parameters); + default Pair getMethod(Function provider, String method, DataType... parameters) { + Pair exactMatch = getExactMatch(provider, method, parameters); if (exactMatch != null) return exactMatch; return getCompatibleMatch(provider, method, parameters); diff --git a/rcode-reader/src/main/java/org/prorefactor/core/Pair.java b/rcode-reader/src/main/java/org/prorefactor/core/Pair.java new file mode 100644 index 000000000..f808c431b --- /dev/null +++ b/rcode-reader/src/main/java/org/prorefactor/core/Pair.java @@ -0,0 +1,42 @@ +/* + * OpenEdge plugin for SonarQube + * Copyright (c) 2015-2024 Riverside Software + * contact AT riverside DASH software DOT fr + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.prorefactor.core; + +public class Pair { + private final X o1; + private final Y o2; + + public Pair(X o1, Y o2) { + this.o1 = o1; + this.o2 = o2; + } + + public static Pair of(A x, B y) { + return new Pair<>(x, y); + } + + public X getO1() { + return o1; + } + + public Y getO2() { + return o2; + } +} diff --git a/rcode-reader/src/test/java/eu/rssw/pct/ITypeInfoTest.java b/rcode-reader/src/test/java/eu/rssw/pct/ITypeInfoTest.java index 1a14abd88..630aa6f63 100644 --- a/rcode-reader/src/test/java/eu/rssw/pct/ITypeInfoTest.java +++ b/rcode-reader/src/test/java/eu/rssw/pct/ITypeInfoTest.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.function.Function; +import org.prorefactor.core.Pair; import org.testng.annotations.Test; import eu.rssw.pct.elements.BuiltinClasses; @@ -65,9 +66,10 @@ public void test2() { assertNotNull(info.getMethod(TYPE_INFO_PROVIDER, "Add", new DataType("Progress.Json.ObjectModel.JsonArray"))); assertNull(info.getMethod(TYPE_INFO_PROVIDER, "Add", new DataType("Progress.Lang.Object"))); - IMethodElement m1 = info.getMethod(TYPE_INFO_PROVIDER, "GetDatetime", DataType.INTEGER, DataType.INTEGER); - assertNotNull(m1); - assertEquals(m1.getReturnType(), DataType.DATETIME); + Pair val1 = info.getMethod(TYPE_INFO_PROVIDER, "GetDatetime", DataType.INTEGER, DataType.INTEGER); + assertNotNull(val1); + assertEquals(val1.getO1().getTypeName(), "Progress.Json.ObjectModel.JsonArray"); + assertEquals(val1.getO2().getReturnType(), DataType.DATETIME); } @Test @@ -95,12 +97,14 @@ public void test4() { map.put(typeInfo02.getTypeName(), typeInfo02); // Expected is method from parent class - IMethodElement m1 = typeInfo02.getMethod(name -> map.get(name), "method1", DataType.INTEGER); - assertNotNull(m1); - assertEquals(m1.getReturnType(), DataType.VOID); + Pair val1 = typeInfo02.getMethod(map::get, "method1", DataType.INTEGER); + assertNotNull(val1); + assertEquals(val1.getO1().getTypeName(), "rssw.ParentClass"); + assertEquals(val1.getO2().getReturnType(), DataType.VOID); // Expected is method from child class - IMethodElement m2 = typeInfo02.getMethod(name -> map.get(name), "method1", DataType.INT64); - assertNotNull(m2); - assertEquals(m2.getReturnType(), DataType.INTEGER); + Pair val2 = typeInfo02.getMethod(map::get, "method1", DataType.INT64); + assertNotNull(val2); + assertEquals(val2.getO1().getTypeName(), "rssw.ChildClass"); + assertEquals(val2.getO2().getReturnType(), DataType.INTEGER); } }