KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > js > JsPrettyNamer


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.dev.js;
17
18 import com.google.gwt.dev.js.ast.JsName;
19 import com.google.gwt.dev.js.ast.JsProgram;
20 import com.google.gwt.dev.js.ast.JsRootScope;
21 import com.google.gwt.dev.js.ast.JsScope;
22
23 import java.util.HashSet JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Set JavaDoc;
27
28 /**
29  * A namer that uses short, readable idents to maximize reability.
30  */

31 public class JsPrettyNamer {
32
33   public static void exec(JsProgram program) {
34     new JsPrettyNamer(program).execImpl();
35   }
36
37   /**
38    * Communicates to a parent scope all the idents used by all child scopes.
39    */

40   private Set JavaDoc childIdents = null;
41
42   private final JsProgram program;
43
44   public JsPrettyNamer(JsProgram program) {
45     this.program = program;
46   }
47
48   private void execImpl() {
49     visit(program.getRootScope());
50   }
51
52   private boolean isLegal(JsScope scope, Set JavaDoc childIdents, String JavaDoc newIdent) {
53     if (JsKeywords.isKeyword(newIdent)) {
54       return false;
55     }
56     if (childIdents.contains(newIdent)) {
57       // one of my children already claimed this ident
58
return false;
59     }
60     /*
61      * Never obfuscate a name into an identifier that conflicts with an existing
62      * unobfuscatable name! It's okay if it conflicts with an existing
63      * obfuscatable name; that name will get obfuscated out of the way.
64      */

65     return (scope.findExistingUnobfuscatableName(newIdent) == null);
66   }
67
68   private void visit(JsScope scope) {
69     // Save off the childIdents which is currently being computed for my parent.
70
Set JavaDoc myChildIdents = childIdents;
71
72     /*
73      * Visit my children first. Reset childIdents so that my children will get a
74      * clean slate: I do not communicate to my children.
75      */

76     childIdents = new HashSet JavaDoc();
77     List JavaDoc children = scope.getChildren();
78     for (Iterator JavaDoc it = children.iterator(); it.hasNext();) {
79       visit((JsScope) it.next());
80     }
81
82     JsRootScope rootScope = program.getRootScope();
83     if (scope == rootScope) {
84       return;
85     }
86
87     // Visit all my idents.
88
for (Iterator JavaDoc it = scope.getAllNames(); it.hasNext();) {
89       JsName name = (JsName) it.next();
90       if (!name.isObfuscatable()) {
91         // Unobfuscatable names become themselves.
92
name.setShortIdent(name.getIdent());
93         continue;
94       }
95
96       String JavaDoc newIdent = name.getShortIdent();
97       if (!isLegal(scope, childIdents, newIdent)) {
98         String JavaDoc checkIdent = newIdent;
99         for (int i = 0; true; ++i) {
100           checkIdent = newIdent + "_" + i;
101           if (isLegal(scope, childIdents, checkIdent)) {
102             break;
103           }
104         }
105         name.setShortIdent(checkIdent);
106       } else {
107         // nothing to do; the short name is already good
108
}
109       childIdents.add(name.getShortIdent());
110     }
111     myChildIdents.addAll(childIdents);
112     childIdents = myChildIdents;
113   }
114 }
115
Popular Tags