001: package org.incava.java;
002:
003: import java.util.*;
004: import net.sourceforge.pmd.ast.JavaParserConstants;
005: import net.sourceforge.pmd.ast.SimpleNode;
006: import net.sourceforge.pmd.ast.Token;
007:
008: /**
009: * Miscellaneous routines for the SimpleNode.
010: */
011: public class SimpleNodeUtil {
012: /**
013: * Returns the token images for the node.
014: */
015: public static String toString(SimpleNode node) {
016: Token tk = node.getFirstToken();
017: Token last = node.getLastToken();
018: String str = tk.image;
019: while (tk != last) {
020: tk = tk.next;
021: str += tk.image;
022: }
023: return str;
024: }
025:
026: /**
027: * Returns whether the node has any children.
028: */
029: public static boolean hasChildren(SimpleNode node) {
030: return node.jjtGetNumChildren() > 0;
031: }
032:
033: /**
034: * Returns the parent node.
035: */
036: public static SimpleNode getParent(SimpleNode node) {
037: return (SimpleNode) node.jjtGetParent();
038: }
039:
040: /**
041: * Returns a list of children, both nodes and tokens.
042: */
043: public static List getChildren(SimpleNode node) {
044: List list = new ArrayList();
045:
046: Token t = new Token();
047: t.next = node.getFirstToken();
048:
049: int nChildren = node.jjtGetNumChildren();
050: for (int ord = 0; ord < nChildren; ++ord) {
051: SimpleNode n = (SimpleNode) node.jjtGetChild(ord);
052: while (true) {
053: t = t.next;
054: if (t == n.getFirstToken()) {
055: break;
056: }
057: list.add(t);
058: }
059: list.add(n);
060: t = n.getLastToken();
061: }
062:
063: while (t != node.getLastToken()) {
064: t = t.next;
065: list.add(t);
066: }
067:
068: return list;
069: }
070:
071: /**
072: * Returns a list of children, optionally nodes and tokens.
073: */
074: public static List getChildren(SimpleNode node, boolean getNodes,
075: boolean getTokens) {
076: List list = new ArrayList();
077:
078: Token t = new Token();
079: t.next = node.getFirstToken();
080:
081: int nChildren = node.jjtGetNumChildren();
082: for (int ord = 0; ord < nChildren; ++ord) {
083: SimpleNode n = (SimpleNode) node.jjtGetChild(ord);
084: while (true) {
085: t = t.next;
086: if (t == n.getFirstToken()) {
087: break;
088: }
089: if (getTokens) {
090: list.add(t);
091: }
092: }
093: if (getNodes) {
094: list.add(n);
095: }
096: t = n.getLastToken();
097: }
098:
099: while (t != node.getLastToken()) {
100: t = t.next;
101: if (getTokens) {
102: list.add(t);
103: }
104: }
105:
106: return list;
107: }
108:
109: public static SimpleNode findChild(SimpleNode parent,
110: Class childType) {
111: return findChild(parent, childType, 0);
112: }
113:
114: public static SimpleNode findChild(SimpleNode parent,
115: Class childType, int index) {
116: if (parent != null) {
117: int nChildren = parent.jjtGetNumChildren();
118: if (index >= 0 && index < nChildren) {
119: int nFound = 0;
120: for (int i = 0; i < nChildren; ++i) {
121: SimpleNode child = (SimpleNode) parent
122: .jjtGetChild(i);
123: // tr.Ace.log("considering " + child.getClass() + " as match against " + childType);
124: if (childType == null
125: || child.getClass().equals(childType)) {
126: if (nFound == index) {
127: // tr.Ace.log("got match");
128: return child;
129: } else {
130: ++nFound;
131: }
132: }
133: }
134: } else {
135: tr.Ace.stack("WARNING: index " + index
136: + " out of bounds (" + 0 + ", " + nChildren
137: + ")");
138: }
139: // tr.Ace.log("no match for " + childType);
140: }
141: return null;
142: }
143:
144: /**
145: * Returns a list of child tokens, non-hierarchically.
146: */
147: public static List getChildrenSerially(SimpleNode node) {
148: return getChildrenSerially(node, null);
149: }
150:
151: /**
152: * Returns a list of child tokens, non-hierarchically.
153: */
154: public static List getChildrenSerially(SimpleNode node, List list) {
155: List children = list;
156: if (children == null) {
157: children = new ArrayList();
158: }
159:
160: Token t = new Token();
161: t.next = node.getFirstToken();
162:
163: int nChildren = node.jjtGetNumChildren();
164: for (int ord = 0; ord < nChildren; ++ord) {
165: SimpleNode n = (SimpleNode) node.jjtGetChild(ord);
166: while (true) {
167: t = t.next;
168: if (t == n.getFirstToken()) {
169: break;
170: }
171: children.add(t);
172: }
173: getChildrenSerially(n, children);
174:
175: t = n.getLastToken();
176: }
177:
178: while (t != node.getLastToken()) {
179: t = t.next;
180: children.add(t);
181: }
182:
183: return children;
184: }
185:
186: public static SimpleNode[] findChildren(SimpleNode parent,
187: Class childType) {
188: List kids = new ArrayList();
189: int nChildren = parent == null ? 0 : parent.jjtGetNumChildren();
190: for (int i = 0; i < nChildren; ++i) {
191: SimpleNode child = (SimpleNode) parent.jjtGetChild(i);
192: if (childType == null || child.getClass().equals(childType)) {
193: kids.add(child);
194: }
195: }
196:
197: if (childType == null) {
198: return (SimpleNode[]) kids.toArray(new SimpleNode[0]);
199: } else {
200: int size = kids.size();
201: SimpleNode[] ary = (SimpleNode[]) java.lang.reflect.Array
202: .newInstance(childType, size);
203: System.arraycopy(kids.toArray(), 0, ary, 0, size);
204: return ary;
205: }
206: }
207:
208: /**
209: * Returns all children of the node.
210: */
211: public static SimpleNode[] findChildren(SimpleNode parent) {
212: return findChildren(parent, null);
213: }
214:
215: /**
216: * Returns the tokens for a node.
217: */
218: public static List getTokens(SimpleNode node) {
219: // tr.Ace.log("node: " + node);
220:
221: List tokens = new ArrayList();
222: Token tk = new Token();
223: tk.next = node.getFirstToken();
224:
225: if (tk != null) {
226: tokens.add(tk);
227: // tr.Ace.log("node.getLastToken(): " + node.getLastToken());
228: do {
229: tk = tk.next;
230: // tr.Ace.log("token: " + tk);
231: tokens.add(tk);
232: } while (tk != node.getLastToken());
233: }
234: return tokens;
235: }
236:
237: public static Token findToken(SimpleNode node, int tokenType) {
238: List childTokens = getChildren(node, false, true);
239: Iterator it = childTokens.iterator();
240: while (it.hasNext()) {
241: Token tk = (Token) it.next();
242: if (tk.kind == tokenType) {
243: return tk;
244: }
245: }
246: return null;
247: }
248:
249: /**
250: * Returns whether the node has a matching token, occurring prior to any
251: * non-tokens (i.e., before any child nodes).
252: */
253: public static boolean hasLeadingToken(SimpleNode node, int tokenType) {
254: return getLeadingToken(node, tokenType) != null;
255: }
256:
257: /**
258: * Returns whether the node has a matching token, occurring prior to any
259: * non-tokens (i.e., before any child nodes).
260: */
261: public static Token getLeadingToken(SimpleNode node, int tokenType) {
262: if (node.jjtGetNumChildren() > 0) {
263: SimpleNode n = (SimpleNode) node.jjtGetChild(0);
264:
265: Token t = new Token();
266: t.next = node.getFirstToken();
267:
268: while (true) {
269: t = t.next;
270: if (t == n.getFirstToken()) {
271: break;
272: } else if (t.kind == tokenType) {
273: return t;
274: }
275: }
276: }
277:
278: return null;
279: }
280:
281: /**
282: * Returns the tokens preceding the first child of the node.
283: */
284: public static List getLeadingTokens(SimpleNode node) {
285: List list = new ArrayList();
286:
287: if (node.jjtGetNumChildren() > 0) {
288: SimpleNode n = (SimpleNode) node.jjtGetChild(0);
289:
290: Token t = new Token();
291: t.next = node.getFirstToken();
292:
293: while (true) {
294: t = t.next;
295: if (t == n.getFirstToken()) {
296: break;
297: } else {
298: list.add(t);
299: }
300: }
301: }
302:
303: return list;
304: }
305:
306: public static void print(SimpleNode node) {
307: print(node, "");
308: }
309:
310: public static void print(SimpleNode node, String prefix) {
311: Token first = node.getFirstToken();
312: Token last = node.getLastToken();
313:
314: tr.Ace.log(prefix + "<" + node.toString() + ">"
315: + getLocation(first, last));
316: }
317:
318: public static void dump(SimpleNode node, String prefix) {
319: dump(node, prefix, false);
320: }
321:
322: public static void dump(SimpleNode node, String prefix,
323: boolean showWhitespace) {
324: print(node, prefix);
325:
326: List children = getChildren(node);
327: Iterator it = children.iterator();
328: while (it.hasNext()) {
329: Object obj = it.next();
330: if (obj instanceof Token) {
331: Token tk = (Token) obj;
332:
333: if (showWhitespace) {
334: Token st = tk.specialToken;
335: if (st != null) {
336: while (st.specialToken != null) {
337: st = st.specialToken;
338: }
339:
340: while (st != null) {
341: String s = st.toString().replaceAll("\n",
342: "\\\\n").replaceAll("\r", "\\\\r");
343: tr.Ace.log(prefix + " s["
344: + getLocation(st, st) + "] \"" + s
345: + "\"");
346: st = st.next;
347: }
348: }
349: }
350:
351: tr.Ace.log(prefix + " t" + getLocation(tk, tk)
352: + " \"" + tk + "\" (" + tk.kind + ")");
353: } else {
354: SimpleNode sn = (SimpleNode) obj;
355: dump(sn, prefix + " ", showWhitespace);
356: }
357: }
358: }
359:
360: protected static String getLocation(Token t1, Token t2) {
361: return "[" + t1.beginLine + ":" + t1.beginColumn + ":"
362: + t2.endLine + ":" + t2.endColumn + "]";
363: }
364:
365: /**
366: * Returns a numeric "level" for the node. Zero is public or abstract, one
367: * is protected, two is package, and three is private.
368: */
369: public static int getLevel(SimpleNode node) {
370: List tokens = getLeadingTokens(node);
371: Iterator tit = tokens.iterator();
372: while (tit.hasNext()) {
373: Token t = (Token) tit.next();
374: switch (t.kind) {
375: case JavaParserConstants.PUBLIC:
376: // fallthrough
377: case JavaParserConstants.ABSTRACT:
378: return 0;
379: case JavaParserConstants.PROTECTED:
380: return 1;
381: case JavaParserConstants.PRIVATE:
382: return 3;
383: }
384: }
385:
386: // AKA "package"
387: return 2;
388: }
389:
390: }
|