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(
17 XObject.extend(this,opts);
21 this.indexedScopes = {};
23 //this.timer = new Date() * 1;
31 timerPrint: function (str) {
32 var ntime = new Date() * 1;
33 var tdif = ntime -this.timer;
36 if (tdif > 100) { //slower ones..
39 print(pref+'['+tdif+']'+str);
44 * @cfg parser {Parser} instance of parser
49 //this.warnings.push(s);
50 print("WARNING:" + htmlescape(s) + "<BR>");
52 // defaults should not be initialized here =- otherwise they get duped on new, rather than initalized..
57 mode : "", //"BUILDING_SYMBOL_TREE",
59 indexedScopes : false,
64 * @param {Object} symbols object store of sumbols..
69 buildSymbolTree : function()
74 this.braceNesting = 0;
78 this.globalScope = new Scope(-1, false, -1, '$global$');
79 indexedScopes = { 0 : this.globalScope };
81 this.mode = 'BUILDING_SYMBOL_TREE';
82 this.parseScope(this.globalScope);
90 //print("<B>LOG:</B>" + htmlescape(str) + "<BR/>\n");
94 //print("<B>LOG:</B>" + str + "<BR/>");
101 parseScope : function(scope, ealiases) // parse a token stream..
103 //this.timerPrint("parseScope EnterScope");
106 var fixAlias = function(str, nomore)
108 var ar = str.split('.');
111 //print(str +"?=" +aliases.toSource());
112 if (aliases[m] == undefined) {
115 var ret = aliases[m] + (ar.length? '.' : '' )+ ar.join('.');
116 if (nomore !== true) {
117 ret = fixAlias(ret, true);
127 if (ealiases != undefined) {
129 for(var i in ealiases) {
130 aliases[i] = ealiases[i];
137 //print("STARTING SCOPE WITH: " + ealiases.toSource());
143 var expressionBraceNesting = this.braceNesting;
144 var bracketNesting = 0;
145 var parensNesting = 0;
148 var l1 = '', l2 = '';
152 var locBraceNest = 0;
153 // determines if we are in object literals...
155 var isObjectLitAr = [ false ];
156 //print("SCOPE: ------------------START ----------------");
157 this.scopesIn(scope);
158 var scopeLen = this.scopes.length;
160 if (this.ts.cursor < 1) {
161 // this.ts.cursor--; // hopeflly this kludge will work
165 //print(JSON.stringify(this.ts, null, 4)); Seed.quit();
167 while (null != (token = this.ts.next())) {
168 //print("TOK"+ token.toString());
169 // this.timerPrint("parseScope AFTER lookT: " + token.toString());
171 if (token.is('COMM')) {
174 if (token.name != 'JSDOC') {
175 //print("Walker2 : spce is not JSDOC");
178 if (this.currentDoc) {
179 // add it to the current scope????
181 this.addSymbol('', true);
182 //print ( "Unconsumed Doc: " + token.toString())
183 //throw "Unconsumed Doc (TOKwhitespace): " + this.currentDoc.toSource();
186 // print ( "NEW COMMENT: " + token.toString())
187 var newDoc = new DocComment(token.data);
189 // it's a scope changer..
190 if (newDoc.getTag("scope").length) {
191 //print("Walker2 : doctag changes scope");
193 scope.ident = '$private$|' + newDoc.getTag("scope")[0].desc;
197 // it's a scope changer..
198 if (newDoc.getTag("scopeAlias").length) {
199 //print(newDoc.getTag("scopeAlias").toSource());
201 //print("Walker2 : doctag changes scope (alias)");
202 var sal = newDoc.getTag("scopeAlias")[0].desc.split("=");
203 aliases[sal[0]] = sal[1];
209 if (newDoc.getTag("namespace").length) {
210 //print("Walker2 : doctag changes scope");
212 this.namespace = newDoc.getTag("namespace")[0].desc +'.';
216 /// got a doc comment..
217 //token.data might be this.??? (not sure though)
218 //print("Walker2 : setting currentDoc");
219 this.currentDoc = newDoc;
223 // catch the various issues .. - scoe changes or doc actions..
227 // things that stop comments carrying on...??
229 if (this.currentDoc && (
231 token.data == '}')) {
232 this.addSymbol('', true);
233 //throw "Unconsumed Doc ("+ token.toString() +"): " + this.currentDoc.toSource();
237 // the rest are scoping issues...
241 if (token.name == 'VAR' &&
243 this.ts.lookTok(1).type == 'NAME' &&
244 this.ts.lookTok(2).data == '=' &&
245 this.ts.lookTok(3).type == 'NAME' &&
246 this.ts.lookTok(4).data == ';'
250 //print("SET ALIAS:" + this.ts.lookTok(1).data +'=' + this.ts.lookTok(3).data);
252 aliases[this.ts.lookTok(1).data] = this.ts.lookTok(3).data;
257 if ((token.data == 'eval') || /\.eval$/.test(token.data)) {
258 this.currentDoc = false;
262 // extends scoping *** not sure if the can be x = Roo.apply(....)
263 // xxx.extends(a,b, {
264 // $this$=b|b.prototype
269 if (token.type == 'NAME') {
271 //print("TOK(ident)"+ token.toString());
273 if (/\.extend$/.test(token.data) &&
274 this.ts.lookTok(1).data == '(' &&
275 this.ts.lookTok(2).type == 'NAME' &&
276 this.ts.lookTok(3).data == ',' &&
277 this.ts.lookTok(4).type == 'NAME' &&
278 this.ts.lookTok(5).data == ',' &&
279 this.ts.lookTok(6).data == '{'
282 // ignore test for ( a and ,
283 this.ts.nextTok(); /// (
284 token = this.ts.nextTok(); // a
285 scopeName = token.data;
287 if (this.currentDoc) {
288 this.addSymbol(scopeName,false,'OBJECT');
291 this.ts.nextTok(); // ,
292 this.ts.nextTok(); // b
295 this.ts.nextTok(); // ,
296 token = this.ts.nextTok(); // {
298 scopeName = fixAlias(scopeName);
300 var fnScope = new Scope(this.braceNesting, scope, token.n,
301 '$this$=' + scopeName + '|'+scopeName+'.prototype');
302 this.indexedScopes[this.ts.cursor] = fnScope;
304 this.scopesIn(fnScope);
307 //print(">>" +locBraceNest);
308 continue; // no more processing..
312 // a = Roo.extend(parentname, {
314 if (/\.extend$/.test(token.data) &&
315 this.ts.lookTok(-2).type == 'NAME' &&
316 this.ts.lookTok(-1).data == '=' &&
317 this.ts.lookTok(1).data == '(' &&
318 this.ts.lookTok(2).type == 'NAME' &&
319 this.ts.lookTok(3).data == ',' &&
320 this.ts.lookTok(4).data == '{'
322 // ignore test for ( a and ,
323 token = this.ts.lookTok(-2);
324 scopeName = token.data;
325 if (this.currentDoc) {
326 this.addSymbol(scopeName,false,'OBJECT');
329 this.ts.nextTok(); /// (
330 this.ts.nextTok(); // parent
332 this.ts.nextTok(); // ,
333 token = this.ts.nextTok(); // {
336 scopeName = fixAlias(scopeName);
337 var fnScope = new Scope(this.braceNesting, scope, token.n,
338 '$this$=' + scopeName + '|'+scopeName+'.prototype');
339 this.indexedScopes[this.ts.cursor] = fnScope;
341 this.scopesIn(fnScope);
344 //print(">>" +locBraceNest);
345 continue; // no more processing..
352 print(JSON.stringify([
354 this.ts.lookTok(1).data ,
355 this.ts.lookTok(2).type ,
356 this.ts.lookTok(3).data ,
357 this.ts.lookTok(4).data
361 if (/\.(applyIf|apply)$/.test(token.data) &&
362 this.ts.lookTok(1).data == '(' &&
363 this.ts.lookTok(2).type == 'NAME' &&
364 this.ts.lookTok(3).data == ',' &&
365 this.ts.lookTok(4).data == '{'
368 this.ts.nextTok(); /// (
370 //print("GOT : applyIF!");
372 token = this.ts.nextTok(); // b
373 scopeName = token.data;
376 if (this.currentDoc) {
377 this.addSymbol(scopeName,false,'OBJECT');
382 this.ts.nextTok(); /// ,
383 this.ts.nextTok(); // {
384 scopeName = fixAlias(scopeName);
385 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
386 this.indexedScopes[this.ts.cursor] = fnScope;
388 this.scopesIn(fnScope);
391 //print(">>" +locBraceNest);
392 continue; // no more processing..
398 // change scope to xxxx
400 print(JSON.stringify([
401 this.ts.lookTok(1).data ,
402 this.ts.lookTok(2).name ,
403 this.ts.lookTok(3).type ,
404 this.ts.lookTok(4).data ,
405 this.ts.lookTok(5).data
408 if ( this.ts.lookTok(1).data == '=' &&
409 this.ts.lookTok(2).name == 'NEW' &&
410 this.ts.lookTok(3).type == 'NAME' &&
411 this.ts.lookTok(4).data == '(' &&
412 this.ts.lookTok(5).data == '{'
414 scopeName = token.data;
415 if (this.currentDoc) {
416 this.addSymbol(scopeName,false,'OBJECT');
420 this.ts.nextTok(); /// =
421 this.ts.nextTok(); /// new
422 this.ts.nextTok(); /// yyy
423 this.ts.nextTok(); /// (
424 this.ts.nextTok(); /// {
426 scopeName = fixAlias(scopeName);
427 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
428 this.indexedScopes[this.ts.cursor] = fnScope;
430 this.scopesIn(fnScope);
433 //print(">>" +locBraceNest);
435 continue; // no more processing..
438 // AAA = XObject.define( ctr, extends, methods)
440 //print(this.ts.lookTok(2).data);
441 /*print(JSON.stringify([
442 'line:' + token.line,
443 this.ts.lookTok(1).data ,
444 this.ts.lookTok(2).data ,
445 this.ts.lookTok(3).data ,
446 this.ts.lookTok(4).name
450 this.ts.lookTok(1).data == '=' &&
451 this.ts.lookTok(2).data.match(/\.define$/) &&
452 this.ts.lookTok(3).data == '(' &&
453 this.ts.lookTok(4).name == 'FUNCTION'
457 scopeName = this.namespace + token.data;
458 print("GOT NEW SCOPE: " + scopeName);
460 if (this.currentDoc) {
461 this.addSymbol(scopeName,false,'OBJECT');
465 this.ts.nextTok(); /// =
466 this.ts.nextTok(); /// XOBJECT.extend?
467 this.ts.nextTok(); /// (
470 scopeName = fixAlias(scopeName);
471 var fnScope = new Scope(this.braceNesting, scope, token.n,
472 '$this$=' + scopeName + '|'+scopeName+'.prototype');
474 print(fnScope.ident);
475 this.indexedScopes[this.ts.cursor] = fnScope;
477 this.scopesIn(fnScope);
480 //print(">>" +locBraceNest);
482 continue; // no more processing..
489 // eval can be prefixed with a hint hider for the compresser..
492 if (this.currentDoc) {
493 //print(token.toString());
495 // ident : function ()
496 // ident = function ()
497 var atype = 'OBJECT';
499 if (((this.ts.lookTok(1).data == ':' )|| (this.ts.lookTok(1).data == '=')) &&
500 (this.ts.lookTok(2).name == "FUNCTION")
502 // this.ts.nextTok();
503 // this.ts.nextTok();
507 //print("ADD SYM:" + atype + ":" + token.toString() + this.ts.lookTok(1).toString() + this.ts.lookTok(2).toString());
510 this.ts.lookTok(-1).data == '.' ? token.data : fixAlias(token.data),
514 this.currentDoc = false;
520 continue; // dont care about other idents..
524 //print ("NOT NAME");
527 if (token.type == "STRN") { // THIS WILL NOT HAPPEN HERE?!!?
528 if (this.currentDoc) {
529 this.addSymbol(token.data.substring(1,token.data.length-1),false,'OBJECT');
534 // really we only have to deal with object constructs and function calls that change the scope...
537 if (token.name == 'FUNCTION') {
538 //print("GOT FUNCTION");
539 // see if we have an unconsumed doc...
543 /** -- removed as it's killing Xobject parsing...
544 if (this.currentDoc) {
546 name: "ArgumentError",
547 message: this.ts.filename + ": Unhandled doc (TOKfunction)" + token.toString()
550 //this.addSymbol(this.currentDoc.getTag('class')[0].name, true);
552 //throw "Unconsumed Doc: (TOKrbrace)" + this.currentDoc.toSource();
559 /// foo = function() {} << really it set's the 'this' scope to foo.prototype
560 //$this$=foo.prototype|$private$|foo.prototype
563 (this.ts.lookTok(-1).data == '=') &&
564 (this.ts.lookTok(-2).type == 'NAME')
566 scopeName = this.ts.lookTok(-2).data;
567 this.ts.balance('(');
568 token = this.ts.nextTok(); // should be {
569 //print("FOO=FUNCITON() {}" + this.ts.context() + "\n" + token.toString());
572 scopeName = fixAlias(scopeName);
573 var fnScope = new Scope(this.braceNesting, scope, token.n,
574 '$this$='+scopeName+'.prototype|$private$|'+scopeName+'.prototype');
576 this.indexedScopes[this.ts.cursor] = fnScope;
578 //this.scopesIn(fnScope);
579 this.parseScope(fnScope, aliases);
584 //print(">>" +locBraceNest);
585 continue; // no more processing..
591 // foo = new function() {}
592 // is this actually used much!?!?!
596 (this.ts.lookTok(-1).name == 'NEW') &&
597 (this.ts.lookTok(-2).data == '=') &&
598 (this.ts.lookTok(-3).type = 'FUNCTION')
600 //scopeName = this.ts.look(-3).data;
601 this.ts.balance("(");
602 token = this.ts.nextTok(); // should be {
603 scopeName = fixAlias(scopeName);
604 var fnScope = new Scope(this.braceNesting, scope, token.n, '$private$');
605 this.indexedScopes[this.ts.cursor] = fnScope;
607 //this.scopesIn(fnScope);
608 this.parseScope(fnScope, aliases);
611 //print(">>" +locBraceNest);
612 continue; // no more processing..
618 ///==== check/set isObjectLitAr ??
621 // foo: function() {}
622 // no change to scoping..
624 //print("checking for : function() {");
625 //print( [this.ts.lookTok(-3).type , this.ts.lookTok(-2).type , this.ts.lookTok(-1).type ].join(":"));
627 (this.ts.lookTok(-1).data == ':') &&
628 (this.ts.lookTok(-2).type == 'NAME') &&
629 (this.ts.lookTok(-3).data == '(' || this.ts.lookTok(-3).data== ',')
631 //print("got for : function() {");
633 //scopeName = this.ts.look(-3).data;
634 this.ts.balance('(');
635 //print(token.toString())
636 token = this.ts.nextTok(); // should be {
637 //print(token.toString())
638 scopeName = fixAlias(scopeName);
639 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
640 this.indexedScopes[this.ts.cursor] = fnScope;
642 //this.scopesIn(fnScope);
643 this.parseScope(fnScope, aliases);
645 //print(">>" +locBraceNest);
646 continue; // no more processing..
649 /// function foo() {} << really it set's the 'this' scope to foo.prototype
650 //$this$=foo|$private$
654 (this.ts.lookTok(1).type == 'NAME')
656 //scopeName = this.ts.look(-3).data;
657 this.ts.balance('(');
658 token = this.ts.nextTok(); // should be {
660 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
661 this.indexedScopes[this.ts.cursor] = fnScope;
663 //this.scopesIn(fnScope);
664 this.parseScope(fnScope, aliases);
666 //print(">>" +locBraceNest);
667 continue; // no more processing..
672 // foo = new (function() { }
674 // RETURN function(...) {
677 // (this.ts.lookTok(-1).tokN == Script.TOKlparen) &&
678 (this.ts.lookTok(1).name != 'NAME')
680 // (this.ts.lookTok(-2).tokN == Script.TOKnew) &&
681 // (this.ts.lookTok(-3).tokN == Script.TOKassign) &&
682 // (this.ts.lookTok(-4).tokN == Script.TOKidentifier)
684 //scopeName = this.ts.look(-3).data;
685 this.ts.balance('(');
686 token = this.ts.nextTok(); // should be {
687 var fnScope = new Scope(this.braceNesting, scope, token.n, '$private$');
688 this.indexedScopes[this.ts.cursor] = fnScope;
690 //this.scopesIn(fnScope);
691 this.parseScope(fnScope, aliases);
693 //print(">>" +locBraceNest);
694 continue; // no more processing..
701 name: "ArgumentError",
702 message: "dont know how to handle function syntax??\n" +
712 } // end checking for TOKfunction
714 if (token.data == '{') {
716 // foo = { // !var!!!
721 (this.ts.lookTok(-1).data == '=') &&
722 (this.ts.lookTok(-2).type == 'NAME') &&
723 (this.ts.lookTok(-3).name != 'VAR')
726 scopeName = this.ts.look(-2).data;
728 scopeName = fixAlias(scopeName);
730 //print(this.scopes.length);
731 var fnScope = new Scope(this.braceNesting, scope, token.n,
732 '$this$='+scopeName + '|'+scopeName
735 this.indexedScopes[this.ts.cursor] = fnScope;
737 // push the same scope onto the stack..
738 this.scopesIn(fnScope);
739 //this.scopesIn(this.scopes[this.scopes.length-1]);
743 //print(">>" +locBraceNest);
744 continue; // no more processing..
749 //print("GOT LBRACE : check for :");
751 (this.ts.lookTok(-1).data == ':') &&
752 (this.ts.lookTok(-2).type == 'NAME') &&
753 (this.ts.lookTok(-3).name != 'VAR')
756 scopeName = this.ts.lookTok(-2).data;
757 scopeName = fixAlias(scopeName);
758 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
759 this.indexedScopes[this.ts.cursor] = fnScope;
761 this.scopesIn(fnScope);
764 //print(">>" +locBraceNest);
765 continue; // no more processing..
767 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
768 this.indexedScopes[this.ts.cursor] = fnScope;
770 this.scopesIn(fnScope);
773 //print(">>" +locBraceNest);
777 if (token.data == '}') {
780 if (this.currentDoc) {
781 this.addSymbol('', true);
783 //throw "Unconsumed Doc: (TOKrbrace)" + this.currentDoc.toSource();
789 //assert braceNesting >= scope.getBraceNesting();
790 var closescope = this.scopeOut();
791 scope = this.scopes[this.scopes.length-1];
792 //print("<<:" + locBraceNest)
793 //print("<<<<<< " + locBraceNest );
794 if (locBraceNest < 0) {
795 // print("POPED OF END OF SCOPE!");
797 //var ls = this.scopeOut();
798 //ls.getUsedSymbols();
811 addSymbol: function(lastIdent, appendIt, atype )
813 //print("Walker.addSymbol : " + lastIdent);
814 // print("Walker.curdoc: " + JSON.stringify(this.currentDoc, null,4));
816 /*if (!this.currentDoc.tags.length) {
819 //print(this.currentDoc.toSource());
820 // this.currentDoc = false;
822 print("SKIP ADD SYM: no tags");
823 print(this.currentDoc.src);
827 if (this.currentDoc.getTag('private').length) {
830 //print(this.currentDoc.toSource());
831 this.currentDoc = false;
832 //print("SKIP ADD SYM: it's private");
836 var token = this.ts.lookTok(0);
837 if (typeof(appendIt) == 'undefined') {
840 // print(this.currentDoc.toSource(););
841 if (this.currentDoc.getTag('event').length) {
842 //?? why does it end up in desc - and not name/...
843 //print(this.currentDoc.getTag('event')[0]);
844 lastIdent = '*' + this.currentDoc.getTag('event')[0].desc;
845 //lastIdent = '*' + lastIdent ;
847 if (!lastIdent.length && this.currentDoc.getTag('property').length) {
848 lastIdent = this.currentDoc.getTag('property')[0].name;
849 //lastIdent = '*' + lastIdent ;
853 if (!/\./.test(_s)) {
855 //print("WALKER ADDsymbol: " + lastIdent);
858 for (var i = 0; i < this.scopes.length;i++) {
859 s.push(this.scopes[i].ident);
863 //print("FULLSCOPE: " + JSON.stringify(s));
866 var s = s.join('|').split('|');
867 //print("FULLSCOPE: " + s);
868 // print("Walker:ADDSymbol: " + s.join('|') );
873 for (var i = 0; i < s.length;i++) {
878 if ((s[i] == '$private$') || (s[i] == '$global$')) {
882 if (s[i].substring(0,6) == '$this$') {
883 var ts = s[i].split('=');
885 _s = ''; // ??? VERY QUESTIONABLE!!!
888 // when to use $this$ (probabl for events)
889 _s += _s.length ? '.' : '';
892 //print("FULLSCOPE: s , t : " + _s +', ' + _t);
895 //print("ADDING SYMBOL: "+ s.join('|') +"\n"+ _s + "\n" +Script.prettyDump(this.currentDoc.toSource()));
896 //print("Walker.addsymbol - add : " + _s);
897 if (appendIt && !lastIdent.length) {
899 // append, and no symbol???
901 // see if it's a @class
902 if (this.currentDoc.getTag('class').length) {
903 _s = this.currentDoc.getTag('class')[0].desc;
904 var symbol = new Symbol(_s, [], "CONSTRUCTOR", this.currentDoc);
906 this.parser.addSymbol(symbol);
907 this.symbols[_s] = symbol;
911 // if (this.currentDoc.getTag('property').length) {
912 // print(Script.pretStringtyDump(this.currentDoc.toSource));
913 // throw "Add Prop?";
916 _s = _s.replace(/\.prototype.*$/, '');
917 if (typeof(this.symbols[_s]) == 'undefined') {
918 //print("Symbol:" + _s);
919 //print(this.currentDoc.src);
922 // name: "ArgumentError",
923 // message: "Trying to append symbol '" + _s + "', but no doc available\n" +
924 // this.ts.lookTok(0).toString()
926 this.currentDoc = false;
931 for (var i =0; i < this.currentDoc.tags.length;i++) {
932 this.symbols[_s].addDocTag(this.currentDoc.tags[i]);
934 this.currentDoc = false;
938 //print("Walker.addsymbol - chkdup: " + _s);
939 if (typeof(this.symbols[_s]) != 'undefined') {
941 if (this.symbols[_s].comment.hasTags) {
942 // then existing comment doesnt has tags
944 // name: "ArgumentError",
945 // message:"DUPLICATE Symbol " + _s + "\n" + token.toString()
949 // otherwise existing comment has tags - overwrite..
953 //print("Walker.addsymbol - ATYPE: " + _s);
955 if (typeof(atype) == "undefined") {
956 atype = 'OBJECT'; //this.currentDoc.getTag('class').length ? 'OBJECT' : 'FUNCTION';;
959 //print("Walker.addsymbol - add : ");
960 var symbol = new Symbol(_s, [], atype, this.currentDoc);
962 this.parser.addSymbol(symbol);
963 this.symbols[_s] = symbol;
965 this.currentDoc = false;
972 scopesIn : function(s)
975 //print(">>>" + this.ts.context() + "\n>>>"+this.scopes.length+":" +this.scopeListToStr());
978 scopeOut : function()
981 // print("<<<" + this.ts.context() + "\n<<<"+this.scopes.length+":" +this.scopeListToStr());
982 return this.scopes.pop();
986 scopeListToStr : function()
989 for (var i = 0; i < this.scopes.length;i++) {
990 s.push(this.scopes[i].ident);
992 return s.join('\n\t');