src/jsdoc/Packer.vala
[roojspacker] / src / jsdoc / Packer.vala
index edbb527..de38574 100644 (file)
@@ -18,7 +18,7 @@ x.srcfiles = array of files (that list other files...) << not supported?
 x.target = "output.pathname.js"
 x.debugTarget = "output.pathname.debug.js"
 
+  
     
 x.pack();  // writes files  etc..
     
@@ -57,7 +57,8 @@ namespace JSDOC
        public errordomain PackerError {
             ArgumentError
     }
-
+    
+    
        public class Packer : Object 
        {
                /**
@@ -80,67 +81,214 @@ namespace JSDOC
                 *  we could do this in memory now, as I suspect vala will not be as bad as javascript for leakage...
                 *
                 */
-               public string tmpDir = "/tmp";  // FIXME??? in ctor?
-       
+               //public string tmpDir = "/tmp";  // FIXME??? in ctor?
        
-                 
-               /**
-                * @cfg {Boolean} cleanup  (optional) clean up temp files after done - 
-                *    Defaults to false if you set tmpDir, otherwise true.
-                */
-               public bool cleanup =  false;
-               
-               
-               /**
-                * @cfg {Boolean} keepWhite (optional) do not remove white space in output.
-                *    usefull for debugging compressed files.
-                */
-               
-               public bool keepWhite =  false;
-                       
-               /**
-                * @cfg {Boolean} skipScope (optional) skip Scope parsing and replacement.
-                *    usefull for debugging...
-                */
-               
-               public bool skipScope = false;
-               
-               
-               /**
-                * @cfg {Boolean} dumpTokens (optional) read the first file and dump the tokens.
-                *    usefull for debugging...
-                */
-               
-               public bool dumpTokens = false;
-               
+        
+                
                // list of files to compile...
-               Gee.ArrayList<string> files;
+               public Gee.ArrayList<string> files;
                
                /**
                * @cfg activeFile ??? used???
                */
                 
                public string activeFile = "";
+                       
+               public  string outstr = ""; // if no target is specified - then this will contain the result
+               
+               public PackerRun config;
                
+               public Packer(PackerRun config)
+               {
+                       this.config = config;
+#if HAVE_JSON_GLIB
+                       this.result = new Json.Object();
+#else
+                       this.result_count = new  Gee.HashMap <string,int>();
+               
+                       this.result =  new Gee.HashMap<
+                               string /* errtype*/ , Gee.HashMap<string /*fn*/,     Gee.HashMap<int /*line*/, Gee.ArrayList<string>>>
+                       >();
+       
+#endif                 
+                       this.files = new Gee.ArrayList<string>();
+                       
+                       new Lang_Class(); ///initilizaze lang..
+                       
+                       //this.tmp = Glib.get_tmp_dir(); // do we have to delete this?
                        
+                        
+               }
+               
+               
+               // this could be another class really..
+               
+               public enum ResultType { 
+                       err , 
+                       warn;
+                       public string to_string() { 
+                               switch(this) {
+                                       case err: return "ERR";
+                                       case warn: return "WARN";
+                                       default: assert_not_reached();
+                               }
+                       
+                         }
+                 }
                /**
-               * @cfg baseDir -- prefix the files listed in indexfiles with this.
+               *  result of complication - a JSON object containing warnings / errors etc..
+               *  FORMAT:
+               *     warn-TOTAL : X  (number of warnings.
+               *     err-TOTAL: X  (number of errors) << this indicates failure...
+               *     warn : {
+               *            FILENAME : {
+               *                  line : [ Errors,Errors,.... ]
+               *     err : {
+               *           .. sane format..
+               *
                */
-                
-               public string baseDir = "";
                
+#if HAVE_JSON_GLIB
                
-               public  string outstr = ""; // if no target is specified - then this will contain the result
-    
-               public Packer()
+               public Json.Object result;   // output - what's the complication result
+
+               public void  logError(ResultType type, string filename, int line, string message) {
+                        
+                        if (!this.result.has_member(type.to_string()+"-TOTAL")) {
+                                this.result.set_int_member(type.to_string()+"-TOTAL", 1);
+                        } else {
+                               this.result.set_int_member(type.to_string()+"-TOTAL", 
+                                       this.result.get_int_member(type.to_string()+"-TOTAL") +1 
+                               );
+                        }
+                        
+                        
+                        if (!this.result.has_member(type.to_string())) {
+                                this.result.set_object_member(type.to_string(), new Json.Object());
+                        }
+                        var t = this.result.get_object_member(type.to_string());
+                        if (!t.has_member(filename)) {
+                                t.set_object_member(filename, new Json.Object());
+                        }
+                        var tt = t.get_object_member(filename);
+                        if (!tt.has_member(line.to_string())) {
+                                tt.set_array_member(line.to_string(), new Json.Array());
+                        }
+                        var tl = tt.get_array_member(line.to_string());
+                        tl.add_string_element(message);
+                        
+               }
+               
+               public bool hasErrors(string fn)
                {
+                        if (!this.result.has_member(ResultType.err.to_string())) {
+                                return false;
+                        }
+                        
+                        if (fn.length < 1) {
+                               return true;
+                        }
+                        var t = this.result.get_object_member(ResultType.err.to_string());
+                        
+                        if (t.has_member(fn)) {
+                                return true;
+                        }
+                        return false;
+               }
+               public void dumpErrors(ResultType type)
+               {
+                        if (!this.result.has_member(type.to_string())) {
+                                return;
+                        }
+                       var t = this.result.get_object_member(type.to_string());
+                       t.foreach_member((obj, filename, node) => {
+                                       var linelist = node.dup_object();
+                                       linelist.foreach_member((linelistobj, linestr, nodear) => {
+                                               var errors=  nodear.dup_array();
+                                               errors.foreach_element((errorar, ignore, nodestr) => {
+                                                       print("%s: %s:%s %s\n", type.to_string(), filename, linestr, nodestr.get_string());
+                                               });
+                                       });
                        
-                       this.files = new Gee.ArrayList<string>();
-                       
-                       new Lang_Class(); ///initilizaze lang..
+                       });
+               }
+#else
+               public Gee.HashMap <string,int> result_count;   // output - what's the complication result
+               
+               public Gee.HashMap<
+                               string /* errtype*/ , Gee.HashMap<string /*fn*/,     Gee.HashMap<int /*line*/, Gee.ArrayList<string>>>
+               > result;
+
+               public void  logError(ResultType type, string filename, int line, string message) {
+                        
+                        
+                        if (!this.result_count.has_key(type.to_string()+"-TOTAL")) {
+                                this.result_count.set(type.to_string()+"-TOTAL", 1);
+                        } else {
+                               this.result_count.set(type.to_string()+"-TOTAL",                                 
+                                       this.result_count.get(type.to_string()+"-TOTAL") +1
+                               );
+                        }
+                        
+                        
+                        
+                        if (!this.result.has_key(type.to_string())) {
+                                this.result.set(type.to_string(),
+                                        new Gee.HashMap<string /*fn*/,     Gee.HashMap<int /*line*/, Gee.ArrayList<string>>>()
+                                );
+                        }
+                        var t = this.result.get(type.to_string());
+                        if (!t.has_key(filename)) {
+                                t.set(filename, new  Gee.HashMap<int /*line*/, Gee.ArrayList<string>>());
+                        }
+                        var tt = t.get(filename);
+                        if (!tt.has_key(line)) {
+                                tt.set(line, new Gee.ArrayList<string>());
+                        }
+                        var tl = tt.get(line);
+                        tl.add(message);
                         
                }
                
+               public bool hasErrors(string fn)
+               {
+                        if (!this.result.has_key(ResultType.err.to_string())) {
+                                return false;
+                        }
+                        
+                        if (fn.length < 1) {
+                               return true;
+                        }
+                        var t = this.result.get(ResultType.err.to_string());
+                        
+                        if (t.has_key(fn)) {
+                                return true;
+                        }
+                        return false;
+               }
+               public void dumpErrors(ResultType type)
+               {
+                        if (!this.result.has_key(type.to_string())) {
+                                return;
+                        }
+                       var t = this.result.get(type.to_string());
+                       foreach(string filename in t.keys) {
+                               var node = t.get(filename);
+                               foreach(int line in node.keys) {
+                                       var errors = node.get(line);
+                                       foreach(string errstr in errors) {
+                                                       print("%s: %s:%d %s\n", type.to_string(), filename, line, errstr);
+                                       }
+                               }
+                       
+                       }
+               }
+
+
+#endif
+               
+               
+               
                public void loadSourceIndexes(Gee.ArrayList<string> indexes)
                {
                        foreach(var f in indexes) {
@@ -165,7 +313,7 @@ namespace JSDOC
                }
                 
                
-               public string pack(string target, string targetDebug = "") throws PackerError, TokenReaderError , ScopeParserError
+               public string pack(string target, string targetDebug = "") throws PackerError 
                {
                    this.target = target;
                        this.targetDebug  = targetDebug;
@@ -197,7 +345,7 @@ namespace JSDOC
                    
                    var srcfile = in_srcfile;
                    if (srcfile[0] != '/') {
-                               srcfile = this.baseDir + in_srcfile;
+                               srcfile = config.opt_real_basedir + in_srcfile;
                        }
                    string str;
                    FileUtils.get_contents(srcfile,out str);
@@ -225,7 +373,7 @@ namespace JSDOC
                        var add = f.replace(".", "/") + ".js";
                        
                        if (add[0] != '/') {
-                                       add = this.baseDir + add;
+                                       add = config.opt_real_basedir + add;
                                }
                        
                        if (this.files.contains(add)) {
@@ -240,7 +388,7 @@ namespace JSDOC
                }
                
     
-               private string packAll() throws  TokenReaderError , ScopeParserError // do the packing (run from constructor)
+               private string packAll()   // do the packing (run from constructor)
                {
                    
                    //this.transOrigFile= bpath + '/../lang.en.js'; // needs better naming...
@@ -254,6 +402,8 @@ namespace JSDOC
                    }
                    
                    
+                   var tmpDir = GLib.DirUtils.make_tmp("roojspacker_XXXXXX");
+                   
                    foreach(var file in this.files) {
                        
                        print("reading %s\n",file );
@@ -280,7 +430,7 @@ namespace JSDOC
                        
                   
                        
-                       var minfile = this.tmpDir + "/" + file.replace("/", ".");
+                       var minfile = tmpDir + "/" + file.replace("/", ".");
                        
                        
                        // let's see if we have a min file already?
@@ -303,7 +453,7 @@ namespace JSDOC
                         
                        print("COMPRESSING to %s\n", minfile);
                        //var codeComp = pack(str, 10, 0, 0);
-                       if (this.cleanup && FileUtils.test (minfile, FileTest.EXISTS)) {
+                       if (config.opt_clean_cache && FileUtils.test (minfile, FileTest.EXISTS)) {
                            FileUtils.remove(minfile);
                        }
                        if (!loaded_string) {
@@ -315,7 +465,16 @@ namespace JSDOC
                      
                    }
                    
-                       if (this.dumpTokens) {
+                   // at this point if we have errors, we should stop..
+
+                                           
+                       this.dumpErrors(ResultType.warn);
+                       this.dumpErrors(ResultType.err); // since they are fatal - display them last...
+                       
+                       
+                       
+                       
+                       if (config.opt_dump_tokens || this.hasErrors("")) {
                                 
                                GLib.Process.exit(0);
                        }
@@ -323,7 +482,7 @@ namespace JSDOC
                    
                    for(var i=0; i < this.files.size; i++)  {
                        var file = this.files[i];
-                       var minfile = this.tmpDir + "/" + file.replace("/", ".");
+                       var minfile = tmpDir + "/" + file.replace("/", ".");
                        
                        
                        if ( !FileUtils.test(minfile, FileTest.EXISTS)) {
@@ -336,22 +495,29 @@ namespace JSDOC
                        if (str.length > 0) {
                            if (this.targetStream != null) {
                                        this.targetStream.write(("// " + 
-                                               ( (file.length > this.baseDir.length) ? file.substring(this.baseDir.length)  : file ) + 
+                                               ( (file.length > config.opt_real_basedir.length) ? file.substring(config.opt_real_basedir.length)  : file ) + 
                                                "\n").data); 
-                                       this.targetStream.write((str + "\n").data); 
+
+                                       this.targetStream.write((str + "\n").data); 
 
                            } else {
                                this.outstr += "//" + 
-                                       ( (file.length > this.baseDir.length) ? file.substring(this.baseDir.length)  : file ) +  "\n";
-                               this.outstr += str + "\n";
+                                       ( (file.length > config.opt_real_basedir.length) ? file.substring(config.opt_real_basedir.length)  : file ) +  "\n";
+                               this.outstr += "//" +  file  +"\n";
+
+                                    this.outstr += str + "\n";
                            }
                            
                        }
-                       if (this.cleanup) {
+                       if (config.opt_clean_cache) {
                            FileUtils.remove(minfile);
                        }
                        
                    }
+                   if (config.opt_clean_cache) {
+                               FileUtils.remove(tmpDir);
+                       }
+                   
                    if (this.target.length > 0 ) {
                            print("Output file: " + this.target);
                    }
@@ -359,6 +525,8 @@ namespace JSDOC
                                 print("Output debug file: %s\n" , this.targetDebug);
                        }
             
+
+            
                        // OUTPUT should be handled by PackerRun (so that this can be used as a library...)
                        if (this.outstr.length > 0 ) {
                 return this.outstr;
@@ -377,10 +545,10 @@ namespace JSDOC
                 * 
                 */
 
-               private string packFile  (string str,string fn, string minfile) throws  TokenReaderError, ScopeParserError
+               public  string packFile  (string str,string fn, string minfile)  
                {
 
-                       var tr = new  TokenReader();
+                       var tr = new  TokenReader(this);
                        tr.keepDocs =true;
                        tr.keepWhite = true;
                        tr.keepComments = true;
@@ -392,7 +560,7 @@ namespace JSDOC
                
                        TokenArray toks = tr.tokenize(new TextStream(str)); // dont merge xxx + . + yyyy etc.
                
-                       if (this.dumpTokens) {
+                       if (config.opt_dump_tokens) {
                                toks.dump();
                                return "";
                                //GLib.Process.exit(0);
@@ -405,14 +573,14 @@ namespace JSDOC
 
                        //var ts = new TokenStream(toks);
                        //print(JSON.stringify(toks, null,4 )); Seed.quit();
-                       var ts = new Collapse(toks.tokens);
+                       var ts = new Collapse(toks.tokens, this, fn);
                        
                        //ts.dumpAll("");                       print("Done collaps"); Process.exit(1);
                        
                   // print(JSON.stringify(ts.tokens, null,4 )); Seed.quit();
                        //return;//
-                       if (!this.skipScope) {
-                               var sp = new ScopeParser(ts);
+                       if (!config.opt_skip_scope) {
+                               var sp = new ScopeParser(ts, this, fn);
  
                                //sp.packer = this;
                                sp.buildSymbolTree();
@@ -426,12 +594,14 @@ namespace JSDOC
                        //print(sp.warnings.join("\n"));
                        //(new TokenStream(toks.tokens)).dumpAll(""); GLib.Process.exit(1);
                        // compress works on the original array - in theory the replacements have already been done by now 
-                       var outf = CompressWhite(new TokenStream(toks.tokens), this, this.keepWhite); // do not kill whitespace..
+                       var outf = CompressWhite(new TokenStream(toks.tokens), this, config.opt_keep_whitespace); // do not kill whitespace..
                
                        
-                       debug("RESULT: \n %s\n", outf);
-               
-                        if (outf.length > 0) {
+       //              debug("RESULT: \n %s\n", outf);
+                       
+                       
+                       
+                       if (outf.length > 0 && minfile.length > 0 && !this.hasErrors(fn)) {
                                FileUtils.set_contents(minfile, outf);
                                 
                        }