001: ////////////////////////////////////////////////////////////////////////////////
002: // checkstyle: Checks Java source code for adherence to a set of rules.
003: // Copyright (C) 2001-2007 Oliver Burn
004: //
005: // This library is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU Lesser General Public
007: // License as published by the Free Software Foundation; either
008: // version 2.1 of the License, or (at your option) any later version.
009: //
010: // This library is distributed in the hope that it will be useful,
011: // but WITHOUT ANY WARRANTY; without even the implied warranty of
012: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: // Lesser General Public License for more details.
014: //
015: // You should have received a copy of the GNU Lesser General Public
016: // License along with this library; if not, write to the Free Software
017: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: ////////////////////////////////////////////////////////////////////////////////
019: package com.puppycrawl.tools.checkstyle.api;
020:
021: import antlr.collections.AST;
022:
023: /**
024: * Contains utility methods for working on scope.
025: *
026: * @author Oliver Burn
027: * @version 1.0
028: */
029: public final class ScopeUtils {
030: ///CLOVER:OFF
031: /** prevent instantiation */
032: private ScopeUtils() {
033: }
034:
035: ///CLOVER:ON
036:
037: /**
038: * Returns the Scope specified by the modifier set.
039: *
040: * @param aMods root node of a modifier set
041: * @return a <code>Scope</code> value
042: */
043: public static Scope getScopeFromMods(DetailAST aMods) {
044: Scope retVal = Scope.PACKAGE; // default scope
045: for (AST token = aMods.getFirstChild(); token != null; token = token
046: .getNextSibling()) {
047: if ("public".equals(token.getText())) {
048: retVal = Scope.PUBLIC;
049: break;
050: } else if ("protected".equals(token.getText())) {
051: retVal = Scope.PROTECTED;
052: break;
053: } else if ("private".equals(token.getText())) {
054: retVal = Scope.PRIVATE;
055: break;
056: }
057: }
058: return retVal;
059: }
060:
061: /**
062: * Returns the scope of the surrounding "block".
063: * @param aAST the node to return the scope for
064: * @return the Scope of the surrounding block
065: */
066: public static Scope getSurroundingScope(DetailAST aAST) {
067: Scope retVal = null;
068: for (DetailAST token = aAST.getParent(); token != null; token = token
069: .getParent()) {
070: final int type = token.getType();
071: if ((type == TokenTypes.CLASS_DEF)
072: || (type == TokenTypes.INTERFACE_DEF)
073: || (type == TokenTypes.ANNOTATION_DEF)
074: || (type == TokenTypes.ENUM_DEF)) {
075: final DetailAST mods = token
076: .findFirstToken(TokenTypes.MODIFIERS);
077: final Scope modScope = ScopeUtils
078: .getScopeFromMods(mods);
079: if ((retVal == null) || (retVal.isIn(modScope))) {
080: retVal = modScope;
081: }
082: } else if (type == TokenTypes.LITERAL_NEW) {
083: retVal = Scope.ANONINNER;
084: break; //because Scope.ANONINNER is not in any other Scope
085: }
086: }
087:
088: return retVal;
089: }
090:
091: /**
092: * Returns whether a node is directly contained within an interface block.
093: *
094: * @param aAST the node to check if directly contained within an interface
095: * block
096: * @return a <code>boolean</code> value
097: */
098: public static boolean inInterfaceBlock(DetailAST aAST) {
099: boolean retVal = false;
100:
101: // Loop up looking for a containing interface block
102: for (DetailAST token = aAST.getParent(); token != null; token = token
103: .getParent()) {
104: final int type = token.getType();
105: if ((type == TokenTypes.CLASS_DEF)
106: || (type == TokenTypes.ENUM_DEF)
107: || (type == TokenTypes.ANNOTATION_DEF)) {
108: break; // in a class, enum or annotation
109: } else if (type == TokenTypes.LITERAL_NEW) {
110: break; // inner implementation
111: } else if (type == TokenTypes.INTERFACE_DEF) {
112: retVal = true;
113: break;
114: }
115: }
116:
117: return retVal;
118: }
119:
120: /**
121: * Returns whether a node is directly contained within an annotation block.
122: *
123: * @param aAST the node to check if directly contained within an annotation
124: * block
125: * @return a <code>boolean</code> value
126: */
127: public static boolean inAnnotationBlock(DetailAST aAST) {
128: boolean retVal = false;
129:
130: // Loop up looking for a containing interface block
131: for (DetailAST token = aAST.getParent(); token != null; token = token
132: .getParent()) {
133: final int type = token.getType();
134: if ((type == TokenTypes.CLASS_DEF)
135: || (type == TokenTypes.ENUM_DEF)
136: || (type == TokenTypes.INTERFACE_DEF)) {
137: break; // in a class, enum or interface
138: } else if (type == TokenTypes.LITERAL_NEW) {
139: break; // inner implementation
140: } else if (type == TokenTypes.ANNOTATION_DEF) {
141: retVal = true;
142: break;
143: }
144: }
145:
146: return retVal;
147: }
148:
149: /**
150: * Returns whether a node is directly contained within an interface or
151: * annotation block.
152: *
153: * @param aAST the node to check if directly contained within an interface
154: * or annotation block
155: * @return a <code>boolean</code> value
156: */
157: public static boolean inInterfaceOrAnnotationBlock(DetailAST aAST) {
158: return inInterfaceBlock(aAST) || inAnnotationBlock(aAST);
159: }
160:
161: /**
162: * Returns whether a node is directly contained within an enum block.
163: *
164: * @param aAST the node to check if directly contained within an enum
165: * block
166: * @return a <code>boolean</code> value
167: */
168: public static boolean inEnumBlock(DetailAST aAST) {
169: boolean retVal = false;
170:
171: // Loop up looking for a containing interface block
172: for (DetailAST token = aAST.getParent(); token != null; token = token
173: .getParent()) {
174: final int type = token.getType();
175: if ((type == TokenTypes.INTERFACE_DEF)
176: || (type == TokenTypes.ANNOTATION_DEF)
177: || (type == TokenTypes.CLASS_DEF)) {
178: break; // in an interface, annotation or class
179: } else if (type == TokenTypes.LITERAL_NEW) {
180: break; // inner implementation, enums can't be inner classes
181: } else if (type == TokenTypes.ENUM_DEF) {
182: retVal = true;
183: break;
184: }
185: }
186:
187: return retVal;
188: }
189:
190: /**
191: * Returns whether the scope of a node is restricted to a code block.
192: * A code block is a method or constructor body, or a initialiser block.
193: *
194: * @param aAST the node to check
195: * @return a <code>boolean</code> value
196: */
197: public static boolean inCodeBlock(DetailAST aAST) {
198: boolean retVal = false;
199:
200: // Loop up looking for a containing code block
201: for (DetailAST token = aAST.getParent(); token != null; token = token
202: .getParent()) {
203: final int type = token.getType();
204: if ((type == TokenTypes.METHOD_DEF)
205: || (type == TokenTypes.CTOR_DEF)
206: || (type == TokenTypes.INSTANCE_INIT)
207: || (type == TokenTypes.STATIC_INIT)) {
208: retVal = true;
209: break;
210: }
211: }
212:
213: return retVal;
214: }
215:
216: /**
217: * Returns whether a node is contained in the outer most type block.
218: *
219: * @param aAST the node to check
220: * @return a <code>boolean</code> value
221: */
222: public static boolean isOuterMostType(DetailAST aAST) {
223: boolean retVal = true;
224: for (DetailAST parent = aAST.getParent(); parent != null; parent = parent
225: .getParent()) {
226: if ((parent.getType() == TokenTypes.CLASS_DEF)
227: || (parent.getType() == TokenTypes.INTERFACE_DEF)
228: || (parent.getType() == TokenTypes.ANNOTATION_DEF)
229: || (parent.getType() == TokenTypes.ENUM_DEF)) {
230: retVal = false;
231: break;
232: }
233: }
234:
235: return retVal;
236: }
237:
238: /**
239: * Determines whether a node is a local variable definition.
240: * I.e. if it is declared in a code block, a for initializer,
241: * or a catch parameter.
242: * @param aAST the node to check.
243: * @return whether aAST is a local variable definition.
244: */
245: public static boolean isLocalVariableDef(DetailAST aAST) {
246: // variable declaration?
247: if (aAST.getType() == TokenTypes.VARIABLE_DEF) {
248: final DetailAST parent = aAST.getParent();
249: if (parent != null) {
250: final int type = parent.getType();
251: return (type == TokenTypes.SLIST)
252: || (type == TokenTypes.FOR_INIT)
253: || (type == TokenTypes.FOR_EACH_CLAUSE);
254: }
255: }
256: // catch parameter?
257: else if (aAST.getType() == TokenTypes.PARAMETER_DEF) {
258: final DetailAST parent = aAST.getParent();
259: if (parent != null) {
260: return (parent.getType() == TokenTypes.LITERAL_CATCH);
261: }
262: }
263: return false;
264: }
265: }
|