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
24 public final class ProhibitFormatInLoggerRule
25 extends AbstractJavaRulechainRule {
26
27
28
29
30 private static final Set<String> METHODS = new HashSet<>(
31 Arrays.asList("trace", "debug", "info", "warn", "error")
32 );
33
34
35
36
37 public ProhibitFormatInLoggerRule() {
38 super(ASTMethodCall.class);
39 }
40
41 @Override
42 public Object visit(final ASTMethodCall call, final Object data) {
43 if (ProhibitFormatInLoggerRule.isLoggerCall(call)
44 && ProhibitFormatInLoggerRule.hasFormatArgument(call)) {
45 this.asCtx(data).addViolation(call);
46 }
47 return data;
48 }
49
50 private static boolean isLoggerCall(final ASTMethodCall call) {
51 boolean result = false;
52 if (ProhibitFormatInLoggerRule.METHODS.contains(call.getMethodName())) {
53 final ASTExpression qualifier = call.getQualifier();
54 result = qualifier != null
55 && ProhibitFormatInLoggerRule.endsWith(
56 qualifier.getText().toString(), "Logger"
57 );
58 }
59 return result;
60 }
61
62 private static boolean hasFormatArgument(final ASTMethodCall call) {
63 final ASTArgumentList args = call.getArguments();
64 return args != null
65 && args.toStream()
66 .any(ProhibitFormatInLoggerRule::isStringFormatCall);
67 }
68
69 private static boolean isStringFormatCall(final ASTExpression expr) {
70 boolean result = false;
71 if (expr instanceof ASTMethodCall method) {
72 final ASTExpression qualifier = method.getQualifier();
73 result = "format".equals(method.getMethodName())
74 && qualifier != null
75 && ProhibitFormatInLoggerRule.endsWith(
76 qualifier.getText().toString(), "String"
77 );
78 }
79 return result;
80 }
81
82 private static boolean endsWith(final String text, final String name) {
83 return text.equals(name) || text.endsWith(".".concat(name));
84 }
85 }