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/ParenPadCheck.java


1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2002  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  
20  package com.puppycrawl.tools.checkstyle.checks;
21  
22  import com.puppycrawl.tools.checkstyle.api.DetailAST;
23  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
24  import com.puppycrawl.tools.checkstyle.api.Utils;
25  
26  /**
27   * <p>Checks the padding of parentheses; that is whether a space is required
28   * after a left parenthesis and before a right parenthesis, or such spaces are
29   * forbidden, with the exception that it does
30   * not check for padding of the right parenthesis  at an empty for iterator.
31   * Use Check {@link EmptyForIteratorPad} to validate empty for iterators.
32   * <p>
33   * </p>
34   * The policy to verify is specified using the {@link PadOption} class and
35   * defaults to {@link PadOption#NOSPACE}.
36   * </p>
37   * <p> By default the check will check parentheses that occur with the following
38   * tokens:
39   *  {@link TokenTypes#CTOR_CALL CTOR_CALL},
40   *  {@link TokenTypes#LPAREN LPAREN},
41   *  {@link TokenTypes#METHOD_CALL METHOD_CALL},
42   *  {@link TokenTypes#RPAREN RPAREN},
43   *  {@link TokenTypes#SUPER_CTOR_CALL SUPER_CTOR_CALL},
44   *  {@link TokenTypes#TYPECAST TYPECAST}.
45   * </p>
46   * <p>
47   * An example of how to configure the check is:
48   * </p>
49   * <pre>
50   * &lt;module name="ParenPad"/&gt;
51   * </pre> 
52   * <p>
53   * An example of how to configure the check to require spaces for the
54   * parentheses of constructor, method, and super constructor invocations is:
55   * </p>
56   * <pre>
57   * &lt;module name="ParenPad"&gt;
58   *     &lt;property name="tokens"
59   *               value="CTOR_CALL, METHOD_CALL, SUPER_CTOR_CALL"/&gt;
60   *     &lt;property name="option" value="space"/&gt;
61   * &lt;/module&gt;
62   * </pre>
63   * @author <a href="mailto:checkstyle@puppycrawl.com">Oliver Burn</a>
64   * @version 1.0
65   */
66  public class ParenPadCheck
67      extends AbstractOptionCheck
68  {    
69      /**
70       * Sets the paren pad otion to nospace.
71       */  
72      public ParenPadCheck()
73      {
74          super(PadOption.NOSPACE);
75      }
76      
77      /** @see com.puppycrawl.tools.checkstyle.api.Check */
78      public int[] getDefaultTokens()
79      {
80          return new int[] {TokenTypes.RPAREN,
81                            TokenTypes.LPAREN,
82                            TokenTypes.CTOR_CALL,
83                            TokenTypes.SUPER_CTOR_CALL,
84                            TokenTypes.TYPECAST, // TODO: treat this?
85                            TokenTypes.METHOD_CALL,
86          };
87      }
88  
89      /** @see com.puppycrawl.tools.checkstyle.api.Check */
90      public void visitToken(DetailAST aAST)
91      {
92          if (aAST.getType() == TokenTypes.RPAREN) {
93              processRight(aAST);
94          }
95          else {
96              processLeft(aAST);
97          }
98      }
99  
100     /**
101      * Process a token representing a left parentheses.
102      * @param aAST the token representing a left parentheses
103      */
104     private void processLeft(DetailAST aAST)
105     {
106         final String line = getLines()[aAST.getLineNo() - 1];
107         final int after = aAST.getColumnNo() + 1;
108         if (after < line.length()) {
109             if ((PadOption.NOSPACE == getAbstractOption())
110                 && (Character.isWhitespace(line.charAt(after))))
111             {
112                 log(aAST.getLineNo(), after, "ws.followed", "(");
113             }
114             else if ((PadOption.SPACE == getAbstractOption())
115                      && !Character.isWhitespace(line.charAt(after))
116                      && (line.charAt(after) != ')'))
117             {
118                 log(aAST.getLineNo(), after, "ws.notFollowed", "(");
119             }
120         }
121     }
122 
123     /**
124      * Process a token representing a right parentheses.
125      * @param aAST the token representing a right parentheses
126      */
127     private void processRight(DetailAST aAST)
128     {
129         final String line = getLines()[aAST.getLineNo() - 1];
130         final int before = aAST.getColumnNo() - 1;
131         if (before >= 0) {
132             boolean followsEmptyForIterator = false;
133             final DetailAST parent = aAST.getParent();
134             if ((parent != null) 
135                 && (parent.getType() == TokenTypes.LITERAL_FOR))
136             {
137                 final DetailAST forIterator =
138                     parent.findFirstToken(TokenTypes.FOR_ITERATOR);
139                 followsEmptyForIterator = (forIterator.getChildCount() == 0)
140                     && (aAST == forIterator.getNextSibling());
141             }
142             if (followsEmptyForIterator) {
143                 return;
144             }
145             else if ((PadOption.NOSPACE == getAbstractOption())
146                 && Character.isWhitespace(line.charAt(before))
147                 && !Utils.whitespaceBefore(before, line))
148             {
149                 log(aAST.getLineNo(), before, "ws.preceeded", ")");
150             }
151             else if ((PadOption.SPACE == getAbstractOption())
152                 && !Character.isWhitespace(line.charAt(before))
153                 && (line.charAt(before) != '('))
154             {
155                 log(aAST.getLineNo(), aAST.getColumnNo(),
156                     "ws.notPreceeded", ")");
157             }
158         }
159     }
160 }