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