Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/puppycrawl/tools/checkstyle/checks/blocks/LeftCurlyCheck.java


1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2003  Oliver Burn
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  package com.puppycrawl.tools.checkstyle.checks.blocks;
20  
21  import com.puppycrawl.tools.checkstyle.api.DetailAST;
22  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
23  import com.puppycrawl.tools.checkstyle.api.Utils;
24  import com.puppycrawl.tools.checkstyle.checks.AbstractOptionCheck;
25  
26  /**
27   * <p>
28   * Checks the placement of left curly braces on types, methods and other the
29   * other blocks:
30   *  {@link  TokenTypes#LITERAL_CATCH LITERAL_CATCH},  {@link
31   * TokenTypes#LITERAL_DO LITERAL_DO},  {@link TokenTypes#LITERAL_ELSE
32   * LITERAL_ELSE},  {@link TokenTypes#LITERAL_FINALLY LITERAL_FINALLY},  {@link
33   * TokenTypes#LITERAL_FOR LITERAL_FOR},  {@link TokenTypes#LITERAL_IF
34   * LITERAL_IF},  {@link TokenTypes#LITERAL_SWITCH LITERAL_SWITCH},  {@link
35   * TokenTypes#LITERAL_SYNCHRONIZED LITERAL_SYNCHRONIZED},  {@link
36   * TokenTypes#LITERAL_TRY LITERAL_TRY},  {@link TokenTypes#LITERAL_WHILE
37   * LITERAL_WHILE}.
38   * </p>
39   *
40   * <p>
41   * The policy to verify is specified using the {@link LeftCurlyOption} class and
42   * defaults to {@link LeftCurlyOption#EOL}. Policies {@link LeftCurlyOption#EOL}
43   * and {@link LeftCurlyOption#NLOW} take into account property maxLineLength.
44   * The default value for maxLineLength is 80.
45   * </p>
46   * <p>
47   * An example of how to configure the check is:
48   * </p>
49   * <pre>
50   * &lt;module name="LeftCurly"/&gt;
51   * </pre>
52   * <p>
53   * An example of how to configure the check with policy
54   * {@link LeftCurlyOption#NLOW} and maxLineLength 120 is:
55   * </p>
56   * <pre>
57   * &lt;module name="LeftCurly"&gt;
58   *      &lt;property name="option"
59   * value="nlow"/&gt;     &lt;property name="maxLineLength" value="120"/&gt; &lt;
60   * /module&gt;
61   * </pre>
62   * @author Oliver Burn
63   * @author lkuehne
64   * @version 1.0
65   */
66  public class LeftCurlyCheck
67      extends AbstractOptionCheck
68  {
69      /** default maximum line length */
70      private static final int DEFAULT_MAX_LINE_LENGTH = 80;
71  
72      /** TODO: replace this ugly hack **/
73      private int mMaxLineLength = DEFAULT_MAX_LINE_LENGTH;
74  
75      /**
76       * Creates a default instance and sets the policy to EOL.
77       */
78      public LeftCurlyCheck()
79      {
80          super(LeftCurlyOption.EOL);
81      }
82  
83      /**
84       * Sets the maximum line length used in calculating the placement of the
85       * left curly brace.
86       * @param aMaxLineLength the max allowed line length
87       */
88      public void setMaxLineLength(int aMaxLineLength)
89      {
90          mMaxLineLength = aMaxLineLength;
91      }
92  
93      /** @see com.puppycrawl.tools.checkstyle.api.Check */
94      public int[] getDefaultTokens()
95      {
96          return new int[] {
97              TokenTypes.INTERFACE_DEF,
98              TokenTypes.CLASS_DEF,
99              TokenTypes.CTOR_DEF,
100             TokenTypes.METHOD_DEF,
101             TokenTypes.LITERAL_WHILE,
102             TokenTypes.LITERAL_TRY,
103             TokenTypes.LITERAL_CATCH,
104             TokenTypes.LITERAL_FINALLY,
105             TokenTypes.LITERAL_SYNCHRONIZED,
106             TokenTypes.LITERAL_SWITCH,
107             TokenTypes.LITERAL_DO,
108             TokenTypes.LITERAL_IF,
109             TokenTypes.LITERAL_ELSE,
110             TokenTypes.LITERAL_FOR,
111             // TODO: need to handle....
112             //TokenTypes.STATIC_INIT,
113         };
114     }
115 
116     /** @see com.puppycrawl.tools.checkstyle.api.Check */
117     public void visitToken(DetailAST aAST)
118     {
119         final DetailAST startToken;
120         final DetailAST brace;
121 
122         switch (aAST.getType()) {
123         case TokenTypes.CTOR_DEF :
124         case TokenTypes.METHOD_DEF :
125             startToken = aAST;
126             brace = aAST.findFirstToken(TokenTypes.SLIST);
127             break;
128 
129         case TokenTypes.INTERFACE_DEF :
130         case TokenTypes.CLASS_DEF :
131             // TODO: should check for modifiers
132             startToken = (DetailAST) aAST.getFirstChild().getNextSibling();
133             brace = (DetailAST) aAST.getLastChild().getFirstChild();
134             break;
135 
136         case TokenTypes.LITERAL_WHILE:
137         case TokenTypes.LITERAL_CATCH:
138         case TokenTypes.LITERAL_SYNCHRONIZED:
139         case TokenTypes.LITERAL_FOR:
140         case TokenTypes.LITERAL_TRY:
141         case TokenTypes.LITERAL_FINALLY:
142         case TokenTypes.LITERAL_DO:
143         case TokenTypes.LITERAL_IF :
144             startToken = aAST;
145             brace = aAST.findFirstToken(TokenTypes.SLIST);
146             break;
147 
148         case TokenTypes.LITERAL_ELSE :
149             startToken = aAST;
150             final DetailAST candidate = (DetailAST) aAST.getFirstChild();
151             brace =
152                 (candidate.getType() == TokenTypes.SLIST)
153                 ? candidate
154                 : null; // silently ignore
155             break;
156 
157         case TokenTypes.LITERAL_SWITCH :
158             startToken = aAST;
159             brace = aAST.findFirstToken(TokenTypes.LCURLY);
160             break;
161 
162         default :
163             startToken = null;
164             brace = null;
165         }
166 
167         if ((brace != null) && (startToken != null)) {
168             verifyBrace(brace, startToken);
169         }
170     }
171 
172     /**
173      * Verifies that a specified left curly brace is placed correctly
174      * according to policy.
175      * @param aBrace token for left curly brace
176      * @param aStartToken token for start of expression
177      */
178     private void verifyBrace(final DetailAST aBrace,
179                              final DetailAST aStartToken)
180     {
181         final String braceLine = getLines()[aBrace.getLineNo() - 1];
182 
183         // calculate the previous line length without trailing whitespace. Need
184         // to handle the case where there is no previous line, cause the line
185         // being check is the first line in the file.
186         final int prevLineLen = (aBrace.getLineNo() == 1)
187             ? mMaxLineLength
188             : Utils.lengthMinusTrailingWhitespace(
189                 getLines()[aBrace.getLineNo() - 2]);
190 
191         // Check for being told to ignore, or have '{}' which is a special case
192         if ((braceLine.length() > (aBrace.getColumnNo() + 1))
193             && (braceLine.charAt(aBrace.getColumnNo() + 1) == '}'))
194         {
195             ; // ignore
196         }
197         else if (getAbstractOption() == LeftCurlyOption.NL) {
198             if (!Utils.whitespaceBefore(aBrace.getColumnNo(), braceLine)) {
199                 log(aBrace.getLineNo(), aBrace.getColumnNo(),
200                     "line.new", "{");
201             }
202         }
203         else if (getAbstractOption() == LeftCurlyOption.EOL) {
204             if (Utils.whitespaceBefore(aBrace.getColumnNo(), braceLine)
205                 && ((prevLineLen + 2) <= mMaxLineLength))
206             {
207                 log(aBrace.getLineNo(), aBrace.getColumnNo(),
208                     "line.previous", "{");
209             }
210         }
211         else if (getAbstractOption() == LeftCurlyOption.NLOW) {
212             if (aStartToken.getLineNo() == aBrace.getLineNo()) {
213                 ; // all ok as on the same line
214             }
215             else if ((aStartToken.getLineNo() + 1) == aBrace.getLineNo()) {
216                 if (!Utils.whitespaceBefore(aBrace.getColumnNo(), braceLine)) {
217                     log(aBrace.getLineNo(), aBrace.getColumnNo(),
218                         "line.new", "{");
219                 }
220                 else if ((prevLineLen + 2) <= mMaxLineLength) {
221                     log(aBrace.getLineNo(), aBrace.getColumnNo(),
222                         "line.previous", "{");
223                 }
224             }
225             else if (!Utils.whitespaceBefore(aBrace.getColumnNo(), braceLine)) {
226                 log(aBrace.getLineNo(), aBrace.getColumnNo(),
227                     "line.new", "{");
228             }
229         }
230     }
231 }