Mon, 23 Aug 2010 15:13:33 -0700
6976747: JCDiagnostic: replace "boolean mandatory" with new "Set<JCDiagnostic.Flag>"
Reviewed-by: mcimadamore
1 /*
2 * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javac.jvm;
28 import java.util.*;
30 import com.sun.tools.javac.tree.*;
31 import com.sun.tools.javac.util.*;
32 import com.sun.tools.javac.util.List;
33 import com.sun.tools.javac.tree.JCTree.*;
35 /** This class contains the CharacterRangeTable for some method
36 * and the hashtable for mapping trees or lists of trees to their
37 * ending positions.
38 *
39 * <p><b>This is NOT part of any supported API.
40 * If you write code that depends on this, you do so at your own risk.
41 * This code and its internal interfaces are subject to change or
42 * deletion without notice.</b>
43 */
44 public class CRTable
45 implements CRTFlags {
47 private final boolean crtDebug = false;
49 /** The list of CRTable entries.
50 */
51 private ListBuffer<CRTEntry> entries = new ListBuffer<CRTEntry>();
53 /** The hashtable for source positions.
54 */
55 private Map<Object,SourceRange> positions = new HashMap<Object,SourceRange>();
57 /** The hashtable for ending positions stored in the parser.
58 */
59 private Map<JCTree, Integer> endPositions;
61 /** The tree of the method this table is intended for.
62 * We should traverse this tree to get source ranges.
63 */
64 JCTree.JCMethodDecl methodTree;
66 /** Constructor
67 */
68 public CRTable(JCTree.JCMethodDecl tree, Map<JCTree, Integer> endPositions) {
69 this.methodTree = tree;
70 this.endPositions = endPositions;
71 }
73 /** Create a new CRTEntry and add it to the entries.
74 * @param tree The tree or the list of trees for which
75 * we are storing the code pointers.
76 * @param flags The set of flags designating type of the entry.
77 * @param startPc The starting code position.
78 * @param endPc The ending code position.
79 */
80 public void put(Object tree, int flags, int startPc, int endPc) {
81 entries.append(new CRTEntry(tree, flags, startPc, endPc));
82 }
84 /** Compute source positions and write CRT to the databuf.
85 * @param databuf The buffer to write bytecodes to.
86 */
87 public int writeCRT(ByteBuffer databuf, Position.LineMap lineMap, Log log) {
89 int crtEntries = 0;
91 // compute source positions for the method
92 new SourceComputer().csp(methodTree);
94 for (List<CRTEntry> l = entries.toList(); l.nonEmpty(); l = l.tail) {
96 CRTEntry entry = l.head;
98 // eliminate entries that do not produce bytecodes:
99 // for example, empty blocks and statements
100 if (entry.startPc == entry.endPc)
101 continue;
103 SourceRange pos = positions.get(entry.tree);
104 assert pos != null : "CRT: tree source positions are undefined";
105 if ((pos.startPos == Position.NOPOS) || (pos.endPos == Position.NOPOS))
106 continue;
108 if (crtDebug) {
109 System.out.println("Tree: " + entry.tree + ", type:" + getTypes(entry.flags));
110 System.out.print("Start: pos = " + pos.startPos + ", pc = " + entry.startPc);
111 }
113 // encode startPos into line/column representation
114 int startPos = encodePosition(pos.startPos, lineMap, log);
115 if (startPos == Position.NOPOS)
116 continue;
118 if (crtDebug) {
119 System.out.print("End: pos = " + pos.endPos + ", pc = " + (entry.endPc - 1));
120 }
122 // encode endPos into line/column representation
123 int endPos = encodePosition(pos.endPos, lineMap, log);
124 if (endPos == Position.NOPOS)
125 continue;
127 // write attribute
128 databuf.appendChar(entry.startPc);
129 // 'endPc - 1' because endPc actually points to start of the next command
130 databuf.appendChar(entry.endPc - 1);
131 databuf.appendInt(startPos);
132 databuf.appendInt(endPos);
133 databuf.appendChar(entry.flags);
135 crtEntries++;
136 }
138 return crtEntries;
139 }
141 /** Return the number of the entries.
142 */
143 public int length() {
144 return entries.length();
145 }
147 /** Return string describing flags enabled.
148 */
149 private String getTypes(int flags) {
150 String types = "";
151 if ((flags & CRT_STATEMENT) != 0) types += " CRT_STATEMENT";
152 if ((flags & CRT_BLOCK) != 0) types += " CRT_BLOCK";
153 if ((flags & CRT_ASSIGNMENT) != 0) types += " CRT_ASSIGNMENT";
154 if ((flags & CRT_FLOW_CONTROLLER) != 0) types += " CRT_FLOW_CONTROLLER";
155 if ((flags & CRT_FLOW_TARGET) != 0) types += " CRT_FLOW_TARGET";
156 if ((flags & CRT_INVOKE) != 0) types += " CRT_INVOKE";
157 if ((flags & CRT_CREATE) != 0) types += " CRT_CREATE";
158 if ((flags & CRT_BRANCH_TRUE) != 0) types += " CRT_BRANCH_TRUE";
159 if ((flags & CRT_BRANCH_FALSE) != 0) types += " CRT_BRANCH_FALSE";
160 return types;
161 }
163 /** Source file positions in CRT are integers in the format:
164 * line-number << LINESHIFT + column-number
165 */
166 private int encodePosition(int pos, Position.LineMap lineMap, Log log) {
167 int line = lineMap.getLineNumber(pos);
168 int col = lineMap.getColumnNumber(pos);
169 int new_pos = Position.encodePosition(line, col);
170 if (crtDebug) {
171 System.out.println(", line = " + line + ", column = " + col +
172 ", new_pos = " + new_pos);
173 }
174 if (new_pos == Position.NOPOS)
175 log.warning(pos, "position.overflow", line);
177 return new_pos;
178 }
180 /* ************************************************************************
181 * Traversal methods
182 *************************************************************************/
184 /**
185 * This class contains methods to compute source positions for trees.
186 * Extends Tree.Visitor to traverse the abstract syntax tree.
187 */
188 class SourceComputer extends JCTree.Visitor {
190 /** The result of the tree traversal methods.
191 */
192 SourceRange result;
194 /** Visitor method: compute source positions for a single node.
195 */
196 public SourceRange csp(JCTree tree) {
197 if (tree == null) return null;
198 tree.accept(this);
199 if (result != null) {
200 positions.put(tree, result);
201 }
202 return result;
203 }
205 /** Visitor method: compute source positions for a list of nodes.
206 */
207 public SourceRange csp(List<? extends JCTree> trees) {
208 if ((trees == null) || !(trees.nonEmpty())) return null;
209 SourceRange list_sr = new SourceRange();
210 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {
211 list_sr.mergeWith(csp(l.head));
212 }
213 positions.put(trees, list_sr);
214 return list_sr;
215 }
217 /** Visitor method: compute source positions for
218 * a list of case blocks of switch statements.
219 */
220 public SourceRange cspCases(List<JCCase> trees) {
221 if ((trees == null) || !(trees.nonEmpty())) return null;
222 SourceRange list_sr = new SourceRange();
223 for (List<JCCase> l = trees; l.nonEmpty(); l = l.tail) {
224 list_sr.mergeWith(csp(l.head));
225 }
226 positions.put(trees, list_sr);
227 return list_sr;
228 }
230 /** Visitor method: compute source positions for
231 * a list of catch clauses in try statements.
232 */
233 public SourceRange cspCatchers(List<JCCatch> trees) {
234 if ((trees == null) || !(trees.nonEmpty())) return null;
235 SourceRange list_sr = new SourceRange();
236 for (List<JCCatch> l = trees; l.nonEmpty(); l = l.tail) {
237 list_sr.mergeWith(csp(l.head));
238 }
239 positions.put(trees, list_sr);
240 return list_sr;
241 }
243 public void visitMethodDef(JCMethodDecl tree) {
244 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
245 sr.mergeWith(csp(tree.body));
246 result = sr;
247 }
249 public void visitVarDef(JCVariableDecl tree) {
250 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
251 csp(tree.vartype);
252 sr.mergeWith(csp(tree.init));
253 result = sr;
254 }
256 public void visitSkip(JCSkip tree) {
257 // endPos is the same as startPos for the empty statement
258 SourceRange sr = new SourceRange(startPos(tree), startPos(tree));
259 result = sr;
260 }
262 public void visitBlock(JCBlock tree) {
263 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
264 csp(tree.stats); // doesn't compare because block's ending position is defined
265 result = sr;
266 }
268 public void visitDoLoop(JCDoWhileLoop tree) {
269 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
270 sr.mergeWith(csp(tree.body));
271 sr.mergeWith(csp(tree.cond));
272 result = sr;
273 }
275 public void visitWhileLoop(JCWhileLoop tree) {
276 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
277 sr.mergeWith(csp(tree.cond));
278 sr.mergeWith(csp(tree.body));
279 result = sr;
280 }
282 public void visitForLoop(JCForLoop tree) {
283 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
284 sr.mergeWith(csp(tree.init));
285 sr.mergeWith(csp(tree.cond));
286 sr.mergeWith(csp(tree.step));
287 sr.mergeWith(csp(tree.body));
288 result = sr;
289 }
291 public void visitForeachLoop(JCEnhancedForLoop tree) {
292 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
293 sr.mergeWith(csp(tree.var));
294 sr.mergeWith(csp(tree.expr));
295 sr.mergeWith(csp(tree.body));
296 result = sr;
297 }
299 public void visitLabelled(JCLabeledStatement tree) {
300 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
301 sr.mergeWith(csp(tree.body));
302 result = sr;
303 }
305 public void visitSwitch(JCSwitch tree) {
306 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
307 sr.mergeWith(csp(tree.selector));
308 sr.mergeWith(cspCases(tree.cases));
309 result = sr;
310 }
312 public void visitCase(JCCase tree) {
313 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
314 sr.mergeWith(csp(tree.pat));
315 sr.mergeWith(csp(tree.stats));
316 result = sr;
317 }
319 public void visitSynchronized(JCSynchronized tree) {
320 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
321 sr.mergeWith(csp(tree.lock));
322 sr.mergeWith(csp(tree.body));
323 result = sr;
324 }
326 public void visitTry(JCTry tree) {
327 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
328 sr.mergeWith(csp(tree.resources));
329 sr.mergeWith(csp(tree.body));
330 sr.mergeWith(cspCatchers(tree.catchers));
331 sr.mergeWith(csp(tree.finalizer));
332 result = sr;
333 }
335 public void visitCatch(JCCatch tree) {
336 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
337 sr.mergeWith(csp(tree.param));
338 sr.mergeWith(csp(tree.body));
339 result = sr;
340 }
342 public void visitConditional(JCConditional tree) {
343 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
344 sr.mergeWith(csp(tree.cond));
345 sr.mergeWith(csp(tree.truepart));
346 sr.mergeWith(csp(tree.falsepart));
347 result = sr;
348 }
350 public void visitIf(JCIf tree) {
351 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
352 sr.mergeWith(csp(tree.cond));
353 sr.mergeWith(csp(tree.thenpart));
354 sr.mergeWith(csp(tree.elsepart));
355 result = sr;
356 }
358 public void visitExec(JCExpressionStatement tree) {
359 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
360 sr.mergeWith(csp(tree.expr));
361 result = sr;
362 }
364 public void visitBreak(JCBreak tree) {
365 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
366 result = sr;
367 }
369 public void visitContinue(JCContinue tree) {
370 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
371 result = sr;
372 }
374 public void visitReturn(JCReturn tree) {
375 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
376 sr.mergeWith(csp(tree.expr));
377 result = sr;
378 }
380 public void visitThrow(JCThrow tree) {
381 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
382 sr.mergeWith(csp(tree.expr));
383 result = sr;
384 }
386 public void visitAssert(JCAssert tree) {
387 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
388 sr.mergeWith(csp(tree.cond));
389 sr.mergeWith(csp(tree.detail));
390 result = sr;
391 }
393 public void visitApply(JCMethodInvocation tree) {
394 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
395 sr.mergeWith(csp(tree.meth));
396 sr.mergeWith(csp(tree.args));
397 result = sr;
398 }
400 public void visitNewClass(JCNewClass tree) {
401 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
402 sr.mergeWith(csp(tree.encl));
403 sr.mergeWith(csp(tree.clazz));
404 sr.mergeWith(csp(tree.args));
405 sr.mergeWith(csp(tree.def));
406 result = sr;
407 }
409 public void visitNewArray(JCNewArray tree) {
410 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
411 sr.mergeWith(csp(tree.elemtype));
412 sr.mergeWith(csp(tree.dims));
413 sr.mergeWith(csp(tree.elems));
414 result = sr;
415 }
417 public void visitParens(JCParens tree) {
418 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
419 sr.mergeWith(csp(tree.expr));
420 result = sr;
421 }
423 public void visitAssign(JCAssign tree) {
424 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
425 sr.mergeWith(csp(tree.lhs));
426 sr.mergeWith(csp(tree.rhs));
427 result = sr;
428 }
430 public void visitAssignop(JCAssignOp tree) {
431 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
432 sr.mergeWith(csp(tree.lhs));
433 sr.mergeWith(csp(tree.rhs));
434 result = sr;
435 }
437 public void visitUnary(JCUnary tree) {
438 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
439 sr.mergeWith(csp(tree.arg));
440 result = sr;
441 }
443 public void visitBinary(JCBinary tree) {
444 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
445 sr.mergeWith(csp(tree.lhs));
446 sr.mergeWith(csp(tree.rhs));
447 result = sr;
448 }
450 public void visitTypeCast(JCTypeCast tree) {
451 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
452 sr.mergeWith(csp(tree.clazz));
453 sr.mergeWith(csp(tree.expr));
454 result = sr;
455 }
457 public void visitTypeTest(JCInstanceOf tree) {
458 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
459 sr.mergeWith(csp(tree.expr));
460 sr.mergeWith(csp(tree.clazz));
461 result = sr;
462 }
464 public void visitIndexed(JCArrayAccess tree) {
465 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
466 sr.mergeWith(csp(tree.indexed));
467 sr.mergeWith(csp(tree.index));
468 result = sr;
469 }
471 public void visitSelect(JCFieldAccess tree) {
472 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
473 sr.mergeWith(csp(tree.selected));
474 result = sr;
475 }
477 public void visitIdent(JCIdent tree) {
478 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
479 result = sr;
480 }
482 public void visitLiteral(JCLiteral tree) {
483 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
484 result = sr;
485 }
487 public void visitTypeIdent(JCPrimitiveTypeTree tree) {
488 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
489 result = sr;
490 }
492 public void visitTypeArray(JCArrayTypeTree tree) {
493 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
494 sr.mergeWith(csp(tree.elemtype));
495 result = sr;
496 }
498 public void visitTypeApply(JCTypeApply tree) {
499 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
500 sr.mergeWith(csp(tree.clazz));
501 sr.mergeWith(csp(tree.arguments));
502 result = sr;
503 }
505 public void visitTypeParameter(JCTypeParameter tree) {
506 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
507 sr.mergeWith(csp(tree.bounds));
508 result = sr;
509 }
511 public void visitWildcard(JCWildcard tree) {
512 result = null;
513 }
515 public void visitErroneous(JCErroneous tree) {
516 result = null;
517 }
519 public void visitTree(JCTree tree) {
520 assert false;
521 }
523 /** The start position of given tree.
524 */
525 public int startPos(JCTree tree) {
526 if (tree == null) return Position.NOPOS;
527 return tree.pos;
528 }
530 /** The end position of given tree, if it has
531 * defined endpos, NOPOS otherwise.
532 */
533 public int endPos(JCTree tree) {
534 if (tree == null) return Position.NOPOS;
535 if (tree.getTag() == JCTree.BLOCK)
536 return ((JCBlock) tree).endpos;
537 Integer endpos = endPositions.get(tree);
538 if (endpos != null)
539 return endpos.intValue();
540 return Position.NOPOS;
541 }
542 }
544 /** This class contains a CharacterRangeTableEntry.
545 */
546 static class CRTEntry {
548 /** A tree or a list of trees to obtain source positions.
549 */
550 Object tree;
552 /** The flags described in the CharacterRangeTable spec.
553 */
554 int flags;
556 /** The starting code position of this entry.
557 */
558 int startPc;
560 /** The ending code position of this entry.
561 */
562 int endPc;
564 /** Constructor */
565 CRTEntry(Object tree, int flags, int startPc, int endPc) {
566 this.tree = tree;
567 this.flags = flags;
568 this.startPc = startPc;
569 this.endPc = endPc;
570 }
571 }
574 /** This class contains source positions
575 * for some tree or list of trees.
576 */
577 static class SourceRange {
579 /** The starting source position.
580 */
581 int startPos;
583 /** The ending source position.
584 */
585 int endPos;
587 /** Constructor */
588 SourceRange() {
589 startPos = Position.NOPOS;
590 endPos = Position.NOPOS;
591 }
593 /** Constructor */
594 SourceRange(int startPos, int endPos) {
595 this.startPos = startPos;
596 this.endPos = endPos;
597 }
599 /** Compare the starting and the ending positions
600 * of the source range and combines them assigning
601 * the widest range to this.
602 */
603 SourceRange mergeWith(SourceRange sr) {
604 if (sr == null) return this;
605 if (startPos == Position.NOPOS)
606 startPos = sr.startPos;
607 else if (sr.startPos != Position.NOPOS)
608 startPos = (startPos < sr.startPos ? startPos : sr.startPos);
609 if (endPos == Position.NOPOS)
610 endPos = sr.endPos;
611 else if (sr.endPos != Position.NOPOS)
612 endPos = (endPos > sr.endPos ? endPos : sr.endPos);
613 return this;
614 }
615 }
617 }