package tfm.nodes; import com.github.javaparser.ast.Node; import org.jetbrains.annotations.NotNull; import tfm.graphs.cfg.CFG; import tfm.graphs.pdg.PDG; import tfm.graphs.sdg.SDG; import tfm.nodes.factories.NodeFactory; import tfm.nodes.factories.StatementNodeFactory; import tfm.nodes.type.NodeType; import tfm.utils.Utils; import tfm.variables.VariableExtractor; import java.util.Collection; import java.util.HashSet; import java.util.Objects; import java.util.Set; /** * Represents a node in the various graphs ({@link CFG CFG}, * {@link PDG PDG} and {@link SDG SDG}), * including its AST representation and the connections it has to other nodes * in the same graph. It can hold a string of characters that will be used * to represent it. *
* It is immutable. * @param The type of the AST represented by this node. */ public class GraphNode implements Comparable> { public static final NodeFactory DEFAULT_FACTORY = new StatementNodeFactory(); private NodeType nodeType; private final long id; private final String instruction; private final N astNode; private final Set declaredVariables; private final Set definedVariables; private final Set usedVariables; GraphNode(long id, NodeType type, String instruction, @NotNull N astNode) { this( id, type, instruction, astNode, Utils.emptySet(), Utils.emptySet(), Utils.emptySet() ); extractVariables(astNode); } GraphNode( long id, NodeType type, String instruction, @NotNull N astNode, Collection declaredVariables, Collection definedVariables, Collection usedVariables ) { this.id = id; this.nodeType = type; this.instruction = instruction; this.astNode = astNode; this.declaredVariables = new HashSet<>(declaredVariables); this.definedVariables = new HashSet<>(definedVariables); this.usedVariables = new HashSet<>(usedVariables); } private void extractVariables(@NotNull Node node) { new VariableExtractor() .setOnVariableDeclarationListener(this.declaredVariables::add) .setOnVariableDefinitionListener(this.definedVariables::add) .setOnVariableUseListener(this.usedVariables::add) .visit(node); } public long getId() { return id; } public String toString() { return String.format("GraphNode{id: %s, type: %s, instruction: '%s', astNodeType: %s}", getId(), getNodeType(), getInstruction(), getAstNode().getClass().getSimpleName() ); } public N getAstNode() { return astNode; } public void addDeclaredVariable(String variable) { declaredVariables.add(variable); } public void addDefinedVariable(String variable) { definedVariables.add(variable); } public void addUsedVariable(String variable) { usedVariables.add(variable); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof GraphNode)) return false; GraphNode other = (GraphNode) o; return Objects.equals(getId(), other.getId()) && Objects.equals(getNodeType(), other.getNodeType()) && Objects.equals(getInstruction(), other.getInstruction()) && Objects.equals(astNode, other.astNode); } @Override public int hashCode() { return Objects.hash(getId(), getNodeType(), getInstruction(), getAstNode()); } public Set getDeclaredVariables() { return declaredVariables; } public Set getDefinedVariables() { return definedVariables; } public Set getUsedVariables() { return usedVariables; } public String getInstruction() { return instruction; } @Override public int compareTo(@NotNull GraphNode o) { return Long.compare(id, o.id); } public NodeType getNodeType() { return nodeType; } }