2 // valac TreeBuilder.vala --pkg libvala-0.24 --pkg posix -o /tmp/treebuilder
6 public errordomain ValaSourceError {
10 public delegate void ValaSourceResult(Json.Object res);
12 public class ValaSourceReport : Vala.Report {
14 public string filepath;
16 public string tmpname;
18 //public Gee.ArrayList<ValaSourceNotice> notices;
19 public Json.Object result;
21 //public Gee.HashMap<int,string> line_errors;
23 public void compile_notice(string type, string filename, int line, string message) {
25 if (!this.result.has_member(type+"-TOTAL")) {
26 this.result.set_int_member(type+"-TOTAL", 1);
28 this.result.set_int_member(type+"-TOTAL",
29 this.result.get_int_member(type+"-TOTAL") +1
34 if (!this.result.has_member(type)) {
35 this.result.set_object_member(type, new Json.Object());
37 var t = this.result.get_object_member(type);
38 if (!t.has_member(filename)) {
39 t.set_object_member(filename, new Json.Object());
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());
45 var tl = tt.get_array_member(line.to_string());
46 tl.add_string_element(message);
52 public ValaSourceReport(string filepath, string tmpname)
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", "");
63 //this.line_errors = new Gee.HashMap<int,string> ();
64 //this.notices = new Gee.ArrayList<ValaSourceNotice>();
67 public override void warn (Vala.SourceReference? source, string message) {
71 //stderr.printf ("My error: %s\n", message);
74 if (source.file.filename != this.tmpname) {
75 this.compile_notice("WARN", source.file.filename , source.begin.line, message);
78 this.compile_notice("WARN", this.filepath, source.begin.line, message);
81 public override void depr (Vala.SourceReference? source, string message) {
85 //stderr.printf ("My error: %s\n", message);
88 if (source.file.filename != this.tmpname) {
89 this.compile_notice("DEPR", source.file.filename, source.begin.line, message);
92 this.compile_notice("DEPR", this.filepath, source.begin.line, message);
96 public override void err (Vala.SourceReference? source, string message) {
100 //stderr.printf ("My error: %s\n", message);
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);
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);
115 var iter = this.line_errors.map_iterator();
116 while (iter.next()) {
117 print ("%d : %s\n\n", iter.get_key(), iter.get_value());
124 public class ValaSource : Object {
126 public static void jerr(string str)
128 var ret = new Json.Object();
129 ret.set_boolean_member("success", false);
130 ret.set_string_member("message", str);
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);
137 generator.pretty = true;
138 generator.indent = 4;
141 print("%s\n", generator.to_data (null));
142 GLib.Process.exit(Posix.EXIT_FAILURE);
146 public static void buildApplication()
148 //print("build based on Application settings\n");
150 if (BuilderApplication.opt_compile_target == null) {
151 jerr("missing compile target --target");
154 Project.Project.loadAll();
155 var proj = Project.Project.getProjectByHash(BuilderApplication.opt_compile_project);
158 jerr("could not load test project %s".printf( BuilderApplication.opt_compile_project));
161 if (proj.xtype != "Gtk") {
162 jerr("%s is not a Gtk Project".printf( BuilderApplication.opt_compile_project));
164 var gproj = (Project.Gtk)proj;
167 if (!gproj.compilegroups.has_key(BuilderApplication.opt_compile_target)) {
168 jerr("missing compile target %s".printf(BuilderApplication.opt_compile_target));
171 if (BuilderApplication.opt_compile_skip != null) {
172 skip_file = BuilderApplication.opt_compile_skip;
175 if (BuilderApplication.opt_compile_add != null) {
176 add_file = BuilderApplication.opt_compile_add;
180 var vs = new ValaSource(gproj, add_file, BuilderApplication.opt_compile_target, skip_file);
186 Vala.CodeContext context;
187 ValaSourceReport report;
189 public string build_module;
190 public string filepath;
191 public string original_filepath;
192 public int line_offset = 0;
194 // file.project , file.path, file.build_module, ""
195 public ValaSource(Project.Gtk project, string filepath, string build_module, string original_filepath) {
198 this.filepath = filepath;
199 this.build_module = build_module;
200 this.original_filepath = original_filepath;
201 this.project = project;
204 public void dumpCode(string str)
206 var ls = str.split("\n");
207 for (var i=0;i < ls.length; i++) {
208 print("%d : %s\n", i+1, ls[i]);
212 //public Gee.HashMap<int,string> checkFile()
214 // return this.checkString(JsRender.NodeToVala.mungeFile(this.file));
217 public void checkFileWithNodePropChange(
218 JsRender.JsRender file,
223 ValaSourceResult result_cb)
228 Gee.HashMap<int,string> ret = new Gee.HashMap<int,string> ();
229 var hash = ptype == "listener" ? node.listeners : node.props;
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());
239 var old = hash.get(prop);
240 var newval = "/*--VALACHECK-START--*/ " + val ;
242 hash.set(prop, newval);
243 var tmpstring = JsRender.NodeToVala.mungeFile(file);
245 //print("%s\n", tmpstring);
246 var bits = tmpstring.split("/*--VALACHECK-START--*/");
248 if (bits.length > 0) {
249 offset = bits[0].split("\n").length +1;
252 this.line_offset = offset;
254 //this.dumpCode(tmpstring);
255 //print("offset %d\n", offset);
256 this.result_callback = result_cb;
257 this.checkStringSpawn(tmpstring );
265 ValaSourceResult result_callback;
266 public void checkStringSpawn(
271 FileIOStream iostream;
272 var tmpfile = File.new_tmp ("test-XXXXXX.vala", out iostream);
275 OutputStream ostream = iostream.output_stream;
276 DataOutputStream dostream = new DataOutputStream (ostream);
277 dostream.put_string (contents);
281 args += FileUtils.read_link("/proc/self/exe");
283 args += this.project.fn;
285 args += this.build_module;
286 args += "--add-file";
287 args += tmpfile.get_path();
288 args += "--skip-file";
289 args += this.filepath;
293 this.compiler = new Spawn("/tmp", args);
296 this.compiler.run(spawnResult);
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);
305 public void spawnResult(int res, string output, string stderr)
310 GLib.debug("GOT output %s", output);
312 var pa = new Json.Parser();
313 pa.load_from_data(output);
314 var node = pa.get_root();
316 if (node.get_node_type () != Json.NodeType.OBJECT) {
317 throw new ValaSourceError.INVALID_FORMAT ("Unexpected element type %s", node.type_name ());
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?");
325 this.result_callback(ret);
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);
341 public void compile( )
344 var valac = "valac " ;
346 context = new Vala.CodeContext ();
347 Vala.CodeContext.push (context);
349 context.experimental = false;
350 context.experimental_non_null = false;
362 for (int i = 2; i <= ver; i += 2) {
363 context.add_define ("VALA_0_%d".printf (i));
369 var vapidirs = this.project.vapidirs();
371 for(var i =0 ; i < context.vapi_directories; i++) {
372 vapidirs += context.vapi_directories[i];
375 for(var i =0 ; i < vapidirs.length; i++) {
376 valac += " --vapidir=" + vapidirs[i];
380 context.vapi_directories = vapidirs;
381 context.report.enable_warnings = true;
382 context.metadata_directories = { };
383 context.gir_directories = {};
384 context.thread = true;
387 this.report = new ValaSourceReport(this.original_filepath, this.filepath);
388 context.report = this.report;
391 context.basedir = "/tmp"; //Posix.realpath (".");
393 context.directory = context.basedir;
396 // add default packages:
397 //if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) {
398 context.profile = Vala.Profile.GOBJECT;
400 var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null));
401 context.root.add_using_directive (ns_ref);
403 var source_file = new Vala.SourceFile (
405 Vala.SourceFileType.SOURCE,
408 source_file.add_using_directive (ns_ref);
409 context.add_source_file (source_file);
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)));
419 if (!FileUtils.test(path, FileTest.EXISTS)) {
422 // skip thie original
423 if (path == this.original_filepath.replace(".bjs", ".vala")) {
427 if (FileUtils.test(path, FileTest.IS_DIR)) {
430 //print("Add source file %s\n", path);
434 if (Regex.match_simple("\\.c$", path)) {
435 context.add_c_source_file(path);
440 var xsf = new Vala.SourceFile (
442 Vala.SourceFileType.SOURCE,
445 xsf.add_using_directive (ns_ref);
446 context.add_source_file(xsf);
450 // default.. packages..
451 context.add_external_package ("glib-2.0");
452 context.add_external_package ("gobject-2.0");
453 // user defined ones..
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 context.add_external_package (dcg.packages.get(i));
461 //Vala.Config.PACKAGE_SUFFIX.substring (1)
463 // add the modules...
467 //context.add_external_package ("libvala-0.24");
471 //add_documented_files (context, settings.source_files);
473 Vala.Parser parser = new Vala.Parser ();
474 parser.parse (context);
475 //gir_parser.parse (context);
476 if (context.report.get_errors () > 0) {
477 Vala.CodeContext.pop ();
478 GLib.debug("parse got errors");
479 //((ValaSourceReport)context.report).dump();
480 this.report.result.set_boolean_member("success", false);
481 this.report.result.set_string_member("message", "Parse failed");
491 if (context.report.get_errors () > 0) {
492 Vala.CodeContext.pop ();
493 GLib.debug("check got errors");
494 //((ValaSourceReport)context.report).dump();
495 this.report.result.set_boolean_member("success", false);
496 this.report.result.set_string_member("message", "Check failed");
502 //context.codegen = new Vala.GDBusServerModule ();
505 context.output = "/tmp/testbuild";
506 valac += " -o " +context.output;
507 //context.codegen.emit (context);
509 var ccompiler = new Vala.CCodeCompiler ();
510 var cc_command = Environment.get_variable ("CC");
511 var pkg_config_command = Environment.get_variable ("PKG_CONFIG");
513 ccompiler.compile (context, cc_command, new string[] { }, pkg_config_command);
515 ccompiler.compile (context, cc_command, new string[] { });
519 Vala.CodeContext.pop ();
523 public void outputResult()
525 var generator = new Json.Generator ();
526 generator.indent = 1;
527 generator.pretty = true;
528 var node = new Json.Node(Json.NodeType.OBJECT);
529 node.set_object(this.report.result);
531 generator.set_root(node);
533 generator.pretty = true;
534 generator.indent = 4;
537 print("%s\n", generator.to_data (null));
538 GLib.Process.exit(Posix.EXIT_SUCCESS);
545 public Gee.HashMap<int,string> checkString(string contents)
548 var valac = "valac " ;
550 context = new Vala.CodeContext ();
551 Vala.CodeContext.push (context);
553 context.experimental = false;
554 context.experimental_non_null = false;
566 for (int i = 2; i <= ver; i += 2) {
567 context.add_define ("VALA_0_%d".printf (i));
576 var vapidirs = ((Project.Gtk)this.file.project).vapidirs();
577 // what's the current version of vala???
580 vapidirs += Path.get_dirname (context.get_vapi_path("glib-2.0")) ;
582 for(var i =0 ; i < vapidirs.length; i++) {
583 valac += " --vapidir=" + vapidirs[i];
587 // or context.get_vapi_path("glib-2.0"); // should return path..
588 context.vapi_directories = vapidirs;
589 context.report.enable_warnings = true;
590 context.metadata_directories = { };
591 context.gir_directories = {};
592 context.thread = true;
595 this.report = new ValaSourceReport(this.file.path);
596 context.report = this.report;
599 context.basedir = "/tmp"; //Posix.realpath (".");
601 context.directory = context.basedir;
604 // add default packages:
605 //if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) {
606 context.profile = Vala.Profile.GOBJECT;
608 var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null));
609 context.root.add_using_directive (ns_ref);
611 var source_file = new Vala.SourceFile (
613 Vala.SourceFileType.SOURCE,
614 "~~~~~testfile.vala",
617 source_file.add_using_directive (ns_ref);
618 context.add_source_file (source_file);
620 // add all the files (except the current one) - this.file.path
621 var pr = ((Project.Gtk)this.file.project);
622 if (this.file.build_module.length > 0) {
623 var cg = pr.compilegroups.get(this.file.build_module);
624 for (var i = 0; i < cg.sources.size; i++) {
625 var path = pr.resolve_path(
626 pr.resolve_path_combine_path(pr.firstPath(),cg.sources.get(i)));
628 if (!FileUtils.test(path, FileTest.EXISTS)) {
632 if (path == this.file.path.replace(".bjs", ".vala")) {
636 if (FileUtils.test(path, FileTest.IS_DIR)) {
639 //print("Add source file %s\n", path);
643 if (Regex.match_simple("\\.c$", path)) {
644 context.add_c_source_file(path);
649 var xsf = new Vala.SourceFile (
651 Vala.SourceFileType.SOURCE,
654 xsf.add_using_directive (ns_ref);
655 context.add_source_file(xsf);
659 // default.. packages..
660 context.add_external_package ("glib-2.0");
661 context.add_external_package ("gobject-2.0");
662 // user defined ones..
664 var dcg = pr.compilegroups.get("_default_");
665 for (var i = 0; i < dcg.packages.size; i++) {
666 valac += " --pkg " + dcg.packages.get(i);
667 context.add_external_package (dcg.packages.get(i));
670 //Vala.Config.PACKAGE_SUFFIX.substring (1)
672 // add the modules...
676 //context.add_external_package ("libvala-0.24");
678 this.report.compile_notice("START", "", 0, "");
681 //add_documented_files (context, settings.source_files);
683 Vala.Parser parser = new Vala.Parser ();
684 parser.parse (context);
685 //gir_parser.parse (context);
686 if (context.report.get_errors () > 0) {
687 print("parse got errors");
688 ((ValaSourceReport)context.report).dump();
690 Vala.CodeContext.pop ();
691 this.report.compile_notice("END", "", 0, "");
692 return this.report.line_errors;
699 if (context.report.get_errors () > 0) {
700 print("check got errors");
701 ((ValaSourceReport)context.report).dump();
702 Vala.CodeContext.pop ();
703 this.report.compile_notice("END", "", 0, "");
704 return this.report.line_errors;
708 //context.codegen = new Vala.GDBusServerModule ();
711 context.output = "/tmp/testbuild";
712 valac += " -o " +context.output;
713 //context.codegen.emit (context);
715 //(new Vala.CodeNode()).get_error_types().clear();
716 //(new Vala.NullType()).get_type_arguments().clear();
717 (new Vala.NullType(null)).get_type_arguments().clear();
719 this.report.compile_notice("END", "", 0, "");
720 print("%s\n", valac);
722 return this.report.line_errors;
731 int main (string[] args) {
733 var a = new ValaSource(file);
734 a.create_valac_tree();