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                 public int line_offset = 0;
193                 
194                 // file.project , file.path, file.build_module, ""
195                 public ValaSource(Project.Gtk project, string filepath, string build_module, string original_filepath) {
196                         base();
197                         //this.file = file;
198                         this.filepath = filepath;
199                         this.build_module = build_module;
200                         this.original_filepath = original_filepath;
201                         this.project =  project;
202                         
203                 }
204                 public void dumpCode(string str) 
205                 {
206                         var ls = str.split("\n");
207                         for (var i=0;i < ls.length; i++) {
208                                 print("%d : %s\n", i+1, ls[i]);
209                         }
210                 }
211                 
212                 //public Gee.HashMap<int,string> checkFile()
213                 //{
214                 //      return this.checkString(JsRender.NodeToVala.mungeFile(this.file));
215                 //}
216
217                 public void checkFileWithNodePropChange(
218                                         JsRender.JsRender file,
219                                         JsRender.Node node, 
220                                         string prop,
221                                         string ptype,
222                                         string val,
223                                         ValaSourceResult result_cb)
224                 {
225                         
226                         
227                         
228                         Gee.HashMap<int,string> ret = new Gee.HashMap<int,string> ();
229                         var hash = ptype == "listener" ? node.listeners : node.props;
230                         
231                         // untill we get a smarter renderer..
232                         // we have some scenarios where changing the value does not work
233                         if (prop == "* xns" || prop == "xtype") {
234                                 result_callback(new Json.Object());
235                                 return ;
236                         }
237                                 
238                         
239                         var old = hash.get(prop);
240                         var newval = "/*--VALACHECK-START--*/ " + val ;
241                         
242                         hash.set(prop, newval);
243                         var tmpstring = JsRender.NodeToVala.mungeFile(file);
244                         hash.set(prop, old);
245                         //print("%s\n", tmpstring);
246                         var bits = tmpstring.split("/*--VALACHECK-START--*/");
247                         var offset =0;
248                         if (bits.length > 0) {
249                                 offset = bits[0].split("\n").length +1;
250                         }
251                         
252                         this.line_offset = offset;
253                         
254                         //this.dumpCode(tmpstring);
255                         //print("offset %d\n", offset);
256                         this.result_callback = result_cb;
257                         this.checkStringSpawn(tmpstring );
258                         
259                         // modify report
260                         
261                         
262                         
263                 }
264                 Spawn compiler;
265                 ValaSourceResult result_callback;
266                 public void checkStringSpawn(
267                                         string contents 
268                                 )
269                 {
270                         
271                         FileIOStream iostream;
272                         var tmpfile = File.new_tmp ("test-XXXXXX.vala", out iostream);
273                         tmpfile.ref();
274
275                         OutputStream ostream = iostream.output_stream;
276                         DataOutputStream dostream = new DataOutputStream (ostream);
277                         dostream.put_string (contents);
278                         
279                         
280                         string[] args = {};
281                         args += FileUtils.read_link("/proc/self/exe");
282                         args += "--project";
283                         args += this.project.fn;
284                         args += "--target";
285                         args += this.build_module;
286                         args += "--add-file";
287                         args +=  tmpfile.get_path();
288                         args += "--skip-file";
289                         args += this.filepath;
290                         
291                          
292                         
293                         this.compiler = new Spawn("/tmp", args);
294                         
295                         try {
296                                 this.compiler.run(spawnResult); 
297                         } catch (Error e) {
298                                 var ret = new Json.Object();
299                                 ret.set_boolean_member("success", false);
300                                 ret.set_string_member("message", e.message);
301                                 this.result_callback(ret);
302                         }
303                          
304                 }
305                 public void spawnResult(int res, string output, string stderr)
306                 {
307                          
308                                 
309                         try { 
310                                 GLib.debug("GOT output %s", output);
311                                 
312                                 var pa = new Json.Parser();
313                                 pa.load_from_data(output);
314                                 var node = pa.get_root();
315
316                                 if (node.get_node_type () != Json.NodeType.OBJECT) {
317                                         throw new ValaSourceError.INVALID_FORMAT ("Unexpected element type %s", node.type_name ());
318                                 }
319                                 var ret = node.get_object ();
320                                 ret.set_int_member("line_offset", this.line_offset);
321                                 if (result_callback == null) {
322                                         print ("no callback?");
323                                         return;
324                                 }
325                                 this.result_callback(ret);
326                                 
327                                 
328                         } catch (Error e) {
329                                 var ret = new Json.Object();
330                                 ret.set_boolean_member("success", false);
331                                 ret.set_string_member("message", e.message);
332                                 this.result_callback(ret);
333                         }
334                         //compiler.unref();
335                         //tmpfile.unref();
336                          
337                         
338                         
339                 }
340                 
341                 public void compile( )
342                 {
343                         // init context:
344                         var valac = "valac " ;
345                         
346                         context = new Vala.CodeContext ();
347                         Vala.CodeContext.push (context);
348                 
349                         context.experimental = false;
350                         context.experimental_non_null = false;
351                         
352 #if VALA_0_28
353                         var ver=28;
354 #elif VALA_0_26 
355                         var ver=26;
356 #elif VALA_0_24
357                         var ver=24;
358 #elif VALA_0_22 
359                         var ver=22;
360 #endif
361                         
362                         for (int i = 2; i <= ver; i += 2) {
363                                 context.add_define ("VALA_0_%d".printf (i));
364                         }
365                         
366                         
367                         
368                          
369                         var vapidirs = this.project.vapidirs();
370                          
371                         for(var i =0 ; i < context.vapi_directories.length; i++) {
372                                 vapidirs += context.vapi_directories[i];
373                         }
374                         
375                         for(var i =0 ; i < vapidirs.length; i++) {
376                                 valac += " --vapidir=" + vapidirs[i];
377                         }
378                                 
379                         
380                         context.vapi_directories = vapidirs;
381                         context.report.enable_warnings = true;
382                         context.metadata_directories = { };
383                         context.gir_directories = {};
384                         context.thread = true;
385                          
386                         
387                         this.report = new ValaSourceReport(this.original_filepath, this.filepath);
388                         context.report = this.report;
389                         
390                         
391                         context.basedir = "/tmp"; //Posix.realpath (".");
392                 
393                         context.directory = context.basedir;
394                 
395
396                         // add default packages:
397                         //if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) {
398                         context.profile = Vala.Profile.GOBJECT;
399                          
400                         var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null));
401                         context.root.add_using_directive (ns_ref);
402
403                         var source_file = new Vala.SourceFile (
404                                 context, 
405                                 Vala.SourceFileType.SOURCE, 
406                                         this.filepath 
407                         );
408                         source_file.add_using_directive (ns_ref);
409                         context.add_source_file (source_file);
410                         
411                 // add all the files (except the current one) - this.file.path
412                 var pr = this.project;
413                 if (this.build_module.length > 0) {
414                                 var cg =  pr.compilegroups.get(this.build_module);
415                                 for (var i = 0; i < cg.sources.size; i++) {
416                                         var path = pr.resolve_path(
417                                                         pr.resolve_path_combine_path(pr.firstPath(),cg.sources.get(i)));
418                                                         
419                                         if (!FileUtils.test(path, FileTest.EXISTS)) {
420                                                 continue;
421                                         }       
422                         // skip thie original
423                                         if (path == this.original_filepath.replace(".bjs", ".vala")) {
424                                                 valac += " " + path;
425                                                 continue;
426                                         }
427                                         if (FileUtils.test(path, FileTest.IS_DIR)) {
428                                                 continue;
429                                         }
430                                         //print("Add source file %s\n", path);
431                                         
432                                         valac += " " + path;
433                                         
434                                         if (Regex.match_simple("\\.c$", path)) {
435                                                 context.add_c_source_file(path);
436                                                 continue;
437                                         }
438                                         
439                                         
440                                         var xsf = new Vala.SourceFile (
441                                                 context,
442                                                 Vala.SourceFileType.SOURCE, 
443                                                 path
444                                         );
445                                         xsf.add_using_directive (ns_ref);
446                                         context.add_source_file(xsf);
447                                         
448                                 }
449                         }
450                         // default.. packages..
451                         context.add_external_package ("glib-2.0"); 
452                         context.add_external_package ("gobject-2.0");
453                         // user defined ones..
454                         
455                 var dcg = pr.compilegroups.get("_default_");
456                 for (var i = 0; i < dcg.packages.size; i++) {
457                                 valac += " --pkg " + dcg.packages.get(i);
458                                 if (!this.has_vapi(context.vapi_directories, dcg.packages.get(i))) {
459                                         GLib.debug("Skip vapi '%s' - does not exist", dcg.packages.get(i));
460                                         continue;
461                                 }
462                                 
463                                 context.add_external_package (dcg.packages.get(i));
464                         }
465                 
466                          //Vala.Config.PACKAGE_SUFFIX.substring (1)
467                         
468                         // add the modules...
469                         
470                         context.output = "/tmp/testbuild";
471                         valac += " -o " +context.output;
472                         GLib.debug("%s", valac);
473                         
474                         //context.add_external_package ("libvala-0.24");
475                         
476  
477                 
478                         //add_documented_files (context, settings.source_files);
479                 
480                         Vala.Parser parser = new Vala.Parser ();
481                         parser.parse (context);
482                         //gir_parser.parse (context);
483                         if (context.report.get_errors () > 0) {
484                                 Vala.CodeContext.pop ();
485                                 GLib.debug("parse got errors");
486                                 //((ValaSourceReport)context.report).dump();
487                                 this.report.result.set_boolean_member("success", false);
488                                 this.report.result.set_string_member("message", "Parse failed");
489                                 
490                                 this.outputResult();
491                                 return;
492                         }
493
494
495                         
496                         // check context:
497                         context.check ();
498                         if (context.report.get_errors () > 0) {
499                                 Vala.CodeContext.pop ();
500                                 GLib.debug("check got errors");
501                                 //((ValaSourceReport)context.report).dump();
502                                 this.report.result.set_boolean_member("success", false);
503                                 this.report.result.set_string_member("message", "Check failed");
504                                 
505                                 this.outputResult();
506                                 return;
507                         }
508                         
509                         //context.codegen = new Vala.GDBusServerModule ();
510                         
511                          
512                         
513                         //context.codegen.emit (context);
514                         /*
515                         var ccompiler = new Vala.CCodeCompiler ();
516                         var cc_command = Environment.get_variable ("CC");
517                         var pkg_config_command = Environment.get_variable ("PKG_CONFIG");
518 #if VALA_0_28
519                         ccompiler.compile (context, cc_command, new string[] { }, pkg_config_command);
520 #else
521                         ccompiler.compile (context, cc_command, new string[] { });
522 #endif
523                         */
524  
525                         Vala.CodeContext.pop ();
526                         this.outputResult();
527                 
528                 }
529                 public void has_vapi(string[] dirs,  string vapi) {
530                         
531                         
532                 }
533                 
534                 public void outputResult()
535                 {
536                         var generator = new Json.Generator ();
537                     generator.indent = 1;
538                     generator.pretty = true;
539                     var node = new Json.Node(Json.NodeType.OBJECT);
540                     node.set_object(this.report.result);
541                     
542                     generator.set_root(node);
543                          
544                         generator.pretty = true;
545                         generator.indent = 4;
546                  
547
548                         print("%s\n",  generator.to_data (null));
549                         GLib.Process.exit(Posix.EXIT_SUCCESS);
550                         
551                          
552                 }
553 /*              
554                 
555                 
556                 public Gee.HashMap<int,string> checkString(string contents)
557                 {
558                         // init context:
559                         var valac = "valac " ;
560                         
561                         context = new Vala.CodeContext ();
562                         Vala.CodeContext.push (context);
563                 
564                         context.experimental = false;
565                         context.experimental_non_null = false;
566                         
567 #if VALA_0_28
568                         var ver=28;
569 #elif VALA_0_26 
570                         var ver=26;
571 #elif VALA_0_24
572                         var ver=24;
573 #elif VALA_0_22 
574                         var ver=22;
575 #endif
576                         
577                         for (int i = 2; i <= ver; i += 2) {
578                                 context.add_define ("VALA_0_%d".printf (i));
579                         }
580                         
581                         
582                         
583                         
584                         
585                         
586                         
587                         var vapidirs = ((Project.Gtk)this.file.project).vapidirs();
588                         // what's the current version of vala???
589                         
590                         
591                         vapidirs +=  Path.get_dirname (context.get_vapi_path("glib-2.0")) ;
592                         
593                         for(var i =0 ; i < vapidirs.length; i++) {
594                                 valac += " --vapidir=" + vapidirs[i];
595                         }
596                                 
597                         
598                         // or context.get_vapi_path("glib-2.0"); // should return path..
599                         context.vapi_directories = vapidirs;
600                         context.report.enable_warnings = true;
601                         context.metadata_directories = { };
602                         context.gir_directories = {};
603                         context.thread = true;
604                         
605                         
606                         this.report = new ValaSourceReport(this.file.path);
607                         context.report = this.report;
608                         
609                         
610                         context.basedir = "/tmp"; //Posix.realpath (".");
611                 
612                         context.directory = context.basedir;
613                 
614
615                         // add default packages:
616                         //if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) {
617                         context.profile = Vala.Profile.GOBJECT;
618                          
619                         var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null));
620                         context.root.add_using_directive (ns_ref);
621
622                         var source_file = new Vala.SourceFile (
623                                 context, 
624                                 Vala.SourceFileType.SOURCE, 
625                                         "~~~~~testfile.vala",
626                                         contents
627                         );
628                         source_file.add_using_directive (ns_ref);
629                         context.add_source_file (source_file);
630                         
631                 // add all the files (except the current one) - this.file.path
632                 var pr = ((Project.Gtk)this.file.project);
633                 if (this.file.build_module.length > 0) {
634                                 var cg =  pr.compilegroups.get(this.file.build_module);
635                                 for (var i = 0; i < cg.sources.size; i++) {
636                                         var path = pr.resolve_path(
637                                                         pr.resolve_path_combine_path(pr.firstPath(),cg.sources.get(i)));
638                                                         
639                                         if (!FileUtils.test(path, FileTest.EXISTS)) {
640                                                 continue;
641                                         }       
642                          
643                                         if (path == this.file.path.replace(".bjs", ".vala")) {
644                                                 valac += " " + path;
645                                                 continue;
646                                         }
647                                         if (FileUtils.test(path, FileTest.IS_DIR)) {
648                                                 continue;
649                                         }
650                                         //print("Add source file %s\n", path);
651                                         
652                                         valac += " " + path;
653                                         
654                                         if (Regex.match_simple("\\.c$", path)) {
655                                                 context.add_c_source_file(path);
656                                                 continue;
657                                         }
658                                         
659                                         
660                                         var xsf = new Vala.SourceFile (
661                                                 context,
662                                                 Vala.SourceFileType.SOURCE, 
663                                                 path
664                                         );
665                                         xsf.add_using_directive (ns_ref);
666                                         context.add_source_file(xsf);
667                                         
668                                 }
669                         }
670                         // default.. packages..
671                         context.add_external_package ("glib-2.0"); 
672                         context.add_external_package ("gobject-2.0");
673                         // user defined ones..
674                         
675                 var dcg = pr.compilegroups.get("_default_");
676                 for (var i = 0; i < dcg.packages.size; i++) {
677                                 valac += " --pkg " + dcg.packages.get(i);
678                                 context.add_external_package (dcg.packages.get(i));
679                         }
680                 
681                          //Vala.Config.PACKAGE_SUFFIX.substring (1)
682                         
683                         // add the modules...
684                         
685                         
686                         
687                         //context.add_external_package ("libvala-0.24");
688                         
689                         this.report.compile_notice("START", "", 0, "");
690
691                 
692                         //add_documented_files (context, settings.source_files);
693                 
694                         Vala.Parser parser = new Vala.Parser ();
695                         parser.parse (context);
696                         //gir_parser.parse (context);
697                         if (context.report.get_errors () > 0) {
698                                 print("parse got errors");
699                                 ((ValaSourceReport)context.report).dump();
700                                 
701                                 Vala.CodeContext.pop ();
702                                 this.report.compile_notice("END", "", 0, "");
703                                 return this.report.line_errors;
704                         }
705
706
707                         
708                         // check context:
709                         context.check ();
710                         if (context.report.get_errors () > 0) {
711                                 print("check got errors");
712                                 ((ValaSourceReport)context.report).dump();
713                                 Vala.CodeContext.pop ();
714                                 this.report.compile_notice("END", "", 0, "");
715                                 return this.report.line_errors;
716                                 
717                         }
718                         
719                         //context.codegen = new Vala.GDBusServerModule ();
720                         
721                          
722                         context.output = "/tmp/testbuild";
723                         valac += " -o " +context.output;
724                         //context.codegen.emit (context);
725                          odeContext.pop ();
726                         //(new Vala.CodeNode()).get_error_types().clear();
727                         //(new Vala.NullType()).get_type_arguments().clear();
728                         (new Vala.NullType(null)).get_type_arguments().clear();
729                         parser = null;
730                         this.report.compile_notice("END", "", 0, "");
731                         print("%s\n", valac);
732                         print("ALL OK?\n");
733                         return this.report.line_errors;
734                 }
735         //
736                 // startpoint:
737                 //
738          */
739         }
740 }
741 /*
742 int main (string[] args) {
743
744         var a = new ValaSource(file);
745         a.create_valac_tree();
746         return 0;
747 }
748 */
749
750