1 /*** 2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html 3 */ 4 package net.sourceforge.pmd.util; 5 6 import net.sourceforge.pmd.TargetJDK1_4; 7 import net.sourceforge.pmd.ast.ASTCompilationUnit; 8 import net.sourceforge.pmd.ast.JavaParser; 9 import net.sourceforge.pmd.ast.ParseException; 10 import net.sourceforge.pmd.ast.SimpleNode; 11 import net.sourceforge.pmd.jaxen.DocumentNavigator; 12 import org.jaxen.BaseXPath; 13 import org.jaxen.JaxenException; 14 import org.jaxen.XPath; 15 16 import javax.swing.*; 17 import java.awt.*; 18 import java.awt.event.ActionEvent; 19 import java.awt.event.ActionListener; 20 import java.io.BufferedReader; 21 import java.io.File; 22 import java.io.FileReader; 23 import java.io.FileWriter; 24 import java.io.IOException; 25 import java.io.PrintStream; 26 import java.io.StringReader; 27 import java.util.Iterator; 28 29 public class ASTViewer { 30 31 private static class JSmartPanel extends JPanel { 32 33 private GridBagConstraints constraints = new GridBagConstraints(); 34 35 public JSmartPanel() { 36 super(new GridBagLayout()); 37 } 38 39 public void add(Component comp, int gridx, int gridy, int gridwidth, int gridheight, double weightx, double weighty, int anchor, int fill, Insets insets) { 40 constraints.gridx = gridx; 41 constraints.gridy = gridy; 42 constraints.gridwidth = gridwidth; 43 constraints.gridheight = gridheight; 44 constraints.weightx = weightx; 45 constraints.weighty = weighty; 46 constraints.anchor = anchor; 47 constraints.fill = fill; 48 constraints.insets = insets; 49 50 add(comp, constraints); 51 } 52 } 53 54 private static class MyPrintStream extends PrintStream { 55 56 public MyPrintStream() { 57 super(System.out); 58 } 59 60 private StringBuffer buf = new StringBuffer(); 61 62 public void println(String s) { 63 super.println(s); 64 buf.append(s); 65 buf.append(System.getProperty("line.separator")); 66 } 67 68 public String getString() { 69 return buf.toString(); 70 } 71 } 72 73 private class ShowListener implements ActionListener { 74 public void actionPerformed(ActionEvent ae) { 75 StringReader sr = new StringReader(codeEditorPane.getText()); 76 JavaParser parser = (new TargetJDK1_4()).createParser(sr); 77 MyPrintStream ps = new MyPrintStream(); 78 System.setOut(ps); 79 try { 80 ASTCompilationUnit c = parser.CompilationUnit(); 81 c.dump(""); 82 astArea.setText(ps.getString()); 83 } catch (ParseException pe) { 84 astArea.setText(pe.fillInStackTrace().getMessage()); 85 } 86 } 87 } 88 89 private class SaveListener implements ActionListener { 90 public void actionPerformed(ActionEvent ae) { 91 try { 92 File f = new File(SETTINGS_FILE_NAME); 93 FileWriter fw = new FileWriter(f); 94 fw.write(codeEditorPane.getText()); 95 fw.close(); 96 } catch (IOException ioe) { 97 } 98 } 99 } 100 101 private class XPathListener implements ActionListener { 102 public void actionPerformed(ActionEvent ae) { 103 if (xpathQueryArea.getText().length() == 0) { 104 xpathResultArea.setText("XPath query field is empty"); 105 codeEditorPane.requestFocus(); 106 return; 107 } 108 StringReader sr = new StringReader(codeEditorPane.getText()); 109 JavaParser parser = (new TargetJDK1_4()).createParser(sr); 110 try { 111 XPath xpath = new BaseXPath(xpathQueryArea.getText(), new DocumentNavigator()); 112 ASTCompilationUnit c = parser.CompilationUnit(); 113 StringBuffer sb = new StringBuffer(); 114 for (Iterator iter = xpath.selectNodes(c).iterator(); iter.hasNext();) { 115 SimpleNode node = (SimpleNode) iter.next(); 116 String name = node.getClass().getName().substring(node.getClass().getName().lastIndexOf('.')+1); 117 String line = " at line " + String.valueOf(node.getBeginLine()); 118 sb.append(name).append(line).append(System.getProperty("line.separator")); 119 } 120 xpathResultArea.setText(sb.toString()); 121 if (sb.length() == 0) { 122 xpathResultArea.setText("No results returned " + System.currentTimeMillis()); 123 } 124 } catch (ParseException pe) { 125 xpathResultArea.setText(pe.fillInStackTrace().getMessage()); 126 } catch (JaxenException je) { 127 xpathResultArea.setText(je.fillInStackTrace().getMessage()); 128 } 129 xpathQueryArea.requestFocus(); 130 } 131 } 132 133 private static final String SETTINGS_FILE_NAME = System.getProperty("user.home") + System.getProperty("file.separator") + ".pmd_astviewer"; 134 135 private JTextPane codeEditorPane = new JTextPane(); 136 private JTextArea astArea = new JTextArea(); 137 private JTextArea xpathResultArea = new JTextArea(); 138 private JTextArea xpathQueryArea = new JTextArea(8, 40); 139 private JFrame frame = new JFrame("AST Viewer"); 140 141 public ASTViewer() { 142 JSmartPanel codePanel = new JSmartPanel(); 143 JScrollPane codeScrollPane = new JScrollPane(codeEditorPane); 144 codePanel.add(codeScrollPane, 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0)); 145 146 JSmartPanel astPanel = new JSmartPanel(); 147 astArea.setRows(20); 148 astArea.setColumns(20); 149 JScrollPane astScrollPane = new JScrollPane(astArea); 150 astPanel.add(astScrollPane, 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0)); 151 152 JSmartPanel xpathResultPanel = new JSmartPanel(); 153 xpathResultArea.setRows(20); 154 xpathResultArea.setColumns(20); 155 JScrollPane xpathResultScrollPane = new JScrollPane(xpathResultArea); 156 xpathResultPanel.add(xpathResultScrollPane, 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0)); 157 158 JButton goButton = new JButton("Go"); 159 goButton.setMnemonic('g'); 160 goButton.addActionListener(new ShowListener()); 161 goButton.addActionListener(new SaveListener()); 162 goButton.addActionListener(new XPathListener()); 163 164 JPanel controlPanel = new JPanel(); 165 controlPanel.add(new JLabel("XPath Query (if any) ->")); 166 xpathQueryArea.setBorder(BorderFactory.createLineBorder(Color.black)); 167 controlPanel.add(new JScrollPane(xpathQueryArea)); 168 controlPanel.add(goButton); 169 170 JSplitPane resultsSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, astPanel, xpathResultPanel); 171 JSplitPane upperSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, codePanel, resultsSplitPane); 172 JSplitPane containerSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upperSplitPane, controlPanel); 173 174 frame.getContentPane().add(containerSplitPane); 175 176 frame.setSize(1000, 500); 177 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 178 int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height; 179 int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width; 180 frame.setLocation((screenWidth/2) - frame.getWidth()/2, (screenHeight/2) - frame.getHeight()/2); 181 frame.setVisible(true); 182 frame.show(); 183 184 containerSplitPane.setDividerLocation(containerSplitPane.getMaximumDividerLocation() - (containerSplitPane.getMaximumDividerLocation()/4)); 185 upperSplitPane.setDividerLocation(upperSplitPane.getMaximumDividerLocation() / 3); 186 codeEditorPane.setText(loadText()); 187 codeEditorPane.setSize(upperSplitPane.getMaximumDividerLocation() / 3, containerSplitPane.getMaximumDividerLocation() - (containerSplitPane.getMaximumDividerLocation()/4)); 188 } 189 190 private String loadText() { 191 try { 192 BufferedReader br = new BufferedReader(new FileReader(new File(SETTINGS_FILE_NAME))); 193 StringBuffer text = new StringBuffer(); 194 String hold = null; 195 while ( (hold = br.readLine()) != null) { 196 text.append(hold); 197 text.append(System.getProperty("line.separator")); 198 } 199 return text.toString(); 200 } catch (IOException e) { 201 e.printStackTrace(); 202 return ""; 203 } 204 } 205 206 public static void main(String[] args) { 207 new ASTViewer(); 208 } 209 }