1 //<Script type="text/javascript">
2 XObject = imports.XObject.XObject;
4 Scope = imports.Scope.Scope;
5 DocComment = imports.DocComment.DocComment;
6 Symbol = imports.Symbol.Symbol;
12 * // FIXME - I need this to do next() without doccomments..
15 Walker2 = XObject.define(
20 this.indexedScopes = {};
22 //this.timer = new Date() * 1;
30 timerPrint: function (str) {
31 var ntime = new Date() * 1;
32 var tdif = ntime -this.timer;
35 if (tdif > 100) { //slower ones..
38 print(pref+'['+tdif+']'+str);
43 //this.warnings.push(s);
44 print("WARNING:" + htmlescape(s) + "<BR>");
46 // defaults should not be initialized here =- otherwise they get duped on new, rather than initalized..
51 mode : "", //"BUILDING_SYMBOL_TREE",
53 indexedScopes : false,
55 symbols: false, /// object store of sumbols..
60 buildSymbolTree : function()
65 this.braceNesting = 0;
69 this.globalScope = new Scope(-1, false, -1, '$global$');
70 indexedScopes = { 0 : this.globalScope };
72 this.mode = 'BUILDING_SYMBOL_TREE';
73 this.parseScope(this.globalScope);
81 //print("<B>LOG:</B>" + htmlescape(str) + "<BR/>\n");
85 //print("<B>LOG:</B>" + str + "<BR/>");
92 parseScope : function(scope, ealiases) // parse a token stream..
94 //this.timerPrint("parseScope EnterScope");
97 var fixAlias = function(str, nomore)
99 var ar = str.split('.');
102 //print(str +"?=" +aliases.toSource());
103 if (aliases[m] == undefined) {
106 var ret = aliases[m] + (ar.length? '.' : '' )+ ar.join('.');
107 if (nomore !== true) {
108 ret = fixAlias(ret, true);
118 if (ealiases != undefined) {
120 for(var i in ealiases) {
121 aliases[i] = ealiases[i];
128 //print("STARTING SCOPE WITH: " + ealiases.toSource());
134 var expressionBraceNesting = this.braceNesting;
135 var bracketNesting = 0;
136 var parensNesting = 0;
139 var l1 = '', l2 = '';
143 var locBraceNest = 0;
144 // determines if we are in object literals...
146 var isObjectLitAr = [ false ];
147 //print("SCOPE: ------------------START ----------------");
148 this.scopesIn(scope);
149 var scopeLen = this.scopes.length;
151 if (this.ts.cursor < 1) {
152 // this.ts.cursor--; // hopeflly this kludge will work
156 //print(JSON.stringify(this.ts, null, 4)); Seed.quit();
158 while (null != (token = this.ts.next())) {
159 //print("TOK"+ token.toString());
160 // this.timerPrint("parseScope AFTER lookT: " + token.toString());
162 if (token.is('COMM')) {
165 if (token.name != 'JSDOC') {
166 //print("Walker2 : spce is not JSDOC");
169 if (this.currentDoc) {
170 // add it to the current scope????
172 this.addSymbol('', true);
174 //throw "Unconsumed Doc (TOKwhitespace): " + this.currentDoc.toSource();
178 var newDoc = new DocComment(token.data);
180 // it's a scope changer..
181 if (newDoc.getTag("scope").length) {
182 //print("Walker2 : doctag changes scope");
184 scope.ident = '$private$|' + newDoc.getTag("scope")[0].desc;
188 // it's a scope changer..
189 if (newDoc.getTag("scopeAlias").length) {
190 //print(newDoc.getTag("scopeAlias").toSource());
192 //print("Walker2 : doctag changes scope (alias)");
193 var sal = newDoc.getTag("scopeAlias")[0].desc.split("=");
194 aliases[sal[0]] = sal[1];
200 /// got a doc comment..
201 //token.data might be this.??? (not sure though)
202 //print("Walker2 : setting currentDoc");
203 this.currentDoc = newDoc;
207 // catch the various issues .. - scoe changes or doc actions..
211 // things that stop comments carrying on...??
213 if (this.currentDoc && (
215 token.data == '}')) {
216 this.addSymbol('', true);
217 //throw "Unconsumed Doc ("+ token.toString() +"): " + this.currentDoc.toSource();
221 // the rest are scoping issues...
225 if (token.name == 'VAR' &&
227 this.ts.lookTok(1).type == 'NAME' &&
228 this.ts.lookTok(2).data == '-' &&
229 this.ts.lookTok(3).type == 'NAME' &&
230 this.ts.lookTok(4).data == ';'
234 //print("SET ALIAS:" + this.ts.lookTok(1).data +'=' + this.ts.lookTok(3).data);
236 aliases[this.ts.lookTok(1).data] = this.ts.lookTok(3).data;
243 // extends scoping *** not sure if the can be x = Roo.apply(....)
244 // xxx.extends(a,b, {
245 // $this$=b|b.prototype
250 if (token.type == 'NAME') {
252 //print("TOK(ident)"+ token.toString());
258 if (/\.extend$/.test(token.data) &&
259 this.ts.lookTok(1).data == '(' &&
260 this.ts.lookTok(2).type == 'NAME' &&
261 this.ts.lookTok(3).data == ',' &&
262 this.ts.lookTok(4).type == 'NAME' &&
263 this.ts.lookTok(5).data == ',' &&
264 this.ts.lookTok(6).data == '{'
267 // ignore test for ( a and ,
268 this.ts.nextTok(); /// (
269 token = this.ts.nextTok(); // a
270 scopeName = token.data;
272 if (this.currentDoc) {
273 this.addSymbol(scopeName,false,'OBJECT');
276 this.ts.nextTok(); // ,
277 this.ts.nextTok(); // b
280 this.ts.nextTok(); // ,
281 token = this.ts.nextTok(); // {
283 scopeName = fixAlias(scopeName);
285 var fnScope = new Scope(this.braceNesting, scope, token.n,
286 '$this$=' + scopeName + '|'+scopeName+'.prototype');
287 this.indexedScopes[this.ts.cursor] = fnScope;
289 this.scopesIn(fnScope);
292 //print(">>" +locBraceNest);
293 continue; // no more processing..
297 // a = Roo.extend(parentname, {
299 if (/\.extend$/.test(token.data) &&
300 this.ts.lookTok(-2).type == 'NAME' &&
301 this.ts.lookTok(-1).data == '=' &&
302 this.ts.lookTok(1).data == '(' &&
303 this.ts.lookTok(2).type == 'NAME' &&
304 this.ts.lookTok(3).data == ',' &&
305 this.ts.lookTok(4).data == '{'
307 // ignore test for ( a and ,
308 token = this.ts.lookTok(-2);
309 scopeName = token.data;
310 if (this.currentDoc) {
311 this.addSymbol(scopeName,false,'OBJECT');
314 this.ts.nextTok(); /// (
315 this.ts.nextTok(); // parent
317 this.ts.nextTok(); // ,
318 token = this.ts.nextTok(); // {
321 scopeName = fixAlias(scopeName);
322 var fnScope = new Scope(this.braceNesting, scope, token.n,
323 '$this$=' + scopeName + '|'+scopeName+'.prototype');
324 this.indexedScopes[this.ts.cursor] = fnScope;
326 this.scopesIn(fnScope);
329 //print(">>" +locBraceNest);
330 continue; // no more processing..
337 print(JSON.stringify([
339 this.ts.lookTok(1).data ,
340 this.ts.lookTok(2).type ,
341 this.ts.lookTok(3).data ,
342 this.ts.lookTok(4).data
346 if (/\.(applyIf|apply)$/.test(token.data) &&
347 this.ts.lookTok(1).data == '(' &&
348 this.ts.lookTok(2).type == 'NAME' &&
349 this.ts.lookTok(3).data == ',' &&
350 this.ts.lookTok(4).data == '{'
353 this.ts.nextTok(); /// (
355 //print("GOT : applyIF!");
357 token = this.ts.nextTok(); // b
358 scopeName = token.data;
361 if (this.currentDoc) {
362 this.addSymbol(scopeName,false,'OBJECT');
367 this.ts.nextTok(); /// ,
368 this.ts.nextTok(); // {
369 scopeName = fixAlias(scopeName);
370 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
371 this.indexedScopes[this.ts.cursor] = fnScope;
373 this.scopesIn(fnScope);
376 //print(">>" +locBraceNest);
377 continue; // no more processing..
383 // change scope to xxxx
385 print(JSON.stringify([
386 this.ts.lookTok(1).data ,
387 this.ts.lookTok(2).name ,
388 this.ts.lookTok(3).type ,
389 this.ts.lookTok(4).data ,
390 this.ts.lookTok(5).data
393 if ( this.ts.lookTok(1).data == '=' &&
394 this.ts.lookTok(2).name == 'NEW' &&
395 this.ts.lookTok(3).type == 'NAME' &&
396 this.ts.lookTok(4).data == '(' &&
397 this.ts.lookTok(5).data == '{'
399 scopeName = token.data;
400 if (this.currentDoc) {
401 this.addSymbol(scopeName,false,'OBJECT');
405 this.ts.nextTok(); /// =
406 this.ts.nextTok(); /// new
407 this.ts.nextTok(); /// yyy
408 this.ts.nextTok(); /// (
409 this.ts.nextTok(); /// {
411 scopeName = fixAlias(scopeName);
412 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
413 this.indexedScopes[this.ts.cursor] = fnScope;
415 this.scopesIn(fnScope);
418 //print(">>" +locBraceNest);
420 continue; // no more processing..
441 // eval can be prefixed with a hint hider for the compresser..
442 if ((token.data == 'eval') || /\.eval$/.test(token.data)) {
443 this.currentDoc = false;
447 if (this.currentDoc) {
448 //print(token.toString());
450 // ident : function ()
451 // ident = function ()
452 var atype = 'OBJECT';
454 if (((this.ts.lookTok(1).data == ':' )|| (this.ts.lookTok(1).data == '=')) &&
455 (this.ts.lookTok(2).name == "FUNCTION")
460 //print("ADD SYM:" + atype + ":" + token.toString() + this.ts.lookTok(1).toString() + this.ts.lookTok(2).toString());
463 this.ts.lookTok(-1).data == '.' ? token.data : fixAlias(token.data),
470 continue; // dont care about other idents..
474 //print ("NOT NAME");
477 if (token.type == "STRN") {
478 if (this.currentDoc) {
479 this.addSymbol(token.data.substring(1,token.data.length-1),false,'OBJECT');
484 // really we only have to deal with object constructs and function calls that change the scope...
487 if (token.name == 'FUNCTION') {
488 //print("GOT FUNCTION");
489 // see if we have an unconsumed doc...
491 if (this.currentDoc) {
492 print(this.ts.dump(this.ts.cursor-20, this.ts.cursor+20));
493 throw "Unhandled doc (TOKfunction)" + token.toString();
494 //this.addSymbol(this.currentDoc.getTag('class')[0].name, true);
496 //throw "Unconsumed Doc: (TOKrbrace)" + this.currentDoc.toSource();
503 /// foo = function() {} << really it set's the 'this' scope to foo.prototype
504 //$this$=foo.prototype|$private$|foo.prototype
507 (this.ts.lookTok(-1).data == '=') &&
508 (this.ts.lookTok(-2).type == 'NAME')
510 scopeName = this.ts.lookTok(-2).data;
511 this.ts.balance('(');
512 token = this.ts.nextTok(); // should be {
513 //print("FOO=FUNCITON() {}" + this.ts.context() + "\n" + token.toString());
516 scopeName = fixAlias(scopeName);
517 var fnScope = new Scope(this.braceNesting, scope, token.n,
518 '$this$='+scopeName+'.prototype|$private$|'+scopeName+'.prototype');
520 this.indexedScopes[this.ts.cursor] = fnScope;
522 //this.scopesIn(fnScope);
523 this.parseScope(fnScope, aliases);
528 //print(">>" +locBraceNest);
529 continue; // no more processing..
535 // foo = new function() {}
536 // is this actually used much!?!?!
540 (this.ts.lookTok(-1).name == 'NEW') &&
541 (this.ts.lookTok(-2).data == '=') &&
542 (this.ts.lookTok(-3).type = 'FUNCTION')
544 //scopeName = this.ts.look(-3).data;
545 this.ts.balanceN(Script.TOKlparen);
546 token = this.ts.nextTok(); // should be {
547 scopeName = fixAlias(scopeName);
548 var fnScope = new Scope(this.braceNesting, scope, token.n, '$private$');
549 this.indexedScopes[this.ts.cursor] = fnScope;
551 //this.scopesIn(fnScope);
552 this.parseScope(fnScope, aliases);
555 //print(">>" +locBraceNest);
556 continue; // no more processing..
562 ///==== check/set isObjectLitAr ??
565 // foo: function() {}
566 // no change to scoping..
568 //print("checking for : function() {");
569 //print( [this.ts.lookTok(-3).type , this.ts.lookTok(-2).type , this.ts.lookTok(-1).type ].join(":"));
571 (this.ts.lookTok(-1).data == ':') &&
572 (this.ts.lookTok(-2).type == 'NAME') &&
573 (this.ts.lookTok(-3).data == '(' || this.ts.lookTok(-3).data== ',')
575 //print("got for : function() {");
577 //scopeName = this.ts.look(-3).data;
578 this.ts.balance('(');
579 //print(token.toString())
580 token = this.ts.nextTok(); // should be {
581 //print(token.toString())
582 scopeName = fixAlias(scopeName);
583 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
584 this.indexedScopes[this.ts.cursor] = fnScope;
586 //this.scopesIn(fnScope);
587 this.parseScope(fnScope, aliases);
589 //print(">>" +locBraceNest);
590 continue; // no more processing..
593 /// function foo() {} << really it set's the 'this' scope to foo.prototype
594 //$this$=foo|$private$
598 (this.ts.lookTok(1).type == 'NAME')
600 //scopeName = this.ts.look(-3).data;
601 this.ts.balance('(');
602 token = this.ts.nextTok(); // should be {
604 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
605 this.indexedScopes[this.ts.cursor] = fnScope;
607 //this.scopesIn(fnScope);
608 this.parseScope(fnScope, aliases);
610 //print(">>" +locBraceNest);
611 continue; // no more processing..
616 // foo = new (function() { }
618 // RETURN function(...) {
621 // (this.ts.lookTok(-1).tokN == Script.TOKlparen) &&
622 (this.ts.lookTok(1).name != 'NAME')
624 // (this.ts.lookTok(-2).tokN == Script.TOKnew) &&
625 // (this.ts.lookTok(-3).tokN == Script.TOKassign) &&
626 // (this.ts.lookTok(-4).tokN == Script.TOKidentifier)
628 //scopeName = this.ts.look(-3).data;
629 this.ts.balance('(');
630 token = this.ts.nextTok(); // should be {
631 var fnScope = new Scope(this.braceNesting, scope, token.n, '$private$');
632 this.indexedScopes[this.ts.cursor] = fnScope;
634 //this.scopesIn(fnScope);
635 this.parseScope(fnScope, aliases);
637 //print(">>" +locBraceNest);
638 continue; // no more processing..
644 print(this.ts.dump(this.ts.cursor-20, this.ts.cursor+20));
645 throw "dont know how to handle function syntax??";
652 } // end checking for TOKfunction
654 if (token.data == '{') {
656 // foo = { // !var!!!
661 (this.ts.lookTok(-1).data == '=') &&
662 (this.ts.lookTok(-2).type == 'NAME') &&
663 (this.ts.lookTok(-3).nane != 'VAR')
666 scopeName = this.ts.look(-2).data;
667 scopeName = fixAlias(scopeName);
668 var fnScope = new Scope(this.braceNesting, scope, token.n,
669 '$this$='+scopeName + '|'+scopeName
671 this.indexedScopes[this.ts.cursor] = fnScope;
673 this.scopesIn(fnScope);
677 //print(">>" +locBraceNest);
678 continue; // no more processing..
683 //print("GOT LBRACE : check for :");
685 (this.ts.lookTok(-1).data == ':') &&
686 (this.ts.lookTok(-2).type == 'NAME') &&
687 (this.ts.lookTok(-3).name != 'VAR')
690 scopeName = this.ts.lookTok(-2).data;
691 scopeName = fixAlias(scopeName);
692 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
693 this.indexedScopes[this.ts.cursor] = fnScope;
695 this.scopesIn(fnScope);
698 //print(">>" +locBraceNest);
699 continue; // no more processing..
701 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
702 this.indexedScopes[this.ts.cursor] = fnScope;
704 this.scopesIn(fnScope);
707 //print(">>" +locBraceNest);
711 if (token.data == '{') {
714 if (this.currentDoc) {
715 this.addSymbol('', true);
717 //throw "Unconsumed Doc: (TOKrbrace)" + this.currentDoc.toSource();
723 //assert braceNesting >= scope.getBraceNesting();
724 var closescope = this.scopeOut();
725 scope = this.scopes[this.scopes.length-1];
726 //print("<<:" + locBraceNest)
727 //print("<<<<<< " + locBraceNest );
728 if (locBraceNest < 0) {
729 // print("POPED OF END OF SCOPE!");
731 //var ls = this.scopeOut();
732 //ls.getUsedSymbols();
745 addSymbol: function(lastIdent, appendIt, atype )
747 //print("Walker.addSymbol : " + lastIdent);
749 /*if (!this.currentDoc.tags.length) {
752 //print(this.currentDoc.toSource());
753 // this.currentDoc = false;
755 print("SKIP ADD SYM: no tags");
756 print(this.currentDoc.src);
760 if (this.currentDoc.getTag('private').length) {
763 //print(this.currentDoc.toSource());
764 this.currentDoc = false;
765 //print("SKIP ADD SYM: it's private");
769 var token = this.ts.lookTok(0);
770 if (typeof(appendIt) == 'undefined') {
773 // print(this.currentDoc.toSource(););
774 if (this.currentDoc.getTag('event').length) {
775 //?? why does it end up in desc - and not name/...
776 //print(this.currentDoc.getTag('event')[0]);
777 lastIdent = '*' + this.currentDoc.getTag('event')[0].desc;
778 //lastIdent = '*' + lastIdent ;
780 if (!lastIdent.length && this.currentDoc.getTag('property').length) {
781 lastIdent = this.currentDoc.getTag('property')[0].name;
782 //lastIdent = '*' + lastIdent ;
786 if (!/\./.test(_s)) {
788 //print("WALKER ADDsymbol: " + lastIdent);
791 for (var i = 0; i < this.scopes.length;i++) {
792 s.push(this.scopes[i].ident);
796 var s = s.join('|').split('|');
797 //print("Walker:ADDSymbol: " + s.join('|') );
802 for (var i = 0; i < s.length;i++) {
807 if ((s[i] == '$private$') || (s[i] == '$global$')) {
811 if (s[i].substring(0,6) == '$this$') {
812 var ts = s[i].split('=');
816 // when to use $this$ (probabl for events)
817 _s += _s.length ? '.' : '';
823 //print("ADDING SYMBOL: "+ s.join('|') +"\n"+ _s + "\n" +Script.prettyDump(this.currentDoc.toSource()));
824 //print("Walker.addsymbol - add : " + _s);
825 if (appendIt && !lastIdent.length) {
827 // append, and no symbol???
829 // see if it's a @class
830 if (this.currentDoc.getTag('class').length) {
831 _s = this.currentDoc.getTag('class')[0].desc;
832 var symbol = new Symbol(_s, [], "CONSTRUCTOR", this.currentDoc);
833 Parser = imports.Parser.Parser;
834 Parser.addSymbol(symbol);
835 this.symbols[_s] = symbol;
839 // if (this.currentDoc.getTag('property').length) {
840 // print(Script.pretStringtyDump(this.currentDoc.toSource));
841 // throw "Add Prop?";
844 _s = _s.replace(/\.prototype.*$/, '');
845 if (typeof(this.symbols[_s]) == 'undefined') {
846 //print("Symbol:" + _s);
847 //print(this.currentDoc.src);
849 throw "Trying to append symbol, but no doc available";
852 for (var i =0; i < this.currentDoc.tags.length;i++) {
853 this.symbols[_s].addDocTag(this.currentDoc.tags[i]);
855 this.currentDoc = false;
859 //print("Walker.addsymbol - chkdup: " + _s);
860 if (typeof(this.symbols[_s]) != 'undefined') {
862 if (this.symbols[_s].comment.hasTags) {
863 // then existing comment doesnt has tags
865 name: "ArgumentError",
866 message:"DUPLICATE Symbol " + _s
870 // otherwise existing comment has tags - overwrite..
874 //print("Walker.addsymbol - ATYPE: " + _s);
876 if (typeof(atype) == "undefined") {
877 atype = 'OBJECT'; //this.currentDoc.getTag('class').length ? 'OBJECT' : 'FUNCTION';;
880 //print("Walker.addsymbol - add : ");
881 var symbol = new Symbol(_s, [], atype, this.currentDoc);
882 Parser = imports.Parser.Parser;
883 Parser.addSymbol(symbol);
884 this.symbols[_s] = symbol;
886 this.currentDoc = false;
893 scopesIn : function(s)
896 //print(">>>" + this.ts.context() + "\n>>>"+this.scopes.length+":" +this.scopeListToStr());
899 scopeOut : function()
902 // print("<<<" + this.ts.context() + "\n<<<"+this.scopes.length+":" +this.scopeListToStr());
903 return this.scopes.pop();
907 scopeListToStr : function()
910 for (var i = 0; i < this.scopes.length;i++) {
911 s.push(this.scopes[i].ident);
913 return s.join('\n\t');