6957438: improve code for generating warning messages containing option names
authorjjg
Mon, 26 Jul 2010 14:25:56 -0700
changeset 6151 dd513881e71d
parent 6150 d055fa8ced62
child 6152 111b884a19a7
6957438: improve code for generating warning messages containing option names Reviewed-by: mcimadamore
langtools/src/share/classes/com/sun/tools/javac/code/Lint.java
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
langtools/src/share/classes/com/sun/tools/javac/file/Paths.java
langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java
langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java
langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java
langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java
langtools/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java
langtools/test/tools/javac/diags/examples/CountWarn.java
langtools/test/tools/javac/diags/examples/CountWarnPlural.java
langtools/test/tools/javac/diags/examples/Error.java
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java	Mon Jul 26 14:25:56 2010 -0700
@@ -119,6 +119,7 @@
         this.suppressedValues = other.suppressedValues.clone();
     }
 
+    @Override
     public String toString() {
         return "Lint:[values" + values + " suppressedValues" + suppressedValues + "]";
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Jul 26 14:25:56 2010 -0700
@@ -3111,7 +3111,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;
             }
 
@@ -3119,15 +3120,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	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Jul 26 14:25:56 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);
     }
 
     /**
@@ -929,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);
         }
     }
 
@@ -2156,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");
         }
     }
 
@@ -2307,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");
             }
         }
     }
@@ -2317,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	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Jul 26 14:25:56 2010 -0700
@@ -942,7 +942,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) {
@@ -1081,8 +1082,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));
@@ -1353,7 +1355,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);
         }
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Jul 26 14:25:56 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/file/Paths.java	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java	Mon Jul 26 14:25:56 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/resources/compiler.properties	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Jul 26 14:25:56 2010 -0700
@@ -697,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\
@@ -723,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 ''...''
@@ -737,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}
@@ -753,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=\
@@ -808,38 +816,38 @@
 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}''
@@ -848,7 +856,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}
 
 #####
@@ -1006,13 +1014,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}
@@ -1182,11 +1190,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
--- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Mon Jul 26 14:25:56 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	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java	Mon Jul 26 14:25:56 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	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java	Mon Jul 26 14:25:56 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	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Mon Jul 26 14:25:56 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/MandatoryWarningHandler.java	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java	Mon Jul 26 14:25:56 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/test/tools/javac/diags/examples/CountWarn.java	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/test/tools/javac/diags/examples/CountWarn.java	Mon Jul 26 14:25:56 2010 -0700
@@ -23,6 +23,7 @@
 
 // key: compiler.misc.count.warn
 // key: compiler.warn.warning
+// key: compiler.warn.lintOption
 // key: compiler.warn.prob.found.req
 // key: compiler.misc.unchecked.assign
 // options: -Xlint:unchecked
--- a/langtools/test/tools/javac/diags/examples/CountWarnPlural.java	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/test/tools/javac/diags/examples/CountWarnPlural.java	Mon Jul 26 14:25:56 2010 -0700
@@ -23,6 +23,7 @@
 
 // key: compiler.misc.count.warn.plural
 // key: compiler.warn.warning
+// key: compiler.warn.lintOption
 // key: compiler.warn.prob.found.req
 // key: compiler.misc.unchecked.assign
 // options: -Xlint:unchecked
--- a/langtools/test/tools/javac/diags/examples/Error.java	Mon Jul 26 14:18:45 2010 -0700
+++ b/langtools/test/tools/javac/diags/examples/Error.java	Mon Jul 26 14:25:56 2010 -0700
@@ -25,6 +25,7 @@
 // key: compiler.err.warnings.and.werror
 // key: compiler.warn.raw.class.use
 // key: compiler.warn.warning
+// key: compiler.warn.lintOption
 // key: compiler.misc.count.error
 // key: compiler.misc.count.warn
 // key: compiler.misc.kindname.interface