DFAPanel.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
net.sourceforge.pmd.util.designer |
![]() |
![]() |
PMD |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
package net.sourceforge.pmd.util.designer;
import net.sourceforge.pmd.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.ast.SimpleNode;
import net.sourceforge.pmd.dfa.IDataFlowNode;
import net.sourceforge.pmd.dfa.variableaccess.VariableAccess;
import net.sourceforge.pmd.util.LineGetter;
import net.sourceforge.pmd.util.StringUtil;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.util.List;
public class DFAPanel extends JComponent implements ListSelectionListener {
public static class DFACanvas extends JPanel {
private static final int NODE_RADIUS = 12;
private static final int NODE_DIAMETER = 2 * NODE_RADIUS;
private SimpleNode node;
private int x = 150;
private int y = 50;
private LineGetter lines;
private void addAccessLabel(StringBuffer sb, VariableAccess va) {
if (va.isDefinition()) {
sb.append("d(");
} else if (va.isReference()) {
sb.append("r(");
} else if (va.isUndefinition()) {
sb.append("u(");
//continue; // eo - the u() entries add a lot of clutter to the report
} else {
sb.append("?(");
}
sb.append(va.getVariableName()).append(')');
}
private String childIndicesOf(IDataFlowNode node, String separator) {
List kids = node.getChildren();
if (kids.isEmpty()) return "";
StringBuffer sb = new StringBuffer();
sb.append(((IDataFlowNode)kids.get(0)).getIndex());
for (int j = 1; j < node.getChildren().size(); j++) {
sb.append(separator);
sb.append(((IDataFlowNode)kids.get(j)).getIndex());
}
return sb.toString();
}
private String[] deriveAccessLabels(List flow) {
if (flow == null || flow.isEmpty()) return StringUtil.EMPTY_STRINGS;
String[] labels = new String[flow.size()];
for (int i=0; i<labels.length; i++) {
List access = ((IDataFlowNode) flow.get(i)).getVariableAccess();
if (access == null || access.isEmpty()) {
continue; // leave a null at this slot
}
StringBuffer exp = new StringBuffer();
addAccessLabel(exp, (VariableAccess) access.get(0));
for (int k = 1; k < access.size(); k++) {
exp.append(", ");
addAccessLabel(exp, (VariableAccess) access.get(k));
}
labels[i] = exp.toString();
}
return labels;
}
private int maxWidthOf(String[] strings, FontMetrics fm) {
int max = 0;
String str;
for (int i=0; i<strings.length; i++) {
str = strings[i];
if (str == null) continue;
max = Math.max(max, SwingUtilities.computeStringWidth(fm, str));
}
return max;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (node == null) return;
List flow = node.getDataFlowNode().getFlow();
FontMetrics fm = g.getFontMetrics();
int halfFontHeight = fm.getAscent() / 2;
String[] accessLabels = deriveAccessLabels(flow);
int maxAccessLabelWidth = maxWidthOf(accessLabels, fm);
for (int i = 0; i < flow.size(); i++) {
IDataFlowNode inode = (IDataFlowNode) flow.get(i);
y = computeDrawPos(inode.getIndex());
g.drawArc(x, y, NODE_DIAMETER, NODE_DIAMETER, 0, 360);
g.drawString(lines.getLine(inode.getLine()), x + 100 + maxAccessLabelWidth, y + 15);
// draw index number centered inside of node
String idx = String.valueOf(inode.getIndex());
int halfWidth = SwingUtilities.computeStringWidth(fm, idx) / 2;
g.drawString(idx, x + NODE_RADIUS - halfWidth, y + NODE_RADIUS + halfFontHeight);
String accessLabel = accessLabels[i];
if (accessLabel != null) {
g.drawString(accessLabel, x + 70, y + 15);
}
for (int j = 0; j < inode.getChildren().size(); j++) {
IDataFlowNode n = inode.getChildren().get(j);
drawMyLine(inode.getIndex(), n.getIndex(), g);
}
String childIndices = childIndicesOf(inode, ", ");
g.drawString(childIndices, x - 3 * NODE_DIAMETER, y + NODE_RADIUS - 2);
}
}
public void setCode(LineGetter h) {
this.lines = h;
}
public void setMethod(SimpleNode node) {
this.node = node;
}
private int computeDrawPos(int index) {
int z = NODE_RADIUS * 4;
return z + index * z;
}
private void drawArrow(Graphics g, int x, int y, int direction) {
final int height = NODE_RADIUS * 2/3;
final int width = NODE_RADIUS * 2/3;
switch (direction) {
case SwingConstants.NORTH :
g.drawLine(x, y, x - width/2, y + height);
g.drawLine(x, y, x + width/2, y + height);
break;
case SwingConstants.SOUTH :
g.drawLine(x, y, x - width/2, y - height);
g.drawLine(x, y, x + width/2, y - height);
break;
case SwingConstants.EAST :
g.drawLine(x, y, x - height, y - width/2);
g.drawLine(x, y, x - height, y + width/2);
break;
case SwingConstants.WEST :
g.drawLine(x, y, x + height, y - width/2);
g.drawLine(x, y, x + height, y + width/2);
}
}
private void drawMyLine(int index1, int index2, Graphics g) {
int y1 = this.computeDrawPos(index1);
int y2 = this.computeDrawPos(index2);
//int arrow = 6;
if (index1 < index2) {
if (index2 - index1 == 1) {
x += NODE_RADIUS;
g.drawLine(x, y1 + NODE_DIAMETER, x, y2);
// g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
drawArrow(g, x, y2, SwingConstants.SOUTH);
x -= NODE_RADIUS;
} else if (index2 - index1 > 1) {
y1 = y1 + NODE_RADIUS;
y2 = y2 + NODE_RADIUS;
int n = ((index2 - index1 - 2) * 10) + 10;
g.drawLine(x, y1, x - n, y1);
g.drawLine(x - n, y1, x - n, y2);
g.drawLine(x - n, y2, x, y2);
// g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
drawArrow(g, x,y2, SwingConstants.EAST);
}
} else {
if (index1 - index2 > 1) {
y1 = y1 + NODE_RADIUS;
y2 = y2 + NODE_RADIUS;
x = x + NODE_DIAMETER;
int n = ((index1 - index2 - 2) * 10) + 10;
g.drawLine(x, y1, x + n, y1);
g.drawLine(x + n, y1, x + n, y2);
g.drawLine(x + n, y2, x, y2);
// g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
drawArrow(g, x, y2, SwingConstants.WEST);
x = x - NODE_DIAMETER;
} else if (index1 - index2 == 1) {
y2 = y2 + NODE_DIAMETER;
g.drawLine(x + NODE_RADIUS, y2, x + NODE_RADIUS, y1);
// g.fillRect(x + NODE_RADIUS - arrow, y2 - arrow, arrow * 2, arrow * 2);
drawArrow(g, x + NODE_RADIUS, y2, SwingConstants.NORTH);
}
}
}
}
private static class ElementWrapper {
private ASTMethodDeclaration node;
public ElementWrapper(ASTMethodDeclaration node) {
this.node = node;
}
public ASTMethodDeclaration getNode() {
return node;
}
public String toString() {
return node.getMethodName();
}
}
private DFACanvas dfaCanvas;
private JList nodeList;
private DefaultListModel nodes = new DefaultListModel();
public DFAPanel() {
super();
setLayout(new BorderLayout());
JPanel leftPanel = new JPanel();
nodeList = new JList(nodes);
nodeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
nodeList.setFixedCellWidth(150);
nodeList.setBorder(BorderFactory.createLineBorder(Color.black));
nodeList.addListSelectionListener(this);
leftPanel.add(nodeList);
add(leftPanel, BorderLayout.WEST);
dfaCanvas = new DFACanvas();
dfaCanvas.setBackground(Color.WHITE);
dfaCanvas.setPreferredSize(new Dimension(900, 1400));
JScrollPane scrollPane = new JScrollPane(dfaCanvas);
add(scrollPane, BorderLayout.CENTER);
}
public void valueChanged(ListSelectionEvent event) {
ElementWrapper wrapper = null;
if (nodes.size() == 1) {
wrapper = (ElementWrapper) nodes.get(0);
} else if (nodes.isEmpty()) {
return;
} else if (nodeList.getSelectedValue() == null) {
wrapper = (ElementWrapper) nodes.get(0);
} else {
wrapper = (ElementWrapper) nodeList.getSelectedValue();
}
dfaCanvas.setMethod(wrapper.getNode());
dfaCanvas.repaint();
}
public void resetTo(List<ASTMethodDeclaration> newNodes, LineGetter lines) {
dfaCanvas.setCode(lines);
nodes.clear();
for (ASTMethodDeclaration md: newNodes) {
nodes.addElement(new ElementWrapper(md));
}
nodeList.setSelectedIndex(0);
dfaCanvas.setMethod(newNodes.get(0));
repaint();
}
}
The table below shows all metrics for DFAPanel.java.




