src/Palete/ValaSource.vala
[app.Builder.js] / src / Palete / ValaSource.vala
1
2 // valac TreeBuilder.vala --pkg libvala-0.24 --pkg posix -o /tmp/treebuilder
3
4 namespace Palete {
5         
6         public errordomain ValaSourceError {
7                 INVALID_FORMAT 
8         }
9         
10         public delegate  void ValaSourceResult(Json.Object res);
11         
12         public class ValaSourceReport  : Vala.Report {
13
14                 public string filepath;
15                 
16                 public string tmpname;
17                 
18                 //public Gee.ArrayList<ValaSourceNotice> notices;
19                 public Json.Object result;
20                  
21                 //public Gee.HashMap<int,string> line_errors;
22                 
23                 public void  compile_notice(string type, string filename, int line, string message) {
24                          
25                          if (!this.result.has_member(type+"-TOTAL")) {
26                                  this.result.set_int_member(type+"-TOTAL", 1);
27                          } else {
28                                 this.result.set_int_member(type+"-TOTAL", 
29                                         this.result.get_int_member(type+"-TOTAL") +1 
30                                 );
31                          }
32                          
33                          
34                          if (!this.result.has_member(type)) {
35                                  this.result.set_object_member(type, new Json.Object());
36                          }
37                          var t = this.result.get_object_member(type);
38                          if (!t.has_member(filename)) {
39                                  t.set_object_member(filename, new Json.Object());
40                          }
41                          var tt = t.get_object_member(filename);
42                          if (!tt.has_member(line.to_string())) {
43                                  tt.set_array_member(line.to_string(), new Json.Array());
44                          }
45                          var tl = tt.get_array_member(line.to_string());
46                          tl.add_string_element(message);
47                          
48                 }
49                 
50                 
51          
52                 public ValaSourceReport(string filepath, string tmpname)
53                 {
54                         base();
55                         this.filepath = filepath;
56                         this.tmpname = tmpname;
57                         this.result = new Json.Object();
58                         this.result.set_boolean_member("success", true);
59                         this.result.set_string_member("message", "");
60                         
61                         
62                         
63                         //this.line_errors = new Gee.HashMap<int,string> ();
64                         //this.notices = new Gee.ArrayList<ValaSourceNotice>();
65                 }
66                 
67                 public override void warn (Vala.SourceReference? source, string message) {
68                          
69                         if (source == null) {
70                                 return;
71                                 //stderr.printf ("My error: %s\n", message);
72                         }
73                         
74                         if (source.file.filename != this.tmpname) {
75                                 this.compile_notice("WARN", source.file.filename , source.begin.line, message);
76                                 return;
77                         }
78                         this.compile_notice("WARN", this.filepath, source.begin.line, message);
79                         
80                 }
81                 public override void depr (Vala.SourceReference? source, string message) {
82                          
83                         if (source == null) {
84                                 return;
85                                 //stderr.printf ("My error: %s\n", message);
86                         }
87                         
88                         if (source.file.filename != this.tmpname) {
89                                 this.compile_notice("DEPR", source.file.filename, source.begin.line, message);
90                                 return;
91                         }
92                         this.compile_notice("DEPR",  this.filepath, source.begin.line, message);
93                         
94                 }
95                 
96                 public override void err (Vala.SourceReference? source, string message) {
97                         errors++;
98                         if (source == null) {
99                                 return;
100                                 //stderr.printf ("My error: %s\n", message);
101                         }
102                         if (source.file.filename != this.tmpname) {
103                                 this.compile_notice("ERR", source.file.filename, source.begin.line, message);
104                                 GLib.debug ("Other file: Got error error: %d:  %s\n", source.begin.line, message);
105                                 return;
106                         }
107                          
108                          
109                         this.compile_notice("ERR", this.filepath, source.begin.line, message);
110                         GLib.debug ("Test file: Got error error: %d: %s\n", source.begin.line, message);
111                 }
112                 /*
113                 public void dump()
114                 {
115                         var iter = this.line_errors.map_iterator();
116                         while (iter.next()) {
117                                 print ("%d : %s\n\n", iter.get_key(), iter.get_value());
118                         }
119                 }
120                 */
121
122         }
123
124         public class ValaSource : Object {
125
126                 public static void jerr(string str)
127                 {
128                         var ret = new Json.Object(); 
129                         ret.set_boolean_member("success", false);
130                         ret.set_string_member("message", str);
131                         
132                         var  generator = new Json.Generator ();
133                         var  root = new Json.Node(Json.NodeType.OBJECT);
134                         root.init_object(ret);
135                         generator.set_root (root);
136                          
137                         generator.pretty = true;
138                         generator.indent = 4;
139                  
140
141                         print("%s\n",  generator.to_data (null));
142                         GLib.Process.exit(Posix.EXIT_FAILURE);
143                         
144                 }
145
146                 public static void buildApplication()
147                 {
148                         //print("build based on Application settings\n");
149                         
150                         if (BuilderApplication.opt_compile_target == null) {
151                                 jerr("missing compile target --target");
152                         }
153                         
154                         Project.Project.loadAll();
155                         var proj = Project.Project.getProjectByHash(BuilderApplication.opt_compile_project);
156                         
157                         if (proj == null) {
158                                 jerr("could not load test project %s".printf( BuilderApplication.opt_compile_project));
159                         }
160                         
161                         if (proj.xtype != "Gtk") {
162                                 jerr("%s is not a Gtk Project".printf( BuilderApplication.opt_compile_project));
163                         }
164                         var gproj = (Project.Gtk)proj;
165                         
166                         
167                         if (!gproj.compilegroups.has_key(BuilderApplication.opt_compile_target)) {
168                                 jerr("missing compile target %s".printf(BuilderApplication.opt_compile_target));
169                         }
170                         var skip_file = "";
171                         if (BuilderApplication.opt_compile_skip != null) {
172                                 skip_file = BuilderApplication.opt_compile_skip;
173                         }
174                         var add_file = "";
175                         if (BuilderApplication.opt_compile_add != null) {
176                                 add_file = BuilderApplication.opt_compile_add;
177                         }
178                         
179                         
180                         var vs = new ValaSource(gproj,  add_file, BuilderApplication.opt_compile_target,   skip_file);
181                         vs.compile();
182                         
183                         
184                 }
185
186                 Vala.CodeContext context;
187                 ValaSourceReport report;
188                 Project.Gtk project;
189                 public string build_module;
190                 public string filepath;
191                 public string original_filepath;
192                 
193                 // file.project , file.path, file.build_module, ""
194                 public ValaSource(Project.Gtk project, string filepath, string build_module, string original_filepath) {
195                         base();
196                         //this.file = file;
197                         this.filepath = filepath;
198                         this.build_module = build_module;
199                         this.original_filepath = original_filepath;
200                         this.project =  project;
201                         
202                 }
203                 public void dumpCode(string str) 
204                 {
205                         var ls = str.split("\n");
206                         for (var i=0;i < ls.length; i++) {
207                                 print("%d : %s\n", i+1, ls[i]);
208                         }
209                 }
210                 
211                 //public Gee.HashMap<int,string> checkFile()
212                 //{
213                 //      return this.checkString(JsRender.NodeToVala.mungeFile(this.file));
214                 //}
215
216                 public void checkFileWithNodePropChange(
217                                         JsRender.JsRender file,
218                                         JsRender.Node node, 
219                                         string prop,
220                                         string ptype,
221                                         string val,
222                                         ValaSourceResult result_callback)
223                 {
224                         
225                         
226                         
227                         Gee.HashMap<int,string> ret = new Gee.HashMap<int,string> ();
228                         var hash = ptype == "listener" ? node.listeners : node.props;
229                         
230                         // untill we get a smarter renderer..
231                         // we have some scenarios where changing the value does not work
232                         if (prop == "* xns" || prop == "xtype") {
233                                 result_callback(new Json.Object());
234                                 return ;
235                         }
236                                 
237                         
238                         var old = hash.get(prop);
239                         var newval = "/*--VALACHECK-START--*/ " + val ;
240                         
241                         hash.set(prop, newval);
242                         var tmpstring = JsRender.NodeToVala.mungeFile(file);
243                         hash.set(prop, old);
244                         //print("%s\n", tmpstring);
245                         var bits = tmpstring.split("/*--VALACHECK-START--*/");
246                         var offset =0;
247                         if (bits.length > 0) {
248                                 offset = bits[0].split("\n").length +1;
249                         }
250                         //this.dumpCode(tmpstring);
251                         //print("offset %d\n", offset);
252                         this.checkStringSpawn(tmpstring,  (owned) result_callback );
253                         
254                         // modify report
255                         
256                         
257                         
258                 }
259                 Spawn compiler;
260                 ValaSourceResult result_callback;
261                 public void checkStringSpawn(
262                                         string contents,
263                                         ValaSourceResult result_cb
264                                 )
265                 {
266                         this.result_callback = result_cb;
267                         
268                         FileIOStream iostream;
269                         var tmpfile = File.new_tmp ("test-XXXXXX.vala", out iostream);
270                         tmpfile.ref();
271
272                         OutputStream ostream = iostream.output_stream;
273                         DataOutputStream dostream = new DataOutputStream (ostream);
274                         dostream.put_string (contents);
275                         
276                         
277                         string[] args = {};
278                         args += FileUtils.read_link("/proc/self/exe");
279                         args += "--project";
280                         args += this.project.fn;
281                         args += "--target";
282                         args += this.build_module;
283                         args += "--add-file";
284                         args +=  tmpfile.get_path();
285                         args += "--skip-file";
286                         args += this.filepath;
287                         
288                          
289                         
290                         this.compiler = new Spawn("/tmp", args);
291                         
292                         this.compiler.run(spawnResult); 
293                         
294                          
295                 }
296                 public void spawnResult(int res, string output, string stderr)
297                 {
298                          
299                                 
300                         try { 
301                                 GLib.debug("GOT output %s", output);
302                                 
303                                 var pa = new Json.Parser();
304                                 pa.load_from_data(output);
305                                 var node = pa.get_root();
306
307                                 if (node.get_node_type () != Json.NodeType.OBJECT) {
308                                         throw new ValaSourceError.INVALID_FORMAT ("Unexpected element type %s", node.type_name ());
309                                 }
310                                 var ret = node.get_object ();
311                                 if (result_callback == null) {
312                                         print ("no callback?");
313                                         return;
314                                 }
315                                 this.result_callback(ret);
316                                 
317                                 
318                         } catch (Error e) {
319                                 var ret = new Json.Object();
320                                 ret.set_boolean_member("success", false);
321                                 ret.set_string_member("message", e.message);
322                                 this.result_callback(ret);
323                         }
324                         //compiler.unref();
325                         //tmpfile.unref();
326                          
327                         
328                         
329                 }
330                 
331                 public void compile( )
332                 {
333                         // init context:
334                         var valac = "valac " ;
335                         
336                         context = new Vala.CodeContext ();
337                         Vala.CodeContext.push (context);
338                 
339                         context.experimental = false;
340                         context.experimental_non_null = false;
341                         
342 #if VALA_0_28
343                         var ver=28;
344 #elif VALA_0_26 
345                         var ver=26;
346 #elif VALA_0_24
347                         var ver=24;
348 #elif VALA_0_22 
349                         var ver=22;
350 #endif
351                         
352                         for (int i = 2; i <= ver; i += 2) {
353                                 context.add_define ("VALA_0_%d".printf (i));
354                         }
355                         
356                         
357                         
358                         
359                         
360                         
361                         
362                         var vapidirs = this.project.vapidirs();
363                         // what's the current version of vala???
364                         
365                         
366                         vapidirs +=  Path.get_dirname (context.get_vapi_path("glib-2.0")) ;
367                         
368                         for(var i =0 ; i < vapidirs.length; i++) {
369                                 valac += " --vapidir=" + vapidirs[i];
370                         }
371                                 
372                         
373                         // or context.get_vapi_path("glib-2.0"); // should return path..
374                         context.vapi_directories = vapidirs;
375                         context.report.enable_warnings = true;
376                         context.metadata_directories = { };
377                         context.gir_directories = {};
378                         context.thread = true;
379                          
380                         
381                         this.report = new ValaSourceReport(this.original_filepath, this.filepath);
382                         context.report = this.report;
383                         
384                         
385                         context.basedir = "/tmp"; //Posix.realpath (".");
386                 
387                         context.directory = context.basedir;
388                 
389
390                         // add default packages:
391                         //if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) {
392                         context.profile = Vala.Profile.GOBJECT;
393                          
394                         var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null));
395                         context.root.add_using_directive (ns_ref);
396
397                         var source_file = new Vala.SourceFile (
398                                 context, 
399                                 Vala.SourceFileType.SOURCE, 
400                                         this.filepath 
401                         );
402                         source_file.add_using_directive (ns_ref);
403                         context.add_source_file (source_file);
404                         
405                 // add all the files (except the current one) - this.file.path
406                 var pr = this.project;
407                 if (this.build_module.length > 0) {
408                                 var cg =  pr.compilegroups.get(this.build_module);
409                                 for (var i = 0; i < cg.sources.size; i++) {
410                                         var path = pr.resolve_path(
411                                                         pr.resolve_path_combine_path(pr.firstPath(),cg.sources.get(i)));
412                                                         
413                                         if (!FileUtils.test(path, FileTest.EXISTS)) {
414                                                 continue;
415                                         }       
416                         // skip thie original
417                                         if (path == this.original_filepath.replace(".bjs", ".vala")) {
418                                                 valac += " " + path;
419                                                 continue;
420                                         }
421                                         if (FileUtils.test(path, FileTest.IS_DIR)) {
422                                                 continue;
423                                         }
424                                         //print("Add source file %s\n", path);
425                                         
426                                         valac += " " + path;
427                                         
428                                         if (Regex.match_simple("\\.c$", path)) {
429                                                 context.add_c_source_file(path);
430                                                 continue;
431                                         }
432                                         
433                                         
434                                         var xsf = new Vala.SourceFile (
435                                                 context,
436                                                 Vala.SourceFileType.SOURCE, 
437                                                 path
438                                         );
439                                         xsf.add_using_directive (ns_ref);
440                                         context.add_source_file(xsf);
441                                         
442                                 }
443                         }
444                         // default.. packages..
445                         context.add_external_package ("glib-2.0"); 
446                         context.add_external_package ("gobject-2.0");
447                         // user defined ones..
448                         
449                 var dcg = pr.compilegroups.get("_default_");
450                 for (var i = 0; i < dcg.packages.size; i++) {
451                                 valac += " --pkg " + dcg.packages.get(i);
452                                 context.add_external_package (dcg.packages.get(i));
453                         }
454                 
455                          //Vala.Config.PACKAGE_SUFFIX.substring (1)
456                         
457                         // add the modules...
458                         
459                         
460                         
461                         //context.add_external_package ("libvala-0.24");
462                         
463  
464                 
465                         //add_documented_files (context, settings.source_files);
466                 
467                         Vala.Parser parser = new Vala.Parser ();
468                         parser.parse (context);
469                         //gir_parser.parse (context);
470                         if (context.report.get_errors () > 0) {
471                                 Vala.CodeContext.pop ();
472                                 GLib.debug("parse got errors");
473                                 //((ValaSourceReport)context.report).dump();
474                                 this.report.result.set_boolean_member("success", false);
475                                 this.report.result.set_string_member("message", "Parse failed");
476                                 
477                                 this.outputResult();
478                                 return;
479                         }
480
481
482                         
483                         // check context:
484                         context.check ();
485                         if (context.report.get_errors () > 0) {
486                                 Vala.CodeContext.pop ();
487                                 GLib.debug("check got errors");
488                                 //((ValaSourceReport)context.report).dump();
489                                 this.report.result.set_boolean_member("success", false);
490                                 this.report.result.set_string_member("message", "Check failed");
491                                 
492                                 this.outputResult();
493                                 return;
494                         }
495                         
496                         //context.codegen = new Vala.GDBusServerModule ();
497                         
498                          
499                         context.output = "/tmp/testbuild";
500                         valac += " -o " +context.output;
501                         //context.codegen.emit (context);
502                         /*
503                         var ccompiler = new Vala.CCodeCompiler ();
504                         var cc_command = Environment.get_variable ("CC");
505                         var pkg_config_command = Environment.get_variable ("PKG_CONFIG");
506 #if VALA_0_28
507                         ccompiler.compile (context, cc_command, new string[] { }, pkg_config_command);
508 #else
509                         ccompiler.compile (context, cc_command, new string[] { });
510 #endif
511                         */
512  
513                         Vala.CodeContext.pop ();
514                         this.outputResult();
515                 
516                 }
517                 public void outputResult()
518                 {
519                         var generator = new Json.Generator ();
520                     generator.indent = 1;
521                     generator.pretty = true;
522                     var node = new Json.Node(Json.NodeType.OBJECT);
523                     node.set_object(this.report.result);
524                     
525                     generator.set_root(node);
526                          
527                         generator.pretty = true;
528                         generator.indent = 4;
529                  
530
531                         print("%s\n",  generator.to_data (null));
532                         GLib.Process.exit(Posix.EXIT_SUCCESS);
533                         
534                          
535                 }
536 /*              
537                 
538                 
539                 public Gee.HashMap<int,string> checkString(string contents)
540                 {
541                         // init context:
542                         var valac = "valac " ;
543                         
544                         context = new Vala.CodeContext ();
545                         Vala.CodeContext.push (context);
546                 
547                         context.experimental = false;
548                         context.experimental_non_null = false;
549                         
550 #if VALA_0_28
551                         var ver=28;
552 #elif VALA_0_26 
553                         var ver=26;
554 #elif VALA_0_24
555                         var ver=24;
556 #elif VALA_0_22 
557                         var ver=22;
558 #endif
559                         
560                         for (int i = 2; i <= ver; i += 2) {
561                                 context.add_define ("VALA_0_%d".printf (i));
562                         }
563                         
564                         
565                         
566                         
567                         
568                         
569                         
570                         var vapidirs = ((Project.Gtk)this.file.project).vapidirs();
571                         // what's the current version of vala???
572                         
573                         
574                         vapidirs +=  Path.get_dirname (context.get_vapi_path("glib-2.0")) ;
575                         
576                         for(var i =0 ; i < vapidirs.length; i++) {
577                                 valac += " --vapidir=" + vapidirs[i];
578                         }
579                                 
580                         
581                         // or context.get_vapi_path("glib-2.0"); // should return path..
582                         context.vapi_directories = vapidirs;
583                         context.report.enable_warnings = true;
584                         context.metadata_directories = { };
585                         context.gir_directories = {};
586                         context.thread = true;
587                         
588                         
589                         this.report = new ValaSourceReport(this.file.path);
590                         context.report = this.report;
591                         
592                         
593                         context.basedir = "/tmp"; //Posix.realpath (".");
594                 
595                         context.directory = context.basedir;
596                 
597
598                         // add default packages:
599                         //if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) {
600                         context.profile = Vala.Profile.GOBJECT;
601                          
602                         var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null));
603                         context.root.add_using_directive (ns_ref);
604
605                         var source_file = new Vala.SourceFile (
606                                 context, 
607                                 Vala.SourceFileType.SOURCE, 
608                                         "~~~~~testfile.vala",
609                                         contents
610                         );
611                         source_file.add_using_directive (ns_ref);
612                         context.add_source_file (source_file);
613                         
614                 // add all the files (except the current one) - this.file.path
615                 var pr = ((Project.Gtk)this.file.project);
616                 if (this.file.build_module.length > 0) {
617                                 var cg =  pr.compilegroups.get(this.file.build_module);
618                                 for (var i = 0; i < cg.sources.size; i++) {
619                                         var path = pr.resolve_path(
620                                                         pr.resolve_path_combine_path(pr.firstPath(),cg.sources.get(i)));
621                                                         
622                                         if (!FileUtils.test(path, FileTest.EXISTS)) {
623                                                 continue;
624                                         }       
625                          
626                                         if (path == this.file.path.replace(".bjs", ".vala")) {
627                                                 valac += " " + path;
628                                                 continue;
629                                         }
630                                         if (FileUtils.test(path, FileTest.IS_DIR)) {
631                                                 continue;
632                                         }
633                                         //print("Add source file %s\n", path);
634                                         
635                                         valac += " " + path;
636                                         
637                                         if (Regex.match_simple("\\.c$", path)) {
638                                                 context.add_c_source_file(path);
639                                                 continue;
640                                         }
641                                         
642                                         
643                                         var xsf = new Vala.SourceFile (
644                                                 context,
645                                                 Vala.SourceFileType.SOURCE, 
646                                                 path
647                                         );
648                                         xsf.add_using_directive (ns_ref);
649                                         context.add_source_file(xsf);
650                                         
651                                 }
652                         }
653                         // default.. packages..
654                         context.add_external_package ("glib-2.0"); 
655                         context.add_external_package ("gobject-2.0");
656                         // user defined ones..
657                         
658                 var dcg = pr.compilegroups.get("_default_");
659                 for (var i = 0; i < dcg.packages.size; i++) {
660                                 valac += " --pkg " + dcg.packages.get(i);
661                                 context.add_external_package (dcg.packages.get(i));
662                         }
663                 
664                          //Vala.Config.PACKAGE_SUFFIX.substring (1)
665                         
666                         // add the modules...
667                         
668                         
669                         
670                         //context.add_external_package ("libvala-0.24");
671                         
672                         this.report.compile_notice("START", "", 0, "");
673
674                 
675                         //add_documented_files (context, settings.source_files);
676                 
677                         Vala.Parser parser = new Vala.Parser ();
678                         parser.parse (context);
679                         //gir_parser.parse (context);
680                         if (context.report.get_errors () > 0) {
681                                 print("parse got errors");
682                                 ((ValaSourceReport)context.report).dump();
683                                 
684                                 Vala.CodeContext.pop ();
685                                 this.report.compile_notice("END", "", 0, "");
686                                 return this.report.line_errors;
687                         }
688
689
690                         
691                         // check context:
692                         context.check ();
693                         if (context.report.get_errors () > 0) {
694                                 print("check got errors");
695                                 ((ValaSourceReport)context.report).dump();
696                                 Vala.CodeContext.pop ();
697                                 this.report.compile_notice("END", "", 0, "");
698                                 return this.report.line_errors;
699                                 
700                         }
701                         
702                         //context.codegen = new Vala.GDBusServerModule ();
703                         
704                          
705                         context.output = "/tmp/testbuild";
706                         valac += " -o " +context.output;
707                         //context.codegen.emit (context);
708                          odeContext.pop ();
709                         //(new Vala.CodeNode()).get_error_types().clear();
710                         //(new Vala.NullType()).get_type_arguments().clear();
711                         (new Vala.NullType(null)).get_type_arguments().clear();
712                         parser = null;
713                         this.report.compile_notice("END", "", 0, "");
714                         print("%s\n", valac);
715                         print("ALL OK?\n");
716                         return this.report.line_errors;
717                 }
718         //
719                 // startpoint:
720                 //
721          */
722         }
723 }
724 /*
725 int main (string[] args) {
726
727         var a = new ValaSource(file);
728         a.create_valac_tree();
729         return 0;
730 }
731 */
732
733