Fix #5682 - fix path in title of source file
[roojspacker] / roojspacker / Walker.vala
1 // this walks through the code, and tries to find patterns that match documentable elements..
2
3
4 namespace JSDOC {
5
6         enum WalkerMode {
7                 BUILDING_SYMBOL_TREE,
8                 XXX
9         }
10         
11         public class Walker  : Object
12         {
13                 TokenStream ts;
14                 Gee.ArrayList<string> warnings;
15                 Gee.ArrayList<Scope> scopes;
16                 Gee.HashMap<int,Scope> indexedScopes;
17                 Gee.HashMap<string,Symbol> symbols;
18                 Gee.HashMap<string,string> aliases;
19                 Scope globalScope;
20                 
21         bool global = false;
22         WalkerMode mode =  WalkerMode.XXX; //"BUILDING_SYMBOL_TREE",
23         int braceNesting = 0;
24         
25         DocComment? currentDoc =  null;
26
27         bool munge =  true;
28                 
29                 public Walker(TokenStream ts)
30                 {
31                         this.ts  = ts;
32                         this.warnings= new Gee.ArrayList<string>();
33                         this.scopes = new Gee.ArrayList<Scope>();
34                         this.indexedScopes = new Gee.HashMap<int,Scope>();
35                         this.symbols = new Gee.HashMap<string,Symbol>();
36                         this.aliases = new Gee.HashMap<string,string>();
37                         this.braceNesting = 0;
38                 }
39
40         //warn: function(s) {
41             //this.warnings.push(s);
42         //    print("WARNING:" + htmlescape(s) + "<BR>");
43         //},
44         // defaults should not be initialized here =- otherwise they get duped on new, rather than initalized..
45
46
47
48
49
50
51         public void buildSymbolTree()
52         {
53             //print("<PRE>");
54             
55             this.ts.rewind();
56             this.braceNesting = 0;
57             this.scopes = new Gee.ArrayList<Scope>();;
58                         this.aliases = new Gee.HashMap<string,string>();
59              
60             this.globalScope = new Scope(-1, null, -1,  "$global$", null);
61             this.indexedScopes = new Gee.HashMap<int,Scope>();
62             this.indexedScopes.set(  0,  this.globalScope );
63             
64             this.mode = WalkerMode.BUILDING_SYMBOL_TREE;
65             this.parseScope(this.globalScope,this.emptyAlias());
66             
67         }
68         Gee.HashMap<string,string>  emptyAlias()
69         {
70                 return new Gee.HashMap<string,string> ();
71         }
72         
73         
74
75         string fixAlias (Gee.HashMap<string,string>aliases, string str, bool nomore = false)
76         {
77             var ar = str.split(".");
78             var m = ar[0];
79             
80             //print(str +"?=" +aliases.toSource());
81             if (!aliases.has_key(m)) {
82                 return str;
83             }
84             ar[0] = aliases.get(m);
85             
86             var ret = string.joinv(".", ar);
87             if (nomore != true) {
88                 ret = this.fixAlias(aliases, ret, true);
89             }
90             
91             
92             return ret;
93         }
94
95         
96
97         void parseScope (Scope in_scope, Gee.HashMap<string,string> ealiases) // parse a token stream..
98         {
99             //this.timerPrint("parseScope EnterScope"); 
100             
101             var scope = in_scope;
102             
103             var aliases = new Gee.HashMap<string,string>();
104
105             foreach(var i in ealiases.keys) {
106                 aliases.set(i, ealiases.get(i));
107             }
108                 
109             //print("STARTING SCOPE WITH: " + ealiases.toSource());
110              
111             var expressionBraceNesting = this.braceNesting;
112             var bracketNesting = 0;
113             var parensNesting = 0;
114            
115             
116             var l1 = "", l2 = "";
117             var scopeName = "";
118             
119             
120             var locBraceNest = 0;
121             // determines if we are in object literals...
122             
123             var isObjectLitAr = new Gee.ArrayList<bool>();
124             isObjectLitAr.add(false);
125             //print("SCOPE: ------------------START ----------------");
126
127             this.scopesIn(scope);
128             var scopeLen = this.scopes.size;
129             
130             if (this.ts.cursor < 1) {
131               // this.ts.cursor--; // hopeflly this kludge will work
132             }
133             
134             
135             //print(JSON.stringify(this.ts, null, 4)); Seed.quit();
136             Token token;
137             while (null != ( token = this.ts.next())) {
138                  //GLib.debug("TOK %s", token.asString());
139                 //  this.timerPrint("parseScope AFTER lookT: " + token.toString()); 
140                   
141                 if (token.isType(TokenType.COMM)) {
142                       
143                  
144                     if (!token.isName(TokenName.JSDOC)) {
145                         //print("Walker2 : spce is not JSDOC");
146                         continue; //skip.
147                     }
148                     if (this.currentDoc != null) {
149                         // add it to the current scope????
150                         
151                         this.addSymbol("", true);
152                         //print ( "Unconsumed Doc: " + token.toString())
153                         //throw "Unconsumed Doc (TOKwhitespace): " + this.currentDoc.toSource();
154                     }
155                     
156                    // print ( "NEW COMMENT: " + token.toString())
157                     var newDoc = new DocComment(token.data);
158                     
159                     // it"s a scope changer..
160                     
161                     if (newDoc.getTag(DocTagTitle.SCOPE).size > 0) {
162                         //print("Walker2 : doctag changes scope");
163                         //throw "done";
164                         scope.ident = "$private$|" + newDoc.getTag(DocTagTitle.SCOPE).get(0).desc;
165                         continue;
166                     } 
167                     
168                     // it"s a scope changer..
169                     if (newDoc.getTag(DocTagTitle.SCOPEALIAS).size > 0) {
170                         //print(newDoc.getTag("scopeAlias").toSource());
171                         // @scopeAlias a=b
172                         //print("Walker2 : doctag changes scope (alias)");
173                         var sal = newDoc.getTag(DocTagTitle.SCOPEALIAS).get(0).desc.split("=");
174                         aliases[sal[0].strip()] = sal[1].strip();
175                         
176                         continue;
177                     }
178                     
179                     
180                     /// got a  doc comment..
181                     //token.data might be this.??? (not sure though)
182                     //print("Walker2 : setting currentDoc");
183                     this.currentDoc = newDoc;
184                     continue;
185                 }
186                 
187                 // catch the various issues .. - scoe changes or doc actions..
188                 
189               
190                 
191                 // things that stop comments carrying on...??
192                 
193                 if (this.currentDoc != null && (
194                         token.data == ";" || 
195                         token.data == "}")) {
196                     this.addSymbol("", true);
197                     //throw "Unconsumed Doc ("+ token.toString() +"): " + this.currentDoc.toSource();
198                 }
199                     
200                 
201                 // the rest are scoping issues...
202                 
203                 // var a = b;
204                 
205                  if (token.isName(TokenName.VAR) &&
206                  
207                         this.ts.lookTok(1).isType(TokenType.NAME) &&
208                         this.ts.lookTok(2).data == "=" &&
209                         this.ts.lookTok(3).isType(TokenType.NAME) &&
210                         this.ts.lookTok(4).data == ";"  
211                         
212                  
213                  ) {
214                     //print("SET ALIAS:" + this.ts.lookTok(1).data +"=" + this.ts.lookTok(3).data);
215                      
216                     aliases.set(this.ts.lookTok(1).data, this.ts.lookTok(3).data);
217                 
218                 }
219                 
220                 if ((token.data == "eval") || /\.eval$/.match(token.data)) {
221                     this.currentDoc = null;
222                     continue;
223                 }
224               
225                 // extends scoping  *** not sure if the can be x = Roo.apply(....)
226                 // xxx.extends(a,b, {
227                     // $this$=b|b.prototype
228                 // xxx.apply(a, {
229                     // a  << scope
230                 // xxx.applyIf(a, {
231                     // a  << scope
232                 if (token.isType(TokenType.NAME) ) {
233                     
234                     //print("TOK(ident)"+ token.toString());
235                      
236                     if (/\.extend$/.match(token.data) &&
237                         this.ts.lookTok(1).data == "(" &&
238                         this.ts.lookTok(2).isType(TokenType.NAME)  &&
239                         this.ts.lookTok(3).data == "," &&
240                         this.ts.lookTok(4).isType(TokenType.NAME)  &&
241                         this.ts.lookTok(5).data == "," &&
242                         this.ts.lookTok(6).data == "{" 
243                            
244                         ) {
245                         // ignore test for ( a and ,
246                         this.ts.nextTok(); /// (
247                         token = this.ts.nextTok(); // a
248                         scopeName = token.data;
249                         
250                         if (this.currentDoc != null) {
251                             this.addSymbol(scopeName,false,"OBJECT");
252
253                         }
254                         this.ts.nextTok(); // ,
255                         this.ts.nextTok(); // b
256                         
257                         
258                         this.ts.nextTok(); // ,
259                         token = this.ts.nextTok(); // {
260                             
261                         scopeName = this.fixAlias(aliases, scopeName);
262                         
263                         var fnScope = new Scope(this.braceNesting, scope, token.id, // was token.n?
264                                         "$this$=" + scopeName  + "|"+scopeName+".prototype", null
265                                         );
266                         
267     
268                         this.indexedScopes.set(this.ts.cursor, fnScope);
269                         scope = fnScope;
270                         this.scopesIn(fnScope);
271                        
272                         locBraceNest++;
273                         //print(">>" +locBraceNest);
274                         continue; // no more processing..
275                         
276                     }
277                     
278                     // a = Roo.extend(parentname, {
279                         
280                      if (/\.extend$/.match(token.data) &&
281                         this.ts.lookTok(-2).isType(TokenType.NAME)  &&
282                         this.ts.lookTok(-1).data == "=" &&
283                         this.ts.lookTok(1).data == "(" &&
284                         this.ts.lookTok(2).isType(TokenType.NAME) &&
285                         this.ts.lookTok(3).data == "," &&
286                         this.ts.lookTok(4).data == "{" 
287                         ) {
288                         // ignore test for ( a and ,
289                         token = this.ts.lookTok(-2);
290                         scopeName = token.data;
291                         if (this.currentDoc != null) {
292                             this.addSymbol(scopeName,false,"OBJECT");
293
294                         }
295                         this.ts.nextTok(); /// (
296                         this.ts.nextTok(); // parent
297                         
298                         this.ts.nextTok(); // ,
299                         token =  this.ts.nextTok(); // {
300                              
301                         
302                         scopeName = this.fixAlias(aliases,scopeName);
303                         var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
304                                          "$this$=" + scopeName  + "|"+scopeName+".prototype",
305                                                  null
306                                         );
307                         
308                          
309                         this.indexedScopes.set(this.ts.cursor, fnScope);
310                         scope = fnScope;
311                         this.scopesIn(fnScope);
312                        
313                         locBraceNest++;
314                         //print(">>" +locBraceNest);
315                         continue; // no more processing..
316                         
317                     }
318                     
319                     
320                      // apply ( XXXX,  {
321                     /*
322                     print(JSON.stringify([
323                         token.data,
324                         this.ts.lookTok(1).data ,
325                         this.ts.lookTok(2).type ,
326                         this.ts.lookTok(3).data ,
327                         this.ts.lookTok(4).data 
328                     ], null, 4));
329                     */
330                     
331                     if (/\.(applyIf|apply)$/.match(token.data) && 
332                         this.ts.lookTok(1).data == "("  &&
333                         this.ts.lookTok(2).isType(TokenType.NAME) &&
334                         this.ts.lookTok(3).data == ","  &&
335                         this.ts.lookTok(4).data == "{" 
336                         
337                         ) {
338                         this.ts.nextTok(); /// (
339                          
340                         //print("GOT : applyIF!"); 
341                          
342                         token = this.ts.nextTok(); // b
343                         scopeName = token.data;
344                         
345                                       
346                         if (this.currentDoc != null) {
347                             this.addSymbol(scopeName,false,"OBJECT");
348                         }
349                      
350
351                         
352                         this.ts.nextTok(); /// ,
353                         this.ts.nextTok(); // {
354                         scopeName = this.fixAlias(aliases,scopeName);
355                         var fnScope =   new Scope(this.braceNesting, scope, token.id, // was token.n?
356                                         scopeName, null
357                                         );
358
359                         this.indexedScopes.set(this.ts.cursor, fnScope);
360                         scope = fnScope;
361                         this.scopesIn(fnScope);
362                          
363                         locBraceNest++;
364                         //print(">>" +locBraceNest);
365                         continue; // no more processing..
366                     }
367                     
368                     
369                     // xxx = new yyy ( {
370                         
371                     // change scope to xxxx
372                     /*
373                     print(JSON.stringify([
374                         this.ts.lookTok(1).data ,
375                         this.ts.lookTok(2).name ,
376                         this.ts.lookTok(3).type ,
377                         this.ts.lookTok(4).data ,
378                         this.ts.lookTok(5).data 
379                     ], null, 4));
380                     */
381                     if ( this.ts.lookTok(1).data == "=" &&
382                         this.ts.lookTok(2).isName(TokenName.NEW) &&
383                         this.ts.lookTok(3).isType(TokenType.NAME)&&
384                         this.ts.lookTok(4).data == "(" &&
385                         this.ts.lookTok(5).data == "{" 
386                         ) {
387                         scopeName = token.data;
388                         if (this.currentDoc != null) {
389                             this.addSymbol(scopeName,false,"OBJECT");
390                             
391                         }
392                         
393                         this.ts.nextTok(); /// =
394                         this.ts.nextTok(); /// new
395                         this.ts.nextTok(); /// yyy
396                         this.ts.nextTok(); /// (
397                         this.ts.nextTok(); /// {
398                             
399                         scopeName = this.fixAlias(aliases,scopeName);
400                         var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
401                                         scopeName,null
402                                         ); 
403                         this.indexedScopes.set(this.ts.cursor,  fnScope);
404                         scope = fnScope;
405                         this.scopesIn(fnScope);
406                          
407                         locBraceNest++;
408                         //print(">>" +locBraceNest);
409                         
410                         continue; // no more processing..
411                     }
412                     
413
414                      
415                     
416                     
417                     
418                     
419                     // eval can be prefixed with a hint hider for the compresser..
420                     
421                     
422                     if (this.currentDoc != null) {
423                         //print(token.toString());
424                         
425                         // ident : function ()
426                         // ident = function ()
427                         var atype = "OBJECT";
428                         
429                         if (((this.ts.lookTok(1).data == ":" )|| (this.ts.lookTok(1).data == "=")) &&
430                             (this.ts.lookTok(2).isName(TokenName.FUNCTION))
431                             ) {
432                                // this.ts.nextTok();
433                                // this.ts.nextTok();
434                                 atype = "FUNCTION";
435                         }
436                         
437                         //print("ADD SYM:" + atype + ":" + token.toString() + this.ts.lookTok(1).toString() + this.ts.lookTok(2).toString());
438                         
439                         this.addSymbol(
440                             this.ts.lookTok(-1).data == "." ? token.data :    this.fixAlias(aliases,token.data),
441                             false,
442                             atype);
443                         
444
445                         this.currentDoc = null;
446                         
447                         
448                         
449                         
450                         
451                         
452                     }
453                  
454                     
455                     continue; // dont care about other idents..
456                     
457                 }
458                 
459                 //print ("NOT NAME");
460                 
461                 
462                 if (token.isType(TokenType.STRN))   { // THIS WILL NOT HAPPEN HERE?!!?
463                     if (this.currentDoc != null) {
464                         this.addSymbol(token.data.substring(1,token.data.length-1),false,"OBJECT");
465                     }
466                 }
467             
468                 // really we only have to deal with object constructs and function calls that change the scope...
469                 
470                 
471                 if (token.isName(TokenName.FUNCTION)) {
472                     //print("GOT FUNCTION");
473                     // see if we have an unconsumed doc...
474                     
475                         if (this.currentDoc != null) {
476                         GLib.error("Unhandled doc (TOKfunction) %s", token.asString());
477                     }
478                     
479                      
480                      
481                      
482                      
483                     /// foo = function() {} << really it set"s the "this" scope to foo.prototype
484                     //$this$=foo.prototype|$private$|foo.prototype
485         
486                     if (
487                             (this.ts.lookTok(-1).data == "=") && 
488                             (this.ts.lookTok(-2).isType(TokenType.NAME))
489                         ) {
490                         scopeName = this.ts.lookTok(-2).data;
491                         this.ts.balance(TokenName.LEFT_PAREN);
492                         token = this.ts.nextTok(); // should be {
493                         //print("FOO=FUNCITON() {}" + this.ts.context() + "\n" + token.toString());
494                         
495                         
496                         scopeName = this.fixAlias(aliases, scopeName);
497                         var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
498                                         "$this$="+scopeName+".prototype|$private$|"+scopeName+".prototype",
499                                         null
500                                         ); 
501                         
502                         this.indexedScopes.set(this.ts.cursor, fnScope);
503                         //scope = fnScope;
504                         //this.scopesIn(fnScope);
505                         this.parseScope(fnScope, aliases);
506                         
507                         
508                        
509                         locBraceNest++;
510                         //print(">>" +locBraceNest);
511                         continue; // no more processing..    
512                           
513                         
514                     }
515                         
516                 
517                 // foo = new function() {}
518                         // is this actually used much!?!?!
519                         //$private$
520                         
521                     if (
522                             (this.ts.lookTok(-1).isName(TokenName.NEW)) && 
523                             (this.ts.lookTok(-2).data == "=") &&
524                             (this.ts.lookTok(-3).isName(TokenName.FUNCTION))
525                         ) {
526                         //scopeName = this.ts.look(-3).data;
527                         this.ts.balance(TokenName.LEFT_PAREN);
528                         token = this.ts.nextTok(); // should be {
529                         scopeName = this.fixAlias(aliases, scopeName);
530                         var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
531                                         "$private$",null
532                                         ); 
533                         
534                         
535                         this.indexedScopes.set(this.ts.cursor,  fnScope);
536                         //scope = fnScope;
537                         //this.scopesIn(fnScope);
538                         this.parseScope(fnScope, aliases);
539                         
540                         locBraceNest++;
541                         //print(">>" +locBraceNest);
542                         continue; // no more processing..    
543                           
544                         
545                     }    
546                    
547                     
548     ///==== check/set isObjectLitAr ??                
549                     
550                     
551                  // foo: function() {}
552                         // no change to scoping..
553                         
554                     //print("checking for : function() {"); 
555                     //print( [this.ts.lookTok(-3).type , this.ts.lookTok(-2).type , this.ts.lookTok(-1).type ].join(":"));
556                     if (
557                             (this.ts.lookTok(-1).data == ":") && 
558                             (this.ts.lookTok(-2).isType(TokenType.NAME)) &&
559                             (this.ts.lookTok(-3).data == "(" || this.ts.lookTok(-3).data== ",") 
560                         ) {
561                         //print("got for : function() {"); 
562                             
563                         //scopeName = this.ts.look(-3).data;
564                         this.ts.balance(TokenName.LEFT_PAREN);
565                         //print(token.toString())
566                         token = this.ts.nextTok(); // should be {
567                         //print(token.toString())
568                         
569                         scopeName = this.fixAlias(aliases, scopeName);
570                         var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
571                                         "", null
572                                         ); 
573
574                         this.indexedScopes.set(this.ts.cursor, fnScope);
575                         //scope = fnScope;
576                         //this.scopesIn(fnScope);
577                          this.parseScope(fnScope, aliases);
578                         locBraceNest++;
579                         //print(">>" +locBraceNest);
580                         continue; // no more processing..    
581                           
582                     } 
583                /// function foo() {} << really it set"s the "this" scope to foo.prototype
584                         //$this$=foo|$private$
585                         //$this$=foo
586                         
587                     if (
588                             (this.ts.lookTok(1).isType(TokenType.NAME)) 
589                         ) {
590                         //scopeName = this.ts.look(-3).data;
591                         this.ts.balance(TokenName.LEFT_PAREN);
592                         token = this.ts.nextTok(); // should be {
593                         var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
594                                         "", null
595                                         ); 
596
597                         this.indexedScopes.set(this.ts.cursor, fnScope);
598                         //scope = fnScope;
599                         //this.scopesIn(fnScope);
600                         this.parseScope(fnScope, aliases);
601                         locBraceNest++;
602                         //print(">>" +locBraceNest);
603                         continue; // no more processing..    
604                           
605                     }
606                     
607                      
608                 // foo = new (function() { }
609                 // (function() { }
610                 // RETURN function(...) {
611                     
612                     if (
613                            // (this.ts.lookTok(-1).tokN == Script.TOKlparen) && 
614                             (!this.ts.lookTok(1).isType(TokenType.NAME))   
615                             
616                         //    (this.ts.lookTok(-2).tokN == Script.TOKnew) &&
617                          //   (this.ts.lookTok(-3).tokN == Script.TOKassign) &&
618                          //   (this.ts.lookTok(-4).tokN == Script.TOKidentifier)
619                         ) {
620                         //scopeName = this.ts.look(-3).data;
621                         this.ts.balance(TokenName.LEFT_PAREN);
622                         token = this.ts.nextTok(); // should be {
623                         var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
624                                                 "$private$",null
625                                         ); 
626
627                         this.indexedScopes.set(this.ts.cursor, fnScope);
628                         //scope = ;
629                         //this.scopesIn(fnScope);
630                          this.parseScope(fnScope, aliases);
631                         locBraceNest++;
632                         //print(">>" +locBraceNest);
633                         continue; // no more processing..    
634                           
635                         
636                     }
637                     
638                     GLib.error( "dont know how to handle function syntax??\n %s" +
639                                 token.asString());
640                     
641             
642                     
643                     continue;
644                     
645                     
646                     
647                     
648                 } // end checking for TOKfunction
649                     
650                 if (token.data == "{") {
651                     
652                      // foo = { // !var!!!
653                         //$this$=foo|Foo
654                
655                 
656                     if (
657                             (this.ts.lookTok(-1).data == "=") &&
658                             (this.ts.lookTok(-2).isType(TokenType.NAME)) &&
659                             (!this.ts.lookTok(-3).isName(TokenName.VAR))  
660                         ) {
661                             
662                             scopeName = this.ts.lookTok(-2).data;
663                             //print(scopeName);
664                             scopeName = this.fixAlias(aliases, scopeName);
665                             GLib.debug("got %s = {", scopeName);
666                             
667                             //print(this.scopes.length);
668                             var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
669                                                         "$this$=" + scopeName +"|"+scopeName, null
670                                                 ); 
671                             
672                             this.indexedScopes.set(this.ts.cursor, fnScope);
673                             scope = fnScope;
674                             // push the same scope onto the stack..
675                             this.scopesIn(fnScope);
676                             //this.scopesIn(this.scopes[this.scopes.length-1]);
677                             
678                               
679                             locBraceNest++;
680                             //print(">>" +locBraceNest);
681                             continue; // no more processing..   
682                     }
683                     // foo : {
684                     // ?? add |foo| ????
685                       
686                     //print("GOT LBRACE : check for :");
687                     if (
688                             (this.ts.lookTok(-1).data == ":") &&
689                             (this.ts.lookTok(-2).isType(TokenType.NAME)) &&
690                             (!this.ts.lookTok(-3).isName(TokenName.VAR)) 
691                         ) {
692                             
693                             scopeName = this.ts.lookTok(-2).data;
694                             scopeName = this.fixAlias(aliases, scopeName);
695                             var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
696                                                         scopeName, null
697                                                 ); 
698
699                             this.indexedScopes.set(this.ts.cursor, fnScope);
700                             scope = fnScope;
701                             this.scopesIn(fnScope);
702                             
703                             locBraceNest++;
704                             //print(">>" +locBraceNest);
705                             continue; // no more processing..   
706                     }
707                     var fnScope =  new Scope(this.braceNesting, scope, token.id, // was token.n?
708                                                 "", null
709                                 ); 
710
711                     this.indexedScopes.set(this.ts.cursor, fnScope);
712                     scope = fnScope;
713                     this.scopesIn(fnScope);
714                    
715                     locBraceNest++;
716                     //print(">>" +locBraceNest);
717                     continue;
718                     
719                 }
720                 if (token.data == "}") {
721                     
722                      
723                         if (this.currentDoc != null) {
724                             this.addSymbol("", true);
725
726                             //throw "Unconsumed Doc: (TOKrbrace)" + this.currentDoc.toSource();
727                         }
728                         
729                        
730                         locBraceNest--;
731                         
732                             //assert braceNesting >= scope.getBraceNesting();
733                         var closescope = this.scopeOut();
734                         
735                         scope = this.scopes.get(this.scopes.size-1);
736                         
737                         //print("<<:" +  locBraceNest)
738                         //print("<<<<<< " + locBraceNest );
739                         if (locBraceNest < 0) {
740                            // print("POPED OF END OF SCOPE!");
741                             ///this.scopeOut();   
742                             //var ls = this.scopeOut();
743                             //ls.getUsedSymbols();
744                             return;
745                         }
746                         continue;
747                 }
748               
749                 
750             }
751             
752             
753         }
754      
755          
756         void addSymbol(string in_lastIdent, bool appendIt = false, string atype = "OBJECT")
757         {
758             
759             GLib.debug("addSymbol %s", in_lastIdent);
760             var lastIdent = in_lastIdent;
761             if (this.currentDoc.getTag(DocTagTitle.PRIVATE).size > 0) {
762                 
763               
764                 //print(this.currentDoc.toSource());
765                  this.currentDoc = null;
766                 //print("SKIP ADD SYM:  it"s private");
767                 return;
768             }
769             
770             var token = this.ts.lookTok(0);
771           
772           //  print(this.currentDoc.toSource(););
773             if (this.currentDoc.getTag(DocTagTitle.EVENT).size > 0) {
774                 //?? why does it end up in desc - and not name/...
775                 //print(this.currentDoc.getTag("event")[0]);
776                 lastIdent = "*" + this.currentDoc.getTag(DocTagTitle.EVENT).get(0).desc;
777                 //lastIdent = "*" + lastIdent ;
778             }
779             if (lastIdent.length < 1 && this.currentDoc.getTag(DocTagTitle.PROPERTY).size > 0) {
780                 lastIdent = this.currentDoc.getTag(DocTagTitle.PROPERTY).get(0).name;
781                 //lastIdent = "*" + lastIdent ;
782             }
783             
784             var _s = lastIdent;
785             if (!/\./.match(_s)) {
786                     
787                 //print("WALKER ADDsymbol: " + lastIdent);
788                 
789                 string[] s = {};
790                 GLib.debug("Checking Scopes %d", this.scopes.size);
791                 for (var i = 0; i < this.scopes.size;i++) {
792                     GLib.debug("Scope %s", this.scopes.get(i).ident);
793                         var adds = this.scopes.get(i).ident;
794                         
795                     s = s + adds;
796                 }
797                 s += lastIdent;
798                 
799                 GLib.debug("FULLSCOPE: '%s'" , string.joinv("', '", s));
800                 
801                 
802                 s = string.joinv("|", s).split("|");
803                 //print("FULLSCOPE: " + s);
804              //  print("Walker:ADDSymbol: " + s.join("|") );
805                 var _t = "";
806                  _s = "";
807                 
808                 /// fixme - needs
809                 for (var i = 0; i < s.length;i++) {
810                     
811                     if (s[i].length < 1) {
812                         continue;
813                     }
814                     if ((s[i] == "$private$") || (s[i] == "$global$")) {
815                         _s = "";
816                         continue;
817                     }
818                     if (s[i].length > 5 &&  s[i].substring(0,6) == "$this$") {
819                         var ts = s[i].split("=");
820                         _t = ts[1];
821                         _s = ""; // ??? VERY QUESTIONABLE!!!
822                         continue;
823                     }
824                     // when to use $this$ (probabl for events)
825                     _s += _s.length > 0 ? "." : "";
826                     _s += s[i];
827                 }
828                 GLib.debug("FULLSCOPE: _s=%s (append = %s)" , _s, appendIt? "YES": "no");
829                 
830                 /// calc scope!!
831                 //print("ADDING SYMBOL: "+ s.join("|") +"\n"+ _s + "\n" +Script.prettyDump(this.currentDoc.toSource()));
832                 //print("Walker.addsymbol - add : " + _s);
833                 
834                 
835                 if (appendIt && lastIdent.length < 1) {
836                     
837                     // append, and no symbol???
838                     
839                     // see if it"s a @class
840                     if (this.currentDoc.getTag(DocTagTitle.CLASS).size > 0) {
841                         _s = this.currentDoc.getTag(DocTagTitle.CLASS).get(0).desc;
842                         var symbol = new Symbol.new_populate_with_args(_s, new Gee.ArrayList<string>(),
843                                          "CONSTRUCTOR", this.currentDoc);
844                        
845                         DocParser.addSymbol(symbol);
846                         this.symbols[_s] = symbol;
847                         return;
848                     }
849                     
850                    // if (this.currentDoc.getTag("property").length) {
851                      //   print(Script.pretStringtyDump(this.currentDoc.toSource));
852                     //    throw "Add Prop?";
853                     //}
854
855                     _s = /\.prototype.*$/.replace(_s, _s.length,0, "");
856                     
857                     if (!this.symbols.has_key(_s)) {
858                         //print("Symbol:" + _s);
859                         //print(this.currentDoc.src);
860                         
861                         //throw {
862                         //    name: "ArgumentError", 
863                         //    message: "Trying to append symbol "" + _s + "", but no doc available\n" +
864                         //        this.ts.lookTok(0).toString()
865                         //};
866                         this.currentDoc = null;
867                         return;
868                      
869                     }
870                     GLib.debug("add to symbol  _s=%s  " , _s);    
871                     for (var i =0; i < this.currentDoc.tags.size;i++) {
872                         this.symbols.get(_s).addDocTag(this.currentDoc.tags.get(i));
873                     } 
874                     this.currentDoc = null;
875                     return;
876                 }
877             }    
878             //print("Walker.addsymbol - chkdup: " + _s);
879             if (this.symbols.has_key(_s)) {
880                 
881                 if (this.symbols.get(_s).comment.hasTags) {
882                     // then existing comment doesnt has tags 
883                     //throw {
884                     //    name: "ArgumentError", 
885                      //   message:"DUPLICATE Symbol " + _s + "\n" + token.toString()
886                     //};
887                     return;
888                 }
889                 // otherwise existing comment has tags - overwrite..
890                 
891                 
892             }
893             //print("Walker.addsymbol - ATYPE: " + _s);
894
895
896
897             
898             //print("Walker.addsymbol - add : ");
899             var symbol = new Symbol.new_populate_with_args(
900                         _s, new Gee.ArrayList<string>(), atype, this.currentDoc);
901
902             DocParser.addSymbol(symbol);
903             this.symbols[_s] = symbol;
904             
905              this.currentDoc = null;
906             
907         }
908         
909         
910         
911         
912         void scopesIn  (Scope s)
913         {
914             this.scopes.add(s);
915             //print(">>>" + this.ts.context()  + "\n>>>"+this.scopes.length+":" +this.scopeListToStr());
916             
917         }
918         Scope scopeOut()
919         {
920             
921            // print("<<<" + this.ts.context()  + "\n<<<"+this.scopes.length+":" +this.scopeListToStr());
922             return this.scopes.remove_at(this.scopes.size -1 );
923             
924         }
925         
926         string scopeListToStr ()
927         {
928             string[] s = {};
929             for (var i = 0; i < this.scopes.size;i++) {
930                 s +=(this.scopes[i].ident);
931             }
932             return  string.joinv("\n\t",s);
933             
934         }
935         
936     }
937     
938      
939 }