KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > dava > toolkits > base > renamer > Renamer


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2006 Nomair A. Naeem
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */

19
20 package soot.dava.toolkits.base.renamer;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26
27 import soot.Local;
28 import soot.RefLikeType;
29 import soot.SootClass;
30 import soot.SootField;
31 import soot.Type;
32 import soot.dava.internal.AST.ASTMethodNode;
33 import soot.util.Chain;
34
35
36 public class Renamer {
37     public final boolean DEBUG = false;
38     heuristicSet heuristics;
39
40     List JavaDoc locals; // a list of locals in scope
41

42     Chain fields; // a list of fields in scope
43

44     ASTMethodNode methodNode;
45     List JavaDoc forLoopNames;
46
47     HashMap JavaDoc changedOrNot;//keeps track of which local was changed previously
48

49     public Renamer(heuristicSet info, ASTMethodNode node) {
50         heuristics = info;
51         locals = null;
52         methodNode = node;
53         
54         changedOrNot = new HashMap JavaDoc();
55         Iterator JavaDoc localIt = info.getLocalsIterator();
56         while(localIt.hasNext())
57             changedOrNot.put(localIt.next(),new Boolean JavaDoc(false));
58         
59         
60         forLoopNames = new ArrayList JavaDoc();
61         forLoopNames.add("i");
62         forLoopNames.add("j");
63         forLoopNames.add("k");
64         forLoopNames.add("l");
65     }
66
67     /*
68      * Add any naming heuristic as a separate method and invoke the method from
69      * this method.
70      *
71      * HOWEVER, NOTE that the order of naming really really matters
72      */

73     public void rename() {
74         debug("rename","Renaming started");
75
76         // String args
77
mainMethodArgument();
78         
79         //for(i=0;i<bla;i++)
80
forLoopIndexing();
81         
82         //exceptions are named using first letter of each capital char in the class name
83
exceptionNaming();
84         
85         //if a local is assigned a field that name can be used since fields are conserved
86
assignedFromAField();
87         
88         //check if a local is assigned the result of a new invocation
89
newClassName();
90
91         //check if a local is assigned after casting
92
castedObject();
93         
94         //if nothing else give a reference the name of the class
95
objectsGetClassName();
96
97         //atleast remove the ugly dollar signs
98
removeDollarSigns();
99     }
100
101     /*
102      * The method assigns any local whose name hasnt been changed yet to
103      * the name of the class type it belongs to
104      */

105     private void objectsGetClassName(){
106         Iterator JavaDoc it = heuristics.getLocalsIterator();
107         while (it.hasNext()) {
108             Local tempLocal = (Local) it.next();
109             if(alreadyChanged(tempLocal)){
110                 continue;
111             }
112             
113             debug("objectsGetClassName","checking "+tempLocal);
114             
115             Type type = tempLocal.getType();
116             if(type instanceof RefLikeType){
117                 debug("objectsGetClassName","Local:"+tempLocal+" Type: "+type.toString());
118
119                 String JavaDoc tempClassName = type.toString();
120                 if(tempClassName.indexOf('.')!= -1){
121                     //contains a dot have to remove that
122
tempClassName=tempClassName.substring(tempClassName.lastIndexOf('.')+1);
123                 }
124                 
125                 
126                 String JavaDoc newName = tempClassName.toLowerCase();
127                 int count=0;
128                 newName += count;
129                 count++;
130                 
131                 while(!isUniqueName(newName)){
132                     newName = newName.substring(0,newName.length()-1)+count;
133                     count++;
134                 }
135                 setName(tempLocal,newName);
136
137             }
138         }
139         
140     }
141     
142     
143     
144     /*
145      * If a local is assigned the resullt of a cast expression temp = (List) object;
146      * then u can use list as the name...however only if its always casted to the same object
147      */

148     private void castedObject(){
149         debug("castedObject","");
150         
151         Iterator JavaDoc it = heuristics.getLocalsIterator();
152         while (it.hasNext()) {
153             Local tempLocal = (Local) it.next();
154             if(!alreadyChanged(tempLocal)){
155                 debug("castedObject","checking "+tempLocal);
156                 List JavaDoc classes = heuristics.getCastStrings(tempLocal);
157                 
158                 Iterator JavaDoc itClass = classes.iterator();
159                 String JavaDoc classNameToUse = null;
160                 while(itClass.hasNext()){
161                     String JavaDoc tempClassName = (String JavaDoc)itClass.next();
162                     if(tempClassName.indexOf('.')!= -1){
163                         //contains a dot have to remove that
164
tempClassName=tempClassName.substring(tempClassName.lastIndexOf('.')+1);
165                     }
166                     if(classNameToUse == null)
167                         classNameToUse = tempClassName;
168                     else if(!classNameToUse.equals(tempClassName)){
169                         //different new assignment
170
//cant use these classNames
171
classNameToUse=null;
172                         break;
173                     }
174                 }//going through class names stored
175
if(classNameToUse!=null){
176                     debug("castedObject","found a classNametoUse through cast expr");
177                     /*
178                      * We should use this classNAme to assign to the local name
179                      * We are guaranteed that all cast expressions use this type
180                      */

181                     String JavaDoc newName = classNameToUse.toLowerCase();
182                     int count=0;
183                     newName += count;
184                     count++;
185                     
186                     while(!isUniqueName(newName)){
187                         newName = newName.substring(0,newName.length()-1)+count;
188                         count++;
189                     }
190                     setName(tempLocal,newName);
191                 }
192             }//not already changed
193
}//going through locals
194
}
195     
196     /*
197      * See if any local was initialized using the new operator
198      * That name might give us a hint to a name to use for the local
199      */

200     private void newClassName(){
201         
202         debug("newClassName","");
203         //check if CLASSNAME is set
204
//that would mean there was new className invocation
205
Iterator JavaDoc it = heuristics.getLocalsIterator();
206         while (it.hasNext()) {
207             Local tempLocal = (Local) it.next();
208             if(!alreadyChanged(tempLocal)){
209                 debug("newClassName","checking "+tempLocal);
210                 List JavaDoc classes = heuristics.getObjectClassName(tempLocal);
211                 Iterator JavaDoc itClass = classes.iterator();
212                 String JavaDoc classNameToUse = null;
213                 while(itClass.hasNext()){
214                     String JavaDoc tempClassName = (String JavaDoc)itClass.next();
215                     if(tempClassName.indexOf('.')!= -1){
216                         //contains a dot have to remove that
217
tempClassName=tempClassName.substring(tempClassName.lastIndexOf('.')+1);
218                     }
219                     if(classNameToUse == null)
220                         classNameToUse = tempClassName;
221                     else if(!classNameToUse.equals(tempClassName)){
222                         //different new assignment
223
//cant use these classNames
224
classNameToUse=null;
225                         break;
226                     }
227                 }//going through class names stored
228
if(classNameToUse!=null){
229                     debug("newClassName","found a classNametoUse");
230                     /*
231                      * We should use this classNAme to assign to the local name
232                      * We are guaranteed that all new invocations use this class name
233                      */

234                     String JavaDoc newName = classNameToUse.toLowerCase();
235                     int count=0;
236                     newName += count;
237                     count++;
238                     
239                     while(!isUniqueName(newName)){
240                         newName = newName.substring(0,newName.length()-1)+count;
241                         count++;
242                     }
243                     setName(tempLocal,newName);
244                 }
245             }//not already changed
246
}//going through locals
247

248     }
249     
250     /*
251      * If a local is assigned from a field (static or non staitc) we can use that name
252      * to assign a some what better name for the local
253      *
254      * If multiple fields are assigned then it might be a better idea to not do
255      * anything since that will only confuse the user
256      *
257      */

258     private void assignedFromAField(){
259         Iterator JavaDoc it = heuristics.getLocalsIterator();
260         while (it.hasNext()) {
261             Local tempLocal = (Local) it.next();
262             if(!alreadyChanged(tempLocal)){
263                 debug("assignedFromField","checking "+tempLocal);
264                 List JavaDoc fieldNames = heuristics.getFieldName(tempLocal);
265                 if(fieldNames.size()>1){
266                     //more than one fields were assigned to this var
267
continue;
268                 }
269                 else if(fieldNames.size()==1){
270                     //only one field was used
271
String JavaDoc fieldName = (String JavaDoc)fieldNames.get(0);
272                     
273                     //okkay to use the name of the field if its not in scope
274
//eg it was some other classes field
275
int count=0;
276                     while(!isUniqueName(fieldName)){
277                         if(count==0)
278                             fieldName = fieldName+count;
279                         else
280                             fieldName = fieldName.substring(0,fieldName.length()-1)+count;
281                         count++;
282                     }
283                     
284                     setName(tempLocal,fieldName);
285                 }//only one field assigned to this local
286
}//not changed
287
}//going through locals
288
}
289     
290     
291     
292     
293     
294     
295     
296     /*
297      * If we cant come up with any better name atleast we should remove the $ signs
298      */

299     private void removeDollarSigns(){
300         Iterator JavaDoc it = heuristics.getLocalsIterator();
301         while (it.hasNext()) {
302             Local tempLocal = (Local) it.next();
303             String JavaDoc currentName = tempLocal.getName();
304             int dollarIndex = currentName.indexOf('$');
305             if(dollarIndex == 0){
306                 //meaning there is a $ sign in the first location
307
String JavaDoc newName = currentName.substring(1,currentName.length());
308                 
309
310                 if(isUniqueName(newName)){
311                     setName(tempLocal,newName);
312 // System.out.println("Changed "+currentName+" to "+newName);
313
//tempLocal.setName(newName);
314
}
315             }
316         }
317     }
318     
319     
320     
321     /*
322      *
323      */

324     private void exceptionNaming(){
325         Iterator JavaDoc it = heuristics.getLocalsIterator();
326         while (it.hasNext()) {
327             Local tempLocal = (Local) it.next();
328             Type localType = tempLocal.getType();
329             String JavaDoc typeString = localType.toString();
330             if(typeString.indexOf("Exception")>=0){
331                 //the string xception occurs in this type
332
debug("exceptionNaming","Type is an exception"+ tempLocal);
333                 
334                 //make a new name of all caps characters in typeString
335
String JavaDoc newName = "";
336                 for(int i=0;i<typeString.length();i++){
337                     char character = typeString.charAt(i);
338                     if(Character.isUpperCase(character)){
339                         newName += Character.toLowerCase(character);
340                     }
341                 }
342                 int count =0;
343                 if(!isUniqueName(newName)){
344                     count++;
345                     while(!isUniqueName(newName+count)){
346                         count++;
347                     }
348                 }
349                 if(count !=0)
350                     newName = newName + count;
351                 
352                 setName(tempLocal,newName);
353             }
354         }
355     }
356     
357     
358     
359     
360     
361     
362     /*
363      * Probably one of the most common programming idioms
364      * for loop indexes are often i j k l
365      */

366     private void forLoopIndexing(){
367         Iterator JavaDoc it = heuristics.getLocalsIterator();
368         while (it.hasNext()) {
369             Local tempLocal = (Local) it.next();
370             debug("foeLoopIndexing","Checking local"+tempLocal.getName());
371             if (heuristics.getHeuristic(tempLocal,
372                     infoGatheringAnalysis.FORLOOPUPDATE)) {
373                 // this local variable is the main argument
374
// will like to set it to args if no one has an objection
375
int count = -1;
376                 
377                 String JavaDoc newName;
378
379                 do{
380                     count++;
381                     if(count>=forLoopNames.size()){
382                         newName=null;
383                         break;
384                     }
385                     newName = (String JavaDoc)forLoopNames.get(count);
386                 }while (!isUniqueName(newName));
387
388                 if(newName!=null){
389                     setName(tempLocal,newName);
390                 }
391             }
392         }
393     }
394     
395     
396     
397     /*
398      * A simple heuristic which sets the mainMethodArgument's name to args
399      */

400     private void mainMethodArgument() {
401         Iterator JavaDoc it = heuristics.getLocalsIterator();
402         while (it.hasNext()) {
403             Local tempLocal = (Local) it.next();
404             if (heuristics.getHeuristic(tempLocal,
405                     infoGatheringAnalysis.MAINARG)) {
406
407                 // this local variable is the main argument
408
// will like to set it to args if no one has an objection
409
String JavaDoc newName = "args";
410                 int count = 0;
411                 while (!isUniqueName(newName)) {
412                     if(count==0)
413                         newName = newName+count;
414                     else
415                         newName = newName.substring(0,newName.length()-1)+count;
416
417                     count++;
418                 }
419                 setName(tempLocal,newName);
420                 //there cant be a same local with this heuristic set so just return
421
return;
422             }
423         }
424
425     }
426
427     
428     
429     
430     
431     /*
432      * In order to make sure that some previous heuristic which is usually a STRONGER
433      * heuristic has not already changed the name we use this method which checks for
434      * past name changes and only changes the name if the name hasnt been changed previously
435      */

436     private void setName(Local var, String JavaDoc newName){
437             
438         Object JavaDoc truthValue = changedOrNot.get(var);
439         
440         //if it wasnt in there add it
441
if(truthValue == null)
442             changedOrNot.put(var,new Boolean JavaDoc(false));
443         else{
444             if(((Boolean JavaDoc)truthValue).booleanValue()){
445                 //already changed just return
446
debug("setName","Var: "+var + " had already been renamed");
447                 return;
448             }
449         }
450         //will only get here if the var had not been changed
451

452         debug("setName","Changed "+var.getName()+" to "+newName);
453         var.setName(newName);
454         changedOrNot.put(var,new Boolean JavaDoc(true));
455     }
456
457     
458     
459     
460     
461     
462     
463     
464     
465     
466     
467     /*
468      * Check if a local has already been changed
469      * @param local to check
470      * @return true if already changed otherwise false
471      */

472     private boolean alreadyChanged(Local var){
473         Object JavaDoc truthValue = changedOrNot.get(var);
474         
475         //if it wasnt in there add it
476
if(truthValue == null){
477             changedOrNot.put(var,new Boolean JavaDoc(false));
478             return false;
479         }
480         else{
481             if(((Boolean JavaDoc)truthValue).booleanValue()){
482                 //already changed just return
483
debug("alreadyChanged","Var: "+var + " had already been renamed");
484                 return true;
485             }
486             else
487                 return false;
488         }
489     }
490
491     
492     
493     /*
494      * Should return true if the name is unique
495      */

496     private boolean isUniqueName(String JavaDoc name) {
497         Iterator JavaDoc it = getScopedLocals();
498         // check that none of the locals uses this name
499
while (it.hasNext()) {
500             Local tempLocal = (Local) it.next();
501             if (tempLocal.getName().equals(name)){
502                 debug("isUniqueName","New Name "+ name+ " is not unique (matches some local)..changing");
503                 return false;
504             }
505             else
506                 debug("isUniqueName","New Name "+ name+ " is different from local "+ tempLocal.getName());
507         }
508
509         it = getScopedFields();
510         // check that none of the fields uses this name
511
while (it.hasNext()) {
512             SootField tempField = (SootField) it.next();
513             if (tempField.getName().equals(name)){
514                 debug("isUniqueName","New Name "+ name+ " is not unique (matches field)..changing");
515                 return false;
516             }
517             else
518                 debug("isUniqurName","New Name "+ name+ " is different from field "+ tempField.getName());
519         }
520         return true;
521     }
522
523     /*
524      * Method is responsible to find all names with which there could be a
525      * potential clash The variables are: all the fields of this class and all
526      * the locals defined in this method
527      */

528     private Iterator JavaDoc getScopedFields() {
529         // get the fields for this class and store them
530
SootClass sootClass = methodNode.getDavaBody().getMethod()
531         .getDeclaringClass();
532         fields = sootClass.getFields();
533
534         return fields.iterator();
535     }
536
537     /*
538      * Method is responsible to find all variable names with which there could
539      * be a potential clash The variables are: all the fields of this class and
540      * all the locals defined in this method
541      */

542     private Iterator JavaDoc getScopedLocals() {
543         Iterator JavaDoc it = heuristics.getLocalsIterator();
544         
545         locals = new ArrayList JavaDoc();
546         while(it.hasNext())
547             locals.add((Local) it.next());
548
549         return locals.iterator();
550
551     }
552
553     public void debug(String JavaDoc methodName, String JavaDoc debug){
554         
555         if(DEBUG)
556             System.out.println(methodName+ " DEBUG: "+debug);
557     }
558     
559 }
Popular Tags