7c0ceec95000facc9a8cec0a8119f8b75adc0eca
[yangtools.git] / common / checkstyle-logging / src / main / java / org / opendaylight / yangtools / checkstyle / LogMessagePlaceholderCountCheck.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.yangtools.checkstyle;
10
11 import com.puppycrawl.tools.checkstyle.api.DetailAST;
12 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
13
14 public class LogMessagePlaceholderCountCheck extends AbstractLogMessageCheck {
15
16     private static final String LOG_MESSAGE = "Log message placeholders count is incorrect.";
17     private static final String PLACEHOLDER = "{}";
18     private static final String EXCEPTION_TYPE = "Exception";
19
20     @Override
21     protected void visitLogMessage(DetailAST ast, String logMessage) {
22         int placeholdersCount = placeholdersCount(logMessage);
23         int argumentsCount = ast.findFirstToken(TokenTypes.ELIST).getChildCount(TokenTypes.EXPR) - 1;
24         final String lastArg = ast.findFirstToken(TokenTypes.ELIST).getLastChild().getFirstChild().getText();
25         if (hasCatchBlockParentWithArgument(lastArg, ast) || hasMethodDefinitionWithExceptionArgument(lastArg, ast)) {
26             argumentsCount--;
27         }
28         if (placeholdersCount > argumentsCount) {
29             log(ast.getLineNo(), LOG_MESSAGE);
30         }
31     }
32
33     private int placeholdersCount(final String message) {
34         return (message.length() - message.replace(PLACEHOLDER, "").length()) / PLACEHOLDER.length();
35     }
36
37     private boolean hasCatchBlockParentWithArgument(final String argumentName, final DetailAST ast) {
38         DetailAST parent = ast.getParent();
39         while (parent != null && parent.getType() != TokenTypes.LITERAL_CATCH) {
40             parent = parent.getParent();
41         }
42         if (parent != null && parent.findFirstToken(TokenTypes.PARAMETER_DEF) != null
43                 && parent.findFirstToken(TokenTypes.PARAMETER_DEF).findFirstToken(TokenTypes.IDENT).getText()
44                         .equals(argumentName)) {
45             return true;
46         }
47         return false;
48     }
49
50     private boolean hasMethodDefinitionWithExceptionArgument(final String argumentName, final DetailAST ast) {
51         DetailAST parent = ast.getParent();
52         while (parent != null && parent.getType() != TokenTypes.METHOD_DEF) {
53             parent = parent.getParent();
54         }
55         if (parent != null && parent.findFirstToken(TokenTypes.PARAMETERS).findFirstToken(TokenTypes.PARAMETER_DEF)
56                 != null) {
57             DetailAST paramDef = parent.findFirstToken(TokenTypes.PARAMETERS).getFirstChild();
58             while (paramDef != null) {
59                 if (paramDef.getType() == TokenTypes.PARAMETER_DEF) {
60                     final String paramName = paramDef.findFirstToken(TokenTypes.IDENT).getText();
61                     if (paramName.equals(argumentName) && isExceptionType(paramDef)) {
62                         return true;
63                     }
64                 }
65                 paramDef = paramDef.getNextSibling();
66             }
67         }
68         return false;
69     }
70
71     private boolean isExceptionType(final DetailAST parameterDef) {
72         if (parameterDef != null) {
73             final DetailAST type = parameterDef.findFirstToken(TokenTypes.TYPE);
74             if (type != null && type.findFirstToken(TokenTypes.IDENT) != null) {
75                 final String argumentType = type.findFirstToken(TokenTypes.IDENT).getText();
76                 if (argumentType.contains(EXCEPTION_TYPE)) {
77                     return true;
78                 }
79             }
80         }
81         return false;
82     }
83
84 }