1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 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.checks.sizes;
21  
22  import java.util.regex.Pattern;
23  
24  import com.puppycrawl.tools.checkstyle.StatelessCheck;
25  import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
26  import com.puppycrawl.tools.checkstyle.api.DetailAST;
27  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
28  
29  /**
30   * Checks for long lines.
31   *
32   * <p>
33   * Rationale: Long lines are hard to read in printouts or if developers
34   * have limited screen space for the source code, e.g. if the IDE displays
35   * additional information like project tree, class hierarchy, etc.
36   * </p>
37   *
38   * <p>
39   * Package statements and import statements (lines matching pattern
40   * {@code ^(package|import) .*}), and are not verified by this check.
41   * </p>
42   * <p>
43   * The default maximum allowable line length is 80 characters. To change the
44   * maximum, set property max.
45   * </p>
46   * <p>
47   * To ignore lines in the check, set property ignorePattern to a regular
48   * expression for the lines to ignore.
49   * </p>
50   * <p>
51   * An example of how to configure the check is:
52   * </p>
53   * <pre>
54   * &lt;module name="LineLength"/&gt;
55   * </pre>
56   * <p> An example of how to configure the check to accept lines up to 120
57   * characters long is:
58   *</p>
59   * <pre>
60   * &lt;module name="LineLength"&gt;
61   *    &lt;property name="max" value="120"/&gt;
62   * &lt;/module&gt;
63   * </pre>
64   * <p> An example of how to configure the check to ignore lines that begin with
65   * &quot; * &quot;, followed by just one word, such as within a Javadoc comment,
66   * is:
67   * </p>
68   * <pre>
69   * &lt;module name="LineLength"&gt;
70   *    &lt;property name="ignorePattern" value="^ *\* *[^ ]+$"/&gt;
71   * &lt;/module&gt;
72   * </pre>
73   *
74   */
75  @StatelessCheck
76  public class LineLengthCheck extends AbstractCheck {
77  
78      /**
79       * A key is pointing to the warning message text in "messages.properties"
80       * file.
81       */
82      public static final String MSG_KEY = "maxLineLen";
83  
84      /** Default maximum number of columns in a line. */
85      private static final int DEFAULT_MAX_COLUMNS = 80;
86  
87      /** Patterns matching package, import, and import static statements. */
88      private static final Pattern IGNORE_PATTERN = Pattern.compile("^(package|import) .*");
89  
90      /** The maximum number of columns in a line. */
91      private int max = DEFAULT_MAX_COLUMNS;
92  
93      /** The regexp when long lines are ignored. */
94      private Pattern ignorePattern = Pattern.compile("^$");
95  
96      @Override
97      public int[] getDefaultTokens() {
98          return getRequiredTokens();
99      }
100 
101     @Override
102     public int[] getAcceptableTokens() {
103         return getRequiredTokens();
104     }
105 
106     @Override
107     public int[] getRequiredTokens() {
108         return CommonUtil.EMPTY_INT_ARRAY;
109     }
110 
111     @Override
112     public void beginTree(DetailAST rootAST) {
113         final String[] lines = getLines();
114         for (int i = 0; i < lines.length; i++) {
115             final String line = lines[i];
116             final int realLength = CommonUtil.lengthExpandedTabs(
117                 line, line.length(), getTabWidth());
118 
119             if (realLength > max && !IGNORE_PATTERN.matcher(line).find()
120                 && !ignorePattern.matcher(line).find()) {
121                 log(i + 1, MSG_KEY, max, realLength);
122             }
123         }
124     }
125 
126     /**
127      * Sets the maximum length of a line.
128      * @param length the maximum length of a line
129      */
130     public void setMax(int length) {
131         max = length;
132     }
133 
134     /**
135      * Set the ignore pattern.
136      * @param pattern a pattern.
137      */
138     public final void setIgnorePattern(Pattern pattern) {
139         ignorePattern = pattern;
140     }
141 
142 }