Add suggestion message on how to suppress 'unusable-by-js' warnings.

Bug: #9349
Bug-Link: http://github.com/gwtproject/gwt/issues/9349
Change-Id: I3603a6ec416cf00a92142633867d167cb0720bc8
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/AbstractRestrictionChecker.java b/dev/core/src/com/google/gwt/dev/jjs/impl/AbstractRestrictionChecker.java
index 6dafe98..040ee21 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/AbstractRestrictionChecker.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/AbstractRestrictionChecker.java
@@ -28,6 +28,7 @@
 import com.google.gwt.thirdparty.guava.common.collect.Sets;
 import com.google.gwt.thirdparty.guava.common.collect.TreeMultimap;
 
+import java.util.Set;
 import java.util.TreeSet;
 
 /**
@@ -38,6 +39,7 @@
       = TreeMultimap.create(Ordering.natural(), AbstractTreeLogger.LOG_LINE_COMPARATOR);
   private Multimap<String, String> warningsByFilename
       = TreeMultimap.create(Ordering.natural(), AbstractTreeLogger.LOG_LINE_COMPARATOR);
+  private Set<String> suggestionMessages = Sets.newLinkedHashSet();
 
   protected static String getDescription(HasSourceInfo hasSourceInfo) {
     if (hasSourceInfo instanceof JDeclaredType) {
@@ -84,6 +86,10 @@
             + String.format(format, args));
   }
 
+  protected void logSuggestion(String format, Object... args) {
+    suggestionMessages.add(String.format(format, args));
+  }
+
   protected boolean reportErrorsAndWarnings(TreeLogger logger) {
     TreeSet<String> filenamesToReport = Sets.newTreeSet(
         Iterables.concat(errorsByFilename.keySet(), warningsByFilename.keySet()));
@@ -98,6 +104,9 @@
         branch.log(Type.WARN, message);
       }
     }
+    for (String message : suggestionMessages) {
+      logger.log(Type.WARN, message);
+    }
     return !errorsByFilename.isEmpty();
   }
 }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java
index 8da4fc4..021dd5c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java
@@ -77,6 +77,7 @@
 
   private final JProgram jprogram;
   private final MinimalRebuildCache minimalRebuildCache;
+  private boolean wasUnusableByJsWarningReported = false;
 
   private JsInteropRestrictionChecker(JProgram jprogram,
       MinimalRebuildCache minimalRebuildCache) {
@@ -722,6 +723,11 @@
     }
     checkStaticJsPropertyCalls();
     checkInstanceOfNativeJsTypes();
+    if (wasUnusableByJsWarningReported) {
+      logSuggestion(
+          "Suppress \"[unusable-by-js]\" warnings by adding a "
+              + "`@SuppressWarnings(\"unusable-by-js\")` annotation to the corresponding member.");
+    }
 
     boolean hasErrors = reportErrorsAndWarnings(logger);
     return !hasErrors;
@@ -782,6 +788,7 @@
     }
     logWarning(x, "[unusable-by-js] %s %s is not usable by but exposed to JavaScript.", prefix,
         getMemberDescription(x));
+    wasUnusableByJsWarningReported = true;
   }
 
   private static class JsMember {
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java
index 529583e..3be61df 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java
@@ -2202,7 +2202,9 @@
             + "is not usable by but exposed to JavaScript.",
         "Line 24: [unusable-by-js] Type of parameter 'a' in "
             + "'EntryPoint.B EntryPoint.Buggy.f4(EntryPoint.B)' is not usable by but "
-            + "exposed to JavaScript.");
+            + "exposed to JavaScript.",
+        "Suppress \"[unusable-by-js]\" warnings by adding a `@SuppressWarnings(\"unusable-by-js\")`"
+            + " annotation to the corresponding member.");
   }
 
   public void testUnusableByJsAccidentalOverrideSuppressionWarns()
@@ -2222,7 +2224,9 @@
     assertBuggySucceeds(
         "Line 10: [unusable-by-js] Type of parameter 'x' in "
             + "'void EntryPoint.Parent.doIt(Class)' (exposed by 'EntryPoint.Buggy') is not usable "
-            + "by but exposed to JavaScript.");
+            + "by but exposed to JavaScript.",
+        "Suppress \"[unusable-by-js]\" warnings by adding a `@SuppressWarnings(\"unusable-by-js\")`"
+            + " annotation to the corresponding member.");
   }
 
   private static final MockJavaResource jsFunctionInterface = new MockJavaResource(