Fix #5666 - roojspacker - create temporary files in temporary location
[roojspacker] / src / jsdoc / DocBuilder.vala
index a86b34c..3afceb0 100644 (file)
@@ -7,29 +7,31 @@ namespace JSDOC
        class DocBuilder : Object 
        {
                
-
-               public string VERSION = "1.0.0";
+               // extractable via JSON?
+               public string VERSION = "1.0.0" ;
                
+               private SymbolSet symbolSet;
                
                private Packer packer;
        
                public DocBuilder (Packer p) 
                {
                        
-                       DocBuilder.init();
-                       GLib.debug("Roo JsDoc Toolkit started  at %s ",  (new GLib.DateTime()).format("Y/m/d H:i:s"));
+                       GLib.debug("Roo JsDoc Toolkit started  at %s ",  (new GLib.DateTime.now_local()).format("Y/m/d H:i:s"));
                        
                        this.packer = p;
         
-                   if (PackerRun.opt_tmp_dir != null && !FileUtils.test(PackerRun.opt_tmp_dir, GLib.FileTest.IS_DIR)) {   
-                       Posix.mkdir(PackerRun.opt_tmp_dir, 0700);
-                   }
+                   //if (PackerRun.singleton().opt_tmp_dir != null && !FileUtils.test(PackerRun.singleton().opt_tmp_dir, GLib.FileTest.IS_DIR)) {   
+                   //    Posix.mkdir(PackerRun.singleton().opt_tmp_dir, 0700);
+                   //}
         
        
                    this.parseSrcFiles();
                    
-                   this.symbolSet = DocParser.symbols;
-                   
+                   this.symbolSet = DocParser.symbols();
+                    
                    // this currently uses the concept of publish.js...
                    
                    this.publish();
@@ -37,39 +39,26 @@ namespace JSDOC
         
                }
                
-               static bool done_init = false;
-               
-               static GLib.Regex regex_dotdot;
-               
-               static void init()
-               {
-                       if (done_init) {
-                               return;
-                       }
-                       // ./ or ../
-                       DocBuilder.regex_dotdot = new Regex("\\\\.\\\\.?[/]");
-
-
-               }
-               
+        
                
                /**
                 * Parse the source files.
                 * 
                 */
-
                private void parseSrcFiles() 
                {
-                   DocParser.init();
+                  
                    
                    
-                   var useCache = PackerRun.opt_cache_dir == null ;
-                   var cacheFile = "";
+                   //var useCache = PackerRun.opt_cache_dir == null ;
+                   //var cacheFile = "";
                    
                    for (var i = 0, l = this.packer.files.size; i < l; i++) {
                        
                        var srcFile = this.packer.files.get(i);
-                       
+                       GLib.debug("Parsing source File: %s", srcFile);
+                    /*   
                        if (useCache) {
                        
                                cacheFile = PackerRun.opt_cache_dir + srcFile.replace("/", '_') + ".cache";
@@ -96,21 +85,21 @@ namespace JSDOC
 
                                            for(var i = 0;i < ar.get_length();i++) {
                                                        var o = ar.get_object_element(i);
-                                                       var sym = Json.gobject_from_data(typeof(Symbol), o) as Symbol;
+                                                       var sym = JSON.gobject_from_data(typeof(Symbol), o) as Symbol;
                                                        DocParser.symbols.add(sym);
                                                }
                                                continue;
                                        }
                            }
                        }
-                       
+                      */ 
                        var src = "";
                        try {
                            GLib.debug("reading : %s" , srcFile);
-                           src = GLib.FileUtils.get_contents(srcFile);
+                           GLib.FileUtils.get_contents(srcFile, out src);
                        }
                        catch(GLib.FileError e) {
-                           GLib.debug("Can't read source file '%s': %s", srcFile, e.to_string());
+                           GLib.debug("Can't read source file '%s': %s", srcFile, e.message);
                            continue;
                        }
 
@@ -126,20 +115,20 @@ namespace JSDOC
                        
 
                        var toks = tr.tokenize( new TextStream(src) );
-                       if (PackerRun.opt_dump_tokens) {
+                       if (PackerRun.singleton().opt_dump_tokens) {
                                        toks.dump();
-                                       return "";
+                                       return;
                                        //GLib.Process.exit(0);
                                }
                        
                        
-                       var ts = new TokenStream(toks);
+                       var ts = new TokenStream(toks.tokens);
                    
                    
                    
                                 
                        DocParser.parse(ts, srcFile);
-                       
+                       /*
                        if (useCache) {
                                
                                var ar = DocParser.symbolsToObject(srcFile);
@@ -161,103 +150,136 @@ namespace JSDOC
                         
                            
                                 }
+                                */
                    }
                    
+                    
                    
-                   
-                   Parser.finish();
+                   DocParser.finish();
                }
-               
-     
+               /*
+
+            //var txs =
+            
+            var tr = new  TokenReader(this.packer);
+                       tr.keepDocs = true;
+                       tr.keepWhite = true;
+                       tr.keepComments = true;
+                       tr.sepIdents = false;
+                       tr.collapseWhite = false;
+                       tr.filename = src;
+            
+
+            var toks = tr.tokenize( new TextStream(src));
+            if (PackerRun.opt_dump_tokens) {
+                               toks.dump();
+                               return "";
+                               //GLib.Process.exit(0);
+                       }
+            
+            
+            var ts = new TokenStream(toks);
+        
+        
+        
+                     
+            DocParser.parse(ts, srcFile);
+            
+            if (useCache) {
+                       
+                       var ar = DocParser.symbolsToObject(srcFile);
+                       
+                       var builder = new Json.Builder ();
+               builder.begin_array ();
+               for (var i=0;i<ar.size;i++) {
+               
+                                       builder.add_object_value (ar.get(i));
+                               }
+                               builder.end_array ();
+                               Json.Generator generator = new Json.Generator ();
+                               Json.Node root = builder.get_root ();
+                               generator.set_root (root);
+                               generator.pretty=  true;
+                               generator.ident = 2;
+                               generator.to_file(cacheFile);
+            
+             
+                
+    //         }
+        }
+        
+        
+        
+        Parser.finish();
+    }
+    
+     */
+       string tempdir;
         
                void publish() 
                {
                    GLib.debug("Publishing");
                     
                    // link!!!
-                   
+                   this.tempdir = GLib.DirUtils.make_tmp("roopackerXXXXXX");
                    
                    GLib.debug("Making directories");
-                   if (!File.isDirectory(PackerRun.opt_doc_target)) {
-                       Posix.mkdir(PackerRun.opt_doc_target,0755);
+                   if (!FileUtils.test (PackerRun.singleton().opt_doc_target,FileTest.IS_DIR )) {
+                       Posix.mkdir(PackerRun.singleton().opt_doc_target,0755);
                    }
-                   if (!File.isDirectory(PackerRun.opt_doc_target+"/symbols")) {
-                       Posix.mkdir(PackerRun.opt_doc_target+"/symbols",0755);
+                   if (!FileUtils.test(PackerRun.singleton().opt_doc_target+"/symbols",FileTest.IS_DIR)) {
+                       Posix.mkdir(PackerRun.singleton().opt_doc_target+"/symbols",0755);
                    }
-                   if (!File.isDirectory(PackerRun.opt_doc_target+"/symbols/src")) {
-                       Posix.mkdir(PackerRun.opt_doc_target+"/symbols/src",075);
+                   if (!FileUtils.test(PackerRun.singleton().opt_doc_target+"/src",FileTest.IS_DIR)) {
+                       Posix.mkdir(PackerRun.singleton().opt_doc_target+"/src",0755);
                    }
-                   if (!File.isDirectory(PackerRun.opt_doc_target +"/json")) {
-                       File.mkdir(PackerRun.opt_doc_target +"/json",0755);
+                   if (!FileUtils.test(PackerRun.singleton().opt_doc_target +"/json",FileTest.IS_DIR)) {
+                       Posix.mkdir(PackerRun.singleton().opt_doc_target +"/json",0755);
                    }
                    
-                   GLib.debug("Copying files from static: %s " , PackerRun.opt_doc_template_dir);
+                   GLib.debug("Copying files from static: %s " , PackerRun.singleton().opt_doc_template_dir);
                    // copy everything in 'static' into 
                    
-                   var iter = GLib.File.new_from_path(PackerRun.opt_doc_template_dir + "/static").enumerate_children (
-                               "standard::*",
-                               FileQueryInfoFlags.NOFOLLOW_SYMLINKS, 
-                               null);
-                   
-                   
-                   while ( (info = enumerator.next_file (null)) != null) {
-                               if (info.get_file_type () == FileType.DIRECTORY) {
-                                       continue;
-                               } 
-                               var src = File.new_from_path(info.get_name());
-                       GLib.debug("Copy %s to %s/%s" , info.get_name() , f,  PackerRun.opt_doc_target , src.get_basename());                   
-                       
-                               src.copy(
-                                       GLib.File.new_from_path(PackerRun.opt_doc_target + '/' + src.get_basename()),
-                                       GLib.FileCopyFlags.OVERWRITE
-                               );
-                       }
-       
-                   
+                   if (PackerRun.singleton().opt_doc_template_dir  != null) {
+                               
+                               var iter = GLib.File.new_for_path(
+                                               PackerRun.singleton().opt_doc_template_dir + "/static"
+                                       ).enumerate_children (
+                                       "standard::*",
+                                       FileQueryInfoFlags.NOFOLLOW_SYMLINKS, 
+                                       null);
+                               FileInfo info;
+                               
+                               while ( (info = iter.next_file (null)) != null) {
+                                       if (info.get_file_type () == FileType.DIRECTORY) {
+                                               continue;
+                                       } 
+                                       var src = File.new_for_path(info.get_name());
+                                   GLib.debug("Copy %s to %s/%s" ,
+                                        info.get_name() ,
+                                         PackerRun.singleton().opt_doc_target , src.get_basename());                   
+                               
+                                       src.copy(
+                                               GLib.File.new_for_path(
+                                                       PackerRun.singleton().opt_doc_target + "/" + src.get_basename()
+                                               ),
+                                               GLib.FileCopyFlags.OVERWRITE
+                                       );
+                               }
+               
+                       }                   
                    GLib.debug("Setting up templates");
-                   // used to check the details of things being linked to
-                   Link.symbolSet = this.symbolSet;// need to work out where 'symbolset will be stored/set!
-                   Link.base = "../";
-                   
-                   Link.srcFileFlatName = this.srcFileFlatName; // where set?
-                   Link.srcFileRelName = this.srcFileRelName; // where set?
-                   
-                   var classTemplate = new Template( PackerRun.opt_doc_template_dir  + "/class." + PackerRun.opt_doc_ext );
-                   var classesTemplate = new Template( PackerRun.opt_doc_template_dir+"/allclasses." + PackerRun.opt_doc_ext  );
-                   var classesindexTemplate = new Template( PackerRun.opt_doc_template_dir +"/index."  + PackerRun.opt_doc_ext );
-                   var fileindexTemplate = new Template( PackerRun.opt_doc_template_dir +"/allfiles."+ PackerRun.opt_doc_ext );
-
-                   
-                   classTemplate.symbolSet = this.symbolSet; // where?
-                   
-                   /*
-                   function hasNoParent($) {
-                       return ($.memberOf == "")
-                   }
-                   function isaFile($) {
-                       return ($.is("FILE"))
-                   }
-                   function isaClass($) {
-                       return ($.is("CONSTRUCTOR") || $.isNamespace || $.isClass); 
-                   }
-                   */
-                   
-                   
-                   
-                   
-                   
-                   
-                   
+                    
                    
                    
-                   var symbols = this.symbolSet.toArray();
+                   var symbols = this.symbolSet.values();
                    
                    var files = this.packer.files;
                    
                    for (var i = 0, l = files.size; i < l; i++) {
                        var file = files.get(i);
-                       var targetDir = PackerRun.opt_doc_target + "/symbols/src/";
-                       this.makeSrcFile(file, targetDir);
+                      // var targetDir = PackerRun.singleton().opt_doc_target + "/symbols/src/";
+                       this.makeSrcFile(file);
                    }
                    //print(JSON.stringify(symbols,null,4));
                    var classes = new Gee.ArrayList<Symbol>();
@@ -266,7 +288,7 @@ namespace JSDOC
                                if (symbol.isaClass()) { 
                                        classes.add(symbol);
                                }
-                   }   
+                   }    
                    classes.sort( (a,b) => {
                                return a.alias.collate(b.alias); 
                        });
@@ -276,8 +298,8 @@ namespace JSDOC
                   // var classesIndex = classesTemplate.process(classes); // kept in memory
                    
                    GLib.debug("iterate classes");
-                   
-                   var jsonAll = new JSON.Object(); 
+                  
+                   var jsonAll = new Json.Object(); 
                    
                    for (var i = 0, l = classes.size; i < l; i++) {
                        var symbol = classes.get(i);
@@ -286,232 +308,486 @@ namespace JSDOC
                        GLib.debug("classTemplate Process : %s" , symbol.alias);
                        
                        
-                       
-                       
-                       FileUtils.set_contents(
-                                               PackerRun.opt_doc_target+"/symbols/" +symbol.alias+'.' + PackerRun.opt_doc_ext ,
-                               classTemplate.process(symbol)
-                       );
+                       var   class_gen = new Json.Generator ();
+                           var  class_root = new Json.Node(Json.NodeType.OBJECT);
+                               class_root.init_object(this.class_to_json(symbol));
+                               class_gen.set_root (class_root);
+                               class_gen.pretty=  true;
+                               class_gen.indent = 2;
+                               GLib.warning("writing JSON:  %s", PackerRun.singleton().opt_doc_target+"/symbols/" +symbol.alias+".json");
+                               this.writeJson(class_gen, PackerRun.singleton().opt_doc_target+"/symbols/" +symbol.alias+".json");
                        
                        jsonAll.set_object_member(symbol.alias,  this.publishJSON(symbol));
 
                    }
-                   Json.Generator generator = new Json.Generator ();
-                       generator.set_root (jsonAll.get_node());
+                   
+                   // outptu class truee
+                   
+                   var   class_tree_gen = new Json.Generator ();
+           var  class_tree_root = new Json.Node(Json.NodeType.ARRAY);
+                       class_tree_root.init_array(this.class_tree(classes));
+                       class_tree_gen.set_root (class_tree_root);
+                       class_tree_gen.pretty=  true;
+                       class_tree_gen.indent = 2;
+                       GLib.warning("writing JSON:  %s", PackerRun.singleton().opt_doc_target+"/tree.json");
+                       this.writeJson(class_tree_gen,PackerRun.singleton().opt_doc_target+"/tree.json");
+                       size_t class_tree_l;
+                       //GLib.debug("JSON: %s", class_tree_gen.to_data(out class_tree_l));
+                   
+                   
+                   
+                   /*---- this is our 'builder' json file.. -- a full list of objects+functions */
+                   
+                   
+                   var   generator = new Json.Generator ();
+           var  root = new Json.Node(Json.NodeType.OBJECT);
+                       root.init_object(jsonAll);
+                       generator.set_root (root);
                        generator.pretty=  true;
-                       generator.ident = 2;
-                       generator.to_file(PackerRun.opt_doc_target+"/json/roodata.json");
-
+                       generator.indent = 2;
+                       GLib.warning("writing JSON:  %s", PackerRun.singleton().opt_doc_target+"/json/roodata.json");
+                       
+                       
+                       this.writeJson(generator,PackerRun.singleton().opt_doc_target+"/json/roodata.json");
+                       size_t l;
+                       //GLib.debug("JSON: %s", generator.to_data(out l));
                    
                    
-                   // regenrate the index with different relative links
-                   Link.base = "";
-                   //var classesIndex = classesTemplate.process(classes);
+                    
                    
                    GLib.debug("build index");
+                  
                    
-                   FileUtils.set_contents(
-                               PackerRun.opt_doc_target +  "/index." + PackerRun.opt_doc_ext , 
-                       classesindexTemplate.process(classes)
-                   );
                    
-                   // blank everything???? classesindexTemplate = classesIndex = classes = null;
+               }
+               
+               Json.Object class_to_json (Symbol cls)
+               {
+                       var ret = new Json.Object();
+                       ret.set_string_member("name", cls.alias);
+                       var ag = new Json.Array();
+                       ret.set_array_member("augments", ag);                   
+                       for(var ii = 0, il = cls.augments.size; ii < il; ii++) {
+                  var contributer = this.symbolSet.getSymbol(cls.augments[ii]);
+                  if (contributer == null) {
+                       continue;
+                       }
+                  ag.add_string_element(contributer.alias);
+            }
+            ret.set_string_member("name", cls.alias);  
+            ret.set_string_member("desc", cls.desc);
+               ret.set_boolean_member("isSingleton", cls.comment.getTag(DocTagTitle.SINGLETON).size > 0);
+               ret.set_boolean_member("isStatic", cls.isa != "CONSTRUCTOR");
+               ret.set_boolean_member("isBuiltin", cls.isBuiltin());
+               
+               // needded so that the class can fake a ctor..
+            ret.set_string_member("memberOf", cls.name);
+                       ret.set_string_member("example", cls.comment.getTagAsString(DocTagTitle.EXAMPLE));
+                   ret.set_string_member("deprecated", // as depricated is used as a flag...
+                                       cls.comment.getTag(DocTagTitle.DEPRECATED).size > 0 ? 
+                                       "This has been deprecated: "+  cls.comment.getTagAsString(DocTagTitle.DEPRECATED) : 
+                               "");
+               ret.set_string_member("since", cls.comment.getTagAsString(DocTagTitle.SINCE));
+               ret.set_string_member("see", cls.comment.getTagAsString(DocTagTitle.SINCE));
+                       // not supported or used yet?
+                       //add.set_string_member("exceptions", m.comment.getTagAsString(DocTagTitle.EXCEPTIONS));
+                       //add.set_string_member("requires", m.comment.getTagAsString(DocTagTitle.REQUIRES));
+               ret.set_array_member("params", cls.paramsToJson());
+               ret.set_array_member("returns", new Json.Array()); 
+                               
+                       //ret.set_string_member("desc", cls.comment.getTagAsString(DocTagTitle.DESC));
+               /// fixme - @see ... any others..
+                       
+                       var props = new Json.Array(); 
+                       ret.set_array_member("config", props);
+                       var cfgProperties = cls.configToArray();
+                       for(var i =0; i < cfgProperties.size;i++) {
+                       var p = cfgProperties.get(i);
+                       var add = new Json.Object();
+                       add.set_string_member("name",p.name);
+                       add.set_string_member("type",p.type);
+                       add.set_string_member("desc",p.desc);
+                       add.set_string_member("memberOf",  p.memberOf);
+                       add.set_array_member("values",p.optvalues.size > 0 ? p.optvalue_as_json_array() : new Json.Array());
+                       props.add_object_element(add );
+                   }
+                    
+                   // methods
+
+                        
+                       var methods = new Json.Array();
+                       ret.set_array_member("methods", methods);                    
+                   foreach(var m in cls.methods) {
+                       if (m.isEvent || m.isIgnored) {
+                               continue;
+                       }
+                       
+                       var add = new Json.Object();
+                       add.set_string_member("name",m.name);
+                       //add.set_string_member("type","function");
+                       add.set_string_member("desc",m.desc);
+                       //add.set_string_member("sig", m.makeMethodSkel());
+                       add.set_boolean_member("isStatic", m.isStatic);
+                       add.set_boolean_member("isConstructor", m.isa == "CONSTRUCTOR");
+                       add.set_boolean_member("isPrivate", m.isPrivate);
+                       //add.set_string_member("instanceOf", m.comment.getTagAsString(DocTagTitle.INSTANCEOF));
+                       add.set_string_member("memberOf", m.memberOf);
+                       add.set_string_member("example", m.comment.getTagAsString(DocTagTitle.EXAMPLE));
+                       add.set_string_member("deprecated", // as depricated is used as a flag...
+                                       m.comment.getTag(DocTagTitle.DEPRECATED).size > 0 ? 
+                                       "This has been deprecated: "+  m.comment.getTagAsString(DocTagTitle.DEPRECATED) : 
+                                       "");
+                       add.set_string_member("since", m.comment.getTagAsString(DocTagTitle.SINCE));
+                       add.set_string_member("see", m.comment.getTagAsString(DocTagTitle.SINCE));
+                       // not supported or used yet?
+                       //add.set_string_member("exceptions", m.comment.getTagAsString(DocTagTitle.EXCEPTIONS));
+                       //add.set_string_member("requires", m.comment.getTagAsString(DocTagTitle.REQUIRES));
+                       add.set_array_member("params", m.paramsToJson());
+                       add.set_array_member("returns", m.returnsToJson());
+                       
+                       /// fixme - @see ... any others..
+                         
+                       
+                       methods.add_object_element(add);
+                   }
                    
-        
-                   /*
-                   var documentedFiles = symbols.filter(function ($) {
-                       return ($.is("FILE"))
-                   });
                    
-                   var allFiles = [];
+                       var events = new Json.Array();
+                       ret.set_array_member("events", events);              
+                   foreach(var m in cls.methods) {
+                       if (!m.isEvent || m.isIgnored) {
+                               continue;
+                       }
+                       
+                       var add = new Json.Object();
+                       add.set_string_member("name",m.name.substring(1)); // all prefixed with '*'...
+                       //add.set_string_member("type","function");
+                       add.set_string_member("desc",m.desc);
+                       //add.set_string_member("sig", m.makeMethodSkel());
+
+                       add.set_string_member("memberOf", m.memberOf);
+                       add.set_string_member("example", m.comment.getTagAsString(DocTagTitle.EXAMPLE));
+                       add.set_string_member("deprecated", // as depricated is used as a flag...
+                                       m.comment.getTag(DocTagTitle.DEPRECATED).size > 0 ? 
+                                       "This has been deprecated: "+  m.comment.getTagAsString(DocTagTitle.DEPRECATED) : 
+                                       "");
+                       add.set_string_member("since", m.comment.getTagAsString(DocTagTitle.SINCE));
+                       add.set_string_member("see", m.comment.getTagAsString(DocTagTitle.SINCE));
+                       // not supported or used yet?
+                       //add.set_string_member("exceptions", m.comment.getTagAsString(DocTagTitle.EXCEPTIONS));
+                       //add.set_string_member("requires", m.comment.getTagAsString(DocTagTitle.REQUIRES));
+                       
+                       add.set_array_member("params", m.paramsToJson());
+                       add.set_array_member("returns", m.returnsToJson());
+                       
+                       /// fixme - @see ... any others..
+                         
+                       
+                       events.add_object_element(add);
+                   }
                    
-                   for (var i = 0; i < files.length; i++) {
-                       allFiles.push(new  Symbol(files[i], [], "FILE", new DocComment("/** *" + "/")));
+                       
+                       
+               
+                       return ret;
+               }
+               /**
+               * needed as Json dumps .xXXX into same directory as it writes...
+               */
+               void writeJson(Json.Generator g, string fname)
+               {
+                               var tmp = this.tempdir + GLib.Path.get_basename(fname);
+                               g.to_file(tmp);
+                               
+                               if (GLib.FileUtils.test(fname, GLib.FileTest.EXISTS)) {
+                                       string new_data, old_data;
+                                       FileUtils.get_contents(tmp, out new_data);
+                                       FileUtils.get_contents(fname, out old_data);
+                                       if (old_data == new_data) {
+                                               GLib.File.new_for_path(tmp).delete();
+                                               return;
+                                       }
+                          }
+                               
+                       GLib.File.new_for_path(tmp).move( File.new_for_path(fname), GLib.FileCopyFlags.OVERWRITE);
+                     
+               }
+               
+               /**
+                * JSON files are lookup files for the documentation
+                * - can be used by IDE's or AJAX based doc tools
+                * 
+                * 
+                */
+               Json.Object publishJSON (Symbol data)
+               {
+                   // what we need to output to be usefull...
+                   // a) props..
+                   var cfgProperties = new Gee.ArrayList<DocTag>();
+                   if (data.comment.getTag(DocTagTitle.SINGLETON).size < 1) {
+                        cfgProperties = data.configToArray();
+                        cfgProperties.sort((a,b) =>{
+                               return a.name.collate(b.name);
+                       }); 
+                       
+                   } 
+                   
+                   var props = new Json.Array(); 
+                   //println(cfgProperties.toSource());
+                   
+                   for(var i =0; i < cfgProperties.size;i++) {
+                       var p = cfgProperties.get(i);
+                       var add = new Json.Object();
+                       add.set_string_member("name",p.name);
+                       add.set_string_member("type",p.type);
+                       add.set_string_member("desc",p.desc);
+                       add.set_string_member("memberOf", p.memberOf == data.alias ? "" : p.memberOf);
+                           
+                       if (p.optvalues.size > 0) {
+                               add.set_array_member("desc",p.optvalue_as_json_array());
+                       }
+                       
+                       props.add_object_element(add );
                    }
                    
-                   for (var i = 0; i < documentedFiles.length; i++) {
-                       var offset = files.indexOf(documentedFiles[i].alias);
-                       allFiles[offset] = documentedFiles[i];
+                   ///// --- events
+                   var ownEvents = new Gee.ArrayList<Symbol>();
+                   for(var i =0; i < data.methods.size;i++) {
+                               var e = data.methods.get(i);
+                               if (e.isEvent && !e.isIgnored) {
+                                       ownEvents.add(e);
+                               }
+                       }; 
+                       ownEvents.sort((a,b) => {
+                               return a.name.collate(b.name);
+                       });
+                   
+                   var events = new Json.Array();
+                    
+                   for(var i =0; i < ownEvents.size;i++) {
+                       var m = ownEvents.get(i);
+                       var add = new Json.Object();
+                       add.set_string_member("name",m.name.substring(1,-1)); // remove'*' on events..
+                       add.set_string_member("type","function");
+                       add.set_string_member("desc",m.desc);
+                       add.set_string_member("sig", m.makeFuncSkel());
+                       add.set_string_member("memberOf", m.memberOf == data.alias ? "" : m.memberOf);                  
+                       events.add_object_element(add);
+                   } 
+                    
+                   // methods
+                   var ownMethods = new Gee.ArrayList<Symbol>();
+                   for(var i =0; i < data.methods.size;i++) {
+                               var e = data.methods.get(i);
+                               if (!e.isEvent && !e.isIgnored) {
+                                       ownMethods.add(e);
+                               }
+                       };
+                       ownMethods.sort((a,b) => {
+                               return a.name.collate(b.name);
+                       });
+                   
+                       var methods = new Json.Array();
+                    
+                   for(var i =0; i < ownMethods.size;i++) {
+                       var m = ownMethods.get(i);
+                       var add = new Json.Object();
+                       add.set_string_member("name",m.name);
+                       add.set_string_member("type","function");
+                       add.set_string_member("desc",m.desc);
+                       add.set_string_member("sig", m.makeMethodSkel());
+                       add.set_boolean_member("static", m.isStatic);
+                       add.set_string_member("memberOf", m.memberOf == data.alias ? "" : m.memberOf);  
+                       methods.add_object_element(add);
                    }
-                       
-                   allFiles = allFiles.sort(makeSortby("name"));
-                   GLib.debug("write files index");
+                    
+                   //println(props.toSource());
+                   // we need to output:
+                   //classname => {
+                   //    propname => 
+                   //        type=>
+                   //        desc=>
+                   //    }
+                       var ret =  new Json.Object();
+                       ret.set_array_member("props", props);
+                       ret.set_array_member("events", events);
+                       ret.set_array_member("methods", methods);
+               
+                   return ret;
                    
-                   FileUtils.set_contents(
-                               PackerRun.opt_doc_target + "/files." + PackerRun.opt_doc_ext , 
-                       fileindexTemplate.process(allFiles)
-                   );
-                   */
                    
+                   // b) methods
+                   // c) events
                    
                    
                }
-    /**
-     * JSON files are lookup files for the documentation
-     * - can be used by IDE's or AJAX based doc tools
-     * 
-     * 
-     */
-    JSON.Object publishJSON (Symbol data)
-    {
-        // what we need to output to be usefull...
-        // a) props..
-        var cfgProperties = new GLib.ArrayList<Symbol>();
-        if (!data.comment.getTag(DocTagTitle.SINGLETON).length) {
-            cfgProperties = data.configToArray();
-            cfgProperties = cfgProperties.sort((a,b) =>{
-                       return a.alias.collate(b.alias);
-            });
-            
-        }
-        
-        var props = new JSON.Array();; 
-        //println(cfgProperties.toSource());
-        
-        for(var i =0; i < cfgProperties.size;i++) {
-            var p = cfgPropertiesget.get(i);
-            var add = new JSON.Object();
-            add.set_string_member("name",p.name);
-            add.set_string_member("type",p.type);
-            add.set_string_member("desc",p.desc);
-            add.set_string_member("memberOf", p.memberOf == data.alias ? '' : p.memberOf);
-                
-            if (p.optvalues.size) {
-                       add.set_array_member("desc",p.optvalues_as_json_array());
-            }
-            props.add_object(add );
-        }
-        
-        ///// --- events
-        var ownEvents = new Gee.ArrayList<Symbol>();
-        for(var i =0; i < data.methods.size;i++) {
-               var e = data.methods.get(i);
-               if (e.isEvent && e.comment.getTag(DocTagTitle.HIDE) == "") {
-                       ownEvents.add(e);
-                       }
-               };
-               ownEvents.sort((a,b) => {
-                       return a.name.collate(b.name);
-               });
-        
-        var events = new JSON.Array();
-         
-        for(var i =0; i < ownEvents.size;i++) {
-            var m = ownEvents.get(i);
-            var add = new JSON.Object();
-            add.set_string_member("name",m.name.substring(1,m.name.length-1);
-            add.set_string_member("type","function");
-            add.set_string_member("desc",m.desc);
-            add.set_string_member("sig", this.makeFuncSkel(m.params));
-            events.add(add);
-        }
-        
-        // methods
-        var ownMethods = new Gee.ArrayList<Symbol>();
-        for(var i =0; i < data.methods.size;i++) {
-               var e = data.methods.get(i);
-               if (!e.isEvent && e.comment.getTag(DocTagTitle.HIDE) == "") {
-                       ownMethods.add(e);
+               Gee.HashMap<string,Json.Object> class_tree_map;
+               Json.Array class_tree_top;
+               
+               Json.Object? class_tree_new_obj(string name, bool is_class, out bool is_new) 
+               {
+               if (this.class_tree_map.has_key(name)) {
+                       var ret = this.class_tree_map.get(name);
+                       if (!ret.get_boolean_member("is_class") && is_class) {
+                               ret.set_boolean_member("is_class", is_class);
+                       }
+                       is_new = false;
+                       return ret; // no need to do anything
+               
+               }
+               
+               GLib.debug("Class Tree: new object %s", name);
+               var add =  new Json.Object();
+               add.set_string_member("name", name);
+               add.set_array_member("cn", new Json.Array());
+               add.set_boolean_member("is_class", is_class);
+               this.class_tree_map.set(name, add);
+               var bits = name.split(".");
+               if (bits.length == 1) {
+                       // top level..
+                       this.class_tree_top.add_object_element(add);
+                        
+               } 
+               is_new = true;
+               
+                       return add;
+               
+               }
+               
+               void class_tree_make_parents(  Json.Object add)
+               {
+                       var name = add.get_string_member("name");
+                       var bits = name.split(".");
+               if (bits.length < 2) {
+                       return;
+               }
+               // got aaa.bb or aaa.bb.cc
+               // find the parent..
+               string[] nn = {};
+               for(var i=0; i < bits.length-1; i++) {
+                       nn += bits[i];
+               }
+               var pname = string.joinv(".", nn);
+               GLib.debug("Class Tree: adding to parent %s => %s", name, pname); 
+                        
+                       // no parent found.. make one..
+                       bool is_new;
+                       var parent = this.class_tree_new_obj(pname, false, out is_new); 
+                       parent.get_array_member("cn").add_object_element(add);
+                       if (is_new) {
+                               this.class_tree_make_parents(  parent);
                        }
-               };
-               ownMethods.sort((a,b) => {
-                       return a.name.collate(b.name);
-               });
-        
-               var methods = new JSON.Array();
-         
-        for(var i =0; i < ownMethods.size;i++) {
-            var m = ownMethods.get(i);
-            var add = new JSON.Object();
-            add.set_string_member("name",m.name.substring(1,m.name.length-1);
-            add.set_string_member("type","function");
-            add.set_string_member("desc",m.desc);
-            add.set_string_member("sig", this.makeMethodSkel(m.params));
-            events.add(add);
-        }
-         
-        //println(props.toSource());
-        // we need to output:
-        //classname => {
-        //    propname => 
-        //        type=>
-        //        desc=>
-        //    }
-               var ret =  new JSON.Object();
-               ret.set_object_member("props", props);
-               ret.set_object_member("events", events);
-               ret.set_object_member("methods", methods);
+               
                
-       return ret;
-        
-        
-        // b) methods
-        // c) events
-        
-        
-    },
-     
-    // in Link (js) ???
-    string srcFileRelName(string sourceFile)
-    {
-               return sourceFile.substring(PackerRun.opt_real_basedir.length+1);
-    }
-    string srcFileFlatName(string sourceFile)
-    {
-        var name = this.srcFileRelName(sourceFile);
-        name = DocBuilder.regex_dotdot.replace(name, name.length, 0, "");
-        name = name.replace("/", "_").replace(":", "_") + .".html";
-        
-    }
-    
-    
-    void makeSrcFile(string sourceFile) 
-    {
-        // this stuff works...
-     
-        
-        var name = this.srcFileFlatName(sourceFile);
-        
-        GLib.debug("Write Source file : %s/symbols/src/%s", opt_doc_target, name);
-        var pretty = PrettyPrint.toPretty(FileUtils.get_contenst(sourceFile));
-        File.write(PackerRun.opt_doc_target+"/symbols/src/" + name, 
-            "<html><head>" +
-            "<title>" + sourceFile + "</title>" +
-            "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../../css/highlight-js.css\"/>" + 
-            "</head><body class=\"highlightpage\">" +
-            pretty +
-            "</body></html>");
-    },
-    /**
-     * used by JSON output to generate a function skeleton
-     */
-     /*
-    string makeFuncSkel(Gee.ArrayList<Symbol> params) {
-        if (params.length < 0) {
-                return "function ()\n{\n\n}";
                }
+               Json.Array class_tree (Gee.ArrayList<Symbol> classes )
+               {
                
-        return "function ("    +
-            params.filter(
-                function($) {
-                    return $.name.indexOf(".") == -1; // don't show config params in signature
-                }
-            ).map( function($) { return $.name == 'this' ? '_self' : $.name; } ).join(", ") +
-        ")\n{\n\n}";
-    },
-       makeMethodSkel :function(params) {
-        if (!params) return "()";
-        return "("     +
-            params.filter(
-                function($) {
-                    return $.name.indexOf(".") == -1; // don't show config params in signature
-                }
-            ).map( function($) { return  $.type + " "  +(  $.name == 'this' ? '_self' : $.name ); } ).join(", ") +
-        ")";
-    }
-    */
-};
+               
+                   // produce a tree array that can be used to render the navigation.
+                   /*
+                   should produce:
+                   
+                   [
+                       {
+                               name : Roo,
+                               desc : ....
+                               is_class : true,
+                               cn : [
+                                       {
+                                               name : 'Roo.util',
+                                               basename : 'util',
+                                               is_class : false,
+                                               cn : [
+                                                       {
+                                                               ....
+                   
+                   to do this, we will need to create the objects in a hashmap
+                   Roo.util => Json.Object
+                   
+                   */
+                   this.class_tree_top = new Json.Array();
+                   this.class_tree_map = new Gee.HashMap<string,Json.Object>();
+                   foreach (var cls in classes) {
+                       if(cls.alias.length < 1 || cls.alias == "this" || cls.alias == "_global_") {
+                               continue;
+                       }
+                       bool is_new;
+                       var add =  this.class_tree_new_obj(cls.alias, cls.methods.size > 0 ? true : false,out is_new);
+                               if (add != null) {
+                                       this.class_tree_make_parents( add);
+                               }
+                       
+                   }
+                   
+                    return this.class_tree_top;
+                   
+               }
+               
+               
+               // in Link (js) ???
+               string srcFileRelName(string sourceFile)
+               {
+                       var rp = Posix.realpath(sourceFile);
+                       return rp.substring(PackerRun.singleton().opt_real_basedir.length);
+               }
+               string srcFileFlatName(string sourceFile)
+               {
+                   var name = this.srcFileRelName(sourceFile);
+                   name = /\.\.?[\/]/.replace(name, name.length, 0, "");
+                   name = name.replace("/", "_").replace(":", "_") + ".html";
+                   return name;
+               }
+               
+               
+               void makeSrcFile(string sourceFile) 
+               {
+                   // this stuff works...
+                   
+                  
+                   
+                       // this check does not appear to work according to the doc's - need to check it out.
+              
+                 
+                   var name = this.srcFileFlatName(sourceFile);
+                   
+                   GLib.debug("Write Source file : %s/src/%s", 
+               PackerRun.singleton().opt_doc_target, name);
+               var str = "";
+               FileUtils.get_contents(sourceFile, out str);
+                   var pretty = PrettyPrint.toPretty(str); 
+                    var fname = PackerRun.singleton().opt_doc_target+"/src/" + name;
+                   
+                   var tmp = this.tempdir + GLib.Path.get_basename(fname);
+                   FileUtils.set_contents(
+                       tmp, 
+                       "<html><head>" +
+                       "<title>" + sourceFile + "</title>" +
+                       "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../css/highlight-js.css\"/>" + 
+                       "</head><body class=\"highlightpage\">" +
+                       pretty +
+                       "</body></html>");
+                       
+                   // same content?
+                    if (GLib.FileUtils.test(fname, GLib.FileTest.EXISTS)) {
+                               string new_data, old_data;
+                               FileUtils.get_contents(tmp, out new_data);
+                               FileUtils.get_contents(fname, out old_data);
+                               if (old_data == new_data) {
+                                       GLib.File.new_for_path(tmp).delete();
+                                       return;
+                               }
+                    }
+                       
+               GLib.File.new_for_path(tmp).move( File.new_for_path(fname), GLib.FileCopyFlags.OVERWRITE);
+                     
+                   
+                   
+
+               }
+       }
+                
+}