langtools/make/tools/crules/AssertCheckAnalyzer.java
changeset 29294 376a915b4ff0
parent 25848 3bc09f4676a9
child 38510 3f450a95c68f
--- a/langtools/make/tools/crules/AssertCheckAnalyzer.java	Mon Mar 02 10:41:08 2015 +0530
+++ b/langtools/make/tools/crules/AssertCheckAnalyzer.java	Thu Mar 05 13:10:49 2015 +0000
@@ -23,10 +23,14 @@
 
 package crules;
 
+import com.sun.source.tree.LambdaExpressionTree.BodyKind;
 import com.sun.source.util.JavacTask;
 import com.sun.source.util.TaskEvent.Kind;
+import com.sun.tools.javac.code.Kinds;
 import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCLambda;
 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
 import com.sun.tools.javac.tree.JCTree.Tag;
 import com.sun.tools.javac.tree.TreeInfo;
@@ -35,6 +39,22 @@
 
 public class AssertCheckAnalyzer extends AbstractCodingRulesAnalyzer {
 
+    enum AssertOverloadKind {
+        EAGER("crules.should.not.use.eager.string.evaluation"),
+        LAZY("crules.should.not.use.lazy.string.evaluation"),
+        NONE(null);
+
+        String errKey;
+
+        AssertOverloadKind(String errKey) {
+            this.errKey = errKey;
+        }
+
+        boolean simpleArgExpected() {
+            return this == AssertOverloadKind.EAGER;
+        }
+    }
+
     public AssertCheckAnalyzer(JavacTask task) {
         super(task);
         treeVisitor = new AssertCheckVisitor();
@@ -45,20 +65,46 @@
 
         @Override
         public void visitApply(JCMethodInvocation tree) {
-            Symbol method = TreeInfo.symbolFor(tree);
-            if (method != null &&
-                method.owner.getQualifiedName().contentEquals(Assert.class.getName()) &&
-                !method.name.contentEquals("error")) {
+            Symbol m = TreeInfo.symbolFor(tree);
+            AssertOverloadKind ak = assertOverloadKind(m);
+            if (ak != AssertOverloadKind.NONE &&
+                !m.name.contentEquals("error")) {
                 JCExpression lastParam = tree.args.last();
-                if (lastParam != null &&
-                    lastParam.type.tsym == syms.stringType.tsym &&
-                    lastParam.hasTag(Tag.PLUS)) {
-                    messages.error(tree, "crules.should.not.use.string.concatenation");
+                if (isSimpleStringArg(lastParam) != ak.simpleArgExpected()) {
+                    messages.error(lastParam, ak.errKey);
                 }
             }
 
             super.visitApply(tree);
         }
 
+        AssertOverloadKind assertOverloadKind(Symbol method) {
+            if (method == null ||
+                !method.owner.getQualifiedName().contentEquals(Assert.class.getName()) ||
+                method.type.getParameterTypes().tail == null) {
+                return AssertOverloadKind.NONE;
+            }
+            Type formal = method.type.getParameterTypes().last();
+            if (types.isSameType(formal, syms.stringType)) {
+                return AssertOverloadKind.EAGER;
+            } else if (types.isSameType(types.erasure(formal), types.erasure(syms.supplierType))) {
+                return AssertOverloadKind.LAZY;
+            } else {
+                return AssertOverloadKind.NONE;
+            }
+        }
+
+        boolean isSimpleStringArg(JCExpression e) {
+            switch (e.getTag()) {
+                case LAMBDA:
+                    JCLambda lambda = (JCLambda)e;
+                    return (lambda.getBodyKind() == BodyKind.EXPRESSION) &&
+                            isSimpleStringArg((JCExpression)lambda.body);
+                default:
+                    Symbol argSym = TreeInfo.symbolFor(e);
+                    return (e.type.constValue() != null ||
+                            (argSym != null && argSym.kind == Kinds.Kind.VAR));
+            }
+        }
     }
 }