From b77b55ad145bd5d4905d6260be5de34c91688e03 Mon Sep 17 00:00:00 2001 From: avishek-sen-gupta Date: Sat, 13 Jul 2024 02:16:51 +0530 Subject: [PATCH] Testing GraphPatternMatcher Adding missing files --- .../org/smojol/common/flowchart/FlowNode.java | 1 + .../analysis/graph/GraphExplorerMain.java | 8 ++- .../analysis/graph/GraphPatternMatcher.java | 58 +++++++++++++++++++ .../analysis/graph/Neo4JFlowCFGVisitor.java | 3 +- .../java/org/smojol/ast/CobolFlowNode.java | 10 +++- .../smojol/ast/CompositeCobolFlowNode.java | 11 ++++ .../smojol/ast/GenericProcessingFlowNode.java | 5 ++ .../org/smojol/ast/MergingChartOverlay.java | 7 +-- .../java/org/smojol/ast/NullFlowNode.java | 5 ++ 9 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 smojol-toolkit/src/main/java/org/smojol/analysis/graph/GraphPatternMatcher.java diff --git a/smojol-core/src/main/java/org/smojol/common/flowchart/FlowNode.java b/smojol-core/src/main/java/org/smojol/common/flowchart/FlowNode.java index 89167ada..7dce7165 100644 --- a/smojol-core/src/main/java/org/smojol/common/flowchart/FlowNode.java +++ b/smojol-core/src/main/java/org/smojol/common/flowchart/FlowNode.java @@ -23,6 +23,7 @@ public interface FlowNode { void linkParentToChild(FlowNodeVisitor visitor, int level); void accept(FlowNodeVisitor visitor, int level); + void accept(FlowNodeVisitor visitor, FlowNodeCondition stopCondition, int level); void acceptUnvisited(FlowNodeVisitor visitor, int level); List getChildren(); diff --git a/smojol-toolkit/src/main/java/org/smojol/analysis/graph/GraphExplorerMain.java b/smojol-toolkit/src/main/java/org/smojol/analysis/graph/GraphExplorerMain.java index 3a62cfef..2cd6d031 100644 --- a/smojol-toolkit/src/main/java/org/smojol/analysis/graph/GraphExplorerMain.java +++ b/smojol-toolkit/src/main/java/org/smojol/analysis/graph/GraphExplorerMain.java @@ -66,7 +66,7 @@ public static void main(String[] args) throws IOException, InterruptedException Record neo4jProgramRoot = sdk.findNodes(qualifier.astNodeCriteria(Map.of(TYPE, FlowNodeType.PROCEDURE_DIVISION_BODY.toString()))).getFirst(); // Summarises AST bottom-up - sdk.traverse(neo4jProgramRoot, new SummariseAction(advisor, sdk), CONTAINS); +// sdk.traverse(neo4jProgramRoot, new SummariseAction(advisor, sdk), CONTAINS); // Builds data structures dataStructures.accept(new Neo4JDataStructureVisitor(sdk, qualifier), null, n -> false, dataStructures); @@ -77,6 +77,10 @@ public static void main(String[] args) throws IOException, InterruptedException Record neo4jDataStructuresRoot = sdk.findNodes(qualifier.dataNodeSearchCriteria(Map.of(TYPE, "ROOT"))).getFirst(); // Summarises data structures - sdk.traverse(neo4jDataStructuresRoot, new DataStructureSummariseAction(advisor, sdk), CONTAINS); +// sdk.traverse(neo4jDataStructuresRoot, new DataStructureSummariseAction(advisor, sdk), CONTAINS); + + GraphPatternMatcher visitor = new GraphPatternMatcher(sdk); + root.accept(visitor, node -> node.type() == FlowNodeType.SENTENCE, -1); + System.out.printf("Number of groups = %s%n", visitor.getMatches().size()); } } diff --git a/smojol-toolkit/src/main/java/org/smojol/analysis/graph/GraphPatternMatcher.java b/smojol-toolkit/src/main/java/org/smojol/analysis/graph/GraphPatternMatcher.java new file mode 100644 index 00000000..b68215fd --- /dev/null +++ b/smojol-toolkit/src/main/java/org/smojol/analysis/graph/GraphPatternMatcher.java @@ -0,0 +1,58 @@ +package org.smojol.analysis.graph; + +import com.mojo.woof.GraphSDK; +import lombok.Getter; +import org.eclipse.lsp.cobol.core.CobolParser; +import org.smojol.common.flowchart.*; + +import java.util.ArrayList; +import java.util.List; + +public class GraphPatternMatcher implements FlowNodeVisitor { + private final GraphSDK sdk; + @Getter + private final List> matches = new ArrayList<>(); + private List currentMatch = new ArrayList<>(); + + public GraphPatternMatcher(GraphSDK sdk) { + this.sdk = sdk; + } + + @Override + public void visit(FlowNode node, List outgoingNodes, List incomingNodes, VisitContext context, FlowNodeService nodeService) { + System.out.println(String.format("Visiting %s", node)); + if (node.type() == FlowNodeType.SENTENCE && node.astChildren().size() == 1 && node.astChildren().getFirst().type() == FlowNodeType.MOVE) { + registerMove(node); + return; + } + if (currentMatch.isEmpty()) return; + matches.add(currentMatch); + currentMatch = new ArrayList<>(); + } + + private void registerMove(FlowNode node) { + currentMatch.add(node); + } + + @Override + public void visitParentChildLink(FlowNode parent, FlowNode internalTreeRoot, VisitContext ctx, FlowNodeService nodeService) { + } + + @Override + public void visitParentChildLink(FlowNode parent, FlowNode internalTreeRoot, VisitContext ctx, FlowNodeService nodeService, FlowNodeCondition hideStrategy) { + } + + @Override + public void visitControlTransfer(FlowNode from, FlowNode to, VisitContext visitContext) { + } + + @Override + public FlowNodeVisitor newScope(FlowNode enclosingScope) { + return this; + } + + @Override + public void group(FlowNode root) { + + } +} diff --git a/smojol-toolkit/src/main/java/org/smojol/analysis/graph/Neo4JFlowCFGVisitor.java b/smojol-toolkit/src/main/java/org/smojol/analysis/graph/Neo4JFlowCFGVisitor.java index 63da1b68..07db9fa3 100644 --- a/smojol-toolkit/src/main/java/org/smojol/analysis/graph/Neo4JFlowCFGVisitor.java +++ b/smojol-toolkit/src/main/java/org/smojol/analysis/graph/Neo4JFlowCFGVisitor.java @@ -6,8 +6,6 @@ import java.util.List; -import static com.mojo.woof.NodeRelations.*; - public class Neo4JFlowCFGVisitor implements FlowNodeVisitor { private final GraphSDK sdk; private final NodeSpecBuilder qualifier; @@ -49,6 +47,7 @@ public void visitControlTransfer(FlowNode from, FlowNode to, VisitContext visitC Record destinationRecord = newOrExisting(to); sdk.jumpsTo(sourceRecord, destinationRecord); } + @Override public FlowNodeVisitor newScope(FlowNode enclosingScope) { return this; diff --git a/smojol-toolkit/src/main/java/org/smojol/ast/CobolFlowNode.java b/smojol-toolkit/src/main/java/org/smojol/ast/CobolFlowNode.java index 4cca2d05..2caae042 100644 --- a/smojol-toolkit/src/main/java/org/smojol/ast/CobolFlowNode.java +++ b/smojol-toolkit/src/main/java/org/smojol/ast/CobolFlowNode.java @@ -135,12 +135,20 @@ public void accept(FlowNodeVisitor visitor, int level) { acceptUnvisited(visitor, level); } + @Override + public void accept(FlowNodeVisitor visitor, FlowNodeCondition stopRecurseCondition, int level) { + acceptUnvisited(visitor, stopRecurseCondition, level); + } + public void acceptUnvisited(FlowNodeVisitor visitor, int level) { -// System.out.println("Current level: " + level); visitor.visit(this, outgoingNodes, incomingNodes, new VisitContext(level), nodeService); outgoingNodes.forEach(c -> c.accept(visitor, level)); } + public void acceptUnvisited(FlowNodeVisitor visitor, FlowNodeCondition stopCondition, int level) { + acceptUnvisited(visitor, level); + } + @Override public void addIncomingNode(FlowNode flowNode) { incomingNodes.add(flowNode); diff --git a/smojol-toolkit/src/main/java/org/smojol/ast/CompositeCobolFlowNode.java b/smojol-toolkit/src/main/java/org/smojol/ast/CompositeCobolFlowNode.java index 0c4c5ffa..3a1f05f3 100644 --- a/smojol-toolkit/src/main/java/org/smojol/ast/CompositeCobolFlowNode.java +++ b/smojol-toolkit/src/main/java/org/smojol/ast/CompositeCobolFlowNode.java @@ -64,6 +64,17 @@ public void acceptUnvisited(FlowNodeVisitor visitor, int level) { } } + @Override + public void acceptUnvisited(FlowNodeVisitor visitor, FlowNodeCondition stopRecurseCondition, int level) { + visitor.visit(this, outgoingNodes, incomingNodes, new VisitContext(level), nodeService); + if (!stopRecurseCondition.apply(this) && internalTreeRoot != null) { + linkParentToChild(visitor, level); + FlowNode current = internalTreeRoot; + current.accept(visitor.newScope(this), stopRecurseCondition, level + 1); + } + outgoingNodes.forEach(c -> c.accept(visitor, stopRecurseCondition, level)); + } + @Override public FlowNode next(FlowNodeCondition nodeCondition, FlowNode startingNode, boolean isComplete) { System.out.println("Moved up to " + executionContext.getClass() + executionContext.getText()); diff --git a/smojol-toolkit/src/main/java/org/smojol/ast/GenericProcessingFlowNode.java b/smojol-toolkit/src/main/java/org/smojol/ast/GenericProcessingFlowNode.java index 4fdd4148..8f7844c0 100644 --- a/smojol-toolkit/src/main/java/org/smojol/ast/GenericProcessingFlowNode.java +++ b/smojol-toolkit/src/main/java/org/smojol/ast/GenericProcessingFlowNode.java @@ -70,6 +70,11 @@ public void accept(FlowNodeVisitor visitor, int level) { } + @Override + public void accept(FlowNodeVisitor visitor, FlowNodeCondition stopCondition, int level) { + + } + @Override public List getChildren() { return List.of(); diff --git a/smojol-toolkit/src/main/java/org/smojol/ast/MergingChartOverlay.java b/smojol-toolkit/src/main/java/org/smojol/ast/MergingChartOverlay.java index 179cad6f..5d32e7eb 100644 --- a/smojol-toolkit/src/main/java/org/smojol/ast/MergingChartOverlay.java +++ b/smojol-toolkit/src/main/java/org/smojol/ast/MergingChartOverlay.java @@ -18,8 +18,7 @@ public FlowNode block(FlowNode node) { if (containingGroups.isEmpty()) return node; if (containingGroups.size() == 1) return containingGroups.getFirst(); // Filters out lower-level groups which are GenericStatement aggregations - // TODO: This is very similar to the OverlayVisitor's condition. Maybe some refactoring to isAtomicType() is needed - return containingGroups.stream().filter(g -> !isAtomic2(g)).findFirst().get(); + return containingGroups.stream().filter(g -> !isAtomic(g)).findFirst().get(); } public static boolean isAtomic(FlowNode node) { @@ -32,8 +31,4 @@ public static boolean isAtomic(FlowNode node) { node.getClass() == DivideFlowNode.class || node.getClass() == AddFlowNode.class; } - - private static boolean isAtomic2(GenericProcessingFlowNode g) { - return isAtomic(g); - } } diff --git a/smojol-toolkit/src/main/java/org/smojol/ast/NullFlowNode.java b/smojol-toolkit/src/main/java/org/smojol/ast/NullFlowNode.java index 310827cf..5cf09bd5 100644 --- a/smojol-toolkit/src/main/java/org/smojol/ast/NullFlowNode.java +++ b/smojol-toolkit/src/main/java/org/smojol/ast/NullFlowNode.java @@ -66,6 +66,11 @@ public void accept(FlowNodeVisitor visitor, int level) { } + @Override + public void accept(FlowNodeVisitor visitor, FlowNodeCondition stopCondition, int level) { + + } + @Override public List getChildren() { return List.of();