Fix #5682 - fix path in title of source file
[roojspacker] / src / jsdoc / Scope.vala
1  
2
3 namespace JSDOC 
4 {
5         public int Scope_gid = 0;
6         
7         public class Scope : Object 
8         {
9         
10             int id ;
11                 int braceN ;
12                 public Scope parent;
13                 public Gee.ArrayList<Scope> subScopes;
14                 public string ident = ""; // used by the walker...
15                 
16                 Gee.HashMap<string,Identifier> identifier_map;   // map of identifiers to {Identifier} objects
17                 Gee.ArrayList<Identifier> identifier_list;
18                 
19                 Gee.HashMap<string,string> hints;
20                 bool mungeM = true;
21                 //ident: '',
22                 
23                 bool munged  = false;
24             Gee.HashMap<string,bool> protectedVars ; // only used by to parent..
25                 Token? token;
26                 // lastIdent is only used on the documentation parser..
27                 public Scope(int braceN, Scope? parent, int startTokN, string lastIdent, Token? token) // Identifier? lastIdent
28                 {
29                         if (lastIdent.length> 0 ) {
30                            GLib.debug("NEW SCOPE: %s", lastIdent);
31                         }
32                         this.ident = "";
33                         this.braceN = braceN;
34                         this.parent = parent;
35                         this.id = startTokN;
36                         this.identifier_map = new Gee.HashMap<string,Identifier>();
37                         this.identifier_list = new Gee.ArrayList<Identifier>();
38                         this.subScopes = new Gee.ArrayList<Scope> ();
39                         this.hints = new Gee.HashMap<string,string>();
40                         this.protectedVars = new Gee.HashMap<string,bool>();
41                         this.ident = lastIdent;
42                         this.id = Scope_gid++;
43                         this.token = token;
44                         //print("ADD SCOPE(" + this.gid + ") TO "+ (parent ? this.parent.gid : 'TOP') + ' : ' + 
45                         //    (token ? token.toString() : ''));
46                 
47                         if (parent != null) {
48                                 this.parent.subScopes.add(this);
49                         } 
50                         Scope.init();
51                 
52                 }
53
54
55
56
57
58
59
60          
61                 /**
62                  * dump the scope to StdOut...
63                  * 
64                  */
65                 public void dump (string indent = "") 
66                 {
67                     //indent = indent || '';
68                     
69                     var str = "";
70                          var idents = this.identifier_list;
71                     var iter = idents.list_iterator();
72                     while (iter.next()) {
73                             var identifier = iter.get();
74                             str += (str.length > 0 ? ", " : "");
75                                 str +=  indent + " " + identifier.name + "=>" +  identifier.mungedValue ;
76                         }
77                         
78                     print( "\n"+ 
79                         indent +  "Scope: %d\n" +
80                         indent + "Started: %s\n" +
81                         indent + "- idents..: %s\n",
82
83                                 this.id,
84                                 this.token != null ? this.token.asString()  : "TOP",
85                                 str
86                                 //                   " + XObject.keys(this.identifiers).join(", ") + "
87                     );
88                     foreach(var s in this.subScopes) {
89                            s.dump(indent + " ");
90                     };
91                     
92                     
93                 }
94     
95     
96                 public Identifier declareIdentifier(string symbol, Token token) 
97                 {
98                     
99                     //print("SCOPE : " + this.gid +  " :SYM: " + symbol + " " + token.toString()+"");
100                     
101                     if (!this.identifier_map.has_key(symbol)) {
102                                 var nid = new Identifier(symbol, this);
103                         this.identifier_list.add(nid);
104                         this.identifier_map.set(symbol,   nid);
105                         
106                     }
107                     
108                     //if (typeof(token) != 'undefined') { // shoudl this happen?
109                         token.identifier = this.identifier_map.get(symbol);
110                         
111                     //}
112                     if (this.braceN < 0) {
113                             // then it's global... 
114                     this.identifier_map.get(symbol).toMunge  = false;
115                     }
116                      
117                     
118                     this.addToParentScope(symbol);
119                     return this.identifier_map.get(symbol);
120                 }
121                 
122                 
123                 
124                 public Identifier? getIdentifier(string symbol, Token token) 
125                 {
126                     if (!this.identifier_map.has_key(symbol)) {
127                                 return null;
128                         //if (['String', 'Date'].indexOf(symbol)> -1) {
129                          //   return false;
130                         //}
131                         
132                         //print("SCOPE : " + this.gid +" = SYMBOL NOT FOUND?" + token.toString());
133                         //return n;
134                     }
135                      //print("SCOPE : " + this.gid +" = FOUND:" + token.toString());
136                     return this.identifier_map.get(symbol);
137                 }
138                 
139                 public void addHint(string varName, string varType) {
140                 
141                     this.hints.set(varName, varType);
142                 }
143                 public void preventMunging () {
144                     this.mungeM = false;
145                 }
146
147                 //usedsymcache : false,
148                 
149                 public string[] getUsedSymbols () {
150                     
151                     string[] result = {};
152                     
153                     // if (this.usedsymcache !== false) {
154                     //    return this.usedsymcache;
155                     //}
156                     
157                     var idents = this.identifier_list;
158                     var iter = idents.list_iterator();
159                     while (iter.next()) {
160                             var identifier = iter.get();
161                         //println('<b>'+i+'</b>='+typeof(idents[i]) +'<br/>');
162                         //var identifier = this.identifier_map.get(i);
163                         var mungedValue = identifier.mungedValue;
164                         
165                         if (mungedValue.length < 1) {
166                             //println(identifier.toSource());
167                             mungedValue = identifier.name;
168                         }
169                         result += mungedValue;
170                     }
171                     //println("Symbols for ("+ this.id +"): <B>" + result.join(',') + "</B><BR/>");
172                     //this.usedsymcache = result;
173                     return result;
174                 }
175
176                 string[] getAllUsedSymbols() 
177                 {
178                     var result = this.getUsedSymbols();
179                     var scope = this.parent;
180                     while (scope != null) {
181                                 var ps = scope.getUsedSymbols();
182                                 for (var i =0;  i< ps.length; i++) {
183                                         result += ps[i];
184                                 }
185                         scope = scope.parent;
186                     }
187                      //println("Done - addused");
188                     return result;
189                 }
190                 /** - we need to register short vairalbes so they never get munged into.. */
191                 public void addToParentScope(string ident) 
192                 {
193                     if (ident.length > 2) {
194                         return;
195                     }
196                     var scope = this.parent;
197                     while (scope != null) {
198                         //println("addused:"+scope.id);
199                         if (scope.parent != null) {
200                             scope.protectedVars.set(ident, true);
201                         }
202                         scope = scope.parent;
203                     }
204                     
205                 }
206                 public bool isProtectedVar(string ident)
207                 {
208                     //if (ident == "_this") { // not sure why we need to protect _this. as it should be calculated as protected..
209                         //      return true;
210                         //}
211                     
212                     if (ident.length > 2) {
213                         return false;
214                     }
215                     var scope = this.parent;
216                     while (scope != null) {
217                         //println("addused:"+scope.id);
218                         if (scope.parent != null) {
219                                 if (scope.protectedVars.has_key(ident)) {
220                                         return true;
221                                         }
222                         }
223                         scope = scope.parent;
224                     }
225                     return false;
226                 }
227                 
228                 
229                 
230                 
231                 /**
232                  * set's all the munged values on the identifiers.
233                  * 
234                  * 
235                  */
236
237                 public void munge() 
238                 {
239
240                     if (!this.mungeM) {
241                         // Stop right here if this scope was flagged as unsafe for munging.
242                        // println("MUNGE: SKIP -  Scope" + this.id+"</BR>");
243                         return;
244                     }
245                     if (this.munged) {
246                         return;
247                     }
248                     
249
250                     
251                     
252                     var pickFromSet = 1;
253
254                     // Do not munge symbols in the global scope!
255                     if (this.parent == null) {
256                                 // same code at bottom... ?? goto::
257                                 this.munged = true;
258                                 //println("Doing sub scopes");
259                                 for (var j = 0; j < this.subScopes.size; j++) {
260                                         this.subScopes.get(j).munge();
261                                         
262                                 }
263                     
264                                 return;
265                         }
266                         
267                     string[] all = {};
268                     var iter = this.identifier_list.list_iterator();
269                     while (iter.next()) {
270                         all += iter.get().name;
271                     }
272                     //print("MUNGE: %s\n", string.joinv(",", all));
273                         
274                         //println("MUNGE: Building FreeSyms:" + this.id+"</BR>");
275                         
276                     Gee.ArrayList<string> freeSymbols= new Gee.ArrayList<string>();
277                     
278                     var sy = this.getAllUsedSymbols();
279
280                     // we need to remove the used from the free.....
281                     
282                     
283                     
284                     
285                     
286                         
287                         Scope.array_merge(freeSymbols,Scope.ones,sy); 
288                          
289                     var repsym = "";
290                         //println(freeSymbols.toSource());
291                        
292                         //println("MUNGE: Replacing " + this.id+"</BR>");
293                     iter = this.identifier_list.list_iterator();
294                     while (iter.next()) {
295                                 var i = iter.get().name;
296                         
297                         // is the identifer in the global scope!?!!?
298                         
299                         
300                         if (!this.identifier_map.get(i).toMunge) {
301                             //print("SKIP toMunge==false : " + i)
302                             continue;
303                         }
304                         
305                         if (this.isProtectedVar(i)) {
306                             //print("SKIP PROTECTED: " + i)
307                             continue; // 
308                         }
309                         
310                         
311                         
312                         //if (this.identifiers[i].constructor !=  Identifier) {
313                         //    print("SKIP NOT IDENTIFIER : " + i)
314                         //    continue;
315                        // }
316                        // println("IDENT:" +i+'</BR>');
317                         
318                         if (repsym.length < 1) {
319                             if (freeSymbols.size < 1) {
320                                 Scope.array_merge(freeSymbols,Scope.twos,sy); 
321                             }
322                             repsym = freeSymbols.remove_at(0); // pop off beginngin???
323                         }
324                         
325                         var identifier = this.identifier_map.get(i); 
326                         //println(typeof(identifier.name));
327                         var mungedValue = identifier.name; 
328                         
329                         if (mungedValue.length < 3) {  // don't bother replacing 1&2 character variables..
330                                 continue;
331                         }
332                         
333                         //println([     repsym,mungedValue ]);
334                         
335                         if (this.mungeM && repsym.length < mungedValue.length) {
336                             //print("REPLACE:"+ mungedValue +" with " + repsym );    
337                             mungedValue = repsym;
338                             repsym = "";
339                         }
340                         
341                         identifier.mungedValue =  mungedValue;
342                     }
343                     //println("MUNGE: Done " + this.id+"</BR>");
344                          
345                         this.munged = true;
346                         //println("Doing sub scopes");
347                         for (var j = 0; j < this.subScopes.size; j++) {
348                                 this.subScopes.get(j).munge();
349                         }
350                 }
351                  
352
353
354                 // ---------------------- static part... --------------------
355
356
357
358                 static void array_merge(Gee.ArrayList<string> fs, string[] toadd, string[] ignore) 
359                 {
360                         var got_it = false;
361                         foreach(var i in toadd) {
362                                 got_it = false;
363                                 foreach(var ig in ignore) {
364                                         if (i == ig) {
365                                                 got_it = true;
366                                                 break;
367                                         }
368                                 }
369                                 if (got_it) {
370                                         continue;
371                                 }
372                                 fs.add(i);
373                         }
374                  
375                 }
376                 static bool initialized = false;
377                 public static Gee.ArrayList<string> builtin;
378                 public static Gee.ArrayList<string> skips;
379                          
380                 public static string[] ones;
381                 public static string[] twos;
382         //      static string[] threes : [],
383                 static  void init () 
384                 {
385                         if (Scope.initialized) {
386                                 return;
387                         }
388                         Scope.initialized = true;
389                         Scope.builtin = new Gee.ArrayList<string>(); 
390                         array_merge(Scope.builtin, "NaN,top".split(","), {});
391                 
392                         Scope.skips =  new Gee.ArrayList<string>(); 
393                         array_merge(Scope.skips, "as,is,do,if,in,for,int,new,try,use,var,NaN,top".split(","), {});
394                 
395                         Scope.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(",");
396                         var n = "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,0,1,2,3,4,5,6,7,8,9".split(",");
397
398                         string[] twos = {};
399                         for(var i = 0; i < Scope.ones.length; i++) {
400                             for(var j = 0; j < n.length; j++) {
401                                 string tw = Scope.ones[i] + n[j];
402                                 if (Scope.skips.index_of(tw) < 0) {
403                                     twos += tw;
404                                 }
405                                     
406                                 /*
407                                 for(var k = 0; k < n.length; k++) {
408                                     var thr = a[i] + n[j] + n[k];
409                                     //println("thr="+ thr + ":iOf="+this.skips.indexOf(thr) );
410                                     if (this.skips.indexOf(thr)  < 0) {
411                                         //println("+"+thr);
412                                         this.threes.push(thr);
413                                        }
414                                     
415                                 }
416                                 */
417                             }
418                         }
419                         Scope.twos = twos;
420                         //println("done creating var list");
421                         //println("threes="+ this.threes.toSource());
422                         //throw "DONE";
423                         
424                          
425                 }
426         
427         }
428 }
429
430
431