7 class DocBuilder : Object
12 // extractable via JSON?
13 public string VERSION = "1.0.0" ;
16 private Packer packer;
18 public DocBuilder (Packer p)
22 GLib.debug("Roo JsDoc Toolkit started at %s ", (new GLib.DateTime()).format("Y/m/d H:i:s"));
26 if (PackerRun.opt_tmp_dir != null && !FileUtils.test(PackerRun.opt_tmp_dir, GLib.FileTest.IS_DIR)) {
27 Posix.mkdir(PackerRun.opt_tmp_dir, 0700);
33 this.symbolSet = DocParser.symbols;
35 // this currently uses the concept of publish.js...
42 static bool done_init = false;
44 static GLib.Regex regex_dotdot;
52 DocBuilder.regex_dotdot = new Regex("\\\\.\\\\.?[/]");
59 * Parse the source files.
63 private void parseSrcFiles()
68 var useCache = PackerRun.opt_cache_dir == null ;
71 for (var i = 0, l = this.packer.files.size; i < l; i++) {
73 var srcFile = this.packer.files.get(i);
77 cacheFile = PackerRun.opt_cache_dir + srcFile.replace("/", '_') + ".cache";
80 // disabled at present!@!!
82 if (GLib.FileUtils.test(cacheFile, GLib.FileTest.EXISTS)) {
84 var cache_mt = File.new_for_path (cacheFile).queryInfo(FileAttribute.TIME_MODIFIED,
85 GLib.FileQueryInfoFlags.NONE, null).
86 get_modification_time();
87 var original_mt = File.new_for_path (sourceInfo).queryInfo(FileAttribute.TIME_MODIFIED,
88 GLib.FileQueryInfoFlags.NONE, null).
89 get_modification_time();
90 // this check does not appear to work according to the doc's - need to check it out.
92 if (cache_mt > original_mt) { // cached time > original time!
93 // use the cached mtimes..
94 GLib.debug("Read %s" , cacheFile);
95 var parser = new Json.Parser();
96 parser.load_from_file(cacheFile);
97 var ar = parser.get_root ().get_array();
99 for(var i = 0;i < ar.get_length();i++) {
100 var o = ar.get_object_element(i);
101 var sym = JSON.gobject_from_data(typeof(Symbol), o) as Symbol;
102 DocParser.symbols.add(sym);
111 GLib.debug("reading : %s" , srcFile);
112 src = GLib.FileUtils.get_contents(srcFile);
114 catch(GLib.FileError e) {
115 GLib.debug("Can't read source file '%s': %s", srcFile, e.to_string());
121 var tr = new TokenReader(this.packer);
124 tr.keepComments = true;
125 tr.sepIdents = false;
126 tr.collapseWhite = false;
130 var toks = tr.tokenize( new TextStream(src) );
131 if (PackerRun.opt_dump_tokens) {
134 //GLib.Process.exit(0);
138 var ts = new TokenStream(toks);
143 DocParser.parse(ts, srcFile);
147 var ar = DocParser.symbolsToObject(srcFile);
149 var builder = new Json.Builder ();
150 builder.begin_array ();
151 for (var i=0;i<ar.size;i++) {
153 builder.add_object_value (ar.get(i));
155 builder.end_array ();
156 Json.Generator generator = new Json.Generator ();
157 Json.Node root = builder.get_root ();
158 generator.set_root (root);
159 generator.pretty= true;
161 generator.to_file(cacheFile);
176 var tr = new TokenReader(this.packer);
179 tr.keepComments = true;
180 tr.sepIdents = false;
181 tr.collapseWhite = false;
185 var toks = tr.tokenize( new TextStream(src));
186 if (PackerRun.opt_dump_tokens) {
189 //GLib.Process.exit(0);
193 var ts = new TokenStream(toks);
198 DocParser.parse(ts, srcFile);
202 var ar = DocParser.symbolsToObject(srcFile);
204 var builder = new Json.Builder ();
205 builder.begin_array ();
206 for (var i=0;i<ar.size;i++) {
208 builder.add_object_value (ar.get(i));
210 builder.end_array ();
211 Json.Generator generator = new Json.Generator ();
212 Json.Node root = builder.get_root ();
213 generator.set_root (root);
214 generator.pretty= true;
216 generator.to_file(cacheFile);
232 GLib.debug("Publishing");
237 GLib.debug("Making directories");
238 if (!File.isDirectory(PackerRun.opt_doc_target)) {
239 Posix.mkdir(PackerRun.opt_doc_target,0755);
241 if (!File.isDirectory(PackerRun.opt_doc_target+"/symbols")) {
242 Posix.mkdir(PackerRun.opt_doc_target+"/symbols",0755);
244 if (!File.isDirectory(PackerRun.opt_doc_target+"/symbols/src")) {
245 Posix.mkdir(PackerRun.opt_doc_target+"/symbols/src",075);
247 if (!File.isDirectory(PackerRun.opt_doc_target +"/json")) {
248 File.mkdir(PackerRun.opt_doc_target +"/json",0755);
251 GLib.debug("Copying files from static: %s " , PackerRun.opt_doc_template_dir);
252 // copy everything in 'static' into
254 var iter = GLib.File.new_from_path(PackerRun.opt_doc_template_dir + "/static").enumerate_children (
256 FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
260 while ( (info = enumerator.next_file (null)) != null) {
261 if (info.get_file_type () == FileType.DIRECTORY) {
264 var src = File.new_from_path(info.get_name());
265 GLib.debug("Copy %s to %s/%s" , info.get_name() , f, PackerRun.opt_doc_target , src.get_basename());
268 GLib.File.new_from_path(PackerRun.opt_doc_target + '/' + src.get_basename()),
269 GLib.FileCopyFlags.OVERWRITE
274 GLib.debug("Setting up templates");
275 // used to check the details of things being linked to
276 Link.symbolSet = this.symbolSet;// need to work out where 'symbolset will be stored/set!
279 Link.srcFileFlatName = this.srcFileFlatName; // where set?
280 Link.srcFileRelName = this.srcFileRelName; // where set?
282 var classTemplate = new Template( PackerRun.opt_doc_template_dir + "/class." + PackerRun.opt_doc_ext );
283 var classesTemplate = new Template( PackerRun.opt_doc_template_dir+"/allclasses." + PackerRun.opt_doc_ext );
284 var classesindexTemplate = new Template( PackerRun.opt_doc_template_dir +"/index." + PackerRun.opt_doc_ext );
285 var fileindexTemplate = new Template( PackerRun.opt_doc_template_dir +"/allfiles."+ PackerRun.opt_doc_ext );
288 classTemplate.symbolSet = this.symbolSet; // where?
291 function hasNoParent($) {
292 return ($.memberOf == "")
294 function isaFile($) {
295 return ($.is("FILE"))
297 function isaClass($) {
298 return ($.is("CONSTRUCTOR") || $.isNamespace || $.isClass);
310 var symbols = this.symbolSet.toArray();
312 var files = this.packer.files;
314 for (var i = 0, l = files.size; i < l; i++) {
315 var file = files.get(i);
316 var targetDir = PackerRun.opt_doc_target + "/symbols/src/";
317 this.makeSrcFile(file, targetDir);
319 //print(JSON.stringify(symbols,null,4));
320 var classes = new Gee.ArrayList<Symbol>();
322 foreach(var symbol in symbols) {
323 if (symbol.isaClass()) {
327 classes.sort( (a,b) => {
328 return a.alias.collate(b.alias);
331 //GLib.debug("classTemplate Process : all classes");
333 // var classesIndex = classesTemplate.process(classes); // kept in memory
335 GLib.debug("iterate classes");
337 var jsonAll = new JSON.Object();
339 for (var i = 0, l = classes.size; i < l; i++) {
340 var symbol = classes.get(i);
343 GLib.debug("classTemplate Process : %s" , symbol.alias);
348 FileUtils.set_contents(
349 PackerRun.opt_doc_target+"/symbols/" +symbol.alias+'.' + PackerRun.opt_doc_ext ,
350 classTemplate.process(symbol)
353 jsonAll.set_object_member(symbol.alias, this.publishJSON(symbol));
356 Json.Generator generator = new Json.Generator ();
357 generator.set_root (jsonAll.get_node());
358 generator.pretty= true;
360 generator.to_file(PackerRun.opt_doc_target+"/json/roodata.json");
364 // regenrate the index with different relative links
366 //var classesIndex = classesTemplate.process(classes);
368 GLib.debug("build index");
370 FileUtils.set_contents(
371 PackerRun.opt_doc_target + "/index." + PackerRun.opt_doc_ext ,
372 classesindexTemplate.process(classes)
375 // blank everything???? classesindexTemplate = classesIndex = classes = null;
379 var documentedFiles = symbols.filter(function ($) {
380 return ($.is("FILE"))
385 for (var i = 0; i < files.length; i++) {
386 allFiles.push(new Symbol(files[i], [], "FILE", new DocComment("/** *" + "/")));
389 for (var i = 0; i < documentedFiles.length; i++) {
390 var offset = files.indexOf(documentedFiles[i].alias);
391 allFiles[offset] = documentedFiles[i];
394 allFiles = allFiles.sort(makeSortby("name"));
395 GLib.debug("write files index");
397 FileUtils.set_contents(
398 PackerRun.opt_doc_target + "/files." + PackerRun.opt_doc_ext ,
399 fileindexTemplate.process(allFiles)
407 * JSON files are lookup files for the documentation
408 * - can be used by IDE's or AJAX based doc tools
412 JSON.Object publishJSON (Symbol data)
414 // what we need to output to be usefull...
416 var cfgProperties = new GLib.ArrayList<Symbol>();
417 if (!data.comment.getTag(DocTagTitle.SINGLETON).length) {
418 cfgProperties = data.configToArray();
419 cfgProperties = cfgProperties.sort((a,b) =>{
420 return a.alias.collate(b.alias);
425 var props = new JSON.Array();;
426 //println(cfgProperties.toSource());
428 for(var i =0; i < cfgProperties.size;i++) {
429 var p = cfgPropertiesget.get(i);
430 var add = new JSON.Object();
431 add.set_string_member("name",p.name);
432 add.set_string_member("type",p.type);
433 add.set_string_member("desc",p.desc);
434 add.set_string_member("memberOf", p.memberOf == data.alias ? '' : p.memberOf);
436 if (p.optvalues.size) {
437 add.set_array_member("desc",p.optvalues_as_json_array());
439 props.add_object(add );
443 var ownEvents = new Gee.ArrayList<Symbol>();
444 for(var i =0; i < data.methods.size;i++) {
445 var e = data.methods.get(i);
446 if (e.isEvent && e.comment.getTag(DocTagTitle.HIDE) == "") {
450 ownEvents.sort((a,b) => {
451 return a.name.collate(b.name);
454 var events = new JSON.Array();
456 for(var i =0; i < ownEvents.size;i++) {
457 var m = ownEvents.get(i);
458 var add = new JSON.Object();
459 add.set_string_member("name",m.name.substring(1,m.name.length-1));
460 add.set_string_member("type","function");
461 add.set_string_member("desc",m.desc);
462 add.set_string_member("sig", this.makeFuncSkel(m.params));
467 var ownMethods = new Gee.ArrayList<Symbol>();
468 for(var i =0; i < data.methods.size;i++) {
469 var e = data.methods.get(i);
470 if (!e.isEvent && e.comment.getTag(DocTagTitle.HIDE) == "") {
474 ownMethods.sort((a,b) => {
475 return a.name.collate(b.name);
478 var methods = new JSON.Array();
480 for(var i =0; i < ownMethods.size;i++) {
481 var m = ownMethods.get(i);
482 var add = new JSON.Object();
483 add.set_string_member("name",m.name.substring(1,m.name.length-1));
484 add.set_string_member("type","function");
485 add.set_string_member("desc",m.desc);
486 add.set_string_member("sig", this.makeMethodSkel(m.params));
490 //println(props.toSource());
491 // we need to output:
497 var ret = new JSON.Object();
498 ret.set_object_member("props", props);
499 ret.set_object_member("events", events);
500 ret.set_object_member("methods", methods);
512 string srcFileRelName(string sourceFile)
514 return sourceFile.substring(PackerRun.opt_real_basedir.length+1);
516 string srcFileFlatName(string sourceFile)
518 var name = this.srcFileRelName(sourceFile);
519 name = DocBuilder.regex_dotdot.replace(name, name.length, 0, "");
520 name = name.replace("/", "_").replace(":", "_") + ".html";
525 void makeSrcFile(string sourceFile)
527 // this stuff works...
530 var name = this.srcFileFlatName(sourceFile);
532 GLib.debug("Write Source file : %s/symbols/src/%s", opt_doc_target, name);
533 var pretty = PrettyPrint.toPretty(FileUtils.get_contenst(sourceFile));
534 File.write(PackerRun.opt_doc_target+"/symbols/src/" + name,
536 "<title>" + sourceFile + "</title>" +
537 "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../../css/highlight-js.css\"/>" +
538 "</head><body class=\"highlightpage\">" +
543 * used by JSON output to generate a function skeleton
546 string makeFuncSkel(Gee.ArrayList<Symbol> params) {
547 if (params.length < 0) {
548 return "function ()\n{\n\n}";
551 return "function (" +
554 return $.name.indexOf(".") == -1; // don't show config params in signature
556 ).map( function($) { return $.name == 'this' ? '_self' : $.name; } ).join(", ") +
559 makeMethodSkel :function(params) {
560 if (!params) return "()";
564 return $.name.indexOf(".") == -1; // don't show config params in signature
566 ).map( function($) { return $.type + " " +( $.name == 'this' ? '_self' : $.name ); } ).join(", ") +