001: /*
002: * Author: Chris Seguin
003: *
004: * This software has been developed under the copyleft
005: * rules of the GNU General Public License. Please
006: * consult the GNU General Public License for more
007: * details about use and distribution of this software.
008: */
009: package org.acm.seguin.pretty;
010:
011: import net.sourceforge.jrefactory.parser.JavaParserConstants;
012: import net.sourceforge.jrefactory.parser.Token;
013: import net.sourceforge.jrefactory.ast.ASTAnnotation;
014: import net.sourceforge.jrefactory.ast.ASTMemberValuePairs;
015: import net.sourceforge.jrefactory.ast.ASTMemberValuePair;
016: import net.sourceforge.jrefactory.ast.ASTMemberValue;
017: import net.sourceforge.jrefactory.ast.ASTMemberValueArrayInitializer;
018: import net.sourceforge.jrefactory.ast.ASTClassOrInterfaceType;
019:
020: import net.sourceforge.jrefactory.ast.ASTFieldDeclaration;
021:
022: import net.sourceforge.jrefactory.ast.ASTIdentifier;
023: import net.sourceforge.jrefactory.ast.ASTPrimitiveType;
024: import net.sourceforge.jrefactory.ast.ASTReferenceType;
025: import net.sourceforge.jrefactory.ast.ASTType;
026: import net.sourceforge.jrefactory.ast.ASTTypeArguments;
027: import net.sourceforge.jrefactory.ast.ASTVariableDeclaratorId;
028: import net.sourceforge.jrefactory.ast.AccessNode;
029: import net.sourceforge.jrefactory.ast.SimpleNode;
030: import net.sourceforge.jrefactory.ast.Node;
031:
032: /**
033: * Helps determine the size of a field for spacing purposes
034: *
035: * @author Chris Seguin
036: * @author Mike Atkinson
037: */
038: class FieldSizeLookAhead {
039: private FieldSize fieldSize;
040: private int code;
041:
042: /**
043: * Constructor for the FieldSizeLookAhead object
044: *
045: * @param init Description of Parameter
046: */
047: public FieldSizeLookAhead(int init) {
048: fieldSize = new FieldSize();
049: code = init;
050: }
051:
052: /**
053: * Main processing method for the FieldSizeLookAhead object
054: *
055: * @param body Description of Parameter
056: * @return Description of the Returned Value
057: */
058: public FieldSize run(SimpleNode body) {
059: int last = body.jjtGetNumChildren();
060: for (int ndx = 0; ndx < last; ndx++) {
061: Node child = body.jjtGetChild(ndx);
062: Node grandchild = child.jjtGetFirstChild();
063: if (grandchild instanceof ASTFieldDeclaration) {
064: ASTFieldDeclaration field = (ASTFieldDeclaration) grandchild;
065: if ((code != PrintData.DFS_NOT_WITH_JAVADOC)
066: || !isJavadocAttached(field)) {
067: int equalsLength = computeEqualsLength(field);
068: fieldSize.setMinimumEquals(equalsLength);
069: }
070: }
071: }
072:
073: return fieldSize;
074: }
075:
076: /**
077: * Compute the size of the modifiers, type, and name
078: *
079: * @param field the field in question
080: * @return the size of the modifiers, type, and name
081: */
082: public int computeEqualsLength(ASTFieldDeclaration field) {
083: int modifierLength = computeModifierLength(field);
084: int typeLength = computeTypeLength(field);
085: int nameLength = computeNameLength(field);
086:
087: int equalsLength = modifierLength + typeLength + nameLength;
088: return equalsLength;
089: }
090:
091: /**
092: * Computes the length of the field declaration type
093: *
094: * @param field the field
095: * @return the number
096: */
097: public int computeTypeLength(ASTFieldDeclaration field) {
098: int childNo = field.skipAnnotations();
099: ASTType typeNode = (ASTType) field.jjtGetChild(childNo);
100: int typeLength = 0;
101: //2 * typeNode.getArrayCount();
102: if (typeNode.jjtGetFirstChild() instanceof ASTPrimitiveType) {
103: ASTPrimitiveType primitive = (ASTPrimitiveType) typeNode
104: .jjtGetFirstChild();
105: typeLength += primitive.getName().length();
106: } else if (typeNode.jjtGetFirstChild() instanceof ASTReferenceType) {
107: typeLength += computeReferenceTypeLength((ASTReferenceType) typeNode
108: .jjtGetFirstChild());
109: } else {
110: //System.out.println("ERROR: computeTypeLength typeNode.jjtGetFirstChild()="+typeNode.jjtGetFirstChild());
111: //ASTName name = (ASTName) typeNode.jjtGetFirstChild();
112: //typeLength += name.getName().length();
113: }
114: fieldSize.setTypeLength(typeLength);
115: return typeLength;
116: }
117:
118: /**
119: * Computes the length of the reference type declaration
120: *
121: * @param reference the field
122: * @return the number
123: * @since JRefactory 2.7.00
124: */
125: public int computeReferenceTypeLength(ASTReferenceType reference) {
126: int typeLength = 0;
127: Node child = reference.jjtGetFirstChild();
128: if (child instanceof ASTPrimitiveType) {
129: typeLength += ((ASTPrimitiveType) child).getName().length();
130: } else if (child instanceof ASTClassOrInterfaceType) {
131: typeLength += ((ASTClassOrInterfaceType) child).getName()
132: .length();
133: // FIXME this does not take into account TypeArgument
134: } else {
135: // FIXME: sometimes the child is a CompilationUnit which should not be a child of a ASTReferenceType
136: //System.out.println("Error: reference="+reference);
137: //System.out.println("Error: reference.jjtGetChild(child)="+reference.jjtGetChild(child));
138: }
139: typeLength += reference.getArrayCount() * 2;
140: for (int ndx = 1; ndx < reference.jjtGetNumChildren(); ndx++) {
141: if (reference.jjtGetChild(ndx) instanceof ASTTypeArguments) {
142: // FIXME: handle TypeArguments length
143: }
144: }
145:
146: return typeLength;
147: }
148:
149: /**
150: * Gets the JavadocAttached attribute of the FieldSizeLookAhead object
151: *
152: * @param node Description of Parameter
153: * @return The JavadocAttached value
154: */
155: private boolean isJavadocAttached(ASTFieldDeclaration node) {
156: int childNo = node.skipAnnotations();
157: ASTType type = (ASTType) node.jjtGetChild(childNo);
158: return hasJavadoc(node.getSpecial("static"))
159: || hasJavadoc(node.getSpecial("transient"))
160: || hasJavadoc(node.getSpecial("volatile"))
161: || hasJavadoc(node.getSpecial("final"))
162: || hasJavadoc(node.getSpecial("public"))
163: || hasJavadoc(node.getSpecial("protected"))
164: || hasJavadoc(node.getSpecial("private"))
165: || hasJavadoc(getInitialToken(type));
166: }
167:
168: /**
169: * Check the initial token, and removes it from the object.
170: *
171: * @param top the type
172: * @return the initial token
173: */
174: private Token getInitialToken(ASTType top) {
175: if (top.jjtGetFirstChild() instanceof ASTPrimitiveType) {
176: ASTPrimitiveType primitiveType = (ASTPrimitiveType) top
177: .jjtGetFirstChild();
178: return primitiveType.getSpecial("primitive");
179: } else if (top.jjtGetFirstChild() instanceof ASTReferenceType) {
180: ASTReferenceType reference = (ASTReferenceType) top
181: .jjtGetFirstChild();
182: if (reference.jjtGetFirstChild() instanceof ASTPrimitiveType) {
183: ASTPrimitiveType primitiveType = (ASTPrimitiveType) reference
184: .jjtGetFirstChild();
185: return primitiveType.getSpecial("primitive");
186: } else {
187: ASTClassOrInterfaceType name = (ASTClassOrInterfaceType) reference
188: .jjtGetFirstChild();
189: ASTIdentifier ident = (ASTIdentifier) name
190: .jjtGetFirstChild();
191: return ident.getSpecial("id");
192: }
193: } else {
194: // FIXME: this should not occur now!
195: ASTClassOrInterfaceType name = (ASTClassOrInterfaceType) top
196: .jjtGetFirstChild();
197: ASTIdentifier ident = (ASTIdentifier) name
198: .jjtGetFirstChild();
199: return ident.getSpecial("id");
200: }
201: }
202:
203: /**
204: * Description of the Method
205: *
206: * @param field Description of Parameter
207: * @return Description of the Returned Value
208: */
209: private int computeNameLength(ASTFieldDeclaration field) {
210: int childNo = field.skipAnnotations();
211: ASTVariableDeclaratorId id = (ASTVariableDeclaratorId) field
212: .jjtGetChild(childNo + 1).jjtGetFirstChild();
213: int nameLength = id.getName().length();
214: nameLength += id.getArrayCount() * 2;
215: fieldSize.setNameLength(nameLength);
216: return nameLength;
217: }
218:
219: /**
220: * Description of the Method
221: *
222: * @param field Description of Parameter
223: * @return Description of the Returned Value
224: */
225: private int computeModifierLength(ASTFieldDeclaration field) {
226: int fieldLength = field.getModifiersString(
227: PrintData.STANDARD_ORDER).length();
228: fieldSize.setModifierLength(fieldLength);
229: return fieldLength;
230: }
231:
232: /**
233: * Description of the Method
234: *
235: * @param tok Description of Parameter
236: * @return Description of the Returned Value
237: */
238: private boolean hasJavadoc(Token tok) {
239: Token current = tok;
240: while (current != null) {
241: if (current.kind == JavaParserConstants.FORMAL_COMMENT) {
242: return true;
243: }
244:
245: current = current.specialToken;
246: }
247:
248: return false;
249: }
250: }
|