001: /*
002: * Hammurapi
003: * Automated Java code review system.
004: * Copyright (C) 2004 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.org
021: * e-Mail: support@hammurapi.biz
022: */
023: package org.hammurapi.inspectors.formatting;
024:
025: import com.pavelvlasov.jsel.impl.JavaTokenTypes;
026: import com.pavelvlasov.jsel.impl.Token;
027:
028: /**
029: * Implementation of FormattingChecker for formatting style with opening curly
030: * braces in the same line
031: *
032: * @author Jochen Skulj
033: * @version $Revision: 1.2 $
034: */
035: class FormattingCheckerSameLine extends FormattingCheckerBase {
036:
037: /**
038: * constructor
039: */
040: public FormattingCheckerSameLine() {
041: }
042:
043: // Dispatch methods
044: public boolean check_catch(Token aToken) {
045: return checkPrevRCurly(aToken) || checkNextLParen(aToken);
046: }
047:
048: public boolean check_LITERAL_do(Token aToken) {
049: return checkNextLCurly(aToken);
050: }
051:
052: public boolean check_LITERAL_else(Token aToken) {
053: boolean violation = checkPrevRCurly(aToken);
054: if (violation != true) {
055: // if the else-Token is followed by an if-token both tokens
056: // must be in the same line
057: Token next = nextNonWhitespace(aToken);
058: if (next.getType() == JavaTokenTypes.LITERAL_if) {
059: if (next.getLine() != aToken.getLine()) {
060: violation = true;
061: }
062: } else {
063: violation = checkNextLCurly(aToken);
064: }
065: }
066: return violation;
067: }
068:
069: public boolean check_LITERAL_finally(Token aToken) {
070: return (checkPrevRCurly(aToken) || checkNextLCurly(aToken));
071: }
072:
073: public boolean check_LITERAL_for(Token aToken) {
074: return checkNextLParen(aToken);
075: }
076:
077: public boolean check_LITERAL_if(Token aToken) {
078: return checkNextLParen(aToken);
079: }
080:
081: public boolean check_LITERAL_while(Token aToken) {
082: return checkWhile(aToken);
083: }
084:
085: public boolean check_LITERAL_switch(Token aToken) {
086: return checkNextLParen(aToken);
087: }
088:
089: public boolean check_LITERAL_synchronized(Token aToken) {
090: boolean violation = false;
091: Token next = nextNonWhitespace(aToken);
092: if (next.getType() == JavaTokenTypes.LPAREN) {
093: violation = checkNextLParen(aToken);
094: }
095: return violation;
096: }
097:
098: public boolean check_LITERAL_try(Token aToken) {
099: return checkNextLCurly(aToken);
100: }
101:
102: /**
103: * checks formatting for tokens that are followed by expression in parenthesis
104: *
105: * @param aToken
106: * currentToken
107: * @return <code>true<code> if the token violates a rule; otherwise <code>false</code>
108: */
109: protected boolean checkNextLParen(Token aToken) {
110: // The token must be followed by a variously complex braced expression.
111: // The expression must start in the same line as the token
112: // This expression is followed by a LCURLY. The last token of the
113: // expression and the LCURLY must be in the same line.
114: Token expressionFirst = nextNonWhitespace(aToken);
115: boolean violation = false;
116: if (expressionFirst.getLine() != aToken.getLine()) {
117: violation = true;
118: }
119: Token expressionLast = skipExpressionTokens(expressionFirst);
120: Token lcurly = nextNonWhitespace(expressionLast);
121: if (lcurly.getType() == JavaTokenTypes.LCURLY) {
122: if (expressionLast.getLine() != lcurly.getLine()) {
123: violation = true;
124: }
125: } else {
126: violation = true;
127: }
128: return violation;
129: }
130:
131: /**
132: * checks formatting for tokens that are follow opening curly brace (like do)
133: *
134: * @param aToken
135: * current Token
136: * @return <code>true<code> if the token violates a rule; otherwise <code>false</code>
137: */
138: protected boolean checkNextLCurly(Token aToken) {
139: // The token must be followed by a LCURLY in the same line
140: boolean violation = false;
141: Token lcurly = nextNonWhitespace(aToken);
142: if (lcurly.getType() == JavaTokenTypes.LCURLY) {
143: if (lcurly.getLine() != aToken.getLine()) {
144: violation = true;
145: }
146: } else {
147: violation = true;
148: }
149: return violation;
150: }
151:
152: /**
153: * checks formatting for tokens that are successors of a closing curly brace
154: * like else, catch or finally
155: *
156: * @param aToken
157: * current Token
158: * @return <code>true<code> if the token violates a rule; otherwise <code>false</code>
159: */
160: protected boolean checkPrevRCurly(Token aToken) {
161: // the token must have e previous RCURLY in the same line
162: Token rcurly = previousNonWhitespace(aToken);
163: boolean violation = false;
164: if (rcurly.getType() == JavaTokenTypes.RCURLY) {
165: if (rcurly.getLine() != aToken.getLine()) {
166: violation = true;
167: }
168: } else {
169: violation = true;
170: }
171: return violation;
172: }
173:
174: /**
175: * checks formatting for while-Tokens
176: *
177: * @param aToken
178: * current Token
179: * @return <code>true<code> if the token violates a rule; otherwise <code>false</code>
180: */
181: protected boolean checkWhile(Token aToken) {
182: // while can be used in two ways: as the beginning of a while-loop or
183: // the end of a do-loop. This is checked by inspecting previous tokens
184: boolean whileLoop = true;
185: Token previous = previousNonWhitespace(aToken);
186: if (previous.getType() == JavaTokenTypes.RCURLY) {
187: // get the matching LCURLY
188: int open = 1;
189: while (open > 0) {
190: previous = previousNonWhitespace(previous);
191: if (previous.getType() == JavaTokenTypes.LCURLY) {
192: --open;
193: }
194: if (previous.getType() == JavaTokenTypes.RCURLY) {
195: ++open;
196: }
197: }
198: // get the token previous to the matching LCURLY
199: previous = previousNonWhitespace(previous);
200: if (previous.getType() == JavaTokenTypes.LITERAL_do) {
201: whileLoop = false;
202: }
203: }
204: boolean violation = true;
205: if (whileLoop) {
206: // in a while-Loop the while is a token followed by a
207: // paranthesis
208: violation = checkNextLParen(aToken);
209: } else {
210: // in a do-Loop the while is a token that is a
211: // successor of a closing curly brace and that is
212: // followed by a expression in parenthesis and semicolon
213: violation = checkPrevRCurly(aToken);
214: if (!violation) {
215: Token expressionFirst = nextNonWhitespace(aToken);
216: if (expressionFirst.getLine() != aToken.getLine()) {
217: violation = true;
218: }
219: Token expressionLast = skipExpressionTokens(expressionFirst);
220: Token semicolon = nextNonWhitespace(expressionLast);
221: if (semicolon.getType() != JavaTokenTypes.SEMI
222: || semicolon.getLine() != aToken.getLine()) {
223: violation = true;
224: }
225: }
226:
227: }
228: return violation;
229: }
230:
231: /**
232: * skips all tokens of a expression in parenthesis
233: *
234: * @param currentToken
235: * first opening parenthesis of expression
236: * @return last closing parenthesis of expression
237: */
238: protected Token skipExpressionTokens(Token currentToken) {
239: int open = 0;
240: Token token = currentToken;
241: do {
242: if (token.getType() == JavaTokenTypes.LPAREN) {
243: ++open;
244: }
245: if (token.getType() == JavaTokenTypes.RPAREN) {
246: --open;
247: }
248:
249: if (open > 0) {
250: token = nextNonWhitespace(token);
251: }
252: } while (token != null && open > 0);
253: return token;
254: }
255:
256: /**
257: * skip all next tokens that are whitespaces
258: *
259: * @param aToken
260: * current token
261: * @return next non-whitespace token
262: */
263: protected Token nextNonWhitespace(Token aToken) {
264: Token current = (Token) aToken.getNextToken();
265: while (current.getType() == JavaTokenTypes.WS
266: || current.getType() == JavaTokenTypes.NEW_LINE) {
267: current = (Token) current.getNextToken();
268: }
269: return current;
270: }
271:
272: /**
273: * skip all previous tokens that are whitespaces
274: *
275: * @param aToken
276: * current token
277: * @return next previous non-whitespace token
278: */
279: protected Token previousNonWhitespace(Token aToken) {
280: Token current = (Token) aToken.getPrevToken();
281: while (current.getType() == JavaTokenTypes.WS
282: || current.getType() == JavaTokenTypes.NEW_LINE) {
283: current = (Token) current.getPrevToken();
284: }
285: return current;
286: }
287: }
|