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