JAL-1424 enhanced for cleaner reporting, checks calls to JvSwingUtils
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 24 Aug 2016 13:05:39 +0000 (14:05 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 24 Aug 2016 13:05:39 +0000 (14:05 +0100)
utils/MessageBundleChecker.java

index 7850eb5..9d322df 100644 (file)
@@ -5,6 +5,7 @@ import java.io.IOException;
 import java.util.HashSet;
 import java.util.Properties;
 import java.util.TreeSet;
+import java.util.regex.Pattern;
 
 /**
  * This class scans Java source files for calls to MessageManager and reports
@@ -22,18 +23,32 @@ import java.util.TreeSet;
 public class MessageBundleChecker
 {
   /*
+   * regex ^"[^"]*"$
+   * opening quote, closing quote, no quotes in between
+   */
+  static Pattern STRING_PATTERN = Pattern.compile("^\"[^\"]*\"$");
+
+  /*
    * number of text lines to read at a time in order to parse
    * code that is split over several lines
    */
   static int bufferSize = 3;
 
+  /*
+   * resource bundle key is arg0 for these methods
+   */
   static final String METHOD1 = "MessageManager.getString(";
 
-  static final String METHOD2 = "MessageManager.getStringOrReturn(";
+  static final String METHOD2 = "MessageManager.formatMessage(";
 
-  static final String METHOD3 = "MessageManager.formatMessage(";
+  static final String METHOD3 = "MessageManager.getStringOrReturn(";
 
-  static final String[] METHODS = { METHOD1, METHOD2, METHOD3 };
+  /*
+   * resource bundle key is arg1 for this method
+   */
+  static final String JVINIT = "JvSwingUtils.jvInitComponent(";
+
+  static final String[] METHODS = { METHOD1, METHOD2, METHOD3, JVINIT };
 
   /*
    * root of the Java source folders we want to scan
@@ -123,7 +138,7 @@ public class MessageBundleChecker
             + " possibly invalid parameter calls");
 
     System.out.println(messageKeys.size()
-            + " keys not found, possibly unused");
+            + " keys not found, either unused or constructed dynamically");
     for (String key : messageKeys)
     {
       System.out.println("    " + key);
@@ -169,6 +184,14 @@ public class MessageBundleChecker
     }
     javaCount++;
 
+    /*
+     * skip class with designed dynamic lookup call
+     */
+    if (path.endsWith("gui/JvSwingUtils.java"))
+    {
+      return;
+    }
+
     String[] lines = new String[bufferSize];
     BufferedReader br = new BufferedReader(new FileReader(f));
     for (int i = 0; i < bufferSize; i++)
@@ -231,30 +254,61 @@ public class MessageBundleChecker
       {
         continue;
       }
-      String methodArgs = combined.substring(pos + method.length());
+
+      /*
+       * extract what follows the opening bracket of the method call
+       */
+      String methodArgs = combined.substring(pos + method.length()).trim();
       if ("".equals(methodArgs))
       {
         /*
-         * continues on next line - catch in the next read loop iteration
+         * arguments are on next line - catch in the next read loop iteration
          */
         continue;
       }
-      if (!methodArgs.startsWith("\""))
+      if (methodArgs.indexOf(",") == -1 && methodArgs.indexOf(")") == -1)
       {
-        System.out.println(String.format(
-                "Possible dynamic key at %s line %s %s",
+        /*
+         * arguments continue on next line - catch in the next read loop iteration
+         */
+        continue;
+      }
+
+      if (JVINIT == method && methodArgs.indexOf(",") == -1)
+      {
+        /*
+         * not interested in 1-arg calls to jvInitComponent
+         */
+        continue;
+      }
+
+      if (METHOD3 == method)
+      {
+        System.out.println(String.format("Dynamic key at %s line %s %s",
                 path.substring(sourcePath.length()), lineNos, combined));
         continue;
       }
-      methodArgs = methodArgs.substring(1);
-      int quotePos = methodArgs.indexOf("\"");
-      if (quotePos == -1)
+
+      String messageKey = getMessageKey(method, methodArgs);
+      if (messageKey == null)
       {
         System.out.println(String.format("Trouble parsing %s line %s %s",
                 path.substring(sourcePath.length()), lineNos, combined));
         continue;
       }
-      String messageKey = methodArgs.substring(0, quotePos);
+
+      if (!(STRING_PATTERN.matcher(messageKey).matches()))
+      {
+        System.out.println(String.format("Dynamic key at %s line %s %s",
+                path.substring(sourcePath.length()), lineNos, combined));
+        continue;
+      }
+
+      /*
+       * strip leading and trailing quote
+       */
+      messageKey = messageKey.substring(1, messageKey.length() - 1);
+
       if (!this.messages.containsKey(messageKey))
       {
         System.out.println(String.format(
@@ -269,6 +323,47 @@ public class MessageBundleChecker
     }
   }
 
+  /**
+   * Helper method to parse out the resource bundle key parameter of a method
+   * call
+   * 
+   * @param method
+   * @param methodArgs
+   *          the rest of the source line starting with arguments to method
+   * @return
+   */
+  private String getMessageKey(String method, String methodArgs)
+  {
+    String key = methodArgs;
+
+    /*
+     * locate second argument if calling jvInitComponent()
+     */
+    if (method == JVINIT)
+    {
+      int commaLoc = methodArgs.indexOf(",");
+      if (commaLoc == -1)
+      {
+        return null;
+      }
+      key = key.substring(commaLoc + 1).trim();
+    }
+
+    /*
+     * take up to next comma or ) or end of line
+     */
+    int commaPos = key.indexOf(",");
+    int bracePos = key.indexOf(")");
+    int endPos = commaPos == -1 ? bracePos : (bracePos == -1 ? commaPos
+            : Math.min(commaPos, bracePos));
+    if (endPos == -1 && key.length() > 1 && key.endsWith("\""))
+    {
+      endPos = key.length();
+    }
+
+    return endPos == -1 ? null : key.substring(0, endPos);
+  }
+
   private String combineLines(String[] lines)
   {
     String combined = "";