test/tools/javac/tree/TreePosTest.java

changeset 1127
ca49d50318dc
parent 808
e8719f95f2d0
child 1138
7375d4979bd3
equal deleted inserted replaced
1126:11c184155128 1127:ca49d50318dc
1 /* 1 /*
2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
78 import com.sun.tools.javac.tree.JCTree.JCNewClass; 78 import com.sun.tools.javac.tree.JCTree.JCNewClass;
79 import com.sun.tools.javac.tree.JCTree.JCVariableDecl; 79 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
80 import com.sun.tools.javac.tree.TreeInfo; 80 import com.sun.tools.javac.tree.TreeInfo;
81 import com.sun.tools.javac.tree.TreeScanner; 81 import com.sun.tools.javac.tree.TreeScanner;
82 82
83 import static com.sun.tools.javac.tree.JCTree.Tag.*;
83 import static com.sun.tools.javac.util.Position.NOPOS; 84 import static com.sun.tools.javac.util.Position.NOPOS;
84 85
85 /** 86 /**
86 * Utility and test program to check validity of tree positions for tree nodes. 87 * Utility and test program to check validity of tree positions for tree nodes.
87 * The program can be run standalone, or as a jtreg test. In standalone mode, 88 * The program can be run standalone, or as a jtreg test. In standalone mode,
289 void error(String msg) { 290 void error(String msg) {
290 System.err.println(msg); 291 System.err.println(msg);
291 errors++; 292 errors++;
292 } 293 }
293 294
295 /**
296 * Names for tree tags.
297 */
298 private static String getTagName(JCTree.Tag tag) {
299 String name = tag.name();
300 return (name == null) ? "??" : name;
301 }
302
294 /** Number of files that have been analyzed. */ 303 /** Number of files that have been analyzed. */
295 int fileCount; 304 int fileCount;
296 /** Number of errors reported. */ 305 /** Number of errors reported. */
297 int errors; 306 int errors;
298 /** Flag: don't report irrelevant files. */ 307 /** Flag: don't report irrelevant files. */
310 Set<String> tags = new HashSet<String>(); 319 Set<String> tags = new HashSet<String>();
311 /** Set of files and directories to be excluded from analysis. */ 320 /** Set of files and directories to be excluded from analysis. */
312 Set<File> excludeFiles = new HashSet<File>(); 321 Set<File> excludeFiles = new HashSet<File>();
313 /** Set of tag names to be excluded from analysis. */ 322 /** Set of tag names to be excluded from analysis. */
314 Set<String> excludeTags = new HashSet<String>(); 323 Set<String> excludeTags = new HashSet<String>();
315 /** Table of printable names for tree tag values. */
316 TagNames tagNames = new TagNames();
317 324
318 /** 325 /**
319 * Main class for testing assertions concerning tree positions for tree nodes. 326 * Main class for testing assertions concerning tree positions for tree nodes.
320 */ 327 */
321 private class PosTester extends TreeScanner { 328 private class PosTester extends TreeScanner {
335 if (check(encl, self)) { 342 if (check(encl, self)) {
336 // Modifiers nodes are present throughout the tree even where 343 // Modifiers nodes are present throughout the tree even where
337 // there is no corresponding source text. 344 // there is no corresponding source text.
338 // Redundant semicolons in a class definition can cause empty 345 // Redundant semicolons in a class definition can cause empty
339 // initializer blocks with no positions. 346 // initializer blocks with no positions.
340 if ((self.tag == JCTree.MODIFIERS || self.tag == JCTree.BLOCK) 347 if ((self.tag == MODIFIERS || self.tag == BLOCK)
341 && self.pos == NOPOS) { 348 && self.pos == NOPOS) {
342 // If pos is NOPOS, so should be the start and end positions 349 // If pos is NOPOS, so should be the start and end positions
343 check("start == NOPOS", encl, self, self.start == NOPOS); 350 check("start == NOPOS", encl, self, self.start == NOPOS);
344 check("end == NOPOS", encl, self, self.end == NOPOS); 351 check("end == NOPOS", encl, self, self.end == NOPOS);
345 } else { 352 } else {
357 // and because of inconsistent nesting of left and right of 364 // and because of inconsistent nesting of left and right of
358 // array declarations: 365 // array declarations:
359 // e.g. int[][] a = new int[2][]; 366 // e.g. int[][] a = new int[2][];
360 check("encl.start <= start", encl, self, encl.start <= self.start); 367 check("encl.start <= start", encl, self, encl.start <= self.start);
361 check("start <= pos", encl, self, self.start <= self.pos); 368 check("start <= pos", encl, self, self.start <= self.pos);
362 if (!(self.tag == JCTree.TYPEARRAY 369 if (!(self.tag == TYPEARRAY
363 && (encl.tag == JCTree.VARDEF || 370 && (encl.tag == VARDEF ||
364 encl.tag == JCTree.METHODDEF || 371 encl.tag == METHODDEF ||
365 encl.tag == JCTree.TYPEARRAY))) { 372 encl.tag == TYPEARRAY))) {
366 check("encl.pos <= start || end <= encl.pos", 373 check("encl.pos <= start || end <= encl.pos",
367 encl, self, encl.pos <= self.start || self.end <= encl.pos); 374 encl, self, encl.pos <= self.start || self.end <= encl.pos);
368 } 375 }
369 check("pos <= end", encl, self, self.pos <= self.end); 376 check("pos <= end", encl, self, self.pos <= self.end);
370 if (!(self.tag == JCTree.TYPEARRAY && encl.tag == JCTree.TYPEARRAY)) { 377 if (!(self.tag == TYPEARRAY && encl.tag == TYPEARRAY)) {
371 check("end <= encl.end", encl, self, self.end <= encl.end); 378 check("end <= encl.end", encl, self, self.end <= encl.end);
372 } 379 }
373 } 380 }
374 } 381 }
375 382
386 // skip the synthesized bits and just check parts which came from 393 // skip the synthesized bits and just check parts which came from
387 // the original source text 394 // the original source text
388 if ((tree.mods.flags & Flags.ENUM) != 0) { 395 if ((tree.mods.flags & Flags.ENUM) != 0) {
389 scan(tree.mods); 396 scan(tree.mods);
390 if (tree.init != null) { 397 if (tree.init != null) {
391 if (tree.init.getTag() == JCTree.NEWCLASS) { 398 if (tree.init.hasTag(NEWCLASS)) {
392 JCNewClass init = (JCNewClass) tree.init; 399 JCNewClass init = (JCNewClass) tree.init;
393 if (init.args != null && init.args.nonEmpty()) { 400 if (init.args != null && init.args.nonEmpty()) {
394 scan(init.args); 401 scan(init.args);
395 } 402 }
396 if (init.def != null && init.def.defs != null) { 403 if (init.def != null && init.def.defs != null) {
402 super.visitVarDef(tree); 409 super.visitVarDef(tree);
403 } 410 }
404 411
405 boolean check(Info encl, Info self) { 412 boolean check(Info encl, Info self) {
406 if (excludeTags.size() > 0) { 413 if (excludeTags.size() > 0) {
407 if (encl != null && excludeTags.contains(tagNames.get(encl.tag)) 414 if (encl != null && excludeTags.contains(getTagName(encl.tag))
408 || excludeTags.contains(tagNames.get(self.tag))) 415 || excludeTags.contains(getTagName(self.tag)))
409 return false; 416 return false;
410 } 417 }
411 return tags.size() == 0 || tags.contains(tagNames.get(self.tag)); 418 return tags.size() == 0 || tags.contains(getTagName(self.tag));
412 } 419 }
413 420
414 void check(String label, Info encl, Info self, boolean ok) { 421 void check(String label, Info encl, Info self, boolean ok) {
415 if (!ok) { 422 if (!ok) {
416 if (gui) { 423 if (gui) {
437 * Utility class providing easy access to position and other info for a tree node. 444 * Utility class providing easy access to position and other info for a tree node.
438 */ 445 */
439 private class Info { 446 private class Info {
440 Info() { 447 Info() {
441 tree = null; 448 tree = null;
442 tag = JCTree.ERRONEOUS; 449 tag = ERRONEOUS;
443 start = 0; 450 start = 0;
444 pos = 0; 451 pos = 0;
445 end = Integer.MAX_VALUE; 452 end = Integer.MAX_VALUE;
446 } 453 }
447 454
453 end = TreeInfo.getEndPos(tree, endPosTable); 460 end = TreeInfo.getEndPos(tree, endPosTable);
454 } 461 }
455 462
456 @Override 463 @Override
457 public String toString() { 464 public String toString() {
458 return tagNames.get(tree.getTag()) + "[start:" + start + ",pos:" + pos + ",end:" + end + "]"; 465 return getTagName(tree.getTag()) + "[start:" + start + ",pos:" + pos + ",end:" + end + "]";
459 } 466 }
460 467
461 final JCTree tree; 468 final JCTree tree;
462 final int tag; 469 final JCTree.Tag tag;
463 final int start; 470 final int start;
464 final int pos; 471 final int pos;
465 final int end; 472 final int end;
466 }
467
468 /**
469 * Names for tree tags.
470 * javac does not provide an API to convert tag values to strings, so this class uses
471 * reflection to determine names of public static final int values in JCTree.
472 */
473 private static class TagNames {
474 String get(int tag) {
475 if (map == null) {
476 map = new HashMap<Integer, String>();
477 Class c = JCTree.class;
478 for (Field f : c.getDeclaredFields()) {
479 if (f.getType().equals(int.class)) {
480 int mods = f.getModifiers();
481 if (Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) {
482 try {
483 map.put(f.getInt(null), f.getName());
484 } catch (IllegalAccessException e) {
485 }
486 }
487 }
488 }
489 }
490 String name = map.get(tag);
491 return (name == null) ? "??" : name;
492 }
493
494 private Map<Integer, String> map;
495 } 473 }
496 474
497 /** 475 /**
498 * Thrown when errors are found parsing a java file. 476 * Thrown when errors are found parsing a java file.
499 */ 477 */
717 add(addListener(end = createTextField(6))); 695 add(addListener(end = createTextField(6)));
718 } 696 }
719 697
720 void setInfo(Info info) { 698 void setInfo(Info info) {
721 this.info = info; 699 this.info = info;
722 tagName.setText(tagNames.get(info.tag)); 700 tagName.setText(getTagName(info.tag));
723 start.setText(String.valueOf(info.start)); 701 start.setText(String.valueOf(info.start));
724 pos.setText(String.valueOf(info.pos)); 702 pos.setText(String.valueOf(info.pos));
725 end.setText(String.valueOf(info.end)); 703 end.setText(String.valueOf(info.end));
726 } 704 }
727 705

mercurial