7 public class DocBuilder : Object
11 // extractable via JSON?
12 public string VERSION = "1.0.0" ;
14 private SymbolSet symbolSet;
16 public Symbol getSymbol(string name) // wrapper for read only...
18 return this.symbolSet.getSymbol(name);
24 private Packer packer;
26 public DocBuilder (Packer p)
30 GLib.debug("Roo JsDoc Toolkit started at %s ", (new GLib.DateTime.now_local()).format("Y/m/d H:i:s"));
34 //if (PackerRun.singleton().opt_tmp_dir != null && !FileUtils.test(PackerRun.singleton().opt_tmp_dir, GLib.FileTest.IS_DIR)) {
35 // Posix.mkdir(PackerRun.singleton().opt_tmp_dir, 0700);
41 DocParser.validateAugments();
42 DocParser.fillChildClasses();
43 DocParser.fillTreeChildren();
46 this.symbolSet = DocParser.symbols();
49 var classes = DocParser.classes();
52 // this currently uses the concept of publish.js...
54 if (PackerRun.singleton().opt_doc_dump_tree) {
60 //print(JSON.stringify(symbols,null,4));
62 var jsonAll = new Json.Object();
63 var ar = new Json.Array();
64 for (var i = 0, l = this.symbolSet.values().size; i < l; i++) {
65 var symbol = this.symbolSet.values().get(i);
67 ar.add_object_element( symbol.toJson());
70 jsonAll.set_array_member("data", ar);
71 var generator = new Json.Generator ();
72 var root = new Json.Node(Json.NodeType.OBJECT);
74 root.init_object(jsonAll);
75 generator.set_root (root);
76 generator.pretty= true;
80 stdout.printf("%s\n",generator.to_data(out l));
85 //GLib.debug("JSON: %s", generator.to_data(out l));
98 * Parse the source files.
102 private void parseSrcFiles()
107 //var useCache = PackerRun.opt_cache_dir == null ;
108 //var cacheFile = "";
110 for (var i = 0, l = this.packer.files.size; i < l; i++) {
112 var srcFile = this.packer.files.get(i);
113 GLib.debug("Parsing source File: %s", srcFile);
117 cacheFile = PackerRun.opt_cache_dir + srcFile.replace("/", '_') + ".cache";
120 // disabled at present!@!!
122 if (GLib.FileUtils.test(cacheFile, GLib.FileTest.EXISTS)) {
124 var cache_mt = File.new_for_path (cacheFile).queryInfo(FileAttribute.TIME_MODIFIED,
125 GLib.FileQueryInfoFlags.NONE, null).
126 get_modification_time();
127 var original_mt = File.new_for_path (sourceInfo).queryInfo(FileAttribute.TIME_MODIFIED,
128 GLib.FileQueryInfoFlags.NONE, null).
129 get_modification_time();
130 // this check does not appear to work according to the doc's - need to check it out.
132 if (cache_mt > original_mt) { // cached time > original time!
133 // use the cached mtimes..
134 GLib.debug("Read %s" , cacheFile);
135 var parser = new Json.Parser();
136 parser.load_from_file(cacheFile);
137 var ar = parser.get_root ().get_array();
139 for(var i = 0;i < ar.get_length();i++) {
140 var o = ar.get_object_element(i);
141 var sym = JSON.gobject_from_data(typeof(Symbol), o) as Symbol;
142 DocParser.symbols.add(sym);
151 GLib.debug("reading : %s" , srcFile);
152 GLib.FileUtils.get_contents(srcFile, out src);
154 catch(GLib.FileError e) {
155 GLib.debug("Can't read source file '%s': %s", srcFile, e.message);
161 var tr = new TokenReader(this.packer);
164 tr.keepComments = true;
165 tr.sepIdents = false;
166 tr.collapseWhite = false;
170 var toks = tr.tokenize( new TextStream(src) );
171 if (PackerRun.singleton().opt_dump_tokens) {
174 //GLib.Process.exit(0);
178 var ts = new TokenStream(toks.tokens);
183 DocParser.parse(ts, srcFile);
192 // this is probably not the best place for this..
208 GLib.debug("Publishing");
211 this.tempdir = GLib.DirUtils.make_tmp("roopackerXXXXXX");
213 GLib.debug("Making directories");
214 if (!FileUtils.test (PackerRun.singleton().opt_doc_target,FileTest.IS_DIR )) {
215 Posix.mkdir(PackerRun.singleton().opt_doc_target,0755);
217 if (!FileUtils.test(PackerRun.singleton().opt_doc_target+"/symbols",FileTest.IS_DIR)) {
218 Posix.mkdir(PackerRun.singleton().opt_doc_target+"/symbols",0755);
220 if (!FileUtils.test(PackerRun.singleton().opt_doc_target+"/src",FileTest.IS_DIR)) {
221 Posix.mkdir(PackerRun.singleton().opt_doc_target+"/src",0755);
223 if (!FileUtils.test(PackerRun.singleton().opt_doc_target +"/json",FileTest.IS_DIR)) {
224 Posix.mkdir(PackerRun.singleton().opt_doc_target +"/json",0755);
227 GLib.debug("Copying files from static: %s " , PackerRun.singleton().opt_doc_template_dir);
228 // copy everything in 'static' into
230 if (PackerRun.singleton().opt_doc_template_dir != null) {
232 var iter = GLib.File.new_for_path(
233 PackerRun.singleton().opt_doc_template_dir + "/static"
234 ).enumerate_children (
236 FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
240 while ( (info = iter.next_file (null)) != null) {
241 if (info.get_file_type () == FileType.DIRECTORY) {
244 var src = File.new_for_path(info.get_name());
245 GLib.debug("Copy %s to %s/%s" ,
247 PackerRun.singleton().opt_doc_target , src.get_basename());
250 GLib.File.new_for_path(
251 PackerRun.singleton().opt_doc_target + "/" + src.get_basename()
253 GLib.FileCopyFlags.OVERWRITE
258 GLib.debug("Setting up templates");
262 var symbols = this.symbolSet.values();
264 var files = this.packer.files;
266 for (var i = 0, l = files.size; i < l; i++) {
267 var file = files.get(i);
268 // var targetDir = PackerRun.singleton().opt_doc_target + "/symbols/src/";
269 this.makeSrcFile(file);
271 //print(JSON.stringify(symbols,null,4));
272 var classes = DocParser.classes();
274 //GLib.debug("classTemplate Process : all classes");
276 // var classesIndex = classesTemplate.process(classes); // kept in memory
278 GLib.debug("iterate classes");
280 var jsonAll = new Json.Object();
282 for (var i = 0, l = classes.size; i < l; i++) {
283 var symbol = classes.get(i);
286 GLib.debug("classTemplate Process : %s" , symbol.alias);
289 var class_gen = new Json.Generator ();
290 var class_root = new Json.Node(Json.NodeType.OBJECT);
291 class_root.init_object(symbol.toClassDocJSON());
292 class_gen.set_root (class_root);
293 class_gen.pretty= true;
294 class_gen.indent = 2;
295 GLib.debug("writing JSON: %s", PackerRun.singleton().opt_doc_target+"/symbols/" +symbol.alias+".json");
296 this.writeJson(class_gen, PackerRun.singleton().opt_doc_target+"/symbols/" +symbol.alias+".json");
298 jsonAll.set_object_member(symbol.alias, symbol.toClassJSON());
304 var class_tree_gen = new Json.Generator ();
305 var class_tree_root = new Json.Node(Json.NodeType.ARRAY);
306 class_tree_root.init_array(this.class_tree(classes));
307 class_tree_gen.set_root (class_tree_root);
308 class_tree_gen.pretty= true;
309 class_tree_gen.indent = 2;
310 GLib.debug("writing JSON: %s", PackerRun.singleton().opt_doc_target+"/tree.json");
311 this.writeJson(class_tree_gen,PackerRun.singleton().opt_doc_target+"/tree.json");
313 //GLib.debug("JSON: %s", class_tree_gen.to_data(out class_tree_l));
317 /*---- this is our 'builder' json file.. -- a full list of objects+functions */
320 var generator = new Json.Generator ();
321 var root = new Json.Node(Json.NodeType.OBJECT);
322 root.init_object(jsonAll);
323 generator.set_root (root);
324 generator.pretty= true;
325 generator.indent = 2;
326 GLib.debug("writing Builder JSON: %s", PackerRun.singleton().opt_doc_target+"/json/roodata.json");
329 this.writeJson(generator,PackerRun.singleton().opt_doc_target+"/json/roodata.json");
331 //GLib.debug("JSON: %s", generator.to_data(out l));
336 GLib.debug("build index");
344 * needed as Json dumps .xXXX into same directory as it writes...
346 void writeJson(Json.Generator g, string fname)
348 var tmp = this.tempdir + GLib.Path.get_basename(fname);
351 if (GLib.FileUtils.test(fname, GLib.FileTest.EXISTS)) {
352 string new_data, old_data;
353 FileUtils.get_contents(tmp, out new_data);
354 FileUtils.get_contents(fname, out old_data);
355 if (old_data == new_data) {
356 GLib.File.new_for_path(tmp).delete();
361 GLib.File.new_for_path(tmp).move( File.new_for_path(fname), GLib.FileCopyFlags.OVERWRITE);
365 Gee.HashMap<string,Json.Object> class_tree_map;
366 Json.Array class_tree_top;
368 Json.Object? class_tree_new_obj(string name, bool is_class, out bool is_new)
370 if (this.class_tree_map.has_key(name)) {
371 var ret = this.class_tree_map.get(name);
372 if (!ret.get_boolean_member("is_class") && is_class) {
373 ret.set_boolean_member("is_class", is_class);
376 return ret; // no need to do anything
380 GLib.debug("Class Tree: new object %s", name);
381 var add = new Json.Object();
382 add.set_string_member("name", name);
383 add.set_array_member("cn", new Json.Array());
384 add.set_boolean_member("is_class", is_class);
386 this.class_tree_map.set(name, add);
387 var bits = name.split(".");
388 if (bits.length == 1) {
390 this.class_tree_top.add_object_element(add);
399 void class_tree_make_parents( Json.Object add)
401 var name = add.get_string_member("name");
402 var bits = name.split(".");
403 if (bits.length < 2) {
406 // got aaa.bb or aaa.bb.cc
409 for(var i=0; i < bits.length-1; i++) {
412 var pname = string.joinv(".", nn);
413 GLib.debug("Class Tree: adding to parent %s => %s", name, pname);
415 // no parent found.. make one..
417 var parent = this.class_tree_new_obj(pname, false, out is_new);
418 parent.get_array_member("cn").add_object_element(add);
420 this.class_tree_make_parents( parent);
425 Json.Array class_tree (Gee.ArrayList<Symbol> classes )
429 // produce a tree array that can be used to render the navigation.
447 to do this, we will need to create the objects in a hashmap
448 Roo.util => Json.Object
451 this.class_tree_top = new Json.Array();
452 this.class_tree_map = new Gee.HashMap<string,Json.Object>();
453 foreach (var cls in classes) {
454 if(cls.alias.length < 1 || cls.alias == "this" || cls.alias == "_global_") {
455 GLib.debug("Skip alias|global %s", cls.name);
459 var add = this.class_tree_new_obj(cls.alias, cls.methods.size > 0 ? true : false,out is_new);
461 this.class_tree_make_parents( add);
466 return this.class_tree_top;
472 string srcFileRelName(string sourceFile)
474 var rp = Posix.realpath(sourceFile);
475 return rp.substring(PackerRun.singleton().opt_real_basedir.length);
477 string srcFileFlatName(string sourceFile)
479 var name = this.srcFileRelName(sourceFile);
480 name = /\.\.?[\/]/.replace(name, name.length, 0, "");
481 name = name.replace("/", "_").replace(":", "_") + ".html";
486 void makeSrcFile(string sourceFile)
488 // this stuff works...
492 // this check does not appear to work according to the doc's - need to check it out.
495 var name = this.srcFileFlatName(sourceFile);
497 GLib.debug("Write Source file : %s/src/%s",
498 PackerRun.singleton().opt_doc_target, name);
500 FileUtils.get_contents(sourceFile, out str);
501 var pretty = PrettyPrint.toPretty(str);
502 var fname = PackerRun.singleton().opt_doc_target+"/src/" + name;
504 var tmp = this.tempdir + GLib.Path.get_basename(fname);
505 FileUtils.set_contents(
508 "<title>" + this.srcFileRelName(sourceFile) + "</title>" +
509 "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../css/highlight-js.css\"/>" +
510 "</head><body class=\"highlightpage\">" +
515 if (GLib.FileUtils.test(fname, GLib.FileTest.EXISTS)) {
516 string new_data, old_data;
517 FileUtils.get_contents(tmp, out new_data);
518 FileUtils.get_contents(fname, out old_data);
519 if (old_data == new_data) {
520 GLib.File.new_for_path(tmp).delete();
525 GLib.File.new_for_path(tmp).move( File.new_for_path(fname), GLib.FileCopyFlags.OVERWRITE);