use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class ControlFlowEdger method addInstanceofExpressionEdges.
private List<ExitEdge> addInstanceofExpressionEdges(Dag dag, DagNode node, LexicalScope scope) {
InstanceofExpression ioe = (InstanceofExpression) node.astNode;
DagNode expressionDag = getDagChild(node.children, ioe.getLeftOperand(), null);
DagNode typeDag = getDagChild(node.children, ioe.getRightOperand(), null);
node.gvAttributes.put("type", ioe.getRightOperand().toString());
Rejigger rejigger = hoistNode(dag, node, expressionDag);
List<ExitEdge> prevNodes = addExpressionEdges(dag, expressionDag, scope);
/*
if (typeDag != null) { // types have Names, which are also expressions, but they're inside the ast node so typeDag is null
for (DagEdge e : prevNodes) {
e.n2 = typeDag;
}
ExitEdge e = new ExitEdge();
e.n1 = typeDag;
prevNodes = Collections.singletonList(e);
}
*/
prevNodes = rejigger.unhoistNode(dag, prevNodes);
return prevNodes;
}
use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class ControlFlowEdger method addClassInstanceCreationEdges.
private List<ExitEdge> addClassInstanceCreationEdges(Dag dag, DagNode node, LexicalScope scope) {
ClassInstanceCreation cic = (ClassInstanceCreation) node.astNode;
// maybe we evaluate the index first ? not sure. reckon it's probably the array ref
DagNode expressionDag = getDagChild(node.children, cic.getExpression(), null);
List<DagNode> argumentDags = getDagChildren(node.children, cic.arguments(), null);
DagNode anonClassDag = getDagChild(node.children, cic.getAnonymousClassDeclaration(), "anonymousClass");
// AnonymousClassDeclaration
node.gvAttributes.put("type", cic.getType().toString());
// DagNode indexDag = getDagChild(node.children, fa.getIndex(), null);
// DagNode fieldDag = getDagChild(node.children, fa.getName(), null); // will put the name on the FA node
List<ExitEdge> prevNodes = null;
if (expressionDag != null || argumentDags.size() > 0) {
// move methodInvocation node after the expression & argument nodes
Rejigger rejigger = hoistNode(dag, node, 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 = node;
prevNodes = Collections.singletonList(e);
}
// jam the anonymous class in here as if it was a lambda, but with methods like a class
if (anonClassDag != null) {
for (ExitEdge e : prevNodes) {
e.n2 = anonClassDag;
addEdge(e);
}
AnonymousClassDeclaration acdNode = (AnonymousClassDeclaration) anonClassDag.astNode;
List<DagNode> bodyDeclarationDags = getDagChildren(anonClassDag.children, acdNode.bodyDeclarations(), null);
LexicalScope lexicalScope = scope.newTypeScope();
// add edges for everything in the class
// @TODO check fields don't appear though. unless they initalise things, then maybe. Or maybe that goes into the constructors.
// or not.
// yeesh what about the static initializers. what about them indeed.
List<ExitEdge> ees = new ArrayList<>();
for (DagNode n : bodyDeclarationDags) {
// add a transparent edge to each thing defined in this class so that the 'AnonymousClassDeclaration' node appears above them
DagEdge e = addEdge(anonClassDag, n);
e.classes.add("anonymousClassDeclarationBegin");
ees.addAll(addEdges(dag, n, lexicalScope));
}
// add an artificial node so we can create an edge out of this thing
CompilationUnit cu = ASTResolving.findParentCompilationUnit(acdNode);
int endOfAnonClassLine = cu.getLineNumber(acdNode.getStartPosition() + acdNode.getLength());
DagNode returnNode = new DagNode();
returnNode.keepNode = anonClassDag.keepNodeMatcher.matches("anonymousClassDeclarationEnd");
returnNode.type = "anonymousClassDeclarationEnd";
returnNode.lineNumber = endOfAnonClassLine;
// rn.name = dag.getUniqueName("m_" + endOfMethodLine);
returnNode.classes.add("anonymousClassDeclaration");
returnNode.classes.add("end");
// rn.label = "return";
returnNode.astNode = null;
// include the artificial return inside the lambda grouping
anonClassDag.children.add(returnNode);
DagSubgraph sg = dag.dagNodeToSubgraph.get(anonClassDag);
dag.addNode(sg, returnNode);
for (ExitEdge ee : ees) {
// add a transparent edge from each thing defined in this class to the artifical node
// so that it appears underneath them
ee.n2 = returnNode;
ee.classes.add("anonymousClassDeclarationEnd");
addEdge(ee);
}
// there's no exit edges out of an anonymous class
// this gets truncated to the subgraph boundary in some css
ExitEdge e = new ExitEdge();
e.n1 = returnNode;
prevNodes = Collections.singletonList(e);
}
return prevNodes;
}
use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class ControlFlowEdger method addBlockEdges.
// draw lines from each statement to each other
// exit node is the last statement
private List<ExitEdge> addBlockEdges(Dag dag, DagNode block, LexicalScope scope) {
// draw the edges from the block
ExitEdge start = new ExitEdge();
start.n1 = block;
List<ExitEdge> prevNodes = Collections.singletonList(start);
for (DagNode c : block.children) {
if (!c.skipNode) {
for (ExitEdge e : prevNodes) {
e.n2 = c;
addEdge(e);
}
prevNodes = addEdges(dag, c, scope);
}
}
return prevNodes;
}
use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class ControlFlowEdger method addLambdaExpressionEdges.
private List<ExitEdge> addLambdaExpressionEdges(Dag dag, DagNode lambdaNode, LexicalScope scope) {
// lambda expression is going to be a big like a method declaration in the middle of a method.
// but has an exit edge
LambdaExpression le = (LambdaExpression) lambdaNode.astNode;
// method.label = "method " + md.getName();
// method.gvAttributes.put("methodName", md.getName().toString());
// we don't create nodes for method parameters yet, so not going to do that for lambdas either
// (maybe we should ? )
// when a lambda is defined control flow doesn't pass to the block,
// so maybe I skip all of that somehow. OK so let's create an edge so it's grouped together but hide it in the diagram.
DagNode blockNode = lambdaNode.children.get(lambdaNode.children.size() - 1);
DagEdge lambdaEntryEdge = addEdge(lambdaNode, blockNode);
lambdaEntryEdge.classes.add("lambdaEntry");
// @TODO these probably need a new lexical scope
LexicalScope lexicalScope = scope.newLambdaScope();
List<ExitEdge> ee;
if (blockNode.type.equals("Block")) {
ee = addBlockEdges(dag, blockNode, lexicalScope);
} else if (blockNode.astNode instanceof Expression) {
ee = addExpressionEdges(dag, blockNode, lexicalScope);
} else {
throw new IllegalStateException("expected Block or Expression in lambda");
}
// add a node which all the return edges return to
// this is an artificial node so maybe only construct it based on some gv declaration earlier on ?
// (whereas all the other nodes are about as concrete as anything else in IT)
// CompilationUnit cu = methodBlock.astNode.getParent();
CompilationUnit cu = ASTResolving.findParentCompilationUnit(le);
int endOfLambdaLine = cu.getLineNumber(le.getStartPosition() + le.getLength());
DagNode returnNode = new DagNode();
returnNode.keepNode = lambdaNode.keepNodeMatcher.matches("lambdaExpressionEnd");
// label this 'end' if it has no return value ?
returnNode.type = "lambdaExpressionEnd";
returnNode.lineNumber = endOfLambdaLine;
// rn.name = dag.getUniqueName("m_" + endOfMethodLine);
returnNode.classes.add("lambdaExpression");
returnNode.classes.add("end");
// rn.label = "return";
returnNode.astNode = null;
// include the artificial return inside the lambda grouping
lambdaNode.children.add(returnNode);
DagSubgraph sg = dag.dagNodeToSubgraph.get(lambdaNode);
dag.addNode(sg, returnNode);
for (ExitEdge e : lexicalScope.returnEdges) {
e.n2 = returnNode;
addEdge(e);
}
for (ExitEdge e : ee) {
e.n2 = returnNode;
addEdge(e);
}
// and everything that was thrown connects to this node as well
for (ExitEdge e : lexicalScope.throwEdges) {
e.n2 = returnNode;
addEdge(e);
}
// there's no exit edges out of a method, but let's say there is from a lambda
// (it's not a real edge, it gets truncated to the subgraph boundary in some css)
ExitEdge e = new ExitEdge();
e.n1 = returnNode;
return Collections.singletonList(e);
}
use of com.randomnoun.build.javaToGraphviz.dag.DagNode in project java-to-graphviz by randomnoun.
the class ControlFlowEdger method addVariableDeclarationStatementEdges.
private List<ExitEdge> addVariableDeclarationStatementEdges(Dag dag, DagNode node, LexicalScope scope) {
// modifiers, type, varDecFragments
VariableDeclarationStatement vs = (VariableDeclarationStatement) node.astNode;
List<DagNode> fragments = getDagChildren(node.children, vs.fragments(), null);
node.gvAttributes.put("type", vs.getType().toString());
ExitEdge e = new ExitEdge();
e.n1 = node;
List<ExitEdge> prevNodes = Collections.singletonList(e);
for (DagNode f : fragments) {
for (ExitEdge pe : prevNodes) {
pe.n2 = f;
dag.edges.add(pe);
}
e = new ExitEdge();
e.n1 = f;
prevNodes = Collections.singletonList(e);
// name, dimension(s), expression
VariableDeclarationFragment vdf = (VariableDeclarationFragment) f.astNode;
DagNode expressionDag = getDagChild(f.children, vdf.getInitializer(), null);
if (expressionDag != null) {
Rejigger rejigger = hoistNode(dag, f, expressionDag);
prevNodes = addExpressionEdges(dag, expressionDag, scope);
prevNodes = rejigger.unhoistNode(dag, prevNodes);
}
f.gvAttributes.put("type", vs.getType().toString());
f.gvAttributes.put("variableName", vdf.getName().toString());
}
return prevNodes;
}
Aggregations