OpenJDK / portola / portola
changeset 6163:157fbe5f1e56
Merge
author | lana |
---|---|
date | Mon, 02 Aug 2010 19:46:14 -0700 |
parents | 10bc903a228d 9d0f96b4befa |
children | 60298a435212 |
files | |
diffstat | 552 files changed, 17195 insertions(+), 586 deletions(-) [+] |
line wrap: on
line diff
--- a/langtools/make/build.properties Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/make/build.properties Mon Aug 02 19:46:14 2010 -0700 @@ -107,7 +107,8 @@ javax/annotation/processing/ \ javax/lang/model/ \ javax/tools/ \ - com/sun/source/ com/sun/tools/javac/ + com/sun/source/ \ + com/sun/tools/javac/ javac.tests = \ tools/javac
--- a/langtools/make/build.xml Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/make/build.xml Mon Aug 02 19:46:14 2010 -0700 @@ -322,6 +322,35 @@ datafile="${build.coverage.dir}/cobertura.ser"/> </target> + <target name="diags-examples" depends="build-javac"> + <!-- can override the following on the command line if desired. --> + <property name="diags.examples.out" location="${build.dir}/diag-examples/diags-examples.html"/> + <mkdir dir="${build.dir}/diag-examples/classes"/> + <javac fork="true" + executable="${dist.bin.dir}/javac" + srcdir="test/tools/javac/diags" + destdir="${build.dir}/diag-examples/classes" + includes="Example.java,FileManager.java,HTMLWriter.java,RunExamples.java" + sourcepath="" + classpath="${dist.lib.dir}/javac.jar" + includeAntRuntime="no" + debug="${javac.debug}" + debuglevel="${javac.debuglevel}"/> + <java fork="true" + jvm="${target.java.home}/bin/java" + dir="test/tools/javac/diags" + classpath="${build.dir}/diag-examples/classes;${dist.lib.dir}/javac.jar" + classname="RunExamples"> + <arg value="-examples"/> + <arg value="examples"/> + <arg value="-o"/> + <arg file="${diags.examples.out}"/> + <arg value="-showFiles"/> + <arg value="-title"/> + <arg value="Examples of javac diagnostics"/> + </java> + </target> + <!-- **** Debugging/diagnostic targets.
--- a/langtools/src/share/classes/com/sun/source/tree/TryTree.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/source/tree/TryTree.java Mon Aug 02 19:46:14 2010 -0700 @@ -49,4 +49,5 @@ BlockTree getBlock(); List<? extends CatchTree> getCatches(); BlockTree getFinallyBlock(); + List<? extends Tree> getResources(); }
--- a/langtools/src/share/classes/com/sun/source/util/TreeScanner.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/source/util/TreeScanner.java Mon Aug 02 19:46:14 2010 -0700 @@ -209,7 +209,8 @@ } public R visitTry(TryTree node, P p) { - R r = scan(node.getBlock(), p); + R r = scan(node.getResources(), p); + r = scanAndReduce(node.getBlock(), p, r); r = scanAndReduce(node.getCatches(), p, r); r = scanAndReduce(node.getFinallyBlock(), p, r); return r;
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java Mon Aug 02 19:46:14 2010 -0700 @@ -119,6 +119,7 @@ this.suppressedValues = other.suppressedValues.clone(); } + @Override public String toString() { return "Lint:[values" + values + " suppressedValues" + suppressedValues + "]"; } @@ -208,7 +209,12 @@ /** * Warn about potentially unsafe vararg methods */ - VARARGS("varargs"); + VARARGS("varargs"), + + /** + * Warn about arm resources + */ + ARM("arm"); LintCategory(String option) { this(option, false);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Mon Aug 02 19:46:14 2010 -0700 @@ -159,6 +159,9 @@ public boolean enforceMandatoryWarnings() { return compareTo(JDK1_5) >= 0; } + public boolean allowTryWithResources() { + return compareTo(JDK1_7) >= 0; + } public boolean allowTypeAnnotations() { return compareTo(JDK1_7) >= 0; }
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Mon Aug 02 19:46:14 2010 -0700 @@ -993,12 +993,17 @@ return data == ElementKind.EXCEPTION_PARAMETER; } + public boolean isResourceVariable() { + return data == ElementKind.RESOURCE_VARIABLE; + } + public Object getConstValue() { // TODO: Consider if getConstValue and getConstantValue can be collapsed - if (data == ElementKind.EXCEPTION_PARAMETER) { + if (data == ElementKind.EXCEPTION_PARAMETER || + data == ElementKind.RESOURCE_VARIABLE) { return null; } else if (data instanceof Callable<?>) { - // In this case, this is final a variable, with an as + // In this case, this is a final variable, with an as // yet unevaluated initializer. Callable<?> eval = (Callable<?>)data; data = null; // to make sure we don't evaluate this twice.
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Mon Aug 02 19:46:14 2010 -0700 @@ -148,6 +148,7 @@ public final Type inheritedType; public final Type proprietaryType; public final Type systemType; + public final Type autoCloseableType; /** The symbol representing the length field of an array. */ @@ -159,6 +160,9 @@ /** The symbol representing the final finalize method on enums */ public final MethodSymbol enumFinalFinalize; + /** The symbol representing the close method on TWR AutoCloseable type */ + public final MethodSymbol autoCloseableClose; + /** The predefined type that belongs to a tag. */ public final Type[] typeOfTag = new Type[TypeTags.TypeTagCount]; @@ -444,6 +448,12 @@ suppressWarningsType = enterClass("java.lang.SuppressWarnings"); inheritedType = enterClass("java.lang.annotation.Inherited"); systemType = enterClass("java.lang.System"); + autoCloseableType = enterClass("java.lang.AutoCloseable"); + autoCloseableClose = new MethodSymbol(PUBLIC, + names.close, + new MethodType(List.<Type>nil(), voidType, + List.of(exceptionType), methodClass), + autoCloseableType.tsym); synthesizeEmptyInterfaceIfMissing(cloneableType); synthesizeEmptyInterfaceIfMissing(serializableType);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Aug 02 19:46:14 2010 -0700 @@ -192,7 +192,7 @@ Type check(JCTree tree, Type owntype, int ownkind, int pkind, Type pt) { if (owntype.tag != ERROR && pt.tag != METHOD && pt.tag != FORALL) { if ((ownkind & ~pkind) == 0) { - owntype = chk.checkType(tree.pos(), owntype, pt); + owntype = chk.checkType(tree.pos(), owntype, pt, errKey); } else { log.error(tree.pos(), "unexpected.type", kindNames(pkind), @@ -239,7 +239,11 @@ !((base == null || (base.getTag() == JCTree.IDENT && TreeInfo.name(base) == names._this)) && isAssignableAsBlankFinal(v, env)))) { - log.error(pos, "cant.assign.val.to.final.var", v); + if (v.isResourceVariable()) { //TWR resource + log.error(pos, "twr.resource.may.not.be.assigned", v); + } else { + log.error(pos, "cant.assign.val.to.final.var", v); + } } } @@ -372,6 +376,10 @@ */ Type pt; + /** Visitor argument: the error key to be generated when a type error occurs + */ + String errKey; + /** Visitor result: the computed type. */ Type result; @@ -385,13 +393,19 @@ * @param pt The prototype visitor argument. */ Type attribTree(JCTree tree, Env<AttrContext> env, int pkind, Type pt) { + return attribTree(tree, env, pkind, pt, "incompatible.types"); + } + + Type attribTree(JCTree tree, Env<AttrContext> env, int pkind, Type pt, String errKey) { Env<AttrContext> prevEnv = this.env; int prevPkind = this.pkind; Type prevPt = this.pt; + String prevErrKey = this.errKey; try { this.env = env; this.pkind = pkind; this.pt = pt; + this.errKey = errKey; tree.accept(this); if (tree == breakTree) throw new BreakAttr(env); @@ -403,6 +417,7 @@ this.env = prevEnv; this.pkind = prevPkind; this.pt = prevPt; + this.errKey = prevErrKey; } } @@ -412,6 +427,10 @@ return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType); } + public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt, String key) { + return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType, key); + } + /** Derived visitor method: attribute an expression tree with * no constraints on the computed type. */ @@ -976,14 +995,34 @@ } public void visitTry(JCTry tree) { + // Create a new local environment with a local + Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup())); + boolean isTryWithResource = tree.resources.nonEmpty(); + // Create a nested environment for attributing the try block if needed + Env<AttrContext> tryEnv = isTryWithResource ? + env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) : + localEnv; + // Attribute resource declarations + for (JCTree resource : tree.resources) { + if (resource.getTag() == JCTree.VARDEF) { + attribStat(resource, tryEnv); + chk.checkType(resource, resource.type, syms.autoCloseableType, "twr.not.applicable.to.type"); + VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource); + var.setData(ElementKind.RESOURCE_VARIABLE); + } else { + attribExpr(resource, tryEnv, syms.autoCloseableType, "twr.not.applicable.to.type"); + } + } // Attribute body - attribStat(tree.body, env.dup(tree, env.info.dup())); + attribStat(tree.body, tryEnv); + if (isTryWithResource) + tryEnv.info.scope.leave(); // Attribute catch clauses for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { JCCatch c = l.head; Env<AttrContext> catchEnv = - env.dup(c, env.info.dup(env.info.scope.dup())); + localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup())); Type ctype = attribStat(c.param, catchEnv); if (TreeInfo.isMultiCatch(c)) { //check that multi-catch parameter is marked as final @@ -1003,7 +1042,9 @@ } // Attribute finalizer - if (tree.finalizer != null) attribStat(tree.finalizer, env); + if (tree.finalizer != null) attribStat(tree.finalizer, localEnv); + + localEnv.info.scope.leave(); result = null; } @@ -1653,8 +1694,22 @@ //if the type of the instance creation expression is an interface //skip the method resolution step (JLS 15.12.2.7). The type to be //inferred is of the kind <X1,X2, ... Xn>C<X1,X2, ... Xn> - clazztype = new ForAll(clazztype.tsym.type.allparams(), - clazztype.tsym.type); + clazztype = new ForAll(clazztype.tsym.type.allparams(), clazztype.tsym.type) { + @Override + public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { + switch (ck) { + case EXTENDS: return types.getBounds(tv); + default: return List.nil(); + } + } + @Override + public Type inst(List<Type> inferred, Types types) throws Infer.NoInstanceException { + // check that inferred bounds conform to their bounds + infer.checkWithinBounds(tvars, + types.subst(tvars, tvars, inferred), Warner.noWarnings); + return super.inst(inferred, types); + } + }; } else { //if the type of the instance creation expression is a class type //apply method resolution inference (JLS 15.12.2.7). The return type @@ -2139,6 +2194,15 @@ checkAssignable(tree.pos(), v, tree.selected, env); } + if (sitesym != null && + sitesym.kind == VAR && + ((VarSymbol)sitesym).isResourceVariable() && + sym.kind == MTH && + sym.overrides(syms.autoCloseableClose, sitesym.type.tsym, types, true) && + env.info.lint.isEnabled(Lint.LintCategory.ARM)) { + log.warning(tree, "twr.explicit.close.call"); + } + // Disallow selecting a type from an expression if (isType(sym) && (sitesym==null || (sitesym.kind&(TYP|PCK)) == 0)) { tree.type = check(tree.selected, pt, @@ -3061,7 +3125,8 @@ Scope.Entry e = c.members().lookup(names.serialVersionUID); while (e.scope != null && e.sym.kind != VAR) e = e.next(); if (e.scope == null) { - log.warning(tree.pos(), "missing.SVUID", c); + log.warning(Lint.LintCategory.SERIAL, + tree.pos(), "missing.SVUID", c); return; } @@ -3069,15 +3134,18 @@ VarSymbol svuid = (VarSymbol)e.sym; if ((svuid.flags() & (STATIC | FINAL)) != (STATIC | FINAL)) - log.warning(TreeInfo.diagnosticPositionFor(svuid, tree), "improper.SVUID", c); + log.warning(Lint.LintCategory.SERIAL, + TreeInfo.diagnosticPositionFor(svuid, tree), "improper.SVUID", c); // check that it is long else if (svuid.type.tag != TypeTags.LONG) - log.warning(TreeInfo.diagnosticPositionFor(svuid, tree), "long.SVUID", c); + log.warning(Lint.LintCategory.SERIAL, + TreeInfo.diagnosticPositionFor(svuid, tree), "long.SVUID", c); // check constant else if (svuid.getConstValue() == null) - log.warning(TreeInfo.diagnosticPositionFor(svuid, tree), "constant.SVUID", c); + log.warning(Lint.LintCategory.SERIAL, + TreeInfo.diagnosticPositionFor(svuid, tree), "constant.SVUID", c); } private Type capture(Type type) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Aug 02 19:46:14 2010 -0700 @@ -111,13 +111,13 @@ boolean enforceMandatoryWarnings = source.enforceMandatoryWarnings(); deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated, - enforceMandatoryWarnings, "deprecated"); + enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION); uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked, - enforceMandatoryWarnings, "unchecked"); + enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED); unsafeVarargsHandler = new MandatoryWarningHandler(log, verboseVarargs, - enforceMandatoryWarnings, "varargs"); + enforceMandatoryWarnings, "varargs", LintCategory.VARARGS); sunApiHandler = new MandatoryWarningHandler(log, verboseSunApi, - enforceMandatoryWarnings, "sunapi"); + enforceMandatoryWarnings, "sunapi", null); } /** Switch: generics enabled? @@ -209,7 +209,7 @@ public void warnStatic(DiagnosticPosition pos, String msg, Object... args) { if (lint.isEnabled(LintCategory.STATIC)) - log.warning(pos, msg, args); + log.warning(LintCategory.STATIC, pos, msg, args); } /** @@ -393,6 +393,10 @@ * @param req The type that was required. */ Type checkType(DiagnosticPosition pos, Type found, Type req) { + return checkType(pos, found, req, "incompatible.types"); + } + + Type checkType(DiagnosticPosition pos, Type found, Type req, String errKey) { if (req.tag == ERROR) return req; if (found.tag == FORALL) @@ -411,7 +415,7 @@ log.error(pos, "assignment.to.extends-bound", req); return types.createErrorType(found); } - return typeError(pos, diags.fragment("incompatible.types"), found, req); + return typeError(pos, diags.fragment(errKey), found, req); } /** Instantiate polymorphic type to some prototype, unless @@ -925,7 +929,8 @@ !TreeInfo.isDiamond(tree) && !env.enclClass.name.isEmpty() && //anonymous or intersection tree.type.isRaw()) { - log.warning(tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type); + log.warning(Lint.LintCategory.RAW, + tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type); } } @@ -1853,6 +1858,7 @@ types.isSameType(types.erasure(sym.type), types.erasure(e.sym.type)) && sym != e.sym && (sym.flags() & Flags.SYNTHETIC) != (e.sym.flags() & Flags.SYNTHETIC) && + (sym.flags() & IPROXY) == 0 && (e.sym.flags() & IPROXY) == 0 && (sym.flags() & BRIDGE) == 0 && (e.sym.flags() & BRIDGE) == 0) { syntheticError(pos, (e.sym.flags() & SYNTHETIC) == 0 ? e.sym : sym); return; @@ -2151,7 +2157,8 @@ (s.flags() & DEPRECATED) != 0 && !syms.deprecatedType.isErroneous() && s.attribute(syms.deprecatedType.tsym) == null) { - log.warning(pos, "missing.deprecated.annotation"); + log.warning(Lint.LintCategory.DEP_ANN, + pos, "missing.deprecated.annotation"); } } @@ -2302,7 +2309,7 @@ int opc = ((OperatorSymbol)operator).opcode; if (opc == ByteCodes.idiv || opc == ByteCodes.imod || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) { - log.warning(pos, "div.zero"); + log.warning(Lint.LintCategory.DIVZERO, pos, "div.zero"); } } } @@ -2312,7 +2319,7 @@ */ void checkEmptyIf(JCIf tree) { if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(Lint.LintCategory.EMPTY)) - log.warning(tree.thenpart.pos(), "empty.if"); + log.warning(Lint.LintCategory.EMPTY, tree.thenpart.pos(), "empty.if"); } /** Check that symbol is unique in given scope.
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Mon Aug 02 19:46:14 2010 -0700 @@ -28,6 +28,8 @@ package com.sun.tools.javac.comp; import java.util.HashMap; +import java.util.Map; +import java.util.LinkedHashMap; import com.sun.tools.javac.code.*; import com.sun.tools.javac.tree.*; @@ -35,6 +37,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.comp.Resolve; import com.sun.tools.javac.tree.JCTree.*; import static com.sun.tools.javac.code.Flags.*; @@ -185,6 +188,8 @@ private final Types types; private final Check chk; private TreeMaker make; + private final Resolve rs; + private Env<AttrContext> attrEnv; private Lint lint; private final boolean allowRethrowAnalysis; @@ -203,6 +208,7 @@ types = Types.instance(context); chk = Check.instance(context); lint = Lint.instance(context); + rs = Resolve.instance(context); Source source = Source.instance(context); allowRethrowAnalysis = source.allowMulticatch(); } @@ -265,6 +271,10 @@ */ List<Type> caught; + /** The list of unreferenced automatic resources. + */ + Map<VarSymbol, JCVariableDecl> unrefdResources; + /** Set when processing a loop body the second time for DU analysis. */ boolean loopPassTwo = false; @@ -936,7 +946,8 @@ alive && lint.isEnabled(Lint.LintCategory.FALLTHROUGH) && c.stats.nonEmpty() && l.tail.nonEmpty()) - log.warning(l.tail.head.pos(), + log.warning(Lint.LintCategory.FALLTHROUGH, + l.tail.head.pos(), "possible.fall-through.into.case"); } if (!hasDefault) { @@ -963,6 +974,7 @@ public void visitTry(JCTry tree) { List<Type> caughtPrev = caught; List<Type> thrownPrev = thrown; + Map<VarSymbol, JCVariableDecl> unrefdResourcesPrev = unrefdResources; thrown = List.nil(); for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ? @@ -977,6 +989,38 @@ pendingExits = new ListBuffer<PendingExit>(); Bits initsTry = inits.dup(); uninitsTry = uninits.dup(); + unrefdResources = new LinkedHashMap<VarSymbol, JCVariableDecl>(); + for (JCTree resource : tree.resources) { + if (resource instanceof JCVariableDecl) { + JCVariableDecl vdecl = (JCVariableDecl) resource; + visitVarDef(vdecl); + unrefdResources.put(vdecl.sym, vdecl); + } else if (resource instanceof JCExpression) { + scanExpr((JCExpression) resource); + } else { + throw new AssertionError(tree); // parser error + } + } + for (JCTree resource : tree.resources) { + List<Type> closeableSupertypes = resource.type.isCompound() ? + types.interfaces(resource.type).prepend(types.supertype(resource.type)) : + List.of(resource.type); + for (Type sup : closeableSupertypes) { + if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) { + Symbol closeMethod = rs.resolveInternalMethod(tree, + attrEnv, + sup, + names.close, + List.<Type>nil(), + List.<Type>nil()); + if (closeMethod.kind == MTH) { + for (Type t : ((MethodSymbol)closeMethod).getThrownTypes()) { + markThrown(tree.body, t); + } + } + } + } + } scanStat(tree.body); List<Type> thrownInTry = thrown; thrown = thrownPrev; @@ -987,6 +1031,14 @@ Bits uninitsEnd = uninits; int nextadrCatch = nextadr; + if (!unrefdResources.isEmpty() && + lint.isEnabled(Lint.LintCategory.ARM)) { + for (Map.Entry<VarSymbol, JCVariableDecl> e : unrefdResources.entrySet()) { + log.warning(e.getValue().pos(), + "automatic.resource.not.referenced", e.getKey()); + } + } + List<Type> caughtInTry = List.nil(); for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { alive = true; @@ -1040,8 +1092,9 @@ thrown = chk.union(thrown, thrownPrev); if (!loopPassTwo && lint.isEnabled(Lint.LintCategory.FINALLY)) { - log.warning(TreeInfo.diagEndPos(tree.finalizer), - "finally.cannot.complete"); + log.warning(Lint.LintCategory.FINALLY, + TreeInfo.diagEndPos(tree.finalizer), + "finally.cannot.complete"); } } else { thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry)); @@ -1070,6 +1123,7 @@ while (exits.nonEmpty()) pendingExits.append(exits.next()); } uninitsTry.andSet(uninitsTryPrev).andSet(uninits); + unrefdResources = unrefdResourcesPrev; } public void visitConditional(JCConditional tree) { @@ -1293,8 +1347,16 @@ } public void visitIdent(JCIdent tree) { - if (tree.sym.kind == VAR) + if (tree.sym.kind == VAR) { checkInit(tree.pos(), (VarSymbol)tree.sym); + referenced(tree.sym); + } + } + + void referenced(Symbol sym) { + if (unrefdResources != null && unrefdResources.containsKey(sym)) { + unrefdResources.remove(sym); + } } public void visitTypeCast(JCTypeCast tree) { @@ -1303,7 +1365,8 @@ && lint.isEnabled(Lint.LintCategory.CAST) && types.isSameType(tree.expr.type, tree.clazz.type) && !(ignoreAnnotatedCasts && containsTypeAnnotation(tree.clazz))) { - log.warning(tree.pos(), "redundant.cast", tree.expr.type); + log.warning(Lint.LintCategory.CAST, + tree.pos(), "redundant.cast", tree.expr.type); } } @@ -1334,8 +1397,10 @@ /** Perform definite assignment/unassignment analysis on a tree. */ - public void analyzeTree(JCTree tree, TreeMaker make) { + public void analyzeTree(Env<AttrContext> env, TreeMaker make) { try { + attrEnv = env; + JCTree tree = env.tree; this.make = make; inits = new Bits(); uninits = new Bits();
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Mon Aug 02 19:46:14 2010 -0700 @@ -256,7 +256,7 @@ UndetVar uv = (UndetVar) l.head; TypeVar tv = (TypeVar)uv.qtype; ListBuffer<Type> hibounds = new ListBuffer<Type>(); - for (Type t : that.getConstraints(tv, ConstraintKind.EXTENDS).prependList(types.getBounds(tv))) { + for (Type t : that.getConstraints(tv, ConstraintKind.EXTENDS)) { if (!t.containsSome(that.tvars) && t.tag != BOT) { hibounds.append(t); } @@ -280,7 +280,6 @@ // check bounds List<Type> targs = Type.map(undetvars, getInstFun); targs = types.subst(targs, that.tvars, targs); - checkWithinBounds(that.tvars, targs, warn); return chk.checkType(warn.pos(), that.inst(targs, types), to); } @@ -398,7 +397,7 @@ UndetVar uv = (UndetVar)t; if (uv.qtype == tv) { switch (ck) { - case EXTENDS: return uv.hibounds; + case EXTENDS: return uv.hibounds.appendList(types.subst(types.getBounds(tv), all_tvars, inferredTypes)); case SUPER: return uv.lobounds; case EQUAL: return uv.inst != null ? List.of(uv.inst) : List.<Type>nil(); } @@ -458,7 +457,7 @@ /** check that type parameters are within their bounds. */ - private void checkWithinBounds(List<Type> tvars, + void checkWithinBounds(List<Type> tvars, List<Type> arguments, Warner warn) throws InvalidInstanceException {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Mon Aug 02 19:46:14 2010 -0700 @@ -605,6 +605,23 @@ s.enter(sym); } + /** Create a fresh synthetic name within a given scope - the unique name is + * obtained by appending '$' chars at the end of the name until no match + * is found. + * + * @param name base name + * @param s scope in which the name has to be unique + * @return fresh synthetic name + */ + private Name makeSyntheticName(Name name, Scope s) { + do { + name = name.append( + target.syntheticNameChar(), + names.empty); + } while (lookupSynthetic(name, s) != null); + return name; + } + /** Check whether synthetic symbols generated during lowering conflict * with user-defined symbols. * @@ -1299,6 +1316,11 @@ */ Scope proxies; + /** A scope containing all unnamed resource variables/saved + * exception variables for translated TWR blocks + */ + Scope twrVars; + /** A stack containing the this$n field of the currently translated * classes (if needed) in innermost first order. * Inside a constructor, proxies and any this$n symbol are duplicated @@ -1400,6 +1422,122 @@ } } + /** Optionally replace a try statement with an automatic resource + * management (ARM) block. + * @param tree The try statement to inspect. + * @return An ARM block, or the original try block if there are no + * resources to manage. + */ + JCTree makeArmTry(JCTry tree) { + make_at(tree.pos()); + twrVars = twrVars.dup(); + JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0); + if (tree.catchers.isEmpty() && tree.finalizer == null) + result = translate(armBlock); + else + result = translate(make.Try(armBlock, tree.catchers, tree.finalizer)); + twrVars = twrVars.leave(); + return result; + } + + private JCBlock makeArmBlock(List<JCTree> resources, JCBlock block, int depth) { + if (resources.isEmpty()) + return block; + + // Add resource declaration or expression to block statements + ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); + JCTree resource = resources.head; + JCExpression expr = null; + if (resource instanceof JCVariableDecl) { + JCVariableDecl var = (JCVariableDecl) resource; + expr = make.Ident(var.sym).setType(resource.type); + stats.add(var); + } else { + assert resource instanceof JCExpression; + VarSymbol syntheticTwrVar = + new VarSymbol(SYNTHETIC | FINAL, + makeSyntheticName(names.fromString("twrVar" + + depth), twrVars), + (resource.type.tag == TypeTags.BOT) ? + syms.autoCloseableType : resource.type, + currentMethodSym); + twrVars.enter(syntheticTwrVar); + JCVariableDecl syntheticTwrVarDecl = + make.VarDef(syntheticTwrVar, (JCExpression)resource); + expr = (JCExpression)make.Ident(syntheticTwrVar); + stats.add(syntheticTwrVarDecl); + } + + // Add primaryException declaration + VarSymbol primaryException = + new VarSymbol(SYNTHETIC, + makeSyntheticName(names.fromString("primaryException" + + depth), twrVars), + syms.throwableType, + currentMethodSym); + twrVars.enter(primaryException); + JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull()); + stats.add(primaryExceptionTreeDecl); + + // Create catch clause that saves exception and then rethrows it + VarSymbol param = + new VarSymbol(FINAL|SYNTHETIC, + names.fromString("t" + + target.syntheticNameChar()), + syms.throwableType, + currentMethodSym); + JCVariableDecl paramTree = make.VarDef(param, null); + JCStatement assign = make.Assignment(primaryException, make.Ident(param)); + JCStatement rethrowStat = make.Throw(make.Ident(param)); + JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat)); + JCCatch catchClause = make.Catch(paramTree, catchBlock); + + int oldPos = make.pos; + make.at(TreeInfo.endPos(block)); + JCBlock finallyClause = makeArmFinallyClause(primaryException, expr); + make.at(oldPos); + JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1), + List.<JCCatch>of(catchClause), + finallyClause); + stats.add(outerTry); + return make.Block(0L, stats.toList()); + } + + private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) { + // primaryException.addSuppressedException(catchException); + VarSymbol catchException = + new VarSymbol(0, make.paramName(2), + syms.throwableType, + currentMethodSym); + JCStatement addSuppressionStatement = + make.Exec(makeCall(make.Ident(primaryException), + names.fromString("addSuppressedException"), + List.<JCExpression>of(make.Ident(catchException)))); + + // try { resource.close(); } catch (e) { primaryException.addSuppressedException(e); } + JCBlock tryBlock = + make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource))); + JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null); + JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement)); + List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock)); + JCTry tryTree = make.Try(tryBlock, catchClauses, null); + + // if (resource != null) resourceClose; + JCExpression nullCheck = makeBinary(JCTree.NE, + make.Ident(primaryException), + makeNull()); + JCIf closeIfStatement = make.If(nullCheck, + tryTree, + makeResourceCloseInvocation(resource)); + return make.Block(0L, List.<JCStatement>of(closeIfStatement)); + } + + private JCStatement makeResourceCloseInvocation(JCExpression resource) { + // create resource.close() method invocation + JCExpression resourceClose = makeCall(resource, names.close, List.<JCExpression>nil()); + return make.Exec(resourceClose); + } + /** Construct a tree that represents the outer instance * <C.this>. Never pick the current `this'. * @param pos The source code position to be used for the tree. @@ -3405,6 +3543,15 @@ result = tree; } + @Override + public void visitTry(JCTry tree) { + if (tree.resources.isEmpty()) { + super.visitTry(tree); + } else { + result = makeArmTry(tree); + } + } + /************************************************************************** * main method *************************************************************************/ @@ -3430,6 +3577,7 @@ actualSymbols = new HashMap<Symbol,Symbol>(); freevarCache = new HashMap<ClassSymbol,List<VarSymbol>>(); proxies = new Scope(syms.noSymbol); + twrVars = new Scope(syms.noSymbol); outerThisStack = List.nil(); accessNums = new HashMap<Symbol,Integer>(); accessSyms = new HashMap<Symbol,MethodSymbol[]>();
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Mon Aug 02 19:46:14 2010 -0700 @@ -1797,13 +1797,13 @@ return null; if (isOperator(name)) { - return diags.create(dkind, false, log.currentSource(), pos, + return diags.create(dkind, log.currentSource(), pos, "operator.cant.be.applied", name, argtypes); } boolean hasLocation = false; if (!site.tsym.name.isEmpty()) { if (site.tsym.kind == PCK && !site.tsym.exists()) { - return diags.create(dkind, false, log.currentSource(), pos, + return diags.create(dkind, log.currentSource(), pos, "doesnt.exist", site.tsym); } hasLocation = true; @@ -1814,13 +1814,13 @@ Name idname = isConstructor ? site.tsym.name : name; String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation); if (hasLocation) { - return diags.create(dkind, false, log.currentSource(), pos, + return diags.create(dkind, log.currentSource(), pos, errKey, kindname, idname, //symbol kindname, name typeargtypes, argtypes, //type parameters and arguments (if any) typeKindName(site), site); //location kindname, type } else { - return diags.create(dkind, false, log.currentSource(), pos, + return diags.create(dkind, log.currentSource(), pos, errKey, kindname, idname, //symbol kindname, name typeargtypes, argtypes); //type parameters and arguments (if any) } @@ -1886,12 +1886,12 @@ return null; if (isOperator(name)) { - return diags.create(dkind, false, log.currentSource(), + return diags.create(dkind, log.currentSource(), pos, "operator.cant.be.applied", name, argtypes); } else { Symbol ws = sym.asMemberOf(site, types); - return diags.create(dkind, false, log.currentSource(), pos, + return diags.create(dkind, log.currentSource(), pos, "cant.apply.symbol" + (explanation != null ? ".1" : ""), kindName(ws), ws.name == names.init ? ws.owner.name : ws.name, @@ -1974,18 +1974,18 @@ else if ((sym.flags() & PUBLIC) != 0 || (env != null && this.site != null && !isAccessible(env, this.site))) { - return diags.create(dkind, false, log.currentSource(), + return diags.create(dkind, log.currentSource(), pos, "not.def.access.class.intf.cant.access", sym, sym.location()); } else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0) { - return diags.create(dkind, false, log.currentSource(), + return diags.create(dkind, log.currentSource(), pos, "report.access", sym, asFlagSet(sym.flags() & (PRIVATE | PROTECTED)), sym.location()); } else { - return diags.create(dkind, false, log.currentSource(), + return diags.create(dkind, log.currentSource(), pos, "not.def.public.cant.access", sym, sym.location()); } } @@ -2011,7 +2011,7 @@ Symbol errSym = ((sym.kind == TYP && sym.type.tag == CLASS) ? types.erasure(sym.type).tsym : sym); - return diags.create(dkind, false, log.currentSource(), pos, + return diags.create(dkind, log.currentSource(), pos, "non-static.cant.be.ref", kindName(sym), errSym); } } @@ -2048,7 +2048,7 @@ } Name sname = pair.sym.name; if (sname == names.init) sname = pair.sym.owner.name; - return diags.create(dkind, false, log.currentSource(), + return diags.create(dkind, log.currentSource(), pos, "ref.ambiguous", sname, kindName(pair.sym), pair.sym,
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Mon Aug 02 19:46:14 2010 -0700 @@ -535,6 +535,14 @@ result = tree; } + public void visitTry(JCTry tree) { + tree.resources = translate(tree.resources, syms.autoCloseableType); + tree.body = translate(tree.body); + tree.catchers = translateCatchers(tree.catchers); + tree.finalizer = translate(tree.finalizer); + result = tree; + } + public void visitConditional(JCConditional tree) { tree.cond = translate(tree.cond, syms.booleanType); tree.truepart = translate(tree.truepart, erasure(tree.type));
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Mon Aug 02 19:46:14 2010 -0700 @@ -246,7 +246,8 @@ private void addDirectory(File dir, boolean warn) { if (!dir.isDirectory()) { if (warn) - log.warning("dir.path.element.not.found", dir); + log.warning(Lint.LintCategory.PATH, + "dir.path.element.not.found", dir); return; } @@ -280,8 +281,10 @@ if (! fsInfo.exists(file)) { /* No such file or directory exists */ - if (warn) - log.warning("path.element.not.found", file); + if (warn) { + log.warning(Lint.LintCategory.PATH, + "path.element.not.found", file); + } } else if (fsInfo.isFile(file)) { /* File is an ordinary file. */ if (!isArchive(file)) { @@ -290,12 +293,16 @@ try { ZipFile z = new ZipFile(file); z.close(); - if (warn) - log.warning("unexpected.archive.file", file); + if (warn) { + log.warning(Lint.LintCategory.PATH, + "unexpected.archive.file", file); + } } catch (IOException e) { // FIXME: include e.getLocalizedMessage in warning - if (warn) - log.warning("invalid.archive.file", file); + if (warn) { + log.warning(Lint.LintCategory.PATH, + "invalid.archive.file", file); + } return; } }
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java Mon Aug 02 19:46:14 2010 -0700 @@ -325,6 +325,7 @@ public void visitTry(JCTry tree) { SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); + sr.mergeWith(csp(tree.resources)); sr.mergeWith(csp(tree.body)); sr.mergeWith(cspCatchers(tree.catchers)); sr.mergeWith(csp(tree.finalizer));
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Mon Aug 02 19:46:14 2010 -0700 @@ -2628,7 +2628,7 @@ * @param arg An argument for substitution into the output string. */ private void printVerbose(String key, CharSequence arg) { - Log.printLines(log.noticeWriter, Log.getLocalizedString("verbose." + key, arg)); + log.printNoteLines("verbose." + key, arg); } /** Output for "-checkclassfile" option. @@ -2636,7 +2636,7 @@ * @param arg An argument for substitution into the output string. */ private void printCCF(String key, Object arg) { - Log.printLines(log.noticeWriter, Log.getLocalizedString(key, arg)); + log.printNoteLines(key, arg); }
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Mon Aug 02 19:46:14 2010 -0700 @@ -1604,7 +1604,7 @@ try { writeClassFile(out, c); if (verbose) - log.errWriter.println(Log.getLocalizedString("verbose.wrote.file", outFile)); + log.printErrLines("verbose.wrote.file", outFile); out.close(); out = null; } finally {
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Aug 02 19:46:14 2010 -0700 @@ -1105,7 +1105,7 @@ return env; if (verboseCompilePolicy) - Log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]"); + printNote("[attribute " + env.enclClass.sym + "]"); if (verbose) printVerbose("checking.attribution", env.enclClass.sym); @@ -1174,7 +1174,7 @@ try { make.at(Position.FIRSTPOS); TreeMaker localMake = make.forToplevel(env.toplevel); - flow.analyzeTree(env.tree, localMake); + flow.analyzeTree(env, localMake); compileStates.put(env, CompileState.FLOW); if (shouldStop(CompileState.FLOW)) @@ -1527,19 +1527,19 @@ * @param arg An argument for substitution into the output string. */ protected void printVerbose(String key, Object arg) { - Log.printLines(log.noticeWriter, Log.getLocalizedString("verbose." + key, arg)); + log.printNoteLines("verbose." + key, arg); } /** Print numbers of errors and warnings. */ protected void printCount(String kind, int count) { if (count != 0) { - String text; + String key; if (count == 1) - text = Log.getLocalizedString("count." + kind, String.valueOf(count)); + key = "count." + kind; else - text = Log.getLocalizedString("count." + kind + ".plural", String.valueOf(count)); - Log.printLines(log.errWriter, text); + key = "count." + kind + ".plural"; + log.printErrLines(key, String.valueOf(count)); log.errWriter.flush(); } }
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Aug 02 19:46:14 2010 -0700 @@ -131,6 +131,7 @@ this.allowForeach = source.allowForeach(); this.allowStaticImport = source.allowStaticImport(); this.allowAnnotations = source.allowAnnotations(); + this.allowTWR = source.allowTryWithResources(); this.allowDiamond = source.allowDiamond(); this.allowMulticatch = source.allowMulticatch(); this.allowTypeAnnotations = source.allowTypeAnnotations(); @@ -186,6 +187,10 @@ */ boolean allowTypeAnnotations; + /** Switch: should we recognize automatic resource management? + */ + boolean allowTWR; + /** Switch: should we keep docComments? */ boolean keepDocComments; @@ -1151,8 +1156,12 @@ t = toP(F.at(pos).Select(t, ident())); break; case ELLIPSIS: - assert this.permitTypeAnnotationsPushBack; - typeAnnotationsPushedBack = annos; + if (this.permitTypeAnnotationsPushBack) { + this.typeAnnotationsPushedBack = annos; + } else if (annos.nonEmpty()) { + // Don't return here -- error recovery attempt + illegal(annos.head.pos); + } break loop; default: break loop; @@ -1842,6 +1851,7 @@ * | WHILE ParExpression Statement * | DO Statement WHILE ParExpression ";" * | TRY Block ( Catches | [Catches] FinallyPart ) + * | TRY "(" ResourceSpecification ")" Block [Catches] [FinallyPart] * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" * | SYNCHRONIZED ParExpression Block * | RETURN [Expression] ";" @@ -1912,6 +1922,13 @@ } case TRY: { S.nextToken(); + List<JCTree> resources = List.<JCTree>nil(); + if (S.token() == LPAREN) { + checkAutomaticResourceManagement(); + S.nextToken(); + resources = resources(); + accept(RPAREN); + } JCBlock body = block(); ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>(); JCBlock finalizer = null; @@ -1922,9 +1939,13 @@ finalizer = block(); } } else { - log.error(pos, "try.without.catch.or.finally"); + if (allowTWR) { + if (resources.isEmpty()) + log.error(pos, "try.without.catch.finally.or.resource.decls"); + } else + log.error(pos, "try.without.catch.or.finally"); } - return F.at(pos).Try(body, catchers.toList(), finalizer); + return F.at(pos).Try(resources, body, catchers.toList(), finalizer); } case SWITCH: { S.nextToken(); @@ -2217,7 +2238,7 @@ /* A modifiers tree with no modifier tokens or annotations * has no text position. */ - if ((flags & Flags.ModifierFlags) == 0 && annotations.isEmpty()) + if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty()) pos = Position.NOPOS; JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); @@ -2385,6 +2406,39 @@ return toP(F.at(pos).VarDef(mods, name, type, null)); } + /** Resources = Resource { ";" Resources } + */ + List<JCTree> resources() { + ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); + defs.append(resource()); + while (S.token() == SEMI) { + // All but last of multiple declarators subsume a semicolon + storeEnd(defs.elems.last(), S.endPos()); + S.nextToken(); + defs.append(resource()); + } + return defs.toList(); + } + + /** Resource = + * VariableModifiers Type VariableDeclaratorId = Expression + * | Expression + */ + JCTree resource() { + int pos = S.pos(); + if (S.token() == FINAL || S.token() == MONKEYS_AT) { + return variableDeclaratorRest(pos, optFinal(0), parseType(), + ident(), true, null); + } else { + JCExpression t = term(EXPR | TYPE); + if ((lastmode & TYPE) != 0 && S.token() == IDENTIFIER) + return variableDeclaratorRest(pos, toP(F.at(pos).Modifiers(Flags.FINAL)), t, + ident(), true, null); + else + return t; + } + } + /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} */ public JCTree.JCCompilationUnit parseCompilationUnit() { @@ -3216,6 +3270,12 @@ if (!allowMulticatch) { log.error(S.pos(), "multicatch.not.supported.in.source", source.name); allowMulticatch = true; - } + } + } + void checkAutomaticResourceManagement() { + if (!allowTWR) { + log.error(S.pos(), "automatic.resource.management.not.supported.in.source", source.name); + allowTWR = true; + } } }
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java Mon Aug 02 19:46:14 2010 -0700 @@ -379,6 +379,15 @@ } private JavaFileObject createSourceOrClassFile(boolean isSourceFile, String name) throws IOException { + if (lint) { + int periodIndex = name.lastIndexOf("."); + if (periodIndex != -1) { + String base = name.substring(periodIndex); + String extn = (isSourceFile ? ".java" : ".class"); + if (base.equals(extn)) + log.warning("proc.suspicious.class.name", name, extn); + } + } checkNameAndExistence(name, isSourceFile); Location loc = (isSourceFile ? SOURCE_OUTPUT : CLASS_OUTPUT); JavaFileObject.Kind kind = (isSourceFile ? @@ -530,11 +539,14 @@ /** * Update internal state for a new round. */ - public void newRound(Context context, boolean lastRound) { + public void newRound(Context context) { this.context = context; this.log = Log.instance(context); + clearRoundState(); + } + + void setLastRound(boolean lastRound) { this.lastRound = lastRound; - clearRoundState(); } public void close() {
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacMessager.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacMessager.java Mon Aug 02 19:46:14 2010 -0700 @@ -46,6 +46,7 @@ Log log; JavacProcessingEnvironment processingEnv; int errorCount = 0; + int warningCount = 0; JavacMessager(Context context, JavacProcessingEnvironment processingEnv) { log = Log.instance(context); @@ -116,10 +117,12 @@ break; case WARNING: + warningCount++; log.warning(pos, "proc.messager", msg.toString()); break; case MANDATORY_WARNING: + warningCount++; log.mandatoryWarning(pos, "proc.messager", msg.toString()); break; @@ -167,6 +170,10 @@ return errorCount; } + public int warningCount() { + return warningCount; + } + public void newRound(Context context) { log = Log.instance(context); errorCount = 0;
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Mon Aug 02 19:46:14 2010 -0700 @@ -68,7 +68,6 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Convert; import com.sun.tools.javac.util.List; -import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.JavacMessages; import com.sun.tools.javac.util.Name; @@ -95,6 +94,7 @@ private final boolean lint; private final boolean procOnly; private final boolean fatalErrors; + private final boolean werror; private boolean foundTypeProcessors; private final JavacFiler filer; @@ -157,6 +157,7 @@ procOnly = options.get("-proc:only") != null || options.get("-Xprint") != null; fatalErrors = options.get("fatalEnterError") != null; + werror = options.get("-Werror") != null; platformAnnotations = initPlatformAnnotations(); foundTypeProcessors = false; @@ -654,9 +655,6 @@ Set<TypeElement> annotationsPresent, List<ClassSymbol> topLevelClasses, List<PackageSymbol> packageInfoFiles) { - // Writer for -XprintRounds and -XprintProcessorInfo data - PrintWriter xout = context.get(Log.outKey); - Map<String, TypeElement> unmatchedAnnotations = new HashMap<String, TypeElement>(annotationsPresent.size()); @@ -708,10 +706,10 @@ ps.removeSupportedOptions(unmatchedProcessorOptions); if (printProcessorInfo || verbose) { - xout.println(Log.getLocalizedString("x.print.processor.info", - ps.processor.getClass().getName(), - matchedNames.toString(), - processingResult)); + log.printNoteLines("x.print.processor.info", + ps.processor.getClass().getName(), + matchedNames.toString(), + processingResult); } if (processingResult) { @@ -760,7 +758,7 @@ } @Override - public Set<TypeElement> scan(Element e, Set<TypeElement> p) { + public Set<TypeElement> scan(Element e, Set<TypeElement> p) { for (AnnotationMirror annotationMirror : elements.getAllAnnotationMirrors(e) ) { Element e2 = annotationMirror.getAnnotationType().asElement(); @@ -785,6 +783,239 @@ } } + /** + * Helper object for a single round of annotation processing. + */ + class Round { + /** The round number. */ + final int number; + /** The context for the round. */ + final Context context; + /** The compiler for the round. */ + final JavaCompiler compiler; + /** The log for the round. */ + final Log log; + + /** The set of annotations to be processed this round. */ + Set<TypeElement> annotationsPresent; + /** The set of top level classes to be processed this round. */ + List<ClassSymbol> topLevelClasses; + /** The set of package-info files to be processed this round. */ + List<PackageSymbol> packageInfoFiles; + + /** Create a round. */ + Round(Context context, int number) { + this.context = context; + this.number = number; + compiler = JavaCompiler.instance(context); + log = Log.instance(context); + + // the following is for the benefit of JavacProcessingEnvironment.getContext() + JavacProcessingEnvironment.this.context = context; + + // the following will be populated as needed + annotationsPresent = new LinkedHashSet<TypeElement>(); + topLevelClasses = List.nil(); + packageInfoFiles = List.nil(); + } + + /** Create the next round to be used. */ + Round next() { + compiler.close(false); + return new Round(contextForNextRound(), number + 1); + } + + /** Return the number of errors found so far in this round. + * This may include uncoverable errors, such as parse errors, + * and transient errors, such as missing symbols. */ + int errorCount() { + return compiler.errorCount(); + } + + /** Return the number of warnings found so far in this round. */ + int warningCount() { + return compiler.warningCount(); + } + + /** Return whether or not an unrecoverable error has occurred. */ + boolean unrecoverableError() { + return log.unrecoverableError; + } + + /** Find the set of annotations present in the set of top level + * classes and package info files to be processed this round. */ + void findAnnotationsPresent(ComputeAnnotationSet annotationComputer) { + // Use annotation processing to compute the set of annotations present + annotationsPresent = new LinkedHashSet<TypeElement>(); + for (ClassSymbol classSym : topLevelClasses) + annotationComputer.scan(classSym, annotationsPresent); + for (PackageSymbol pkgSym : packageInfoFiles) + annotationComputer.scan(pkgSym, annotationsPresent); + } + + /** + * Parse the latest set of generated source files created by the filer. + */ + List<JCCompilationUnit> parseNewSourceFiles() + throws IOException { + List<JavaFileObject> fileObjects = List.nil(); + for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) { + fileObjects = fileObjects.prepend(jfo); + } + + return compiler.parseFiles(fileObjects); + } + + /** Enter the latest set of generated class files created by the filer. */ + List<ClassSymbol> enterNewClassFiles() { + ClassReader reader = ClassReader.instance(context); + Names names = Names.instance(context); + List<ClassSymbol> list = List.nil(); + + for (Map.Entry<String,JavaFileObject> entry : filer.getGeneratedClasses().entrySet()) { + Name name = names.fromString(entry.getKey()); + JavaFileObject file = entry.getValue(); + if (file.getKind() != JavaFileObject.Kind.CLASS) + throw new AssertionError(file); + ClassSymbol cs; + if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) { + Name packageName = Convert.packagePart(name); + PackageSymbol p = reader.enterPackage(packageName); + if (p.package_info == null) + p.package_info = reader.enterClass(Convert.shortName(name), p); + cs = p.package_info; + if (cs.classfile == null) + cs.classfile = file; + } else + cs = reader.enterClass(name, file); + list = list.prepend(cs); + } + return list.reverse(); + } + + /** Enter a set of syntax trees. */ + void enterTrees(List<JCCompilationUnit> roots) { + compiler.enterTrees(roots); + } + + /** Run a processing round. */ + void run(boolean lastRound, boolean errorStatus) { +// assert lastRound +// ? (topLevelClasses.size() == 0 && annotationsPresent.size() == 0) +// : (errorStatus == false); +// +// printRoundInfo(topLevelClasses, annotationsPresent, lastRound); + + TaskListener taskListener = context.get(TaskListener.class); + if (taskListener != null) + taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); + + try { + if (lastRound) { + printRoundInfo(List.<ClassSymbol>nil(), Collections.<TypeElement>emptySet(), lastRound); + filer.setLastRound(true); + Set<Element> emptyRootElements = Collections.emptySet(); // immutable + RoundEnvironment renv = new JavacRoundEnvironment(true, + errorStatus, + emptyRootElements, + JavacProcessingEnvironment.this); + discoveredProcs.iterator().runContributingProcs(renv); + } else { + printRoundInfo(topLevelClasses, annotationsPresent, lastRound); + discoverAndRunProcs(context, annotationsPresent, topLevelClasses, packageInfoFiles); + } + } finally { + if (taskListener != null) + taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); + } + } + + /** Update the processing state for the current context. */ + // Question: should this not be part of next()? + // Note: Calling it from next() breaks some tests. There is an issue + // whether the annotationComputer is using elementUtils with the + // correct context. + void updateProcessingState() { + filer.newRound(context); + messager.newRound(context); + + elementUtils.setContext(context); + typeUtils.setContext(context); + } + + /** Print info about this round. */ + private void printRoundInfo(List<ClassSymbol> topLevelClasses, + Set<TypeElement> annotationsPresent, + boolean lastRound) { + if (printRounds || verbose) { + log.printNoteLines("x.print.rounds", + (!lastRound ? number : number + 1), + "{" + topLevelClasses.toString(", ") + "}", + annotationsPresent, + lastRound); + } + } + + /** Get the context for the next round of processing. + * Important values are propogated from round to round; + * other values are implicitly reset. + */ + private Context contextForNextRound() { + Context next = new Context(); + + Options options = Options.instance(context); + assert options != null; + next.put(Options.optionsKey, options); + + PrintWriter out = context.get(Log.outKey); + assert out != null; + next.put(Log.outKey, out); + + final boolean shareNames = true; + if (shareNames) { + Names names = Names.instance(context); + assert names != null; + next.put(Names.namesKey, names); + } + + DiagnosticListener<?> dl = context.get(DiagnosticListener.class); + if (dl != null) + next.put(DiagnosticListener.class, dl); + + TaskListener tl = context.get(TaskListener.class); + if (tl != null) + next.put(TaskListener.class, tl); + + JavaFileManager jfm = context.get(JavaFileManager.class); + assert jfm != null; + next.put(JavaFileManager.class, jfm); + if (jfm instanceof JavacFileManager) { + ((JavacFileManager)jfm).setContext(next); + } + + Names names = Names.instance(context); + assert names != null; + next.put(Names.namesKey, names); + + Keywords keywords = Keywords.instance(context); + assert(keywords != null); + next.put(Keywords.keywordsKey, keywords); + + JavaCompiler oldCompiler = JavaCompiler.instance(context); + JavaCompiler nextCompiler = JavaCompiler.instance(next); + nextCompiler.initRound(oldCompiler); + + JavacTaskImpl task = context.get(JavacTaskImpl.class); + if (task != null) { + next.put(JavacTaskImpl.class, task); + task.updateContext(next); + } + + context.clear(); + return next; + } + } + // TODO: internal catch clauses?; catch and rethrow an annotation // processing error @@ -795,61 +1026,37 @@ throws IOException { log = Log.instance(context); - // Writer for -XprintRounds and -XprintProcessorInfo data - PrintWriter xout = context.get(Log.outKey); - TaskListener taskListener = context.get(TaskListener.class); - JavaCompiler compiler = JavaCompiler.instance(context); - compiler.todo.clear(); // free the compiler's resources + Round round = new Round(context, 1); + round.compiler.todo.clear(); // free the compiler's resources - int round = 0; - - // List<JCAnnotation> annotationsPresentInSource = collector.findAnnotations(roots); - List<ClassSymbol> topLevelClasses = getTopLevelClasses(roots); + // The reverse() in the following line is to maintain behavioural + // compatibility with the previous revision of the code. Strictly speaking, + // it should not be necessary, but a javah golden file test fails without it. + round.topLevelClasses = + getTopLevelClasses(roots).prependList(classSymbols.reverse()); - for (ClassSymbol classSym : classSymbols) - topLevelClasses = topLevelClasses.prepend(classSym); - List<PackageSymbol> packageInfoFiles = - getPackageInfoFiles(roots); + round.packageInfoFiles = getPackageInfoFiles(roots); Set<PackageSymbol> specifiedPackages = new LinkedHashSet<PackageSymbol>(); for (PackageSymbol psym : pckSymbols) specifiedPackages.add(psym); this.specifiedPackages = Collections.unmodifiableSet(specifiedPackages); - // Use annotation processing to compute the set of annotations present - Set<TypeElement> annotationsPresent = new LinkedHashSet<TypeElement>(); ComputeAnnotationSet annotationComputer = new ComputeAnnotationSet(elementUtils); - for (ClassSymbol classSym : topLevelClasses) - annotationComputer.scan(classSym, annotationsPresent); - for (PackageSymbol pkgSym : packageInfoFiles) - annotationComputer.scan(pkgSym, annotationsPresent); + round.findAnnotationsPresent(annotationComputer); - Context currentContext = context; - - int roundNumber = 0; boolean errorStatus = false; runAround: - while(true) { - if (fatalErrors && compiler.errorCount() != 0) { + while (true) { + if ((fatalErrors && round.errorCount() != 0) + || (werror && round.warningCount() != 0)) { errorStatus = true; break runAround; } - this.context = currentContext; - roundNumber++; - printRoundInfo(xout, roundNumber, topLevelClasses, annotationsPresent, false); - - if (taskListener != null) - taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); - - try { - discoverAndRunProcs(currentContext, annotationsPresent, topLevelClasses, packageInfoFiles); - } finally { - if (taskListener != null) - taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); - } + round.run(false, false); /* * Processors for round n have run to completion. Prepare @@ -860,65 +1067,54 @@ if (messager.errorRaised()) { errorStatus = true; break runAround; - } else { - if (moreToDo()) { - // annotationsPresentInSource = List.nil(); - annotationsPresent = new LinkedHashSet<TypeElement>(); - topLevelClasses = List.nil(); - packageInfoFiles = List.nil(); + } - compiler.close(false); - currentContext = contextForNextRound(currentContext, true); + if (!moreToDo()) + break runAround; // No new files - JavaFileManager fileManager = currentContext.get(JavaFileManager.class); + round = round.next(); - compiler = JavaCompiler.instance(currentContext); - List<JCCompilationUnit> parsedFiles = sourcesToParsedFiles(compiler); - roots = cleanTrees(roots).appendList(parsedFiles); + List<JCCompilationUnit> parsedFiles = round.parseNewSourceFiles(); + roots = cleanTrees(roots).appendList(parsedFiles); - // Check for errors after parsing - if (log.unrecoverableError) { - errorStatus = true; - break runAround; - } else { - List<ClassSymbol> newClasses = enterNewClassFiles(currentContext); - compiler.enterTrees(roots); + // Check for errors after parsing + if (round.unrecoverableError()) { + errorStatus = true; + break runAround; + } + + List<ClassSymbol> newClasses = round.enterNewClassFiles(); + round.enterTrees(roots); - // annotationsPresentInSource = - // collector.findAnnotations(parsedFiles); - ListBuffer<ClassSymbol> tlc = new ListBuffer<ClassSymbol>(); - tlc.appendList(getTopLevelClasses(parsedFiles)); - tlc.appendList(getTopLevelClassesFromClasses(newClasses)); - topLevelClasses = tlc.toList(); + round.topLevelClasses = join( + getTopLevelClasses(parsedFiles), + getTopLevelClassesFromClasses(newClasses)); - ListBuffer<PackageSymbol> pif = new ListBuffer<PackageSymbol>(); - pif.appendList(getPackageInfoFiles(parsedFiles)); - pif.appendList(getPackageInfoFilesFromClasses(newClasses)); - packageInfoFiles = pif.toList(); + round.packageInfoFiles = join( + getPackageInfoFiles(parsedFiles), + getPackageInfoFilesFromClasses(newClasses)); - annotationsPresent = new LinkedHashSet<TypeElement>(); - for (ClassSymbol classSym : topLevelClasses) - annotationComputer.scan(classSym, annotationsPresent); - for (PackageSymbol pkgSym : packageInfoFiles) - annotationComputer.scan(pkgSym, annotationsPresent); + round.findAnnotationsPresent(annotationComputer); + round.updateProcessingState(); + } + + // run last round + round.run(true, errorStatus); - updateProcessingState(currentContext, false); - } - } else - break runAround; // No new files - } + // Add any sources generated during the last round to the set + // of files to be compiled. + if (moreToDo()) { + List<JCCompilationUnit> parsedFiles = round.parseNewSourceFiles(); + roots = cleanTrees(roots).appendList(parsedFiles); } - roots = runLastRound(xout, roundNumber, errorStatus, compiler, roots, taskListener); + // Set error status for any files compiled and generated in // the last round - if (log.unrecoverableError) + if (round.unrecoverableError() || (werror && round.warningCount() != 0)) errorStatus = true; - compiler.close(false); - currentContext = contextForNextRound(currentContext, true); - compiler = JavaCompiler.instance(currentContext); + round = round.next(); - filer.newRound(currentContext, true); filer.warnIfUnclosedFiles(); warnIfUnmatchedOptions(); @@ -935,143 +1131,43 @@ */ errorStatus = errorStatus || messager.errorRaised(); - // Free resources this.close(); + TaskListener taskListener = this.context.get(TaskListener.class); if (taskListener != null) taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); + JavaCompiler compiler; + if (errorStatus) { + compiler = round.compiler; + compiler.log.nwarnings += messager.warningCount(); compiler.log.nerrors += messager.errorCount(); if (compiler.errorCount() == 0) compiler.log.nerrors++; } else if (procOnly && !foundTypeProcessors) { + compiler = round.compiler; compiler.todo.clear(); } else { // Final compilation - compiler.close(false); - currentContext = contextForNextRound(currentContext, true); - this.context = currentContext; - updateProcessingState(currentContext, true); - compiler = JavaCompiler.instance(currentContext); + round = round.next(); + round.updateProcessingState(); + compiler = round.compiler; if (procOnly && foundTypeProcessors) compiler.shouldStopPolicy = CompileState.FLOW; - if (true) { - compiler.enterTrees(cleanTrees(roots)); - } else { - List<JavaFileObject> fileObjects = List.nil(); - for (JCCompilationUnit unit : roots) - fileObjects = fileObjects.prepend(unit.getSourceFile()); - roots = null; - compiler.enterTrees(compiler.parseFiles(fileObjects.reverse())); - } + compiler.enterTrees(cleanTrees(roots)); } return compiler; } - private List<JCCompilationUnit> sourcesToParsedFiles(JavaCompiler compiler) - throws IOException { - List<JavaFileObject> fileObjects = List.nil(); - for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) { - fileObjects = fileObjects.prepend(jfo); - } - - return compiler.parseFiles(fileObjects); - } - - // Call the last round of annotation processing - private List<JCCompilationUnit> runLastRound(PrintWriter xout, - int roundNumber, - boolean errorStatus, - JavaCompiler compiler, - List<JCCompilationUnit> roots, - TaskListener taskListener) throws IOException { - roundNumber++; - List<ClassSymbol> noTopLevelClasses = List.nil(); - Set<TypeElement> noAnnotations = Collections.emptySet(); - printRoundInfo(xout, roundNumber, noTopLevelClasses, noAnnotations, true); - - Set<Element> emptyRootElements = Collections.emptySet(); // immutable - RoundEnvironment renv = new JavacRoundEnvironment(true, - errorStatus, - emptyRootElements, - JavacProcessingEnvironment.this); - if (taskListener != null) - taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); - - try { - discoveredProcs.iterator().runContributingProcs(renv); - } finally { - if (taskListener != null) - taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); - } - - // Add any sources generated during the last round to the set - // of files to be compiled. - if (moreToDo()) { - List<JCCompilationUnit> parsedFiles = sourcesToParsedFiles(compiler); - roots = cleanTrees(roots).appendList(parsedFiles); - } - - return roots; - } - - private void updateProcessingState(Context currentContext, boolean lastRound) { - filer.newRound(currentContext, lastRound); - messager.newRound(currentContext); - - elementUtils.setContext(currentContext); - typeUtils.setContext(currentContext); - } - private void warnIfUnmatchedOptions() { if (!unmatchedProcessorOptions.isEmpty()) { log.warning("proc.unmatched.processor.options", unmatchedProcessorOptions.toString()); } } - private void printRoundInfo(PrintWriter xout, - int roundNumber, - List<ClassSymbol> topLevelClasses, - Set<TypeElement> annotationsPresent, - boolean lastRound) { - if (printRounds || verbose) { - xout.println(Log.getLocalizedString("x.print.rounds", - roundNumber, - "{" + topLevelClasses.toString(", ") + "}", - annotationsPresent, - lastRound)); - } - } - - private List<ClassSymbol> enterNewClassFiles(Context currentContext) { - ClassReader reader = ClassReader.instance(currentContext); - Names names = Names.instance(currentContext); - List<ClassSymbol> list = List.nil(); - - for (Map.Entry<String,JavaFileObject> entry : filer.getGeneratedClasses().entrySet()) { - Name name = names.fromString(entry.getKey()); - JavaFileObject file = entry.getValue(); - if (file.getKind() != JavaFileObject.Kind.CLASS) - throw new AssertionError(file); - ClassSymbol cs; - if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) { - Name packageName = Convert.packagePart(name); - PackageSymbol p = reader.enterPackage(packageName); - if (p.package_info == null) - p.package_info = reader.enterClass(Convert.shortName(name), p); - cs = p.package_info; - if (cs.classfile == null) - cs.classfile = file; - } else - cs = reader.enterClass(name, file); - list = list.prepend(cs); - } - return list.reverse(); - } - /** * Free resources related to annotation processing. */ @@ -1126,6 +1222,11 @@ return packages.reverse(); } + // avoid unchecked warning from use of varargs + private static <T> List<T> join(List<T> list1, List<T> list2) { + return list1.appendList(list2); + } + private boolean isPkgInfo(JavaFileObject fo, JavaFileObject.Kind kind) { return fo.isNameCompatible("package-info", kind); } @@ -1134,62 +1235,6 @@ return isPkgInfo(sym.classfile, JavaFileObject.Kind.CLASS) && (sym.packge().package_info == sym); } - private Context contextForNextRound(Context context, boolean shareNames) - throws IOException - { - Context next = new Context(); - - Options options = Options.instance(context); - assert options != null; - next.put(Options.optionsKey, options); - - PrintWriter out = context.get(Log.outKey); - assert out != null; - next.put(Log.outKey, out); - - if (shareNames) { - Names names = Names.instance(context); - assert names != null; - next.put(Names.namesKey, names); - } - - DiagnosticListener<?> dl = context.get(DiagnosticListener.class); - if (dl != null) - next.put(DiagnosticListener.class, dl); - - TaskListener tl = context.get(TaskListener.class); - if (tl != null) - next.put(TaskListener.class, tl); - - JavaFileManager jfm = context.get(JavaFileManager.class); - assert jfm != null; - next.put(JavaFileManager.class, jfm); - if (jfm instanceof JavacFileManager) { - ((JavacFileManager)jfm).setContext(next); - } - - Names names = Names.instance(context); - assert names != null; - next.put(Names.namesKey, names); - - Keywords keywords = Keywords.instance(context); - assert(keywords != null); - next.put(Keywords.keywordsKey, keywords); - - JavaCompiler oldCompiler = JavaCompiler.instance(context); - JavaCompiler nextCompiler = JavaCompiler.instance(next); - nextCompiler.initRound(oldCompiler); - - JavacTaskImpl task = context.get(JavacTaskImpl.class); - if (task != null) { - next.put(JavacTaskImpl.class, task); - task.updateContext(next); - } - - context.clear(); - return next; - } - /* * Called retroactively to determine if a class loader was required, * after we have failed to create one.
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Aug 02 19:46:14 2010 -0700 @@ -61,6 +61,8 @@ anonymous class implements interface; cannot have type arguments compiler.err.anon.class.impl.intf.no.qual.for.new=\ anonymous class implements interface; cannot have qualifier for new +compiler.misc.twr.not.applicable.to.type=\ + automatic resource management not applicable to variable type compiler.err.array.and.varargs=\ cannot declare both {0} and {1} in {2} compiler.err.array.dimension.missing=\ @@ -172,6 +174,8 @@ compiler.err.final.parameter.may.not.be.assigned=\ final parameter {0} may not be assigned +compiler.err.twr.resource.may.not.be.assigned=\ + automatic resource {0} may not be assigned compiler.err.multicatch.parameter.may.not.be.assigned=\ multi-catch parameter {0} may not be assigned compiler.err.multicatch.param.must.be.final=\ @@ -448,6 +452,8 @@ throws clause not allowed in @interface members compiler.err.try.without.catch.or.finally=\ ''try'' without ''catch'' or ''finally'' +compiler.err.try.without.catch.finally.or.resource.decls=\ + ''try'' without ''catch'', ''finally'' or resource declarations compiler.err.type.doesnt.take.params=\ type {0} does not take parameters compiler.err.type.var.cant.be.deref=\ @@ -691,25 +697,31 @@ compiler.warn.warning=\ warning:\u0020 +## Warning messages may also include the following prefix to identify a +## lint option +compiler.warn.lintOption=\ + [{0}]\u0020 + compiler.warn.constant.SVUID=\ - [serial] serialVersionUID must be constant in class {0} + serialVersionUID must be constant in class {0} compiler.warn.dir.path.element.not.found=\ - [path] bad path element "{0}": no such directory + bad path element "{0}": no such directory compiler.warn.finally.cannot.complete=\ - [finally] finally clause cannot complete normally + finally clause cannot complete normally compiler.warn.has.been.deprecated=\ - [deprecation] {0} in {1} has been deprecated + {0} in {1} has been deprecated compiler.warn.sun.proprietary=\ {0} is internal proprietary API and may be removed in a future release compiler.warn.illegal.char.for.encoding=\ unmappable character for encoding {0} + compiler.warn.improper.SVUID=\ - [serial] serialVersionUID must be declared static final in class {0} + serialVersionUID must be declared static final in class {0} compiler.warn.inexact.non-varargs.call=\ non-varargs call of varargs method with inexact argument type for last parameter;\n\ @@ -717,10 +729,10 @@ cast to {1} for a non-varargs call and to suppress this warning compiler.warn.long.SVUID=\ - [serial] serialVersionUID must be of type long in class {0} + serialVersionUID must be of type long in class {0} compiler.warn.missing.SVUID=\ - [serial] serializable class {0} has no definition of serialVersionUID + serializable class {0} has no definition of serialVersionUID compiler.warn.override.varargs.missing=\ {0}; overridden method has no ''...'' @@ -731,13 +743,15 @@ compiler.warn.pkg-info.already.seen=\ a package-info.java file has already been seen for package {0} + compiler.warn.path.element.not.found=\ - [path] bad path element "{0}": no such file or directory + bad path element "{0}": no such file or directory + compiler.warn.possible.fall-through.into.case=\ - [fallthrough] possible fall-through into case + possible fall-through into case compiler.warn.redundant.cast=\ - [cast] redundant cast to {0} + redundant cast to {0} compiler.warn.position.overflow=\ Position encoding overflows at line {0} @@ -747,7 +761,7 @@ 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 + 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=\ @@ -764,6 +778,9 @@ compiler.warn.proc.illegal.file.name=\ Cannot create file for illegal name ''{0}''. +compiler.warn.proc.suspicious.class.name=\ + Creating file for a type whose name ends in {1}: ''{0}'' + compiler.warn.proc.file.create.last.round=\ File for type ''{0}'' created in the last round will not be subject to annotation processing. @@ -797,39 +814,43 @@ compiler.warn.proc.unmatched.processor.options=\ The following options were not recognized by any processor: ''{0}'' +compiler.warn.twr.explicit.close.call=\ + [arm] explicit call to close() on an automatic resource +compiler.warn.automatic.resource.not.referenced=\ + [arm] automatic resource {0} is never referenced in body of corresponding try statement compiler.warn.unchecked.assign=\ - [unchecked] unchecked assignment: {0} to {1} + unchecked assignment: {0} to {1} compiler.warn.unchecked.assign.to.var=\ - [unchecked] unchecked assignment to variable {0} as member of raw type {1} + unchecked assignment to variable {0} as member of raw type {1} compiler.warn.unchecked.call.mbr.of.raw.type=\ - [unchecked] unchecked call to {0} as a member of the raw type {1} + unchecked call to {0} as a member of the raw type {1} compiler.warn.unchecked.cast.to.type=\ - [unchecked] unchecked cast to type {0} + unchecked cast to type {0} compiler.warn.unchecked.meth.invocation.applied=\ - [unchecked] unchecked method invocation: {0} {1} in {4} {5} is applied to given types\n\ + unchecked method invocation: {0} {1} in {4} {5} is applied to given types\n\ required: {2}\n\ found: {3} compiler.warn.unchecked.generic.array.creation=\ - [unchecked] unchecked generic array creation for varargs parameter of type {0} + unchecked generic array creation for varargs parameter of type {0} compiler.warn.varargs.non.reifiable.type=\ - [varargs] Possible heap pollution from parameterized vararg type {0} + Possible heap pollution from parameterized vararg type {0} compiler.warn.missing.deprecated.annotation=\ - [dep-ann] deprecated item is not annotated with @Deprecated + deprecated item is not annotated with @Deprecated compiler.warn.invalid.archive.file=\ - [path] Unexpected file on path: {0} + Unexpected file on path: {0} compiler.warn.unexpected.archive.file=\ - [path] Unexpected extension for archive file: {0} + Unexpected extension for archive file: {0} compiler.warn.div.zero=\ - [divzero] division by zero + division by zero compiler.warn.empty.if=\ - [empty] empty statement after if + empty statement after if compiler.warn.annotation.method.not.found=\ Cannot find annotation method ''{1}()'' in type ''{0}'' @@ -838,7 +859,7 @@ Cannot find annotation method ''{1}()'' in type ''{0}'': {2} compiler.warn.raw.class.use=\ - [rawtypes] found raw type: {0}\n\ + found raw type: {0}\n\ missing type parameters for generic class {1} ##### @@ -996,13 +1017,13 @@ possible loss of precision compiler.misc.unchecked.assign=\ - [unchecked] unchecked conversion + unchecked conversion # compiler.misc.storecheck=\ -# [unchecked] assignment might cause later store checks to fail +# assignment might cause later store checks to fail # compiler.misc.unchecked=\ -# [unchecked] assigned array cannot dynamically check its stores +# assigned array cannot dynamically check its stores compiler.misc.unchecked.cast.to.type=\ - [unchecked] unchecked cast + unchecked cast compiler.misc.assignment.from.super-bound=\ assignment from super-bound type {0} @@ -1172,11 +1193,11 @@ return type {1} is not compatible with {2} compiler.warn.override.unchecked.ret=\ - [unchecked] {0}\n\ + {0}\n\ return type requires unchecked conversion from {1} to {2} compiler.warn.override.unchecked.thrown=\ - [unchecked] {0}\n\ + {0}\n\ overridden method does not throw {1} ## The following are all possible strings for the first argument ({0}) of the @@ -1217,6 +1238,10 @@ underscores in literals are not supported in -source {0}\n\ (use -source 7 or higher to enable underscores in literals) +compiler.err.automatic.resource.management.not.supported.in.source=\ + automatic resource management is not supported in -source {0}\n\ +(use -source 7 or higher to enable automatic resource management) + compiler.warn.enum.as.identifier=\ as of release 5, ''enum'' is a keyword, and may not be used as an identifier\n\ (use -source 5 or higher to use ''enum'' as a keyword) @@ -1263,7 +1288,7 @@ compiler.err.diamond.not.supported.in.source=\ diamond operator is not supported in -source {0}\n\ -(use -source 7 or higher to enable multi-catch statement) +(use -source 7 or higher to enable diamond operator) compiler.err.multicatch.not.supported.in.source=\ multi-catch statement is not supported in -source {0}\n\
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Mon Aug 02 19:46:14 2010 -0700 @@ -1021,10 +1021,15 @@ public JCBlock body; public List<JCCatch> catchers; public JCBlock finalizer; - protected JCTry(JCBlock body, List<JCCatch> catchers, JCBlock finalizer) { + public List<JCTree> resources; + protected JCTry(List<JCTree> resources, + JCBlock body, + List<JCCatch> catchers, + JCBlock finalizer) { this.body = body; this.catchers = catchers; this.finalizer = finalizer; + this.resources = resources; } @Override public void accept(Visitor v) { v.visitTry(this); } @@ -1040,6 +1045,10 @@ return v.visitTry(this, d); } @Override + public List<? extends JCTree> getResources() { + return resources; + } + @Override public int getTag() { return TRY; } @@ -2162,6 +2171,10 @@ JCCase Case(JCExpression pat, List<JCStatement> stats); JCSynchronized Synchronized(JCExpression lock, JCBlock body); JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer); + JCTry Try(List<JCTree> resources, + JCBlock body, + List<JCCatch> catchers, + JCBlock finalizer); JCCatch Catch(JCVariableDecl param, JCBlock body); JCConditional Conditional(JCExpression cond, JCExpression thenpart,
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java Mon Aug 02 19:46:14 2010 -0700 @@ -691,6 +691,19 @@ public void visitTry(JCTry tree) { try { print("try "); + if (tree.resources.nonEmpty()) { + print("("); + boolean first = true; + for (JCTree var : tree.resources) { + if (!first) { + println(); + indent(); + } + printStat(var); + first = false; + } + print(") "); + } printStat(tree.body); for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { printStat(l.head);
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Mon Aug 02 19:46:14 2010 -0700 @@ -332,10 +332,11 @@ public JCTree visitTry(TryTree node, P p) { JCTry t = (JCTry) node; + List<JCTree> resources = copy(t.resources, p); JCBlock body = copy(t.body, p); List<JCCatch> catchers = copy(t.catchers, p); JCBlock finalizer = copy(t.finalizer, p); - return M.at(t.pos).Try(body, catchers, finalizer); + return M.at(t.pos).Try(resources, body, catchers, finalizer); } public JCTree visitParameterizedType(ParameterizedTypeTree node, P p) {
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Mon Aug 02 19:46:14 2010 -0700 @@ -269,7 +269,14 @@ } public JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer) { - JCTry tree = new JCTry(body, catchers, finalizer); + return Try(List.<JCTree>nil(), body, catchers, finalizer); + } + + public JCTry Try(List<JCTree> resources, + JCBlock body, + List<JCCatch> catchers, + JCBlock finalizer) { + JCTry tree = new JCTry(resources, body, catchers, finalizer); tree.pos = pos; return tree; } @@ -486,7 +493,7 @@ public JCModifiers Modifiers(long flags, List<JCAnnotation> annotations) { JCModifiers tree = new JCModifiers(flags, annotations); - boolean noFlags = (flags & Flags.ModifierFlags) == 0; + boolean noFlags = (flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0; tree.pos = (noFlags && annotations.isEmpty()) ? Position.NOPOS : pos; return tree; }
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Mon Aug 02 19:46:14 2010 -0700 @@ -147,6 +147,7 @@ } public void visitTry(JCTry tree) { + scan(tree.resources); scan(tree.body); scan(tree.catchers); scan(tree.finalizer);
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Mon Aug 02 19:46:14 2010 -0700 @@ -212,6 +212,7 @@ } public void visitTry(JCTry tree) { + tree.resources = translate(tree.resources); tree.body = translate(tree.body); tree.catchers = translateCatchers(tree.catchers); tree.finalizer = translate(tree.finalizer);
--- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Mon Aug 02 19:46:14 2010 -0700 @@ -38,6 +38,7 @@ import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.MultilineLimit; import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind; import com.sun.tools.javac.api.Formattable; +import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Printer; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Type; @@ -285,6 +286,13 @@ return buf.toString(); } + protected String formatLintCategory(JCDiagnostic d, Locale l) { + LintCategory lc = d.getLintCategory(); + if (lc == null) + return ""; + return localize(l, "compiler.warn.lintOption", lc.option); + } + /** * Converts a String into a locale-dependent representation accordingly to a given locale. *
--- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java Mon Aug 02 19:46:14 2010 -0700 @@ -29,6 +29,7 @@ import java.util.Map; import javax.tools.JavaFileObject; +import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition; @@ -112,6 +113,16 @@ report(diags.warning(source, null, key, args)); } + /** Report a lint warning, unless suppressed by the -nowarn option or the + * maximum number of warnings has been reached. + * @param lc The lint category for the diagnostic + * @param key The key for the localized warning message. + * @param args Fields of the warning message. + */ + public void warning(LintCategory lc, String key, Object ... args) { + report(diags.warning(lc, key, args)); + } + /** Report a warning, unless suppressed by the -nowarn option or the * maximum number of warnings has been reached. * @param pos The source position at which to report the warning. @@ -122,6 +133,17 @@ report(diags.warning(source, pos, key, args)); } + /** Report a lint warning, unless suppressed by the -nowarn option or the + * maximum number of warnings has been reached. + * @param lc The lint category for the diagnostic + * @param pos The source position at which to report the warning. + * @param key The key for the localized warning message. + * @param args Fields of the warning message. + */ + public void warning(LintCategory lc, DiagnosticPosition pos, String key, Object ... args) { + report(diags.warning(lc, source, pos, key, args)); + } + /** Report a warning, unless suppressed by the -nowarn option or the * maximum number of warnings has been reached. * @param pos The source position at which to report the warning. @@ -141,6 +163,16 @@ report(diags.mandatoryWarning(source, pos, key, args)); } + /** Report a warning. + * @param lc The lint category for the diagnostic + * @param pos The source position at which to report the warning. + * @param key The key for the localized warning message. + * @param args Fields of the warning message. + */ + public void mandatoryWarning(LintCategory lc, DiagnosticPosition pos, String key, Object ... args) { + report(diags.mandatoryWarning(lc, source, pos, key, args)); + } + /** Provide a non-fatal notification, unless suppressed by the -nowarn option. * @param key The key for the localized notification message. * @param args Fields of the notint an error or warning message:
--- a/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Mon Aug 02 19:46:14 2010 -0700 @@ -73,7 +73,6 @@ * @param opts list of command-line options * @param msgs JavacMessages object used for i18n */ - @SuppressWarnings("fallthrough") public BasicDiagnosticFormatter(Options options, JavacMessages msgs) { super(msgs, new BasicConfiguration(options)); } @@ -189,6 +188,8 @@ } case 'm': return formatMessage(d, l); + case 'L': + return formatLintCategory(d, l); case '_': return " "; case '%': @@ -244,9 +245,9 @@ setFormat(BasicFormatKind.DEFAULT_POS_FORMAT, formats[0]); } } - String sourcePosition = null; - if ((((sourcePosition = options.get("sourcePosition")) != null)) && - sourcePosition.equals("bottom")) + String srcPos = null; + if ((((srcPos = options.get("sourcePosition")) != null)) && + srcPos.equals("bottom")) setSourcePosition(SourcePosition.BOTTOM); else setSourcePosition(SourcePosition.AFTER_SUMMARY); @@ -289,9 +290,9 @@ //where private void initFormat() { availableFormats = new HashMap<BasicFormatKind, String>(); - setFormat(BasicFormatKind.DEFAULT_POS_FORMAT, "%f:%l:%_%t%m"); - setFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT, "%p%m"); - setFormat(BasicFormatKind.DEFAULT_CLASS_FORMAT, "%f:%_%t%m"); + setFormat(BasicFormatKind.DEFAULT_POS_FORMAT, "%f:%l:%_%t%L%m"); + setFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT, "%p%L%m"); + setFormat(BasicFormatKind.DEFAULT_CLASS_FORMAT, "%f:%_%t%L%m"); } //where private void initIndentation() {
--- a/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Mon Aug 02 19:46:14 2010 -0700 @@ -32,6 +32,7 @@ import javax.tools.JavaFileObject; import com.sun.tools.javac.api.DiagnosticFormatter; +import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.tree.JCTree; import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*; @@ -82,86 +83,143 @@ */ public JCDiagnostic error( DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { - return create(ERROR, true, source, pos, key, args); + return create(ERROR, null, true, source, pos, key, args); } /** * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options. * @param source The source of the compilation unit, if any, in which to report the warning. * @param pos The source position at which to report the warning. - * @param key The key for the localized error message. - * @param args Fields of the error message. + * @param key The key for the localized warning message. + * @param args Fields of the warning message. * @see MandatoryWarningHandler */ public JCDiagnostic mandatoryWarning( - DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { - return create(WARNING, true, source, pos, key, args); + DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { + return create(WARNING, null, true, source, pos, key, args); + } + + /** + * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options. + * @param lc The lint category for the diagnostic + * @param source The source of the compilation unit, if any, in which to report the warning. + * @param pos The source position at which to report the warning. + * @param key The key for the localized warning message. + * @param args Fields of the warning message. + * @see MandatoryWarningHandler + */ + public JCDiagnostic mandatoryWarning( + LintCategory lc, + DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { + return create(WARNING, lc, true, source, pos, key, args); + } + + /** + * Create a warning diagnostic. + * @param lc The lint category for the diagnostic + * @param key The key for the localized error message. + * @param args Fields of the warning message. + * @see MandatoryWarningHandler + */ + public JCDiagnostic warning( + LintCategory lc, String key, Object... args) { + return create(WARNING, lc, false, null, null, key, args); } /** * Create a warning diagnostic. * @param source The source of the compilation unit, if any, in which to report the warning. * @param pos The source position at which to report the warning. - * @param key The key for the localized error message. - * @param args Fields of the error message. + * @param key The key for the localized warning message. + * @param args Fields of the warning message. */ public JCDiagnostic warning( DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { - return create(WARNING, false, source, pos, key, args); + return create(WARNING, null, false, source, pos, key, args); + } + + /** + * Create a warning diagnostic. + * @param lc The lint category for the diagnostic + * @param source The source of the compilation unit, if any, in which to report the warning. + * @param pos The source position at which to report the warning. + * @param key The key for the localized warning message. + * @param args Fields of the warning message. + * @see MandatoryWarningHandler + */ + public JCDiagnostic warning( + LintCategory lc, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { + return create(WARNING, lc, false, source, pos, key, args); } /** * Create a note diagnostic that will not be hidden by the -nowarn or -Xlint:none options. - * @param key The key for the localized error message. - * @param args Fields of the error message. + * @param key The key for the localized message. + * @param args Fields of the message. * @see MandatoryWarningHandler */ public JCDiagnostic mandatoryNote(DiagnosticSource source, String key, Object... args) { - return create(NOTE, true, source, null, key, args); + return create(NOTE, null, true, source, null, key, args); } /** * Create a note diagnostic. * @param key The key for the localized error message. - * @param args Fields of the error message. + * @param args Fields of the message. */ public JCDiagnostic note(String key, Object... args) { - return create(NOTE, false, null, null, key, args); + return create(NOTE, null, false, null, null, key, args); } /** * Create a note diagnostic. * @param source The source of the compilation unit, if any, in which to report the note. * @param pos The source position at which to report the note. - * @param key The key for the localized error message. - * @param args Fields of the error message. + * @param key The key for the localized message. + * @param args Fields of the message. */ public JCDiagnostic note( DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { - return create(NOTE, false, source, pos, key, args); + return create(NOTE, null, false, source, pos, key, args); } /** * Create a fragment diagnostic, for use as an argument in other diagnostics - * @param key The key for the localized error message. - * @param args Fields of the error message. + * @param key The key for the localized message. + * @param args Fields of the message. */ public JCDiagnostic fragment(String key, Object... args) { - return create(FRAGMENT, false, null, null, key, args); + return create(FRAGMENT, null, false, null, null, key, args); + } + + /** + * Create a new diagnostic of the given kind, which is not mandatory and which has + * no lint category. + * @param kind The diagnostic kind + * @param ls The lint category, if applicable, or null + * @param source The source of the compilation unit, if any, in which to report the message. + * @param pos The source position at which to report the message. + * @param key The key for the localized message. + * @param args Fields of the message. + */ + public JCDiagnostic create( + DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { + return create(kind, null, false, source, pos, key, args); } /** * Create a new diagnostic of the given kind. * @param kind The diagnostic kind + * @param lc The lint category, if applicable, or null * @param isMandatory is diagnostic mandatory? - * @param source The source of the compilation unit, if any, in which to report the note. - * @param pos The source position at which to report the note. - * @param key The key for the localized error message. - * @param args Fields of the error message. + * @param source The source of the compilation unit, if any, in which to report the message. + * @param pos The source position at which to report the message. + * @param key The key for the localized message. + * @param args Fields of the message. */ public JCDiagnostic create( - DiagnosticType kind, boolean isMandatory, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { - return new JCDiagnostic(formatter, kind, isMandatory, source, pos, qualify(kind, key), args); + DiagnosticType kind, LintCategory lc, boolean isMandatory, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { + return new JCDiagnostic(formatter, kind, lc, isMandatory, source, pos, qualify(kind, key), args); } protected String qualify(DiagnosticType t, String key) { @@ -181,6 +239,7 @@ public static JCDiagnostic fragment(String key, Object... args) { return new JCDiagnostic(getFragmentFormatter(), FRAGMENT, + null, false, null, null, @@ -274,30 +333,34 @@ private final int line; private final int column; private final String key; - protected Object[] args; - private boolean mandatory; + protected final Object[] args; + private final boolean mandatory; + private final LintCategory lintCategory; /** * Create a diagnostic object. - * @param messages the resource for localized messages + * @param fomatter the formatter to use for the diagnostic * @param dt the type of diagnostic - * @param name the name of the source file, or null if none. + * @param lc the lint category for the diagnostic + * @param source the name of the source file, or null if none. * @param pos the character offset within the source file, if given. * @param key a resource key to identify the text of the diagnostic * @param args arguments to be included in the text of the diagnostic */ protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter, DiagnosticType dt, + LintCategory lc, boolean mandatory, DiagnosticSource source, DiagnosticPosition pos, String key, - Object ... args) { + Object... args) { if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS) throw new IllegalArgumentException(); this.defaultFormatter = formatter; this.type = dt; + this.lintCategory = lc; this.mandatory = mandatory; this.source = source; this.position = pos; @@ -342,6 +405,20 @@ } /** + * Check whether this diagnostic has an associated lint category. + */ + public boolean hasLintCategory() { + return (lintCategory != null); + } + + /** + * Get the associated lint category, or null if none. + */ + public LintCategory getLintCategory() { + return lintCategory; + } + + /** * Get the name of the source file referred to by this diagnostic. * @return the name of the source referred to with this diagnostic, or null if none */ @@ -467,6 +544,7 @@ public MultilineDiagnostic(JCDiagnostic other, List<JCDiagnostic> subdiagnostics) { super(other.defaultFormatter, other.getType(), + other.getLintCategory(), other.isMandatory(), other.getDiagnosticSource(), other.position,
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java Mon Aug 02 19:46:14 2010 -0700 @@ -269,7 +269,7 @@ */ public void prompt() { if (promptOnError) { - System.err.println(getLocalizedString("resume.abort")); + System.err.println(localize("resume.abort")); char ch; try { while (true) { @@ -317,8 +317,23 @@ if (msg.length() != 0) writer.println(msg); } + /** Print the text of a message to the errWriter stream, + * translating newlines appropriately for the platform. + */ + public void printErrLines(String key, Object... args) { + printLines(errWriter, localize(key, args)); + } + + + /** Print the text of a message to the noticeWriter stream, + * translating newlines appropriately for the platform. + */ + public void printNoteLines(String key, Object... args) { + printLines(noticeWriter, localize(key, args)); + } + protected void directError(String key, Object... args) { - printLines(errWriter, getLocalizedString(key, args)); + printErrLines(key, args); errWriter.flush(); } @@ -426,6 +441,8 @@ } /** Find a localized string in the resource bundle. + * Because this method is static, it ignores the locale. + * Use localize(key, args) when possible. * @param key The key for the localized string. * @param args Fields to substitute into the string. */ @@ -433,6 +450,14 @@ return JavacMessages.getDefaultLocalizedString("compiler.misc." + key, args); } + /** Find a localized string in the resource bundle. + * @param key The key for the localized string. + * @param args Fields to substitute into the string. + */ + public String localize(String key, Object... args) { + return messages.getLocalizedString("compiler.misc." + key, args); + } + /*************************************************************************** * raw error messages without internationalization; used for experimentation * and quick prototyping
--- a/langtools/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java Mon Aug 02 19:46:14 2010 -0700 @@ -29,6 +29,7 @@ import java.util.Set; import javax.tools.JavaFileObject; +import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -105,13 +106,16 @@ * True if mandatory warnings and notes are being enforced. * @param prefix A common prefix for the set of message keys for * the messages that may be generated. + * @param lc An associated lint category for the warnings, or null if none. */ public MandatoryWarningHandler(Log log, boolean verbose, - boolean enforceMandatory, String prefix) { + boolean enforceMandatory, String prefix, + LintCategory lc) { this.log = log; this.verbose = verbose; this.prefix = prefix; this.enforceMandatory = enforceMandatory; + this.lintCategory = lc; } /** @@ -235,15 +239,22 @@ private final boolean enforceMandatory; /** + * A LintCategory to be included in point-of-use diagnostics to indicate + * how messages might be suppressed (i.e. with @SuppressWarnings). + */ + private final LintCategory lintCategory; + + /** * Reports a mandatory warning to the log. If mandatory warnings * are not being enforced, treat this as an ordinary warning. */ private void logMandatoryWarning(DiagnosticPosition pos, String msg, Object... args) { + // Note: the following log methods are safe if lintCategory is null. if (enforceMandatory) - log.mandatoryWarning(pos, msg, args); + log.mandatoryWarning(lintCategory, pos, msg, args); else - log.warning(pos, msg, args); + log.warning(lintCategory, pos, msg, args); } /**
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Names.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Names.java Mon Aug 02 19:46:14 2010 -0700 @@ -148,6 +148,8 @@ public final Name getDeclaringClass; public final Name ex; public final Name finalize; + public final Name java_lang_AutoCloseable; + public final Name close; public final Name.Table table; @@ -263,6 +265,9 @@ getDeclaringClass = fromString("getDeclaringClass"); ex = fromString("ex"); finalize = fromString("finalize"); + + java_lang_AutoCloseable = fromString("java.lang.AutoCloseable"); + close = fromString("close"); } protected Name.Table createTable(Options options) {
--- a/langtools/test/tools/javac/4980495/static/Test.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/4980495/static/Test.java Mon Aug 02 19:46:14 2010 -0700 @@ -1,7 +1,7 @@ /* * @test /nodynamiccopyright/ * @bug 4980495 6260444 - * @compile/fail/ref=Test.out -XDstdout -XDrawDiagnostics Test.java p1/A1.java p2/A2.java + * @compile/fail/ref=Test.out -XDrawDiagnostics Test.java p1/A1.java p2/A2.java */ package p;
--- a/langtools/test/tools/javac/4980495/std/Test.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/4980495/std/Test.java Mon Aug 02 19:46:14 2010 -0700 @@ -1,7 +1,7 @@ /* * @test /nodynamiccopyright/ * @bug 4980495 6260444 - * @compile/fail/ref=Test.out -XDstdout -XDrawDiagnostics Test.java p1/A1.java p2/A2.java + * @compile/fail/ref=Test.out -XDrawDiagnostics Test.java p1/A1.java p2/A2.java * */
--- a/langtools/test/tools/javac/6304921/T6304921.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/6304921/T6304921.java Mon Aug 02 19:46:14 2010 -0700 @@ -1,7 +1,7 @@ /* * @test (important: no SCCS keywords to affect offsets in golden file.) /nodynamiccopyright/ * @bug 6304921 - * @compile/fail/ref=T6304921.out -XDstdout -XDcompilePolicy=bytodo -XDrawDiagnostics -Xjcov -Xlint:all,-path -Werror T6304921.java + * @compile/fail/ref=T6304921.out -XDcompilePolicy=bytodo -XDrawDiagnostics -Xjcov -Xlint:all,-path -Werror T6304921.java */ import java.util.ArrayList;
--- a/langtools/test/tools/javac/6330920/T6330920.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/6330920/T6330920.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6330920 * @summary Verify that javac doesn't duplicate method error on method with error * @author Peter von der Ah\u00e9 - * @compile/fail/ref=T6330920.out -XDstdout -XDrawDiagnostics T6330920.java + * @compile/fail/ref=T6330920.out -XDrawDiagnostics T6330920.java */ public class T6330920 {
--- a/langtools/test/tools/javac/6491592/T6491592.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/6491592/T6491592.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6491592 * @summary Compiler crashes on assignment operator * @author alex.buckley@... - * @compile/fail/ref=T6491592.out -XDstdout -XDrawDiagnostics T6491592.java + * @compile/fail/ref=T6491592.out -XDrawDiagnostics T6491592.java */ public class T6491592 {
--- a/langtools/test/tools/javac/6717241/T6717241a.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/6717241/T6717241a.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6717241 * @summary some diagnostic argument is prematurely converted into a String object * @author Maurizio Cimadamore - * @compile/fail/ref=T6717241a.out -XDstdout -XDrawDiagnostics T6717241a.java + * @compile/fail/ref=T6717241a.out -XDrawDiagnostics T6717241a.java */ class T6717241a<X extends Object & java.io.Serializable> {
--- a/langtools/test/tools/javac/6717241/T6717241b.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/6717241/T6717241b.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6717241 * @summary some diagnostic argument is prematurely converted into a String object * @author Maurizio Cimadamore - * @compile/fail/ref=T6717241b.out -XDstdout -XDrawDiagnostics T6717241b.java + * @compile/fail/ref=T6717241b.out -XDrawDiagnostics T6717241b.java */ class T6717241b {
--- a/langtools/test/tools/javac/ClassFileModifiers/ClassModifiers.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/ClassFileModifiers/ClassModifiers.java Mon Aug 02 19:46:14 2010 -0700 @@ -28,7 +28,7 @@ * file are correct, including those within InnerClasses attributes. * @author John Rose (jrose). Entered as a regression test by Bill Maddox (maddox). * - * @compile/ref=ClassModifiers.out -XDstdout -XDdumpmodifiers=ci ClassModifiers.java + * @compile/ref=ClassModifiers.out -XDdumpmodifiers=ci ClassModifiers.java * */
--- a/langtools/test/tools/javac/ClassFileModifiers/MemberModifiers.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/ClassFileModifiers/MemberModifiers.java Mon Aug 02 19:46:14 2010 -0700 @@ -26,7 +26,7 @@ * @bug 4249112 4785453 * @summary Verify that implicit member modifiers are set correctly. * - * @compile/ref=MemberModifiers.out -XDstdout -source 1.4 -target 1.4.2 -XDdumpmodifiers=cfm MemberModifiers.java + * @compile/ref=MemberModifiers.out -source 1.4 -target 1.4.2 -XDdumpmodifiers=cfm MemberModifiers.java */ // Currently, we check only that members of final classes are not final.
--- a/langtools/test/tools/javac/CyclicInheritance.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/CyclicInheritance.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary Test that recursive 'extends' and 'implements' clauses are detected * and disallowed. * - * @compile/fail/ref=CyclicInheritance.out -XDrawDiagnostics -XDstdout CyclicInheritance.java + * @compile/fail/ref=CyclicInheritance.out -XDrawDiagnostics CyclicInheritance.java */
--- a/langtools/test/tools/javac/Digits.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/Digits.java Mon Aug 02 19:46:14 2010 -0700 @@ -2,7 +2,7 @@ * @test /nodynamiccopyright/ * @bug 6183529 * @summary javac gives warnings instead of errors on non-ASCII digits - * @compile/fail/ref=Digits.out -XDstdout -XDrawDiagnostics Digits.java + * @compile/fail/ref=Digits.out -XDrawDiagnostics Digits.java */ class Digits
--- a/langtools/test/tools/javac/ExtendArray.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/ExtendArray.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 4336282 4785453 * @summary Verify that extending an erray class does not crash the compiler. * - * @compile/fail/ref=ExtendArray.out -XDstdout -XDrawDiagnostics ExtendArray.java + * @compile/fail/ref=ExtendArray.out -XDrawDiagnostics ExtendArray.java */ // Note that an error is expected, but not a crash.
--- a/langtools/test/tools/javac/ExtendsAccess/ExtendsAccess.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/ExtendsAccess/ExtendsAccess.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 4087314 4087314 4785453 * @summary Test access checking within 'extends' and 'implements' clause. * @author William Maddox (maddox) - * @compile/fail/ref=ExtendsAccess.out -XDrawDiagnostics -XDstdout ExtendsAccess.java + * @compile/fail/ref=ExtendsAccess.out -XDrawDiagnostics ExtendsAccess.java */ /*
--- a/langtools/test/tools/javac/FloatingPointChanges/BadConstructorModifiers.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/FloatingPointChanges/BadConstructorModifiers.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary strictfp may not be used with constructors * @author David Stoutamire (dps) * - * @compile/fail/ref=BadConstructorModifiers.out -XDrawDiagnostics -XDstdout BadConstructorModifiers.java + * @compile/fail/ref=BadConstructorModifiers.out -XDrawDiagnostics BadConstructorModifiers.java */ public class BadConstructorModifiers {
--- a/langtools/test/tools/javac/IllegalAnnotation.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/IllegalAnnotation.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary javac crash when declare an annotation type illegally * * @compile/fail IllegalAnnotation.java - * @compile/fail/ref=IllegalAnnotation.out -XDdev -XDrawDiagnostics -XDstdout IllegalAnnotation.java + * @compile/fail/ref=IllegalAnnotation.out -XDdev -XDrawDiagnostics IllegalAnnotation.java */ class IllegalAnnotation { {
--- a/langtools/test/tools/javac/InnerNamedConstant_2.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/InnerNamedConstant_2.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary Verify rejection of illegal static variables in inner classes. * @author William Maddox (maddox) * - * @compile/fail/ref=InnerNamedConstant_2.out -XDrawDiagnostics -XDstdout InnerNamedConstant_2.java + * @compile/fail/ref=InnerNamedConstant_2.out -XDrawDiagnostics InnerNamedConstant_2.java */ public class InnerNamedConstant_2 {
--- a/langtools/test/tools/javac/InterfaceMemberClassModifiers.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/InterfaceMemberClassModifiers.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary Verify that invalid access modifiers on interface members don't cause crash. * @author maddox * - * @compile/fail/ref=InterfaceMemberClassModifiers.out -XDstdout -XDdiags=%b:%l:%_%m InterfaceMemberClassModifiers.java + * @compile/fail/ref=InterfaceMemberClassModifiers.out -XDdiags=%b:%l:%_%m InterfaceMemberClassModifiers.java */ public interface InterfaceMemberClassModifiers {
--- a/langtools/test/tools/javac/LocalClasses_2.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/LocalClasses_2.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary Verify that a local class cannot be redefined within its scope. * @author William Maddox (maddox) * - * @compile/fail/ref=LocalClasses_2.out -XDrawDiagnostics -XDstdout LocalClasses_2.java + * @compile/fail/ref=LocalClasses_2.out -XDrawDiagnostics LocalClasses_2.java */ class LocalClasses_2 {
--- a/langtools/test/tools/javac/NameCollision.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/NameCollision.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary Interface names for classes in the same scope should not * cause the compiler to crash. * - * @compile/fail/ref=NameCollision.out -XDrawDiagnostics -XDstdout NameCollision.java + * @compile/fail/ref=NameCollision.out -XDrawDiagnostics NameCollision.java */ // The test fails if the compiler crashes.
--- a/langtools/test/tools/javac/NestedInnerClassNames.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/NestedInnerClassNames.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary Verify that an inner class cannot have the same simple name as an enclosing one. * @author William Maddox (maddox) * - * @compile/fail/ref=NestedInnerClassNames.out -XDrawDiagnostics -XDstdout NestedInnerClassNames.java + * @compile/fail/ref=NestedInnerClassNames.out -XDrawDiagnostics NestedInnerClassNames.java */ /*
--- a/langtools/test/tools/javac/NonStaticFieldExpr1.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/NonStaticFieldExpr1.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ @author dps @summary field: instance access through types is not allowed - @compile/fail/ref=NonStaticFieldExpr1.out -XDrawDiagnostics -XDstdout NonStaticFieldExpr1.java + @compile/fail/ref=NonStaticFieldExpr1.out -XDrawDiagnostics NonStaticFieldExpr1.java */ class NonStaticFieldExpr1 { public int x;
--- a/langtools/test/tools/javac/NonStaticFieldExpr2.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/NonStaticFieldExpr2.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ @author dps @summary method: instance access through types is not allowed - @compile/fail/ref=NonStaticFieldExpr2.out -XDrawDiagnostics -XDstdout NonStaticFieldExpr2.java + @compile/fail/ref=NonStaticFieldExpr2.out -XDrawDiagnostics NonStaticFieldExpr2.java */ class NonStaticFieldExpr2 {
--- a/langtools/test/tools/javac/NonStaticFieldExpr3.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/NonStaticFieldExpr3.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ @author dps @summary class: instance access through types is not allowed - @compile/fail/ref=NonStaticFieldExpr3.out -XDrawDiagnostics -XDstdout NonStaticFieldExpr3.java + @compile/fail/ref=NonStaticFieldExpr3.out -XDrawDiagnostics NonStaticFieldExpr3.java */ class NonStaticFieldExpr3 {
--- a/langtools/test/tools/javac/OverridePosition.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/OverridePosition.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary "attemping to assign weaker access" message doesn't give method line number * @author Neal Gafter * - * @compile/fail/ref=OverridePosition.out -XDstdout -XDrawDiagnostics OverridePosition.java + * @compile/fail/ref=OverridePosition.out -XDrawDiagnostics OverridePosition.java */ package T4524388;
--- a/langtools/test/tools/javac/QualifiedAccess/QualifiedAccess_1.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/QualifiedAccess/QualifiedAccess_1.java Mon Aug 02 19:46:14 2010 -0700 @@ -7,7 +7,7 @@ * * @compile pack1/P1.java * @compile pack1/P2.java - * @compile/fail/ref=QualifiedAccess_1.out -XDrawDiagnostics -XDstdout QualifiedAccess_1.java + * @compile/fail/ref=QualifiedAccess_1.out -XDrawDiagnostics QualifiedAccess_1.java */ import pack1.P1;
--- a/langtools/test/tools/javac/QualifiedAccess/QualifiedAccess_2.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/QualifiedAccess/QualifiedAccess_2.java Mon Aug 02 19:46:14 2010 -0700 @@ -7,7 +7,7 @@ * * @compile pack1/P1.java * @compile pack1/P2.java - * @compile/fail/ref=QualifiedAccess_2.out -XDrawDiagnostics -XDstdout QualifiedAccess_2.java + * @compile/fail/ref=QualifiedAccess_2.out -XDrawDiagnostics QualifiedAccess_2.java */ import pack1.P1;
--- a/langtools/test/tools/javac/QualifiedAccess/QualifiedAccess_3.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/QualifiedAccess/QualifiedAccess_3.java Mon Aug 02 19:46:14 2010 -0700 @@ -5,7 +5,7 @@ * the type to which a component member belongs be accessible in qualified * names. * - * @compile/fail/ref=QualifiedAccess_3.out -XDrawDiagnostics -XDstdout QualifiedAccess_3.java + * @compile/fail/ref=QualifiedAccess_3.out -XDrawDiagnostics QualifiedAccess_3.java */ import pack1.P1;
--- a/langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel1.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel1.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6827009 * @summary Check for case labels of different types. * @compile/fail -source 6 BadlyTypedLabel1.java - * @compile/fail/ref=BadlyTypedLabel1.out -XDstdout -XDrawDiagnostics BadlyTypedLabel1.java + * @compile/fail/ref=BadlyTypedLabel1.out -XDrawDiagnostics BadlyTypedLabel1.java */ class BadlyTypedLabel1 { String m(String s) {
--- a/langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel2.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel2.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6827009 * @summary Check for case lables of different types. * @compile/fail -source 6 BadlyTypedLabel2.java - * @compile/fail/ref=BadlyTypedLabel2.out -XDstdout -XDrawDiagnostics BadlyTypedLabel2.java + * @compile/fail/ref=BadlyTypedLabel2.out -XDrawDiagnostics BadlyTypedLabel2.java */ import static java.math.RoundingMode.*;
--- a/langtools/test/tools/javac/StringsInSwitch/NonConstantLabel.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/StringsInSwitch/NonConstantLabel.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6827009 * @summary Check for non-constant case labels. * @compile/fail -source 6 NonConstantLabel.java - * @compile/fail/ref=NonConstantLabel.out -XDstdout -XDrawDiagnostics NonConstantLabel.java + * @compile/fail/ref=NonConstantLabel.out -XDrawDiagnostics NonConstantLabel.java */ class NonConstantLabel { String m(String s) {
--- a/langtools/test/tools/javac/StringsInSwitch/RepeatedStringCaseLabels1.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/StringsInSwitch/RepeatedStringCaseLabels1.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6827009 * @summary Check for repeated string case labels. * @compile/fail -source 6 RepeatedStringCaseLabels1.java - * @compile/fail/ref=RSCL1.out -XDstdout -XDrawDiagnostics RepeatedStringCaseLabels1.java + * @compile/fail/ref=RSCL1.out -XDrawDiagnostics RepeatedStringCaseLabels1.java */ class RepeatedStringCaseLabels1 { String m(String s) {
--- a/langtools/test/tools/javac/StringsInSwitch/RepeatedStringCaseLabels2.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/StringsInSwitch/RepeatedStringCaseLabels2.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6827009 * @summary Check for repeated string case labels. * @compile/fail -source 6 RepeatedStringCaseLabels2.java - * @compile/fail/ref=RSCL2.out -XDstdout -XDrawDiagnostics RepeatedStringCaseLabels2.java + * @compile/fail/ref=RSCL2.out -XDrawDiagnostics RepeatedStringCaseLabels2.java */ class RepeatedStringCaseLabels2 { String m(String s) {
--- a/langtools/test/tools/javac/SynchronizedClass.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/SynchronizedClass.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ @summary Verify that ClassModifier "synchronized" is not allowed. @author dps - @compile/fail/ref=SynchronizedClass.out -XDrawDiagnostics -XDstdout SynchronizedClass.java + @compile/fail/ref=SynchronizedClass.out -XDrawDiagnostics SynchronizedClass.java */ public synchronized class SynchronizedClass { } // ERROR
--- a/langtools/test/tools/javac/T4093617/T4093617.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T4093617/T4093617.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 4093617 * @summary Object has no superclass * @author Peter von der Ah\u00e9 - * @compile/fail/ref=T4093617.out -XDstdout -XDrawDiagnostics T4093617.java + * @compile/fail/ref=T4093617.out -XDrawDiagnostics T4093617.java */ package java.lang;
--- a/langtools/test/tools/javac/T4906100.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T4906100.java Mon Aug 02 19:46:14 2010 -0700 @@ -2,7 +2,7 @@ * @test /nodynamiccopyright/ * @bug 4906100 * @summary detect empty statement after if - * @compile/ref=T4906100.out -XDstdout -XDrawDiagnostics -Xlint:empty T4906100.java + * @compile/ref=T4906100.out -XDrawDiagnostics -Xlint:empty T4906100.java */ class T4906100 {
--- a/langtools/test/tools/javac/T4994049/T4994049.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T4994049/T4994049.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 4994049 * @summary Improved diagnostics while parsing enums * @author Peter von der Ah\u00e9 - * @compile/fail/ref=T4994049.out -XDstdout -XDrawDiagnostics T4994049.java + * @compile/fail/ref=T4994049.out -XDrawDiagnostics T4994049.java */ public enum T4994049 {
--- a/langtools/test/tools/javac/T5003235/T5003235a.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T5003235/T5003235a.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 5003235 * @summary Private inner class accessible from subclasses * @author Peter von der Ah\u00e9 - * @compile/fail/ref=T5003235a.out -XDstdout -XDdiags=%b:%l:%_%m T5003235a.java + * @compile/fail/ref=T5003235a.out -XDdiags=%b:%l:%_%m T5003235a.java */ class Super {
--- a/langtools/test/tools/javac/T5003235/T5003235b.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T5003235/T5003235b.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 5003235 * @summary Accessibility of private inner class * @author Peter von der Ah\u00e9 - * @compile/fail/ref=T5003235b.out -XDstdout -XDdiags=%b:%l:%_%m T5003235b.java + * @compile/fail/ref=T5003235b.out -XDdiags=%b:%l:%_%m T5003235b.java */ class Outer {
--- a/langtools/test/tools/javac/T5003235/T5003235c.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T5003235/T5003235c.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 5003235 * @summary Access to private inner classes * @author Peter von der Ah\u00e9 - * @compile/fail/ref=T5003235c.out -XDstdout -XDrawDiagnostics T5003235c.java + * @compile/fail/ref=T5003235c.out -XDrawDiagnostics T5003235c.java */ class T5003235c {
--- a/langtools/test/tools/javac/T5024091/T5024091.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T5024091/T5024091.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 5024091 * @summary AssertionError shouldn't be thrown * @author Wei Tao - * @compile/fail/ref=T5024091.out -XDfailcomplete=java.lang.StringBuilder -XDdev -XDstdout -XDrawDiagnostics T5024091.java + * @compile/fail/ref=T5024091.out -XDfailcomplete=java.lang.StringBuilder -XDdev -XDrawDiagnostics T5024091.java */ public class T5024091 {
--- a/langtools/test/tools/javac/T5048776.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T5048776.java Mon Aug 02 19:46:14 2010 -0700 @@ -1,8 +1,8 @@ /* * @test /nodynamiccopyright/ * @bug 5048776 - * @compile/ref=T5048776a.out -XDstdout -XDrawDiagnostics T5048776.java - * @compile/ref=T5048776b.out -XDstdout -XDrawDiagnostics -Xlint:all,-path T5048776.java + * @compile/ref=T5048776a.out -XDrawDiagnostics T5048776.java + * @compile/ref=T5048776b.out -XDrawDiagnostics -Xlint:all,-path T5048776.java */ class A1 { void foo(Object[] args) { }
--- a/langtools/test/tools/javac/T6214885.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T6214885.java Mon Aug 02 19:46:14 2010 -0700 @@ -2,8 +2,8 @@ * @test /nodynamiccopyright/ * @bug 6214885 * @summary This test exercises features provided by the new internal Diagnostics API - * @compile/fail/ref=T6214885a.out -XDstdout -XDdiags=%b:%l%_%t%m|%p%m T6214885.java - * @compile/fail/ref=T6214885b.out -XDstdout -XDdiags=%b:%l:%c%_%t%m|%p%m T6214885.java + * @compile/fail/ref=T6214885a.out -XDdiags=%b:%l%_%t%m|%p%m T6214885.java + * @compile/fail/ref=T6214885b.out -XDdiags=%b:%l:%c%_%t%m|%p%m T6214885.java */ class T6214885 {
--- a/langtools/test/tools/javac/T6224167.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T6224167.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6224167 * @summary misleading error message when both array and varargs * methods are defined - * @compile/fail/ref=T6224167.out -XDstdout -XDrawDiagnostics T6224167.java + * @compile/fail/ref=T6224167.out -XDrawDiagnostics T6224167.java */ class T6224167 {
--- a/langtools/test/tools/javac/T6227617.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T6227617.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 6227617 * @summary Lint option for redundant casts * @compile -Werror T6227617.java - * @compile/ref=T6227617.out -XDstdout -XDrawDiagnostics -Xlint:cast T6227617.java + * @compile/ref=T6227617.out -XDrawDiagnostics -Xlint:cast T6227617.java */ import java.util.HashMap; import java.util.Map;
--- a/langtools/test/tools/javac/T6230128.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T6230128.java Mon Aug 02 19:46:14 2010 -0700 @@ -1,7 +1,7 @@ /* * @test /nodynamiccopyright/ * @bug 6230128 - * @compile/fail/ref=T6230128.out -XDstdout -XDrawDiagnostics T6230128.java + * @compile/fail/ref=T6230128.out -XDrawDiagnostics T6230128.java */ class A1 { public void foo(Object[] args) { }
--- a/langtools/test/tools/javac/T6231847.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T6231847.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary Crash in com.sun.tools.javac.comp.Attr.visitNewClass:1352 * @author Peter von der Ah\u00e9 * @compile/fail -XDdev T6231847.java - * @compile/fail/ref=T6231847.out -XDdev -XDrawDiagnostics -XDstdout T6231847.java + * @compile/fail/ref=T6231847.out -XDdev -XDrawDiagnostics T6231847.java */ class T6231847 {
--- a/langtools/test/tools/javac/T6241723.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T6241723.java Mon Aug 02 19:46:14 2010 -0700 @@ -2,7 +2,7 @@ * @test /nodynamiccopyright/ * @bug 6241723 * @summary compiler can miss some references to at-Deprecated classes - * @compile/fail/ref=T6241723.out -XDstdout -XDrawDiagnostics -Xlint:deprecation -Werror T6241723.java + * @compile/fail/ref=T6241723.out -XDrawDiagnostics -Xlint:deprecation -Werror T6241723.java */ @Deprecated class A1
--- a/langtools/test/tools/javac/T6245591.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T6245591.java Mon Aug 02 19:46:14 2010 -0700 @@ -1,7 +1,7 @@ /* * @test /nodynamiccopyright/ * @bug 6245591 - * @compile/ref=T6245591.out -XDstdout -XDrawDiagnostics -Xlint:all,-path T6245591.java + * @compile/ref=T6245591.out -XDrawDiagnostics -Xlint:all,-path T6245591.java */ enum Season { /** @deprecated */
--- a/langtools/test/tools/javac/T6247324.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T6247324.java Mon Aug 02 19:46:14 2010 -0700 @@ -1,7 +1,7 @@ /* * @test /nodynamiccopyright/ * @bug 6247324 - * @compile/fail/ref=T6247324.out -XDrawDiagnostics -XDstdout -Xlint -Xlint:-path T6247324.java + * @compile/fail/ref=T6247324.out -XDrawDiagnostics -Xlint -Xlint:-path T6247324.java */ class Pair<X,Y> { private X x;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/T6340549.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 6403456 + * @summary javax.tools.JavaCompilerTool.getStandardFileManager().list() includes directories + */ + +import javax.tools.*; +import java.util.*; +import java.io.*; + +import static javax.tools.JavaFileObject.Kind; + +public class T6340549 { + public static void main(String... args) throws Exception { + + // Ensure a directory exists + File dir = new File("temp" + args.hashCode()); + if (!dir.exists()) + dir.mkdir(); + if (!dir.isDirectory()) + throw new AssertionError("Not a directory " + dir); + + try { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null); + jfm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(new File("."))); + + for (JavaFileObject jfo : jfm.list(StandardLocation.CLASS_PATH, + "", EnumSet.of(Kind.OTHER), false)) { + if (new File(jfo.getName()).isDirectory()) { + throw new AssertionError("Found directory: " + jfo); + } + } + } finally { + dir.delete(); // cleanup + } + } +}
--- a/langtools/test/tools/javac/T6394563.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/T6394563.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,13 +3,13 @@ * @bug 6394563 * @summary javac ignores -nowarn switch in 1.5.0_06 for deprecation warnings * - * @compile/ref=T6394563.note.out -XDstdout -XDrawDiagnostics -nowarn T6394563.java - * @compile/ref=T6394563.note.out -XDstdout -XDrawDiagnostics -nowarn -source 1.5 T6394563.java - * @compile/ref=T6394563.empty.out -XDstdout -XDrawDiagnostics -nowarn -source 1.4 T6394563.java + * @compile/ref=T6394563.note.out -XDrawDiagnostics -nowarn T6394563.java + * @compile/ref=T6394563.note.out -XDrawDiagnostics -nowarn -source 1.5 T6394563.java + * @compile/ref=T6394563.empty.out -XDrawDiagnostics -nowarn -source 1.4 T6394563.java * - * @compile/ref=T6394563.warn.out -XDstdout -XDrawDiagnostics -Xlint -nowarn T6394563.java - * @compile/ref=T6394563.warn.out -XDstdout -XDrawDiagnostics -Xlint -nowarn -source 1.5 T6394563.java - * @compile/ref=T6394563.empty.out -XDstdout -XDrawDiagnostics -Xlint -nowarn -source 1.4 T6394563.java + * @compile/ref=T6394563.warn.out -XDrawDiagnostics -Xlint -nowarn T6394563.java + * @compile/ref=T6394563.warn.out -XDrawDiagnostics -Xlint -nowarn -source 1.5 T6394563.java + * @compile/ref=T6394563.empty.out -XDrawDiagnostics -Xlint -nowarn -source 1.4 T6394563.java */ class T6394563 {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/T6972327.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6972327 + * @summary JCTree.pos incorrect for annotations without modifiers and package + */ + +import com.sun.source.tree.*; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.*; +import com.sun.tools.javac.tree.*; +import com.sun.tools.javac.tree.JCTree.*; +import java.net.URI; +import java.util.Arrays; +import javax.tools.*; + +public class T6972327 { + + public static void main(String[] args) throws Exception { + final String bootPath = System.getProperty("sun.boot.class.path"); //NOI18N + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + assert tool != null; + + String code = "\n@interface Test {}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, + Arrays.asList("-bootclasspath", bootPath, "-Xjcov"), null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + Trees t = Trees.instance(ct); + + long pos = t.getSourcePositions().getStartPosition(cut, clazz); + if (pos != code.indexOf(code.trim())) + throw new IllegalStateException("Unexpected position=" + pos); + } + + static class MyFileObject extends SimpleJavaFileObject { + private String text; + + public MyFileObject(String text) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + this.text = text; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return text; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/ArmLint.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,55 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 6967065 + * @author Joseph D. Darcy + * @summary Check that -Xlint:arm warnings are generated as expected + * @compile/ref=ArmLint.out -Xlint:arm,deprecation -XDrawDiagnostics ArmLint.java + */ + +class ArmLint implements AutoCloseable { + private static void test1() { + try(ArmLint r1 = new ArmLint(); + ArmLint r2 = new ArmLint(); + ArmLint r3 = new ArmLint()) { + r1.close(); // The resource's close + r2.close(42); // *Not* the resource's close + // r3 not referenced + } + + } + + @SuppressWarnings("arm") + private static void test2() { + try(@SuppressWarnings("deprecation") AutoCloseable r4 = + new DeprecatedAutoCloseable()) { + // r4 not referenced + } catch(Exception e) { + ; + } + } + + /** + * The AutoCloseable method of a resource. + */ + @Override + public void close () { + return; + } + + /** + * <em>Not</em> the AutoCloseable method of a resource. + */ + public void close (int arg) { + return; + } +} + +@Deprecated +class DeprecatedAutoCloseable implements AutoCloseable { + public DeprecatedAutoCloseable(){super();} + + @Override + public void close () { + return; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/ArmLint.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,3 @@ +ArmLint.java:14:15: compiler.warn.twr.explicit.close.call +ArmLint.java:13:13: compiler.warn.automatic.resource.not.referenced: r3 +2 warnings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/BadTwr.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,36 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Verify bad TWRs don't compile + * @compile/fail -source 6 TwrFlow.java + * @compile/fail/ref=BadTwr.out -XDrawDiagnostics BadTwr.java + */ + +public class BadTwr implements AutoCloseable { + public static void main(String... args) { + // illegal repeated name + try(BadTwr r1 = new BadTwr(); BadTwr r1 = new BadTwr()) { + System.out.println(r1.toString()); + } + + // illegal duplicate name of method argument + try(BadTwr args = new BadTwr()) { + System.out.println(args.toString()); + final BadTwr thatsIt = new BadTwr(); + thatsIt = null; + } + + try(BadTwr name = new BadTwr()) { + // illegal duplicate name of enclosing try + try(BadTwr name = new BadTwr()) { + System.out.println(name.toString()); + } + } + + } + + public void close() { + ; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/BadTwr.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,5 @@ +BadTwr.java:13:39: compiler.err.already.defined: r1, main(java.lang.String...) +BadTwr.java:18:13: compiler.err.already.defined: args, main(java.lang.String...) +BadTwr.java:21:13: compiler.err.cant.assign.val.to.final.var: thatsIt +BadTwr.java:26:17: compiler.err.already.defined: name, main(java.lang.String...) +4 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,22 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Verify bad TWRs don't compile + * @compile/fail -source 6 BadTwrSyntax.java + * @compile/fail/ref=BadTwrSyntax.out -XDrawDiagnostics BadTwrSyntax.java + */ + +import java.io.IOException; +public class BadTwrSyntax implements AutoCloseable { + public static void main(String... args) throws Exception { + // illegal semicolon ending resources + try(BadTwr twrflow = new BadTwr();) { + System.out.println(twrflow.toString()); + } + } + + public void close() { + ; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,2 @@ +BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.expr +1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/DuplicateResource.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Check that lowered arm block does not end up creating resource twice + */ + +import java.util.ArrayList; + +public class DuplicateResource { + + static class TestResource implements AutoCloseable { + TestResource() { + resources.add(this); + } + boolean isClosed = false; + public void close() throws Exception { + isClosed = true; + } + } + + static ArrayList<TestResource> resources = new ArrayList<TestResource>(); + + public static void main(String[] args) { + try(new TestResource()) { + //do something + } catch (Exception e) { + throw new AssertionError("Shouldn't reach here", e); + } + check(); + } + + public static void check() { + if (resources.size() != 1) { + throw new AssertionError("Expected one resource, found: " + resources.size()); + } + TestResource resource = resources.get(0); + if (!resource.isClosed) { + throw new AssertionError("Resource used in ARM block has not been automatically closed"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,20 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Check that resource variable is not accessible from catch/finally clause + * @compile/fail/ref=DuplicateResourceDecl.out -XDrawDiagnostics DuplicateResourceDecl.java + */ + +class DuplicateResourceDecl { + + public static void main(String[] args) { + try(MyResource c = new MyResource();MyResource c = new MyResource()) { + //do something + } catch (Exception e) { } + } + + static class MyResource implements AutoCloseable { + public void close() throws Exception {} + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,2 @@ +DuplicateResourceDecl.java:12:45: compiler.err.already.defined: c, main(java.lang.String[]) +1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/ImplicitFinal.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,27 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Test that resource variables are implicitly final + * @compile/fail/ref=ImplicitFinal.out -XDrawDiagnostics ImplicitFinal.java + */ + +import java.io.IOException; + +class ImplicitFinal implements AutoCloseable { + public static void main(String... args) { + try(ImplicitFinal r = new ImplicitFinal()) { + r = null; //disallowed + } catch (IOException ioe) { // Not reachable + throw new AssertionError("Shouldn't reach here", ioe); + } + } + + + // A close method, but the class is <em>not</em> Closeable or + // AutoCloseable. + + public void close() throws IOException { + throw new IOException(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/ImplicitFinal.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,2 @@ +ImplicitFinal.java:14:13: compiler.err.twr.resource.may.not.be.assigned: r +1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/PlainTry.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Test error messages for an unadorned try + * @compile/fail/ref=PlainTry6.out -XDrawDiagnostics -source 6 PlainTry.java + * @compile/fail/ref=PlainTry.out -XDrawDiagnostics PlainTry.java + */ +public class PlainTry { + public static void main(String... args) { + try { + ; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/PlainTry.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,2 @@ +PlainTry.java:11:9: compiler.err.try.without.catch.finally.or.resource.decls +1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/PlainTry6.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,2 @@ +PlainTry.java:11:9: compiler.err.try.without.catch.or.finally +1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/ResourceInterface.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6970833 + * @author Maurizio Cimadamore + * @summary Try-with-resource implementation throws an NPE during Flow analysis + * @compile/fail/ref=ResourceInterface.out -XDrawDiagnostics ResourceInterface.java + */ + +class ResourceInterface { + public void test1() { + try(Resource1 r1 = null) { } + } + + public void test2() { + try(Resource2 r2 = null) { } + } + + static class E1 extends Exception {} + + static class E2 extends Exception {} + + + interface C1 extends AutoCloseable { + void close() throws E1; + } + + interface C2 extends AutoCloseable { + void close() throws E2; + } + + interface C3 extends AutoCloseable { + void close() throws E2, E1; + } + + static interface Resource1 extends C1, C2 {} + + static interface Resource2 extends C1, C3 {} +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/ResourceInterface.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,2 @@ +ResourceInterface.java:38:34: compiler.err.unreported.exception.need.to.catch.or.throw: ResourceInterface.E1 +1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,23 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Check that resource variable is not accessible from catch/finally clause + * @compile/fail/ref=ResourceOutsideTry.out -XDrawDiagnostics ResourceOutsideTry.java + */ + +class ResourceOutsideTry { + void test() { + try(MyResource c = new MyResource()) { + //do something + } catch (Exception e) { + c.test(); + } finally { + c.test(); + } + } + static class MyResource implements AutoCloseable { + public void close() throws Exception {} + void test() {} + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,3 @@ +ResourceOutsideTry.java:14:13: compiler.err.cant.resolve.location: kindname.variable, c, , , kindname.class, ResourceOutsideTry +ResourceOutsideTry.java:16:13: compiler.err.cant.resolve.location: kindname.variable, c, , , kindname.class, ResourceOutsideTry +2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/ResourceTypeVar.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Resource of a type-variable type crashes Flow + * @compile ResourceTypeVar.java + */ + +class ResourceTypeVar<X extends AutoCloseable> { + + public void test() { + try(X armflow = getX()) { + //do something + } catch (Exception e) { // Not reachable + throw new AssertionError("Shouldn't reach here", e); + } + } + + X getX() { return null; } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrFlow.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,39 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Test exception analysis of ARM blocks + * @compile/fail/ref=TwrFlow.out -XDrawDiagnostics TwrFlow.java + */ + +import java.io.IOException; +public class TwrFlow implements AutoCloseable { + public static void main(String... args) { + try(TwrFlow armflow = new TwrFlow()) { + System.out.println(armflow.toString()); + } catch (IOException ioe) { // Not reachable + throw new AssertionError("Shouldn't reach here", ioe); + } + // CustomCloseException should be caught or added to throws clause + + // Also check behavior on a resource expression rather than a + // declaration. + TwrFlow armflowexpr = new TwrFlow(); + try(armflowexpr) { + System.out.println(armflowexpr.toString()); + } catch (IOException ioe) { // Not reachable + throw new AssertionError("Shouldn't reach here", ioe); + } + // CustomCloseException should be caught or added to throws clause + } + + /* + * A close method, but the class is <em>not</em> Closeable or + * AutoCloseable. + */ + public void close() throws CustomCloseException { + throw new CustomCloseException(); + } +} + +class CustomCloseException extends Exception {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrFlow.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,5 @@ +TwrFlow.java:14:11: compiler.err.except.never.thrown.in.try: java.io.IOException +TwrFlow.java:24:11: compiler.err.except.never.thrown.in.try: java.io.IOException +TwrFlow.java:12:46: compiler.err.unreported.exception.need.to.catch.or.throw: CustomCloseException +TwrFlow.java:22:26: compiler.err.unreported.exception.need.to.catch.or.throw: CustomCloseException +4 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrInference.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Verify that method type-inference works as expected in TWR context + * @compile TwrInference.java + */ + +class TwrInference { + + public void test() { + try(getX()) { + //do something + } catch (Exception e) { // Not reachable + throw new AssertionError("Shouldn't reach here", e); + } + } + + <X> X getX() { return null; } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrIntersection.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Resource of an intersection type crashes Flow + * @compile TwrIntersection.java + */ + +interface MyCloseable extends AutoCloseable { + void close() throws java.io.IOException; +} + +class ResourceTypeVar { + + public void test() { + try(getX()) { + //do something + } catch (java.io.IOException e) { // Not reachable + throw new AssertionError("Shouldn't reach here", e); + } + } + + <X extends Number & MyCloseable> X getX() { return null; } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrIntersection02.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,37 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Check that resources of an intersection type forces union of exception types + * to be caught outside twr block + * @compile/fail/ref=TwrIntersection02.out -XDrawDiagnostics TwrIntersection02.java + */ + +class TwrIntersection02 { + + static class Exception1 extends Exception {} + static class Exception2 extends Exception {} + + + interface MyResource1 extends AutoCloseable { + void close() throws Exception1; + } + + interface MyResource2 extends AutoCloseable { + void close() throws Exception2; + } + + public void test1() throws Exception1 { + try(getX()) { + //do something + } + } + + public void test2() throws Exception2 { + try(getX()) { + //do something + } + } + + <X extends MyResource1 & MyResource2> X getX() { return null; } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrIntersection02.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,3 @@ +TwrIntersection02.java:25:21: compiler.err.unreported.exception.need.to.catch.or.throw: TwrIntersection02.Exception2 +TwrIntersection02.java:31:21: compiler.err.unreported.exception.need.to.catch.or.throw: TwrIntersection02.Exception1 +2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrMultiCatch.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Test that TWR and multi-catch play well together + * @compile TwrMultiCatch.java + * @run main TwrMultiCatch + */ + +import java.io.IOException; +public class TwrMultiCatch implements AutoCloseable { + private final Class<? extends Exception> exceptionClass; + + private TwrMultiCatch(Class<? extends Exception> exceptionClass) { + this.exceptionClass = exceptionClass; + } + + public static void main(String... args) { + test(new TwrMultiCatch(CustomCloseException1.class), + CustomCloseException1.class); + + test(new TwrMultiCatch(CustomCloseException2.class), + CustomCloseException2.class); + } + + private static void test(TwrMultiCatch twrMultiCatch, + Class<? extends Exception> expected) { + try(twrMultiCatch) { + System.out.println(twrMultiCatch.toString()); + } catch (final CustomCloseException1 | + CustomCloseException2 exception) { + if (!exception.getClass().equals(expected) ) { + throw new RuntimeException("Unexpected catch!"); + } + } + } + + public void close() throws CustomCloseException1, CustomCloseException2 { + Throwable t; + try { + t = exceptionClass.newInstance(); + } catch(ReflectiveOperationException rfe) { + throw new RuntimeException(rfe); + } + + try { + throw t; + } catch (final CustomCloseException1 | + CustomCloseException2 exception) { + throw exception; + } catch (Throwable throwable) { + throw new RuntimeException(throwable); + } + } +} + +class CustomCloseException1 extends Exception {} +class CustomCloseException2 extends Exception {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,42 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Verify invalid TWR block is not accepted. + * @compile/fail -source 6 TwrOnNonResource.java + * @compile/fail/ref=TwrOnNonResource.out -XDrawDiagnostics TwrOnNonResource.java + */ + +class TwrOnNonResource { + public static void main(String... args) { + try(TwrOnNonResource aonr = new TwrOnNonResource()) { + System.out.println(aonr.toString()); + } + try(TwrOnNonResource aonr = new TwrOnNonResource()) { + System.out.println(aonr.toString()); + } finally {;} + try(TwrOnNonResource aonr = new TwrOnNonResource()) { + System.out.println(aonr.toString()); + } catch (Exception e) {;} + + // Also check expression form + TwrOnNonResource aonr = new TwrOnNonResource(); + try(aonr) { + System.out.println(aonr.toString()); + } + try(aonr) { + System.out.println(aonr.toString()); + } finally {;} + try(aonr) { + System.out.println(aonr.toString()); + } catch (Exception e) {;} + } + + /* + * A close method, but the class is <em>not</em> Closeable or + * AutoCloseable. + */ + public void close() { + throw new AssertionError("I'm not Closable!"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,7 @@ +TwrOnNonResource.java:12:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:15:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:18:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:24:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:27:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:30:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +6 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrSuppression.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6971877 + * @author Joseph D. Darcy + * @summary Verify a primary exception suppresses all throwables + */ + +public class TwrSuppression implements AutoCloseable { + public static void main(String... args) throws Throwable { + try { + try (TwrSuppression r1 = new TwrSuppression(false); + TwrSuppression r2 = new TwrSuppression(true)) { + throw new RuntimeException(); + } + } catch(RuntimeException e) { + Throwable[] suppressedExceptions = e.getSuppressedExceptions(); + int length = suppressedExceptions.length; + if (length != 2) + throw new RuntimeException("Unexpected length " + length); + + if (suppressedExceptions[0].getClass() != Error.class || + suppressedExceptions[1].getClass() != Exception.class) { + System.err.println("Unexpected suppressed types!"); + e.printStackTrace(); + throw new RuntimeException(e); + } + } + } + + private boolean throwError; + + private TwrSuppression(boolean throwError) { + this.throwError = throwError; + } + + @Override + public void close() throws Exception { + if (throwError) { + throw new Error(); + } else { + throw new Exception(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/TwrTests.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,742 @@ +/* + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6911256 6964740 + * @summary Tests of generated TWR code. + */ + +import java.util.List; +import java.util.ArrayList; + +public class TwrTests { + public static void main(String[] args) { + testCreateFailure1(); + testCreateFailure2(); + testCreateFailure2Nested(); + testCreateFailure3(); + testCreateFailure3Nested(); + testCreateFailure4(); + testCreateFailure4Nested(); + testCreateFailure5(); + testCreateFailure5Nested(); + + testCreateSuccess1(); + testCreateSuccess2(); + testCreateSuccess2Nested(); + testCreateSuccess3(); + testCreateSuccess3Nested(); + testCreateSuccess4(); + testCreateSuccess4Nested(); + testCreateSuccess5(); + testCreateSuccess5Nested(); + } + + /* + * The following tests simulate a creation failure of every possible + * resource in an TWR block, and check to make sure that the failure + * prevents creation of subsequent resources, and that all created + * resources are properly closed, even if one or more of the close + * attempts fails. + */ + + public static void testCreateFailure1() { + int creationFailuresDetected = 0; + List<Integer> closedList = new ArrayList<Integer>(0); + try (Resource r0 = createResource(0, 0, 0, closedList)) { + throw new AssertionError("Resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + if (e.resourceId() != 0) { + throw new AssertionError("Wrong resource creation " + + e.resourceId() + " failed"); + } + } catch (Resource.CloseFailException e) { + throw new AssertionError("Unexpected CloseFailException: " + e.resourceId()); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, 0); + } + + public static void testCreateFailure2() { + for (int createFailureId = 0; createFailureId < 2; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList); + Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed"); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure2Nested() { + for (int createFailureId = 0; createFailureId < 2; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) { + try(Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed"); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure3() { + for (int createFailureId = 0; createFailureId < 3; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList); + Resource r1 = createResource(1, createFailureId, bitMap, closedList); + Resource r2 = createResource(2, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure3Nested() { + for (int createFailureId = 0; createFailureId < 3; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) { + try (Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + try (Resource r2 = createResource(2, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } + } + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure4() { + for (int createFailureId = 0; createFailureId < 4; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList); + Resource r1 = createResource(1, createFailureId, bitMap, closedList); + Resource r2 = createResource(2, createFailureId, bitMap, closedList); + Resource r3 = createResource(3, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure4Nested() { + for (int createFailureId = 0; createFailureId < 4; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) { + try (Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + try (Resource r2 = createResource(2, createFailureId, bitMap, closedList)) { + try (Resource r3 = createResource(3, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } + } + } + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure5() { + for (int createFailureId = 0; createFailureId < 5; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList); + Resource r1 = createResource(1, createFailureId, bitMap, closedList); + Resource r2 = createResource(2, createFailureId, bitMap, closedList); + Resource r3 = createResource(3, createFailureId, bitMap, closedList); + Resource r4 = createResource(4, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure5Nested() { + for (int createFailureId = 0; createFailureId < 5; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) { + try (Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + try (Resource r2 = createResource(2, createFailureId, bitMap, closedList)) { + try (Resource r3 = createResource(3, createFailureId, bitMap, closedList)) { + try (Resource r4 = createResource(4, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } + } + } + } + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + /** + * Create a resource with the specified ID. The ID must be less than createFailureId. + * A subsequent attempt to close the resource will fail iff the corresponding bit + * is set in closeFailureBitMap. When an attempt is made to close this resource, + * its ID will be added to closedList, regardless of whether the attempt succeeds. + * + * @param id the ID of this resource + * @param createFailureId the ID of the resource whose creation will fail + * @param closeFailureBitMap a bit vector describing which resources should throw an + * exception when close is attempted + * @param closedList a list on which to record resource close attempts + * @throws AssertionError if no attempt should be made to create this resource + */ + private static Resource createResource(int id, + int createFailureId, + int closeFailureBitMap, + List<Integer> closedList) throws Resource.CreateFailException { + if (id > createFailureId) + throw new AssertionError("Resource " + id + " shouldn't be created"); + boolean createSucceeds = id != createFailureId; + boolean closeSucceeds = (closeFailureBitMap & (1 << id)) == 0; + return new Resource(id, createSucceeds, closeSucceeds, closedList); + } + + + /** + * Check that an observed creation failure has the expected resource ID. + * + * @param foundId the ID of the resource whose creation failed + * @param expectedId the ID of the resource whose creation should have failed + */ + private static void checkCreateFailureId(int foundId, int expectedId) { + if (foundId != expectedId) + throw new AssertionError("Wrong resource creation failed. Found ID " + + foundId + " expected " + expectedId); + } + + /** + * Check for proper suppressed exceptions in proper order. + * + * @param suppressedExceptions the suppressed exceptions array returned by + * getSuppressedExceptions() + * @bitmap a bitmap indicating which suppressed exceptions are expected. + * Bit i is set iff id should throw a CloseFailException. + */ + private static void checkSuppressedExceptions(Throwable[] suppressedExceptions, int bitMap) { + if (suppressedExceptions.length != Integer.bitCount(bitMap)) + throw new AssertionError("Expected " + Integer.bitCount(bitMap) + + " suppressed exceptions, got " + suppressedExceptions.length); + + int prevCloseFailExceptionId = Integer.MAX_VALUE; + for (Throwable t : suppressedExceptions) { + int id = ((Resource.CloseFailException) t).resourceId(); + if ((1 << id & bitMap) == 0) + throw new AssertionError("Unexpected suppressed CloseFailException: " + id); + if (id > prevCloseFailExceptionId) + throw new AssertionError("Suppressed CloseFailException" + id + + " followed " + prevCloseFailExceptionId); + } + } + + /** + * Check that exactly one resource creation failed. + * + * @param numCreationFailuresDetected the number of creation failures detected + */ + private static void checkForSingleCreationFailure(int numCreationFailuresDetected) { + if (numCreationFailuresDetected != 1) + throw new AssertionError("Wrong number of creation failures: " + + numCreationFailuresDetected); + } + + /** + * Check that a close was attempted on every resourced that was successfully opened, + * and that the close attempts occurred in the proper order. + * + * @param closedList the resource IDs of the close attempts, in the order they occurred + * @param the ID of the resource whose creation failed. Close attempts should occur + * for all previous resources, in reverse order. + */ + private static void checkClosedList(List<Integer> closedList, int createFailureId) { + List<Integer> expectedList = new ArrayList<Integer>(createFailureId); + for (int i = createFailureId - 1; i >= 0; i--) + expectedList.add(i); + if (!closedList.equals(expectedList)) + throw new AssertionError("Closing sequence " + closedList + " != " + expectedList); + } + + /* + * The following tests simulate the creation of several resources, followed + * by success or failure of forward processing. They test that all resources + * are properly closed, even if one or more of the close attempts fails. + */ + + public static void testCreateSuccess1() { + for (int bitMap = 0, n = 1 << 1; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 1); + } + } + } + + public static void testCreateSuccess2() { + for (int bitMap = 0, n = 1 << 2; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, bitMap, closedList); + Resource r1 = createResource(1, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 2); + } + } + } + + public static void testCreateSuccess2Nested() { + for (int bitMap = 0, n = 1 << 2; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + try (Resource r1 = createResource(1, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 2); + } + } + } + + public static void testCreateSuccess3() { + for (int bitMap = 0, n = 1 << 3; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, bitMap, closedList); + Resource r1 = createResource(1, bitMap, closedList); + Resource r2 = createResource(2, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 3); + } + } + } + + public static void testCreateSuccess3Nested() { + for (int bitMap = 0, n = 1 << 3; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + try (Resource r1 = createResource(1, bitMap, closedList)) { + try (Resource r2 = createResource(2, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } + } + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 3); + } + } + } + + public static void testCreateSuccess4() { + for (int bitMap = 0, n = 1 << 4; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, bitMap, closedList); + Resource r1 = createResource(1, bitMap, closedList); + Resource r2 = createResource(2, bitMap, closedList); + Resource r3 = createResource(3, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 4); + } + } + } + + public static void testCreateSuccess4Nested() { + for (int bitMap = 0, n = 1 << 4; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + try (Resource r1 = createResource(1, bitMap, closedList)) { + try (Resource r2 = createResource(2, bitMap, closedList)) { + try (Resource r3 = createResource(3, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } + } + } + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 4); + } + } + } + + public static void testCreateSuccess5() { + for (int bitMap = 0, n = 1 << 5; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, bitMap, closedList); + Resource r1 = createResource(1, bitMap, closedList); + Resource r2 = createResource(2, bitMap, closedList); + Resource r3 = createResource(3, bitMap, closedList); + Resource r4 = createResource(4, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError("Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 5); + } + } + } + + public static void testCreateSuccess5Nested() { + for (int bitMap = 0, n = 1 << 5; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List<Integer> closedList = new ArrayList<Integer>(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + try (Resource r1 = createResource(1, bitMap, closedList)) { + try (Resource r2 = createResource(2, bitMap, closedList)) { + try (Resource r3 = createResource(3, bitMap, closedList)) { + try (Resource r4 = createResource(4, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } + } + } + } + } catch (Resource.CreateFailException e) { + throw new AssertionError("Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 5); + } + } + } + + private static Resource createResource(int id, + int closeFailureBitMap, + List<Integer> closedList) throws Resource.CreateFailException { + boolean closeSucceeds = (closeFailureBitMap & (1 << id)) == 0; + return new Resource(id, true, closeSucceeds, closedList); + } + + private static class MyKindOfException extends Exception { + } +} + +class Resource implements AutoCloseable { + /** A number identifying this resource */ + private final int resourceId; + + /** Whether the close call on this resource should succeed or fail */ + private final boolean closeSucceeds; + + /** When resource is closed, it records its ID in this list */ + private final List<Integer> closedList; + + Resource(int resourceId, boolean createSucceeds, boolean closeSucceeds, + List<Integer> closedList) throws CreateFailException { + if (!createSucceeds) + throw new CreateFailException(resourceId); + this.resourceId = resourceId; + this.closeSucceeds = closeSucceeds; + this.closedList = closedList; + } + + public void close() throws CloseFailException { + closedList.add(resourceId); + if (!closeSucceeds) + throw new CloseFailException(resourceId); + } + + public static class ResourceException extends RuntimeException { + private final int resourceId; + + public ResourceException(int resourceId) { + super("Resource ID = " + resourceId); + this.resourceId = resourceId; + } + + public int resourceId() { + return resourceId; + } + } + + public static class CreateFailException extends ResourceException { + public CreateFailException(int resourceId) { + super(resourceId); + } + } + + public static class CloseFailException extends ResourceException { + public CloseFailException(int resourceId) { + super(resourceId); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/WeirdTwr.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Strange TWRs + * @compile/fail -source 6 WeirdTwr.java + * @compile WeirdTwr.java + * @run main WeirdTwr + */ + +public class WeirdTwr implements AutoCloseable { + private static int closeCount = 0; + public static void main(String... args) { + try(WeirdTwr r1 = new WeirdTwr(); WeirdTwr r2 = r1) { + if (r1 != r2) + throw new RuntimeException("Unexpected inequality."); + } + if (closeCount != 2) + throw new RuntimeException("bad closeCount" + closeCount); + } + + public void close() { + closeCount++; + } +}
--- a/langtools/test/tools/javac/annotations/6214965/T6214965.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/annotations/6214965/T6214965.java Mon Aug 02 19:46:14 2010 -0700 @@ -27,5 +27,5 @@ * @summary Compiler crash on redefing nested annotation types * @compile CompilerAnnotationTest.java CompilerAnnotationTest2.java * @compile CompilerAnnotationTest2bad.java - * @compile/ref=T6214965.out -XDstdout -XDrawDiagnostics CompilerAnnotationTest2bad.java + * @compile/ref=T6214965.out -XDrawDiagnostics CompilerAnnotationTest2bad.java */
--- a/langtools/test/tools/javac/annotations/6365854/T6365854.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/annotations/6365854/T6365854.java Mon Aug 02 19:46:14 2010 -0700 @@ -33,11 +33,11 @@ * * @compile TestAnnotation.java TestCore.java * @clean test.annotation.TestAnnotation - * @compile/ref=test1.out -XDstdout -XDrawDiagnostics T6365854.java + * @compile/ref=test1.out -XDrawDiagnostics T6365854.java * @run main T6365854 - * @compile/ref=test2.out -XDstdout -XDrawDiagnostics evolve/TestAnnotation.java T6365854.java + * @compile/ref=test2.out -XDrawDiagnostics evolve/TestAnnotation.java T6365854.java * @run main T6365854 - * @compile/ref=test2.out -XDstdout -XDrawDiagnostics T6365854.java + * @compile/ref=test2.out -XDrawDiagnostics T6365854.java * @run main T6365854 */
--- a/langtools/test/tools/javac/danglingDep/DepX.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/danglingDep/DepX.java Mon Aug 02 19:46:14 2010 -0700 @@ -25,7 +25,7 @@ * control test (2): verify that compiler handles at-deprecated correctly * @test * @clean X DepX refX - * @compile/ref=DepX.out -XDstdout -XDrawDiagnostics DepX.java RefX.java + * @compile/ref=DepX.out -XDrawDiagnostics DepX.java RefX.java */ class DepX {
--- a/langtools/test/tools/javac/danglingDep/NoDepX.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/danglingDep/NoDepX.java Mon Aug 02 19:46:14 2010 -0700 @@ -25,7 +25,7 @@ * control test (1): verify that compiler handles (lack of) at-deprecated correctly * @test * @clean NoDepX X RefX - * @compile/ref=NoDepX.out -XDstdout -XDrawDiagnostics NoDepX.java RefX.java + * @compile/ref=NoDepX.out -XDrawDiagnostics NoDepX.java RefX.java */ class NoDepX {
--- a/langtools/test/tools/javac/danglingDep/Test1.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/danglingDep/Test1.java Mon Aug 02 19:46:14 2010 -0700 @@ -25,7 +25,7 @@ * @test * @bug 6213430 * @clean Test1 X RefX - * @compile/ref=Test1.out -XDstdout -XDrawDiagnostics Test1.java RefX.java + * @compile/ref=Test1.out -XDrawDiagnostics Test1.java RefX.java */ class Test1 {
--- a/langtools/test/tools/javac/depDocComment/DeprecatedDocComment.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/depDocComment/DeprecatedDocComment.java Mon Aug 02 19:46:14 2010 -0700 @@ -6,7 +6,7 @@ * @author Jing Qian * * @compile DeprecatedDocComment2.java - * @compile/fail/ref=DeprecatedDocComment.out -XDrawDiagnostics -XDstdout -Werror -deprecation DeprecatedDocComment.java + * @compile/fail/ref=DeprecatedDocComment.out -XDrawDiagnostics -Werror -deprecation DeprecatedDocComment.java */ // WARNING: This file needs to be compiled with the -deprecation flag on.
--- a/langtools/test/tools/javac/depDocComment/SuppressDeprecation.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/depDocComment/SuppressDeprecation.java Mon Aug 02 19:46:14 2010 -0700 @@ -4,7 +4,7 @@ * @summary New rules for when deprecation messages are suppressed * @author gafter * - * @compile/ref=SuppressDeprecation.out -XDstdout -Xlint:deprecation -XDrawDiagnostics SuppressDeprecation.java + * @compile/ref=SuppressDeprecation.out -Xlint:deprecation -XDrawDiagnostics SuppressDeprecation.java */ /* Test for the contexts in which deprecations warnings should
--- a/langtools/test/tools/javac/depOverrides/annotation/Test1.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/depOverrides/annotation/Test1.java Mon Aug 02 19:46:14 2010 -0700 @@ -26,12 +26,12 @@ * @bug 5086088 * @summary check warnings generated when overriding deprecated methods * - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation I.java - * @compile/ref=Test1A.out -XDstdout -XDrawDiagnostics -Xlint:deprecation A.java - * @compile/ref=Test1B.out -XDstdout -XDrawDiagnostics -Xlint:deprecation B.java - * @compile/ref=Test1B2.out -XDstdout -XDrawDiagnostics -Xlint:deprecation B2.java - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation B3.java - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation Test1.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation I.java + * @compile/ref=Test1A.out -XDrawDiagnostics -Xlint:deprecation A.java + * @compile/ref=Test1B.out -XDrawDiagnostics -Xlint:deprecation B.java + * @compile/ref=Test1B2.out -XDrawDiagnostics -Xlint:deprecation B2.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation B3.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation Test1.java */
--- a/langtools/test/tools/javac/depOverrides/annotation/Test2.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/depOverrides/annotation/Test2.java Mon Aug 02 19:46:14 2010 -0700 @@ -26,10 +26,10 @@ * @bug 5086088 * @summary check warnings generated when overriding deprecated methods * - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation P.java - * @compile/ref=Test2Q.out -XDstdout -XDrawDiagnostics -Xlint:deprecation Q.java - * @compile/ref=Test2R.out -XDstdout -XDrawDiagnostics -Xlint:deprecation R.java - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation Test2.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation P.java + * @compile/ref=Test2Q.out -XDrawDiagnostics -Xlint:deprecation Q.java + * @compile/ref=Test2R.out -XDrawDiagnostics -Xlint:deprecation R.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation Test2.java */
--- a/langtools/test/tools/javac/depOverrides/annotation/Test3.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/depOverrides/annotation/Test3.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 5086088 * @summary check warnings generated when overriding deprecated methods * - * @compile/ref=Test3.out -XDstdout -XDrawDiagnostics -Xlint:deprecation Test3.java + * @compile/ref=Test3.out -XDrawDiagnostics -Xlint:deprecation Test3.java */ interface LibInterface {
--- a/langtools/test/tools/javac/depOverrides/doccomment/Test1.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/depOverrides/doccomment/Test1.java Mon Aug 02 19:46:14 2010 -0700 @@ -26,12 +26,12 @@ * @bug 5086088 * @summary check warnings generated when overriding deprecated methods * - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation I.java - * @compile/ref=Test1A.out -XDstdout -XDrawDiagnostics -Xlint:deprecation A.java - * @compile/ref=Test1B.out -XDstdout -XDrawDiagnostics -Xlint:deprecation B.java - * @compile/ref=Test1B2.out -XDstdout -XDrawDiagnostics -Xlint:deprecation B2.java - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation B3.java - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation Test1.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation I.java + * @compile/ref=Test1A.out -XDrawDiagnostics -Xlint:deprecation A.java + * @compile/ref=Test1B.out -XDrawDiagnostics -Xlint:deprecation B.java + * @compile/ref=Test1B2.out -XDrawDiagnostics -Xlint:deprecation B2.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation B3.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation Test1.java */
--- a/langtools/test/tools/javac/depOverrides/doccomment/Test2.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/depOverrides/doccomment/Test2.java Mon Aug 02 19:46:14 2010 -0700 @@ -26,10 +26,10 @@ * @bug 5086088 * @summary check warnings generated when overriding deprecated methods * - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation P.java - * @compile/ref=Test2Q.out -XDstdout -XDrawDiagnostics -Xlint:deprecation Q.java - * @compile/ref=Test2R.out -XDstdout -XDrawDiagnostics -Xlint:deprecation R.java - * @compile/ref=empty -XDstdout -XDrawDiagnostics -Xlint:deprecation Test2.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation P.java + * @compile/ref=Test2Q.out -XDrawDiagnostics -Xlint:deprecation Q.java + * @compile/ref=Test2R.out -XDrawDiagnostics -Xlint:deprecation R.java + * @compile/ref=empty -XDrawDiagnostics -Xlint:deprecation Test2.java */
--- a/langtools/test/tools/javac/depOverrides/doccomment/Test3.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/depOverrides/doccomment/Test3.java Mon Aug 02 19:46:14 2010 -0700 @@ -3,7 +3,7 @@ * @bug 5086088 * @summary check warnings generated when overriding deprecated methods * - * @compile/ref=Test3.out -XDstdout -XDrawDiagnostics -Xlint:deprecation Test3.java + * @compile/ref=Test3.out -XDrawDiagnostics -Xlint:deprecation Test3.java */ interface LibInterface {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/CheckExamples.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6968063 + * @summary provide examples of code that generate diagnostics + * @build Example CheckExamples + * @run main CheckExamples + */ + +import java.io.*; +import java.util.*; + +/** + * Check invariants for a set of examples. + * -- each example should exactly declare the keys that will be generated when + * it is run. + * -- together, the examples should cover the set of resource keys in the + * compiler.properties bundle. A list of exceptions may be given in the + * not-yet.txt file. Entries on the not-yet.txt list should not be + * covered by examples. + * When new keys are added to the resource buncle, it is strongly recommended + * that corresponding new examples be added here, if at all practical, instead + * of simply and lazily being added to the not-yet.txt list. + */ +public class CheckExamples { + /** + * Standard entry point. + */ + public static void main(String... args) throws Exception { + new CheckExamples().run(); + } + + /** + * Run the test. + */ + void run() throws Exception { + Set<Example> examples = getExamples(); + + Set<String> notYetList = getNotYetList(); + Set<String> declaredKeys = new TreeSet<String>(); + for (Example e: examples) { + Set<String> e_decl = e.getDeclaredKeys(); + Set<String> e_actual = e.getActualKeys(); + for (String k: e_decl) { + if (!e_actual.contains(k)) + error("Example " + e + " declares key " + k + " but does not generate it"); + } + for (String k: e_actual) { + if (!e_decl.contains(k)) + error("Example " + e + " generates key " + k + " but does not declare it"); + } + for (String k: e.getDeclaredKeys()) { + if (notYetList.contains(k)) + error("Example " + e + " declares key " + k + " which is also on the \"not yet\" list"); + declaredKeys.add(k); + } + } + + ResourceBundle b = + ResourceBundle.getBundle("com.sun.tools.javac.resources.compiler"); + Set<String> resourceKeys = new TreeSet<String>(b.keySet()); + + for (String dk: declaredKeys) { + if (!resourceKeys.contains(dk)) + error("Key " + dk + " is declared in tests but is not a valid key in resource bundle"); + } + + for (String nk: notYetList) { + if (!resourceKeys.contains(nk)) + error("Key " + nk + " is declared in not-yet list but is not a valid key in resource bundle"); + } + + for (String rk: resourceKeys) { + if (!declaredKeys.contains(rk) && !notYetList.contains(rk)) + error("Key " + rk + " is declared in resource bundle but is not in tests or not-yet list"); + } + + System.err.println(examples.size() + " examples checked"); + System.err.println(notYetList.size() + " keys on not-yet list"); + + Counts declaredCounts = new Counts(declaredKeys); + Counts resourceCounts = new Counts(resourceKeys); + List<String> rows = new ArrayList<String>(Arrays.asList(Counts.prefixes)); + rows.add("other"); + rows.add("total"); + System.err.println(); + System.err.println(String.format("%-14s %15s %15s %4s", + "prefix", "#keys in tests", "#keys in javac", "%")); + for (String p: rows) { + int d = declaredCounts.get(p); + int r = resourceCounts.get(p); + System.err.print(String.format("%-14s %15d %15d", p, d, r)); + if (r != 0) + System.err.print(String.format(" %3d%%", (d * 100) / r)); + System.err.println(); + } + + if (errors > 0) + throw new Exception(errors + " errors occurred."); + } + + /** + * Get the complete set of examples to be checked. + */ + Set<Example> getExamples() { + Set<Example> results = new TreeSet<Example>(); + File testSrc = new File(System.getProperty("test.src")); + File examples = new File(testSrc, "examples"); + for (File f: examples.listFiles()) { + if (f.isDirectory() || f.isFile() && f.getName().endsWith(".java")) + results.add(new Example(f)); + } + return results; + } + + /** + * Get the contents of the "not-yet" list. + */ + Set<String> getNotYetList() { + Set<String> results = new TreeSet<String>(); + File testSrc = new File(System.getProperty("test.src")); + File notYetList = new File(testSrc, "examples.not-yet.txt"); + try { + String[] lines = read(notYetList).split("[\r\n]"); + for (String line: lines) { + int hash = line.indexOf("#"); + if (hash != -1) + line = line.substring(0, hash).trim(); + if (line.matches("[A-Za-z0-9-_.]+")) + results.add(line); + } + } catch (IOException e) { + throw new Error(e); + } + return results; + } + + /** + * Read the contents of a file. + */ + String read(File f) throws IOException { + byte[] bytes = new byte[(int) f.length()]; + DataInputStream in = new DataInputStream(new FileInputStream(f)); + try { + in.readFully(bytes); + } finally { + in.close(); + } + return new String(bytes); + } + + /** + * Report an error. + */ + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; + + static class Counts { + static String[] prefixes = { + "compiler.err.", + "compiler.warn.", + "compiler.note.", + "compiler.misc." + }; + + Counts(Set<String> keys) { + nextKey: + for (String k: keys) { + for (String p: prefixes) { + if (k.startsWith(p)) { + inc(p); + continue nextKey; + } + } + inc("other"); + } + table.put("total", keys.size()); + } + + int get(String p) { + Integer i = table.get(p); + return (i == null ? 0 : i); + } + + void inc(String p) { + Integer i = table.get(p); + table.put(p, (i == null ? 1 : i + 1)); + } + + Map<String,Integer> table = new HashMap<String,Integer>(); + }; +}
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java Wed Jul 05 17:19:00 2017 +0200 +++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java Mon Aug 02 19:46:14 2010 -0700 @@ -294,6 +294,7 @@ Set<String> results = new TreeSet<String>(); JavaCompiler c = ToolProvider.getSystemJavaCompiler(); JavaFileManager fm = c.getStandardFileManager(null, null, null); + JavaFileManager.Location javacLoc = findJavacLocation(fm); String[] pkgs = { "javax.annotation.processing", "javax.lang.model", @@ -302,7 +303,7 @@ "com.sun.tools.javac" }; for (String pkg: pkgs) { - for (JavaFileObject fo: fm.list(StandardLocation.PLATFORM_CLASS_PATH, + for (JavaFileObject fo: fm.list(javacLoc, pkg, EnumSet.of(JavaFileObject.Kind.CLASS), true)) { String name = fo.getName(); // ignore resource files, and files which are not really part of javac @@ -316,6 +317,23 @@ return results; } + // depending on how the test is run, javac may be on bootclasspath or classpath + JavaFileManager.Location findJavacLocation(JavaFileManager fm) { + JavaFileManager.Location[] locns = + { StandardLocation.PLATFORM_CLASS_PATH, StandardLocation.CLASS_PATH }; + try { + for (JavaFileManager.Location l: locns) { + JavaFileObject fo = fm.getJavaFileForInput(l, + "com.sun.tools.javac.Main", JavaFileObject.Kind.CLASS); + if (fo != null) + return l; + } + } catch (IOException e) { + throw new Error(e); + } + throw new IllegalStateException("Cannot find javac"); + } + /** * Get the set of strings from a class file. * Only strings that look like they might be a resource key are returned.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/Example.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.javac.file.JavacFileManager; +import java.io.*; +import java.util.*; +import java.util.regex.*; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +// The following two classes are both used, but cannot be imported directly +// import com.sun.tools.javac.Main +// import com.sun.tools.javac.main.Main + +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.JavacMessages; +import com.sun.tools.javac.util.JCDiagnostic; +import java.net.URL; +import java.net.URLClassLoader; +import javax.annotation.processing.Processor; + +/** + * Class to handle example code designed to illustrate javac diagnostic messages. + */ +class Example implements Comparable<Example> { + /* Create an Example from the files found at path. + * The head of the file, up to the first Java code, is scanned + * for information about the test, such as what resource keys it + * generates when run, what options are required to run it, and so on. + */ + Example(File file) { + this.file = file; + declaredKeys = new TreeSet<String>(); + srcFiles = new ArrayList<File>(); + procFiles = new ArrayList<File>(); + supportFiles = new ArrayList<File>(); + srcPathFiles = new ArrayList<File>(); + + findFiles(file, srcFiles); + for (File f: srcFiles) { + parse(f); + } + + if (infoFile == null) + throw new Error("Example " + file + " has no info file"); + } + + private void findFiles(File f, List<File> files) { + if (f.isDirectory()) { + for (File c: f.listFiles()) { + if (files == srcFiles && c.getName().equals("processors")) + findFiles(c, procFiles); + else if (files == srcFiles && c.getName().equals("sourcepath")) { + srcPathDir = c; + findFiles(c, srcPathFiles); + } else if (files == srcFiles && c.getName().equals("support")) + findFiles(c, supportFiles); + else + findFiles(c, files); + } + } else if (f.isFile() && f.getName().endsWith(".java")) { + files.add(f); + } + } + + private void parse(File f) { + Pattern keyPat = Pattern.compile(" *// *key: *([^ ]+) *"); + Pattern optPat = Pattern.compile(" *// *options: *(.*)"); + Pattern runPat = Pattern.compile(" *// *run: *(.*)"); + Pattern javaPat = Pattern.compile(" *@?[A-Za-z].*"); + try { + String[] lines = read(f).split("[\r\n]+"); + for (String line: lines) { + Matcher keyMatch = keyPat.matcher(line); + if (keyMatch.matches()) { + foundInfo(f); + declaredKeys.add(keyMatch.group(1)); + continue; + } + Matcher optMatch = optPat.matcher(line); + if (optMatch.matches()) { + foundInfo(f); + options = Arrays.asList(optMatch.group(1).trim().split(" +")); + continue; + } + Matcher runMatch = runPat.matcher(line); + if (runMatch.matches()) { + foundInfo(f); + runOpts = Arrays.asList(runMatch.group(1).trim().split(" +")); + } + if (javaPat.matcher(line).matches()) + break; + } + } catch (IOException e) { + throw new Error(e); + } + } + + private void foundInfo(File file) { + if (infoFile != null && !infoFile.equals(file)) + throw new Error("multiple info files found: " + infoFile + ", " + file); + infoFile = file; + } + + String getName() { + return file.getName(); + } + + /** + * Get the set of resource keys that this test declares it will generate + * when it is run. + */ + Set<String> getDeclaredKeys() { + return declaredKeys; + } + + /** + * Get the set of resource keys that this test generates when it is run. + * The test will be run if it has not already been run. + */ + Set<String> getActualKeys() { + if (actualKeys == null) + actualKeys = run(false); + return actualKeys; + } + + /** + * Run the test. Information in the test header is used to determine + * how to run the test. + */ + void run(PrintWriter out, boolean raw, boolean verbose) { + if (out == null) + throw new NullPointerException(); + try { + run(out, null, raw, verbose); + } catch (IOException e) { + e.printStackTrace(out); + } + } + + Set<String> run(boolean verbose) { + Set<String> keys = new TreeSet<String>(); + try { + run(null, keys, true, verbose); + } catch (IOException e) { + e.printStackTrace(); + } + return keys; + } + + /** + * Run the test. Information in the test header is used to determine + * how to run the test. + */ + private void run(PrintWriter out, Set<String> keys, boolean raw, boolean verbose) + throws IOException { + ClassLoader loader = getClass().getClassLoader(); + if (supportFiles.size() > 0) { + File supportDir = new File(tempDir, "support"); + supportDir.mkdirs(); + clean(supportDir); + List<String> sOpts = Arrays.asList("-d", supportDir.getPath()); + new Jsr199Compiler(verbose).run(null, null, false, sOpts, procFiles); + URLClassLoader ucl = + new URLClassLoader(new URL[] { supportDir.toURI().toURL() }, loader); + loader = ucl; + } + + File classesDir = new File(tempDir, "classes"); + classesDir.mkdirs(); + clean(classesDir); + + List<String> opts = new ArrayList<String>(); + opts.add("-d"); + opts.add(classesDir.getPath()); + if (options != null) + opts.addAll(options); + + if (procFiles.size() > 0) { + List<String> pOpts = Arrays.asList("-d", classesDir.getPath()); + new Jsr199Compiler(verbose).run(null, null, false, pOpts, procFiles); + opts.add("-classpath"); // avoid using -processorpath for now + opts.add(classesDir.getPath()); + createAnnotationServicesFile(classesDir, procFiles); + } + + if (srcPathDir != null) { + opts.add("-sourcepath"); + opts.add(srcPathDir.getPath()); + } + + try { + Compiler c = Compiler.getCompiler(runOpts, verbose); + c.run(out, keys, raw, opts, srcFiles); + } catch (IllegalArgumentException e) { + if (out != null) { + out.println("Invalid value for run tag: " + runOpts); + } + } + } + + void createAnnotationServicesFile(File dir, List<File> procFiles) throws IOException { + File servicesDir = new File(new File(dir, "META-INF"), "services"); + servicesDir.mkdirs(); + File annoServices = new File(servicesDir, Processor.class.getName()); + Writer out = new FileWriter(annoServices); + try { + for (File f: procFiles) { + out.write(f.getName().toString().replace(".java", "")); + } + } finally { + out.close(); + } + } + + @Override + public int compareTo(Example e) { + return file.compareTo(e.file); + } + + @Override + public String toString() { + return file.getPath(); + } + + /** + * Read the contents of a file. + */ + private String read(File f) throws IOException { + byte[] bytes = new byte[(int) f.length()]; + DataInputStream in = new DataInputStream(new FileInputStream(f)); + try { + in.readFully(bytes); + } finally { + in.close(); + } + return new String(bytes); + } + + /** + * Clean the contents of a directory. + */ + boolean clean(File dir) { + boolean ok = true; + for (File f: dir.listFiles()) { + if (f.isDirectory()) + ok &= clean(f); + ok &= f.delete(); + } + return ok; + } + + File file; + List<File> srcFiles; + List<File> procFiles; + File srcPathDir; + List<File> srcPathFiles; + List<File> supportFiles; + File infoFile; + private List<String> runOpts; + private List<String> options; + private Set<String> actualKeys; + private Set<String> declaredKeys; + + static File tempDir = new File(System.getProperty("java.io.tmpdir")); + static void setTempDir(File tempDir) { + Example.tempDir = tempDir; + } + + abstract static class Compiler { + static Compiler getCompiler(List<String> opts, boolean verbose) { + String first; + String[] rest; + if (opts == null || opts.size() == 0) { + first = null; + rest = new String[0]; + } else { + first = opts.get(0); + rest = opts.subList(1, opts.size()).toArray(new String[opts.size() - 1]); + } + if (first == null || first.equals("jsr199")) + return new Jsr199Compiler(verbose, rest); + else if (first.equals("simple")) + return new SimpleCompiler(verbose); + else if (first.equals("backdoor")) + return new BackdoorCompiler(verbose); + else + throw new IllegalArgumentException(first); + } + + protected Compiler(boolean verbose) { + this.verbose = verbose; + } + + abstract boolean run(PrintWriter out, Set<String> keys, boolean raw, + List<String> opts, List<File> files); + + void setSupportClassLoader(ClassLoader cl) { + loader = cl; + } + + protected ClassLoader loader; + protected boolean verbose; + } + + /** + * Compile using the JSR 199 API. The diagnostics generated are + * scanned for resource keys. Not all diagnostic keys are generated + * via the JSR 199 API -- for example, rich diagnostics are not directly + * accessible, and some diagnostics generated by the file manager may + * not be generated (for example, the JSR 199 file manager does not see + * -Xlint:path). + */ + static class Jsr199Compiler extends Compiler { + List<String> fmOpts; + + Jsr199Compiler(boolean verbose, String... args) { + super(verbose); + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-filemanager") && (i + 1 < args.length)) { + fmOpts = Arrays.asList(args[++i].split(",")); + } else + throw new IllegalArgumentException(arg); + } + } + + @Override + boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) { + if (out != null && keys != null) + throw new IllegalArgumentException(); + + if (verbose) + System.err.println("run_jsr199: " + opts + " " + files); + + DiagnosticCollector<JavaFileObject> dc = null; + if (keys != null) + dc = new DiagnosticCollector<JavaFileObject>(); + + if (raw) { + List<String> newOpts = new ArrayList<String>(); + newOpts.add("-XDrawDiagnostics"); + newOpts.addAll(opts); + opts = newOpts; + } + + JavaCompiler c = ToolProvider.getSystemJavaCompiler(); + + StandardJavaFileManager fm = c.getStandardFileManager(dc, null, null); + if (fmOpts != null) + fm = new FileManager(fm, fmOpts); + + Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files); + + CompilationTask t = c.getTask(out, fm, dc, opts, null, fos); + Boolean ok = t.call(); + + if (keys != null) { + for (Diagnostic<? extends JavaFileObject> d: dc.getDiagnostics()) { + scanForKeys((JCDiagnostic) d, keys); + } + } + + return ok; + } + + /** + * Scan a diagnostic for resource keys. This will not detect additional + * sub diagnostics that might be generated by a rich diagnostic formatter. + */ + private static void scanForKeys(JCDiagnostic d, Set<String> keys) { + keys.add(d.getCode()); + for (Object o: d.getArgs()) { + if (o instanceof JCDiagnostic) { + scanForKeys((JCDiagnostic) o, keys); + } + } + for (JCDiagnostic sd: d.getSubdiagnostics()) + scanForKeys(d, keys); + } + } + + /** + * Run the test using the standard simple entry point. + */ + static class SimpleCompiler extends Compiler { + SimpleCompiler(boolean verbose) { + super(verbose); + } + + @Override + boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) { + if (out != null && keys != null) + throw new IllegalArgumentException(); + + if (verbose) + System.err.println("run_simple: " + opts + " " + files); + + List<String> args = new ArrayList<String>(opts); + + if (keys != null || raw) + args.add("-XDrawDiagnostics"); + + args.addAll(opts); + for (File f: files) + args.add(f.getPath()); + + StringWriter sw = null; + PrintWriter pw; + if (keys != null) { + sw = new StringWriter(); + pw = new PrintWriter(sw); + } else + pw = out; + + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); + + if (keys != null) { + pw.close(); + scanForKeys(sw.toString(), keys); + } + + return (rc == 0); + } + + private static void scanForKeys(String text, Set<String> keys) { + StringTokenizer st = new StringTokenizer(text, " ,\r\n():"); + while (st.hasMoreElements()) { + String t = st.nextToken(); + if (t.startsWith("compiler.")) + keys.add(t); + } + } + } + + static class BackdoorCompiler extends Compiler { + BackdoorCompiler(boolean verbose) { + super(verbose); + } + + @Override + boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) { + if (out != null && keys != null) + throw new IllegalArgumentException(); + + if (verbose) + System.err.println("run_simple: " + opts + " " + files); + + List<String> args = new ArrayList<String>(opts); + + if (out != null && raw) + args.add("-XDrawDiagnostics"); + + args.addAll(opts); + for (File f: files) + args.add(f.getPath()); + + StringWriter sw = null; + PrintWriter pw; + if (keys != null) { + sw = new StringWriter(); + pw = new PrintWriter(sw); + } else + pw = out; + + Context c = new Context(); + JavacFileManager.preRegister(c); // can't create it until Log has been set up + MessageTracker.preRegister(c, keys); + com.sun.tools.javac.main.Main m = new com.sun.tools.javac.main.Main("javac", pw); + int rc = m.compile(args.toArray(new String[args.size()]), c); + + if (keys != null) { + pw.close(); + } + + return (rc == 0); + } + + static class MessageTracker extends JavacMessages { + + MessageTracker(Context context) { + super(context); + } + + static void preRegister(final Context c, final Set<String> keys) { + if (keys != null) { + c.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() { + public JavacMessages make() { + return new MessageTracker(c) { + @Override + public String getLocalizedString(Locale l, String key, Object... args) { + keys.add(key); + return super.getLocalizedString(l, key, args); + } + }; + } + }); + } + } + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/FileManager.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.NestingKind; +import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.tools.javac.api.WrappingJavaFileManager; + +/** + * A JavaFileManager that can throw IOException on attempting to read or write + * selected files that match a regular expression. + */ +public class FileManager + extends WrappingJavaFileManager<StandardJavaFileManager> + implements StandardJavaFileManager { + private static final String CANT_READ = "cantRead:"; + private static final String CANT_WRITE = "cantWrite:"; + + private Pattern cantRead; + private Pattern cantWrite; + + public FileManager(StandardJavaFileManager fm, List<String> opts) { + super(fm); + for (String opt: opts) { + if (opt.startsWith(CANT_READ)) + cantRead = Pattern.compile(opt.substring(CANT_READ.length())); + else if (opt.startsWith(CANT_WRITE)) + cantWrite = Pattern.compile(opt.substring(CANT_WRITE.length())); + else + throw new IllegalArgumentException(opt); + } + } + + @Override + protected JavaFileObject wrap(JavaFileObject fo) { + return new WrappedFileObject(fo); + } + + @Override + protected JavaFileObject unwrap(JavaFileObject fo) { + if (fo instanceof WrappedFileObject) + return ((WrappedFileObject) fo).delegate; + else + return fo; + } + + public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) { + return wrap2(fileManager.getJavaFileObjectsFromFiles(files)); + } + + public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) { + return wrap2(fileManager.getJavaFileObjects(files)); + } + + public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) { + return wrap2(fileManager.getJavaFileObjectsFromStrings(names)); + } + + public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) { + return wrap2(fileManager.getJavaFileObjects(names)); + } + + /* This method is regrettably necessary because WrappingJavaFileManager.wrap takes + * Iterable<JavaFileObject> fileObjects + * instead of + * Iterable<? extends JavaFileObject> fileObjects + */ + protected Iterable<JavaFileObject> wrap2(Iterable<? extends JavaFileObject> fileObjects) { + List<JavaFileObject> mapped = new ArrayList<JavaFileObject>(); + for (JavaFileObject fileObject : fileObjects) + mapped.add(wrap(fileObject)); + return Collections.unmodifiableList(mapped); + } + + public void setLocation(Location location, Iterable<? extends File> path) throws IOException { + fileManager.setLocation(location, path); + } + + public Iterable<? extends File> getLocation(Location location) { + return fileManager.getLocation(location); + } + + class WrappedFileObject implements JavaFileObject { + WrappedFileObject(JavaFileObject fileObject) { + delegate = fileObject; + } + + public Kind getKind() { + return delegate.getKind(); + } + + public boolean isNameCompatible(String simpleName, Kind kind) { + return delegate.isNameCompatible(simpleName, kind); + } + + public NestingKind getNestingKind() { + return delegate.getNestingKind(); + } + + public Modifier getAccessLevel() { + return delegate.getAccessLevel(); + } + + public URI toUri() { + return delegate.toUri(); + } + + public String getName() { + return delegate.getName(); + } + + public InputStream openInputStream() throws IOException { + checkRead(); + return delegate.openInputStream(); + } + + public OutputStream openOutputStream() throws IOException { + checkWrite(); + return delegate.openOutputStream(); + } + + public Reader openReader(boolean ignoreEncodingErrors) throws IOException { + checkRead(); + return delegate.openReader(ignoreEncodingErrors); + } + + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + checkRead(); + return delegate.getCharContent(ignoreEncodingErrors); + } + + public Writer openWriter() throws IOException { + checkWrite(); + return delegate.openWriter(); + } + + public long getLastModified() { + return delegate.getLastModified(); + } + + public boolean delete() { + return delegate.delete(); + } + + void checkRead() throws IOException { + if (cantRead != null && cantRead.matcher(getName()).matches()) + throw new IOException("FileManager: Can't read"); + } + + void checkWrite() throws IOException { + if (cantWrite != null && cantWrite.matcher(getName()).matches()) + throw new IOException("FileManager: Can't write"); + } + + JavaFileObject delegate; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/HTMLWriter.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,582 @@ +/* + * Copyright (c) 1996,2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.net.URL; +import java.text.MessageFormat; +import java.util.ResourceBundle; + +/** + * A class to facilitate writing HTML via a stream. + */ +public class HTMLWriter +{ + /** + * Create an HTMLWriter object, using a default doctype for HTML 3.2. + * @param out a Writer to which to write the generated HTML + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out) throws IOException { + this(out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">"); + } + + /** + * Create an HTMLWriter object, using a specifed doctype header. + * @param out a Writer to which to write the generated HTML + * @param docType a string containing a doctype header for the HTML to be generetaed + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out, String docType) throws IOException { + if (out instanceof BufferedWriter) + this.out = (BufferedWriter) out; + else + this.out = new BufferedWriter(out); + this.out.write(docType); + this.out.newLine(); + } + + /** + * Create an HTMLWriter object, using a specified bundle for localizing messages. + * @param out a Writer to which to write the generated HTML + * @param i18n a resource bundle to use to localize messages + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out, ResourceBundle i18n) throws IOException { + this(out); + this.i18n = i18n; + } + + + /** + * Create an HTMLWriter object, using a specifed doctype header and + * using a specified bundle for l0calizing messages. + * @param out a Writer to which to write the generated HTML + * @param docType a string containing a doctype header for the HTML to be generetaed + * @param i18n a resource bundle to use to localize messages + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out, String docType, ResourceBundle i18n) throws IOException { + this(out, docType); + this.i18n = i18n; + } + + /** + * Set the reource bundle to be used for localizing messages. + * @param i18n the resource bundle to be used for localizing messages + */ + public void setResourceBundle(ResourceBundle i18n) { + this.i18n = i18n; + } + + /** + * Flush the stream, and the underlying output stream. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void flush() throws IOException { + out.flush(); + } + + /** + * Close the stream, and the underlying output stream. + * @throws IOException if there is a problem closing the underlying stream + */ + public void close() throws IOException { + out.close(); + } + + /** + * Write a newline to the underlying output stream. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void newLine() throws IOException { + out.newLine(); + } + + /** + * Start an HTML tag. If a prior tag has been started, it will + * be closed first. Once a tag has been opened, attributes for the + * tag may be written out, followed by body content before finally + * ending the tag. + * @param tag the tag to be started + * @throws IOException if there is a problem writing to the underlying stream + * @see #writeAttr + * @see #write + * @see #endTag + */ + public void startTag(String tag) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + } + //newLine(); + out.write("<"); + out.write(tag); + state = IN_TAG; + } + + /** + * Finish an HTML tag. It is expected that a call to endTag will match + * a corresponding earlier call to startTag, but there is no formal check + * for this. + * @param tag the tag to be closed. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void endTag(String tag) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + out.newLine(); + } + out.write("</"); + out.write(tag); + out.write(">"); + //out.newLine(); // PATCHED, jjg + state = IN_BODY; + } + + /** + * Finish an empty element tag, such as a META, BASE or LINK tag. + * This is expected to correspond with a startTag. + * @param tag the tag which is being closed. this is only useful for + * validation, it is not written out + * @throws IllegalStateException if this call does not follow startTag + * (stream is not currently inside a tag) + * @throws IOException if there is a problem writing to the underlying stream + */ + public void endEmptyTag(String tag) throws IOException { + if (state != IN_TAG) + throw new IllegalStateException(); + + out.write(">"); + state = IN_BODY; + out.newLine(); + } + + /** + * Write an attribute for a tag. A tag must previously have been started. + * All tag attributes must be written before any body text is written. + * The value will be quoted if necessary when writing it to the underlying + * stream. No check is made that the attribute is valid for the current tag. + * @param name the name of the attribute to be written + * @param value the value of the attribute to be written + * @throws IllegalStateException if the stream is not in a state to + * write attributes -- e.g. if this call does not follow startTag or other + * calls of writteAttr + * @throws IOException if there is a problem writing to the underlying stream + */ + public void writeAttr(String name, String value) throws IOException { + if (state != IN_TAG) + throw new IllegalStateException(); + + out.write(" "); + out.write(name); + out.write("="); + boolean alpha = true; + for (int i = 0; i < value.length() && alpha; i++) + alpha = Character.isLetter(value.charAt(i)); + if (!alpha) + out.write("\""); + out.write(value); + if (!alpha) + out.write("\""); + } + + /** + * Write an attribute for a tag. A tag must previously have been started. + * All tag attributes must be written before any body text is written. + * The value will be quoted if necessary when writing it to the underlying + * stream. No check is made that the attribute is valid for the current tag. + * @param name the name of the attribute to be written + * @param value the value of the attribute to be written + * @throws IllegalStateException if the stream is not in a state to + * write attributes -- e.g. if this call does not follow startTag or other + * calls of writteAttr + * @throws IOException if there is a problem writing to the underlying stream + */ + public void writeAttr(String name, int value) throws IOException { + writeAttr(name, Integer.toString(value)); + } + + /** + * Write a line of text, followed by a newline. + * The text will be escaped as necessary. + * @param text the text to be written. + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLine(String text) throws IOException { + write(text); + out.newLine(); + } + + /** + * Write body text, escaping it as necessary. + * If this call follows a call of startTag, the open tag will be + * closed -- meaning that no more attributes can be written until another + * tag is started. If the text value is null, the current tag will still + * be closed, but no other text will be written. + * @param text the text to be written, may be null or zero length. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void write(String text) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + } + + if (text == null) + return; + + // check to see if there are any special characters + boolean specialChars = false; + for (int i = 0; i < text.length() && !specialChars; i++) { + switch (text.charAt(i)) { + case '<': case '>': case '&': + specialChars = true; + } + } + + // if there are special characters write the string character at a time; + // otherwise, write it out as is + if (specialChars) { + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + switch (c) { + case '<': out.write("<"); break; + case '>': out.write(">"); break; + case '&': out.write("&"); break; + default: out.write(c); + } + } + } + else + out.write(text); + } + + /** + * Write a basic HTML entity, such as or { . + * @param entity the entity to write + * @throws IOException if there is a problem writing to the underlying stream + */ + public void writeEntity(String entity) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + } + out.write(entity); + } + + /** + * Write an image tag, using a specified path for the image source attribute. + * @param imagePath the path for the image source + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeImage(String imagePath) throws IOException { + startTag(IMAGE); + writeAttr(SRC, imagePath); + } + + /** + * Write an image tag, using a specified path for the image source attribute. + * @param imageURL the url for the image source + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeImage(URL imageURL) throws IOException { + writeImage(imageURL.toString()); + } + + /** + * Write a hypertext link. + * @param anchor the target for the link + * @param body the body text for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(String anchor, String body) throws IOException { + startTag(A); + writeAttr(HREF, anchor); + write(body); + endTag(A); + } + + /** + * Write a hypertext link. + * @param file the target for the link + * @param body the body text for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(File file, String body) throws IOException { + startTag(A); + StringBuffer sb = new StringBuffer(); + String path = file.getPath().replace(File.separatorChar, '/'); + if (file.isAbsolute() && !path.startsWith("/")) + sb.append('/'); + sb.append(path); + writeAttr(HREF, sb.toString()); + write(body); + endTag(A); + } + + /** + * Write a hypertext link. + * @param file the target and body for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(File file) throws IOException { + writeLink(file, file.getPath()); + } + + /** + * Write a hypertext link. + * @param url the target for the link + * @param body the body text for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(URL url, String body) throws IOException { + startTag(A); + writeAttr(HREF, url.toString()); + write(body); + endTag(A); + } + + /** + * Write the destination marker for a hypertext link. + * @param anchor the destination marker for hypertext links + * @param body the body text for the marker + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLinkDestination(String anchor, String body) throws IOException { + startTag(A); + writeAttr(NAME, anchor); + write(body); + endTag(A); + } + + /** + * Write a parameter tag. + * @param name the name of the parameter + * @param value the value of the parameter + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeParam(String name, String value) throws IOException { + startTag(PARAM); + writeAttr(NAME, name); + writeAttr(VALUE, value); + } + + /** + * Write a style attribute. + * @param value the value for the style atrtribute + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeStyleAttr(String value) throws IOException { + writeAttr(STYLE, value); + } + + /** + * Write a localized message, using a specified resource bundle. + * @param i18n the resource bundle used to localize the message + * @param key the key for the message to be localized + * @throws IOException if there is a problem closing the underlying stream + */ + public void write(ResourceBundle i18n, String key) throws IOException { + write(getString(i18n, key)); + } + + /** + * Write a localized message, using a specified resource bundle. + * @param i18n the resource bundle used to localize the message + * @param key the key for the message to be localized + * @param arg an argument to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void write(ResourceBundle i18n, String key, Object arg) throws IOException { + write(getString(i18n, key, arg)); + } + + /** + * Write a localized message, using a specified resource bundle. + * @param i18n the resource bundle used to localize the message + * @param key the key for the message to be localized + * @param args arguments to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void write(ResourceBundle i18n, String key, Object[] args) throws IOException { + write(getString(i18n, key, args)); + } + + /** + * Write a localized message, using the default resource bundle. + * @param key the key for the message to be localized + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeI18N(String key) throws IOException { + write(getString(i18n, key)); + } + + /** + * Write a localized message, using the default resource bundle. + * @param key the key for the message to be localized + * @param arg an argument to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeI18N(String key, Object arg) throws IOException { + write(getString(i18n, key, arg)); + } + + /** + * Write a localized message, using the default resource bundle. + * @param key the key for the message to be localized + * @param args arguments to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeI18N(String key, Object[] args) throws IOException { + write(getString(i18n, key, args)); + } + + private String getString(ResourceBundle rb, String key, Object... args) { + String s = rb.getString(key); + return MessageFormat.format(s, args); + } + + /** The HTML "a" tag. */ + public static final String A = "a"; + /** The HTML "align" attribute. */ + public static final String ALIGN = "align"; + /** The HTML "b" tag. */ + public static final String B = "b"; + /** The HTML "body" tag. */ + public static final String BODY = "body"; + /** The HTML "border" attribute. */ + public static final String BORDER = "border"; + /** The HTML "br" tag. */ + public static final String BR = "br"; + /** The HTML "class" attribute. */ + public static final String CLASS = "class"; + /** The HTML "classid" attribute. */ + public static final String CLASSID = "classid"; + /** The HTML "code" tag. */ + public static final String CODE = "code"; + /** The HTML "color" attribte. */ + public static final String COLOR = "color"; + /** The HTML "col" attribute value. */ + public static final String COL = "col"; + /** The HTML "dd" tag. */ + public static final String DD = "dd"; + /** The HTML "div" tag. */ + public static final String DIV = "div"; + /** The HTML "dl" tag. */ + public static final String DL = "dl"; + /** The HTML "dt" tag. */ + public static final String DT = "dt"; + /** The HTML "font" tag. */ + public static final String FONT = "font"; + /** The HTML "h1" tag. */ + public static final String H1 = "h1"; + /** The HTML "h2" tag. */ + public static final String H2 = "h2"; + /** The HTML "h3" tag. */ + public static final String H3 = "h3"; + /** The HTML "h4" tag. */ + public static final String H4 = "h4"; + /** The HTML "h5" tag. */ + public static final String H5 = "h5"; + /** The HTML "head" tag. */ + public static final String HEAD = "head"; + /** The HTML "href" attribute. */ + public static final String HREF = "href"; + /** The HTML "html" tag. */ + public static final String HTML = "html"; + /** The HTML "hr" tag. */ + public static final String HR = "hr"; + /** The HTML "i" tag. */ + public static final String I = "i"; + /** The HTML "id" tag. */ + public static final String ID = "id"; + /** The HTML "image" tag. */ + public static final String IMAGE = "image"; + /** The HTML "left" attribute value. */ + public static final String LEFT = "left"; + /** The HTML "li" tag. */ + public static final String LI = "li"; + /** The HTML "link" tag. */ + public static final String LINK = "link"; + /** The HTML "name" attribute. */ + public static final String NAME = "name"; + /** The HTML "object" tag. */ + public static final String OBJECT = "object"; + /** The HTML "p" tag. */ + public static final String PARAM = "param"; + /** The HTML "param" tag. */ + public static final String P = "p"; + /** The HTML "rel" attribute value. */ + public static final String REL = "rel"; + /** The HTML "right" attribute value. */ + public static final String RIGHT = "right"; + /** The HTML "row" attribute value. */ + public static final String ROW = "row"; + /** The HTML "script" tag. */ + public static final String SCRIPT = "script"; + /** The HTML "small" tag. */ + public static final String SMALL = "small"; + /** The HTML "span" tag. */ + public static final String SPAN = "span"; + /** The HTML "src" attribute. */ + public static final String SRC = "src"; + /** The HTML "scope" attribute. */ + public static final String SCOPE = "scope"; + /** The HTML "style" attribute. */ + public static final String STYLE = "style"; + /** The HTML "table" tag. */ + public static final String TABLE = "table"; + /** The HTML "td" tag. */ + public static final String TD = "td"; + /** The HTML type for JavaScript. */ + public static final String TEXT_JAVASCRIPT = "text/javascript"; + /** The HTML "title"attribute. */ + public static final String TITLE = "title"; + /** The HTML "th" tag. */ + public static final String TH = "th"; + /** The HTML "top" attribute value. */ + public static final String TOP = "top"; + /** The HTML "tr" tag. */ + public static final String TR = "tr"; + /** The HTML "type" attribute. */ + public static final String TYPE = "type"; + /** The HTML "ul" tag. */ + public static final String UL = "ul"; + /** The HTML "valign" attribute. */ + public static final String VALIGN = "valign"; + /** The HTML "value" attribute. */ + public static final String VALUE = "value"; + + + private BufferedWriter out; + private int state; + private ResourceBundle i18n; + private static final int IN_TAG = 1; + private static final int IN_BODY = 2; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/README.examples.txt Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,134 @@ +Diagnostics Examples. + +The "examples/ directory contains a collection of examples of Java code, each of +which is designed to illustrate one or more diagnostics that can be generated by +the JDK Java compiler, javac. These examples are represented by files or +directories of files, each of which is designed to illustrate a specific +diagnostic. Sometimes it is unavoidable that creating one issue will lead to +downstream issues: this is especially true for lex errors, where the error +recovery is fragile at best. Each example declares the diagnostics that it is +expected to generate -- this allows the examples to be verified and facilitates +searching for examples for specific messages. + +Normally, tests for javac errors avoid checking the actual error messages that +get generated. Older tests simply verify that one or more warnings or errors +are generated; more recent tests verify that specific messages are generated, +but these tests typically avoid checking the localized text by using the +-XDrawDiagnostics mechanism. In addition, the focus of such tests is often on +completeness instead of simplicity. + +By contrast, the intent of these examples is to provide simple and easy to +understand examples of the situations in which a diagnostic can arise, and the +messages that may be displayed. This will aid in reviewing the output generated +by javac and in localizing the resource bundle to other locales. In addition, +the examples include simple meta-information so that the collection as a whole +can be audited for coverage, thus encouraging new examples to be added when new +diagnostics are added to javac. + +There are two utilities for processing these examples. + +The first utility is "CheckExamples" which checks various conditions for the +examples: +-- each example must generate exactly the set of keys that it is declared to + generate +-- together, the examples must generate all the resource keys coming from javac + (except for resource keys that are registered in a "not yet" list) +-- the "not yet" list should only contain those resource keys from javac that + are not covered by any example + +CheckExamples can be run standalone, and as a jtreg test, and will fail if any +anomalous conditions are found. + +The second utility is "RunExamples" which runs selected examples or all of them. +The examples can be run with -XDrawDiagnostics or without. Examples can be +selected by name or by resource key. Most examples are simple to run directly +anyway, but some use annotation processors or sourcepath or other options, and +the framework handles all these requirements. + +RunExamples can be run standalone and as a jtreg test, in which case it +generates a simple plain text report. In addition, the langtools/make/build.xml +file has a target "diags-examples" that uses RunExamples to create an HTML +report containing the output from all the examples. + + +Adding examples. + +When new diagnostics are added to javac, CheckExamples will probably initially +fail because the diagnostic will not have a corresponding example, nor will the +resource key be registered in the "not yet" list. Avoid the temptation to +simply add the resource key to the "not yet" list, except as a last resort. + +Examples should be as simple as possible to illustrate a diagnostic. An example +that is a single file is to be preferred over multiple files. An example that +generates just the one intended diagnostic is to be preferred over one that +generates multiple diagnostics. Examples should be a simple illustration of the +conditions that give rise to the diagnostic and should be easy to understand by +the reviewer and, potentially, by the localization folk, who have to understand +the context in which these new messages can appear. + + +Specification for writing examples. + +An example may a single file or a directory of files directly in the "examples" +directory. One file within an example must contain meta-information such as the +keys that it generates, any javac options that may be required, and additional +info about how to run the test, if needed. + +If an example is represented by a directory of files, by default all files +within that directory will be compiled together, putting all the files on the +command line. However, some subdirectories are special: +-- processors/ + Files within this directory will be treated as annotation processors and + compiled ahead of time. Currently, annotation processors are made available + to javac using the -classpath option (not -processorpath). This is to avoid + explicit use of annotation processing options on the javac command line. + Any annotation processors found will be registered for access by the JDK + service loaded. Currently, annotation processors are assumed to be in the + unnamed package. +-- sourcepath/ + If present, this directory will be put passed to javac using the -sourcepath + option. +-- classpath/ + This name is reserved for future use. It is expected that this directory + will be used to provide classes to be compiled and passes to javac via the + -classpath option. +-- support/ + This name is reserved for future use. It is expected that this directory + will be used to provide classes that setup non-standard conditions for a + test, such as very large source files, or illegal class files. + +Meta-information is represented by simple comment lines in exactly one of the +source files of the example. The file must not be in one of the special +subdirectories (processors/, sourcepath/, classpath/ or support/). Three +different types of information may be given: +// key: <resource-key> + One or more such lines must be provided, declaring the full resource keys + that will be used by javac when this example is run. +// options: <javac-options> + This line may be given at most once, providing one or more options to be + passed to javac. It is not possible to use this to specify options that + require filenames or directories. +// run: <mode> <optional-args> + This line may be given at most once, providing infomation about how to + run the example. Three different kinds are supported: + jsr199 -- The example will be run using the JSR 199 Compiler API. + This is the default if the tag is omitted. Messages generated + by the "rich diagnostic formatter" can not be accessed in this + way. However, this mode does provide additional options for + simulating errors in the filesystem. (See the options below.) + simple -- The example will be run using the simple com.sun.tools.javac.Main + API. This mode is most like the normal command line invocation. + backdoor -- The example will be run using an internal "backdoor" API, that + interposes access to the main compiler message bundle. This mode + is required to detect and track messages that bypass the normal + diagnostic mechanisms, such as output generated by the -verbose + option. + +The "jsr199" run mode accepts the following options: + -cantRead:pattern + -cantWrite:pattern +In both cases, the pattern is a standard Java regular expression (See the +javadoc for java.util.regex.Pattern for a complete specification.) Attempts to +read or write from files matching the corresponding pattern will cause an +IOException to occur within javac. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/RunExamples.java Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,582 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6968063 + * @summary provide examples of code that generate diagnostics + * @build Example HTMLWriter RunExamples + * @run main RunExamples + */ + +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility to run selected or all examples, writing results to + * stdout, a plain text file or an HTML file. This program can be + * run standalone, or as a jtreg test. + * + * Options: + * -examples dir directory of examples. Defaults to ${test.src}/examples + * -raw run examples with -XDrawDiagnostics + * -showFiles include text of source files in the output + * -verbose verbose output + * -o file write output to file: format will be HTML if + * file has .html extension; otherwise it will be plain text. + * default is to stdout + * -title string specify a title, only applies to HTML output + */ +public class RunExamples { + public static void main(String... args) throws Exception { + boolean jtreg = (System.getProperty("test.src") != null); + File tmpDir; + if (jtreg) { + // use standard jtreg scratch directory: the current directory + tmpDir = new File(System.getProperty("user.dir")); + } else { + tmpDir = new File(System.getProperty("java.io.tmpdir"), + RunExamples.class.getName() + + (new SimpleDateFormat("yyMMddHHmmss")).format(new Date())); + } + Example.setTempDir(tmpDir); + + RunExamples r = new RunExamples(); + + try { + if (r.run(args)) + return; + } finally { + /* VERY IMPORTANT NOTE. In jtreg mode, tmpDir is set to the + * jtreg scratch directory, which is the current directory. + * In case someone is faking jtreg mode, make sure to only + * clean tmpDir when it is reasonable to do so. + */ + if (tmpDir.isDirectory() && + tmpDir.getName().startsWith(RunExamples.class.getName())) { + if (clean(tmpDir)) + tmpDir.delete(); + } + } + + if (jtreg) + throw new Exception(r.errors + " errors occurred"); + else + System.exit(1); + } + + boolean run(String... args) { + Set<String> selectedKeys = new TreeSet<String>(); + Set<Example> selectedExamples = new TreeSet<Example>(); + File testSrc = new File(System.getProperty("test.src", ".")); + File examplesDir = new File(testSrc, "examples"); + File outFile = null; + boolean raw = false; + boolean showFiles = false; + boolean verbose = false; + String title = null; + + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-k") && (i + 1) < args.length) + selectedKeys.add(args[++i]); + else if (arg.equals("-examples") && (i + 1) < args.length) + examplesDir = new File(args[++i]); + else if (arg.equals("-raw")) + raw = true; + else if (arg.equals("-showFiles")) + showFiles = true; + else if (arg.equals("-verbose")) + verbose = true; + else if (arg.equals("-o") && (i + 1) < args.length) + outFile = new File(args[++i]); + else if (arg.equals("-title") && (i + 1) < args.length) + title = args[++i]; + else if (arg.startsWith("-")) { + error("unknown option: " + arg); + return false; + } else { + while (i < args.length) { + File f = new File(examplesDir, args[i]); + selectedExamples.add(new Example(f)); + i++; + } + } + } + + if (selectedKeys.size() > 0) { + Set<Example> examples = getExamples(examplesDir); + nextKey: + for (String k: selectedKeys) { + for (Example e: examples) { + if (e.getDeclaredKeys().contains(k)) + continue nextKey; + } + error("Key " + k + ": no examples found"); + } + } else { + if (selectedExamples.size() == 0) + selectedExamples = getExamples(examplesDir); + } + + try { + Runner r; + if (outFile == null) { + PrintWriter out = new PrintWriter(System.out); + r = new TextRunner(out, showFiles, raw, verbose); + } else if (outFile.getName().endsWith(".html")) + r = new HTMLRunner(outFile, showFiles, raw, verbose, title); + else + r = new TextRunner(outFile, showFiles, raw, verbose); + r.run(selectedExamples); + r.close(); + } catch (IOException e) { + error("Error writing output: " + e); + } + + return (errors == 0); + } + + /** + * Get the complete set of examples to be checked. + */ + Set<Example> getExamples(File examplesDir) { + Set<Example> results = new TreeSet<Example>(); + for (File f: examplesDir.listFiles()) { + if (f.isDirectory() || f.isFile() && f.getName().endsWith(".java")) + results.add(new Example(f)); + } + return results; + } + + /** + * Report an error. + */ + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; + + /** + * Clean the contents of a directory. + */ + static boolean clean(File dir) { + boolean ok = true; + for (File f: dir.listFiles()) { + if (f.isDirectory()) + ok &= clean(f); + ok &= f.delete(); + } + return ok; + } + + static abstract class Runner { + Runner(boolean showFiles, boolean raw, boolean verbose) { + this.showFiles = showFiles; + this.raw = raw; + this.verbose = verbose; + } + + void close() throws IOException { } + + void run(Collection<Example> examples) throws IOException { + for (Example e: examples) { + startExample(e); + if (showFiles) { + showFile(e, e.infoFile); + Set<File> srcFiles = new TreeSet<File>(e.srcFiles); + srcFiles.remove(e.infoFile); + showFiles(e, srcFiles); + showFiles(e, e.srcPathFiles); + showFiles(e, e.procFiles); + showFiles(e, e.supportFiles); + } + run(e); + } + } + + void showFiles(Example e, Collection<File> files) throws IOException { + for (File f: files) + showFile(e, f); + } + + abstract void startExample(Example e) throws IOException; + + abstract void showFile(Example e, File f) throws IOException; + + abstract void run(Example e) throws IOException; + + protected String read(File f) throws IOException { + byte[] bytes = new byte[(int) f.length()]; + DataInputStream in = new DataInputStream(new FileInputStream(f)); + try { + in.readFully(bytes); + } finally { + in.close(); + } + return new String(bytes); + } + + protected Pattern copyrightHeaderPat = + Pattern.compile("(?s)(/\\*.*?Copyright.*?\\*/\n)\\s*(.*)"); + protected Pattern infoHeaderPat = + Pattern.compile("(?s)((?://\\s*[a-z]+:[^\n]*\n)+)\\s*(.*)"); + + protected boolean showFiles; + protected boolean raw; + protected boolean verbose; + } + + static class TextRunner extends Runner { + TextRunner(File file, boolean showFiles, boolean raw, boolean verbose) + throws IOException { + super(showFiles, raw, verbose); + this.file = file; + out = new PrintWriter(new FileWriter(file)); + } + + TextRunner(PrintWriter out, boolean showFiles, boolean raw, boolean verbose) + throws IOException { + super(showFiles, raw, verbose); + this.out = out; + } + + @Override + void close() { + if (file != null) + out.close(); + } + + @Override + void startExample(Example e) { + out.println("----- " + e.getName() + " --------------------"); + out.println(); + } + + @Override + void showFile(Example e, File f) { + out.println("--- " + f); + String text; + try { + text = read(f); + } catch (IOException ex) { + text = "Error reading " + f + "; " + ex; + } + Matcher m = copyrightHeaderPat.matcher(text); + if (m.matches()) { + out.println("(Copyright)"); + writeLines(m.group(2)); + } else { + writeLines(text); + } + out.println(); + } + + @Override + void run(Example e) { + // only show Output: header if also showing files + if (showFiles) + out.println("--- Output:"); + e.run(out, raw, verbose); + out.println(); + } + + void writeLines(String text) { + for (String line: text.split("\n")) + out.println(line); + } + + File file; + PrintWriter out; + } + + static class HTMLRunner extends Runner { + HTMLRunner(File file, boolean showFiles, boolean raw, boolean verbose, String title) + throws IOException { + super(showFiles, raw, verbose); + this.file = file; + PrintWriter out = new PrintWriter(new FileWriter(file)); + html = new HTMLWriter(out); + html.startTag(HTMLWriter.HEAD); + if (title != null) { + html.startTag(HTMLWriter.TITLE); + html.write(title); + html.endTag(HTMLWriter.TITLE); + } + html.startTag(HTMLWriter.STYLE); + html.newLine(); + html.writeLine("div.file { background-color:#e0ffe0; margin-left:30px; margin-right:30px;\n" + + " padding: 3px; border: thin solid silver; }"); + html.writeLine("p.file { white-space: pre-wrap; font-family:monospace; margin: 0; }"); + html.writeLine("div.output { background-color:#e0e0ff; margin-left:30px; margin-right:30px;\n" + + " padding: 3px; border: thin solid silver; }"); + html.writeLine("p.output { white-space: pre-wrap; font-family:monospace; margin: 0; }"); + html.writeLine("table.index { border: thin solid silver; }"); + html.writeLine(".copyright { font-size: x-small }"); + html.writeLine(".hidden { display:none }"); + html.writeLine(".unhidden { display:block }"); + html.writeLine(".odd { background-color: #e0e0e0 }"); + html.writeLine(".even { background-color: white }"); + html.endTag(HTMLWriter.STYLE); + html.startTag(HTMLWriter.SCRIPT); + html.writeAttr(HTMLWriter.TYPE, HTMLWriter.TEXT_JAVASCRIPT); + html.writeLine("\nfunction unhide(id) {\n" + + " var item = document.getElementById(id);\n" + + " if (item) {\n" + + " item.className=(item.className=='hidden')?'unhidden':'hidden';\n" + + " }\n" + + "}"); + html.endTag(HTMLWriter.SCRIPT); + html.endTag(HTMLWriter.HEAD); + html.startTag(HTMLWriter.BODY); + if (title != null) { + html.startTag(TITLE_HEADER); + html.write(title); + html.endTag(TITLE_HEADER); + } + } + + @Override + void close() throws IOException { + html.endTag(HTMLWriter.BODY); + html.newLine(); + html.flush(); + } + + @Override + void run(Collection<Example> examples) throws IOException { + if (examples.size() > 1) + writeIndex(examples); + super.run(examples); + } + + void writeIndex(Collection<Example> examples) throws IOException { + Map<String, Set<Example>> index = new TreeMap<String, Set<Example>>(); + Set<String> initials = new HashSet<String>(); + for (Example e: examples) { + for (String k: e.getDeclaredKeys()) { + Set<Example> s = index.get(k); + if (s == null) + index.put(k, s = new TreeSet<Example>()); + s.add(e); + } + initials.add(e.getName().substring(0, 1).toUpperCase()); + } + + + if (INDEX_HEADER != null) { + html.startTag(INDEX_HEADER); + html.write("Index"); + html.endTag(INDEX_HEADER); + } + + html.startTag(HTMLWriter.P); + html.writeLine("Examples: "); + for (char initial = 'A'; initial <= 'Z'; initial++) { + String s = String.valueOf(initial); + if (initials.contains(s)) { + html.writeLink("#" + s, s); + } else { + html.write(s); + } + html.newLine(); + } + html.endTag(HTMLWriter.P); + + html.startTag(HTMLWriter.TABLE); + html.writeAttr(HTMLWriter.CLASS, "index"); + html.newLine(); + int row = 0; + for (Map.Entry<String, Set<Example>> entry: index.entrySet()) { + html.startTag(HTMLWriter.TR); + html.writeAttr(HTMLWriter.CLASS, + (row++ % 2 == 0 ? "even" : "odd")); + html.startTag(HTMLWriter.TD); + html.writeAttr("valign", "top"); + html.write(entry.getKey()); + html.endTag(HTMLWriter.TD); + html.newLine(); + html.startTag(HTMLWriter.TD); + html.writeAttr(HTMLWriter.ALIGN, "top"); + String sep = ""; + for (Example e: entry.getValue()) { + html.write(sep); + html.writeLink('#' + e.getName(), e.getName()); + sep = ", "; + } + html.endTag(HTMLWriter.TD); + html.endTag(HTMLWriter.TR); + html.newLine(); + } + html.endTag(HTMLWriter.TABLE); + } + + @Override + void startExample(Example e) throws IOException { + String name = e.getName(); + String initial = name.substring(0, 1).toUpperCase(); + if (!initial.equals(currInitial)) { + html.writeLinkDestination(initial, ""); + currInitial = initial; + } + html.writeLinkDestination(name, ""); + html.startTag(EXAMPLE_HEADER); + html.write(e.getName()); + html.endTag(EXAMPLE_HEADER); + } + + @Override + void showFile(Example e, File f) throws IOException { + String text; + try { + text = read(f); + } catch (IOException ex) { + text = "Error reading " + f + ": " + ex; + } + if (!f.equals(e.file)) { + html.startTag(FILE_HEADER); + html.write(e.file.toURI().relativize(f.toURI()).toString()); + html.endTag(FILE_HEADER); + } + html.startTag(HTMLWriter.DIV); + html.writeAttr(CLASS, FILE); + + String legalHeader; + Matcher m1 = copyrightHeaderPat.matcher(text); + if (m1.matches()) { + legalHeader = m1.group(1); + text = m1.group(2); + } else + legalHeader = null; + + String infoHeader; + Matcher m2 = infoHeaderPat.matcher(text); + if (m2.matches()) { + infoHeader = m2.group(1); + text = m2.group(2); + } else + infoHeader = null; + + String legalId = null, infoId = null; + if (legalHeader != null || infoHeader != null) { + String sep = ""; + html.startTag(HTMLWriter.SPAN); + html.writeStyleAttr("float: right"); + if (legalHeader != null) { + legalId = nextId(); + html.startTag(HTMLWriter.A); + html.writeAttr(HTMLWriter.HREF, "javascript:unhide('" + legalId + "');"); + //html.writeEntity("©"); + html.write("Copyright"); + html.endTag(HTMLWriter.A); + sep = ", "; + } + if (infoHeader != null) { + html.write(sep); + infoId = nextId(); + html.startTag(HTMLWriter.A); + html.writeAttr(HTMLWriter.HREF, "javascript:unhide('" + infoId + "');"); + html.write("Info"); + html.endTag(HTMLWriter.A); + sep = ", "; + } + html.endTag(HTMLWriter.SPAN); + } + + html.startTag(HTMLWriter.P); + html.writeAttr(CLASS, FILE); + if (legalHeader != null) { + html.startTag(HTMLWriter.SPAN); + html.writeAttr(HTMLWriter.CLASS, "hidden"); + html.writeAttr(HTMLWriter.ID, legalId); + html.write(legalHeader); + html.newLine(); + html.endTag(HTMLWriter.SPAN); + } + if (infoHeader != null) { + html.startTag(HTMLWriter.SPAN); + html.writeAttr(HTMLWriter.CLASS, "hidden"); + html.writeAttr(HTMLWriter.ID, infoId); + html.write(infoHeader); + html.newLine(); + html.endTag(HTMLWriter.SPAN); + } + html.write(text); + html.endTag(HTMLWriter.P); + + html.endTag(HTMLWriter.DIV); + } + + @Override + void run(Example e) throws IOException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.run(pw, raw, verbose); + pw.flush(); + + // only show Output: header if also showing files + if (showFiles) { + html.startTag(OUTPUT_HEADER); + html.write("Output:"); + html.endTag(OUTPUT_HEADER); + } + + html.startTag(HTMLWriter.DIV); + html.writeAttr(CLASS, OUTPUT); + html.startTag(HTMLWriter.P); + html.writeAttr(CLASS, OUTPUT); + String[] lines = sw.toString().split("\n"); + for (String line: lines) { + html.write(line); + html.newLine(); + } + html.endTag(HTMLWriter.P); + html.endTag(HTMLWriter.DIV); + } + + String nextId() { + return "id" + (nextId++); + } + + File file; + HTMLWriter html; + int nextId; + String currInitial = ""; + + static final String TITLE_HEADER = HTMLWriter.H3; + static final String INDEX_HEADER = HTMLWriter.H4; + static final String EXAMPLE_HEADER = HTMLWriter.H4; + static final String FILE_HEADER = HTMLWriter.H5; + static final String OUTPUT_HEADER = HTMLWriter.H5; + static final String CLASS = "class"; + static final String FILE = "file"; + static final String OUTPUT = "output"; + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Mon Aug 02 19:46:14 2010 -0700 @@ -0,0 +1,114 @@ +compiler.err.already.annotated # internal compiler error? +compiler.err.already.defined.this.unit # seems to be masked by compiler.err.duplicate.class +compiler.err.annotation.value.not.allowable.type # cannot happen: precluded by complete type-specific tests +compiler.err.assignment.from.super-bound # DEAD +compiler.err.assignment.to.extends-bound # DEAD +compiler.err.cant.apply.symbol.1 +compiler.err.cant.read.file # (apt.JavaCompiler?) +compiler.err.cant.select.static.class.from.param.type +compiler.err.illegal.char.for.encoding +compiler.err.internal.error.cant.instantiate # Attr: should not happen +compiler.err.io.exception # (javah.JavahTask?) +compiler.err.limit.code # Code +compiler.err.limit.code.too.large.for.try.stmt # Gen +compiler.err.limit.dimensions # Gen +compiler.err.limit.locals # Code +compiler.err.limit.parameters # Gen +compiler.err.limit.pool # Gen,JavaCompiler +compiler.err.limit.pool.in.class # UNUSED? +compiler.err.limit.stack # Code +compiler.err.limit.string # Gen +compiler.err.limit.string.overflow # JavaCompiler +compiler.err.name.reserved.for.internal.use # UNUSED +compiler.err.no.annotation.member +compiler.err.no.encl.instance.of.type.in.scope # cannot occur; always followed by assert false; +compiler.err.no.match.entry # UNUSED? +compiler.err.not.annotation.type # cannot occur given preceding checkType +compiler.err.not.within.bounds.explain # UNUSED? +compiler.err.prob.found.req.1 # Check: DEAD, in unused method +compiler.err.proc.bad.config.file # JavacProcessingEnvironment +compiler.err.proc.cant.access # completion failure +compiler.err.proc.cant.create.loader # security exception from service loader +compiler.err.proc.no.service # JavacProcessingEnvironment: no service loader available +compiler.err.proc.processor.bad.option.name # cannot happen? masked by javac.err.invalid.A.key +compiler.err.proc.processor.constructor.error +compiler.err.proc.service.problem # JavacProcessingEnvironment: catch Throwable from service loader +compiler.err.signature.doesnt.match.intf # UNUSED +compiler.err.signature.doesnt.match.supertype # UNUSED +compiler.err.source.cant.overwrite.input.file +compiler.err.stack.sim.error +compiler.err.type.var.more.than.once # UNUSED +compiler.err.type.var.more.than.once.in.result # UNUSED +compiler.err.undetermined.type +compiler.err.unexpected.type +compiler.err.unknown.enum.constant # in bad class file +compiler.err.unsupported.cross.fp.lit # Scanner: host system dependent +compiler.misc.arg.length.mismatch +compiler.misc.assignment.from.super-bound +compiler.misc.assignment.to.extends-bound +compiler.misc.bad.class.file.header # bad class file +compiler.misc.bad.class.signature # bad class file +compiler.misc.bad.const.pool.tag # bad class file +compiler.misc.bad.const.pool.tag.at # bad class file +compiler.misc.bad.enclosing.method # bad class file +compiler.misc.bad.runtime.invisible.param.annotations # bad class file +compiler.misc.bad.signature # bad class file +compiler.misc.bad.type.annotation.value +compiler.misc.base.membership # UNUSED +compiler.misc.ccf.found.later.version +compiler.misc.ccf.unrecognized.attribute +compiler.misc.class.file.not.found # ClassReader +compiler.misc.class.file.wrong.class +compiler.misc.fatal.err.cant.locate.ctor # Resolve, from Lower +compiler.misc.fatal.err.cant.locate.field # Resolve, from Lower +compiler.misc.fatal.err.cant.locate.meth # Resolve, from Lower +compiler.misc.file.does.not.contain.package +compiler.misc.illegal.start.of.class.file +compiler.misc.kindname.annotation +compiler.misc.kindname.enum +compiler.misc.kindname.package +compiler.misc.kindname.static +compiler.misc.kindname.type.variable +compiler.misc.kindname.type.variable.bound +compiler.misc.kindname.value +compiler.misc.no.conforming.assignment.exists +compiler.misc.non.denotable.type +compiler.misc.no.unique.minimal.instance.exists +compiler.misc.resume.abort # prompt for a response +compi