View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2026 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle;
21  
22  import java.util.Locale;
23  
24  import com.puppycrawl.tools.checkstyle.api.AuditEvent;
25  import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
26  
27  /**
28   * Represents the default formatter for log message.
29   * Default log message format is:
30   * [SEVERITY LEVEL] filePath:lineNo:columnNo: message. [CheckName]
31   * When the module id of the message has been set, the format is:
32   * [SEVERITY LEVEL] filePath:lineNo:columnNo: message. [ModuleId]
33   */
34  public class AuditEventDefaultFormatter implements AuditEventFormatter {
35  
36      /** Length of all separators. */
37      private static final int LENGTH_OF_ALL_SEPARATORS = 10;
38  
39      /** Suffix of module names like FooCheck. */
40      private static final String SUFFIX = "Check";
41  
42      /**
43       * Creates a new {@code AuditEventDefaultFormatter} instance.
44       */
45      public AuditEventDefaultFormatter() {
46          // no code by default
47      }
48  
49      @Override
50      public String format(AuditEvent event) {
51          final String fileName = event.getFileName();
52          final String message = event.getMessage();
53  
54          final SeverityLevel severityLevel = event.getSeverityLevel();
55          final String severityLevelName;
56          if (severityLevel == SeverityLevel.WARNING) {
57              // We change the name of severity level intentionally
58              // to shorten the length of the log message.
59              severityLevelName = "WARN";
60          }
61          else {
62              severityLevelName = severityLevel.getName().toUpperCase(Locale.US);
63          }
64  
65          final StringBuilder sb = initStringBuilderWithOptimalBuffer(event, severityLevelName);
66  
67          sb.append('[').append(severityLevelName).append("] ")
68              .append(fileName).append(':').append(event.getLine());
69          if (event.getColumn() > 0) {
70              sb.append(':').append(event.getColumn());
71          }
72          sb.append(": ").append(message).append(" [");
73          if (event.getModuleId() == null) {
74              final String checkShortName = getCheckShortName(event);
75              sb.append(checkShortName);
76          }
77          else {
78              sb.append(event.getModuleId());
79          }
80          sb.append(']');
81  
82          return sb.toString();
83      }
84  
85      /**
86       * Returns the StringBuilder that should avoid StringBuffer.expandCapacity.
87       * bufferLength = fileNameLength + messageLength + lengthOfAllSeparators +
88       * + severityNameLength + checkNameLength.
89       * Method is excluded from pitest validation.
90       *
91       * @param event audit event.
92       * @param severityLevelName severity level name.
93       * @return optimal StringBuilder.
94       */
95      private static StringBuilder initStringBuilderWithOptimalBuffer(AuditEvent event,
96              String severityLevelName) {
97          final int bufLen = LENGTH_OF_ALL_SEPARATORS + event.getFileName().length()
98              + event.getMessage().length() + severityLevelName.length()
99              + getCheckShortName(event).length();
100         return new StringBuilder(bufLen);
101     }
102 
103     /**
104      * Returns check name without 'Check' suffix.
105      *
106      * @param event audit event.
107      * @return check name without 'Check' suffix.
108      */
109     private static String getCheckShortName(AuditEvent event) {
110         final String checkFullName = event.getSourceName();
111         String checkShortName = checkFullName.substring(checkFullName.lastIndexOf('.') + 1);
112         if (checkShortName.endsWith(SUFFIX)) {
113             final int endIndex = checkShortName.length() - SUFFIX.length();
114             checkShortName = checkShortName.substring(0, endIndex);
115         }
116         return checkShortName;
117     }
118 
119 }