1
2
3
4
5 package com.qulice.pmd.rules;
6
7 import java.util.Arrays;
8 import java.util.HashSet;
9 import java.util.Set;
10 import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
11 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
12 import net.sourceforge.pmd.lang.java.ast.ASTMethodCall;
13 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
14
15
16
17
18
19
20
21
22
23 public final class ProhibitFormatInLoggerRule
24 extends AbstractJavaRulechainRule {
25
26
27
28
29 private static final Set<String> METHODS = new HashSet<>(
30 Arrays.asList("trace", "debug", "info", "warn", "error")
31 );
32
33 public ProhibitFormatInLoggerRule() {
34 super(ASTMethodCall.class);
35 }
36
37 @Override
38 public Object visit(final ASTMethodCall call, final Object data) {
39 if (ProhibitFormatInLoggerRule.isLoggerCall(call)
40 && ProhibitFormatInLoggerRule.hasFormatArgument(call)) {
41 this.asCtx(data).addViolation(call);
42 }
43 return data;
44 }
45
46 private static boolean isLoggerCall(final ASTMethodCall call) {
47 boolean result = false;
48 if (ProhibitFormatInLoggerRule.METHODS.contains(call.getMethodName())) {
49 final ASTExpression qualifier = call.getQualifier();
50 result = qualifier != null
51 && ProhibitFormatInLoggerRule.endsWith(
52 qualifier.getText().toString(), "Logger"
53 );
54 }
55 return result;
56 }
57
58 private static boolean hasFormatArgument(final ASTMethodCall call) {
59 final ASTArgumentList args = call.getArguments();
60 return args != null
61 && args.toStream()
62 .any(ProhibitFormatInLoggerRule::isStringFormatCall);
63 }
64
65 private static boolean isStringFormatCall(final ASTExpression expr) {
66 boolean result = false;
67 if (expr instanceof ASTMethodCall) {
68 final ASTMethodCall method = (ASTMethodCall) expr;
69 final ASTExpression qualifier = method.getQualifier();
70 result = "format".equals(method.getMethodName())
71 && qualifier != null
72 && ProhibitFormatInLoggerRule.endsWith(
73 qualifier.getText().toString(), "String"
74 );
75 }
76 return result;
77 }
78
79 private static boolean endsWith(final String text, final String name) {
80 return text.equals(name) || text.endsWith(".".concat(name));
81 }
82 }