JSDOC/Scope.js
[gnome.introspection-doc-generator] / JSDOC / Scope.js
1 //<Script type="text/javascript">
2
3 /**
4 * Scope stuff
5
6 * // FIXME - I need this to do next() without doccomments..
7 */
8
9 Identifier = imports['JSDOC/Identifier.js'].Identifier
10 XObject = imports.XObject.XObject; 
11
12
13 function Scope(braceN, parent, startTokN, lastIdent)
14 {
15     if (lastIdent.length) {
16        //  println("NEW SCOPE: " + lastIdent);
17     }
18     
19     this.braceN = braceN
20     this.parent = parent;
21     this.id = startTokN;
22     this.identifiers = { };
23     this.subScopes = [];
24     this.hints = { };
25     this.ident = lastIdent;
26     
27     
28     //println("ADD SCOPE(" + this.id + ") TO "+ (parent ? this.parent.id : 'TOP') + "<BR/>");
29     
30     if (parent) {
31         this.parent.subScopes.push(this);
32     } 
33     
34 }
35
36
37
38
39
40
41
42 Scope.prototype = {
43     
44     id : 0,
45     braceN : -1,
46     parent : false,
47     subScopes : false,
48     identifiers : false,  // map of identifiers to {Identifier} objects
49     hints: false, 
50     mungeM : true, 
51     ident: '',
52     
53     munged : false,
54     protectedVars : {}, // only used by to parent..
55     declareIdentifier : function(symbol, token) {
56         
57         //println("ADD IDENT(" + this.id + "):<B>" + symbol+"</B><BR/>");
58         
59         if (typeof(this.identifiers[symbol])== 'undefined') {
60             
61             this.identifiers[symbol] =  new Identifier(symbol, this);
62             
63         }
64         if (typeof(token) != 'undefined') { // shoudl this happen?
65             token.identifier = this.identifiers[symbol];
66             
67         }
68         if (this.braceN < 0) {
69                 // then it's global... 
70                 this.identifiers[symbol].toMunge  = false;
71         }
72         this.addToParentScope(symbol);
73         return this.identifiers[symbol];
74     },
75     getIdentifier : function(symbol) {
76         return (typeof(this.identifiers[symbol])== 'undefined') ? false : this.identifiers[symbol];
77     },
78     
79     addHint : function(varName, varType) {
80         this.hint[varName] = varType;
81     },
82     preventMunging : function() {
83         this.mungeM = false;
84     },
85
86     usedsymcache : false,
87     
88     getUsedSymbols : function() {
89         
90         var result = [];
91        // if (this.usedsymcache !== false) {
92         //    return this.usedsymcache;
93         //}
94         
95         var idents = this.identifiers;
96         for(var i in idents) { 
97             //println('<b>'+i+'</b>='+typeof(idents[i]) +'<br/>');
98             var identifier = this.identifiers[i];
99             var mungedValue = identifier.mungedValue
100             if (!mungedValue.length) {
101                 //println(identifier.toSource());
102                 mungedValue = identifier.name;
103             }
104             result.push(mungedValue);
105         }
106         //println("Symbols for ("+ this.id +"): <B>" + result.join(',') + "</B><BR/>");
107         //this.usedsymcache = result;
108         return result;
109     },
110
111     getAllUsedSymbols :function() {
112         var result = this.getUsedSymbols();
113         var scope = this.parent;
114         while (scope !== false) {
115             //println("addused:"+scope.id);
116             result = result.concat(scope.getUsedSymbols());
117             scope = scope.parent;
118         }
119          //println("Done - addused");
120         return result;
121     },
122     /** - we need to register short vairalbes so they never get munged into.. */
123     addToParentScope: function(ident) 
124     {
125         if (ident.length > 2) {
126             return;
127         }
128         var scope = this.parent;
129         while (scope !== false) {
130             //println("addused:"+scope.id);
131             if (!scope.parent) {
132                 scope.protectedVars[ident] = true;
133             }
134             scope = scope.parent;
135         }
136         
137     },
138     isProtectedVar: function(ident)
139     {
140         if (ident.length > 2) {
141             return false;
142         }
143         var scope = this.parent;
144         while (scope !== false) {
145             //println("addused:"+scope.id);
146             if (!scope.parent) {
147                 if (typeof(scope.protectedVars[ident])  != 'undefined') return true;
148             }
149             scope = scope.parent;
150         }
151         return false;
152     },
153     
154     /**
155      * set's all the munged values on the identifiers.
156      * 
157      * 
158      */
159
160     munge :function() 
161     {
162
163         if (!this.mungeM) {
164             // Stop right here if this scope was flagged as unsafe for munging.
165            // println("MUNGE: SKIP -  Scope" + this.id+"</BR>");
166             return;
167         }
168         if (this.munged) {
169             return;
170         }
171         
172
173         
174         
175         var pickFromSet = 1;
176
177         // Do not munge symbols in the global scope!
178         if (this.parent) {
179             print("MUNGE: SCOPE");
180             for (var i in this.identifiers) {
181                 print("MUNGE VAR:" + i);
182             }
183             
184             //println("MUNGE: Building FreeSyms:" + this.id+"</BR>");
185             
186             var freeSymbols = [];
187             var sy = this.getAllUsedSymbols();
188             
189             var addSyms=function(batch)
190             {
191                 for(var i =0;i<batch.length;i++) {
192                     if (sy.indexOf(batch[i]) > -1) {
193                         continue;
194                     }
195                     freeSymbols.push(batch[i]);
196                 }
197             }
198              
199             addSyms(Scope.ones); 
200              
201             var repsym = '';
202             //println(freeSymbols.toSource());
203             
204             //println("MUNGE: Replacing " + this.id+"</BR>");
205             for (var i in  this.identifiers) {
206                 
207                 // is the identifer in the global scope!?!!?
208                 
209                 
210                 if (!this.identifiers[i].toMunge) {
211                     continue;
212                 }
213                 
214                 if (this.isProtectedVar(i)) {
215                     continue; // 
216                 }
217                 
218                 
219                 
220                 if (this.identifiers[i].constructor !=  Identifier) {
221                     continue;
222                 }
223                // println("IDENT:" +i+'</BR>');
224                 
225                 if (!repsym.length) {
226                     if (!freeSymbols.length) {
227                         addSyms(JSDOC.Scope.twos); 
228                     }
229                     repsym = freeSymbols.shift(); // pop off beginngin???
230                 }
231                 
232                 var identifier = this.identifiers[i]; 
233                 //println(typeof(identifier.name));
234                 var mungedValue = identifier.name; 
235                 
236                 //println([     repsym,mungedValue ]);
237                 
238                 if (this.mungeM && repsym.length < mungedValue.length) {
239                     println("REPLACE:"+ mungedValue +" with " + repsym + "<BR>");    
240                     mungedValue = repsym;
241                     repsym = '';
242                 }
243                 
244                 identifier.mungedValue =  mungedValue;
245             }
246             //println("MUNGE: Done " + this.id+"</BR>");
247         }
248         this.munged = true;
249         //println("Doing sub scopes");
250         for (var i = 0; i < this.subScopes.length; i++) {
251             var ss = this.subScopes[i];
252             ss.munge();
253         }
254     }
255  
256
257 };
258
259
260
261
262
263 XObject.extend(Scope, {
264     
265     builtin : ["NaN","top"],
266     skips : [  'as', 'is', 'do', 'if', 'in', 'for', 'int', 'new', 'try', 'use', 'var', "NaN","top"],
267      
268     ones : [],
269     twos : [],
270     threes : [],
271     init : function () {
272         /* cache it later?
273         if (File.exists('/tmp/var_list_ones.js')) {
274             eval("JSDOC.Scope.ones = " + File.read('/tmp/var_list_ones.js'));
275             eval("JSDOC.Scope.twos = " + File.read('/tmp/var_twos_ones.js'));
276             eval("JSDOC.Scope.threes = " + File.read('/tmp/var_threes_ones.js'));
277         }
278         */
279         this.ones = 'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z'.split(',');
280         var a = this.ones;
281         var n = a.concat( '0,1,2,3,4,5,6,7,8,9'.split(','));
282         for(var i = 0; i < a.length; i++) {
283             for(var j = 0; j < n.length; j++) {
284                 var tw = a[i] + n[j];
285                 if (this.skips.indexOf(tw) < 0) {
286                     this.twos.push(tw);
287                 }
288                     
289                 /*
290                 for(var k = 0; k < n.length; k++) {
291                     var thr = a[i] + n[j] + n[k];
292                     //println("thr="+ thr + ":iOf="+this.skips.indexOf(thr) );
293                     if (this.skips.indexOf(thr)  < 0) {
294                         //println("+"+thr);
295                         this.threes.push(thr);
296                        }
297                     
298                 }
299                 */
300             }
301         }
302         //println("done creating var list");
303         //println("threes="+ this.threes.toSource());
304         //throw "DONE";
305         
306        
307     }
308 })
309 // init the scope constants..
310 Scope.init();
311