Mercurial > hg > openjdk > jigsaw > langtools
changeset 549:e2879c758bac jigsaw-b03
Track TL/langtools changes, including workaround for using Ant 1.8.0
line wrap: on
line diff
--- a/.hgtags Mon Mar 01 17:53:56 2010 -0800 +++ b/.hgtags Thu Apr 01 10:07:33 2010 -0700 @@ -60,4 +60,5 @@ 47003a3622f6a17756ab0338bfa8a43e36549e99 jdk7-b82 c9f4ae1f1480e89aaf7e72173184089d9cea397a jdk7-b83 d9cd5b8286e44f3baf90da290cd295433e21c05a jdk7-b84 +136bfc67946219fb02ee223984540a4a9c5b209f jdk7-b85 51b53bc20417668e7e9a013238d3079f3df1800f jigsaw-b01
--- a/make/Makefile Mon Mar 01 17:53:56 2010 -0800 +++ b/make/Makefile Thu Apr 01 10:07:33 2010 -0700 @@ -188,10 +188,16 @@ # All ant targets of interest ANT_TARGETS = build clean sanity post-sanity diagnostics # for now +# Create diagnostics log (careful, ant 1.8.0 -diagnostics always does an exit 1) +$(OUTPUTDIR)/build/ant-diagnostics.log: + @mkdir -p $(OUTPUTDIR)/build $(ANT_TMPDIR) + @$(RM) $@ + $(ANT_JAVA_HOME) $(ANT_OPTS) $(ANT) -diagnostics > $@ ; \ + $(ANT_JAVA_HOME) $(ANT_OPTS) $(ANT) -version >> $@ + # Create a make target for each -$(ANT_TARGETS): +$(ANT_TARGETS): $(OUTPUTDIR)/build/ant-diagnostics.log @ mkdir -p $(OUTPUTDIR)/build $(ANT_TMPDIR) - $(ANT_JAVA_HOME) $(ANT_OPTS) $(ANT) -diagnostics > $(OUTPUTDIR)/build/ant-diagnostics.log $(ANT_JAVA_HOME) $(ANT_OPTS) $(ANT) $(ANT_OPTIONS) $@ #-------------------------------------------------------------------
--- a/make/jprt.properties Mon Mar 01 17:53:56 2010 -0800 +++ b/make/jprt.properties Thu Apr 01 10:07:33 2010 -0700 @@ -50,6 +50,5 @@ jprt.test.targets= # Directories needed to build -jprt.bundle.src.dirs=make src jprt.bundle.exclude.src.dirs=build dist
--- a/src/share/classes/com/sun/tools/apt/comp/Apt.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/apt/comp/Apt.java Thu Apr 01 10:07:33 2010 -0700 @@ -457,8 +457,10 @@ throw new UsageMessageNeededException(); try { - for(AnnotationProcessorFactory apFactory: factoryToAnnotation.keySet()) { - AnnotationProcessor processor = apFactory.getProcessorFor(factoryToAnnotation.get(apFactory), + for(Map.Entry<AnnotationProcessorFactory, Set<AnnotationTypeDeclaration>> entry : + factoryToAnnotation.entrySet()) { + AnnotationProcessorFactory apFactory = entry.getKey(); + AnnotationProcessor processor = apFactory.getProcessorFor(entry.getValue(), trivAPE); if (processor != null) processors.add(processor);
--- a/src/share/classes/com/sun/tools/apt/main/CommandLine.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/apt/main/CommandLine.java Thu Apr 01 10:07:33 2010 -0700 @@ -82,7 +82,7 @@ st.commentChar('#'); st.quoteChar('"'); st.quoteChar('\''); - while (st.nextToken() != st.TT_EOF) { + while (st.nextToken() != StreamTokenizer.TT_EOF) { args.append(st.sval); } r.close();
--- a/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java Thu Apr 01 10:07:33 2010 -0700 @@ -270,7 +270,7 @@ * The toString, hashCode, and equals methods foward to the underlying * type. */ - private static class MirroredTypeExceptionProxy extends ExceptionProxy { + private static final class MirroredTypeExceptionProxy extends ExceptionProxy { private static final long serialVersionUID = 6662035281599933545L; private MirroredTypeException ex; @@ -312,7 +312,7 @@ * The toString, hashCode, and equals methods foward to the underlying * types. */ - private static class MirroredTypesExceptionProxy extends ExceptionProxy { + private static final class MirroredTypesExceptionProxy extends ExceptionProxy { private static final long serialVersionUID = -6670822532616693951L; private MirroredTypesException ex;
--- a/src/share/classes/com/sun/tools/apt/mirror/declaration/DeclarationImpl.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/apt/mirror/declaration/DeclarationImpl.java Thu Apr 01 10:07:33 2010 -0700 @@ -58,7 +58,7 @@ protected final AptEnv env; public final Symbol sym; - protected static DeclarationFilter identityFilter = + protected static final DeclarationFilter identityFilter = new DeclarationFilter();
--- a/src/share/classes/com/sun/tools/apt/mirror/type/TypeMirrorImpl.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/apt/mirror/type/TypeMirrorImpl.java Thu Apr 01 10:07:33 2010 -0700 @@ -71,6 +71,6 @@ * {@inheritDoc} */ public int hashCode() { - return env.jctypes.hashCode(type); + return Types.hashCode(type); } }
--- a/src/share/classes/com/sun/tools/classfile/ConstantPool.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/classfile/ConstantPool.java Thu Apr 01 10:07:33 2010 -0700 @@ -40,7 +40,7 @@ */ public class ConstantPool { - public class InvalidIndex extends ConstantPoolException { + public static class InvalidIndex extends ConstantPoolException { private static final long serialVersionUID = -4350294289300939730L; InvalidIndex(int index) { super(index); @@ -53,7 +53,7 @@ } } - public class UnexpectedEntry extends ConstantPoolException { + public static class UnexpectedEntry extends ConstantPoolException { private static final long serialVersionUID = 6986335935377933211L; UnexpectedEntry(int index, int expected_tag, int found_tag) { super(index); @@ -71,7 +71,7 @@ public final int found_tag; } - public class InvalidEntry extends ConstantPoolException { + public static class InvalidEntry extends ConstantPoolException { private static final long serialVersionUID = 1000087545585204447L; InvalidEntry(int index, int tag) { super(index); @@ -87,7 +87,7 @@ public final int tag; } - public class EntryNotFound extends ConstantPoolException { + public static class EntryNotFound extends ConstantPoolException { private static final long serialVersionUID = 2885537606468581850L; EntryNotFound(Object value) { super(-1); @@ -746,7 +746,7 @@ public int byteLength() { class SizeOutputStream extends OutputStream { @Override - public void write(int b) throws IOException { + public void write(int b) { size++; } int size;
--- a/src/share/classes/com/sun/tools/doclets/standard/Standard.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/doclets/standard/Standard.java Thu Apr 01 10:07:33 2010 -0700 @@ -31,23 +31,21 @@ public class Standard { - public static final HtmlDoclet htmlDoclet = new HtmlDoclet(); - public static int optionLength(String option) { - return htmlDoclet.optionLength(option); + return HtmlDoclet.optionLength(option); } public static boolean start(RootDoc root) { - return htmlDoclet.start(root); + return HtmlDoclet.start(root); } public static boolean validOptions(String[][] options, DocErrorReporter reporter) { - return htmlDoclet.validOptions(options, reporter); + return HtmlDoclet.validOptions(options, reporter); } public static LanguageVersion languageVersion() { - return htmlDoclet.languageVersion(); + return HtmlDoclet.languageVersion(); } }
--- a/src/share/classes/com/sun/tools/javac/Launcher.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/Launcher.java Thu Apr 01 10:07:33 2010 -0700 @@ -64,7 +64,7 @@ fileChooser.setSelectedFile(new File(fileName)); } } - if (fileChooser.showOpenDialog(null) == fileChooser.APPROVE_OPTION) { + if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { String fileName = fileChooser.getSelectedFile().getPath(); prefs.put("recent.file", fileName); javac.run(System.in, null, null, "-d", "/tmp", fileName);
--- a/src/share/classes/com/sun/tools/javac/api/JavacTool.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/api/JavacTool.java Thu Apr 01 10:07:33 2010 -0700 @@ -137,7 +137,7 @@ } private static boolean match(OptionKind clientKind, OptionKind optionKind) { - return (clientKind == (optionKind == OptionKind.HIDDEN ? optionKind.EXTENDED : optionKind)); + return (clientKind == (optionKind == OptionKind.HIDDEN ? OptionKind.EXTENDED : optionKind)); } public JavacFileManager getStandardFileManager(
--- a/src/share/classes/com/sun/tools/javac/code/Lint.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/code/Lint.java Thu Apr 01 10:07:33 2010 -0700 @@ -198,7 +198,12 @@ /** * Warn about Sun proprietary API that may be removed in a future release. */ - SUNAPI("sunapi", true); + SUNAPI("sunapi", true), + + /** + * Warn about issues relating to use of statics + */ + STATIC("static"); LintCategory(String option) { this(option, false);
--- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu Apr 01 10:07:33 2010 -0700 @@ -166,7 +166,7 @@ * the default package; otherwise, the owner symbol is returned */ public Symbol location() { - if (owner.name == null || (owner.name.isEmpty() && owner.kind != PCK)) { + if (owner.name == null || (owner.name.isEmpty() && owner.kind != PCK && owner.kind != TYP)) { return null; } return owner;
--- a/src/share/classes/com/sun/tools/javac/code/Types.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Thu Apr 01 10:07:33 2010 -0700 @@ -2504,7 +2504,7 @@ } @Override public int hashCode() { - return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2); + return 127 * Types.hashCode(t1) + Types.hashCode(t2); } @Override public boolean equals(Object obj) { @@ -3375,7 +3375,7 @@ this.t = t; } public int hashCode() { - return Types.this.hashCode(t); + return Types.hashCode(t); } public boolean equals(Object obj) { return (obj instanceof SingletonType) &&
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Apr 01 10:07:33 2010 -0700 @@ -2025,6 +2025,10 @@ tree.pos(), site, sym.name, true); } } + } else if (sym.kind != ERR && (sym.flags() & STATIC) != 0 && sym.name != names._class) { + // If the qualified item is not a type and the selected item is static, report + // a warning. Make allowance for the class of an array type e.g. Object[].class) + chk.warnStatic(tree, "static.not.qualified.by.type", Kinds.kindName(sym.kind), sym.owner); } // If we are selecting an instance member via a `super', ... @@ -2641,6 +2645,7 @@ if (tree.bounds.tail.nonEmpty()) { log.error(tree.bounds.tail.head.pos(), "type.var.may.not.be.followed.by.other.bounds"); + log.unrecoverableError = true; tree.bounds = List.of(tree.bounds.head); a.bound = bs.head; }
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Apr 01 10:07:33 2010 -0700 @@ -190,6 +190,11 @@ sunApiHandler.report(pos, msg, args); } + public void warnStatic(DiagnosticPosition pos, String msg, Object... args) { + if (lint.isEnabled(LintCategory.STATIC)) + log.warning(pos, msg, args); + } + /** * Report any deferred diagnostics. */
--- a/src/share/classes/com/sun/tools/javac/comp/Enter.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Enter.java Thu Apr 01 10:07:33 2010 -0700 @@ -532,14 +532,9 @@ for (JCCompilationUnit tree : trees) { if (tree.starImportScope.elems == null) { JavaFileObject prev = log.useSource(tree.sourcefile); - try { - Env<AttrContext> tenv = typeEnvs.get(tree); - if (tenv == null) - tenv = topLevelEnv(tree); - memberEnter.memberEnter(tree, tenv); - } finally { - log.useSource(prev); - } + Env<AttrContext> treeEnv = topLevelEnv(tree); + memberEnter.memberEnter(tree, treeEnv); + log.useSource(prev); } } }
--- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Thu Apr 01 10:07:33 2010 -0700 @@ -607,10 +607,12 @@ public void visitNewArray(JCNewArray tree) { tree.elemtype = translate(tree.elemtype, null); translate(tree.dims, syms.intType); - tree.elems = translate(tree.elems, - (tree.type == null) ? null - : erasure(types.elemtype(tree.type))); - tree.type = erasure(tree.type); + if (tree.type != null) { + tree.elems = translate(tree.elems, erasure(types.elemtype(tree.type))); + tree.type = erasure(tree.type); + } else { + tree.elems = translate(tree.elems, null); + } result = tree; }
--- a/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Thu Apr 01 10:07:33 2010 -0700 @@ -271,7 +271,7 @@ archive = openArchive(directory); } catch (IOException ex) { log.error("error.reading.file", - directory, ex.getLocalizedMessage()); + directory, getMessage(ex)); return; } } @@ -682,7 +682,7 @@ archive = new MissingArchive(zipFileName); } catch (IOException ex) { if (zipFileName.exists()) - log.error("error.reading.file", zipFileName, ex.getLocalizedMessage()); + log.error("error.reading.file", zipFileName, getMessage(ex)); archive = new MissingArchive(zipFileName); } @@ -1106,4 +1106,23 @@ } throw new IllegalArgumentException("Invalid relative path: " + file); } + + /** + * Get a detail message from an IOException. + * Most, but not all, instances of IOException provide a non-null result + * for getLocalizedMessage(). But some instances return null: in these + * cases, fallover to getMessage(), and if even that is null, return the + * name of the exception itself. + * @param e an IOException + * @return a string to include in a compiler diagnostic + */ + public static String getMessage(IOException e) { + String s = e.getLocalizedMessage(); + if (s != null) + return s; + s = e.getMessage(); + if (s != null) + return s; + return e.toString(); + } }
--- a/src/share/classes/com/sun/tools/javac/file/Paths.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/file/Paths.java Thu Apr 01 10:07:33 2010 -0700 @@ -426,7 +426,7 @@ addFile(f, warn); } } catch (IOException e) { - log.error("error.reading.file", jarFile, e.getLocalizedMessage()); + log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e)); } }
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Apr 01 10:07:33 2010 -0700 @@ -1239,7 +1239,7 @@ self.name = simpleBinaryName(self.flatname, c.flatname) ; self.owner = m != null ? m : c; if (self.name.isEmpty()) - self.fullname = null; + self.fullname = names.empty; else self.fullname = ClassSymbol.formFullName(self.name, self.owner);
--- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java Thu Apr 01 10:07:33 2010 -0700 @@ -808,8 +808,8 @@ code.resolve(secondJumps); CondItem second = genCond(tree.falsepart, CRT_FLOW_TARGET); CondItem result = items.makeCondItem(second.opcode, - code.mergeChains(trueJumps, second.trueJumps), - code.mergeChains(falseJumps, second.falseJumps)); + Code.mergeChains(trueJumps, second.trueJumps), + Code.mergeChains(falseJumps, second.falseJumps)); if (markBranches) result.tree = tree.falsepart; return result; } else { @@ -1322,7 +1322,7 @@ if (useJsrLocally) { if (tree.finalizer != null) { Code.State jsrState = code.state.dup(); - jsrState.push(code.jsrReturnValue); + jsrState.push(Code.jsrReturnValue); tryEnv.info.cont = new Chain(code.emitJump(jsr), tryEnv.info.cont, @@ -1375,7 +1375,7 @@ genFinalizer(env); if (hasFinalizer || l.tail.nonEmpty()) { code.statBegin(TreeInfo.endPos(env.tree)); - exitChain = code.mergeChains(exitChain, + exitChain = Code.mergeChains(exitChain, code.branch(goto_)); } endFinalizerGap(env); @@ -1963,7 +1963,7 @@ result = items. makeCondItem(rcond.opcode, rcond.trueJumps, - code.mergeChains(falseJumps, + Code.mergeChains(falseJumps, rcond.falseJumps)); } else { result = lcond; @@ -1976,7 +1976,7 @@ CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET); result = items. makeCondItem(rcond.opcode, - code.mergeChains(trueJumps, rcond.trueJumps), + Code.mergeChains(trueJumps, rcond.trueJumps), rcond.falseJumps); } else { result = lcond;
--- a/src/share/classes/com/sun/tools/javac/jvm/Items.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/Items.java Thu Apr 01 10:07:33 2010 -0700 @@ -792,25 +792,25 @@ } Chain jumpTrue() { - if (tree == null) return code.mergeChains(trueJumps, code.branch(opcode)); + if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode)); // we should proceed further in -Xjcov mode only int startpc = code.curPc(); - Chain c = code.mergeChains(trueJumps, code.branch(opcode)); + Chain c = Code.mergeChains(trueJumps, code.branch(opcode)); code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc()); return c; } Chain jumpFalse() { - if (tree == null) return code.mergeChains(falseJumps, code.branch(code.negate(opcode))); + if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode))); // we should proceed further in -Xjcov mode only int startpc = code.curPc(); - Chain c = code.mergeChains(falseJumps, code.branch(code.negate(opcode))); + Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode))); code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc()); return c; } CondItem negate() { - CondItem c = new CondItem(code.negate(opcode), falseJumps, trueJumps); + CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps); c.tree = tree; return c; }
--- a/src/share/classes/com/sun/tools/javac/main/CommandLine.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/main/CommandLine.java Thu Apr 01 10:07:33 2010 -0700 @@ -82,7 +82,7 @@ st.commentChar('#'); st.quoteChar('"'); st.quoteChar('\''); - while (st.nextToken() != st.TT_EOF) { + while (st.nextToken() != StreamTokenizer.TT_EOF) { args.append(st.sval); } r.close();
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Apr 01 10:07:33 2010 -0700 @@ -549,12 +549,6 @@ return log.nwarnings; } - /** Whether or not any parse errors have occurred. - */ - public boolean parseErrors() { - return parseErrors; - } - /** Try to open input stream with given name. * Report an error if this fails. * @param filename The file name of the input stream to be opened. @@ -564,7 +558,7 @@ inputFiles.add(filename); return filename.getCharContent(false); } catch (IOException e) { - log.error("error.reading.file", filename, e.getLocalizedMessage()); + log.error("error.reading.file", filename, JavacFileManager.getMessage(e)); return null; } } @@ -587,7 +581,7 @@ int initialErrorCount = log.nerrors; Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); tree = parser.parseCompilationUnit(); - parseErrors |= (log.nerrors > initialErrorCount); + log.unrecoverableError |= (log.nerrors > initialErrorCount); if (verbose) { printVerbose("parsing.done", Long.toString(elapsed(msec))); } @@ -718,7 +712,7 @@ try { tree = parse(filename, filename.getCharContent(false)); } catch (IOException e) { - log.error("error.reading.file", filename, e); + log.error("error.reading.file", filename, JavacFileManager.getMessage(e)); tree = make.TopLevel(List.<JCTree>nil()); } finally { log.useSource(prev); @@ -774,9 +768,6 @@ private long start_msec = 0; public long elapsed_msec = 0; - /** Track whether any errors occurred while parsing source text. */ - private boolean parseErrors = false; - public void compile(List<JavaFileObject> sourceFileObject) throws Throwable { compile(sourceFileObject, List.<String>nil(), null); @@ -1121,7 +1112,7 @@ return env; if (verboseCompilePolicy) - log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]"); + Log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]"); if (verbose) printVerbose("checking.attribution", env.enclClass.sym);
--- a/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java Thu Apr 01 10:07:33 2010 -0700 @@ -26,6 +26,8 @@ package com.sun.tools.javac.model; import com.sun.tools.javac.util.*; +import java.io.ObjectInputStream; +import java.io.IOException; import java.lang.annotation.*; import java.lang.reflect.Array; import java.lang.reflect.Method; @@ -268,10 +270,10 @@ * The toString, hashCode, and equals methods foward to the underlying * type. */ - private static class MirroredTypeExceptionProxy extends ExceptionProxy { + private static final class MirroredTypeExceptionProxy extends ExceptionProxy { static final long serialVersionUID = 269; - private transient final TypeMirror type; + private transient TypeMirror type; private final String typeString; MirroredTypeExceptionProxy(TypeMirror t) { @@ -296,6 +298,13 @@ protected RuntimeException generateException() { return new MirroredTypeException(type); } + + // Explicitly set all transient fields. + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + type = null; + } } @@ -304,10 +313,10 @@ * The toString, hashCode, and equals methods foward to the underlying * types. */ - private static class MirroredTypesExceptionProxy extends ExceptionProxy { + private static final class MirroredTypesExceptionProxy extends ExceptionProxy { static final long serialVersionUID = 269; - private transient final List<TypeMirror> types; + private transient List<TypeMirror> types; private final String typeStrings; MirroredTypesExceptionProxy(List<TypeMirror> ts) { @@ -333,5 +342,12 @@ protected RuntimeException generateException() { return new MirroredTypesException(types); } + + // Explicitly set all transient fields. + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + types = null; + } } }
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Apr 01 10:07:33 2010 -0700 @@ -1585,7 +1585,10 @@ JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t); if (newClass.def != null) { assert newClass.def.mods.annotations.isEmpty(); - newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations); + if (newAnnotations.nonEmpty()) { + newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos); + newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations); + } } return newClass; } else { @@ -3266,6 +3269,18 @@ return (oc >= 0) ? TreeInfo.opPrec(oc) : -1; } + /** + * Return the lesser of two positions, making allowance for either one + * being unset. + */ + static int earlier(int pos1, int pos2) { + if (pos1 == Position.NOPOS) + return pos2; + if (pos2 == Position.NOPOS) + return pos1; + return (pos1 < pos2 ? pos1 : pos2); + } + /** Return operation tag of binary operator represented by token, * -1 if token is not a binary operator. */
--- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Apr 01 10:07:33 2010 -0700 @@ -690,10 +690,12 @@ ProcessorState ps = psi.next(); Set<String> matchedNames = new HashSet<String>(); Set<TypeElement> typeElements = new LinkedHashSet<TypeElement>(); - for (String unmatchedAnnotationName : unmatchedAnnotations.keySet()) { + + for (Map.Entry<String, TypeElement> entry: unmatchedAnnotations.entrySet()) { + String unmatchedAnnotationName = entry.getKey(); if (ps.annotationSupported(unmatchedAnnotationName) ) { matchedNames.add(unmatchedAnnotationName); - TypeElement te = unmatchedAnnotations.get(unmatchedAnnotationName); + TypeElement te = entry.getValue(); if (te != null) typeElements.add(te); } @@ -790,16 +792,13 @@ List<JCCompilationUnit> roots, List<ClassSymbol> classSymbols, Iterable<? extends PackageSymbol> pckSymbols) - throws IOException { + throws IOException { log = Log.instance(context); // Writer for -XprintRounds and -XprintProcessorInfo data PrintWriter xout = context.get(Log.outKey); TaskListener taskListener = context.get(TaskListener.class); - - AnnotationCollector collector = new AnnotationCollector(); - JavaCompiler compiler = JavaCompiler.instance(context); compiler.todo.clear(); // free the compiler's resources @@ -878,7 +877,7 @@ roots = cleanTrees(roots).appendList(parsedFiles); // Check for errors after parsing - if (compiler.parseErrors()) { + if (log.unrecoverableError) { errorStatus = true; break runAround; } else { @@ -912,7 +911,7 @@ roots = runLastRound(xout, roundNumber, errorStatus, compiler, roots, taskListener); // Set error status for any files compiled and generated in // the last round - if (compiler.parseErrors()) + if (log.unrecoverableError) errorStatus = true; compiler.close(false); @@ -1218,45 +1217,6 @@ return false; } - private class AnnotationCollector extends TreeScanner { - List<JCTree> path = List.nil(); - static final boolean verbose = false; - List<JCAnnotation> annotations = List.nil(); - - public List<JCAnnotation> findAnnotations(List<? extends JCTree> nodes) { - annotations = List.nil(); - scan(nodes); - List<JCAnnotation> found = annotations; - annotations = List.nil(); - return found.reverse(); - } - - public void scan(JCTree node) { - if (node == null) - return; - Symbol sym = TreeInfo.symbolFor(node); - if (sym != null) - path = path.prepend(node); - super.scan(node); - if (sym != null) - path = path.tail; - } - - public void visitAnnotation(JCAnnotation node) { - annotations = annotations.prepend(node); - if (verbose) { - StringBuilder sb = new StringBuilder(); - for (JCTree tree : path.reverse()) { - System.err.print(sb); - System.err.println(TreeInfo.symbolFor(tree)); - sb.append(" "); - } - System.err.print(sb); - System.err.println(node); - } - } - } - private static <T extends JCTree> List<T> cleanTrees(List<T> nodes) { for (T node : nodes) treeCleaner.scan(node);
--- a/src/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java Thu Apr 01 10:07:33 2010 -0700 @@ -229,23 +229,24 @@ if (kind == ENUM) { List<Element> enclosedElements = new ArrayList<Element>(e.getEnclosedElements()); + // Handle any enum constants specially before other entities. List<Element> enumConstants = new ArrayList<Element>(); for(Element element : enclosedElements) { if (element.getKind() == ENUM_CONSTANT) enumConstants.add(element); } - - int i; - for(i = 0; i < enumConstants.size()-1; i++) { + if (!enumConstants.isEmpty()) { + int i; + for(i = 0; i < enumConstants.size()-1; i++) { + this.visit(enumConstants.get(i), true); + writer.print(","); + } this.visit(enumConstants.get(i), true); - writer.print(","); - } - if (i >= 0 ) { - this.visit(enumConstants.get(i), true); - writer.print(";"); + writer.println(";\n"); + + enclosedElements.removeAll(enumConstants); } - enclosedElements.removeAll(enumConstants); for(Element element : enclosedElements) this.visit(element); } else {
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Apr 01 10:07:33 2010 -0700 @@ -731,6 +731,9 @@ {0}: major version {1} is newer than {2}, the highest major version supported by this compiler.\n\ It is recommended that the compiler be upgraded. +compiler.warn.static.not.qualified.by.type=\ + [static] static {0} should be qualified by type name, {1}, instead of by an expression + # Warnings related to annotation processing compiler.warn.proc.package.does.not.exist=\ package {0} does not exist
--- a/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Thu Apr 01 10:07:33 2010 -0700 @@ -201,7 +201,7 @@ private String selectFormat(JCDiagnostic d) { DiagnosticSource source = d.getDiagnosticSource(); String format = getConfiguration().getFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT); - if (source != null) { + if (source != null && source != DiagnosticSource.NO_SOURCE) { if (d.getIntPosition() != Position.NOPOS) { format = getConfiguration().getFormat(BasicFormatKind.DEFAULT_POS_FORMAT); } else if (source.getFile() != null &&
--- a/src/share/classes/com/sun/tools/javac/util/Log.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/util/Log.java Thu Apr 01 10:07:33 2010 -0700 @@ -192,6 +192,12 @@ */ public int nwarnings = 0; + /** + * Whether or not an unrecoverable error has been seen. + * Unrecoverable errors prevent subsequent annotation processing. + */ + public boolean unrecoverableError; + /** A set of all errors generated so far. This is used to avoid printing an * error message more than once. For each error, a pair consisting of the * source file name and source code position of the error is added to the set.
--- a/src/share/classes/com/sun/tools/javadoc/DocEnv.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javadoc/DocEnv.java Thu Apr 01 10:07:33 2010 -0700 @@ -34,7 +34,6 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.ClassType; -import com.sun.tools.javac.comp.Attr; import com.sun.tools.javac.comp.Check; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.Context; @@ -73,10 +72,6 @@ /** Referenced directly in RootDocImpl. */ JavadocClassReader reader; - /** The compiler's attribution phase (needed to evaluate - * constant initializers). */ - Attr attr; - /** Javadoc's own version of the compiler's enter phase. */ JavadocEnter enter; @@ -91,8 +86,6 @@ /** Access filter (public, protected, ...). */ ModifierFilter showAccess; - private ClassDocImpl runtimeException; - /** True if we are using a sentence BreakIterator. */ boolean breakiterator; @@ -129,7 +122,6 @@ syms = Symtab.instance(context); reader = JavadocClassReader.instance0(context); enter = JavadocEnter.instance0(context); - attr = Attr.instance(context); names = Names.instance(context); externalizableSym = reader.enterClass(names.fromString("java.io.Externalizable")); chk = Check.instance(context);
--- a/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java Thu Apr 01 10:07:33 2010 -0700 @@ -349,12 +349,12 @@ // (int i, String s) ==> [0] = "int", [1] = String // (int[][], String[]) ==> [0] = "int[][]" // [1] = "String[]" class ParameterParseMachine { - final int START = 0; - final int TYPE = 1; - final int NAME = 2; - final int TNSPACE = 3; // space between type and name - final int ARRAYDECORATION = 4; - final int ARRAYSPACE = 5; + static final int START = 0; + static final int TYPE = 1; + static final int NAME = 2; + static final int TNSPACE = 3; // space between type and name + static final int ARRAYDECORATION = 4; + static final int ARRAYSPACE = 5; String parameters;
--- a/src/share/classes/com/sun/tools/javah/JavahTask.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javah/JavahTask.java Thu Apr 01 10:07:33 2010 -0700 @@ -255,9 +255,11 @@ } this.classes = new ArrayList<String>(); - for (String classname: classes) { - classname.getClass(); // null-check - this.classes.add(classname); + if (classes != null) { + for (String classname: classes) { + classname.getClass(); // null-check + this.classes.add(classname); + } } } @@ -347,8 +349,7 @@ fileManager = getDefaultFileManager(diagnosticListener, log); Iterator<String> iter = args.iterator(); - if (!iter.hasNext()) - help = true; + noArgs = !iter.hasNext(); while (iter.hasNext()) { String arg = iter.next(); @@ -365,7 +366,7 @@ } if ((classes == null || classes.size() == 0) && - !(help || version || fullVersion)) { + !(noArgs || help || version || fullVersion)) { throw new BadArgs("err.no.classes.specified"); } @@ -409,9 +410,9 @@ Util util = new Util(log, diagnosticListener); - if (help) { + if (noArgs || help) { showHelp(); - return true; + return help; // treat noArgs as an error for purposes of exit code } if (version || fullVersion) { @@ -629,6 +630,7 @@ String usercp; List<String> classes; boolean verbose; + boolean noArgs; boolean help; boolean trace; boolean version;
--- a/src/share/classes/com/sun/tools/javap/ClassWriter.java Mon Mar 01 17:53:56 2010 -0800 +++ b/src/share/classes/com/sun/tools/javap/ClassWriter.java Thu Apr 01 10:07:33 2010 -0700 @@ -225,15 +225,15 @@ writeModifiers(flags.getFieldModifiers()); Signature_attribute sigAttr = getSignature(f.attributes); if (sigAttr == null) - print(getFieldType(f.descriptor)); + print(getJavaFieldType(f.descriptor)); else { try { Type t = sigAttr.getParsedSignature().getType(constant_pool); - print(t); + print(getJavaName(t.toString())); } catch (ConstantPoolException e) { // report error? // fall back on non-generic descriptor - print(getFieldType(f.descriptor)); + print(getJavaFieldType(f.descriptor)); } } print(" "); @@ -314,14 +314,14 @@ } if (getName(m).equals("<init>")) { print(getJavaName(classFile)); - print(getParameterTypes(d, flags)); + print(getJavaParameterTypes(d, flags)); } else if (getName(m).equals("<clinit>")) { print("{}"); } else { - print(getReturnType(d)); + print(getJavaReturnType(d)); print(" "); print(getName(m)); - print(getParameterTypes(d, flags)); + print(getJavaParameterTypes(d, flags)); } Attribute e_attr = m.attributes.get(Attribute.Exceptions); @@ -460,9 +460,9 @@ } } - String getFieldType(Descriptor d) { + String getJavaFieldType(Descriptor d) { try { - return d.getFieldType(constant_pool); + return getJavaName(d.getFieldType(constant_pool)); } catch (ConstantPoolException e) { return report(e); } catch (DescriptorException e) { @@ -470,9 +470,9 @@ } } - String getReturnType(Descriptor d) { + String getJavaReturnType(Descriptor d) { try { - return d.getReturnType(constant_pool); + return getJavaName(d.getReturnType(constant_pool)); } catch (ConstantPoolException e) { return report(e); } catch (DescriptorException e) { @@ -480,9 +480,9 @@ } } - String getParameterTypes(Descriptor d, AccessFlags flags) { + String getJavaParameterTypes(Descriptor d, AccessFlags flags) { try { - return adjustVarargs(flags, d.getParameterTypes(constant_pool)); + return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool))); } catch (ConstantPoolException e) { return report(e); } catch (DescriptorException e) {
--- a/test/Makefile Mon Mar 01 17:53:56 2010 -0800 +++ b/test/Makefile Thu Apr 01 10:07:33 2010 -0700 @@ -1,6 +1,20 @@ # -# Makefile to run jtreg and any other tests +# Makefile to run jtreg and other tests +# + +# Product builds and langtools builds +# +# A full product build (or "control" build) creates a complete JDK image. +# To test a product build, set TESTJAVA to the path for the image. # +# A langtools build just builds the langtools components of a JDK. +# To test a langtools build, set TESTJAVA to the path for a recent JDK +# build, and set TESTBOOTCLASSPATH to the compiled langtools classes -- +# for example build/classes or dist/lib/classes.jar. + +# JPRT +# JPRT may invoke this Makefile directly, as part of a langtools build, +# or indirectly, via FOREST/test/Makefile, as part of a control build. # Get OS/ARCH specifics OSNAME = $(shell uname -s) @@ -41,8 +55,11 @@ # Root of this test area (important to use full paths in some places) TEST_ROOT := $(shell pwd) -# Default bundle of all test results (passed or not) -JPRT_ARCHIVE_BUNDLE=$(TEST_ROOT)/JPRT_ARCHIVE_BUNDLE.zip +# Default bundle of all test results (passed or not) (JPRT only) +ifdef JPRT_JOB_ID + JPRT_CLEAN = clean + JPRT_ARCHIVE_BUNDLE = $(TEST_ROOT)/JPRT_ARCHIVE_BUNDLE.zip +endif ifeq ($(PLATFORM), windows) SLASH_JAVA = J: @@ -57,8 +74,21 @@ JTREG_HOME = $(SLASH_JAVA)/re/jtreg/4.0/promoted/latest/binaries/jtreg endif JTREG = $(JTREG_HOME)/$(JT_PLATFORM)/bin/jtreg +JTDIFF = $(JTREG_HOME)/$(JT_PLATFORM)/bin/jtdiff -# Default JDK for JTREG +# Default JCK to run +ifdef JPRT_JCK_HOME + JCK_HOME = $(JPRT_JCK_HOME) +else + JCK_HOME = $(SLASH_JAVA)/re/jck/7/promoted/latest/binaries +endif + +# Default JDK for JTREG and JCK +# +# JT_JAVA is the version of java used to run jtreg/JCK. Since it is now +# standard to execute tests in sameVM mode, it should normally be set the +# same as TESTJAVA (although not necessarily so.) +# ifdef JPRT_JAVA_HOME JT_JAVA = $(JPRT_JAVA_HOME) else @@ -72,49 +102,275 @@ TESTJAVA = $(SLASH_JAVA)/re/jdk/1.7.0/promoted/latest/binaries/$(PLATFORM)-$(ARCH) endif -TESTBOOTCLASSPATH = $(PRODUCT_HOME)/dist/lib/classes.jar +# PRODUCT_HOME is a JPRT variable pointing to a directory containing the output from +# make/Makefile +# For langtools, this is a directory containing build and dist +# For a control build, this is build/$(PRODUCT)-$(ARCH)/j2sdk-image +ifdef PRODUCT_HOME + ifeq ($(shell [ -r $(PRODUCT_HOME)/dist/lib/classes.jar ]; echo $$?),0) + TESTBOOTCLASSPATH = $(PRODUCT_HOME)/dist/lib/classes.jar + endif + ifeq ($(shell [ -r $(PRODUCT_HOME)/lib/tools.jar ]; echo $$?),0) + TESTJAVA = $(PRODUCT_HOME) + endif +endif + +ifdef TESTBOOTCLASSPATH + JTREG_OPTIONS += -Xbootclasspath/p:$(TESTBOOTCLASSPATH) +### In the following, -refvmoptions is an undocumented option +### The following does not work JCK 7 b30 2/6/2010. Awaiting b31. + JCK_OPTIONS += \ + -vmoptions:-Xbootclasspath/p:$(TESTBOOTCLASSPATH) \ + -refvmoptions:-Xbootclasspath/p:$(TESTBOOTCLASSPATH) +endif + +# Concurrency is the number of tests that can execute at once. +# Supported for JCK, not supported for jtreg. +# On an otherwise empty machine, suggest setting to (#cpus + 2) +# If unset, the default is (#cpus) +### RFE: determine and use #cpus +ifdef JCK_CONCURRENCY + JCK_OPTIONS += -concurrency:$(JCK_CONCURRENCY) +endif + +# JCK is executed using "Multi-JVM Group Mode", which is a hybrid +# of otherVM and sameVM modes. New JVMs are created and reused for +# a number of tests, then eventually discarded and a new one started. +# This amortizes the JVM startup time. The "group size" defines +# how many tests are run in a JVM before it is replaced. +# If unset, the default is 100. +JCK_GROUP_SIZE = 1000 +ifdef JCK_GROUP_SIZE + JCK_COMPILER_OPTIONS += \ + -jtoptions:-Ejck.env.compiler.testCompile.groupMode.groupSize=$(JCK_GROUP_SIZE) \ + -jtoptions:-Ejck.env.compiler.compRefExecute.groupMode.groupSize=$(JCK_GROUP_SIZE) +### The following is not supported. Awaiting RFE 6924287 +### 6924287: Jck4Jdk: Allow to configure test group size for group mode via simple command line option +### JCK_RUNTIME_OPTIONS += \ +### -jtoptions:-Ejck.env.runtime.testCompile.groupMode.groupSize=$(JCK_GROUP_SIZE) +endif + +# Assertions: some tests show failures when assertions are enabled. +# Since javac is typically loaded via the bootclassloader (either via TESTJAVA +# or TESTBOOTCLASSPATH), you may need -esa to enable assertions in javac. +JTREG_OPTIONS += $(ASSERTION_OPTIONS) +JCK_OPTIONS += $(ASSERTION_OPTIONS:%=-vmoptions:%) + +# Include shared options +JCK_COMPILER_OPTIONS += $(JCK_OPTIONS) +JCK_RUNTIME_OPTIONS += $(JCK_OPTIONS) + +# Exit codes: +# jtreg, jck: 0: OK, 1: tests failed, 2: tests error; 3+: SERIOUS +FATAL_JTREG_EXIT = 3 +FATAL_JCK_EXIT = 3 +# jtdiff: 0: OK, 1: differences found; 2+: SERIOUS +FATAL_JTDIFF_EXIT = 2 +# +# Exit -- used for final "normal" exit from "make". Redefine to "true" to avoid +# having make exit with non-zero return code. +EXIT = exit +# Function to exit shell if exit code of preceding command is greater than or equal +# to a given level. Redefine function or preceding FATAL_*_EXIT codes as needed. +EXIT_IF_FATAL = status=$$?; if [ $$status -ge $(1) ]; then exit $$status ; fi # The test directories to run DEFAULT_TESTDIRS = . TESTDIRS = $(DEFAULT_TESTDIRS) # Root of all test results -TEST_OUTPUT_DIR = $(TEST_ROOT)/o_$(PLATFORM)-$(ARCH) +TEST_OUTPUT_DIR = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)/test/langtools +ABS_TEST_OUTPUT_DIR := \ + $(shell mkdir -p $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)/test/langtools; \ + cd $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)/test/langtools; \ + pwd ) +# Subdirectories for different test runs +JTREG_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jtreg +JCK_COMPILER_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jck-compiler +JCK_RUNTIME_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jck-runtime-Xcompile -# Default make rule -all apt javac javadoc javah javap: clean check jtreg-tests $(JPRT_ARCHIVE_BUNDLE) +# Default make rule -- warning, may take a while +all: $(JPRT_CLEAN) jtreg-tests jck-compiler-tests jck-runtime-tests $(JPRT_ARCHIVE_BUNDLE) all-summary + @echo "Testing completed successfully" + +jtreg apt javac javadoc javah javap: $(JPRT_CLEAN) jtreg-tests $(JPRT_ARCHIVE_BUNDLE) jtreg-summary + @echo "Testing completed successfully" + +jck-compiler: $(JPRT_CLEAN) jck-compiler-tests $(JPRT_ARCHIVE_BUNDLE) jck-compiler-summary + @echo "Testing completed successfully" + +jck-runtime: $(JPRT_CLEAN) jck-runtime-tests $(JPRT_ARCHIVE_BUNDLE) jck-runtime-summary @echo "Testing completed successfully" # for use with JPRT -testrule -all: TESTDIRS = . -apt: TESTDIRS = tools/apt -javac: TESTDIRS = tools/javac -javadoc: TESTDIRS = tools/javadoc com/sun/javadoc -javah: TESTDIRS = tools/javah -javap: TESTDIRS = tools/javap +all: JTREG_TESTDIRS = . +jtreg: JTREG_TESTDIRS = . +apt: JTREG_TESTDIRS = tools/apt +javac: JTREG_TESTDIRS = tools/javac +javadoc: JTREG_TESTDIRS = tools/javadoc com/sun/javadoc +javah: JTREG_TESTDIRS = tools/javah +javap: JTREG_TESTDIRS = tools/javap + +# Run jtreg tests +# +# JTREG_HOME +# Installed location of jtreg +# JT_JAVA +# Version of java used to run jtreg. Should normally be the same as TESTJAVA +# TESTJAVA +# Version of java to be tested. +# JTREG_OPTIONS +# Additional options for jtreg +# JTREG_TESTDIRS +# Directories of tests to be run +# JTREG_OUTPUT_DIR +# Where to write the results +# JTREG_REFERENCE +# (Optional) reference results (e.g. work, report or summary.txt) +# +jtreg-tests: check-jtreg FRC + @rm -f -r $(JTREG_OUTPUT_DIR)/JTwork $(JTREG_OUTPUT_DIR)/JTreport \ + $(JTREG_OUTPUT_DIR)/diff.html $(JTREG_OUTPUT_DIR)/status.txt + @mkdir -p $(JTREG_OUTPUT_DIR) + JT_JAVA=$(JT_JAVA) $(JTREG) \ + -J-Xmx512m \ + -a -samevm -ignore:quiet -v:fail,error,nopass \ + -r:$(JTREG_OUTPUT_DIR)/JTreport \ + -w:$(JTREG_OUTPUT_DIR)/JTwork \ + -jdk:$(TESTJAVA) \ + $(JAVA_ARGS:%=-vmoption:%) \ + $(JTREG_OPTIONS) \ + $(JTREG_TESTDIRS) \ + || ( $(call EXIT_IF_FATAL,$(FATAL_JTREG_EXIT)) ; \ + echo $$status > $(JTREG_OUTPUT_DIR)/status.txt \ + ) +ifdef JTREG_REFERENCE + JT_JAVA=$(JT_JAVA) $(JTDIFF) -o $(JTREG_OUTPUT_DIR)/diff.html \ + $(JTREG_REFERENCE) $(JTREG_OUTPUT_DIR)/JTreport \ + || ( $(call EXIT_IF_FATAL,$(FATAL_JTDIFF_EXIT)) ) +endif + +jtreg-summary: FRC + if [ -r $(JTREG_OUTPUT_DIR)/status.txt ]; then \ + echo ; echo "Summary of jtreg test failures" ; \ + cat $(JTREG_OUTPUT_DIR)/JTreport/text/summary.txt | \ + grep -v 'Not run' | grep -v 'Passed' ; \ + echo ; \ + $(EXIT) `cat $(JTREG_OUTPUT_DIR)/status.txt` ; \ + fi # Check to make sure these directories exist -check: $(JT_HOME) $(PRODUCT_HOME) $(JTREG) +check-jtreg: $(JT_HOME) $(PRODUCT_HOME) $(JTREG) + + +# Run JCK-compiler tests +# +# JCK_HOME +# Installed location of JCK: should include JCK-compiler, and JCK-extras +# JT_JAVA +# Version of java used to run JCK. Should normally be the same as TESTJAVA +# TESTJAVA +# Version of java to be tested. +# JCK_COMPILER_OPTIONS +# Additional options for JCK-compiler +# JCK_COMPILER_TESTDIRS +# Directories of tests to be run +# JCK_COMPILER_OUTPUT_DIR +# Where to write the results +# JCK_COMPILER_REFERENCE +# (Optional) reference results (e.g. work, report or summary.txt) +# +jck-compiler-tests: check-jck FRC + @rm -f -r $(JCK_COMPILER_OUTPUT_DIR)/work $(JCK_COMPILER_OUTPUT_DIR)/report \ + $(JCK_COMPILER_OUTPUT_DIR)/diff.html $(JCK_COMPILER_OUTPUT_DIR)/status.txt + @mkdir -p $(JCK_COMPILER_OUTPUT_DIR) + $(JT_JAVA)/bin/java -XX:MaxPermSize=256m -Xmx512m \ + -jar $(JCK_HOME)/JCK-compiler-7/lib/jtjck.jar \ + -v:non-pass \ + -r:$(JCK_COMPILER_OUTPUT_DIR)/report \ + -w:$(JCK_COMPILER_OUTPUT_DIR)/work \ + -jdk:$(TESTJAVA) \ + $(JCK_COMPILER_OPTIONS) \ + $(JCK_COMPILER_TESTDIRS) \ + || ( $(call EXIT_IF_FATAL,$(FATAL_JCK_EXIT)) ; \ + echo $$status > $(JCK_COMPILER_OUTPUT_DIR)/status.txt \ + ) +ifdef JCK_COMPILER_REFERENCE + JT_JAVA=$(JT_JAVA) $(JTDIFF) -o $(JCK_COMPILER_OUTPUT_DIR)/diff.html \ + $(JCK_COMPILER_REFERENCE) $(JCK_COMPILER_OUTPUT_DIR)/report \ + || ( $(call EXIT_IF_FATAL,$(FATAL_JTDIFF_EXIT)) ) +endif + +jck-compiler-summary: FRC + if [ -r $(JCK_COMPILER_OUTPUT_DIR)/status.txt ]; then \ + echo ; echo "Summary of JCK-compiler test failures" ; \ + cat $(JCK_COMPILER_OUTPUT_DIR)/report/text/summary.txt | \ + grep -v 'Not run' | grep -v 'Passed' ; \ + echo ; \ + $(EXIT) `cat $(JCK_COMPILER_OUTPUT_DIR)/status.txt` ; \ + fi -# Run the tests -jtreg-tests: FRC - @echo "Using export JAVA_TOOL_OPTIONS=$(JAVA_TOOL_OPTIONS)" - @rm -f -r $(TEST_OUTPUT_DIR)/JTwork $(TEST_OUTPUT_DIR)/JTreport - @mkdir -p $(TEST_OUTPUT_DIR) - JT_JAVA=$(JT_JAVA) $(JTREG) \ - -a -samevm -k:\!ignore -v:fail,error,nopass \ - -r:$(TEST_OUTPUT_DIR)/JTreport \ - -w:$(TEST_OUTPUT_DIR)/JTwork \ - -jdk:$(TESTJAVA) \ - -Xbootclasspath/p:$(TESTBOOTCLASSPATH) \ - $(JAVA_ARGS:%=-vmoption:%) \ - $(TESTDIRS) \ - || ( status=$$? ; \ - echo ; echo "Summary of test failures" ; \ - cat $(TEST_OUTPUT_DIR)/JTreport/text/summary.txt | \ - grep -v 'Not run' | grep -v 'Passed' ; \ - echo ; \ - exit $$status ) +# Run JCK-runtime tests in -Xcompile mode +# This is a special mode to test javac by compiling the tests in the JCK-runtime test suite +# Normal JCK-runtime invocation belongs in the jdk/ repository. +# +# JCK_HOME +# Installed location of JCK: should include JCK-compiler, JCK-runtime and JCK-extras +# JT_JAVA +# Version of java used to run JCK. Should normally be the same as TESTJAVA +# TESTJAVA +# Version of java to be tested. +# JCK_RUNTIME_OPTIONS +# Additional options for JCK-runtime +# JCK_RUNTIME_TESTDIRS +# Directories of tests to be run +# JCK_RUNTIME_OUTPUT_DIR +# Where to write the results +# JCK_RUNTIME_REFERENCE +# (Optional) reference results (e.g. work, report or summary.txt) +# +jck-runtime-tests: check-jck FRC + @rm -f -r $(JCK_RUNTIME_OUTPUT_DIR)/work $(JCK_RUNTIME_OUTPUT_DIR)/report \ + $(JCK_RUNTIME_OUTPUT_DIR)/diff.html $(JCK_RUNTIME_OUTPUT_DIR)/status.txt + @mkdir -p $(JCK_RUNTIME_OUTPUT_DIR) + $(JT_JAVA)/bin/java -XX:MaxPermSize=256m -Xmx512m \ + -jar $(JCK_HOME)/JCK-runtime-7/lib/jtjck.jar \ + -v:non-pass \ + -r:$(JCK_RUNTIME_OUTPUT_DIR)/report \ + -w:$(JCK_RUNTIME_OUTPUT_DIR)/work \ + -jdk:$(TESTJAVA) \ + -Xcompile \ + $(JCK_RUNTIME_OPTIONS) \ + $(JCK_RUNTIME_TESTDIRS) \ + || ( $(call EXIT_IF_FATAL,$(FATAL_JCK_EXIT)) ; \ + echo $$status > $(JCK_RUNTIME_OUTPUT_DIR)/status.txt \ + ) +ifdef JCK_RUNTIME_REFERENCE + JT_JAVA=$(JT_JAVA) $(JTDIFF) -o $(JCK_RUNTIME_OUTPUT_DIR)/diff.html \ + $(JCK_RUNTIME_REFERENCE) $(JCK_RUNTIME_OUTPUT_DIR)/report \ + || ( $(call EXIT_IF_FATAL,$(FATAL_JTDIFF_EXIT)) ) +endif + +jck-runtime-summary: FRC + if [ -r $(JCK_RUNTIME_OUTPUT_DIR)/status.txt ]; then \ + echo ; echo "Summary of JCK-runtime test failures" ; \ + cat $(JCK_RUNTIME_OUTPUT_DIR)/report/text/summary.txt | \ + grep -v 'Not run' | grep -v 'Passed' ; \ + echo ; \ + $(EXIT) `cat $(JCK_RUNTIME_OUTPUT_DIR)/status.txt` ; \ + fi + +# Check to make sure these directories exist +check-jck: $(JT_HOME) $(JCK_HOME) $(PRODUCT_HOME) + +all-summary: FRC + if [ -n "`find $(TEST_OUTPUT_DIR) -name status.txt`" ]; then + echo ; echo "Summary of test failures" ; \ + cat `find $(TEST_OUTPUT_DIR) -name summary.txt` | \ + grep -v 'Not run' | grep -v 'Passed' ; \ + echo ; \ + $(EXIT) 1 + fi # Bundle up the results $(JPRT_ARCHIVE_BUNDLE): FRC @@ -124,12 +380,17 @@ # Cleanup clean: - rm -f -r $(TEST_OUTPUT_DIR) rm -f $(JPRT_ARCHIVE_BUNDLE) # Used to force a target rules to run FRC: # Phony targets (e.g. these are not filenames) -.PHONY: all tests clean check +.PHONY: all clean \ + jtreg javac javadoc javah javap jtreg-tests jtreg-summary check-jtreg \ + jck-compiler jck-compiler-tests jck-compiler-summary \ + jck-runtime jck-runtime-tests jck-runtime-summary check-jck +# No use of suffix rules +.SUFFIXES: +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/4880220/T4880220.error.out Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,9 @@ +T4880220.java:20:27: compiler.warn.static.not.qualified.by.type: kindname.method, T4880220.C +T4880220.java:21:27: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:22:27: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:24:29: compiler.warn.static.not.qualified.by.type: kindname.method, T4880220.C +T4880220.java:25:29: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:26:29: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +- compiler.err.warnings.and.werror +1 error +6 warnings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/4880220/T4880220.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,43 @@ +/* + * @test /nodynamiccopyright/ + * @bug 4880220 + * @summary Add a warning when accessing a static method via an reference + * + * @compile/ref=T4880220.empty.out T4880220.java + * @compile/ref=T4880220.warn.out -XDrawDiagnostics -Xlint:static T4880220.java + * @compile/ref=T4880220.warn.out -XDrawDiagnostics -Xlint:all T4880220.java + * @compile/ref=T4880220.empty.out -XDrawDiagnostics -Xlint:all,-static T4880220.java + * @compile/ref=T4880220.error.out/fail -XDrawDiagnostics -Werror -Xlint:all T4880220.java + */ + +public class T4880220 { + void m1() { + int good_1 = C.m(); + int good_2 = C.f; + int good_3 = C.x; + + C c = new C(); + int bad_inst_1 = c.m(); + int bad_inst_2 = c.f; + int bad_inst_3 = c.x; + + int bad_expr_1 = c().m(); + int bad_expr_2 = c().f; + int bad_expr_3 = c().x; + } + + void m2() { + Class<?> good_1 = C.class; + Class<?> good_2 = C[].class; + } + + C c() { + return new C(); + } + + static class C { + static int m() { return 0; } + static int f; + static final int x = 3; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/4880220/T4880220.warn.out Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,7 @@ +T4880220.java:20:27: compiler.warn.static.not.qualified.by.type: kindname.method, T4880220.C +T4880220.java:21:27: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:22:27: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:24:29: compiler.warn.static.not.qualified.by.type: kindname.method, T4880220.C +T4880220.java:25:29: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:26:29: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +6 warnings
--- a/test/tools/javac/OverrideChecks/6738538/T6738538a.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/OverrideChecks/6738538/T6738538a.java Thu Apr 01 10:07:33 2010 -0700 @@ -41,4 +41,4 @@ public T m(); } class Crash<T extends C<?> & I> {} -} \ No newline at end of file +}
--- a/test/tools/javac/OverrideChecks/6738538/T6738538b.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/OverrideChecks/6738538/T6738538b.java Thu Apr 01 10:07:33 2010 -0700 @@ -44,4 +44,4 @@ } class C2<T extends C1<?> & I2> {} -} \ No newline at end of file +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6881645.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Unchecked method call on a method declared inside anonymous inner causes javac to crash + * @compile -Xlint:unchecked T6881645.java + */ + +class T6881645 { + Object o = new Object() { + <Z> void m (Class<Z> x) {} + void test() { + m((Class)null); + } + }; +} +
--- a/test/tools/javac/ThrowsIntersection_1.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/ThrowsIntersection_1.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,6 +30,8 @@ * @compile ThrowsIntersection_1.java */ +package ThrowsIntersection_1; + class Ex1 extends Exception {} class Ex2 extends Exception {}
--- a/test/tools/javac/ThrowsIntersection_2.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/ThrowsIntersection_2.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,6 +30,8 @@ * @compile ThrowsIntersection_2.java */ +package ThrowsIntersection_2; + class Ex1 extends Exception {} class Ex2 extends Exception {} class Ex3 extends Exception {}
--- a/test/tools/javac/ThrowsIntersection_3.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/ThrowsIntersection_3.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,6 +30,8 @@ * @run compile/fail ThrowsIntersection_3.java */ +package ThrowsIntersection_3; + class Ex1 extends Exception {} class Ex2 extends Exception {}
--- a/test/tools/javac/ThrowsIntersection_4.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/ThrowsIntersection_4.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,6 +30,8 @@ * @run compile/fail ThrowsIntersection_4.java */ +package ThrowsIntersection_4; + // Note: This is the test that actually failed for 4042259. The others are for completeness. class Ex1 extends Exception {}
--- a/test/tools/javac/annotations/neg/Constant.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/annotations/neg/Constant.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile/fail Constant.java */ -package test.tools.javac.annotation.Constant; +package Constant; @T(a = X.x) @interface T {
--- a/test/tools/javac/api/6731573/Erroneous.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/api/6731573/Erroneous.java Thu Apr 01 10:07:33 2010 -0700 @@ -1,4 +1,4 @@ class A { boolean b; boolean b; -} \ No newline at end of file +}
--- a/test/tools/javac/api/6731573/T6731573.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/api/6731573/T6731573.java Thu Apr 01 10:07:33 2010 -0700 @@ -106,4 +106,4 @@ public static void main(String... args) throws Exception { new T6731573().test(); } -} \ No newline at end of file +}
--- a/test/tools/javac/api/TestJavacTaskScanner.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/api/TestJavacTaskScanner.java Thu Apr 01 10:07:33 2010 -0700 @@ -34,7 +34,10 @@ import com.sun.tools.javac.parser.*; // XXX import com.sun.tools.javac.util.*; // XXX import java.io.*; +import java.net.*; import java.nio.*; +import java.nio.charset.Charset; +import java.util.Arrays; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; @@ -43,6 +46,10 @@ import javax.lang.model.util.Types; import javax.tools.*; +import static javax.tools.StandardLocation.CLASS_PATH; +import static javax.tools.StandardLocation.SOURCE_PATH; +import static javax.tools.StandardLocation.CLASS_OUTPUT; + public class TestJavacTaskScanner extends ToolTester { final JavacTaskImpl task; @@ -56,6 +63,7 @@ TestJavacTaskScanner(File file) { final Iterable<? extends JavaFileObject> compilationUnits = fm.getJavaFileObjects(new File[] {file}); + StandardJavaFileManager fm = getLocalFileManager(tool, null, null); task = (JavacTaskImpl)tool.getTask(null, fm, null, null, null, compilationUnits); task.getContext().put(Scanner.Factory.scannerFactoryKey, new MyScanner.Factory(task.getContext(), this)); @@ -83,7 +91,7 @@ System.out.println("#parseTypeElements: " + numParseTypeElements); System.out.println("#allMembers: " + numAllMembers); - check(numTokens, "#Tokens", 891); + check(numTokens, "#Tokens", 1222); check(numParseTypeElements, "#parseTypeElements", 136); check(numAllMembers, "#allMembers", 67); } @@ -117,6 +125,47 @@ numAllMembers++; } } + + /* Similar to ToolTester.getFileManager, except that this version also ensures + * javac classes will be available on the classpath. The javac classes are assumed + * to be on the classpath used to run this test (this is true when using jtreg). + * The classes are found by obtaining the URL for a sample javac class, using + * getClassLoader().getResource(), and then deconstructing the URL to find the + * underlying directory or jar file to place on the classpath. + */ + public StandardJavaFileManager getLocalFileManager(JavaCompiler tool, + DiagnosticListener<JavaFileObject> dl, + Charset encoding) { + File javac_classes; + try { + final String javacMainClass = "com/sun/tools/javac/Main.class"; + URL url = getClass().getClassLoader().getResource(javacMainClass); + if (url == null) + throw new Error("can't locate javac classes"); + URI uri = url.toURI(); + String scheme = uri.getScheme(); + String ssp = uri.getSchemeSpecificPart(); + if (scheme.equals("jar")) { + javac_classes = new File(new URI(ssp.substring(0, ssp.indexOf("!/")))); + } else if (scheme.equals("file")) { + javac_classes = new File(ssp.substring(0, ssp.indexOf(javacMainClass))); + } else + throw new Error("unknown URL: " + url); + } catch (URISyntaxException e) { + throw new Error(e); + } + System.err.println("javac_classes: " + javac_classes); + + StandardJavaFileManager fm = tool.getStandardFileManager(dl, null, encoding); + try { + fm.setLocation(SOURCE_PATH, Arrays.asList(test_src)); + fm.setLocation(CLASS_PATH, Arrays.asList(test_classes, javac_classes)); + fm.setLocation(CLASS_OUTPUT, Arrays.asList(test_classes)); + } catch (IOException e) { + throw new AssertionError(e); + } + return fm; + } } class MyScanner extends Scanner {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/api/TestResolveError.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,101 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6930108 + * @summary IllegalArgumentException in AbstractDiagnosticFormatter for tools/javac/api/TestJavacTaskScanner.java + * @library ./lib + * @build ToolTester + * @run main TestResolveError + */ + +import java.io.*; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import javax.tools.*; + +import com.sun.tools.javac.api.JavacTaskImpl; + +/* + * This is a cut down version of TestJavacTaskScanner, which as originally written + * caused an IllegalArgumentException in AbstractDiagnosticFormatter as a result + * of calling task.parseType with a name whose resolution depended on the setting + * of the bootclasspath. + * This test has the same call, task.parseType("List<String>", clazz), but checks + * that the error is handled in a reasonable way by javac. + */ +public class TestResolveError extends ToolTester { + public static void main(String... args) throws Exception { + new TestResolveError().run(); + } + + void run() throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + File file = new File(test_src, "TestResolveError.java"); + final Iterable<? extends JavaFileObject> compilationUnits = + fm.getJavaFileObjects(new File[] {file}); + task = (JavacTaskImpl)tool.getTask(pw, fm, null, null, null, compilationUnits); + elements = task.getElements(); + types = task.getTypes(); + + Iterable<? extends TypeElement> toplevels; + try { + toplevels = task.enter(task.parse()); + } catch (IOException ex) { + throw new AssertionError(ex); + } + + for (TypeElement clazz : toplevels) { + System.out.format("Testing %s:%n%n", clazz.getSimpleName()); + // this should not cause any exception from the compiler, + // such as IllegalArgumentException + testParseType(clazz); + } + + pw.close(); + + String out = sw.toString(); + System.out.println(out); + + if (out.contains("com.sun.tools.javac.util")) + throw new Exception("Unexpected output from compiler"); + } + + void testParseType(TypeElement clazz) { + DeclaredType type = (DeclaredType)task.parseType("List<String>", clazz); + for (Element member : elements.getAllMembers((TypeElement)type.asElement())) { + TypeMirror mt = types.asMemberOf(type, member); + System.out.format("%s : %s -> %s%n", member.getSimpleName(), member.asType(), mt); + } + } + + JavacTaskImpl task; + Elements elements; + Types types; +}
--- a/test/tools/javac/cast/6548436/T6548436d.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/cast/6548436/T6548436d.java Thu Apr 01 10:07:33 2010 -0700 @@ -37,4 +37,4 @@ static void test(Base<? extends Double> je) { Object o = (Base<Integer>)je; } -} \ No newline at end of file +}
--- a/test/tools/javac/cast/6558559/T6558559a.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/cast/6558559/T6558559a.java Thu Apr 01 10:07:33 2010 -0700 @@ -37,4 +37,4 @@ A<?> x = null; B<?> y = (B<?>)x; -} \ No newline at end of file +}
--- a/test/tools/javac/cast/6558559/T6558559b.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/cast/6558559/T6558559b.java Thu Apr 01 10:07:33 2010 -0700 @@ -40,4 +40,4 @@ Object o = unboundList; Throwable t3 = (Throwable) o; } -} \ No newline at end of file +}
--- a/test/tools/javac/cast/6586091/T6586091.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/cast/6586091/T6586091.java Thu Apr 01 10:07:33 2010 -0700 @@ -35,4 +35,4 @@ A<A<?>> t = null; B c = (B)t; -} \ No newline at end of file +}
--- a/test/tools/javac/enum/T6724345.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/enum/T6724345.java Thu Apr 01 10:07:33 2010 -0700 @@ -48,4 +48,4 @@ enum E implements I { V {public void i() {}}; } -} \ No newline at end of file +}
--- a/test/tools/javac/generics/Casting.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/Casting.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile Casting.java */ -package test.tools.javac.generics.Casting; +package Casting; class Test {}
--- a/test/tools/javac/generics/Casting3.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/Casting3.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile Casting3.java */ -package test.tools.javac.generics.Casting3; +package Casting3; class A<T extends A<T>> { <U extends A<U>> void f() {
--- a/test/tools/javac/generics/Casting4.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/Casting4.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile -Werror -Xlint:unchecked Casting4.java */ -package test.tools.javac.generics.Casting4; +package Casting4; class Casting4 { <M> Integer f(Comparable<M> c) {
--- a/test/tools/javac/generics/InnerInterface1.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/InnerInterface1.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile InnerInterface1.java */ -package test.tools.javac.generics.InnerInterface1; +package InnerInterface1; interface Iterator<E> { }
--- a/test/tools/javac/generics/InnerInterface2.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/InnerInterface2.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile InnerInterface2.java */ -package test.tools.javac.generics.InnerInterface2; +package InnerInterface2; class Builder<Community> {
--- a/test/tools/javac/generics/Multibound1.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/Multibound1.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile/fail Multibound1.java */ -package test.tools.javac.generics.Multibound1; +package Multibound1; interface A {} interface B {}
--- a/test/tools/javac/generics/MultipleInheritance.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/MultipleInheritance.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile MultipleInheritance.java */ -package test.tools.javac.generics.MultipleInheritance; +package MultipleInheritance; import java.util.*;
--- a/test/tools/javac/generics/NameOrder.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/NameOrder.java Thu Apr 01 10:07:33 2010 -0700 @@ -27,22 +27,22 @@ * @summary generics: type inference failure due to a bug in ClassSymbol.isLess * @author gafter * - * @compile NameOrder.java + * @compile NameOrder.java */ -package test.tools.javac.generics.NameOrder; +package NameOrder; interface a {} interface b {} interface c {} -class A implements a, b {} -class B implements c, a {} +class AB implements a, b {} +class CA implements c, a {} // this is how to trigger a symptom: -abstract class C { +abstract class X { <T> T f(T t1, T t2) { return null; } void g() { - a x = f( new A(), new B() ); + a x = f( new AB(), new CA() ); } }
--- a/test/tools/javac/generics/PermuteBound.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/PermuteBound.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile PermuteBound.java */ -package test.tools.javac.generics.PermuteBound; +package PermuteBound; class C<X, Y> {}
--- a/test/tools/javac/generics/PrimitiveVariant.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/PrimitiveVariant.java Thu Apr 01 10:07:33 2010 -0700 @@ -30,7 +30,7 @@ * @compile/fail PrimitiveVariant.java */ -package test.tools.javac.generics.PrimitiveVariant; +package PrimitiveVariant; interface I { double m();
--- a/test/tools/javac/generics/T6557954.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/T6557954.java Thu Apr 01 10:07:33 2010 -0700 @@ -33,4 +33,4 @@ class T6557954<T> { class Foo<U extends T> {} T6557954<Number>.Foo<Integer> f; -} \ No newline at end of file +}
--- a/test/tools/javac/generics/T6751514.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/T6751514.java Thu Apr 01 10:07:33 2010 -0700 @@ -79,4 +79,4 @@ " - found: " + found + ")"); } } -} \ No newline at end of file +}
--- a/test/tools/javac/generics/T6869075.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/T6869075.java Thu Apr 01 10:07:33 2010 -0700 @@ -64,4 +64,4 @@ " - found: " + found + ")"); } } -} \ No newline at end of file +}
--- a/test/tools/javac/generics/inference/6569789/T6569789.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/inference/6569789/T6569789.java Thu Apr 01 10:07:33 2010 -0700 @@ -41,4 +41,4 @@ } static <W extends C & I & I1 & I2, T extends W> void testMethod(T t) {} -} \ No newline at end of file +}
--- a/test/tools/javac/generics/inference/6650759/T6650759a.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/inference/6650759/T6650759a.java Thu Apr 01 10:07:33 2010 -0700 @@ -42,4 +42,4 @@ Integer test = getGenericValue(new IntegerInterface()); testSet(getGenericValue(new IntegerInterface())); } -} \ No newline at end of file +}
--- a/test/tools/javac/generics/wildcards/T6732484.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/generics/wildcards/T6732484.java Thu Apr 01 10:07:33 2010 -0700 @@ -34,4 +34,4 @@ class B extends A<B> {} A<? super B> f; -} \ No newline at end of file +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/6511613/DummyProcessor.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import java.util.Set; + +@SupportedAnnotationTypes("*") +public class DummyProcessor extends AbstractProcessor { + public boolean process(Set<? extends TypeElement> annotations, + RoundEnvironment roundEnv) { + return true; + } + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/6511613/clss41701.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6511613 + * @summary javac unexpectedly doesn't fail in some cases if an annotation processor specified + * + * @build DummyProcessor + * @compile/fail clss41701.java + * @compile/fail -processor DummyProcessor clss41701.java + */ + +import java.io.PrintStream; + +interface clss41701i { + void run(); +} + +class clss41701a<A extends clss41701i, + B extends clss41701i, + C extends A&B> { +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/model/element/TestAnonClassNames.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,186 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6449781 + * @summary Test that reported names of anonymous classes are non-null. + * @author Joseph D. Darcy + * @build TestAnonSourceNames + * @compile/fail -processor TestAnonSourceNames TestAnonClassNames.java + * @build TestAnonClassNames + * @run main TestAnonClassNames + */ + +/* + * This test operates in phases to test retrieving the qualified name + * of anonymous classes from type elements modeling the anonymous + * class. The type elements are generated using both source files and + * class files as the basis of constructing the elements. + * + * Source files will be tested by the @compile line which runs + * TestAnonSourceNames as an annotation processor over this file. + * This compile line is expected to fail until 6930507 is fixed. Once + * bug 6930507 is fixed, the "@compile/fail -processor ..." and + * following "@build..." steps can be replaced with a single "@compile + * -processor ..." directive. + * + * Class files are tested by the @run command on this type. This + * class gets the names of classes with different nesting kinds, + * including anonymous classes, and then invokes the compiler with an + * annotation processor having the class files names as inputs. The + * compiler is invoked via the javax.tools mechanism. + */ + +import java.lang.annotation.*; +import javax.lang.model.element.*; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import javax.lang.model.util.*; +import javax.tools.*; +import java.util.*; + +import static java.lang.annotation.RetentionPolicy.*; +import static javax.lang.model.element.NestingKind.*; +import static javax.lang.model.util.ElementFilter.*; +import static javax.tools.Diagnostic.Kind.*; +import static javax.tools.StandardLocation.*; + +@Nesting(TOP_LEVEL) +public class TestAnonClassNames { + @Nesting(MEMBER) + static class MemberClass1{} + + @Nesting(MEMBER) + class MemberClass2{} + + @Nesting(MEMBER) + class Win$$AtVegas { } // Class with funny name. + + public static void main(String... argv) { + @Nesting(LOCAL) + class LocalClass{}; + + Object o = new @Nesting(ANONYMOUS) Object() { // An anonymous annotated class + public String toString() { + return "I have no name!"; + } + }; + + Class<?>[] classes = { + MemberClass1.class, + MemberClass2.class, + LocalClass.class, + Win$$AtVegas.class, + o.getClass(), + TestAnonClassNames.class, + }; + + for(Class<?> clazz : classes) { + String name = clazz.getName(); + System.out.format("%s is %s%n", + clazz.getName(), + clazz.getAnnotation(Nesting.class).value()); + testClassName(name); + } + } + + /** + * Perform annotation processing on the class file name and verify + * the existence of different flavors of class names when the + * input classes are modeled as elements. + */ + static void testClassName(String className) { + JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); + List<String> classNames = new ArrayList<>(); + classNames.add(className); + + List<String> options = new ArrayList<>(); + options.add("-proc:only"); + options.add("-classpath"); + options.add(System.getProperty("test.classes")); + + JavaCompiler.CompilationTask compileTask = + javaCompiler.getTask(null, // Output + null, // File manager + null, // Diagnostics + options, + classNames, + null); // Sources + List<Processor> processors = new ArrayList<>(); + processors.add(new ClassNameProber()); + compileTask.setProcessors(processors); + Boolean goodResult = compileTask.call(); + if (!goodResult) { + throw new RuntimeException("Errors found during compile."); + } + } +} + +@Retention(RUNTIME) +@interface Nesting { + NestingKind value(); +} + +/** + * Probe at the various kinds of names of a type element. + */ +@SupportedAnnotationTypes("*") +class ClassNameProber extends AbstractProcessor { + public ClassNameProber(){super();} + + private boolean classesFound=false; + + public boolean process(Set<? extends TypeElement> annotations, + RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + for(TypeElement typeElt : typesIn(roundEnv.getRootElements())) { + classesFound = true; + + // Verify different names are non-null; an NPE will + // result in failed compile status being reported. + NestingKind nestingKind = typeElt.getNestingKind(); + System.out.printf("\tSimple name: ''%s''\tQualified Name: ''%s''\tKind ''%s''\tNesting ''%s''%n", + typeElt.getSimpleName().toString(), + typeElt.getQualifiedName().toString(), + typeElt.getKind().toString(), + nestingKind.toString()); + + if (typeElt.getAnnotation(Nesting.class).value() != nestingKind) { + throw new RuntimeException("Mismatch of expected and reported nesting kind."); + } + } + + } + + if (!classesFound) { + throw new RuntimeException("Error: no classes processed."); + } + return true; + } + + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/model/element/TestAnonSourceNames.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import java.util.*; +import com.sun.source.tree.*; +import com.sun.source.util.*; +import static javax.tools.Diagnostic.Kind.*; + +/** + * Using the tree API, retrieve element representations of anonymous + * classes and verify their names are as specified. + */ +@SupportedAnnotationTypes("*") +public class TestAnonSourceNames extends AbstractProcessor { + + public boolean process(Set<? extends TypeElement> annotations, + RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + Trees trees = Trees.instance(processingEnv); + + for(Element rootElement : roundEnv.getRootElements()) { + TreePath treePath = trees.getPath(rootElement); + + (new ClassTreeScanner(trees)). + scan(trees.getTree(rootElement), + treePath.getCompilationUnit()); + } + } + return true; + } + + class ClassTreeScanner extends TreeScanner<Void, CompilationUnitTree> { + private Trees trees; + + public ClassTreeScanner(Trees trees) { + super(); + this.trees = trees; + } + @Override + public Void visitClass(ClassTree node, CompilationUnitTree cu) { + Element element = trees.getElement(trees.getPath(cu, node)); + if (element == null) { + processingEnv.getMessager().printMessage(ERROR, + "No element retreived for node named ''" + + node.getSimpleName() + "''."); + } else { + + System.out.println("\nVisiting class ``" + element.getSimpleName() + + "'' of kind " + element.getKind()); + if (element instanceof TypeElement) { + TypeElement typeElement = (TypeElement) element; + String s = typeElement.getQualifiedName().toString(); + System.out.println("\tqualified name:" + s); + } else { + throw new RuntimeException("TypeElement not gotten from ClassTree."); + } + } + return super.visitClass(node, cu); + } + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +}
--- a/test/tools/javac/processing/model/util/elements/Foo.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/processing/model/util/elements/Foo.java Thu Apr 01 10:07:33 2010 -0700 @@ -26,4 +26,4 @@ * Dummy type to compile. */ public class Foo { -} \ No newline at end of file +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/model/util/elements/VacuousEnum.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6937417 + * @summary Test -Xprint on enum type with no constants + * @author Joseph D. Darcy + * @compile -Xprint VacuousEnum.java + */ +public enum VacuousEnum { + // But alas, no enum constants! +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/tree/TestAnnotatedAnonClass.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +/* + * This file is not a regular test, but is processed by ./TreePosTest.java, + * which verifies the position info in the javac tree. + * To run the test standalone, compile TreePosTest, then run TreePosTest + * on this file. + * @bug 6931927 + * @summary position issues with synthesized anonymous class + */ +class TestAnnotatedAnonClass { + void m() { + Object o = new @Deprecated Object() { }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/tree/TreePosTest.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,762 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Highlighter; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCNewClass; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; + +import static com.sun.tools.javac.util.Position.NOPOS; + +/** + * Utility and test program to check validity of tree positions for tree nodes. + * The program can be run standalone, or as a jtreg test. In standalone mode, + * errors can be displayed in a gui viewer. For info on command line args, + * run program with no args. + * + * <p> + * jtreg: Note that by using the -r switch in the test description below, this test + * will process all java files in the langtools/test directory, thus implicitly + * covering any new language features that may be tested in this test suite. + */ + +/* + * @test + * @bug 6919889 + * @summary assorted position errors in compiler syntax trees + * @run main TreePosTest -q -r -ef ./tools/javac/typeAnnotations -ef ./tools/javap/typeAnnotations -et ANNOTATED_TYPE . + */ +public class TreePosTest { + /** + * Main entry point. + * If test.src is set, program runs in jtreg mode, and will throw an Error + * if any errors arise, otherwise System.exit will be used, unless the gui + * viewer is being used. In jtreg mode, the default base directory for file + * args is the value of ${test.src}. In jtreg mode, the -r option can be + * given to change the default base directory to the root test directory. + */ + public static void main(String... args) { + String testSrc = System.getProperty("test.src"); + File baseDir = (testSrc == null) ? null : new File(testSrc); + boolean ok = new TreePosTest().run(baseDir, args); + if (!ok) { + if (testSrc != null) // jtreg mode + throw new Error("failed"); + else + System.exit(1); + } + } + + /** + * Run the program. A base directory can be provided for file arguments. + * In jtreg mode, the -r option can be given to change the default base + * directory to the test root directory. For other options, see usage(). + * @param baseDir base directory for any file arguments. + * @param args command line args + * @return true if successful or in gui mode + */ + boolean run(File baseDir, String... args) { + if (args.length == 0) { + usage(System.out); + return true; + } + + List<File> files = new ArrayList<File>(); + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-encoding") && i + 1 < args.length) + encoding = args[++i]; + else if (arg.equals("-gui")) + gui = true; + else if (arg.equals("-q")) + quiet = true; + else if (arg.equals("-v")) + verbose = true; + else if (arg.equals("-t") && i + 1 < args.length) + tags.add(args[++i]); + else if (arg.equals("-ef") && i + 1 < args.length) + excludeFiles.add(new File(baseDir, args[++i])); + else if (arg.equals("-et") && i + 1 < args.length) + excludeTags.add(args[++i]); + else if (arg.equals("-r")) { + if (excludeFiles.size() > 0) + throw new Error("-r must be used before -ef"); + File d = baseDir; + while (!new File(d, "TEST.ROOT").exists()) { + d = d.getParentFile(); + if (d == null) + throw new Error("cannot find TEST.ROOT"); + } + baseDir = d; + } + else if (arg.startsWith("-")) + throw new Error("unknown option: " + arg); + else { + while (i < args.length) + files.add(new File(baseDir, args[i++])); + } + } + + for (File file: files) { + if (file.exists()) + test(file); + else + error("File not found: " + file); + } + + if (fileCount != 1) + System.err.println(fileCount + " files read"); + if (errors > 0) + System.err.println(errors + " errors"); + + return (gui || errors == 0); + } + + /** + * Print command line help. + * @param out output stream + */ + void usage(PrintStream out) { + out.println("Usage:"); + out.println(" java TreePosTest options... files..."); + out.println(""); + out.println("where options include:"); + out.println("-gui Display returns in a GUI viewer"); + out.println("-q Quiet: don't report on inapplicable files"); + out.println("-v Verbose: report on files as they are being read"); + out.println("-t tag Limit checks to tree nodes with this tag"); + out.println(" Can be repeated if desired"); + out.println("-ef file Exclude file or directory"); + out.println("-et tag Exclude tree nodes with given tag name"); + out.println(""); + out.println("files may be directories or files"); + out.println("directories will be scanned recursively"); + out.println("non java files, or java files which cannot be parsed, will be ignored"); + out.println(""); + } + + /** + * Test a file. If the file is a directory, it will be recursively scanned + * for java files. + * @param file the file or directory to test + */ + void test(File file) { + if (excludeFiles.contains(file)) { + if (!quiet) + error("File " + file + " excluded"); + return; + } + + if (file.isDirectory()) { + for (File f: file.listFiles()) { + test(f); + } + return; + } + + if (file.isFile() && file.getName().endsWith(".java")) { + try { + if (verbose) + System.err.println(file); + fileCount++; + PosTester p = new PosTester(); + p.test(read(file)); + } catch (ParseException e) { + if (!quiet) { + error("Error parsing " + file + "\n" + e.getMessage()); + } + } catch (IOException e) { + error("Error reading " + file + ": " + e); + } + return; + } + + if (!quiet) + error("File " + file + " ignored"); + } + + /** + * Read a file. + * @param file the file to be read + * @return the tree for the content of the file + * @throws IOException if any IO errors occur + * @throws TreePosTest.ParseException if any errors occur while parsing the file + */ + JCCompilationUnit read(File file) throws IOException, ParseException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Reporter r = new Reporter(pw); + JavacTool tool = JavacTool.create(); + Charset cs = (encoding == null ? null : Charset.forName(encoding)); + StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file); + JavacTask task = tool.getTask(pw, fm, r, Collections.<String>emptyList(), null, files); + Iterable<? extends CompilationUnitTree> trees = task.parse(); + pw.flush(); + if (r.errors > 0) + throw new ParseException(sw.toString()); + Iterator<? extends CompilationUnitTree> iter = trees.iterator(); + if (!iter.hasNext()) + throw new Error("no trees found"); + JCCompilationUnit t = (JCCompilationUnit) iter.next(); + if (iter.hasNext()) + throw new Error("too many trees found"); + return t; + } + + /** + * Report an error. When the program is complete, the program will either + * exit or throw an Error if any errors have been reported. + * @param msg the error message + */ + void error(String msg) { + System.err.println(msg); + errors++; + } + + /** Number of files that have been analyzed. */ + int fileCount; + /** Number of errors reported. */ + int errors; + /** Flag: don't report irrelevant files. */ + boolean quiet; + /** Flag: report files as they are processed. */ + boolean verbose; + /** Flag: show errors in GUI viewer. */ + boolean gui; + /** Option: encoding for test files. */ + String encoding; + /** The GUI viewer for errors. */ + Viewer viewer; + /** The set of tags for tree nodes to be analyzed; if empty, all tree nodes + * are analyzed. */ + Set<String> tags = new HashSet<String>(); + /** Set of files and directories to be excluded from analysis. */ + Set<File> excludeFiles = new HashSet<File>(); + /** Set of tag names to be excluded from analysis. */ + Set<String> excludeTags = new HashSet<String>(); + /** Table of printable names for tree tag values. */ + TagNames tagNames = new TagNames(); + + /** + * Main class for testing assertions concerning tree positions for tree nodes. + */ + private class PosTester extends TreeScanner { + void test(JCCompilationUnit tree) { + sourcefile = tree.sourcefile; + endPosTable = tree.endPositions; + encl = new Info(); + tree.accept(this); + } + + @Override + public void scan(JCTree tree) { + if (tree == null) + return; + + Info self = new Info(tree, endPosTable); + if (check(encl, self)) { + // Modifiers nodes are present throughout the tree even where + // there is no corresponding source text. + // Redundant semicolons in a class definition can cause empty + // initializer blocks with no positions. + if ((self.tag == JCTree.MODIFIERS || self.tag == JCTree.BLOCK) + && self.pos == NOPOS) { + // If pos is NOPOS, so should be the start and end positions + check("start == NOPOS", encl, self, self.start == NOPOS); + check("end == NOPOS", encl, self, self.end == NOPOS); + } else { + // For this node, start , pos, and endpos should be all defined + check("start != NOPOS", encl, self, self.start != NOPOS); + check("pos != NOPOS", encl, self, self.pos != NOPOS); + check("end != NOPOS", encl, self, self.end != NOPOS); + // The following should normally be ordered + // encl.start <= start <= pos <= end <= encl.end + // In addition, the position of the enclosing node should be + // within this node. + // The primary exceptions are for array type nodes, because of the + // need to support legacy syntax: + // e.g. int a[]; int[] b[]; int f()[] { return null; } + // and because of inconsistent nesting of left and right of + // array declarations: + // e.g. int[][] a = new int[2][]; + check("encl.start <= start", encl, self, encl.start <= self.start); + check("start <= pos", encl, self, self.start <= self.pos); + if (!(self.tag == JCTree.TYPEARRAY + && (encl.tag == JCTree.VARDEF || encl.tag == JCTree.TYPEARRAY))) { + check("encl.pos <= start || end <= encl.pos", + encl, self, encl.pos <= self.start || self.end <= encl.pos); + } + check("pos <= end", encl, self, self.pos <= self.end); + if (!(self.tag == JCTree.TYPEARRAY && encl.tag == JCTree.TYPEARRAY)) { + check("end <= encl.end", encl, self, self.end <= encl.end); + } + } + } + + Info prevEncl = encl; + encl = self; + tree.accept(this); + encl = prevEncl; + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + // enum member declarations are desugared in the parser and have + // ill-defined semantics for tree positions, so for now, we + // skip the synthesized bits and just check parts which came from + // the original source text + if ((tree.mods.flags & Flags.ENUM) != 0) { + scan(tree.mods); + if (tree.init != null) { + if (tree.init.getTag() == JCTree.NEWCLASS) { + JCNewClass init = (JCNewClass) tree.init; + if (init.args != null && init.args.nonEmpty()) { + scan(init.args); + } + if (init.def != null && init.def.defs != null) { + scan(init.def.defs); + } + } + } + } else + super.visitVarDef(tree); + } + + boolean check(Info encl, Info self) { + if (excludeTags.size() > 0) { + if (encl != null && excludeTags.contains(tagNames.get(encl.tag)) + || excludeTags.contains(tagNames.get(self.tag))) + return false; + } + return tags.size() == 0 || tags.contains(tagNames.get(self.tag)); + } + + void check(String label, Info encl, Info self, boolean ok) { + if (!ok) { + if (gui) { + if (viewer == null) + viewer = new Viewer(); + viewer.addEntry(sourcefile, label, encl, self); + } + + String s = self.tree.toString(); + String msg = sourcefile.getName() + ": " + label + ": " + + "encl:" + encl + " this:" + self + "\n" + + s.substring(0, Math.min(80, s.length())).replaceAll("[\r\n]+", " "); + error(msg); + } + } + + JavaFileObject sourcefile; + Map<JCTree, Integer> endPosTable; + Info encl; + + } + + /** + * Utility class providing easy access to position and other info for a tree node. + */ + private class Info { + Info() { + tree = null; + tag = JCTree.ERRONEOUS; + start = 0; + pos = 0; + end = Integer.MAX_VALUE; + } + + Info(JCTree tree, Map<JCTree, Integer> endPosTable) { + this.tree = tree; + tag = tree.getTag(); + start = TreeInfo.getStartPos(tree); + pos = tree.pos; + end = TreeInfo.getEndPos(tree, endPosTable); + } + + @Override + public String toString() { + return tagNames.get(tree.getTag()) + "[start:" + start + ",pos:" + pos + ",end:" + end + "]"; + } + + final JCTree tree; + final int tag; + final int start; + final int pos; + final int end; + } + + /** + * Names for tree tags. + * javac does not provide an API to convert tag values to strings, so this class uses + * reflection to determine names of public static final int values in JCTree. + */ + private static class TagNames { + String get(int tag) { + if (map == null) { + map = new HashMap<Integer, String>(); + Class c = JCTree.class; + for (Field f : c.getDeclaredFields()) { + if (f.getType().equals(int.class)) { + int mods = f.getModifiers(); + if (Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) { + try { + map.put(f.getInt(null), f.getName()); + } catch (IllegalAccessException e) { + } + } + } + } + } + String name = map.get(tag); + return (name == null) ? "??" : name; + } + + private Map<Integer, String> map; + } + + /** + * Thrown when errors are found parsing a java file. + */ + private static class ParseException extends Exception { + ParseException(String msg) { + super(msg); + } + } + + /** + * DiagnosticListener to report diagnostics and count any errors that occur. + */ + private static class Reporter implements DiagnosticListener<JavaFileObject> { + Reporter(PrintWriter out) { + this.out = out; + } + + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + out.println(diagnostic); + switch (diagnostic.getKind()) { + case ERROR: + errors++; + } + } + int errors; + PrintWriter out; + } + + /** + * GUI viewer for issues found by TreePosTester. The viewer provides a drop + * down list for selecting error conditions, a header area providing details + * about an error, and a text area with the ranges of text highlighted as + * appropriate. + */ + private class Viewer extends JFrame { + /** + * Create a viewer. + */ + Viewer() { + initGUI(); + } + + /** + * Add another entry to the list of errors. + * @param file The file containing the error + * @param check The condition that was being tested, and which failed + * @param encl the enclosing tree node + * @param self the tree node containing the error + */ + void addEntry(JavaFileObject file, String check, Info encl, Info self) { + Entry e = new Entry(file, check, encl, self); + DefaultComboBoxModel m = (DefaultComboBoxModel) entries.getModel(); + m.addElement(e); + if (m.getSize() == 1) + entries.setSelectedItem(e); + } + + /** + * Initialize the GUI window. + */ + private void initGUI() { + JPanel head = new JPanel(new GridBagLayout()); + GridBagConstraints lc = new GridBagConstraints(); + GridBagConstraints fc = new GridBagConstraints(); + fc.anchor = GridBagConstraints.WEST; + fc.fill = GridBagConstraints.HORIZONTAL; + fc.gridwidth = GridBagConstraints.REMAINDER; + + entries = new JComboBox(); + entries.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + showEntry((Entry) entries.getSelectedItem()); + } + }); + fc.insets.bottom = 10; + head.add(entries, fc); + fc.insets.bottom = 0; + head.add(new JLabel("check:"), lc); + head.add(checkField = createTextField(80), fc); + fc.fill = GridBagConstraints.NONE; + head.add(setBackground(new JLabel("encl:"), enclColor), lc); + head.add(enclPanel = new InfoPanel(), fc); + head.add(setBackground(new JLabel("self:"), selfColor), lc); + head.add(selfPanel = new InfoPanel(), fc); + add(head, BorderLayout.NORTH); + + body = new JTextArea(); + body.setFont(Font.decode(Font.MONOSPACED)); + body.addCaretListener(new CaretListener() { + public void caretUpdate(CaretEvent e) { + int dot = e.getDot(); + int mark = e.getMark(); + if (dot == mark) + statusText.setText("dot: " + dot); + else + statusText.setText("dot: " + dot + ", mark:" + mark); + } + }); + JScrollPane p = new JScrollPane(body, + JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + p.setPreferredSize(new Dimension(640, 480)); + add(p, BorderLayout.CENTER); + + statusText = createTextField(80); + add(statusText, BorderLayout.SOUTH); + + pack(); + setLocationRelativeTo(null); // centered on screen + setVisible(true); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + + /** Show an entry that has been selected. */ + private void showEntry(Entry e) { + try { + // update simple fields + setTitle(e.file.getName()); + checkField.setText(e.check); + enclPanel.setInfo(e.encl); + selfPanel.setInfo(e.self); + // show file text with highlights + body.setText(e.file.getCharContent(true).toString()); + Highlighter highlighter = body.getHighlighter(); + highlighter.removeAllHighlights(); + addHighlight(highlighter, e.encl, enclColor); + addHighlight(highlighter, e.self, selfColor); + scroll(body, getMinPos(enclPanel.info, selfPanel.info)); + } catch (IOException ex) { + body.setText("Cannot read " + e.file.getName() + ": " + e); + } + } + + /** Create a test field. */ + private JTextField createTextField(int width) { + JTextField f = new JTextField(width); + f.setEditable(false); + f.setBorder(null); + return f; + } + + /** Add a highlighted region based on the positions in an Info object. */ + private void addHighlight(Highlighter h, Info info, Color c) { + int start = info.start; + int end = info.end; + if (start == -1 && end == -1) + return; + if (start == -1) + start = end; + if (end == -1) + end = start; + try { + h.addHighlight(info.start, info.end, + new DefaultHighlighter.DefaultHighlightPainter(c)); + if (info.pos != -1) { + Color c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), (int)(.4f * 255)); // 40% + h.addHighlight(info.pos, info.pos + 1, + new DefaultHighlighter.DefaultHighlightPainter(c2)); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** Get the minimum valid position in a set of info objects. */ + private int getMinPos(Info... values) { + int i = Integer.MAX_VALUE; + for (Info info: values) { + if (info.start >= 0) i = Math.min(i, info.start); + if (info.pos >= 0) i = Math.min(i, info.pos); + if (info.end >= 0) i = Math.min(i, info.end); + } + return (i == Integer.MAX_VALUE) ? 0 : i; + } + + /** Set the background on a component. */ + private JComponent setBackground(JComponent comp, Color c) { + comp.setOpaque(true); + comp.setBackground(c); + return comp; + } + + /** Scroll a text area to display a given position near the middle of the visible area. */ + private void scroll(final JTextArea t, final int pos) { + // Using invokeLater appears to give text a chance to sort itself out + // before the scroll happens; otherwise scrollRectToVisible doesn't work. + // Maybe there's a better way to sync with the text... + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + Rectangle r = t.modelToView(pos); + JScrollPane p = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, t); + r.y = Math.max(0, r.y - p.getHeight() * 2 / 5); + r.height += p.getHeight() * 4 / 5; + t.scrollRectToVisible(r); + } catch (BadLocationException ignore) { + } + } + }); + } + + private JComboBox entries; + private JTextField checkField; + private InfoPanel enclPanel; + private InfoPanel selfPanel; + private JTextArea body; + private JTextField statusText; + + private Color selfColor = new Color(0.f, 1.f, 0.f, 0.2f); // 20% green + private Color enclColor = new Color(1.f, 0.f, 0.f, 0.2f); // 20% red + + /** Panel to display an Info object. */ + private class InfoPanel extends JPanel { + InfoPanel() { + add(tagName = createTextField(20)); + add(new JLabel("start:")); + add(addListener(start = createTextField(6))); + add(new JLabel("pos:")); + add(addListener(pos = createTextField(6))); + add(new JLabel("end:")); + add(addListener(end = createTextField(6))); + } + + void setInfo(Info info) { + this.info = info; + tagName.setText(tagNames.get(info.tag)); + start.setText(String.valueOf(info.start)); + pos.setText(String.valueOf(info.pos)); + end.setText(String.valueOf(info.end)); + } + + JTextField addListener(final JTextField f) { + f.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + body.setCaretPosition(Integer.valueOf(f.getText())); + body.getCaret().setVisible(true); + } + }); + return f; + } + + Info info; + JTextField tagName; + JTextField start; + JTextField pos; + JTextField end; + } + + /** Object to record information about an error to be displayed. */ + private class Entry { + Entry(JavaFileObject file, String check, Info encl, Info self) { + this.file = file; + this.check = check; + this.encl = encl; + this.self= self; + } + + @Override + public String toString() { + return file.getName() + " " + check + " " + getMinPos(encl, self); + } + + final JavaFileObject file; + final String check; + final Info encl; + final Info self; + } + } +} +
--- a/test/tools/javac/treepostests/TreePosTest.java Mon Mar 01 17:53:56 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,762 +0,0 @@ -/* - * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.event.CaretEvent; -import javax.swing.event.CaretListener; -import javax.swing.text.BadLocationException; -import javax.swing.text.DefaultHighlighter; -import javax.swing.text.Highlighter; -import javax.tools.Diagnostic; -import javax.tools.DiagnosticListener; -import javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; - -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.util.JavacTask; -import com.sun.tools.javac.api.JavacTool; -import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; -import com.sun.tools.javac.tree.JCTree.JCNewClass; -import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeInfo; -import com.sun.tools.javac.tree.TreeScanner; - -import static com.sun.tools.javac.util.Position.NOPOS; - -/** - * Utility and test program to check validity of tree positions for tree nodes. - * The program can be run standalone, or as a jtreg test. In standalone mode, - * errors can be displayed in a gui viewer. For info on command line args, - * run program with no args. - * - * <p> - * jtreg: Note that by using the -r switch in the test description below, this test - * will process all java files in the langtools/test directory, thus implicitly - * covering any new language features that may be tested in this test suite. - */ - -/* - * @test - * @bug 6919889 - * @summary assorted position errors in compiler syntax trees - * @run main TreePosTest -q -r -ef ./tools/javac/typeAnnotations -ef ./tools/javap/typeAnnotations -et ANNOTATED_TYPE . - */ -public class TreePosTest { - /** - * Main entry point. - * If test.src is set, program runs in jtreg mode, and will throw an Error - * if any errors arise, otherwise System.exit will be used, unless the gui - * viewer is being used. In jtreg mode, the default base directory for file - * args is the value of ${test.src}. In jtreg mode, the -r option can be - * given to change the default base directory to the root test directory. - */ - public static void main(String... args) { - String testSrc = System.getProperty("test.src"); - File baseDir = (testSrc == null) ? null : new File(testSrc); - boolean ok = new TreePosTest().run(baseDir, args); - if (!ok) { - if (testSrc != null) // jtreg mode - throw new Error("failed"); - else - System.exit(1); - } - } - - /** - * Run the program. A base directory can be provided for file arguments. - * In jtreg mode, the -r option can be given to change the default base - * directory to the test root directory. For other options, see usage(). - * @param baseDir base directory for any file arguments. - * @param args command line args - * @return true if successful or in gui mode - */ - boolean run(File baseDir, String... args) { - if (args.length == 0) { - usage(System.out); - return true; - } - - List<File> files = new ArrayList<File>(); - for (int i = 0; i < args.length; i++) { - String arg = args[i]; - if (arg.equals("-encoding") && i + 1 < args.length) - encoding = args[++i]; - else if (arg.equals("-gui")) - gui = true; - else if (arg.equals("-q")) - quiet = true; - else if (arg.equals("-v")) - verbose = true; - else if (arg.equals("-t") && i + 1 < args.length) - tags.add(args[++i]); - else if (arg.equals("-ef") && i + 1 < args.length) - excludeFiles.add(new File(baseDir, args[++i])); - else if (arg.equals("-et") && i + 1 < args.length) - excludeTags.add(args[++i]); - else if (arg.equals("-r")) { - if (excludeFiles.size() > 0) - throw new Error("-r must be used before -ef"); - File d = baseDir; - while (!new File(d, "TEST.ROOT").exists()) { - d = d.getParentFile(); - if (d == null) - throw new Error("cannot find TEST.ROOT"); - } - baseDir = d; - } - else if (arg.startsWith("-")) - throw new Error("unknown option: " + arg); - else { - while (i < args.length) - files.add(new File(baseDir, args[i++])); - } - } - - for (File file: files) { - if (file.exists()) - test(file); - else - error("File not found: " + file); - } - - if (fileCount != 1) - System.err.println(fileCount + " files read"); - if (errors > 0) - System.err.println(errors + " errors"); - - return (gui || errors == 0); - } - - /** - * Print command line help. - * @param out output stream - */ - void usage(PrintStream out) { - out.println("Usage:"); - out.println(" java TreePosTest options... files..."); - out.println(""); - out.println("where options include:"); - out.println("-gui Display returns in a GUI viewer"); - out.println("-q Quiet: don't report on inapplicable files"); - out.println("-v Verbose: report on files as they are being read"); - out.println("-t tag Limit checks to tree nodes with this tag"); - out.println(" Can be repeated if desired"); - out.println("-ef file Exclude file or directory"); - out.println("-et tag Exclude tree nodes with given tag name"); - out.println(""); - out.println("files may be directories or files"); - out.println("directories will be scanned recursively"); - out.println("non java files, or java files which cannot be parsed, will be ignored"); - out.println(""); - } - - /** - * Test a file. If the file is a directory, it will be recursively scanned - * for java files. - * @param file the file or directory to test - */ - void test(File file) { - if (excludeFiles.contains(file)) { - if (!quiet) - error("File " + file + " excluded"); - return; - } - - if (file.isDirectory()) { - for (File f: file.listFiles()) { - test(f); - } - return; - } - - if (file.isFile() && file.getName().endsWith(".java")) { - try { - if (verbose) - System.err.println(file); - fileCount++; - PosTester p = new PosTester(); - p.test(read(file)); - } catch (ParseException e) { - if (!quiet) { - error("Error parsing " + file + "\n" + e.getMessage()); - } - } catch (IOException e) { - error("Error reading " + file + ": " + e); - } - return; - } - - if (!quiet) - error("File " + file + " ignored"); - } - - /** - * Read a file. - * @param file the file to be read - * @return the tree for the content of the file - * @throws IOException if any IO errors occur - * @throws TreePosTest.ParseException if any errors occur while parsing the file - */ - JCCompilationUnit read(File file) throws IOException, ParseException { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - Reporter r = new Reporter(pw); - JavacTool tool = JavacTool.create(); - Charset cs = (encoding == null ? null : Charset.forName(encoding)); - StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); - Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file); - JavacTask task = tool.getTask(pw, fm, r, Collections.<String>emptyList(), null, files); - Iterable<? extends CompilationUnitTree> trees = task.parse(); - pw.flush(); - if (r.errors > 0) - throw new ParseException(sw.toString()); - Iterator<? extends CompilationUnitTree> iter = trees.iterator(); - if (!iter.hasNext()) - throw new Error("no trees found"); - JCCompilationUnit t = (JCCompilationUnit) iter.next(); - if (iter.hasNext()) - throw new Error("too many trees found"); - return t; - } - - /** - * Report an error. When the program is complete, the program will either - * exit or throw an Error if any errors have been reported. - * @param msg the error message - */ - void error(String msg) { - System.err.println(msg); - errors++; - } - - /** Number of files that have been analyzed. */ - int fileCount; - /** Number of errors reported. */ - int errors; - /** Flag: don't report irrelevant files. */ - boolean quiet; - /** Flag: report files as they are processed. */ - boolean verbose; - /** Flag: show errors in GUI viewer. */ - boolean gui; - /** Option: encoding for test files. */ - String encoding; - /** The GUI viewer for errors. */ - Viewer viewer; - /** The set of tags for tree nodes to be analyzed; if empty, all tree nodes - * are analyzed. */ - Set<String> tags = new HashSet<String>(); - /** Set of files and directories to be excluded from analysis. */ - Set<File> excludeFiles = new HashSet<File>(); - /** Set of tag names to be excluded from analysis. */ - Set<String> excludeTags = new HashSet<String>(); - /** Table of printable names for tree tag values. */ - TagNames tagNames = new TagNames(); - - /** - * Main class for testing assertions concerning tree positions for tree nodes. - */ - private class PosTester extends TreeScanner { - void test(JCCompilationUnit tree) { - sourcefile = tree.sourcefile; - endPosTable = tree.endPositions; - encl = new Info(); - tree.accept(this); - } - - @Override - public void scan(JCTree tree) { - if (tree == null) - return; - - Info self = new Info(tree, endPosTable); - if (check(encl, self)) { - // Modifiers nodes are present throughout the tree even where - // there is no corresponding source text. - // Redundant semicolons in a class definition can cause empty - // initializer blocks with no positions. - if ((self.tag == JCTree.MODIFIERS || self.tag == JCTree.BLOCK) - && self.pos == NOPOS) { - // If pos is NOPOS, so should be the start and end positions - check("start == NOPOS", encl, self, self.start == NOPOS); - check("end == NOPOS", encl, self, self.end == NOPOS); - } else { - // For this node, start , pos, and endpos should be all defined - check("start != NOPOS", encl, self, self.start != NOPOS); - check("pos != NOPOS", encl, self, self.pos != NOPOS); - check("end != NOPOS", encl, self, self.end != NOPOS); - // The following should normally be ordered - // encl.start <= start <= pos <= end <= encl.end - // In addition, the position of the enclosing node should be - // within this node. - // The primary exceptions are for array type nodes, because of the - // need to support legacy syntax: - // e.g. int a[]; int[] b[]; int f()[] { return null; } - // and because of inconsistent nesting of left and right of - // array declarations: - // e.g. int[][] a = new int[2][]; - check("encl.start <= start", encl, self, encl.start <= self.start); - check("start <= pos", encl, self, self.start <= self.pos); - if (!(self.tag == JCTree.TYPEARRAY - && (encl.tag == JCTree.VARDEF || encl.tag == JCTree.TYPEARRAY))) { - check("encl.pos <= start || end <= encl.pos", - encl, self, encl.pos <= self.start || self.end <= encl.pos); - } - check("pos <= end", encl, self, self.pos <= self.end); - if (!(self.tag == JCTree.TYPEARRAY && encl.tag == JCTree.TYPEARRAY)) { - check("end <= encl.end", encl, self, self.end <= encl.end); - } - } - } - - Info prevEncl = encl; - encl = self; - tree.accept(this); - encl = prevEncl; - } - - @Override - public void visitVarDef(JCVariableDecl tree) { - // enum member declarations are desugared in the parser and have - // ill-defined semantics for tree positions, so for now, we - // skip the synthesized bits and just check parts which came from - // the original source text - if ((tree.mods.flags & Flags.ENUM) != 0) { - scan(tree.mods); - if (tree.init != null) { - if (tree.init.getTag() == JCTree.NEWCLASS) { - JCNewClass init = (JCNewClass) tree.init; - if (init.args != null && init.args.nonEmpty()) { - scan(init.args); - } - if (init.def != null && init.def.defs != null) { - scan(init.def.defs); - } - } - } - } else - super.visitVarDef(tree); - } - - boolean check(Info encl, Info self) { - if (excludeTags.size() > 0) { - if (encl != null && excludeTags.contains(tagNames.get(encl.tag)) - || excludeTags.contains(tagNames.get(self.tag))) - return false; - } - return tags.size() == 0 || tags.contains(tagNames.get(self.tag)); - } - - void check(String label, Info encl, Info self, boolean ok) { - if (!ok) { - if (gui) { - if (viewer == null) - viewer = new Viewer(); - viewer.addEntry(sourcefile, label, encl, self); - } - - String s = self.tree.toString(); - String msg = sourcefile.getName() + ": " + label + ": " + - "encl:" + encl + " this:" + self + "\n" + - s.substring(0, Math.min(80, s.length())).replaceAll("[\r\n]+", " "); - error(msg); - } - } - - JavaFileObject sourcefile; - Map<JCTree, Integer> endPosTable; - Info encl; - - } - - /** - * Utility class providing easy access to position and other info for a tree node. - */ - private class Info { - Info() { - tree = null; - tag = JCTree.ERRONEOUS; - start = 0; - pos = 0; - end = Integer.MAX_VALUE; - } - - Info(JCTree tree, Map<JCTree, Integer> endPosTable) { - this.tree = tree; - tag = tree.getTag(); - start = TreeInfo.getStartPos(tree); - pos = tree.pos; - end = TreeInfo.getEndPos(tree, endPosTable); - } - - @Override - public String toString() { - return tagNames.get(tree.getTag()) + "[start:" + start + ",pos:" + pos + ",end:" + end + "]"; - } - - final JCTree tree; - final int tag; - final int start; - final int pos; - final int end; - } - - /** - * Names for tree tags. - * javac does not provide an API to convert tag values to strings, so this class uses - * reflection to determine names of public static final int values in JCTree. - */ - private static class TagNames { - String get(int tag) { - if (map == null) { - map = new HashMap<Integer, String>(); - Class c = JCTree.class; - for (Field f : c.getDeclaredFields()) { - if (f.getType().equals(int.class)) { - int mods = f.getModifiers(); - if (Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) { - try { - map.put(f.getInt(null), f.getName()); - } catch (IllegalAccessException e) { - } - } - } - } - } - String name = map.get(tag); - return (name == null) ? "??" : name; - } - - private Map<Integer, String> map; - } - - /** - * Thrown when errors are found parsing a java file. - */ - private static class ParseException extends Exception { - ParseException(String msg) { - super(msg); - } - } - - /** - * DiagnosticListener to report diagnostics and count any errors that occur. - */ - private static class Reporter implements DiagnosticListener<JavaFileObject> { - Reporter(PrintWriter out) { - this.out = out; - } - - public void report(Diagnostic<? extends JavaFileObject> diagnostic) { - out.println(diagnostic); - switch (diagnostic.getKind()) { - case ERROR: - errors++; - } - } - int errors; - PrintWriter out; - } - - /** - * GUI viewer for issues found by TreePosTester. The viewer provides a drop - * down list for selecting error conditions, a header area providing details - * about an error, and a text area with the ranges of text highlighted as - * appropriate. - */ - private class Viewer extends JFrame { - /** - * Create a viewer. - */ - Viewer() { - initGUI(); - } - - /** - * Add another entry to the list of errors. - * @param file The file containing the error - * @param check The condition that was being tested, and which failed - * @param encl the enclosing tree node - * @param self the tree node containing the error - */ - void addEntry(JavaFileObject file, String check, Info encl, Info self) { - Entry e = new Entry(file, check, encl, self); - DefaultComboBoxModel m = (DefaultComboBoxModel) entries.getModel(); - m.addElement(e); - if (m.getSize() == 1) - entries.setSelectedItem(e); - } - - /** - * Initialize the GUI window. - */ - private void initGUI() { - JPanel head = new JPanel(new GridBagLayout()); - GridBagConstraints lc = new GridBagConstraints(); - GridBagConstraints fc = new GridBagConstraints(); - fc.anchor = GridBagConstraints.WEST; - fc.fill = GridBagConstraints.HORIZONTAL; - fc.gridwidth = GridBagConstraints.REMAINDER; - - entries = new JComboBox(); - entries.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - showEntry((Entry) entries.getSelectedItem()); - } - }); - fc.insets.bottom = 10; - head.add(entries, fc); - fc.insets.bottom = 0; - head.add(new JLabel("check:"), lc); - head.add(checkField = createTextField(80), fc); - fc.fill = GridBagConstraints.NONE; - head.add(setBackground(new JLabel("encl:"), enclColor), lc); - head.add(enclPanel = new InfoPanel(), fc); - head.add(setBackground(new JLabel("self:"), selfColor), lc); - head.add(selfPanel = new InfoPanel(), fc); - add(head, BorderLayout.NORTH); - - body = new JTextArea(); - body.setFont(Font.decode(Font.MONOSPACED)); - body.addCaretListener(new CaretListener() { - public void caretUpdate(CaretEvent e) { - int dot = e.getDot(); - int mark = e.getMark(); - if (dot == mark) - statusText.setText("dot: " + dot); - else - statusText.setText("dot: " + dot + ", mark:" + mark); - } - }); - JScrollPane p = new JScrollPane(body, - JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, - JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - p.setPreferredSize(new Dimension(640, 480)); - add(p, BorderLayout.CENTER); - - statusText = createTextField(80); - add(statusText, BorderLayout.SOUTH); - - pack(); - setLocationRelativeTo(null); // centered on screen - setVisible(true); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - } - - /** Show an entry that has been selected. */ - private void showEntry(Entry e) { - try { - // update simple fields - setTitle(e.file.getName()); - checkField.setText(e.check); - enclPanel.setInfo(e.encl); - selfPanel.setInfo(e.self); - // show file text with highlights - body.setText(e.file.getCharContent(true).toString()); - Highlighter highlighter = body.getHighlighter(); - highlighter.removeAllHighlights(); - addHighlight(highlighter, e.encl, enclColor); - addHighlight(highlighter, e.self, selfColor); - scroll(body, getMinPos(enclPanel.info, selfPanel.info)); - } catch (IOException ex) { - body.setText("Cannot read " + e.file.getName() + ": " + e); - } - } - - /** Create a test field. */ - private JTextField createTextField(int width) { - JTextField f = new JTextField(width); - f.setEditable(false); - f.setBorder(null); - return f; - } - - /** Add a highlighted region based on the positions in an Info object. */ - private void addHighlight(Highlighter h, Info info, Color c) { - int start = info.start; - int end = info.end; - if (start == -1 && end == -1) - return; - if (start == -1) - start = end; - if (end == -1) - end = start; - try { - h.addHighlight(info.start, info.end, - new DefaultHighlighter.DefaultHighlightPainter(c)); - if (info.pos != -1) { - Color c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), (int)(.4f * 255)); // 40% - h.addHighlight(info.pos, info.pos + 1, - new DefaultHighlighter.DefaultHighlightPainter(c2)); - } - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - - /** Get the minimum valid position in a set of info objects. */ - private int getMinPos(Info... values) { - int i = Integer.MAX_VALUE; - for (Info info: values) { - if (info.start >= 0) i = Math.min(i, info.start); - if (info.pos >= 0) i = Math.min(i, info.pos); - if (info.end >= 0) i = Math.min(i, info.end); - } - return (i == Integer.MAX_VALUE) ? 0 : i; - } - - /** Set the background on a component. */ - private JComponent setBackground(JComponent comp, Color c) { - comp.setOpaque(true); - comp.setBackground(c); - return comp; - } - - /** Scroll a text area to display a given position near the middle of the visible area. */ - private void scroll(final JTextArea t, final int pos) { - // Using invokeLater appears to give text a chance to sort itself out - // before the scroll happens; otherwise scrollRectToVisible doesn't work. - // Maybe there's a better way to sync with the text... - EventQueue.invokeLater(new Runnable() { - public void run() { - try { - Rectangle r = t.modelToView(pos); - JScrollPane p = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, t); - r.y = Math.max(0, r.y - p.getHeight() * 2 / 5); - r.height += p.getHeight() * 4 / 5; - t.scrollRectToVisible(r); - } catch (BadLocationException ignore) { - } - } - }); - } - - private JComboBox entries; - private JTextField checkField; - private InfoPanel enclPanel; - private InfoPanel selfPanel; - private JTextArea body; - private JTextField statusText; - - private Color selfColor = new Color(0.f, 1.f, 0.f, 0.2f); // 20% green - private Color enclColor = new Color(1.f, 0.f, 0.f, 0.2f); // 20% red - - /** Panel to display an Info object. */ - private class InfoPanel extends JPanel { - InfoPanel() { - add(tagName = createTextField(20)); - add(new JLabel("start:")); - add(addListener(start = createTextField(6))); - add(new JLabel("pos:")); - add(addListener(pos = createTextField(6))); - add(new JLabel("end:")); - add(addListener(end = createTextField(6))); - } - - void setInfo(Info info) { - this.info = info; - tagName.setText(tagNames.get(info.tag)); - start.setText(String.valueOf(info.start)); - pos.setText(String.valueOf(info.pos)); - end.setText(String.valueOf(info.end)); - } - - JTextField addListener(final JTextField f) { - f.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - body.setCaretPosition(Integer.valueOf(f.getText())); - body.getCaret().setVisible(true); - } - }); - return f; - } - - Info info; - JTextField tagName; - JTextField start; - JTextField pos; - JTextField end; - } - - /** Object to record information about an error to be displayed. */ - private class Entry { - Entry(JavaFileObject file, String check, Info encl, Info self) { - this.file = file; - this.check = check; - this.encl = encl; - this.self= self; - } - - @Override - public String toString() { - return file.getName() + " " + check + " " + getMinPos(encl, self); - } - - final JavaFileObject file; - final String check; - final Info encl; - final Info self; - } - } -} -
--- a/test/tools/javac/varargs/T6746184.java Mon Mar 01 17:53:56 2010 -0800 +++ b/test/tools/javac/varargs/T6746184.java Thu Apr 01 10:07:33 2010 -0700 @@ -36,4 +36,4 @@ class A { public static void m(final Object... varargs) {} private static void m(final Object singleArg) {} -} \ No newline at end of file +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javah/T6893943.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6893943 6937318 + * @summary exit code from javah with no args is 0 + */ + +import java.io.*; +import java.util.*; + +public class T6893943 { + static final String[] NO_ARGS = { }; + static final String[] HELP = { "-help" }; + static final String NEWLINE = System.getProperty("line.separator"); + + public static void main(String... args) throws Exception { + new T6893943().run(); + } + + void run() throws Exception { + testSimpleAPI(NO_ARGS, 1); + testSimpleAPI(HELP, 0); + testCommand(NO_ARGS, 1); + testCommand(HELP, 0); + } + + void testSimpleAPI(String[] args, int expect_rc) throws Exception { + System.err.println("Test simple api: " + Arrays.asList(args)); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javah.Main.run(args, pw); + pw.close(); + expect("testSimpleAPI", sw.toString(), rc, expect_rc); + } + + void testCommand(String[] args, int expect_rc) throws Exception { + System.err.println("Test command: " + Arrays.asList(args)); + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + + List<String> command = new ArrayList<String>(); + command.add(new File(new File(javaHome, "bin"), "javah").getPath()); + command.add("-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path")); + command.addAll(Arrays.asList(args)); + //System.err.println("command: " + command); + + ProcessBuilder pb = new ProcessBuilder(command); + pb.redirectErrorStream(true); + Process p = pb.start(); + p.getOutputStream().close(); + StringWriter sw = new StringWriter(); + String line; + BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); + while ((line = in.readLine()) != null) + sw.write(line + NEWLINE); + int rc = p.waitFor(); + expect("testCommand", sw.toString(), rc, expect_rc); + } + + void expect(String name, String out, int actual_rc, int expect_rc) throws Exception { + if (out.isEmpty()) + throw new Exception("No output from javah"); + + if (!out.startsWith("Usage:")) { + System.err.println(out); + throw new Exception("Unexpected output from javah"); + } + + if (actual_rc != expect_rc) + throw new Exception(name + ": unexpected exit: " + actual_rc + ", expected: " + expect_rc); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javap/6937244/T6937244.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,57 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6937244 + * @summary fields display with JVMS names, not Java names + */ + +import java.io.*; + +public class T6937244 { + public static void main(String[] args) throws Exception { + new T6937244().run(); + } + + void run() throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + String[] args = { "java.lang.String" }; + int rc = com.sun.tools.javap.Main.run(args, pw); + pw.close(); + String out = sw.toString(); + System.err.println(out); + if (rc != 0) + throw new Exception("unexpected exit from javap: " + rc); + for (String line: out.split("[\r\n]+")) { + if (line.contains("CASE_INSENSITIVE_ORDER")) { + if (line.matches("\\s*\\Qpublic static final java.util.Comparator<java.lang.String> CASE_INSENSITIVE_ORDER;\\E\\s*")) + return; + throw new Exception("declaration not shown as expected"); + } + } + throw new Exception("declaration of CASE_INSENSITIVE_ORDER not found"); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javap/6937244/T6937244A.java Thu Apr 01 10:07:33 2010 -0700 @@ -0,0 +1,90 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6937244 + * @summary fields display with JVMS names, not Java names + */ + +import java.io.*; +import java.util.*; + +public class T6937244A { + public static void main(String[] args) throws Exception { + new T6937244A().run(); + } + + void run() throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + String[] args = { "Test" }; + int rc = com.sun.tools.javap.Main.run(args, pw); + pw.close(); + String out = sw.toString(); + System.err.println(out); + if (rc != 0) + throw new Exception("unexpected exit from javap: " + rc); + + int count = 0; + + for (String line: out.split("[\r\n]+")) { + if (line.contains("extends")) { + verify(line, "extends java.lang.Object implements java.util.List<java.lang.String>"); + count++; + } + + if (line.contains("field")) { + verify(line, "java.util.List<java.lang.String> field"); + count++; + } + + if (line.contains("method")) { + verify(line, "java.util.List<java.lang.String> method(java.util.List<java.lang.String>) throws java.lang.Exception"); + count++; + } + } + + // final backstop check + if (out.contains("/")) + throw new Exception("unexpected \"/\" in output"); + + if (count != 3) + throw new Exception("wrong number of matches found: " + count); + } + + void verify(String line, String expect) throws Exception { + if (!line.contains(expect)) { + System.err.println("line: " + line); + System.err.println("expect: " + expect); + throw new Exception("expected string not found in line"); + } + } +} + + +abstract class Test implements List<String> { + public List<String> field; + public List<String> method(List<String> arg) throws Exception { return null; } +} +