use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class ControlFlowEdger method addSuperConstructorInvocationEdges.
private List<ExitEdge> addSuperConstructorInvocationEdges(Dag dag, DagNode superConstructorInvocationNode, LexicalScope scope) {
SuperConstructorInvocation mi = (SuperConstructorInvocation) superConstructorInvocationNode.astNode;
DagNode expressionDag = getDagChild(superConstructorInvocationNode.children, mi.getExpression(), null);
superConstructorInvocationNode.gvAttributes.put("methodName", "super");
List<DagNode> argumentDags = getDagChildren(superConstructorInvocationNode.children, mi.arguments(), null);
List<ExitEdge> prevNodes = null;
if (expressionDag != null || argumentDags.size() > 0) {
// move methodInvocation node after the expression & argument nodes
Rejigger rejigger = hoistNode(dag, superConstructorInvocationNode, expressionDag != null ? expressionDag : argumentDags.get(0));
// expression is null for method calls within the same object
if (expressionDag != null) {
prevNodes = addExpressionEdges(dag, expressionDag, scope);
}
for (DagNode a : argumentDags) {
if (prevNodes != null) {
for (ExitEdge e : prevNodes) {
e.n2 = a;
e.classes.add("invocationArgument");
addEdge(e);
}
}
prevNodes = addExpressionEdges(dag, a, scope);
}
prevNodes = rejigger.unhoistNode(dag, prevNodes);
} else {
ExitEdge e = new ExitEdge();
e.n1 = superConstructorInvocationNode;
prevNodes = Collections.singletonList(e);
}
return prevNodes;
}
use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class JavaToGraphviz method writeGraphviz.
/**
* Generate a single graphviz diagram.
*
* @param writer
* @return true if there are more diagrams, false otherwise
* @throws IOException
*/
public boolean writeGraphviz(Writer writer) throws IOException {
DagSubgraph rootGraph = dag.rootGraphs.get(rootGraphIdx);
PrintWriter pw = new PrintWriter(writer);
// remove edges from previous runs
dag.edges.clear();
// a rootGraph can now contain multiple rootNodes
// but a rootNode can only be in a single rootGraph
int c = 0;
for (DagNode rootNode : dag.rootNodes) {
c++;
if (rootGraph.nodes.contains(rootNode)) {
// logger.info("including rootNode " + c);
String edgerNamesCsv = rootNode.options.get("edgerNamesCsv");
if (Text.isBlank(edgerNamesCsv)) {
edgerNamesCsv = "control-flow";
}
boolean enableKeepNodeFilter = "true".equals(rootNode.options.get("enableKeepNodeFilter"));
List<String> edgerNames;
try {
edgerNames = Text.parseCsv(edgerNamesCsv);
} catch (ParseException e1) {
throw new IllegalArgumentException("edgerNamesCsv is not valid CSV", e1);
}
rootNode.options.get("removeNodes");
LexicalScope lexicalScope = new LexicalScope();
for (String edgerName : edgerNames) {
if (edgerName.equals("control-flow")) {
ControlFlowEdger edger = new ControlFlowEdger(dag);
edger.addEdges(dag, rootNode, lexicalScope);
} else if (edgerName.equals("ast")) {
AstEdger edger = new AstEdger(dag);
edger.addEdges(dag, rootNode, lexicalScope);
// @TODO data-flow
} else {
throw new IllegalArgumentException("unknown edgerName '" + edgerName + "'");
}
}
// going to assume that edges don't cross rootNodes, which they don't yet either.
for (DagNode n : dag.nodes) {
n.inEdges = new ArrayList<>();
n.outEdges = new ArrayList<>();
}
for (DagEdge e : dag.edges) {
e.n1.outEdges.add(e);
e.n2.inEdges.add(e);
}
if (enableKeepNodeFilter) {
DagNodeFilter filter = new DagNodeFilter(dag);
if (rootNode.keepNodeMatcher.matches("startNode")) {
rootNode.keepNode = true;
filter.setLastKeepNode(rootNode, rootNode);
} else {
rootNode.keepNode = false;
}
filter.removeNodes(rootNode);
}
}
}
// subgraphs are now defined in the Dag from the stylesheet
DagStyleApplier dsa = new DagStyleApplier(dag, rootGraph);
Document doc = dsa.createDom();
if (format.equals("dom1")) {
pw.println(doc.toString());
} else {
dsa.inlineStyles(styleSheet);
}
if (format.equals("dom1")) {
// already generated output
} else if (format.equals("dom2")) {
doc = dsa.getDocument();
pw.println(doc.toString());
} else {
pw.println(rootGraph.toGraphviz(0));
}
rootGraphIdx++;
return (rootGraphIdx < dag.rootGraphs.size());
}
use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class AstEdger method addEdges.
/**
* Adds the edges for a DagNode into the Dag, and returns the edges leading out of that DagNode
* (which may now be labelled)
*
* @param dag
* @param node
* @param scope a lexical scope, which define the boundary for 'break', 'continue', 'return' and 'throws' statements
*/
public void addEdges(Dag dag, DagNode node, LexicalScope scope) {
if (node.type.equals("SimpleName") || node.type.equals("QualifiedName")) {
addNameAttributes(dag, node, scope);
}
if (node.children != null && node.children.size() > 0) {
for (DagNode c : node.children) {
DagEdge ce = dag.addEdge(node, c);
ce.classes.add("ast");
addEdges(dag, c, scope);
}
}
}
use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class AstToDagVisitor method getStartingDagNodeOnLine.
private DagNode getStartingDagNodeOnLine(int originalLine) {
// find the first ast node on this line which has a dag node
List<ASTNode> astNodes = startLineNumberAsts.get(originalLine);
if (astNodes == null) {
return null;
}
// first dag node that doesn't already have a comment
for (int i = 0; i < astNodes.size(); i++) {
ASTNode n = astNodes.get(i);
DagNode dn = dag.astToDagNode.get(n);
if (dn != null && !dn.hasComment) {
return dn;
}
}
// there isn't one; first dag node
for (int i = 0; i < astNodes.size(); i++) {
ASTNode n = astNodes.get(i);
DagNode dn = dag.astToDagNode.get(n);
if (dn != null) {
return dn;
}
}
return null;
}
use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class AstToDagVisitor method processCommentsToTypeOrMethodNode.
private void processCommentsToTypeOrMethodNode(DagNode pdn, int line, DagNode mn) {
// DagNode lastNode = null;
while (lastIdx < comments.size() && comments.get(lastIdx).line < line) {
CommentText ct = comments.get(lastIdx);
/*
DagNode dn = new DagNode();
dn.keepNode = true; // always keep comments
dn.type = "comment";
dn.line = ct.line;
dn.name = dag.getUniqueName("c_" + ct.line);
dn.label = ct.text;
dn.astNode = null;
dn.options = options;
*/
DagNode dn = null;
if (ct instanceof GvComment) {
mn.classes.addAll(((GvComment) ct).classes);
// last comment wins
mn.label = ct.text;
} else if (ct instanceof GvGraphComment) {
GvGraphComment gc = ((GvGraphComment) ct);
// to remove the class ast node from the 0th root graph
if (rootGraphIdx == 0) {
dag.clear();
root = new DagSubgraph(dag, null);
dag.rootGraphs.add(root);
} else {
root = new DagSubgraph(dag, null);
dag.rootGraphs.add(root);
}
root.name = gc.id;
root.classes.addAll(gc.classes);
// append to existing ?
root.gvAttributes.put("style", gc.inlineStyleString);
rootGraphIdx++;
} else if (ct instanceof GvEndGraphComment) {
if (rootGraphIdx == 0) {
throw new IllegalStateException("gv-endGraph without gv-graph");
} else {
root = null;
}
} else if (ct instanceof GvSubgraphComment) {
GvSubgraphComment gvsc = (GvSubgraphComment) ct;
dn = new DagNode();
// dn.name = dag.getUniqueName("c_" + ct.line);
// always keep gv comments
dn.keepNode = true;
dn.type = "comment";
dn.lineNumber = ct.line;
dn.classes.add("comment");
dn.label = ct.text;
dn.astNode = null;
dn.options = options;
dn.keepNodeMatcher = keepNodeMatcher;
dn.name = gvsc.id;
dn.classes.addAll(gvsc.classes);
dn.classes.add("beginSubgraph");
} else if (ct instanceof GvEndSubgraphComment) {
dn = new DagNode();
// dn.name = dag.getUniqueName("c_" + ct.line);
// always keep gv comments
dn.keepNode = true;
dn.type = "comment";
dn.lineNumber = ct.line;
dn.classes.add("comment");
dn.label = ct.text;
dn.astNode = null;
dn.options = options;
dn.keepNodeMatcher = keepNodeMatcher;
dn.classes.add("endSubgraph");
} else if (ct instanceof GvLiteralComment) {
logger.warn("gv-literal outside of method");
} else if (ct instanceof GvKeepNodeComment) {
GvKeepNodeComment knc = ((GvKeepNodeComment) ct);
boolean defaultKeepNode = "true".equals(options.get("defaultKeepNode"));
keepNodeMatcher = keepNodeMatcher.getModifiedKeepNodeMatcher(defaultKeepNode, knc.text.trim());
} else if (ct instanceof GvOptionComment) {
GvOptionComment oc = ((GvOptionComment) ct);
options = newOptions(oc.text.trim());
}
if (dn != null) {
if (pdn != null) {
if (root == null) {
throw new IllegalStateException("gv comment outside of graph");
}
dag.addNode(root, dn);
pdn.addChild(dn);
} else {
// could add as a root node, but let's see how we go
throw new IllegalStateException("null pdn in processCommentsToTypeOrMethodNode");
}
}
lastIdx++;
}
}
Aggregations