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 }