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.refactor.method;
010:
011: import java.util.Iterator;
012: import java.util.LinkedList;
013: import net.sourceforge.jrefactory.ast.Node;
014: import net.sourceforge.jrefactory.ast.ASTClassBodyDeclaration;
015: import net.sourceforge.jrefactory.ast.ASTConstructorDeclaration;
016: import net.sourceforge.jrefactory.ast.ASTFormalParameter;
017: import net.sourceforge.jrefactory.ast.ASTFormalParameters;
018: import net.sourceforge.jrefactory.ast.ASTInitializer;
019: import net.sourceforge.jrefactory.ast.ASTMethodDeclaration;
020: import net.sourceforge.jrefactory.ast.ASTMethodDeclarator;
021: import net.sourceforge.jrefactory.ast.ASTVariableDeclaratorId;
022: import net.sourceforge.jrefactory.ast.ASTAnnotation;
023: import org.acm.seguin.summary.FieldAccessSummary;
024: import org.acm.seguin.summary.FileSummary;
025: import org.acm.seguin.summary.LocalVariableSummary;
026: import org.acm.seguin.summary.MessageSendSummary;
027: import org.acm.seguin.summary.MethodSummary;
028: import org.acm.seguin.summary.ParameterSummary;
029: import org.acm.seguin.summary.TypeSummary;
030: import org.acm.seguin.summary.VariableSummary;
031: import net.sourceforge.jrefactory.ast.ASTTypeParameters;
032:
033: /**
034: * Creates a list of arguments to the extacted method
035: *
036: *@author Chris Seguin
037: */
038: public class EMParameterFinder {
039: private FileSummary main;
040: private FileSummary extract;
041: private Node found;
042: private LinkedList list;
043: private LinkedList cantBe;
044: private LinkedList parameters;
045: private LinkedList returnTypes;
046:
047: /**
048: * Constructor for the EMParameterFinder object
049: */
050: public EMParameterFinder() {
051: list = new LinkedList();
052: cantBe = new LinkedList();
053: parameters = new LinkedList();
054: returnTypes = new LinkedList();
055: }
056:
057: /**
058: * Sets the MainFileSummary attribute of the EMParameterFinder object
059: *
060: *@param value The new MainFileSummary value
061: */
062: public void setMainFileSummary(FileSummary value) {
063: main = value;
064: }
065:
066: /**
067: * Sets the ExtractFileSummary attribute of the EMParameterFinder object
068: *
069: *@param value The new ExtractFileSummary value
070: */
071: public void setExtractFileSummary(FileSummary value) {
072: extract = value;
073: }
074:
075: /**
076: * Sets the Location attribute of the EMParameterFinder object
077: *
078: *@param value The new Location value
079: */
080: public void setLocation(Node value) {
081: found = value;
082: }
083:
084: /**
085: * Sets the order of the parameters
086: *
087: *@param data The new ParameterOrder value
088: */
089: public void setParameterOrder(Object[] data) {
090: parameters = new LinkedList();
091: for (int ndx = 0; ndx < data.length; ndx++) {
092: parameters.add(data[ndx]);
093: }
094: }
095:
096: /**
097: * Gets the list of parameters
098: *
099: *@return The List value
100: */
101: public LinkedList getList() {
102: return parameters;
103: }
104:
105: /**
106: * Main processing method for the EMParameterFinder object
107: */
108: public void run() {
109: TypeSummary type = (TypeSummary) extract.getTypes().next();
110: MethodSummary method = (MethodSummary) type.getMethods().next();
111:
112: MethodSummary mainMethod = find();
113:
114: Iterator iter = method.getDependencies();
115: if (iter == null) {
116: return;
117: }
118:
119: while (iter.hasNext()) {
120: Object next = iter.next();
121: if (next instanceof FieldAccessSummary) {
122: FieldAccessSummary fas = (FieldAccessSummary) next;
123: String fieldName = fas.getFirstObject();
124: updateLists(fieldName, mainMethod);
125: if (fas.isAssignment()) {
126: VariableSummary paramSummary = find(fieldName,
127: mainMethod);
128: if (paramSummary != null) {
129: addReturnType(paramSummary);
130: }
131: }
132: } else if (next instanceof MessageSendSummary) {
133: MessageSendSummary mss = (MessageSendSummary) next;
134: String name = mss.getFirstObject();
135: updateLists(name, mainMethod);
136: } else if (next instanceof LocalVariableSummary) {
137: LocalVariableSummary lvs = (LocalVariableSummary) next;
138: cantBe.add(lvs.getName());
139: addReturnType(lvs);
140: } else if (next instanceof ParameterSummary) {
141: ParameterSummary param = (ParameterSummary) next;
142: cantBe.add(param.getName());
143: }
144: }
145: }
146:
147: /**
148: * Returns the list of possible return types
149: *
150: *@return The ReturnTypes value
151: */
152: Object[] getReturnTypes() {
153: Object[] result = new Object[returnTypes.size() + 1];
154: Iterator iter = returnTypes.iterator();
155: result[0] = "void";
156: int count = 1;
157: while (iter.hasNext()) {
158: result[count] = iter.next();
159: count++;
160: }
161: return result;
162: }
163:
164: /**
165: * Determines if the method summary and the method parse tree are the same
166: *
167: *@param methodSummary the summary in question
168: *@param classBodyDecl Description of Parameter
169: *@return true if they appear to be the same
170: */
171: private boolean isSame(MethodSummary methodSummary,
172: ASTClassBodyDeclaration classBodyDecl) {
173: Node classChild = classBodyDecl.jjtGetFirstChild();
174: if (classChild instanceof ASTMethodDeclaration) {
175: int childNo = ((ASTMethodDeclaration) classChild)
176: .skipAnnotationsAndTypeParameters();
177: ASTMethodDeclarator decl = (ASTMethodDeclarator) classChild
178: .jjtGetChild(childNo + 1);
179: if (decl.getName().equals(methodSummary.getName())) {
180: ASTFormalParameters params = (ASTFormalParameters) decl
181: .jjtGetFirstChild();
182: return isParametersSame(params, methodSummary);
183: }
184: return false;
185: }
186:
187: if (classChild instanceof ASTConstructorDeclaration) {
188: ASTConstructorDeclaration decl = (ASTConstructorDeclaration) classChild;
189: if (methodSummary.isConstructor()) {
190: int childNo = decl.skipAnnotations();
191: ASTFormalParameters params = (ASTFormalParameters) decl
192: .jjtGetChild(childNo);
193: return isParametersSame(params, methodSummary);
194: }
195: return false;
196: }
197:
198: if (classChild instanceof ASTInitializer) {
199: return methodSummary.isInitializer();
200: }
201:
202: return false;
203: }
204:
205: /**
206: * Gets the ParametersSame attribute of the EMParameterFinder object
207: *
208: *@param methodSummary Description of Parameter
209: *@param params Description of Parameter
210: *@return The ParametersSame value
211: */
212: private boolean isParametersSame(Node params,
213: MethodSummary methodSummary) {
214: if (params.jjtGetNumChildren() == methodSummary
215: .getParameterCount()) {
216: if (methodSummary.getParameterCount() == 0) {
217: return true;
218: }
219: int count = 0;
220: Iterator iter = methodSummary.getParameters();
221: while (iter.hasNext()) {
222: ParameterSummary next = (ParameterSummary) iter.next();
223: Node nextNode = params.jjtGetChild(count);
224: ASTVariableDeclaratorId paramName = (ASTVariableDeclaratorId) nextNode
225: .jjtGetChild(1);
226:
227: String nextName = next.getName();
228: String parameterID = paramName.getName();
229:
230: if (!nextName.equals(parameterID)) {
231: return false;
232: }
233:
234: count++;
235: }
236: return true;
237: }
238:
239: return false;
240: }
241:
242: /**
243: * Checks to see if the lists have variables with the same names in it
244: *
245: *@param var Description of Parameter
246: *@param list Description of Parameter
247: *@return The Contained value
248: */
249: private boolean isContained(VariableSummary var, LinkedList list) {
250: Iterator iter = list.iterator();
251: while (iter.hasNext()) {
252: Object obj = iter.next();
253: if (obj instanceof VariableSummary) {
254: VariableSummary next = (VariableSummary) obj;
255: if (next.getName().equals(var.getName())) {
256: return true;
257: }
258: }
259: }
260:
261: return false;
262: }
263:
264: /**
265: * Finds the object we extracted the code from
266: *
267: *@return the portion of the parse tree
268: */
269: private ASTClassBodyDeclaration findDecl() {
270: Node current = found;
271: while (!(current instanceof ASTClassBodyDeclaration)) {
272: current = current.jjtGetParent();
273: if (current == null) {
274: return null;
275: }
276: }
277:
278: return (ASTClassBodyDeclaration) current;
279: }
280:
281: /**
282: * Finds the method summary
283: *
284: *@return the method summary
285: */
286: private MethodSummary find() {
287: ASTClassBodyDeclaration classBodyDecl = findDecl();
288: if (classBodyDecl == null) {
289: return null;
290: }
291: Iterator typeIterator = main.getTypes();
292: while (typeIterator.hasNext()) {
293: TypeSummary nextType = (TypeSummary) typeIterator.next();
294: Iterator methodIterator = nextType.getMethods();
295: while (methodIterator.hasNext()) {
296: MethodSummary nextMethod = (MethodSummary) methodIterator
297: .next();
298: if (isSame(nextMethod, classBodyDecl)) {
299: return nextMethod;
300: }
301: }
302: }
303:
304: return null;
305: }
306:
307: /**
308: * Searches for a variable declaration of a variable named name in the
309: * method summary method
310: *
311: *@param name the variable name
312: *@param method the method we are searching in
313: *@return the variable summary if one is found
314: */
315: private VariableSummary find(String name, MethodSummary method) {
316: if (method == null) {
317: return null;
318: }
319:
320: Iterator iter = method.getParameters();
321: while ((iter != null) && iter.hasNext()) {
322: ParameterSummary param = (ParameterSummary) iter.next();
323: if (param.getName().equals(name)) {
324: return param;
325: }
326: }
327:
328: iter = method.getDependencies();
329: while ((iter != null) && iter.hasNext()) {
330: Object next = iter.next();
331: if (next instanceof LocalVariableSummary) {
332: LocalVariableSummary lvs = (LocalVariableSummary) next;
333: if (lvs.getName().equals(name)) {
334: return lvs;
335: }
336: } else if (next instanceof ParameterSummary) {
337: ParameterSummary ps = (ParameterSummary) next;
338: if (ps.getName().equals(name)) {
339: return ps;
340: }
341: }
342: }
343:
344: return null;
345: }
346:
347: /**
348: * Updates the list of parameters for the extracted method
349: *
350: *@param name the method to add to the various lists
351: *@param mainMethod the method summary
352: */
353: private void updateLists(String name, MethodSummary mainMethod) {
354: if (name == null) {
355: // Do nothing
356: } else if (cantBe.contains(name)) {
357: //System.out.println("---" + name + " c");
358: } else if (!list.contains(name)) {
359: //System.out.println("Variable: " + name);
360: list.add(name);
361: VariableSummary paramSummary = find(name, mainMethod);
362: if (paramSummary != null) {
363: //System.out.println("\t***");
364: parameters.add(paramSummary);
365: }
366: } else {
367: //System.out.println("---" + name + " a");
368: }
369: }
370:
371: /**
372: * Adds a return type to the list
373: *
374: *@param var the variable summary to add
375: */
376: private void addReturnType(VariableSummary var) {
377: if (!isContained(var, returnTypes)) {
378: returnTypes.add(var);
379: }
380: }
381: }
|