From: Alan Knowles Date: Sat, 13 Jan 2024 15:00:30 +0000 (+0800) Subject: fix #7968 - language server support for syntax check and completion X-Git-Tag: release-5.0.1~18 X-Git-Url: http://git.roojs.org/?p=roobuilder;a=commitdiff_plain;h=67b4cca903e02417c1802b41c2fd8bb0da45c3e0 fix #7968 - language server support for syntax check and completion --- diff --git a/.roobuilder.jcfg b/.roobuilder.jcfg index 486260c88..38a066e3a 100644 --- a/.roobuilder.jcfg +++ b/.roobuilder.jcfg @@ -148,11 +148,14 @@ "src/Spawn.vala", "src/Application.vala", "src/Palete/ValalCompileQueue.vala", - "src/Palete/ValaCompileRequest.vala", - "src/Palete/ValaCompileQueue.vala", "src/Palete/Javascript.vala", "src/Project/Meson.vala", - "src/Palete/RooDatabase.vala" + "src/Palete/RooDatabase.vala", + "src/Palete/LanguageClient.vala", + "src/Palete/LanguageClientVala.vala", + "src/Lsp.vala", + "src/Palete/LanguageClientDummy.vala", + "src/Palete/ValaCompileRequest.vala" ] } ], @@ -167,11 +170,12 @@ "json-glib-1.0", "gobject-introspection-1.0", "libvala-0.56", - "libadwaita-1", "libxml-2.0", "posix", "roojspacker-1.4", "gtksourceview-5", - "libgda-5.0" + "libgda-5.0", + "jsonrpc-glib-1.0", + "gio-unix-2.0" ] } \ No newline at end of file diff --git a/configure.ac b/configure.ac index 23f639ade..e2a053648 100644 --- a/configure.ac +++ b/configure.ac @@ -33,6 +33,8 @@ PKG_CHECK_MODULES(ROOBUILDER, [ zlib libxml-2.0 libsoup-3.0 roojspacker-1.4 + jsonrpc-glib-1.0 + gio-unix-2.0 ]) dnl --- libvala -- needs to find matching really.. diff --git a/meson.build b/meson.build index c6db9650b..9e9887728 100644 --- a/meson.build +++ b/meson.build @@ -24,12 +24,13 @@ deps = [ dependency('json-glib-1.0'), dependency('gobject-introspection-1.0'), dependency('libvala-0.56'), - dependency('libadwaita-1'), dependency('libxml-2.0'), valac.find_library('posix'), dependency('roojspacker-1.4'), dependency('gtksourceview-5'), dependency('libgda-5.0'), + dependency('jsonrpc-glib-1.0'), + dependency('gio-unix-2.0'), ] @@ -188,11 +189,14 @@ roobuilder_src = files([ 'src/Resources.vala', 'src/Spawn.vala', 'src/Application.vala', - 'src/Palete/ValaCompileRequest.vala', - 'src/Palete/ValaCompileQueue.vala', 'src/Palete/Javascript.vala', 'src/Project/Meson.vala', 'src/Palete/RooDatabase.vala', + 'src/Palete/LanguageClient.vala', + 'src/Palete/LanguageClientVala.vala', + 'src/Lsp.vala', + 'src/Palete/LanguageClientDummy.vala', + 'src/Palete/ValaCompileRequest.vala', ]) roobuilder = executable('roobuilder', diff --git a/src/Application.vala b/src/Application.vala index b2d347c1a..41f1c0ae3 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -66,7 +66,7 @@ { "skip-file", 0, 0, OptionArg.STRING, ref opt_compile_skip ,"For test compiles do not add this (usually used in conjunction with add-file ", null }, { "add-file", 0, 0, OptionArg.STRING, ref opt_compile_add, "Add this file to compile list", null }, { "output", 0, 0, OptionArg.STRING, ref opt_compile_output, "output binary file path", null }, - { "debug", 0, 0, OptionArg.NONE, ref opt_debug, "Show debug messages", null }, + { "debug", 0, 0, OptionArg.NONE, ref opt_debug, "Show debug messages for non-ui, or crash on warnings for gdb ", null }, { "pull-resources", 0, 0, OptionArg.NONE, ref opt_pull_resources, "Fetch the online resources", null }, // some testing code. @@ -77,7 +77,7 @@ { "bjs-test-all", 0, 0, OptionArg.NONE, ref opt_bjs_test, "Test all the BJS files to see if the new parser/writer would change anything", null }, { "bjs-target", 0, 0, OptionArg.STRING, ref opt_bjs_compile_target, "convert bjs file to tareet : vala / js", null }, { "test", 0, 0, OptionArg.STRING, ref opt_test, "run a test use 'help' to list the available tests", null }, - + { "language-server", 0, 0, OptionArg.STRING, ref opt_language_server, "run language server on this file", null }, { "drop-list", 0, 0, OptionArg.STRING, ref opt_drop_list, "show droplist / children for a Gtk type (eg. Gtk.Widget)", null }, @@ -88,11 +88,11 @@ public static string opt_compile_skip; public static string opt_compile_add; public static string opt_compile_output; - public static string opt_bjs_compile; - public static string opt_bjs_compile_target; - public static string opt_test; - public static string opt_drop_list; - + public static string opt_bjs_compile; + public static string opt_bjs_compile_target; + public static string opt_test; + public static string opt_drop_list; + public static string opt_language_server; public static bool opt_skip_linking = false; public static bool opt_debug = false; @@ -122,7 +122,7 @@ - public static Palete.ValaCompileQueue valacompilequeue; + //public static Palete.ValaCompileQueue valacompilequeue; public BuilderApplication ( string[] args) @@ -149,7 +149,7 @@ flags: ApplicationFlags.FLAGS_NONE ); BuilderApplication.windows = new Gee.ArrayList(); - BuilderApplication.valacompilequeue = new Palete.ValaCompileQueue(); + //BuilderApplication.valacompilequeue = new Palete.ValaCompileQueue(); configDirectory(); @@ -176,9 +176,11 @@ Project.Project.loadAll(); this.listProjects(); var cur_project = this.compileProject(); - this.dropList(cur_project); + this.dropList(cur_project); // --drop-list + this.languageServer(cur_project); // --language-server this.listFiles(cur_project); this.testBjs(cur_project); + this.languageServer(cur_project); this.compileBjs(cur_project); this.compileVala(); @@ -227,12 +229,24 @@ void initDebug() { - + + if (BuilderApplication.opt_debug || BuilderApplication.opt_compile_project == null) { - GLib.Log.set_handler(null, - GLib.LogLevelFlags.LEVEL_DEBUG | GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_CRITICAL, + GLib.Log.set_default_handler( + // GLib.LogLevelFlags.LEVEL_DEBUG | GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_CRITICAL, (dom, lvl, msg) => { - print("%s: %s\n", (new DateTime.now_local()).format("%H:%M:%S.%f"), msg); + + print("%s: %s : %s\n", (new DateTime.now_local()).format("%H:%M:%S.%f"), lvl.to_string(), msg); + + if (dom== "GtkSourceView") { // seems to be some critical wanrings comming from gtksourceview related to insert? + return; + } + //if (msg.contains("gdk_popup_present")) { // seems to be problems with the popup present on gtksourceview competion. + // return; + //} + if (BuilderApplication.opt_debug && lvl == GLib.LogLevelFlags.LEVEL_CRITICAL) { + GLib.error(msg); + } }); } @@ -413,7 +427,7 @@ - var file = cur_project.getByName(BuilderApplication.opt_bjs_compile); + var file = cur_project.getByRelPath(BuilderApplication.opt_bjs_compile); if (file == null) { // then compile them all, and compare them... @@ -466,7 +480,44 @@ GLib.Process.exit(Posix.EXIT_SUCCESS); } - + void languageServer(Project.Project? cur_project) + { + if (BuilderApplication.opt_language_server == null) { + return; + } + if (cur_project == null) { + GLib.error("missing project, use --project to select which project"); + } + var file = cur_project.getByRelPath(BuilderApplication.opt_language_server); + if (file == null) { + // then compile them all, and compare them... + GLib.error("missing file %s in project %s", BuilderApplication.opt_language_server, cur_project.name); + } + + var ls = file.getLanguageServer(); + if (ls == null) { + GLib.error("No langauge server returned for file:%s", file.relpath); + } + var loop = new MainLoop(); + GLib.Timeout.add_seconds(1, () => { + if (!ls.isReady()) { + GLib.debug("waiting for server to be ready"); + return true; + } + GLib.debug("Sending document_open"); + // it's ready.. + + ls.document_open(file); + return false; + + }); + + + loop.run(); + GLib.Process.exit(Posix.EXIT_SUCCESS); + } + + void compileVala() { if (BuilderApplication.opt_compile_target == null) { @@ -504,7 +555,7 @@ case "help": print(""" help - list available tests -flutter-project - create a flutter project in /tmp/test-flutter +flutter-project - was try and read flutter data (but desnt work.) """); break; case "flutter-project": @@ -523,6 +574,9 @@ flutter-project - create a flutter project in /tmp/test-flutter */ break; + + + default: print("Invalid test\n"); break; @@ -593,29 +647,27 @@ flutter-project - create a flutter project in /tmp/test-flutter if (ww == null || ww.windowstate == null || ww.windowstate.project ==null) { continue; } - if (ww.windowstate.project.last_request == null) { - ww.updateErrors(null); - return; - } - var req = ww.windowstate.project.last_request; - GLib.debug("checking errors editor for %s", ww.windowstate.file.targetName()); - - if (req.errorByFile.has_key(ww.windowstate.file.targetName())) { - GLib.debug("calling update Error margs for %s", ww.windowstate.file.targetName()); - ww.windowstate.code_editor_tab.updateErrorMarks(req.errorByFile.get(ww.windowstate.file.targetName())); - } else { - ww.windowstate.code_editor_tab.updateErrorMarks(null); + + ww.windowstate.updateErrorMarksAll(); - GLib.debug("no errors in errrobyfile for %s", ww.windowstate.file.targetName()); - } - GLib.debug("calling udate Errors of window %s", ww.windowstate.file.targetName()); - ww.updateErrors(req); + ww.updateErrors(); } } + public static void showSpinner(bool state) + { + foreach (var win in BuilderApplication.windows) { + if (state) { + win.statusbar_compile_spinner.start(); + } else { + win.statusbar_compile_spinner.stop(); + } + } + } + diff --git a/src/Builder4/DialogFiles.bjs b/src/Builder4/DialogFiles.bjs index d53a5a2d1..647b18541 100644 --- a/src/Builder4/DialogFiles.bjs +++ b/src/Builder4/DialogFiles.bjs @@ -186,7 +186,7 @@ " ", "\tvar lbl = (Gtk.Label) ((Gtk.ListItem)listitem).get_child();", "\t ", - "\tvar item = (JsRender.JsRender) ((Gtk.ListItem)listitem).get_item();", + "\tvar item = (Project.Project) ((Gtk.ListItem)listitem).get_item();", "", "\titem.bind_property(\"name\",", " lbl, \"label\",", diff --git a/src/Builder4/DialogFiles.vala b/src/Builder4/DialogFiles.vala index 36e438759..0d3723bf0 100644 --- a/src/Builder4/DialogFiles.vala +++ b/src/Builder4/DialogFiles.vala @@ -590,7 +590,7 @@ var lbl = (Gtk.Label) ((Gtk.ListItem)listitem).get_child(); - var item = (JsRender.JsRender) ((Gtk.ListItem)listitem).get_item(); + var item = (Project.Project) ((Gtk.ListItem)listitem).get_item(); item.bind_property("name", lbl, "label", diff --git a/src/Builder4/Editor.bjs b/src/Builder4/Editor.bjs index 492bdd828..038d0a778 100644 --- a/src/Builder4/Editor.bjs +++ b/src/Builder4/Editor.bjs @@ -1,6 +1,5 @@ { "build_module" : "builder", - "gen_extended" : false, "items" : [ { "# GtkSource.SearchContext searchcontext" : "null", @@ -132,15 +131,22 @@ "\t", " ", "\t ", - "", - " ", - "this.el.completion.add_provider(new Palete.CompletionProvider(_this));", + "/*", + "this is pretty flakey - triggers Gtk with < 0 d", + " var cp = new GtkSource.CompletionWords(\"test\"); ", + " cp.minimum_word_size = 3;", + " //cp.priority = 100; //?? does this do anything", + " cp.proposals_batch_size = 10;", + " cp.scan_batch_size = 1000;", " ", - "", - "this.el.completion.unblock_interactive();", + "cp.register(_this.buffer.el);", + "this.el.completion.add_provider(cp);", + "*/", + "this.el.completion.add_provider(new Palete.CompletionProvider(_this));", + " ", + "//this.el.completion.unblock_interactive();", "this.el.completion.select_on_show = true; // select", - "", - "this.el.completion.remember_info_visibility\t = true;", + "//this.el.completion.remember_info_visibility\t = true;", "", "", "var attrs = new GtkSource.MarkAttributes();", @@ -261,15 +267,15 @@ " }", " ", " // bit presumptiona", - " if (_this.file.xtype == \"PlainFile\" && _this.file.project.xtype == \"Gtk\") {", + " if (_this.file.xtype == \"PlainFile\") {", " ", " // assume it's gtk...", - " ", - "\t\tBuilderApplication.valacompilequeue.addFile( ", - "\t\t\tPalete.ValaCompileRequestType.FILE_CHANGE, ", - "\t\t\t_this.file , str, false) ;", - " ", - "", + " var oldcode =_this.file.toSource();", + " _this.file.setSource(str);", + " _this.file.getLanguageServer().document_change(_this.file);", + " _this.file.setSource(oldcode);", + " ", + "\t\t ", " return true;", " ", " }", @@ -283,14 +289,14 @@ " ", " GLib.debug(\"calling validate\"); ", " // clear the buttons.", - " ", - " BuilderApplication.valacompilequeue.addProp( ", - " \t\tPalete.ValaCompileRequestType.PROP_CHANGE,", - "\t\t\t_this.file,", - "\t\t\t_this.node,", - "\t\t\t_this.prop,", - "\t\t\tstr); ", - " ", + " \tif (_this.prop.name == \"xns\" || _this.prop.name == \"xtype\") {", + "\t\treturn true ;", + "\t}", + "\tvar oldcode = _this.prop.val;", + "\t", + "\t_this.prop.val = str;", + " _this.file.getLanguageServer().document_change(_this.file);", + " _this.prop.val = oldcode;", " ", " ", " //print(\"done mark line\\n\");", @@ -475,7 +481,7 @@ "\t\t_this.search_entry.el.grab_focus();", "\t return;", "\t}", - " ", + " //_this.view.el.show_completion();", " // print(event.key.keyval)", " ", " return;", @@ -994,27 +1000,21 @@ "}" ], "| void updateErrorMarks" : [ - "(GLib.ListStore? ar) {", + "(string category) {", "\t", " ", - "\t", - "\t var buf = _this.buffer.el;", + "", + "\tvar buf = _this.buffer.el;", "\tGtk.TextIter start;", "\tGtk.TextIter end; ", "\tbuf.get_bounds (out start, out end);", "", - "\tbuf.remove_source_marks (start, end, \"ERR\");", - "\tbuf.remove_source_marks (start, end, \"WARN\");", - "\tbuf.remove_source_marks (start, end, \"DEPR\");", + "\tbuf.remove_source_marks (start, end, category);", + " ", "\tGLib.debug(\"highlight errors\");\t\t ", "", "\t // we should highlight other types of errors..", "", - "\tif (ar == null || ar.get_n_items() < 1) {", - "\t\tGLib.debug(\"Return has no errors\\n\");", - "\t\treturn;", - "\t}", - "", "\tif (_this.window.windowstate.state != WindowState.State.CODEONLY ", "\t\t&&", "\t\t_this.window.windowstate.state != WindowState.State.CODE", @@ -1030,11 +1030,16 @@ "\t\treturn;", "", "\t}", + "\tvar ar = this.file.getErrors(category);", + "\tif (ar == null || ar.get_n_items() < 1) {", + "\t\tGLib.debug(\"highlight %s : %s has no errors\", this.file.relpath, category);", + "\t\treturn;", + "\t}", " ", "", " ", "\t", - "\tvar offset = 1;", + "\tvar offset = 0;", "\t ", "", "\tvar tlines = buf.get_line_count () +1;", @@ -1066,8 +1071,8 @@ "\t ", "\t\tvar msg = \"Line: %d %s : %s\".printf(eline+1, err.category, err.msg);", "\t buf.create_source_mark( msg, err.category, iter);", - "\t GLib.debug(\"set line %d to %m\", eline, msg);", - "\t // this.marks.set(eline, msg);", + "\t GLib.debug(\"set line %d to %s\", eline, msg);", + "\t //this.marks.set(eline, msg);", "\t}", "\treturn ;", "", @@ -1079,5 +1084,10 @@ ] } ], - "name" : "Editor" + "modOrder" : "", + "name" : "Editor", + "parent" : "", + "path" : "/home/alan/gitlive/roobuilder/src/Builder4/Editor.bjs", + "permname" : "", + "title" : "" } \ No newline at end of file diff --git a/src/Builder4/Editor.vala b/src/Builder4/Editor.vala index e03db08c5..c1cca4bcb 100644 --- a/src/Builder4/Editor.vala +++ b/src/Builder4/Editor.vala @@ -1,1475 +1,1496 @@ - static Editor _Editor; +static Editor _Editor; - public class Editor : Object - { - public Gtk.Box el; - private Editor _this; - - public static Editor singleton() - { - if (_Editor == null) { - _Editor= new Editor(); - } - return _Editor; - } - public Xcls_save_button save_button; - public Xcls_close_btn close_btn; - public Xcls_RightEditor RightEditor; - public Xcls_view view; - public Xcls_buffer buffer; - public Xcls_search_entry search_entry; - public Xcls_search_results search_results; - public Xcls_nextBtn nextBtn; - public Xcls_backBtn backBtn; - public Xcls_search_settings search_settings; - public Xcls_case_sensitive case_sensitive; - public Xcls_regex regex; - public Xcls_multiline multiline; - - // my vars (def) - public int pos_root_x; - public Xcls_MainWindow window; - public bool dirty; - public int pos_root_y; - public bool pos; - public GtkSource.SearchContext searchcontext; - public int last_search_end; - public signal void save (); - public JsRender.JsRender? file; - public JsRender.Node node; - public JsRender.NodeProp? prop; - public string activeEditor; - - // ctor - public Editor() - { - _this = this; - this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 ); - - // my vars (dec) - this.window = null; - this.dirty = false; - this.pos = false; - this.searchcontext = null; - this.last_search_end = 0; - this.file = null; - this.node = null; - this.prop = null; - this.activeEditor = ""; +public class Editor : Object +{ + public Gtk.Box el; + private Editor _this; - // set gobject values - this.el.homogeneous = false; - this.el.hexpand = true; - this.el.vexpand = true; - var child_1 = new Xcls_Box2( _this ); - child_1.ref(); - this.el.append( child_1.el ); - new Xcls_RightEditor( _this ); - this.el.append( _this.RightEditor.el ); - var child_3 = new Xcls_Box12( _this ); - child_3.ref(); - this.el.append ( child_3.el ); + public static Editor singleton() + { + if (_Editor == null) { + _Editor= new Editor(); } + return _Editor; + } + public Xcls_save_button save_button; + public Xcls_close_btn close_btn; + public Xcls_RightEditor RightEditor; + public Xcls_view view; + public Xcls_buffer buffer; + public Xcls_search_entry search_entry; + public Xcls_search_results search_results; + public Xcls_nextBtn nextBtn; + public Xcls_backBtn backBtn; + public Xcls_search_settings search_settings; + public Xcls_case_sensitive case_sensitive; + public Xcls_regex regex; + public Xcls_multiline multiline; + + // my vars (def) + public int pos_root_x; + public Xcls_MainWindow window; + public bool dirty; + public int pos_root_y; + public bool pos; + public GtkSource.SearchContext searchcontext; + public int last_search_end; + public signal void save (); + public JsRender.JsRender? file; + public JsRender.Node node; + public JsRender.NodeProp? prop; + public string activeEditor; + + // ctor + public Editor() + { + _this = this; + this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 ); + + // my vars (dec) + this.window = null; + this.dirty = false; + this.pos = false; + this.searchcontext = null; + this.last_search_end = 0; + this.file = null; + this.node = null; + this.prop = null; + this.activeEditor = ""; + + // set gobject values + this.el.homogeneous = false; + this.el.hexpand = true; + this.el.vexpand = true; + var child_1 = new Xcls_Box2( _this ); + child_1.ref(); + this.el.append( child_1.el ); + var child_2 = new Xcls_RightEditor( _this ); + child_2.ref(); + this.el.append( child_2.el ); + var child_3 = new Xcls_Box12( _this ); + child_3.ref(); + this.el.append ( child_3.el ); + } - // user defined functions - public bool saveContents () { - - - if (_this.file == null) { - return true; - } - - - - var str = _this.buffer.toString(); - - _this.buffer.checkSyntax(); - - - - // LeftPanel.model.changed( str , false); - _this.dirty = false; - _this.save_button.el.sensitive = false; - - // find the text for the node.. - if (_this.file.xtype != "PlainFile") { - // in theory these properties have to exist!?! - this.prop.val = str; - //this.window.windowstate.left_props.reload(); - } else { - _this.file.setSource( str ); - } - - // call the signal.. - this.save(); - - return true; + // user defined functions + public bool saveContents () { - } - public void forwardSearch (bool change_focus) { - if (this.searchcontext == null) { - return; - } - - Gtk.TextIter beg, st,en; - bool has_wrapped_around; - this.buffer.el.get_iter_at_offset(out beg, this.last_search_end); - if (!this.searchcontext.forward(beg, out st, out en, out has_wrapped_around)) { - - this.last_search_end = 0; // not sure if this should happen - } else { - if (has_wrapped_around) { - return; - } - - this.last_search_end = en.get_offset(); - if (change_focus) { - this.view.el.grab_focus(); - } - this.buffer.el.place_cursor(st); - this.view.el.scroll_to_iter(st, 0.1f, true, 0.0f, 0.5f); - } - + if (_this.file == null) { + return true; } - public void show (JsRender.JsRender file, JsRender.Node? node, JsRender.NodeProp? prop) - { - this.reset(); - this.file = file; - - if (file.xtype != "PlainFile") { - this.prop = prop; - this.node = node; - // find the text for the node.. - this.view.load( prop.val ); - - - this.close_btn.el.show(); - - } else { - this.view.load( file.toSource() ); - this.close_btn.el.hide(); - } - } - public void backSearch (bool change_focus) { - - if (this.searchcontext == null) { - return; - } - - Gtk.TextIter beg, st,en; - bool has_wrapped_around; - this.buffer.el.get_iter_at_offset(out beg, this.last_search_end -1 ); - - if (!this.searchcontext.backward(beg, out st, out en, out has_wrapped_around)) { - this.last_search_end = 0; - } else { - this.last_search_end = en.get_offset(); - if (change_focus) { - this.view.el.grab_focus(); - } - this.buffer.el.place_cursor(st); - this.view.el.scroll_to_iter(st, 0.1f, true, 0.0f, 0.5f); - } - - } - public void reset () { - this.file = null; - - this.node = null; - this.prop = null; - this.searchcontext = null; - - } - public int search (string in_txt) { - - var s = new GtkSource.SearchSettings(); - s.case_sensitive = _this.case_sensitive.el.active; - s.regex_enabled = _this.regex.el.active; - s.wrap_around = false; - - this.searchcontext = new GtkSource.SearchContext(this.buffer.el,s); - this.searchcontext.set_highlight(true); - var txt = in_txt; - - if (_this.multiline.el.active) { - txt = in_txt.replace("\\n", "\n"); - } - - s.set_search_text(txt); - Gtk.TextIter beg, st,en; - - this.buffer.el.get_start_iter(out beg); - bool has_wrapped_around; - this.searchcontext.forward(beg, out st, out en, out has_wrapped_around); - this.last_search_end = 0; - - return this.searchcontext.get_occurrences_count(); - - - - } - public void updateErrorMarks (GLib.ListStore? ar) { - + var str = _this.buffer.toString(); - - var buf = _this.buffer.el; - Gtk.TextIter start; - Gtk.TextIter end; - buf.get_bounds (out start, out end); - - buf.remove_source_marks (start, end, "ERR"); - buf.remove_source_marks (start, end, "WARN"); - buf.remove_source_marks (start, end, "DEPR"); - GLib.debug("highlight errors"); - - // we should highlight other types of errors.. - - if (ar == null || ar.get_n_items() < 1) { - GLib.debug("Return has no errors\n"); - return; - } - - if (_this.window.windowstate.state != WindowState.State.CODEONLY - && - _this.window.windowstate.state != WindowState.State.CODE - ) { - GLib.debug("windowstate != CODEONLY?"); - - return; - } - - - if (_this.file == null) { - GLib.debug("file is null?"); - return; - - } + _this.buffer.checkSyntax(); - - - var offset = 1; - - - var tlines = buf.get_line_count () +1; - - if (_this.prop != null) { - - tlines = _this.prop.end_line + 1; - offset = _this.prop.start_line + 1; - - } - - for (var i = 0; i < ar.get_n_items();i++) { - var err = (Palete.CompileError) ar.get_item(i); - - Gtk.TextIter iter; - // print("get inter\n"); - var eline = err.line - offset; - GLib.debug("GOT ERROR on line %d -- converted to %d (offset = %d)", - err.line ,eline, offset); - - - if (eline > tlines || eline < 0) { - return; - } - - - buf.get_iter_at_line( out iter, eline); - - - var msg = "Line: %d %s : %s".printf(eline+1, err.category, err.msg); - buf.create_source_mark( msg, err.category, iter); - GLib.debug("set line %d to %m", eline, msg); - // this.marks.set(eline, msg); - } - return ; - - - + // LeftPanel.model.changed( str , false); + _this.dirty = false; + _this.save_button.el.sensitive = false; + + // find the text for the node.. + if (_this.file.xtype != "PlainFile") { + // in theory these properties have to exist!?! + this.prop.val = str; + //this.window.windowstate.left_props.reload(); + } else { + _this.file.setSource( str ); + } - } - public void scroll_to_line (int line) { + // call the signal.. + this.save(); - GLib.Timeout.add(500, () => { - - var buf = this.view.el.get_buffer(); - - var sbuf = (GtkSource.Buffer) buf; + return true; + + } + public void forwardSearch (bool change_focus) { + + if (this.searchcontext == null) { + return; + } + + Gtk.TextIter beg, st,en; + bool has_wrapped_around; + this.buffer.el.get_iter_at_offset(out beg, this.last_search_end); + if (!this.searchcontext.forward(beg, out st, out en, out has_wrapped_around)) { + + this.last_search_end = 0; // not sure if this should happen + } else { + if (has_wrapped_around) { + return; + } + + this.last_search_end = en.get_offset(); + if (change_focus) { + this.view.el.grab_focus(); + } + this.buffer.el.place_cursor(st); + this.view.el.scroll_to_iter(st, 0.1f, true, 0.0f, 0.5f); + } + + } + public void show (JsRender.JsRender file, JsRender.Node? node, JsRender.NodeProp? prop) + { + this.reset(); + this.file = file; + if (file.xtype != "PlainFile") { + this.prop = prop; + this.node = node; + + // find the text for the node.. + this.view.load( prop.val ); + + + this.close_btn.el.show(); - Gtk.TextIter iter; - sbuf.get_iter_at_line(out iter, line); - this.view.el.scroll_to_iter(iter, 0.1f, true, 0.0f, 0.5f); - return false; - }); + } else { + this.view.load( file.toSource() ); + this.close_btn.el.hide(); } - public class Xcls_Box2 : Object - { - public Gtk.Box el; - private Editor _this; + + } + public void backSearch (bool change_focus) { + + if (this.searchcontext == null) { + return; + } + + Gtk.TextIter beg, st,en; + bool has_wrapped_around; + this.buffer.el.get_iter_at_offset(out beg, this.last_search_end -1 ); + + if (!this.searchcontext.backward(beg, out st, out en, out has_wrapped_around)) { + this.last_search_end = 0; + } else { + this.last_search_end = en.get_offset(); + if (change_focus) { + this.view.el.grab_focus(); + } + this.buffer.el.place_cursor(st); + this.view.el.scroll_to_iter(st, 0.1f, true, 0.0f, 0.5f); + } + + } + public void reset () { + this.file = null; + + this.node = null; + this.prop = null; + this.searchcontext = null; + + } + public int search (string in_txt) { + + var s = new GtkSource.SearchSettings(); + s.case_sensitive = _this.case_sensitive.el.active; + s.regex_enabled = _this.regex.el.active; + s.wrap_around = false; + + this.searchcontext = new GtkSource.SearchContext(this.buffer.el,s); + this.searchcontext.set_highlight(true); + var txt = in_txt; + + if (_this.multiline.el.active) { + txt = in_txt.replace("\\n", "\n"); + } + + s.set_search_text(txt); + Gtk.TextIter beg, st,en; + + this.buffer.el.get_start_iter(out beg); + bool has_wrapped_around; + this.searchcontext.forward(beg, out st, out en, out has_wrapped_around); + this.last_search_end = 0; + + return this.searchcontext.get_occurrences_count(); + + + + + } + public void updateErrorMarks (string category) { + + + + var buf = _this.buffer.el; + Gtk.TextIter start; + Gtk.TextIter end; + buf.get_bounds (out start, out end); + + buf.remove_source_marks (start, end, category); + + GLib.debug("highlight errors"); + + // we should highlight other types of errors.. + + if (_this.window.windowstate.state != WindowState.State.CODEONLY + && + _this.window.windowstate.state != WindowState.State.CODE + ) { + GLib.debug("windowstate != CODEONLY?"); + + return; + } + + + if (_this.file == null) { + GLib.debug("file is null?"); + return; + + } + var ar = this.file.getErrors(category); + if (ar == null || ar.get_n_items() < 1) { + GLib.debug("highlight %s : %s has no errors", this.file.relpath, category); + return; + } + + + + + var offset = 0; + + + var tlines = buf.get_line_count () +1; + + if (_this.prop != null) { + + tlines = _this.prop.end_line + 1; + offset = _this.prop.start_line + 1; + + } + + for (var i = 0; i < ar.get_n_items();i++) { + var err = (Palete.CompileError) ar.get_item(i); + + Gtk.TextIter iter; + // print("get inter\n"); + var eline = err.line - offset; + GLib.debug("GOT ERROR on line %d -- converted to %d (offset = %d)", + err.line ,eline, offset); + + + if (eline > tlines || eline < 0) { + return; + } + + + buf.get_iter_at_line( out iter, eline); + + + var msg = "Line: %d %s : %s".printf(eline+1, err.category, err.msg); + buf.create_source_mark( msg, err.category, iter); + GLib.debug("set line %d to %s", eline, msg); + //this.marks.set(eline, msg); + } + return ; + + + + + + } + public void scroll_to_line (int line) { + + GLib.Timeout.add(500, () => { + + var buf = this.view.el.get_buffer(); + + var sbuf = (GtkSource.Buffer) buf; + + + Gtk.TextIter iter; + sbuf.get_iter_at_line(out iter, line); + this.view.el.scroll_to_iter(iter, 0.1f, true, 0.0f, 0.5f); + return false; + }); + } + public class Xcls_Box2 : Object + { + public Gtk.Box el; + private Editor _this; - // my vars (def) + // my vars (def) - // ctor - public Xcls_Box2(Editor _owner ) - { - _this = _owner; - this.el = new Gtk.Box( Gtk.Orientation.HORIZONTAL, 0 ); - - // my vars (dec) - - // set gobject values - this.el.homogeneous = false; - this.el.hexpand = true; - new Xcls_save_button( _this ); - this.el.append( _this.save_button.el ); - var child_2 = new Xcls_Label4( _this ); - child_2.ref(); - this.el.append( child_2.el ); - var child_3 = new Xcls_Scale5( _this ); - child_3.ref(); - this.el.append( child_3.el ); - new Xcls_close_btn( _this ); - this.el.append( _this.close_btn.el ); - } + // ctor + public Xcls_Box2(Editor _owner ) + { + _this = _owner; + this.el = new Gtk.Box( Gtk.Orientation.HORIZONTAL, 0 ); + + // my vars (dec) - // user defined functions + // set gobject values + this.el.homogeneous = false; + this.el.hexpand = true; + var child_1 = new Xcls_save_button( _this ); + child_1.ref(); + this.el.append( child_1.el ); + var child_2 = new Xcls_Label4( _this ); + child_2.ref(); + this.el.append( child_2.el ); + var child_3 = new Xcls_Scale5( _this ); + child_3.ref(); + this.el.append( child_3.el ); + var child_4 = new Xcls_close_btn( _this ); + child_4.ref(); + this.el.append( child_4.el ); } - public class Xcls_save_button : Object - { - public Gtk.Button el; - private Editor _this; + // user defined functions + } + public class Xcls_save_button : Object + { + public Gtk.Button el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_save_button(Editor _owner ) - { - _this = _owner; - _this.save_button = this; - this.el = new Gtk.Button(); + // my vars (def) - // my vars (dec) + // ctor + public Xcls_save_button(Editor _owner ) + { + _this = _owner; + _this.save_button = this; + this.el = new Gtk.Button(); - // set gobject values - this.el.label = "Save"; + // my vars (dec) - //listeners - this.el.clicked.connect( () => { - _this.saveContents(); - }); - } + // set gobject values + this.el.label = "Save"; - // user defined functions + //listeners + this.el.clicked.connect( () => { + _this.saveContents(); + }); } - public class Xcls_Label4 : Object - { - public Gtk.Label el; - private Editor _this; + // user defined functions + } + public class Xcls_Label4 : Object + { + public Gtk.Label el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_Label4(Editor _owner ) - { - _this = _owner; - this.el = new Gtk.Label( null ); + // my vars (def) - // my vars (dec) + // ctor + public Xcls_Label4(Editor _owner ) + { + _this = _owner; + this.el = new Gtk.Label( null ); - // set gobject values - this.el.hexpand = true; - } + // my vars (dec) - // user defined functions + // set gobject values + this.el.hexpand = true; } - public class Xcls_Scale5 : Object - { - public Gtk.Scale el; - private Editor _this; + // user defined functions + } + public class Xcls_Scale5 : Object + { + public Gtk.Scale el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_Scale5(Editor _owner ) - { - _this = _owner; - this.el = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL,6, 30, 1); + // my vars (def) - // my vars (dec) + // ctor + public Xcls_Scale5(Editor _owner ) + { + _this = _owner; + this.el = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL,6, 30, 1); - // set gobject values - this.el.width_request = 200; - this.el.has_origin = true; - this.el.draw_value = false; - this.el.digits = 0; - this.el.sensitive = true; + // my vars (dec) - // init method + // set gobject values + this.el.width_request = 200; + this.el.has_origin = true; + this.el.draw_value = false; + this.el.digits = 0; + this.el.sensitive = true; - { - this.el.set_range(6,30); - this.el.set_value(8); - } + // init method - //listeners - this.el.change_value.connect( (st, val ) => { - - - _this.view.css.load_from_string( - "#editor-view { font: %dpx monospace; }".printf((int)val) - ); - - return false; - }); + { + this.el.set_range(6,30); + this.el.set_value(8); } - // user defined functions + //listeners + this.el.change_value.connect( (st, val ) => { + + + _this.view.css.load_from_string( + "#editor-view { font: %dpx monospace; }".printf((int)val) + ); + + return false; + }); } - public class Xcls_close_btn : Object - { - public Gtk.Button el; - private Editor _this; + // user defined functions + } + public class Xcls_close_btn : Object + { + public Gtk.Button el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_close_btn(Editor _owner ) - { - _this = _owner; - _this.close_btn = this; - this.el = new Gtk.Button(); + // my vars (def) - // my vars (dec) + // ctor + public Xcls_close_btn(Editor _owner ) + { + _this = _owner; + _this.close_btn = this; + this.el = new Gtk.Button(); - // set gobject values - this.el.icon_name = "window-close"; - var child_1 = new Xcls_Image7( _this ); - this.el.child = child_1.el; + // my vars (dec) - //listeners - this.el.clicked.connect( () => { - _this.saveContents(); - _this.window.windowstate.switchState(WindowState.State.PREVIEW); - }); - } + // set gobject values + this.el.icon_name = "window-close"; + var child_1 = new Xcls_Image7( _this ); + child_1.ref(); + this.el.child = child_1.el; - // user defined functions + //listeners + this.el.clicked.connect( () => { + _this.saveContents(); + _this.window.windowstate.switchState(WindowState.State.PREVIEW); + }); } - public class Xcls_Image7 : Object - { - public Gtk.Image el; - private Editor _this; + // user defined functions + } + public class Xcls_Image7 : Object + { + public Gtk.Image el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_Image7(Editor _owner ) - { - _this = _owner; - this.el = new Gtk.Image(); + // my vars (def) - // my vars (dec) + // ctor + public Xcls_Image7(Editor _owner ) + { + _this = _owner; + this.el = new Gtk.Image(); - // set gobject values - this.el.icon_name = "window-close"; - this.el.icon_size = Gtk.IconSize.NORMAL; - } + // my vars (dec) - // user defined functions + // set gobject values + this.el.icon_name = "window-close"; + this.el.icon_size = Gtk.IconSize.NORMAL; } + // user defined functions + } - public class Xcls_RightEditor : Object - { - public Gtk.ScrolledWindow el; - private Editor _this; + public class Xcls_RightEditor : Object + { + public Gtk.ScrolledWindow el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_RightEditor(Editor _owner ) - { - _this = _owner; - _this.RightEditor = this; - this.el = new Gtk.ScrolledWindow(); - - // my vars (dec) - - // set gobject values - this.el.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - this.el.vexpand = true; - this.el.overlay_scrolling = false; - this.el.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - new Xcls_view( _this ); - this.el.child = _this.view.el; - } + // my vars (def) - // user defined functions - } - public class Xcls_view : Object + // ctor + public Xcls_RightEditor(Editor _owner ) { - public GtkSource.View el; - private Editor _this; + _this = _owner; + _this.RightEditor = this; + this.el = new Gtk.ScrolledWindow(); + // my vars (dec) - // my vars (def) - public Gtk.CssProvider css; + // set gobject values + this.el.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + this.el.vexpand = true; + this.el.overlay_scrolling = false; + this.el.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC; + var child_1 = new Xcls_view( _this ); + child_1.ref(); + this.el.child = child_1.el; + } - // ctor - public Xcls_view(Editor _owner ) - { - _this = _owner; - _this.view = this; - this.el = new GtkSource.View(); - - // my vars (dec) - this.css = null; - - // set gobject values - this.el.auto_indent = true; - this.el.indent_width = 4; - this.el.name = "editor-view"; - this.el.show_line_marks = true; - this.el.insert_spaces_instead_of_tabs = true; - this.el.show_line_numbers = true; - this.el.hexpand = true; - this.el.vexpand = true; - this.el.has_tooltip = true; - this.el.tab_width = 4; - this.el.highlight_current_line = true; - new Xcls_buffer( _this ); - this.el.buffer = _this.buffer.el; - var child_2 = new Xcls_EventControllerKey11( _this ); - child_2.ref(); - this.el.add_controller( child_2.el ); - - // init method - - this.css = new Gtk.CssProvider(); - - this.css.load_from_string( - "#editor-view { font: 12px monospace;}" - ); - - Gtk.StyleContext.add_provider_for_display( - this.el.get_display(), - this.css, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - - - - - - this.el.completion.add_provider(new Palete.CompletionProvider(_this)); - - - this.el.completion.unblock_interactive(); - this.el.completion.select_on_show = true; // select - - this.el.completion.remember_info_visibility = true; - - - var attrs = new GtkSource.MarkAttributes(); - var pink = Gdk.RGBA(); - pink.parse ( "pink"); - attrs.set_background ( pink); - attrs.set_icon_name ( "process-stop"); - attrs.query_tooltip_text.connect(( mark) => { - GLib.debug("tooltip query? %s", mark.name); - return strdup( mark.name); - }); - attrs.query_tooltip_markup.connect(( mark) => { - GLib.debug("tooltip query? %s", mark.name); - return strdup( mark.name); - }); - this.el.set_mark_attributes ("ERR", attrs, 1); - attrs.ref(); - var wattrs = new GtkSource.MarkAttributes(); - var blue = Gdk.RGBA(); - blue.parse ( "#ABF4EB"); - wattrs.set_background ( blue); - wattrs.set_icon_name ( "process-stop"); - wattrs.query_tooltip_text.connect(( mark) => { - GLib.debug("tooltip query? %s", mark.name); - return strdup(mark.name); - }); - wattrs.query_tooltip_markup.connect(( mark) => { - GLib.debug("tooltip query? %s", mark.name); - return strdup(mark.name); - }); - this.el.set_mark_attributes ("WARN", wattrs, 1); - wattrs.ref(); - - - var dattrs = new GtkSource.MarkAttributes(); - var purple = Gdk.RGBA(); - purple.parse ( "#EEA9FF"); - dattrs.set_background ( purple); - dattrs.set_icon_name ( "process-stop"); - dattrs.query_tooltip_text.connect(( mark) => { - GLib.debug("tooltip query? %s", mark.name); - return strdup(mark.name); - }); - dattrs.query_tooltip_markup.connect(( mark) => { - GLib.debug("tooltip query? %s", mark.name); - return strdup(mark.name); - }); - this.el.set_mark_attributes ("DEPR", dattrs, 1); - dattrs.ref(); - - this.el.get_space_drawer().set_matrix(null); - this.el.get_space_drawer().set_types_for_locations( - GtkSource.SpaceLocationFlags.ALL, - GtkSource.SpaceTypeFlags.ALL - ); - this.el.get_space_drawer().set_enable_matrix(true); - /* - Gtk.SourceDrawSpacesFlags.LEADING + - Gtk.SourceDrawSpacesFlags.TRAILING + - Gtk.SourceDrawSpacesFlags.TAB + - Gtk.SourceDrawSpacesFlags.SPACE - */ - - //listeners - this.el.query_tooltip.connect( (x, y, keyboard_tooltip, tooltip) => { - - //GLib.debug("query tooltip"); - Gtk.TextIter iter; - int trailing; - - var yoff = (int) _this.RightEditor.el.vadjustment.value; - - // I think this is problematic - if it's compliing / updating at same time as query. - - //if (_this.window.statusbar_compile_spinner.el.spinning) { - // return false; - //} - - this.el.get_iter_at_position (out iter, out trailing, x, y + yoff); - - var l = iter.get_line(); - - - - // GLib.debug("query tooltip line %d", (int) l); - if (l < 0) { - - return false; - } - /* - if (_this.buffer.marks != null && _this.buffer.marks.has_key(l)) { - GLib.debug("line %d setting tip to %s", l, _this.buffer.marks.get(l)); - tooltip.set_text(_this.buffer.marks.get(l).dup()); - return true; - } - - return false; - */ - - - // this crashes?? - not sure why. - var marks = _this.buffer.el.get_source_marks_at_line(l, "ERR"); - if (marks.is_empty()) { - marks = _this.buffer.el.get_source_marks_at_line(l, "WARN"); - } - if (marks.is_empty()) { - marks = _this.buffer.el.get_source_marks_at_line(l, "DEPR"); - } - - // GLib.debug("query tooltip line %d marks %d", (int)l, (int) marks.length()); - var str = ""; - marks.@foreach((m) => { - //GLib.debug("got mark %s", m.name); - str += (str.length > 0 ? "\n" : "") + m.category + ": " + m.name; - }); - // true if there is a mark.. - if (str.length > 0 ) { - tooltip.set_text( str ); - } - return str.length > 0 ? true : false; - - }); - } + // user defined functions + } + public class Xcls_view : Object + { + public GtkSource.View el; + private Editor _this; - // user defined functions - public void load (string str) { - - // show the help page for the active node.. - //this.get('/Help').show(); - - // this.get('/BottomPane').el.set_current_page(0); - GLib.debug("load called - Reset undo buffer"); - - var buf = (GtkSource.Buffer)this.el.get_buffer(); - buf.begin_irreversible_action(); - buf.set_text(str, str.length); - buf.end_irreversible_action(); - - var lm = GtkSource.LanguageManager.get_default(); - var lang = "vala"; - if (_this.file != null) { - lang = _this.file.language; - } - print("lang=%s, content_type = %s\n", lang, _this.file.content_type); - var lg = _this.file.content_type.length > 0 ? - lm.guess_language(_this.file.path, _this.file.content_type) : - lm.get_language(lang); - - - ((GtkSource.Buffer)(this.el.get_buffer())) .set_language(lg); - - this.el.insert_spaces_instead_of_tabs = true; - if (lg != null) { - print("sourcelanguage = %s\n", lg.name); - if (lg.name == "Vala") { - this.el.insert_spaces_instead_of_tabs = false; - } - } - _this.dirty = false; - this.el.grab_focus(); - _this.save_button.el.sensitive = false; - } - } - public class Xcls_buffer : Object + + // my vars (def) + public Gtk.CssProvider css; + + // ctor + public Xcls_view(Editor _owner ) { - public GtkSource.Buffer el; - private Editor _this; + _this = _owner; + _this.view = this; + this.el = new GtkSource.View(); + // my vars (dec) + this.css = null; - // my vars (def) - public int error_line; - public Gee.HashMap? xmarks; - public bool check_queued; + // set gobject values + this.el.auto_indent = true; + this.el.indent_width = 4; + this.el.name = "editor-view"; + this.el.show_line_marks = true; + this.el.insert_spaces_instead_of_tabs = true; + this.el.show_line_numbers = true; + this.el.hexpand = true; + this.el.vexpand = true; + this.el.has_tooltip = true; + this.el.tab_width = 4; + this.el.highlight_current_line = true; + var child_1 = new Xcls_buffer( _this ); + child_1.ref(); + this.el.buffer = child_1.el; + var child_2 = new Xcls_EventControllerKey11( _this ); + child_2.ref(); + this.el.add_controller( child_2.el ); - // ctor - public Xcls_buffer(Editor _owner ) - { - _this = _owner; - _this.buffer = this; - this.el = new GtkSource.Buffer( null ); - - // my vars (dec) - this.error_line = -1; - this.xmarks = null; - this.check_queued = false; - - // set gobject values - this.el.enable_undo = true; - - //listeners - this.el.changed.connect( () => { - // check syntax?? - // ??needed..?? - _this.save_button.el.sensitive = true; - print("EDITOR CHANGED"); - this.checkSyntax(); - - _this.dirty = true; - - // this.get('/LeftPanel.model').changed( str , false); - return ; - }); - } + // init method - // user defined functions - public bool checkSyntax () { - - - var str = this.toString(); - - // needed??? - if (this.error_line > 0) { - Gtk.TextIter start; - Gtk.TextIter end; - this.el.get_bounds (out start, out end); + this.css = new Gtk.CssProvider(); - this.el.remove_source_marks (start, end, null); - } - if (str.length < 1) { - print("checkSyntax - empty string?\n"); - return true; - } - - // bit presumptiona - if (_this.file.xtype == "PlainFile" && _this.file.project.xtype == "Gtk") { - - // assume it's gtk... - - BuilderApplication.valacompilequeue.addFile( - Palete.ValaCompileRequestType.FILE_CHANGE, - _this.file , str, false) ; + this.css.load_from_string( + "#editor-view { font: 12px monospace;}" + ); + + Gtk.StyleContext.add_provider_for_display( + this.el.get_display(), + this.css, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + ); + + + + /* + this is pretty flakey - triggers Gtk with < 0 d + var cp = new GtkSource.CompletionWords("test"); + cp.minimum_word_size = 3; + //cp.priority = 100; //?? does this do anything + cp.proposals_batch_size = 10; + cp.scan_batch_size = 1000; + + cp.register(_this.buffer.el); + this.el.completion.add_provider(cp); + */ + this.el.completion.add_provider(new Palete.CompletionProvider(_this)); + //this.el.completion.unblock_interactive(); + this.el.completion.select_on_show = true; // select + //this.el.completion.remember_info_visibility = true; - return true; - - } - if (_this.file == null) { - return true; - } - - - - - GLib.debug("calling validate"); - // clear the buttons. - - BuilderApplication.valacompilequeue.addProp( - Palete.ValaCompileRequestType.PROP_CHANGE, - _this.file, - _this.node, - _this.prop, - str); - - - - //print("done mark line\n"); - - return true; // at present allow saving - even if it's invalid.. - } - public bool highlightErrorsJson (string type, Json.Object obj) { - Gtk.TextIter start; - Gtk.TextIter end; - this.el.get_bounds (out start, out end); + var attrs = new GtkSource.MarkAttributes(); + var pink = Gdk.RGBA(); + pink.parse ( "pink"); + attrs.set_background ( pink); + attrs.set_icon_name ( "process-stop"); + attrs.query_tooltip_text.connect(( mark) => { + GLib.debug("tooltip query? %s", mark.name); + return strdup( mark.name); + }); + attrs.query_tooltip_markup.connect(( mark) => { + GLib.debug("tooltip query? %s", mark.name); + return strdup( mark.name); + }); + this.el.set_mark_attributes ("ERR", attrs, 1); + attrs.ref(); + var wattrs = new GtkSource.MarkAttributes(); + var blue = Gdk.RGBA(); + blue.parse ( "#ABF4EB"); + wattrs.set_background ( blue); + wattrs.set_icon_name ( "process-stop"); + wattrs.query_tooltip_text.connect(( mark) => { + GLib.debug("tooltip query? %s", mark.name); + return strdup(mark.name); + }); + wattrs.query_tooltip_markup.connect(( mark) => { + GLib.debug("tooltip query? %s", mark.name); + return strdup(mark.name); + }); + this.el.set_mark_attributes ("WARN", wattrs, 1); + wattrs.ref(); - this.el.remove_source_marks (start, end, type); - GLib.debug("highlight errors"); - // we should highlight other types of errors.. + var dattrs = new GtkSource.MarkAttributes(); + var purple = Gdk.RGBA(); + purple.parse ( "#EEA9FF"); + dattrs.set_background ( purple); + dattrs.set_icon_name ( "process-stop"); + dattrs.query_tooltip_text.connect(( mark) => { + GLib.debug("tooltip query? %s", mark.name); + return strdup(mark.name); + }); + dattrs.query_tooltip_markup.connect(( mark) => { + GLib.debug("tooltip query? %s", mark.name); + return strdup(mark.name); + }); + this.el.set_mark_attributes ("DEPR", dattrs, 1); + dattrs.ref(); - if (!obj.has_member(type)) { - GLib.debug("Return has no errors\n"); - return true; - } + this.el.get_space_drawer().set_matrix(null); + this.el.get_space_drawer().set_types_for_locations( + GtkSource.SpaceLocationFlags.ALL, + GtkSource.SpaceTypeFlags.ALL + ); + this.el.get_space_drawer().set_enable_matrix(true); + /* + Gtk.SourceDrawSpacesFlags.LEADING + + Gtk.SourceDrawSpacesFlags.TRAILING + + Gtk.SourceDrawSpacesFlags.TAB + + Gtk.SourceDrawSpacesFlags.SPACE + */ + + //listeners + this.el.query_tooltip.connect( (x, y, keyboard_tooltip, tooltip) => { + + //GLib.debug("query tooltip"); + Gtk.TextIter iter; + int trailing; + + var yoff = (int) _this.RightEditor.el.vadjustment.value; + + // I think this is problematic - if it's compliing / updating at same time as query. + + //if (_this.window.statusbar_compile_spinner.el.spinning) { + // return false; + //} + + this.el.get_iter_at_position (out iter, out trailing, x, y + yoff); + + var l = iter.get_line(); - if (_this.window.windowstate.state != WindowState.State.CODEONLY - && - _this.window.windowstate.state != WindowState.State.CODE - ) { - GLib.debug("windowstate != CODEONLY?"); - - return true; - } + + + // GLib.debug("query tooltip line %d", (int) l); + if (l < 0) { - //this.marks = new Gee.HashMap(); - var err = obj.get_object_member(type); - - if (_this.file == null) { - GLib.debug("file is null?"); + return false; + } + /* + if (_this.buffer.marks != null && _this.buffer.marks.has_key(l)) { + GLib.debug("line %d setting tip to %s", l, _this.buffer.marks.get(l)); + tooltip.set_text(_this.buffer.marks.get(l).dup()); return true; - } - var valafn = _this.file.path; - - if (_this.file.xtype != "PlainFile") { - - valafn = ""; - try { - var regex = new Regex("\\.bjs$"); - // should not happen - valafn = regex.replace(_this.file.path,_this.file.path.length , 0 , ".vala"); - } catch (GLib.RegexError e) { - return true; - } - - - + + return false; + */ + + + // this crashes?? - not sure why. + var marks = _this.buffer.el.get_source_marks_at_line(l, "ERR"); + if (marks.is_empty()) { + marks = _this.buffer.el.get_source_marks_at_line(l, "WARN"); } - if (!err.has_member(valafn)) { - GLib.debug("File path has no errors"); - return true; + if (marks.is_empty()) { + marks = _this.buffer.el.get_source_marks_at_line(l, "DEPR"); } - - var lines = err.get_object_member(valafn); - var offset = 1; - if (obj.has_member("line_offset")) { // ?? why?? - offset = (int)obj.get_int_member("line_offset") + 1; + // GLib.debug("query tooltip line %d marks %d", (int)l, (int) marks.length()); + var str = ""; + marks.@foreach((m) => { + //GLib.debug("got mark %s", m.name); + str += (str.length > 0 ? "\n" : "") + m.category + ": " + m.name; + }); + // true if there is a mark.. + if (str.length > 0 ) { + tooltip.set_text( str ); } + return str.length > 0 ? true : false; + + }); + } + + // user defined functions + public void load (string str) { + + // show the help page for the active node.. + //this.get('/Help').show(); + + // this.get('/BottomPane').el.set_current_page(0); + GLib.debug("load called - Reset undo buffer"); + + var buf = (GtkSource.Buffer)this.el.get_buffer(); + buf.begin_irreversible_action(); + buf.set_text(str, str.length); + buf.end_irreversible_action(); + + var lm = GtkSource.LanguageManager.get_default(); + var lang = "vala"; + if (_this.file != null) { + lang = _this.file.language; + } + print("lang=%s, content_type = %s\n", lang, _this.file.content_type); + var lg = _this.file.content_type.length > 0 ? + lm.guess_language(_this.file.path, _this.file.content_type) : + lm.get_language(lang); + + + ((GtkSource.Buffer)(this.el.get_buffer())) .set_language(lg); + + this.el.insert_spaces_instead_of_tabs = true; + if (lg != null) { + print("sourcelanguage = %s\n", lg.name); + if (lg.name == "Vala") { + this.el.insert_spaces_instead_of_tabs = false; + } + } + _this.dirty = false; + this.el.grab_focus(); + _this.save_button.el.sensitive = false; + } + } + public class Xcls_buffer : Object + { + public GtkSource.Buffer el; + private Editor _this; + + + // my vars (def) + public int error_line; + public Gee.HashMap? xmarks; + public bool check_queued; + + // ctor + public Xcls_buffer(Editor _owner ) + { + _this = _owner; + _this.buffer = this; + this.el = new GtkSource.Buffer( null ); + + // my vars (dec) + this.error_line = -1; + this.xmarks = null; + this.check_queued = false; + + // set gobject values + this.el.enable_undo = true; + + //listeners + this.el.changed.connect( () => { + // check syntax?? + // ??needed..?? + _this.save_button.el.sensitive = true; + print("EDITOR CHANGED"); + this.checkSyntax(); + + _this.dirty = true; + // this.get('/LeftPanel.model').changed( str , false); + return ; + }); + } + + // user defined functions + public bool checkSyntax () { + - var tlines = this.el.get_line_count () +1; - - if (_this.prop != null) { - - tlines = _this.prop.end_line + 1; - offset = _this.prop.start_line + 1; - - } - + var str = this.toString(); + // needed??? + if (this.error_line > 0) { + Gtk.TextIter start; + Gtk.TextIter end; + this.el.get_bounds (out start, out end); + + this.el.remove_source_marks (start, end, null); + } + if (str.length < 1) { + print("checkSyntax - empty string?\n"); + return true; + } - lines.foreach_member((obj, line, node) => { - - Gtk.TextIter iter; - // print("get inter\n"); - var eline = int.parse(line) - offset; - GLib.debug("GOT ERROR on line %s -- converted to %d (offset = %d)\n", line,eline, offset); - - - if (eline > tlines || eline < 0) { - return; - } - - - this.el.get_iter_at_line( out iter, eline); - //print("mark line\n"); - var msg = ""; - var ar = lines.get_array_member(line); - for (var i = 0 ; i < ar.get_length(); i++) { - if (ar.get_string_element(i) == "Success") { - continue; - } - msg += (msg.length > 0) ? "\n" : ""; - msg += ar.get_string_element(i); - } - if (msg == "") { - return; - } - msg = "Line: %d".printf(eline+1) + " " + msg; - this.el.create_source_mark(msg, type, iter); - GLib.debug("set line %d to %m", eline, msg); - // this.marks.set(eline, msg); - } ); - return false; + // bit presumptiona + if (_this.file.xtype == "PlainFile") { + // assume it's gtk... + var oldcode =_this.file.toSource(); + _this.file.setSource(str); + _this.file.getLanguageServer().document_change(_this.file); + _this.file.setSource(oldcode); + + + return true; + } + if (_this.file == null) { + return true; + } + + + + + GLib.debug("calling validate"); + // clear the buttons. + if (_this.prop.name == "xns" || _this.prop.name == "xtype") { + return true ; + } + var oldcode = _this.prop.val; + + _this.prop.val = str; + _this.file.getLanguageServer().document_change(_this.file); + _this.prop.val = oldcode; + + + //print("done mark line\n"); + + return true; // at present allow saving - even if it's invalid.. + } + public bool highlightErrorsJson (string type, Json.Object obj) { + Gtk.TextIter start; + Gtk.TextIter end; + this.el.get_bounds (out start, out end); + + this.el.remove_source_marks (start, end, type); + GLib.debug("highlight errors"); + + // we should highlight other types of errors.. + + if (!obj.has_member(type)) { + GLib.debug("Return has no errors\n"); + return true; + } + + if (_this.window.windowstate.state != WindowState.State.CODEONLY + && + _this.window.windowstate.state != WindowState.State.CODE + ) { + GLib.debug("windowstate != CODEONLY?"); + + return true; + } + + //this.marks = new Gee.HashMap(); + var err = obj.get_object_member(type); + + if (_this.file == null) { + GLib.debug("file is null?"); + return true; + + } + var valafn = _this.file.path; + + if (_this.file.xtype != "PlainFile") { + + valafn = ""; + try { + var regex = new Regex("\\.bjs$"); + // should not happen + valafn = regex.replace(_this.file.path,_this.file.path.length , 0 , ".vala"); + } catch (GLib.RegexError e) { + return true; + } + + + + } + if (!err.has_member(valafn)) { + GLib.debug("File path has no errors"); + return true; + } + + var lines = err.get_object_member(valafn); + + var offset = 1; + if (obj.has_member("line_offset")) { // ?? why?? + offset = (int)obj.get_int_member("line_offset") + 1; + } + + + var tlines = this.el.get_line_count () +1; + + if (_this.prop != null) { + + tlines = _this.prop.end_line + 1; + offset = _this.prop.start_line + 1; + + } + + + + lines.foreach_member((obj, line, node) => { + + Gtk.TextIter iter; + // print("get inter\n"); + var eline = int.parse(line) - offset; + GLib.debug("GOT ERROR on line %s -- converted to %d (offset = %d)\n", line,eline, offset); + + + if (eline > tlines || eline < 0) { + return; + } + + + this.el.get_iter_at_line( out iter, eline); + //print("mark line\n"); + var msg = ""; + var ar = lines.get_array_member(line); + for (var i = 0 ; i < ar.get_length(); i++) { + if (ar.get_string_element(i) == "Success") { + continue; + } + msg += (msg.length > 0) ? "\n" : ""; + msg += ar.get_string_element(i); + } + if (msg == "") { + return; + } + msg = "Line: %d".printf(eline+1) + " " + msg; + this.el.create_source_mark(msg, type, iter); + GLib.debug("set line %d to %m", eline, msg); + // this.marks.set(eline, msg); + } ); + return false; + + + + + + } + public bool highlightErrors ( Gee.HashMap validate_res) { + + this.error_line = validate_res.size; + + if (this.error_line < 1) { + return true; + } + var tlines = this.el.get_line_count (); + Gtk.TextIter iter; + var valiter = validate_res.map_iterator(); + while (valiter.next()) { + + // print("get inter\n"); + var eline = valiter.get_key(); + if (eline > tlines) { + continue; + } + this.el.get_iter_at_line( out iter, eline); + //print("mark line\n"); + this.el.create_source_mark(valiter.get_value(), "ERR", iter); + } + return false; + } + public string toString () { + Gtk.TextIter s; + Gtk.TextIter e; + this.el.get_start_iter(out s); + this.el.get_end_iter(out e); + var ret = this.el.get_text(s,e,true); + //print("TO STRING? " + ret); + return ret; + } + } + + public class Xcls_EventControllerKey11 : Object + { + public Gtk.EventControllerKey el; + private Editor _this; + + + // my vars (def) + + // ctor + public Xcls_EventControllerKey11(Editor _owner ) + { + _this = _owner; + this.el = new Gtk.EventControllerKey(); + + // my vars (dec) + + // set gobject values + + //listeners + this.el.key_released.connect( (keyval, keycode, state) => { + + if (keyval == Gdk.Key.s && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) { + GLib.debug("SAVE: ctrl-S pressed"); + _this.saveContents(); + return; + } + + if (keyval == Gdk.Key.g && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) { + GLib.debug("SAVE: ctrl-g pressed"); + _this.forwardSearch(true); + return; } - public bool highlightErrors ( Gee.HashMap validate_res) { - - this.error_line = validate_res.size; - - if (this.error_line < 1) { - return true; + if (keyval == Gdk.Key.f && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) { + GLib.debug("SAVE: ctrl-f pressed"); + _this.search_entry.el.grab_focus(); + return; } - var tlines = this.el.get_line_count (); - Gtk.TextIter iter; - var valiter = validate_res.map_iterator(); - while (valiter.next()) { - - // print("get inter\n"); - var eline = valiter.get_key(); - if (eline > tlines) { - continue; - } - this.el.get_iter_at_line( out iter, eline); - //print("mark line\n"); - this.el.create_source_mark(valiter.get_value(), "ERR", iter); - } - return false; - } - public string toString () { + //_this.view.el.show_completion(); + // print(event.key.keyval) - Gtk.TextIter s; - Gtk.TextIter e; - this.el.get_start_iter(out s); - this.el.get_end_iter(out e); - var ret = this.el.get_text(s,e,true); - //print("TO STRING? " + ret); - return ret; - } + return; + + + }); } - public class Xcls_EventControllerKey11 : Object - { - public Gtk.EventControllerKey el; - private Editor _this; + // user defined functions + } - // my vars (def) - // ctor - public Xcls_EventControllerKey11(Editor _owner ) - { - _this = _owner; - this.el = new Gtk.EventControllerKey(); + public class Xcls_Box12 : Object + { + public Gtk.Box el; + private Editor _this; - // my vars (dec) - // set gobject values + // my vars (def) - //listeners - this.el.key_released.connect( (keyval, keycode, state) => { - - - if (keyval == Gdk.Key.s && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) { - GLib.debug("SAVE: ctrl-S pressed"); - _this.saveContents(); - return; - } - - if (keyval == Gdk.Key.g && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) { - GLib.debug("SAVE: ctrl-g pressed"); - _this.forwardSearch(true); - return; - } - if (keyval == Gdk.Key.f && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) { - GLib.debug("SAVE: ctrl-f pressed"); - _this.search_entry.el.grab_focus(); - return; - } - - // print(event.key.keyval) - - return; - - - }); - } + // ctor + public Xcls_Box12(Editor _owner ) + { + _this = _owner; + this.el = new Gtk.Box( Gtk.Orientation.HORIZONTAL, 0 ); + + // my vars (dec) - // user defined functions + // set gobject values + this.el.homogeneous = false; + this.el.vexpand = false; + var child_1 = new Xcls_search_entry( _this ); + child_1.ref(); + this.el.append( child_1.el ); + var child_2 = new Xcls_search_results( _this ); + child_2.ref(); + this.el.append( child_2.el ); + var child_3 = new Xcls_nextBtn( _this ); + child_3.ref(); + this.el.append( child_3.el ); + var child_4 = new Xcls_backBtn( _this ); + child_4.ref(); + this.el.append( child_4.el ); + var child_5 = new Xcls_MenuButton18( _this ); + child_5.ref(); + this.el.append( child_5.el ); } + // user defined functions + } + public class Xcls_search_entry : Object + { + public Gtk.SearchEntry el; + private Editor _this; + + // my vars (def) + public Gtk.CssProvider css; - public class Xcls_Box12 : Object + // ctor + public Xcls_search_entry(Editor _owner ) { - public Gtk.Box el; - private Editor _this; + _this = _owner; + _this.search_entry = this; + this.el = new Gtk.SearchEntry(); + // my vars (dec) - // my vars (def) + // set gobject values + this.el.name = "editor-search-entry"; + this.el.hexpand = true; + this.el.placeholder_text = "Press enter to search"; + this.el.search_delay = 3; + var child_1 = new Xcls_EventControllerKey14( _this ); + child_1.ref(); + this.el.add_controller( child_1.el ); - // ctor - public Xcls_Box12(Editor _owner ) - { - _this = _owner; - this.el = new Gtk.Box( Gtk.Orientation.HORIZONTAL, 0 ); - - // my vars (dec) - - // set gobject values - this.el.homogeneous = false; - this.el.vexpand = false; - new Xcls_search_entry( _this ); - this.el.append( _this.search_entry.el ); - new Xcls_search_results( _this ); - this.el.append( _this.search_results.el ); - new Xcls_nextBtn( _this ); - this.el.append( _this.nextBtn.el ); - new Xcls_backBtn( _this ); - this.el.append( _this.backBtn.el ); - var child_5 = new Xcls_MenuButton18( _this ); - child_5.ref(); - this.el.append( child_5.el ); - } + //listeners + this.el.search_changed.connect( ( ) => { + + _this.search(_this.search_entry.el.text); + _this.search_results.updateResults(); + + GLib.Timeout.add_seconds(1,() => { + _this.search_results.updateResults(); + return false; + }); + }); + } - // user defined functions + // user defined functions + public void forwardSearch (bool change_focus) { + + + _this.forwardSearch(change_focus); + + /* + + switch(_this.windowstate.state) { + case WindowState.State.CODEONLY: + //case WindowState.State.CODE: + // search the code being edited.. + _this.windowstate.code_editor_tab.forwardSearch(change_focus); + + break; + case WindowState.State.PREVIEW: + if (_this.windowstate.file.xtype == "Gtk") { + _this.windowstate.window_gladeview.forwardSearch(change_focus); + } else { + _this.windowstate.window_rooview.forwardSearch(change_focus); + } + + break; + } + */ + } - public class Xcls_search_entry : Object - { - public Gtk.SearchEntry el; - private Editor _this; + } + public class Xcls_EventControllerKey14 : Object + { + public Gtk.EventControllerKey el; + private Editor _this; - // my vars (def) - public Gtk.CssProvider css; + // my vars (def) - // ctor - public Xcls_search_entry(Editor _owner ) - { - _this = _owner; - _this.search_entry = this; - this.el = new Gtk.SearchEntry(); - - // my vars (dec) - - // set gobject values - this.el.name = "editor-search-entry"; - this.el.hexpand = true; - this.el.placeholder_text = "Press enter to search"; - this.el.search_delay = 3; - var child_1 = new Xcls_EventControllerKey14( _this ); - child_1.ref(); - this.el.add_controller( child_1.el ); - - //listeners - this.el.search_changed.connect( ( ) => { - - _this.search(_this.search_entry.el.text); - _this.search_results.updateResults(); - - GLib.Timeout.add_seconds(1,() => { - _this.search_results.updateResults(); - return false; - }); - }); - } + // ctor + public Xcls_EventControllerKey14(Editor _owner ) + { + _this = _owner; + this.el = new Gtk.EventControllerKey(); - // user defined functions - public void forwardSearch (bool change_focus) { - - - _this.forwardSearch(change_focus); - - /* + // my vars (dec) + + // set gobject values + + //listeners + this.el.key_pressed.connect( (keyval, keycode, state) => { - switch(_this.windowstate.state) { - case WindowState.State.CODEONLY: - //case WindowState.State.CODE: - // search the code being edited.. - _this.windowstate.code_editor_tab.forwardSearch(change_focus); - - break; - case WindowState.State.PREVIEW: - if (_this.windowstate.file.xtype == "Gtk") { - _this.windowstate.window_gladeview.forwardSearch(change_focus); - } else { - _this.windowstate.window_rooview.forwardSearch(change_focus); - } - - break; + if (keyval == Gdk.Key.g && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) { + GLib.debug("SAVE: ctrl-g pressed"); + _this.forwardSearch(true); + return true; } - */ - - } + + + if (keyval == Gdk.Key.Return && _this.search_entry.el.text.length > 0) { + _this.forwardSearch(true); + + + return true; + + } + // print(event.key.keyval) + + return false; + }); } - public class Xcls_EventControllerKey14 : Object - { - public Gtk.EventControllerKey el; - private Editor _this; + // user defined functions + } - // my vars (def) - // ctor - public Xcls_EventControllerKey14(Editor _owner ) - { - _this = _owner; - this.el = new Gtk.EventControllerKey(); + public class Xcls_search_results : Object + { + public Gtk.Label el; + private Editor _this; - // my vars (dec) - // set gobject values + // my vars (def) - //listeners - this.el.key_pressed.connect( (keyval, keycode, state) => { - - if (keyval == Gdk.Key.g && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) { - GLib.debug("SAVE: ctrl-g pressed"); - _this.forwardSearch(true); - return true; - } - - - if (keyval == Gdk.Key.Return && _this.search_entry.el.text.length > 0) { - _this.forwardSearch(true); - - - return true; - - } - // print(event.key.keyval) - - return false; - }); - } + // ctor + public Xcls_search_results(Editor _owner ) + { + _this = _owner; + _this.search_results = this; + this.el = new Gtk.Label( "No Results" ); + + // my vars (dec) - // user defined functions + // set gobject values + this.el.margin_end = 4; + this.el.margin_start = 4; } + // user defined functions + public void updateResults () { + this.el.visible = true; + + var res = _this.searchcontext.get_occurrences_count(); + if (res < 0) { + _this.search_results.el.label = "??? Matches"; + return; + } + + _this.nextBtn.el.sensitive = false; + _this.backBtn.el.sensitive = false; + + if (res > 0) { + _this.search_results.el.label = "%d Matches".printf(res); + _this.nextBtn.el.sensitive = true; + _this.backBtn.el.sensitive = true; + return; + } + _this.search_results.el.label = "No Matches"; + + } + } - public class Xcls_search_results : Object - { - public Gtk.Label el; - private Editor _this; + public class Xcls_nextBtn : Object + { + public Gtk.Button el; + private Editor _this; - // my vars (def) + // my vars (def) + public bool always_show_image; - // ctor - public Xcls_search_results(Editor _owner ) - { - _this = _owner; - _this.search_results = this; - this.el = new Gtk.Label( "No Results" ); + // ctor + public Xcls_nextBtn(Editor _owner ) + { + _this = _owner; + _this.nextBtn = this; + this.el = new Gtk.Button(); - // my vars (dec) + // my vars (dec) + this.always_show_image = true; - // set gobject values - this.el.margin_end = 4; - this.el.margin_start = 4; - } + // set gobject values + this.el.icon_name = "go-down"; + this.el.sensitive = false; - // user defined functions - public void updateResults () { - this.el.visible = true; - - var res = _this.searchcontext.get_occurrences_count(); - if (res < 0) { - _this.search_results.el.label = "??? Matches"; - return; - } + //listeners + this.el.clicked.connect( (event) => { - _this.nextBtn.el.sensitive = false; - _this.backBtn.el.sensitive = false; - - if (res > 0) { - _this.search_results.el.label = "%d Matches".printf(res); - _this.nextBtn.el.sensitive = true; - _this.backBtn.el.sensitive = true; - return; - } - _this.search_results.el.label = "No Matches"; + _this.forwardSearch(true); - } + + }); } - public class Xcls_nextBtn : Object - { - public Gtk.Button el; - private Editor _this; + // user defined functions + } + public class Xcls_backBtn : Object + { + public Gtk.Button el; + private Editor _this; - // my vars (def) - public bool always_show_image; - // ctor - public Xcls_nextBtn(Editor _owner ) - { - _this = _owner; - _this.nextBtn = this; - this.el = new Gtk.Button(); + // my vars (def) + public bool always_show_image; - // my vars (dec) - this.always_show_image = true; + // ctor + public Xcls_backBtn(Editor _owner ) + { + _this = _owner; + _this.backBtn = this; + this.el = new Gtk.Button(); - // set gobject values - this.el.icon_name = "go-down"; - this.el.sensitive = false; + // my vars (dec) + this.always_show_image = true; - //listeners - this.el.clicked.connect( (event) => { - - _this.forwardSearch(true); - - - }); - } + // set gobject values + this.el.icon_name = "go-up"; + this.el.sensitive = false; - // user defined functions + //listeners + this.el.clicked.connect( (event) => { + + _this.backSearch(true); + + }); } - public class Xcls_backBtn : Object - { - public Gtk.Button el; - private Editor _this; - + // user defined functions + } - // my vars (def) - public bool always_show_image; + public class Xcls_MenuButton18 : Object + { + public Gtk.MenuButton el; + private Editor _this; - // ctor - public Xcls_backBtn(Editor _owner ) - { - _this = _owner; - _this.backBtn = this; - this.el = new Gtk.Button(); - // my vars (dec) - this.always_show_image = true; + // my vars (def) + public bool always_show_image; - // set gobject values - this.el.icon_name = "go-up"; - this.el.sensitive = false; + // ctor + public Xcls_MenuButton18(Editor _owner ) + { + _this = _owner; + this.el = new Gtk.MenuButton(); - //listeners - this.el.clicked.connect( (event) => { - - _this.backSearch(true); - - }); - } + // my vars (dec) + this.always_show_image = true; - // user defined functions + // set gobject values + this.el.icon_name = "emblem-system"; + this.el.always_show_arrow = true; + var child_1 = new Xcls_search_settings( _this ); + child_1.ref(); + this.el.popover = child_1.el; } - public class Xcls_MenuButton18 : Object - { - public Gtk.MenuButton el; - private Editor _this; - + // user defined functions + } + public class Xcls_search_settings : Object + { + public Gtk.Popover el; + private Editor _this; - // my vars (def) - public bool always_show_image; - // ctor - public Xcls_MenuButton18(Editor _owner ) - { - _this = _owner; - this.el = new Gtk.MenuButton(); + // my vars (def) - // my vars (dec) - this.always_show_image = true; + // ctor + public Xcls_search_settings(Editor _owner ) + { + _this = _owner; + _this.search_settings = this; + this.el = new Gtk.Popover(); - // set gobject values - this.el.icon_name = "emblem-system"; - this.el.always_show_arrow = true; - new Xcls_search_settings( _this ); - this.el.popover = _this.search_settings.el; - } + // my vars (dec) - // user defined functions + // set gobject values + var child_1 = new Xcls_Box20( _this ); + child_1.ref(); + this.el.child = child_1.el; } - public class Xcls_search_settings : Object - { - public Gtk.Popover el; - private Editor _this; + // user defined functions + } + public class Xcls_Box20 : Object + { + public Gtk.Box el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_search_settings(Editor _owner ) - { - _this = _owner; - _this.search_settings = this; - this.el = new Gtk.Popover(); + // my vars (def) - // my vars (dec) + // ctor + public Xcls_Box20(Editor _owner ) + { + _this = _owner; + this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 ); - // set gobject values - var child_1 = new Xcls_Box20( _this ); - this.el.child = child_1.el; - } + // my vars (dec) - // user defined functions + // set gobject values + var child_1 = new Xcls_case_sensitive( _this ); + child_1.ref(); + this.el.append( child_1.el ); + var child_2 = new Xcls_regex( _this ); + child_2.ref(); + this.el.append( child_2.el ); + var child_3 = new Xcls_multiline( _this ); + child_3.ref(); + this.el.append( child_3.el ); } - public class Xcls_Box20 : Object - { - public Gtk.Box el; - private Editor _this; + // user defined functions + } + public class Xcls_case_sensitive : Object + { + public Gtk.CheckButton el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_Box20(Editor _owner ) - { - _this = _owner; - this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 ); - - // my vars (dec) - - // set gobject values - new Xcls_case_sensitive( _this ); - this.el.append( _this.case_sensitive.el ); - new Xcls_regex( _this ); - this.el.append( _this.regex.el ); - new Xcls_multiline( _this ); - this.el.append( _this.multiline.el ); - } + // my vars (def) - // user defined functions - } - public class Xcls_case_sensitive : Object + // ctor + public Xcls_case_sensitive(Editor _owner ) { - public Gtk.CheckButton el; - private Editor _this; + _this = _owner; + _this.case_sensitive = this; + this.el = new Gtk.CheckButton(); + // my vars (dec) - // my vars (def) - - // ctor - public Xcls_case_sensitive(Editor _owner ) - { - _this = _owner; - _this.case_sensitive = this; - this.el = new Gtk.CheckButton(); - - // my vars (dec) - - // set gobject values - this.el.label = "Case Sensitive"; + // set gobject values + this.el.label = "Case Sensitive"; - // init method + // init method - { - this.el.show(); - } + { + this.el.show(); } - - // user defined functions } - public class Xcls_regex : Object - { - public Gtk.CheckButton el; - private Editor _this; + // user defined functions + } + public class Xcls_regex : Object + { + public Gtk.CheckButton el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_regex(Editor _owner ) - { - _this = _owner; - _this.regex = this; - this.el = new Gtk.CheckButton(); + // my vars (def) - // my vars (dec) + // ctor + public Xcls_regex(Editor _owner ) + { + _this = _owner; + _this.regex = this; + this.el = new Gtk.CheckButton(); + + // my vars (dec) - // set gobject values - this.el.label = "Regex"; + // set gobject values + this.el.label = "Regex"; - // init method + // init method - { - this.el.show(); - } + { + this.el.show(); } - - // user defined functions } - public class Xcls_multiline : Object - { - public Gtk.CheckButton el; - private Editor _this; + // user defined functions + } + public class Xcls_multiline : Object + { + public Gtk.CheckButton el; + private Editor _this; - // my vars (def) - // ctor - public Xcls_multiline(Editor _owner ) - { - _this = _owner; - _this.multiline = this; - this.el = new Gtk.CheckButton(); + // my vars (def) - // my vars (dec) + // ctor + public Xcls_multiline(Editor _owner ) + { + _this = _owner; + _this.multiline = this; + this.el = new Gtk.CheckButton(); - // set gobject values - this.el.label = "Multi-line (add \\n)"; - } + // my vars (dec) - // user defined functions + // set gobject values + this.el.label = "Multi-line (add \\n)"; } + // user defined functions + } - } + +} diff --git a/src/Builder4/FakeServer.vala b/src/Builder4/FakeServer.vala index 4739c61ef..b7cb9361b 100644 --- a/src/Builder4/FakeServer.vala +++ b/src/Builder4/FakeServer.vala @@ -194,14 +194,17 @@ public class FakeServerCache : Object public class FakeServer : Object { - WebKit.WebView view; + //WebKit.WebView view; + static WebKit.WebContext cx = null; public FakeServer(WebKit.WebView wkview) { - this.view = wkview; - + //this.view = wkview; + if (cx != null) { + return; + } - var cx = WebKit.WebContext.get_default(); + cx = WebKit.WebContext.get_default(); //var cx = this.view.get_context(); cx.register_uri_scheme("xhttp", serve); cx.register_uri_scheme("resources", serve); diff --git a/src/Builder4/GtkView.bjs b/src/Builder4/GtkView.bjs index 3e9a9751a..5d6304423 100644 --- a/src/Builder4/GtkView.bjs +++ b/src/Builder4/GtkView.bjs @@ -305,82 +305,6 @@ "}", "" ], - "| void highlightErrorsJson" : [ - " (string type, Json.Object obj) {", - " Gtk.TextIter start;", - " Gtk.TextIter end; ", - " ", - " var buf = this.el.get_buffer();", - " var sbuf = (GtkSource.Buffer)buf;", - " buf.get_bounds (out start, out end);", - " ", - " sbuf.remove_source_marks (start, end, type);", - " ", - " ", - " // we should highlight other types of errors..", - " ", - " if (!obj.has_member(type)) {", - " GLib.debug(\"Return has no errors\\n\");", - " return ;", - " }", - " var err = obj.get_object_member(type);", - " ", - " if (_this.file == null) { ", - "\t", - " return; // just in case the file has not loaded yet?", - " }", - " ", - "", - " var valafn = \"\";", - " try { ", - " var regex = new Regex(\"\\\\.bjs$\");", - " ", - " ", - " valafn = regex.replace(_this.file.path,_this.file.path.length , 0 , \".vala\");", - " } catch (GLib.RegexError e) {", - " return;", - " } ", - "", - " if (!err.has_member(valafn)) {", - " GLib.debug(\"File path has no errors\\n\");", - " return ;", - " }", - " var lines = err.get_object_member(valafn);", - " ", - " ", - " ", - " var tlines = buf.get_line_count () +1;", - " ", - " lines.foreach_member((obj, line, node) => {", - " ", - " Gtk.TextIter iter;", - " // print(\"get inter\\n\");", - " var eline = int.parse(line) -1 ;", - " GLib.debug(\"GOT ERROR on line %s -- converted to %d\\n\", line,eline);", - " ", - " ", - " if (eline > tlines || eline < 0) {", - " return;", - " }", - " sbuf.get_iter_at_line( out iter, eline);", - " //print(\"mark line\\n\");", - " var msg = type + \" on line: %d - %s\".printf(eline+1, valafn);", - " var ar = lines.get_array_member(line);", - " for (var i = 0 ; i < ar.get_length(); i++) {", - "\t\t msg += (msg.length > 0) ? \"\\n\" : \"\";", - "\t\t msg += ar.get_string_element(i);", - "\t }", - " ", - " ", - " sbuf.create_source_mark(msg, type, iter);", - " } );", - " return ;", - " ", - " ", - "", - "", - "}" - ], "| void loadFile" : [ "( ) {", " this.loading = true;", @@ -431,23 +355,10 @@ " ", " ((GtkSource.Buffer)(buf)) .set_language(lm.get_language(_this.file.language));", " ", - " ", - " Gtk.TextIter start;", - " Gtk.TextIter end; ", - " ", - " sbuf.get_bounds (out start, out end);", - " sbuf.remove_source_marks (start, end, null); // remove all marks..", - " ", - " ", - " if (_this.main_window.windowstate.last_compile_result != null) {", - " var obj = _this.main_window.windowstate.last_compile_result;", - " this.highlightErrorsJson(\"ERR\", obj);", - " this.highlightErrorsJson(\"WARN\", obj);", - " this.highlightErrorsJson(\"DEPR\", obj);\t\t\t", - " }", - " // while (Gtk.events_pending()) {", - " // Gtk.main_iteration();", - " // }", + " ", + " _this.main_window.windowstate.updateErrorMarksAll(); ", + " ", + " ", " ", " this.loading = false; ", "}", @@ -1048,6 +959,77 @@ " ", "}", "" + ], + "| void updateErrorMarks" : [ + "(string category) {", + "\t", + " ", + "", + "\tvar buf = _this.buffer.el;", + "\tGtk.TextIter start;", + "\tGtk.TextIter end; ", + "\tbuf.get_bounds (out start, out end);", + "", + "\tbuf.remove_source_marks (start, end, category);", + " ", + "\tGLib.debug(\"highlight errors\");\t\t ", + "", + "\t // we should highlight other types of errors..", + "", + " ", + "", + "\t ", + "\tif (_this.file == null) {", + "\t\tGLib.debug(\"file is null?\");", + "\t\treturn;", + "", + "\t}", + "\tvar ar = this.file.getErrors(category);", + "\tif (ar == null || ar.get_n_items() < 1) {", + "\t\tGLib.debug(\"higjlight %s has no errors\", category);", + "\t\treturn;", + "\t}", + " ", + "", + " ", + "\t", + "\tvar offset = 0;", + "\t ", + "", + "\tvar tlines = buf.get_line_count () +1;", + "\t", + " ", + "\t ", + "\tfor (var i = 0; i < ar.get_n_items();i++) {", + "\t\tvar err = (Palete.CompileError) ar.get_item(i);", + "\t\t", + "\t Gtk.TextIter iter;", + "// print(\"get inter\\n\");", + "\t var eline = err.line - offset;", + "\t GLib.debug(\"GOT ERROR on line %d -- converted to %d (offset = %d)\",", + "\t \terr.line ,eline, offset);", + "\t ", + "\t ", + "\t if (eline > tlines || eline < 0) {", + "\t return;", + "\t }", + "\t ", + "\t ", + "\t buf.get_iter_at_line( out iter, eline);", + "\t ", + "\t ", + "\t\tvar msg = \"Line: %d %s : %s\".printf(eline+1, err.category, err.msg);", + "\t buf.create_source_mark( msg, err.category, iter);", + "\t GLib.debug(\"set line %d to %s\", eline, msg);", + "\t //this.marks.set(eline, msg);", + "\t}", + "\treturn ;", + "", + "", + "", + " ", + "", + "}" ] } ], diff --git a/src/Builder4/GtkView.vala b/src/Builder4/GtkView.vala index ef0c8f3d7..830bd0178 100644 --- a/src/Builder4/GtkView.vala +++ b/src/Builder4/GtkView.vala @@ -327,6 +327,75 @@ + } + public void updateErrorMarks (string category) { + + + + var buf = _this.buffer.el; + Gtk.TextIter start; + Gtk.TextIter end; + buf.get_bounds (out start, out end); + + buf.remove_source_marks (start, end, category); + + GLib.debug("highlight errors"); + + // we should highlight other types of errors.. + + + + + if (_this.file == null) { + GLib.debug("file is null?"); + return; + + } + var ar = this.file.getErrors(category); + if (ar == null || ar.get_n_items() < 1) { + GLib.debug("higjlight %s has no errors", category); + return; + } + + + + + var offset = 0; + + + var tlines = buf.get_line_count () +1; + + + + for (var i = 0; i < ar.get_n_items();i++) { + var err = (Palete.CompileError) ar.get_item(i); + + Gtk.TextIter iter; + // print("get inter\n"); + var eline = err.line - offset; + GLib.debug("GOT ERROR on line %d -- converted to %d (offset = %d)", + err.line ,eline, offset); + + + if (eline > tlines || eline < 0) { + return; + } + + + buf.get_iter_at_line( out iter, eline); + + + var msg = "Line: %d %s : %s".printf(eline+1, err.category, err.msg); + buf.create_source_mark( msg, err.category, iter); + GLib.debug("set line %d to %s", eline, msg); + //this.marks.set(eline, msg); + } + return ; + + + + + } public void scroll_to_line (int line) { // code preview... @@ -745,23 +814,10 @@ ((GtkSource.Buffer)(buf)) .set_language(lm.get_language(_this.file.language)); - - Gtk.TextIter start; - Gtk.TextIter end; - - sbuf.get_bounds (out start, out end); - sbuf.remove_source_marks (start, end, null); // remove all marks.. - - - if (_this.main_window.windowstate.last_compile_result != null) { - var obj = _this.main_window.windowstate.last_compile_result; - this.highlightErrorsJson("ERR", obj); - this.highlightErrorsJson("WARN", obj); - this.highlightErrorsJson("DEPR", obj); - } - // while (Gtk.events_pending()) { - // Gtk.main_iteration(); - // } + + _this.main_window.windowstate.updateErrorMarksAll(); + + this.loading = false; } @@ -824,80 +880,6 @@ } - } - public void highlightErrorsJson (string type, Json.Object obj) { - Gtk.TextIter start; - Gtk.TextIter end; - - var buf = this.el.get_buffer(); - var sbuf = (GtkSource.Buffer)buf; - buf.get_bounds (out start, out end); - - sbuf.remove_source_marks (start, end, type); - - - // we should highlight other types of errors.. - - if (!obj.has_member(type)) { - GLib.debug("Return has no errors\n"); - return ; - } - var err = obj.get_object_member(type); - - if (_this.file == null) { - - return; // just in case the file has not loaded yet? - } - - - var valafn = ""; - try { - var regex = new Regex("\\.bjs$"); - - - valafn = regex.replace(_this.file.path,_this.file.path.length , 0 , ".vala"); - } catch (GLib.RegexError e) { - return; - } - - if (!err.has_member(valafn)) { - GLib.debug("File path has no errors\n"); - return ; - } - var lines = err.get_object_member(valafn); - - - - var tlines = buf.get_line_count () +1; - - lines.foreach_member((obj, line, node) => { - - Gtk.TextIter iter; - // print("get inter\n"); - var eline = int.parse(line) -1 ; - GLib.debug("GOT ERROR on line %s -- converted to %d\n", line,eline); - - - if (eline > tlines || eline < 0) { - return; - } - sbuf.get_iter_at_line( out iter, eline); - //print("mark line\n"); - var msg = type + " on line: %d - %s".printf(eline+1, valafn); - var ar = lines.get_array_member(line); - for (var i = 0 ; i < ar.get_length(); i++) { - msg += (msg.length > 0) ? "\n" : ""; - msg += ar.get_string_element(i); - } - - - sbuf.create_source_mark(msg, type, iter); - } ); - return ; - - - - } public string toString () { Gtk.TextIter s; diff --git a/src/Builder4/MainWindow.bjs b/src/Builder4/MainWindow.bjs index 337bf15c9..d43dd8f14 100644 --- a/src/Builder4/MainWindow.bjs +++ b/src/Builder4/MainWindow.bjs @@ -496,29 +496,19 @@ "xtype" : "Label" }, { - "# GLib.ListStore notices" : "null", "$ xns" : "Gtk", "Xcls_ValaCompileErrors popup" : "", "id" : "statusbar_errors", "listeners" : { "clicked" : [ "() => {", - " ", - "", - " ", - " if (this.popup == null) {", - " this.popup = new Xcls_ValaCompileErrors();", - " this.popup.window = _this;", - " //this.popup.el.application = _this.el.application;", - "\t // this.popup.el.set_transient_for( _this.el );", - " this.popup.el.set_parent(this.el);", - " }", - " if (_this.statusbar_compile_spinner.el.spinning) {", - "\t\tthis.popup.el.show(); \t", - " \treturn;", - "\t} ", - " this.popup.show(this.notices, this.el);", - " return;", + " ", + "\tif (this.popup == null) {", + "\t\treturn;", + "\t}", + " ", + " this.popup.show();", + " ", "}" ] }, @@ -526,28 +516,34 @@ "string label" : "0 Errors", "xtype" : "Button", "| void setNotices" : [ - "(GLib.ListStore nots, int qty, int tf) {", + "(GLib.ListStore nots, GLib.ListStore fe ) {", " ", - " if (qty < 1 ) {", + " if (nots.get_n_items() < 1 ) {", " \tthis.el.hide();", - " \tif (this.popup != null && this.popup.el.visible) {", + " \tif (this.popup != null) {", " \t\tthis.popup.el.hide();", "\t\t}", " \treturn;", " }", " ", " this.el.show();", - " this.el.label = \"%d/%d Errors\".printf(tf,qty);", - " this.notices = nots;", - "\tif (this.popup != null && this.popup.el.visible) {", - "\t\t this.popup.show(this.notices, this.el);", + " this.el.label = \"%d/%d Errors\".printf((int)fe.get_n_items(),(int)nots.get_n_items());", + "", + " ", + " ", + "\tif (this.popup == null) {", + " this.popup = new Xcls_ValaCompileErrors();", + " this.popup.window = _this;", + " // this.popup.el.set_transient_for( _this.el );", + " this.popup.el.set_parent(this.el);", " }", + "\tthis.popup.updateNotices(nots);", + "\t ", "}", "" ] }, { - "# GLib.ListStore notices" : "null", "$ xns" : "Gtk", "Xcls_ValaCompileErrors popup" : "", "id" : "statusbar_warnings", @@ -556,16 +552,10 @@ "() => {", " ", "\tif (this.popup == null) {", - " this.popup = new Xcls_ValaCompileErrors();", - " this.popup.window = _this;", - " // this.popup.el.set_transient_for( _this.el );", - " this.popup.el.set_parent(this.el);", - " }", - " if (_this.statusbar_compile_spinner.el.spinning) {", - "\t\tthis.popup.el.show(); \t", - " \treturn;", - "\t} ", - " this.popup.show(this.notices, this.el);", + "\t\treturn;", + "\t}", + " ", + " this.popup.show();", " return;", "}" ] @@ -574,23 +564,29 @@ "string label" : "0 Warnings", "xtype" : "Button", "| void setNotices" : [ - "(GLib.ListStore nots, int qty, int tf) {", + "(GLib.ListStore nots, GLib.ListStore fe ) {", " ", - " if (qty < 1 ) {", + " if (nots.get_n_items() < 1 ) {", " \tthis.el.hide();", - " \tif (this.popup != null && this.popup.el.visible) {", + " \tif (this.popup != null) {", " \t\tthis.popup.el.hide();", "\t\t}", " \treturn;", " }", - " this.el.show();", - " this.el.label = \"%d/%d Warnings\".printf(tf,qty);", - " this.notices = nots;", - " if (this.popup != null && this.popup.el.visible) {", - "\t\t this.popup.show(this.notices, this.el);", - " }", " ", + " this.el.show();", + " this.el.label = \"%d/%d Warnings\".printf((int)fe.get_n_items(),(int)nots.get_n_items());", "", + " ", + " ", + "\tif (this.popup == null) {", + " this.popup = new Xcls_ValaCompileErrors();", + " this.popup.window = _this;", + " // this.popup.el.set_transient_for( _this.el );", + " this.popup.el.set_parent(this.el);", + " }", + "\tthis.popup.updateNotices(nots);", + "\t ", "}", "" ] @@ -603,20 +599,13 @@ "listeners" : { "clicked" : [ "() => {", - " ", + " ", "\tif (this.popup == null) {", - " this.popup = new Xcls_ValaCompileErrors();", - " this.popup.window = _this;", - " // this.popup.el.set_transient_for( _this.el );", - " this.popup.el.set_parent(this.el);", - " }", - " if (_this.statusbar_compile_spinner.el.spinning) {", - "\t\tthis.popup.el.show(); \t", - " \treturn;", - "\t} ", - " ", - " this.popup.show(this.notices, this.el);", - " return;", + "\t\treturn;", + "\t}", + " ", + " this.popup.show();", + " ", "}" ] }, @@ -624,23 +613,30 @@ "string label" : "0 Depricated", "xtype" : "Button", "| void setNotices" : [ - "(GLib.ListStore nots, int qty, int tf) {", - " if (qty < 1) {", + "", + "(GLib.ListStore nots, GLib.ListStore fe ) {", + " ", + " if (nots.get_n_items() < 1 ) {", " \tthis.el.hide();", - " \tif (this.popup != null && this.popup.el.visible) {", - "\t\t\t this.popup.el.hide();", + " \tif (this.popup != null) {", + " \t\tthis.popup.el.hide();", "\t\t}", - " ", " \treturn;", - "\t}", + " }", " ", " this.el.show();", + " this.el.label = \"%d/%d Depricated\".printf((int)fe.get_n_items(),(int)nots.get_n_items());", + "", " ", - " this.el.label = \"%d/%d Depricated\".printf(tf,qty);", - " this.notices = nots;", - "\tif (this.popup != null && this.popup.el.visible) {", - "\t\t this.popup.show(this.notices, this.el);", + " ", + "\tif (this.popup == null) {", + " this.popup = new Xcls_ValaCompileErrors();", + " this.popup.window = _this;", + " // this.popup.el.set_transient_for( _this.el );", + " this.popup.el.set_parent(this.el);", " }", + "\tthis.popup.updateNotices(nots);", + "\t ", "}", "" ] @@ -661,10 +657,16 @@ "\t _this.windowstate.compile_results.el.show(); // show currently running.", " \treturn;", "\t}", - "\tBuilderApplication.valacompilequeue.addFile( ", - "\t \t\t\t\t\tPalete.ValaCompileRequestType.RUN, ", - "\t \t\t\t\t\t_this.windowstate.file, \"\", true ) ;", - "", + "\t", + "\tvar req = new Palete.ValaCompileRequest(", + "\t\tPalete.ValaCompileRequestType.RUN,", + "\t\t_this.windowstate.file,", + "\t\tnull,", + "\t\tnull,", + "\t\t\"\"", + "\t);", + "\treq.run();", + "\t ", "\t_this.windowstate.compile_results.el.set_parent(this.el);", "\t_this.windowstate.compile_results.show(this.el,true);", "\t ", @@ -715,10 +717,15 @@ "( ) => {", "\t Resources.singleton().disconnect(_this.statusbar.handler_id);", "\t ", + "\t ", + "\t this.windowstate.file.getLanguageServer().document_close(", + "\t \tthis.windowstate.file", + " \t);", + "\t ", "\t BuilderApplication.removeWindow(this);", "\t ", "\t if (BuilderApplication.windows.size < 1) {", - "", + "\t\tthis.windowstate.file.getLanguageServer().exit();", "\t\tBuilderApplication.singleton( null ).quit();", "\t }", "\treturn true;", @@ -805,38 +812,32 @@ "}" ], "| void updateErrors" : [ - "(Palete.ValaCompileRequest? req) {", + "() {", "", - "\tif (req == null) {", - " ", - "\t _this.statusbar_errors.el.hide();", - "\t\t_this.statusbar_warnings.el.hide();", - "\t\t_this.statusbar_depricated.el.hide();", - "\t\treturn;", - "\t}", + "", + " \tGLib.debug(\"updateErrors\");", "\t", + "\tvar pr = this.windowstate.project.getErrors(\"ERR\");", "\t", "\tthis.statusbar_errors.setNotices(", - "\t\treq.errorByType.get(\"ERR\"),", - "\t\treq.totalErrors(\"ERR\"),", - "\t\treq.totalErrors(\"ERR\", this.windowstate.file)", + "\t\tpr,", + "\t\tthis.windowstate.file.getErrors(\"ERR\")", "\t);", + "\t", "\tthis.statusbar_warnings.setNotices(", - "\t\treq.errorByType.get(\"WARN\"),", - "\t\treq.totalErrors(\"WARN\"),", - "\t\treq.totalErrors(\"WARN\", this.windowstate.file)", + "\t\tthis.windowstate.project.getErrors(\"WARN\"),", + "\t\tthis.windowstate.file.getErrors(\"WARN\")", "\t);", "\tthis.statusbar_depricated.setNotices(", - "\t\treq.errorByType.get(\"DEPR\"),", - "\t\treq.totalErrors(\"DEPR\"),", - "\t\treq.totalErrors(\"DEPR\", this.windowstate.file)", + "\t\tthis.windowstate.project.getErrors(\"DEPR\"),", + "\t\tthis.windowstate.file.getErrors(\"DEPR\")", "\t);", - "", + " ", "\t_this.statusbar_run.el.hide();", "", - "\tif (req.totalErrors(\"ERR\") < 1) {", + "\tif (pr.get_n_items() < 1) {", "\t\t_this.statusbar_run.el.show();", - "\t}", + "\t} ", "\t", "}" ] diff --git a/src/Builder4/MainWindow.vala b/src/Builder4/MainWindow.vala index 76242bb7c..65636a63e 100644 --- a/src/Builder4/MainWindow.vala +++ b/src/Builder4/MainWindow.vala @@ -64,10 +64,15 @@ this.el.close_request.connect( ( ) => { Resources.singleton().disconnect(_this.statusbar.handler_id); + + this.windowstate.file.getLanguageServer().document_close( + this.windowstate.file + ); + BuilderApplication.removeWindow(this); if (BuilderApplication.windows.size < 1) { - + this.windowstate.file.getLanguageServer().exit(); BuilderApplication.singleton( null ).quit(); } return true; @@ -96,38 +101,32 @@ } // user defined functions - public void updateErrors (Palete.ValaCompileRequest? req) { + public void updateErrors () { - if (req == null) { - - _this.statusbar_errors.el.hide(); - _this.statusbar_warnings.el.hide(); - _this.statusbar_depricated.el.hide(); - return; - } + + GLib.debug("updateErrors"); + var pr = this.windowstate.project.getErrors("ERR"); this.statusbar_errors.setNotices( - req.errorByType.get("ERR"), - req.totalErrors("ERR"), - req.totalErrors("ERR", this.windowstate.file) + pr, + this.windowstate.file.getErrors("ERR") ); + this.statusbar_warnings.setNotices( - req.errorByType.get("WARN"), - req.totalErrors("WARN"), - req.totalErrors("WARN", this.windowstate.file) + this.windowstate.project.getErrors("WARN"), + this.windowstate.file.getErrors("WARN") ); this.statusbar_depricated.setNotices( - req.errorByType.get("DEPR"), - req.totalErrors("DEPR"), - req.totalErrors("DEPR", this.windowstate.file) + this.windowstate.project.getErrors("DEPR"), + this.windowstate.file.getErrors("DEPR") ); - + _this.statusbar_run.el.hide(); - if (req.totalErrors("ERR") < 1) { + if (pr.get_n_items() < 1) { _this.statusbar_run.el.show(); - } + } } public void initChildren () { @@ -1248,7 +1247,6 @@ // my vars (def) public Xcls_ValaCompileErrors popup; - public GLib.ListStore notices; // ctor public Xcls_statusbar_errors(Xcls_MainWindow _owner ) @@ -1258,7 +1256,6 @@ this.el = new Gtk.Button(); // my vars (dec) - this.notices = null; // set gobject values this.el.icon_name = "dialog-error"; @@ -1266,42 +1263,40 @@ //listeners this.el.clicked.connect( () => { - - - - if (this.popup == null) { - this.popup = new Xcls_ValaCompileErrors(); - this.popup.window = _this; - //this.popup.el.application = _this.el.application; - // this.popup.el.set_transient_for( _this.el ); - this.popup.el.set_parent(this.el); - } - if (_this.statusbar_compile_spinner.el.spinning) { - this.popup.el.show(); - return; - } - this.popup.show(this.notices, this.el); - return; + + if (this.popup == null) { + return; + } + + this.popup.show(); + }); } // user defined functions - public void setNotices (GLib.ListStore nots, int qty, int tf) { + public void setNotices (GLib.ListStore nots, GLib.ListStore fe ) { - if (qty < 1 ) { + if (nots.get_n_items() < 1 ) { this.el.hide(); - if (this.popup != null && this.popup.el.visible) { + if (this.popup != null) { this.popup.el.hide(); } return; } this.el.show(); - this.el.label = "%d/%d Errors".printf(tf,qty); - this.notices = nots; - if (this.popup != null && this.popup.el.visible) { - this.popup.show(this.notices, this.el); + this.el.label = "%d/%d Errors".printf((int)fe.get_n_items(),(int)nots.get_n_items()); + + + + if (this.popup == null) { + this.popup = new Xcls_ValaCompileErrors(); + this.popup.window = _this; + // this.popup.el.set_transient_for( _this.el ); + this.popup.el.set_parent(this.el); } + this.popup.updateNotices(nots); + } } @@ -1313,7 +1308,6 @@ // my vars (def) public Xcls_ValaCompileErrors popup; - public GLib.ListStore notices; // ctor public Xcls_statusbar_warnings(Xcls_MainWindow _owner ) @@ -1323,7 +1317,6 @@ this.el = new Gtk.Button(); // my vars (dec) - this.notices = null; // set gobject values this.el.icon_name = "dialog-warning"; @@ -1333,38 +1326,38 @@ this.el.clicked.connect( () => { if (this.popup == null) { - this.popup = new Xcls_ValaCompileErrors(); - this.popup.window = _this; - // this.popup.el.set_transient_for( _this.el ); - this.popup.el.set_parent(this.el); - } - if (_this.statusbar_compile_spinner.el.spinning) { - this.popup.el.show(); - return; - } - this.popup.show(this.notices, this.el); + return; + } + + this.popup.show(); return; }); } // user defined functions - public void setNotices (GLib.ListStore nots, int qty, int tf) { + public void setNotices (GLib.ListStore nots, GLib.ListStore fe ) { - if (qty < 1 ) { + if (nots.get_n_items() < 1 ) { this.el.hide(); - if (this.popup != null && this.popup.el.visible) { + if (this.popup != null) { this.popup.el.hide(); } return; } - this.el.show(); - this.el.label = "%d/%d Warnings".printf(tf,qty); - this.notices = nots; - if (this.popup != null && this.popup.el.visible) { - this.popup.show(this.notices, this.el); - } + this.el.show(); + this.el.label = "%d/%d Warnings".printf((int)fe.get_n_items(),(int)nots.get_n_items()); + + + if (this.popup == null) { + this.popup = new Xcls_ValaCompileErrors(); + this.popup.window = _this; + // this.popup.el.set_transient_for( _this.el ); + this.popup.el.set_parent(this.el); + } + this.popup.updateNotices(nots); + } } @@ -1394,41 +1387,40 @@ //listeners this.el.clicked.connect( () => { - + if (this.popup == null) { - this.popup = new Xcls_ValaCompileErrors(); - this.popup.window = _this; - // this.popup.el.set_transient_for( _this.el ); - this.popup.el.set_parent(this.el); - } - if (_this.statusbar_compile_spinner.el.spinning) { - this.popup.el.show(); - return; - } - - this.popup.show(this.notices, this.el); - return; + return; + } + + this.popup.show(); + }); } // user defined functions - public void setNotices (GLib.ListStore nots, int qty, int tf) { - if (qty < 1) { + public void setNotices (GLib.ListStore nots, GLib.ListStore fe ) { + + if (nots.get_n_items() < 1 ) { this.el.hide(); - if (this.popup != null && this.popup.el.visible) { - this.popup.el.hide(); + if (this.popup != null) { + this.popup.el.hide(); } - return; - } + } this.el.show(); + this.el.label = "%d/%d Depricated".printf((int)fe.get_n_items(),(int)nots.get_n_items()); + - this.el.label = "%d/%d Depricated".printf(tf,qty); - this.notices = nots; - if (this.popup != null && this.popup.el.visible) { - this.popup.show(this.notices, this.el); + + if (this.popup == null) { + this.popup = new Xcls_ValaCompileErrors(); + this.popup.window = _this; + // this.popup.el.set_transient_for( _this.el ); + this.popup.el.set_parent(this.el); } + this.popup.updateNotices(nots); + } } @@ -1465,10 +1457,16 @@ _this.windowstate.compile_results.el.show(); // show currently running. return; } - BuilderApplication.valacompilequeue.addFile( - Palete.ValaCompileRequestType.RUN, - _this.windowstate.file, "", true ) ; - + + var req = new Palete.ValaCompileRequest( + Palete.ValaCompileRequestType.RUN, + _this.windowstate.file, + null, + null, + "" + ); + req.run(); + _this.windowstate.compile_results.el.set_parent(this.el); _this.windowstate.compile_results.show(this.el,true); diff --git a/src/Builder4/ValaCompileErrors.bjs b/src/Builder4/ValaCompileErrors.bjs index 3bf4b5583..5e4aeb35c 100644 --- a/src/Builder4/ValaCompileErrors.bjs +++ b/src/Builder4/ValaCompileErrors.bjs @@ -3,12 +3,12 @@ "gen_extended" : false, "items" : [ { - "# GLib.ListStore notices" : "", "# Xcls_MainWindow window" : "", "$ xns" : "Gtk", "* ctor" : "new Gtk.Popover()", "Gtk.PositionType position" : "Gtk.PositionType.TOP", "bool autohide" : true, + "bool loaded" : false, "id" : "ValaCompileErrors", "int height_request" : 800, "int width_request" : 900, @@ -69,6 +69,27 @@ "* prop" : "model", "id" : "model", "xtype" : "TreeListModel" + }, + { + "$ xns" : "Gtk", + "* prop" : "sorter", + "items" : [ + { + "$ xns" : "Gtk", + "* prop" : "sorter", + "items" : [ + { + "$ xns" : "Gtk", + "* prop" : "expression", + "GLib.Type this_type" : "typeof(Palete.CompileError)", + "string property_name" : "linemsg", + "xtype" : "PropertyExpression" + } + ], + "xtype" : "StringSorter" + } + ], + "xtype" : "TreeListRowSorter" } ], "xtype" : "SortListModel", @@ -133,16 +154,20 @@ "\t", "\t", "\t//GLib.debug(\"change %s to %s\", lbl.label, np.name);", - "\tlbl.label = np.line_msg;", + "\tlbl.label = np.linemsg;", "\t//lbl.tooltip_markup = np.to_property_option_tooltip();", "\t ", " expand.set_hide_expander( np.lines.n_items < 1);", "\texpand.set_list_row(lr);", " ", " \t// expand current file.", - " \tif (_this.window.windowstate.file.path == np.file.path) {", - " \t\tlr.expanded = true;", - "\t}", + " \t// this causes problems? - critical errors?", + " \t// maybe do it on show", + " \t//if (_this.window.windowstate.file.path == np.file.path &&", + " \t//\tnp.line < 0) {", + " \t//\tlr.expanded = true;", + " \t", + "\t//}", " \t ", " \t// bind image...", " \t", @@ -201,9 +226,9 @@ "\t}", "\t ", "\t ", - " var fname = ce.parent.file;", + " var fname = ce.file;", " \tvar line = ce.line; ", - " GLib.debug(\"open %s @ %d\\n\", ce.parent.file.path, ce.line);", + " GLib.debug(\"open %s @ %d\\n\", ce.file.path, ce.line);", " ", " ", " var bjsf = \"\";", @@ -224,21 +249,19 @@ " _this.window.windowstate.fileViewOpen(jsr, true, line);", " ", " if (jsr.path == _this.window.windowstate.file.path) {", - " \t_this.el.hide();", - " \t}", " ", + " \t}", + " \t_this.el.hide();", " ", " return;", " ", " }", - " try {", - "\t\tvar pf = JsRender.JsRender.factory(\"PlainFile\", p, fname.path);", - "\t\t_this.window.windowstate.fileViewOpen(pf, true, line);", - " } catch (JsRender.Error e) {}", - " // try hiding the left nav..", - " ", - " return;", + " ", + "\tvar pf = p.getByPath(fname.path);", + "\t_this.el.hide();", + "\t_this.window.windowstate.fileViewOpen(pf, true, line);", "", + " ", "}", "" ] @@ -258,18 +281,22 @@ ], "xtype" : "Popover", "| void show" : [ - "( GLib.ListStore ls , Gtk.Widget onbtn) {", - "", - " ", + "( ) {", + "\tGLib.debug(\"errors : show\");", + "\t", + "\tif (_this.model.el.get_n_items() < 1) {", + " ", + " \t GLib.debug(\"errors : none available\");", + " \treturn;", + "\t}", " \t//this.el.present();", " //this.el.popup();", - " this.notices = ls;", - " ", + " ", " //print(\"looking for %s\\n\", id);", " // loop through parent childnre", " ", " ", - " this.tree.el.hide(); //<< very important!!!", + " ; //<< very important!!!", " ", " // store.set_sort_column_id(0,Gtk.SortType.ASCENDING);", " ", @@ -277,8 +304,7 @@ " var w = win.get_width();", " var h = win.get_height();", "", - " ", - " ", + " ", " // left tree = 250, editor area = 500?", " ", " // min 450?", @@ -286,6 +312,7 @@ " if (new_w > (w-100)) {", " new_w = w-100;", " }", + " GLib.debug(\"set size\");", " this.el.set_size_request( int.max(100, new_w), int.max(100, h-120));", " ", "", @@ -293,10 +320,36 @@ "\t//Gtk.Allocation rect;", "\t//onbtn.get_allocation(out rect);", " //this.el.set_pointing_to(rect);", - "\tthis.el.present();", + "\t//this.el.present();", + "\t", + "\tGLib.debug(\"call popup\");", " this.el.popup();", + " // only need to load once.", + " \t//if (!this.loaded) {", + " \t\t ", + "\t\t//this.loaded = true;", + "\t //}", + "\t ", + " ", " ", - " ", + " \t//if (expand != null) {", + " //\t_this.compile_tree.el.expand_row( store.get_path(expand) , true);", + "//\t}", + " ", + " // this.hpane.el.set_position( 0);", + "}", + "" + ], + "| void updateNotices" : [ + "( GLib.ListStore? ls) {", + "\tGLib.debug(\"errors : update\");", + " if (ls == null || ls.get_n_items() < 1) {", + " \t GLib.debug(\"errors : none available\");", + " \treturn;", + "\t}", + "\t", + "\tGLib.debug(\"Loading list into tree\");", + "\tthis.tree.el.hide();", "\tvar tm = new Gtk.TreeListModel(", "\t\tls, //..... << that's our store..", "\t\tfalse, // passthru", @@ -306,20 +359,13 @@ "\t\t\t return ((Palete.CompileError)item).lines;", "\t\t", "\t\t}", + "\t\t", "\t);", " ", - " _this.model.el = tm;", - " _this.sortmodel.el.set_model(tm);", - " ", - " this.tree.el.show(); ", - " ", - " \t//if (expand != null) {", - " //\t_this.compile_tree.el.expand_row( store.get_path(expand) , true);", - "//\t}", - " ", - " // this.hpane.el.set_position( 0);", - "}", - "" + "\t_this.model.el = tm;", + "\t_this.sortmodel.el.set_model(tm);", + "\t this.tree.el.show();", + "}" ] } ], diff --git a/src/Builder4/ValaCompileErrors.vala b/src/Builder4/ValaCompileErrors.vala index 295f01cc0..baac166dd 100644 --- a/src/Builder4/ValaCompileErrors.vala +++ b/src/Builder4/ValaCompileErrors.vala @@ -20,7 +20,7 @@ // my vars (def) public Xcls_MainWindow window; - public GLib.ListStore notices; + public bool loaded; // ctor public Xcls_ValaCompileErrors() @@ -29,6 +29,7 @@ this.el = new Gtk.Popover(); // my vars (dec) + this.loaded = false; // set gobject values this.el.width_request = 900; @@ -40,18 +41,47 @@ } // user defined functions - public void show ( GLib.ListStore ls , Gtk.Widget onbtn) { - - + public void updateNotices ( GLib.ListStore? ls) { + GLib.debug("errors : update"); + if (ls == null || ls.get_n_items() < 1) { + GLib.debug("errors : none available"); + return; + } + + GLib.debug("Loading list into tree"); + this.tree.el.hide(); + var tm = new Gtk.TreeListModel( + ls, //..... << that's our store.. + false, // passthru + false, // autexpand + (item) => { + + return ((Palete.CompileError)item).lines; + + } + + ); + + _this.model.el = tm; + _this.sortmodel.el.set_model(tm); + this.tree.el.show(); + } + public void show ( ) { + GLib.debug("errors : show"); + + if (_this.model.el.get_n_items() < 1) { + + GLib.debug("errors : none available"); + return; + } //this.el.present(); //this.el.popup(); - this.notices = ls; - + //print("looking for %s\n", id); // loop through parent childnre - this.tree.el.hide(); //<< very important!!! + ; //<< very important!!! // store.set_sort_column_id(0,Gtk.SortType.ASCENDING); @@ -59,8 +89,7 @@ var w = win.get_width(); var h = win.get_height(); - - + // left tree = 250, editor area = 500? // min 450? @@ -68,6 +97,7 @@ if (new_w > (w-100)) { new_w = w-100; } + GLib.debug("set size"); this.el.set_size_request( int.max(100, new_w), int.max(100, h-120)); @@ -75,25 +105,17 @@ //Gtk.Allocation rect; //onbtn.get_allocation(out rect); //this.el.set_pointing_to(rect); - this.el.present(); + //this.el.present(); + + GLib.debug("call popup"); this.el.popup(); - - - var tm = new Gtk.TreeListModel( - ls, //..... << that's our store.. - false, // passthru - false, // autexpand - (item) => { - - return ((Palete.CompileError)item).lines; - - } - ); - - _this.model.el = tm; - _this.sortmodel.el.set_model(tm); - - this.tree.el.show(); + // only need to load once. + //if (!this.loaded) { + + //this.loaded = true; + //} + + //if (expand != null) { // _this.compile_tree.el.expand_row( store.get_path(expand) , true); @@ -180,10 +202,10 @@ // set gobject values this.el.hexpand = true; this.el.vexpand = true; - var child_2 = new Xcls_ColumnViewColumn8( _this ); + var child_2 = new Xcls_ColumnViewColumn11( _this ); child_2.ref(); this.el.append_column ( child_2.el ); - var child_3 = new Xcls_GestureClick10( _this ); + var child_3 = new Xcls_GestureClick13( _this ); child_3.ref(); this.el.add_controller( child_3.el ); } @@ -237,7 +259,9 @@ _this = _owner; _this.sortmodel = this; new Xcls_model( _this ); - this.el = new Gtk.SortListModel( _this.model.el, null ); + var child_2 = new Xcls_TreeListRowSorter8( _this ); + child_2.ref(); + this.el = new Gtk.SortListModel( _this.model.el, child_2.el ); // my vars (dec) @@ -292,9 +316,79 @@ // user defined functions } + public class Xcls_TreeListRowSorter8 : Object + { + public Gtk.TreeListRowSorter el; + private Xcls_ValaCompileErrors _this; + + + // my vars (def) + + // ctor + public Xcls_TreeListRowSorter8(Xcls_ValaCompileErrors _owner ) + { + _this = _owner; + var child_1 = new Xcls_StringSorter9( _this ); + child_1.ref(); + this.el = new Gtk.TreeListRowSorter( child_1.el ); + + // my vars (dec) + // set gobject values + } - public class Xcls_ColumnViewColumn8 : Object + // user defined functions + } + public class Xcls_StringSorter9 : Object + { + public Gtk.StringSorter el; + private Xcls_ValaCompileErrors _this; + + + // my vars (def) + + // ctor + public Xcls_StringSorter9(Xcls_ValaCompileErrors _owner ) + { + _this = _owner; + var child_1 = new Xcls_PropertyExpression10( _this ); + child_1.ref(); + this.el = new Gtk.StringSorter( child_1.el ); + + // my vars (dec) + + // set gobject values + } + + // user defined functions + } + public class Xcls_PropertyExpression10 : Object + { + public Gtk.PropertyExpression el; + private Xcls_ValaCompileErrors _this; + + + // my vars (def) + + // ctor + public Xcls_PropertyExpression10(Xcls_ValaCompileErrors _owner ) + { + _this = _owner; + this.el = new Gtk.PropertyExpression( typeof(Palete.CompileError), null, "linemsg" ); + + // my vars (dec) + + // set gobject values + } + + // user defined functions + } + + + + + + public class Xcls_ColumnViewColumn11 : Object { public Gtk.ColumnViewColumn el; private Xcls_ValaCompileErrors _this; @@ -303,10 +397,10 @@ // my vars (def) // ctor - public Xcls_ColumnViewColumn8(Xcls_ValaCompileErrors _owner ) + public Xcls_ColumnViewColumn11(Xcls_ValaCompileErrors _owner ) { _this = _owner; - var child_1 = new Xcls_SignalListItemFactory9( _this ); + var child_1 = new Xcls_SignalListItemFactory12( _this ); child_1.ref(); this.el = new Gtk.ColumnViewColumn( "Compile Result", child_1.el ); @@ -319,7 +413,7 @@ // user defined functions } - public class Xcls_SignalListItemFactory9 : Object + public class Xcls_SignalListItemFactory12 : Object { public Gtk.SignalListItemFactory el; private Xcls_ValaCompileErrors _this; @@ -328,7 +422,7 @@ // my vars (def) // ctor - public Xcls_SignalListItemFactory9(Xcls_ValaCompileErrors _owner ) + public Xcls_SignalListItemFactory12(Xcls_ValaCompileErrors _owner ) { _this = _owner; this.el = new Gtk.SignalListItemFactory(); @@ -378,16 +472,20 @@ //GLib.debug("change %s to %s", lbl.label, np.name); - lbl.label = np.line_msg; + lbl.label = np.linemsg; //lbl.tooltip_markup = np.to_property_option_tooltip(); expand.set_hide_expander( np.lines.n_items < 1); expand.set_list_row(lr); // expand current file. - if (_this.window.windowstate.file.path == np.file.path) { - lr.expanded = true; - } + // this causes problems? - critical errors? + // maybe do it on show + //if (_this.window.windowstate.file.path == np.file.path && + // np.line < 0) { + // lr.expanded = true; + + //} // bind image... @@ -398,7 +496,7 @@ } - public class Xcls_GestureClick10 : Object + public class Xcls_GestureClick13 : Object { public Gtk.GestureClick el; private Xcls_ValaCompileErrors _this; @@ -407,7 +505,7 @@ // my vars (def) // ctor - public Xcls_GestureClick10(Xcls_ValaCompileErrors _owner ) + public Xcls_GestureClick13(Xcls_ValaCompileErrors _owner ) { _this = _owner; this.el = new Gtk.GestureClick(); @@ -437,9 +535,9 @@ } - var fname = ce.parent.file; + var fname = ce.file; var line = ce.line; - GLib.debug("open %s @ %d\n", ce.parent.file.path, ce.line); + GLib.debug("open %s @ %d\n", ce.file.path, ce.line); var bjsf = ""; @@ -460,21 +558,19 @@ _this.window.windowstate.fileViewOpen(jsr, true, line); if (jsr.path == _this.window.windowstate.file.path) { - _this.el.hide(); - } + } + _this.el.hide(); return; } - try { - var pf = JsRender.JsRender.factory("PlainFile", p, fname.path); - _this.window.windowstate.fileViewOpen(pf, true, line); - } catch (JsRender.Error e) {} - // try hiding the left nav.. - - return; + + var pf = p.getByPath(fname.path); + _this.el.hide(); + _this.window.windowstate.fileViewOpen(pf, true, line); + }); } diff --git a/src/Builder4/WindowLeftTree.bjs b/src/Builder4/WindowLeftTree.bjs index e1e1a1760..ae238abfc 100644 --- a/src/Builder4/WindowLeftTree.bjs +++ b/src/Builder4/WindowLeftTree.bjs @@ -763,6 +763,9 @@ "\t\t", "\t\t}", "\t);", + "\tif (_this.selmodel.el == null) {", + "\t\treturn this.el;", + "\t}", "\t_this.selmodel.el.set_model(this.el);", "\treturn this.el;", "}" @@ -1426,12 +1429,10 @@ "label" : "Delete Element", "listeners" : { "clicked" : [ - " ( ) => {", - " ", - " print(\"ACTIVATE?\");", - " ", - " \t_this.LeftTreeMenu.el.hide();", - " _this.model.deleteSelected();", + " ( ) => {", + "_this.LeftTreeMenu.el.hide();", + " _this.model.deleteSelected();", + "_this.changed();", "}" ] }, diff --git a/src/Builder4/WindowLeftTree.vala b/src/Builder4/WindowLeftTree.vala index f22c4d059..87dadcb2c 100644 --- a/src/Builder4/WindowLeftTree.vala +++ b/src/Builder4/WindowLeftTree.vala @@ -1431,6 +1431,9 @@ } ); + if (_this.selmodel.el == null) { + return this.el; + } _this.selmodel.el.set_model(this.el); return this.el; } @@ -1751,11 +1754,9 @@ //listeners this.el.clicked.connect( ( ) => { - - print("ACTIVATE?"); - - _this.LeftTreeMenu.el.hide(); - _this.model.deleteSelected(); + _this.LeftTreeMenu.el.hide(); + _this.model.deleteSelected(); + _this.changed(); }); } diff --git a/src/Builder4/WindowRooView.bjs b/src/Builder4/WindowRooView.bjs index 8a05b79f3..506da32fb 100644 --- a/src/Builder4/WindowRooView.bjs +++ b/src/Builder4/WindowRooView.bjs @@ -872,12 +872,9 @@ " ((GtkSource.Buffer)(buf)) .set_language(lm.get_language(_this.file.language));", " ", " ", - " Gtk.TextIter start;", - " Gtk.TextIter end; ", - " ", - " sbuf.get_bounds (out start, out end);", - " sbuf.remove_source_marks (start, end, null); // remove all marks..", + " _this.main_window.windowstate.updateErrorMarksAll();", " ", + " // what does this do?", " GLib.Timeout.add(500, () => {", "", " print(\"RESORTING cursor to = %d\\n\", cpos);", @@ -1632,6 +1629,77 @@ " ", "}", "" + ], + "| void updateErrorMarks" : [ + "(string category) {", + "\t", + " ", + "", + "\tvar buf = _this.buffer.el;", + "\tGtk.TextIter start;", + "\tGtk.TextIter end; ", + "\tbuf.get_bounds (out start, out end);", + "", + "\tbuf.remove_source_marks (start, end, category);", + " ", + "\tGLib.debug(\"highlight errors\");\t\t ", + "", + "\t // we should highlight other types of errors..", + "", + " ", + "", + "\t ", + "\tif (_this.file == null) {", + "\t\tGLib.debug(\"file is null?\");", + "\t\treturn;", + "", + "\t}", + "\tvar ar = this.file.getErrors(category);", + "\tif (ar == null || ar.get_n_items() < 1) {", + "\t\tGLib.debug(\"higjlight %s has no errors\", category);", + "\t\treturn;", + "\t}", + " ", + "", + " ", + "\t", + "\tvar offset = 0;", + "\t ", + "", + "\tvar tlines = buf.get_line_count () +1;", + "\t", + " ", + "\t ", + "\tfor (var i = 0; i < ar.get_n_items();i++) {", + "\t\tvar err = (Palete.CompileError) ar.get_item(i);", + "\t\t", + "\t Gtk.TextIter iter;", + "// print(\"get inter\\n\");", + "\t var eline = err.line - offset;", + "\t GLib.debug(\"GOT ERROR on line %d -- converted to %d (offset = %d)\",", + "\t \terr.line ,eline, offset);", + "\t ", + "\t ", + "\t if (eline > tlines || eline < 0) {", + "\t return;", + "\t }", + "\t ", + "\t ", + "\t buf.get_iter_at_line( out iter, eline);", + "\t ", + "\t ", + "\t\tvar msg = \"Line: %d %s : %s\".printf(eline+1, err.category, err.msg);", + "\t buf.create_source_mark( msg, err.category, iter);", + "\t GLib.debug(\"set line %d to %s\", eline, msg);", + "\t //this.marks.set(eline, msg);", + "\t}", + "\treturn ;", + "", + "", + "", + " ", + "", + "}" ] } ], diff --git a/src/Builder4/WindowRooView.vala b/src/Builder4/WindowRooView.vala index 22062d888..e8d16f4ba 100644 --- a/src/Builder4/WindowRooView.vala +++ b/src/Builder4/WindowRooView.vala @@ -241,6 +241,75 @@ + } + public void updateErrorMarks (string category) { + + + + var buf = _this.buffer.el; + Gtk.TextIter start; + Gtk.TextIter end; + buf.get_bounds (out start, out end); + + buf.remove_source_marks (start, end, category); + + GLib.debug("highlight errors"); + + // we should highlight other types of errors.. + + + + + if (_this.file == null) { + GLib.debug("file is null?"); + return; + + } + var ar = this.file.getErrors(category); + if (ar == null || ar.get_n_items() < 1) { + GLib.debug("higjlight %s has no errors", category); + return; + } + + + + + var offset = 0; + + + var tlines = buf.get_line_count () +1; + + + + for (var i = 0; i < ar.get_n_items();i++) { + var err = (Palete.CompileError) ar.get_item(i); + + Gtk.TextIter iter; + // print("get inter\n"); + var eline = err.line - offset; + GLib.debug("GOT ERROR on line %d -- converted to %d (offset = %d)", + err.line ,eline, offset); + + + if (eline > tlines || eline < 0) { + return; + } + + + buf.get_iter_at_line( out iter, eline); + + + var msg = "Line: %d %s : %s".printf(eline+1, err.category, err.msg); + buf.create_source_mark( msg, err.category, iter); + GLib.debug("set line %d to %s", eline, msg); + //this.marks.set(eline, msg); + } + return ; + + + + + } public void scroll_to_line (int line) { // code preview... @@ -1161,12 +1230,9 @@ ((GtkSource.Buffer)(buf)) .set_language(lm.get_language(_this.file.language)); - Gtk.TextIter start; - Gtk.TextIter end; - - sbuf.get_bounds (out start, out end); - sbuf.remove_source_marks (start, end, null); // remove all marks.. + _this.main_window.windowstate.updateErrorMarksAll(); + // what does this do? GLib.Timeout.add(500, () => { print("RESORTING cursor to = %d\n", cpos); diff --git a/src/Builder4/WindowState.vala b/src/Builder4/WindowState.vala index 832c36700..9aa323863 100644 --- a/src/Builder4/WindowState.vala +++ b/src/Builder4/WindowState.vala @@ -157,6 +157,30 @@ public class WindowState : Object }); } + + public void updateErrorMarksAll() + { + this.updateErrorMarks("ERR"); + this.updateErrorMarks("WARN"); + this.updateErrorMarks("DEPR"); + + } + void updateErrorMarks(string cat) + { + this.code_editor_tab.updateErrorMarks(cat); + switch(this.file.xtype) { + case "Roo": + this.window_rooview.updateErrorMarks(cat);// foce scroll. + return; + case "Gtk": + this.window_gladeview.updateErrorMarks(cat); + return; + default: + return; + } + } + + public bool leftTreeBeforeChange() { @@ -361,13 +385,7 @@ public class WindowState : Object } //this.left_tree.model.updateSelected(); this.file.save(); - if (this.file.project.xtype=="Gtk") { - BuilderApplication.valacompilequeue.addFile( - Palete.ValaCompileRequestType.PROJECT, - this.file, "", true ) ; - - //BuilderApplication.valasource.checkFileSpawn(this.file); - } + }); @@ -520,11 +538,7 @@ public class WindowState : Object } else { this.window_gladeview.loadFile(this.left_tree.getActiveFile()); } - if (this.file.project.xtype=="Gtk") { - BuilderApplication.valacompilequeue.addFile( - Palete.ValaCompileRequestType.PROJECT, - this.file, "", false ) ; - } + // we do not need to call spawn... - as it's already called by the editor? @@ -640,7 +654,7 @@ public class WindowState : Object this.file = file; BuilderApplication.updateWindows(); - + file.getLanguageServer().document_open(file); if (file.xtype == "PlainFile") { @@ -659,14 +673,11 @@ public class WindowState : Object } - BuilderApplication.updateCompileResults(); - if (file.project.xtype == "Gtk" && file.project.last_request == null ) { - - BuilderApplication.valacompilequeue.addFile( - Palete.ValaCompileRequestType.PROJECT, - this.file, "" , true) ; - - } + + + + + this.gotoLine(line); var ctr= this.win.rooviewbox.el; @@ -709,7 +720,8 @@ public class WindowState : Object //this.win.editpane.el.set_position(this.win.editpane.el.max_position); } this.win.setTitle(); - + + BuilderApplication.updateCompileResults(); } diff --git a/src/JsRender/Dir.vala b/src/JsRender/Dir.vala index c536094d9..f51972e01 100644 --- a/src/JsRender/Dir.vala +++ b/src/JsRender/Dir.vala @@ -10,7 +10,7 @@ namespace JsRender { public Dir(Project.Project project, string path) { - aconstruct( project, path); + base( project, path); this.xtype = "Dir"; this.language = ""; @@ -40,6 +40,7 @@ namespace JsRender { public override string toGlade() {return "";} public override string targetName() {return "";} public override void loadItems() throws GLib.Error {} + public override string language_id() { return ""; } } diff --git a/src/JsRender/Gtk.vala b/src/JsRender/Gtk.vala index 83de74dad..dc4313948 100644 --- a/src/JsRender/Gtk.vala +++ b/src/JsRender/Gtk.vala @@ -27,7 +27,7 @@ namespace JsRender { public Gtk(Project.Project project, string path) { - aconstruct( project, path); + base( project, path); this.xtype = "Gtk"; this.language = "vala"; @@ -167,6 +167,7 @@ namespace JsRender { // this.saveJS(); - disabled at present.. project settings will probably enable this later.. this.saveVala(); + this.getLanguageServer().document_save(this); } // ignore these calls. public override void saveHTML ( string html ) {} @@ -269,7 +270,10 @@ namespace JsRender { { return NodeToGlade.mungeFile(this); } - + public override string language_id() + { + return "vala"; + } diff --git a/src/JsRender/JsRender.vala b/src/JsRender/JsRender.vala index 3c446885a..09e4f13b6 100644 --- a/src/JsRender/JsRender.vala +++ b/src/JsRender/JsRender.vala @@ -76,7 +76,16 @@ namespace JsRender { public string title = ""; // a title.. ?? nickname.. ??? - - + private int _version = 1; // should we increment this based on the node..? + public int version { + get { + return ++this._version; // increased on every call? - bit of a kludge until we do real versioning + } + private set { + this._version = value; + } + + } public string permname; public string language; @@ -104,11 +113,17 @@ namespace JsRender { public Gee.HashMap transStrings; // map of md5 -> string. public Gee.HashMap namedStrings; + public Gee.HashMap errorsByType; + + public signal void changed (Node? node, string source); public signal void compile_notice(string type, string file, int line, string message); + + + /** * UI componenets * @@ -119,10 +134,11 @@ namespace JsRender { //abstract JsRender(Project.Project project, string path); - public void aconstruct(Project.Project project, string path) + protected JsRender(Project.Project project, string path) { //this.cn = new GLib.List(); + GLib.debug("new jsrender %s", path); this.path = path; this.project = project; this.hasParent = false; @@ -154,6 +170,11 @@ namespace JsRender { this.doubleStringProps = new Gee.ArrayList(); this.childfiles = new GLib.ListStore(typeof(JsRender)); + this.errorsByType = new Gee.HashMap(); + + if (this.relpath == "src/Lsp.vala") { + GLib.debug("got testing lsp"); + } } @@ -691,6 +712,28 @@ namespace JsRender { } + public string to_url() + { + return File.new_for_path (this.targetName()).get_uri (); + } + public Palete.LanguageClient? getLanguageServer() + { + + return this.project.getLanguageServer(this.language_id()); + + } + public GLib.ListStore getErrors(string n) + { + var ls = this.errorsByType.get(n); + if (ls == null) { + ls = new GLib.ListStore(typeof(Palete.CompileError)); + this.errorsByType.set(n, ls ); + } + return ls; + } + + + public abstract string language_id(); public abstract void save(); public abstract void saveHTML(string html); public abstract string toSource() ; diff --git a/src/JsRender/PlainFile.vala b/src/JsRender/PlainFile.vala index c54a9b21e..29f828497 100644 --- a/src/JsRender/PlainFile.vala +++ b/src/JsRender/PlainFile.vala @@ -21,7 +21,7 @@ namespace JsRender { public PlainFile(Project.Project project, string path) { - aconstruct( project, path); + base( project, path); this.xtype = "PlainFile"; this.content_type = "text/plain"; @@ -158,6 +158,18 @@ namespace JsRender { return this.path; } + + public override string language_id() + { + switch(this.file_ext) { + case "js": return "javascript"; + case "vala": return "vala"; + case "php": return "php"; + case "css": return "css"; + case "sql": return "sql"; + default: return "???"; + } + } } diff --git a/src/JsRender/Roo.vala b/src/JsRender/Roo.vala index e62bbee67..582984d8e 100644 --- a/src/JsRender/Roo.vala +++ b/src/JsRender/Roo.vala @@ -25,7 +25,7 @@ namespace JsRender { public Roo(Project.Roo project, string path) { - aconstruct( project, path); + base( project, path); this.xtype = "Roo"; this.language = "js"; @@ -406,7 +406,7 @@ namespace JsRender { if (xinc.size > 0 ) { for(var i = 0; i < xinc.size; i++) { print("check xinclude: %s\n", xinc.get(i)); - var sf = this.project.getByName(xinc.get(i)); + var sf = this.project.getByRelPath(xinc.get(i)); if (sf == null) { print("Failed to find file by name?\n"); continue; @@ -799,6 +799,10 @@ namespace JsRender { { return "Roo files do not convert to glade"; } + public override string language_id() + { + return "javascript"; + } } } diff --git a/src/Lsp.vala b/src/Lsp.vala new file mode 100644 index 000000000..b5c4f00cb --- /dev/null +++ b/src/Lsp.vala @@ -0,0 +1,1376 @@ +/* protocol.vala + * + * Copyright 2017-2019 Ben Iofel + * Copyright 2017-2020 Princeton Ferro + * Copyright 2020 Sergii Fesenko + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +namespace Lsp { + /** + * Defines how the host (editor) should sync document changes to the language server. + */ + [CCode (default_value = "LSP_TEXT_DOCUMENT_SYNC_KIND_Unset")] + public enum TextDocumentSyncKind { + Unset = -1, + /** + * Documents should not be synced at all. + */ + None = 0, + /** + * Documents are synced by always sending the full content of the document. + */ + Full = 1, + /** + * Documents are synced by sending the full content on open. After that only incremental + * updates to the document are sent. + */ + Incremental = 2 + } + + public enum DiagnosticSeverity { + Unset = 0, + /** + * Reports an error. + */ + Error = 1, + /** + * Reports a warning. + */ + Warning = 2, + /** + * Reports an information. + */ + Information = 3, + /** + * Reports a hint. + */ + Hint = 4 + + } + + public class Position : Object, Gee.Comparable { + /** + * Line position in a document (zero-based). + */ + public uint line { get; set; default = -1; } + + /** + * Character offset on a line in a document (zero-based). Assuming that the line is + * represented as a string, the `character` value represents the gap between the + * `character` and `character + 1`. + * + * If the character value is greater than the line length it defaults back to the + * line length. + */ + public uint character { get; set; default = -1; } + + public int compare_to (Position other) { + return line > other.line ? 1 : + (line == other.line ? + (character > other.character ? 1 : + (character == other.character ? 0 : -1)) : -1); + } + + public string to_string () { + return @"$line:$character"; + } + + public Position.from_libvala (Vala.SourceLocation sloc) { + line = sloc.line - 1; + character = sloc.column; + } + + public Position dup () { + return this.translate (); + } + + public Position translate (int dl = 0, int dc = 0) { + return new Position () { + line = this.line + dl, + character = this.character + dc + }; + } + } + + public class Range : Object, Gee.Hashable, Gee.Comparable { + /** + * The range's start position. + */ + public Position start { get; set; } + + /** + * The range's end position. + */ + public Position end { get; set; } + + private string? filename; + + public string to_string () { return (filename != null ? @"$filename:" : "") + @"$start -> $end"; } + + public Range.from_pos (Position pos) { + this.start = pos; + this.end = pos.dup (); + } + + public Range.from_sourceref (Vala.SourceReference sref) { + this.start = new Position.from_libvala (sref.begin); + this.end = new Position.from_libvala (sref.end); + this.start.character -= 1; + this.filename = sref.file.filename; + } + + public uint hash () { + return this.to_string ().hash (); + } + + public bool equal_to (Range other) { return this.to_string () == other.to_string (); } + + public int compare_to (Range other) { + return start.compare_to (other.start); + } + + /** + * Return a new range that includes `this` and `other`. + */ + public Range union (Range other) { + var range = new Range () { + start = start.compare_to (other.start) < 0 ? start : other.start, + end = end.compare_to (other.end) < 0 ? other.end : end, + }; + if (filename == other.filename) + range.filename = filename; + return range; + } + + public bool contains (Position pos) { + return start.compare_to (pos) <= 0 && pos.compare_to (end) <= 0; + } + } + + public class Diagnostic : Object { + /** + * The range at which the message applies. + */ + public Range range { get; set; } + + /** + * The diagnostic's severity. Can be omitted. If omitted it is up to the + * client to interpret diagnostics as error, warning, info or hint. + */ + public DiagnosticSeverity severity { get; set; } + + /** + * The diagnostic's code. Can be omitted. + */ + public string? code { get; set; } + + /** + * A human-readable string describing the source of this + * diagnostic, e.g. 'typescript' or 'super lint'. + */ + public string? source { get; set; } + + /** + * The diagnostic's message. + */ + public string message { get; set; } + + + public string category { + get { + switch(this.severity) { + + case DiagnosticSeverity.Error : + return "ERR"; + case DiagnosticSeverity.Warning : + return this.message.contains("deprecated") ? "DEPR" : "WARN"; + default : + return "WARN"; + } + } + private set {} + + } + } + + /** + * An event describing a change to a text document. If range and rangeLength are omitted + * the new text is considered to be the full content of the document. + */ + public class TextDocumentContentChangeEvent : Object { + public Range? range { get; set; } + public int rangeLength { get; set; } + public string text { get; set; } + } + + public enum MessageType { + /** + * An error message. + */ + Error = 1, + /** + * A warning message. + */ + Warning = 2, + /** + * An information message. + */ + Info = 3, + /** + * A log message. + */ + Log = 4 + } + + public class TextDocumentIdentifier : Object { + public string uri { get; set; } + } + + public class VersionedTextDocumentIdentifier : TextDocumentIdentifier { + /** + * The version number of this document. If a versioned text document identifier + * is sent from the server to the client and the file is not open in the editor + * (the server has not received an open notification before) the server can send + * `null` to indicate that the version is known and the content on disk is the + * master (as speced with document content ownership). + * + * The version number of a document will increase after each change, including + * undo/redo. The number doesn't need to be consecutive. + */ + public int version { get; set; default = -1; } + } + + public class TextDocumentPositionParams : Object { + public TextDocumentIdentifier textDocument { get; set; } + public Position position { get; set; } + } + + public class ReferenceParams : TextDocumentPositionParams { + public class ReferenceContext : Object { + public bool includeDeclaration { get; set; } + } + public ReferenceContext? context { get; set; } + } + + public class Location : Object { + public string uri { get; set; } + public Range range { get; set; } + + public Location.from_sourceref (Vala.SourceReference sref) { + this (sref.file.filename, new Range.from_sourceref (sref)); + } + + public Location (string filename, Range range) { + this.uri = File.new_for_commandline_arg (filename).get_uri (); + this.range = range; + } + } + + [CCode (default_value = "LSP_DOCUMENT_HIGHLIGHT_KIND_Text")] + public enum DocumentHighlightKind { + Text = 1, + Read = 2, + Write = 3 + } + + public class DocumentHighlight : Object { + public Range range { get; set; } + public DocumentHighlightKind kind { get; set; } + } + + public class DocumentSymbolParams: Object { + public TextDocumentIdentifier textDocument { get; set; } + } + + public class DocumentSymbol : Object, Json.Serializable { + private Vala.SourceReference? _source_reference; + public string name { get; set; } + public string? detail { get; set; } + public SymbolKind kind { get; set; } + public bool deprecated { get; set; } + private Range? _initial_range; + public Range range { + owned get { + if (_initial_range == null) + _initial_range = new Range.from_sourceref (children.first ()._source_reference); + + return children.fold ((child, current_range) => current_range.union (child.range), _initial_range); + } + } + public Range selectionRange { get; set; } + public Gee.List children { get; private set; default = new Gee.LinkedList (); } + public string? parent_name; + + private DocumentSymbol () {} + + /** + * @param type the data type containing this symbol, if there was one (not available for Namespaces, for example) + * @param sym the symbol + */ + /* + public DocumentSymbol.from_vala_symbol (Vala.DataType? type, Vala.Symbol sym, SymbolKind kind) { + this.parent_name = sym.parent_symbol != null ? sym.parent_symbol.name : null; + this._initial_range = new Range.from_sourceref (sym.source_reference); + if (sym is Vala.Subroutine) { + var sub = (Vala.Subroutine) sym; + var body_sref = sub.body != null ? sub.body.source_reference : null; + // debug ("subroutine %s found (body @ %s)", sym.get_full_name (), + // body_sref != null ? body_sref.to_string () : null); + if (body_sref != null && (body_sref.begin.line < body_sref.end.line || + body_sref.begin.line == body_sref.end.line && body_sref.begin.pos <= body_sref.end.pos)) { + this._initial_range = this._initial_range.union (new Range.from_sourceref (body_sref)); + } + } + this.name = sym.name; + this.detail = Vls.CodeHelp.get_symbol_representation (type, sym, null, false); + this.kind = kind; + this.selectionRange = new Range.from_sourceref (sym.source_reference); + this.deprecated = sym.version.deprecated; + } + */ + public new void Json.Serializable.set_property (ParamSpec pspec, Value value) { + base.set_property (pspec.get_name (), value); + } + + public new Value Json.Serializable.get_property (ParamSpec pspec) { + Value val = Value (pspec.value_type); + base.get_property (pspec.get_name (), ref val); + return val; + } + + public unowned ParamSpec? find_property (string name) { + return this.get_class ().find_property (name); + } + + public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) { + if (property_name != "children") + return default_serialize_property (property_name, value, pspec); + var node = new Json.Node (Json.NodeType.ARRAY); + node.init_array (new Json.Array ()); + var array = node.get_array (); + foreach (var child in children) + array.add_element (Json.gobject_serialize (child)); + return node; + } + + public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) { + error ("deserialization not supported"); + } + } + + public class SymbolInformation : Object { + public string name { get; set; } + public SymbolKind kind { get; set; } + public Location location { get; set; } + public string? containerName { get; set; } + + public SymbolInformation.from_document_symbol (DocumentSymbol dsym, string uri) { + this.name = dsym.name; + this.kind = dsym.kind; + this.location = new Location (uri, dsym.range); + this.containerName = dsym.parent_name; + } + } + + [CCode (default_value = "LSP_SYMBOL_KIND_Variable")] + public enum SymbolKind { + File = 1, + Module = 2, + Namespace = 3, + Package = 4, + Class = 5, + Method = 6, + Property = 7, + Field = 8, + Constructor = 9, + Enum = 10, + Interface = 11, + Function = 12, + Variable = 13, + Constant = 14, + String = 15, + Number = 16, + Boolean = 17, + Array = 18, + Object = 19, + Key = 20, + Null = 21, + EnumMember = 22, + Struct = 23, + Event = 24, + Operator = 25, + TypeParameter = 26 + } + + public class CompletionList : Object, Json.Serializable { + public bool isIncomplete { get; set; } + public Gee.List items { get; private set; default = new Gee.LinkedList (); } + + public new void Json.Serializable.set_property (ParamSpec pspec, Value value) { + base.set_property (pspec.get_name (), value); + } + + public new Value Json.Serializable.get_property (ParamSpec pspec) { + Value val = Value(pspec.value_type); + base.get_property (pspec.get_name (), ref val); + return val; + } + + public unowned ParamSpec? find_property (string name) { + return this.get_class ().find_property (name); + } + + public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) { + if (property_name != "items") + return default_serialize_property (property_name, value, pspec); + var node = new Json.Node (Json.NodeType.ARRAY); + node.init_array (new Json.Array ()); + var array = node.get_array (); + foreach (var child in items) + array.add_element (Json.gobject_serialize (child)); + return node; + } + + public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) { + error ("deserialization not supported"); + } + } + + [CCode (default_value = "LSP_COMPLETION_TRIGGER_KIND_Invoked")] + public enum CompletionTriggerKind { + /** + * Completion was triggered by typing an identifier (24x7 code + * complete), manual invocation (e.g Ctrl+Space) or via API. + */ + Invoked = 1, + + /** + * Completion was triggered by a trigger character specified by + * the `triggerCharacters` properties of the `CompletionRegistrationOptions`. + */ + TriggerCharacter = 2, + + /** + * Completion was re-triggered as the current completion list is incomplete. + */ + TriggerForIncompleteCompletions = 3 + } + + public class CompletionContext : Object { + public CompletionTriggerKind triggerKind { get; set;} + public string? triggerCharacter { get; set; } + } + + public class CompletionParams : TextDocumentPositionParams { + /** + * The completion context. This is only available if the client specifies + * to send this using `ClientCapabilities.textDocument.completion.contextSupport === true` + */ + public CompletionContext? context { get; set; } + } + + public enum CompletionItemTag { + // Render a completion as obsolete, usually using a strike-out. + Deprecated = 1, + } + + [CCode (default_value = "LSP_INSERT_TEXT_FORMAT_PlainText")] + public enum InsertTextFormat { + /** + * The primary text to be inserted is treated as a plain string. + */ + PlainText = 1, + + /** + * The primary text to be inserted is treated as a snippet. + * + * A snippet can define tab stops and placeholders with `$1`, `$2` + * and `${3:foo}`. `$0` defines the final tab stop, it defaults to + * the end of the snippet. Placeholders with equal identifiers are linked, + * that is typing in one will update others too. + */ + Snippet = 2, + } + + public class CompletionItem : Object, Gee.Hashable, Json.Serializable { + public string label { get; set; } + public CompletionItemKind kind { get; set; } + public string detail { get; set; } + public MarkupContent? documentation { get; set; } + public bool deprecated { get; set; } + public Gee.List tags { get; private set; default = new Gee.ArrayList (); } + public string? insertText { get; set; } + public InsertTextFormat insertTextFormat { get; set; default = InsertTextFormat.PlainText; } + private uint _hash; + + private CompletionItem () {} + + public CompletionItem.keyword (string keyword, string? insert_text = null, string? documentation = null) { + this.label = keyword; + this.kind = CompletionItemKind.Keyword; + this.insertText = insert_text; + if (insert_text != null && (insert_text.contains ("$0") || insert_text.contains ("${0"))) + this.insertTextFormat = InsertTextFormat.Snippet; + if (documentation != null) + this.documentation = new MarkupContent.from_plaintext (documentation); + this._hash = @"$label $kind".hash (); + } + + /** + * A completion suggestion from an existing Vala symbol. + * + * @param instance_type the parent data type of data type of the expression where this symbol appears, or null + * @param sym the symbol itself + * @param scope the scope to display this in + * @param kind the kind of completion to display + * @param documentation the documentation to display + * @param label_override if non-null, override the displayed symbol name with this + */ + /* + public CompletionItem.from_symbol (Vala.DataType? instance_type, Vala.Symbol sym, Vala.Scope? scope, + CompletionItemKind kind, + Vls.DocComment? documentation, string? label_override = null) { + this.label = label_override ?? sym.name; + this.kind = kind; + this.detail = Vls.CodeHelp.get_symbol_representation (instance_type, sym, scope, true, null, label_override, false); + this._hash = @"$label $kind".hash (); + + if (documentation != null) + this.documentation = new MarkupContent.from_markdown (documentation.body); + + var version = sym.get_attribute ("Version"); + if (version != null && (version.get_bool ("deprecated") || version.get_string ("deprecated_since") != null)) { + this.tags.add (CompletionItemTag.Deprecated); + this.deprecated = true; + }public + } + */ + /** + * A completion suggestion from a data type and a synthetic symbol name. + * + * @param symbol_type the data type of the symbol + * @param symbol_name the name of the synthetic symbol + * @param scope the scope that this completion item is displayed in, or null + * @param kind the type of completion to display + * @param documentation the documentation for this symbol, or null + */ + /* + public CompletionItem.from_synthetic_symbol (Vala.DataType symbol_type, string symbol_name, Vala.Scope? scope, + CompletionItemKind kind, Vls.DocComment? documentation) { + this.label = symbol_name; + this.kind = kind; + this.detail = @"$(Vls.CodeHelp.get_symbol_representation (symbol_type, null, scope, true, null, null, false)) $symbol_name"; + this._hash = @"$label $kind".hash (); + + if (documentation != null) + this.documentation = new MarkupContent.from_markdown (documentation.body); + } + */ + /* + public CompletionItem.from_unimplemented_symbol (Vala.Symbol sym, + string label, CompletionItemKind kind, + string insert_text, + Vls.DocComment? documentation) { + this.label = label; + this.kind = kind; + this.insertText = insert_text; + if (insert_text.contains ("$0") || insert_text.contains ("${0")) + this.insertTextFormat = InsertTextFormat.Snippet; + this._hash = @"$label $kind".hash (); + if (documentation != null) + this.documentation = new MarkupContent.from_markdown (documentation.body); + } + */ + + public uint hash () { + return this._hash; + } + + public bool equal_to (CompletionItem other) { + return other.label == this.label && other.kind == this.kind; + } + + public new void Json.Serializable.set_property (ParamSpec pspec, Value value) { + base.set_property (pspec.get_name (), value); + } + + public new Value Json.Serializable.get_property (ParamSpec pspec) { + Value val = Value(pspec.value_type); + base.get_property (pspec.get_name (), ref val); + return val; + } + + public unowned ParamSpec? find_property (string name) { + return this.get_class ().find_property (name); + } + + public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) { + if (property_name != "tags") + return default_serialize_property (property_name, value, pspec); + + var node = new Json.Node (Json.NodeType.ARRAY); + node.init_array (new Json.Array ()); + var array = node.get_array (); + foreach (var tag in this.tags) { + array.add_int_element (tag); + } + + return node; + } + public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) + { + if (property_name != "tags") { + return default_deserialize_property (property_name, out value, pspec, property_node); + } + if (property_node.get_node_type () != Json.NodeType.ARRAY) { + warning ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ()); + return false; + } + + var arguments = new Gee.ArrayList(); + + property_node.get_array ().foreach_element ((array, index, element) => { + try { + arguments.add ((CompletionItemTag) Json.gvariant_deserialize (element, null).get_int32() ); + } catch (Error e) { + warning ("argument %u to command could not be deserialized: %s", index, e.message); + } + }); + + value.set_boxed (arguments); + return true; + } + } + + public class MarkupContent : Object { + public string kind { get; set; } + public string value { get; set; } + + private MarkupContent () {} + + /** + * Create a MarkupContent with plain text. + */ + public MarkupContent.from_plaintext (string doc) { + this.kind = "plaintext"; + this.value = doc; + } + + /** + * Create a MarkupContent with markdown text. + */ + public MarkupContent.from_markdown (string doc) { + this.kind = "markdown"; + this.value = doc; + } + } + + [CCode (default_value = "LSP_COMPLETION_ITEM_KIND_Text")] + public enum CompletionItemKind { + Text = 1, + Method = 2, + Function = 3, + Constructor = 4, + Field = 5, + Variable = 6, + Class = 7, + Interface = 8, + Module = 9, + Property = 10, + Unit = 11, + Value = 12, + Enum = 13, + Keyword = 14, + Snippet = 15, + Color = 16, + File = 17, + Reference = 18, + Folder = 19, + EnumMember = 20, + Constant = 21, + Struct = 22, + Event = 23, + Operator = 24, + TypeParameter = 25 + } + + /** + * Capabilities of the client/editor for `textDocument/documentSymbol` + */ + public class DocumentSymbolCapabilities : Object { + public bool hierarchicalDocumentSymbolSupport { get; set; } + } + + /** + * Capabilities of the client/editor for `textDocument/rename` + */ + public class RenameClientCapabilities : Object { + public bool prepareSupport { get; set; } + } + + /** + * Capabilities of the client/editor pertaining to language features. + */ + public class TextDocumentClientCapabilities : Object { + public DocumentSymbolCapabilities documentSymbol { get; set; default = new DocumentSymbolCapabilities ();} + public RenameClientCapabilities rename { get; set; default = new RenameClientCapabilities (); } + } + + /** + * Capabilities of the client/editor. + */ + public class ClientCapabilities : Object { + public TextDocumentClientCapabilities textDocument { get; set; default = new TextDocumentClientCapabilities (); } + } + + public class InitializeParams : Object { + public int processId { get; set; } + public string? rootPath { get; set; } + public string? rootUri { get; set; } + public ClientCapabilities capabilities { get; set; default = new ClientCapabilities (); } + } + + public class SignatureInformation : Object, Json.Serializable { + public string label { get; set; } + public MarkupContent documentation { get; set; } + + public Gee.List parameters { get; private set; default = new Gee.LinkedList (); } + + public new void Json.Serializable.set_property (ParamSpec pspec, Value value) { + base.set_property (pspec.get_name (), value); + } + + public new Value Json.Serializable.get_property (ParamSpec pspec) { + Value val = Value(pspec.value_type); + base.get_property (pspec.get_name (), ref val); + return val; + } + + public unowned ParamSpec? find_property (string name) { + return this.get_class ().find_property (name); + } + + public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) { + if (property_name != "parameters") + return default_serialize_property (property_name, value, pspec); + var node = new Json.Node (Json.NodeType.ARRAY); + node.init_array (new Json.Array ()); + var array = node.get_array (); + foreach (var child in parameters) + array.add_element (Json.gobject_serialize (child)); + return node; + } + + public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) { + error ("deserialization not supported"); + } + } + + public class SignatureHelp : Object, Json.Serializable { + public Gee.Collection signatures { get; set; default = new Gee.ArrayList (); } + public int activeSignature { get; set; } + public int activeParameter { get; set; } + + public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) { + if (property_name != "signatures") + return default_serialize_property (property_name, value, pspec); + + var node = new Json.Node (Json.NodeType.ARRAY); + node.init_array (new Json.Array ()); + var array = node.get_array (); + foreach (var child in signatures) + array.add_element (Json.gobject_serialize (child)); + return node; + } + + public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) { + error ("deserialization not supported"); + } + } + + public class ParameterInformation : Object { + public string label { get; set; } + public MarkupContent documentation { get; set; } + } + + public class MarkedString : Object { + public string language { get; set; } + public string value { get; set; } + } + + public class Hover : Object, Json.Serializable { + public Gee.List contents { get; set; default = new Gee.ArrayList (); } + public Range range { get; set; } + + public new void Json.Serializable.set_property (ParamSpec pspec, Value value) { + base.set_property (pspec.get_name (), value); + } + + public new Value Json.Serializable.get_property (ParamSpec pspec) { + Value val = Value(pspec.value_type); + base.get_property (pspec.get_name (), ref val); + return val; + } + + public unowned ParamSpec? find_property (string name) { + return this.get_class ().find_property (name); + } + + public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) { + if (property_name != "contents") + return default_serialize_property (property_name, value, pspec); + var node = new Json.Node (Json.NodeType.ARRAY); + node.init_array (new Json.Array ()); + var array = node.get_array (); + foreach (var child in contents) { + if (child.language != null) + array.add_element (Json.gobject_serialize (child)); + else + array.add_element (new Json.Node (Json.NodeType.VALUE).init_string (child.value)); + } + return node; + } + + public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) { + error ("deserialization not supported"); + } + } + + /** + * A textual edit applicable to a text document. + */ + public class TextEdit : Object { + /** + * The range of the text document to be manipulated. To insert + * text into a document create a range where ``start === end``. + */ + public Range range { get; set; } + + /** + * The string to be inserted. For delete operations use an + * empty string. + */ + public string newText { get; set; } + + public TextEdit (Range range, string new_text = "") { + this.range = range; + this.newText = new_text; + } + } + + /** + * Describes textual changes on a single text document. The text document is + * referred to as a {@link VersionedTextDocumentIdentifier} to allow clients to + * check the text document version before an edit is applied. A + * {@link TextDocumentEdit} describes all changes on a version ``Si`` and after they are + * applied move the document to version ``Si+1``. So the creator of a + * {@link TextDocumentEdit} doesn’t need to sort the array of edits or do any kind + * of ordering. However the edits must be non overlapping. + */ + public class TextDocumentEdit : Object, Json.Serializable { + /** + * The text document to change. + */ + public VersionedTextDocumentIdentifier textDocument { get; set; } + + /** + * The edits to be applied. + */ + public Gee.ArrayList edits { get; set; default = new Gee.ArrayList (); } + + public TextDocumentEdit (VersionedTextDocumentIdentifier text_document) { + this.textDocument = text_document; + } + + public Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) { + if (property_name != "edits") + return default_serialize_property (property_name, value, pspec); + + var node = new Json.Node (Json.NodeType.ARRAY); + node.init_array (new Json.Array ()); + var array = node.get_array (); + foreach (var text_edit in edits) { + array.add_element (Json.gobject_serialize (text_edit)); + } + return node; + } + + public bool deserialize_property (string property_name, out GLib.Value value, GLib.ParamSpec pspec, Json.Node property_node) { + error ("deserialization not supported"); + } + } + + public abstract class CommandLike : Object, Json.Serializable { + /** + * The identifier of the actual command handler. + */ + public string command { get; set; } + + /** + * Arguments that the command handler should be invoked with. + */ + public Array? arguments { get; set; } + + public Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) { + if (property_name != "arguments" || arguments == null) + return default_serialize_property (property_name, value, pspec); + + var array = new Json.Array (); + for (int i = 0; i < arguments.length; i++) + array.add_element (Json.gvariant_serialize (arguments.index (i))); + + var node = new Json.Node (Json.NodeType.ARRAY); + node.set_array (array); + return node; + } + + public bool deserialize_property (string property_name, out GLib.Value value, GLib.ParamSpec pspec, Json.Node property_node) { + if (property_name == "arguments") { + value = Value (typeof (Array)); + if (property_node.get_node_type () != Json.NodeType.ARRAY) { + warning ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ()); + return false; + } + + var arguments = new Array (); + + property_node.get_array ().foreach_element ((array, index, element) => { + try { + arguments.append_val (Json.gvariant_deserialize (element, null)); + } catch (Error e) { + warning ("argument %u to command could not be deserialized: %s", index, e.message); + } + }); + + value.set_boxed (arguments); + return true; + } else if (property_name == "command") { + // workaround for json-glib < 1.5.2 (Ubuntu 20.04 / eOS 6) + if (property_node.get_value_type () != typeof (string)) { + value = ""; + warning ("unexpected property node type for 'commands' %s", property_node.get_node_type ().to_string ()); + return false; + } + + value = property_node.get_string (); + return true; + } else { + return default_deserialize_property (property_name, out value, pspec, property_node); + } + } + } + + public class ExecuteCommandParams : CommandLike { + } + + /** + * Represents a reference to a command. Provides a title which will be used + * to represent a command in the UI. Commands are identified by a string + * identifier. The recommended way to handle commands is to implement their + * execution on the server side if the client and server provides the + * corresponding capabilities. Alternatively the tool extension code could + * handle the command. The protocol currently doesn’t specify a set of + * well-known commands. + */ + public class Command : CommandLike { + /** + * The title of the command, like `save`. + */ + public string title { get; set; } + } + + /** + * A code lens represents a command that should be shown along with + * source text, like the number of references, a way to run tests, etc. + * + * A code lens is _unresolved_ when no command is associated to it. For + * performance reasons the creation of a code lens and resolving should be done + * in two stages. + */ + public class CodeLens : Object { + /** + * The range in which this code lens is valid. Should only span a single + * line. + */ + public Range range { get; set; } + + /** + * The command this code lens represents. + */ + public Command? command { get; set; } + } + + public class DocumentRangeFormattingParams : Object { + public TextDocumentIdentifier textDocument { get; set; } + public Range? range { get; set; } + public FormattingOptions options { get; set; } + } + + public class FormattingOptions : Object { + public uint tabSize { get; set; } + public bool insertSpaces { get; set; } + public bool trimTrailingWhitespace { get; set; } + public bool insertFinalNewline { get; set; } + public bool trimFinalNewlines { get; set; } + } + + public class CodeActionParams : Object { + public TextDocumentIdentifier textDocument { get; set; } + public Range range { get; set; } + public CodeActionContext context { get; set; } + } + + + public class CodeActionContext : Object, Json.Serializable { + public Gee.List diagnostics { get; set; default = new Gee.ArrayList (); } + public string[]? only { get; set; } +/* + public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) { + if (property_name != "diagnostics") + return default_deserialize_property (property_name, out value, pspec, property_node); + var diags = new Gee.ArrayList (); + property_node.get_array ().foreach_element ((array, index, element) => { + try { + diags.add (Vls.Util.parse_variant (Json.gvariant_deserialize (element, null))); + } catch (Error e) { + warning ("argument %u could not be deserialized: %s", index, e.message); + } + }); + value = diags; + return true; + } + */ + } + + + public class Diagnostics : Object, Json.Serializable + { + public string uri { get; set; } + + public int version { get; set; default = 0; } + public Gee.ArrayList? diagnostics { get; set; } + + public string filename { + owned get { + return File.new_for_uri (this.uri).get_path(); + } + private set {} + } + + public bool deserialize_property (string property_name, out GLib.Value val, GLib.ParamSpec pspec, Json.Node property_node) { + if (property_name == "diagnostics") { + var diags = new Gee.ArrayList (); + if (property_node.get_node_type () != Json.NodeType.ARRAY) { + val = diags; + warning ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ()); + return false; + } + + + + property_node.get_array ().foreach_element ((array, index, element) => { + + diags.add (Json.gobject_deserialize (typeof (Lsp.Diagnostic), element) as Diagnostic ); + + //warning ("argument %u to command could not be deserialized: %s", index, e.message); + + }); + val = diags; + + return true; + } + + return default_deserialize_property (property_name, out val, pspec, property_node); + + } + + + } + + + public class CodeAction : Object, Json.Serializable { + public string title { get; set; } + public string? kind { get; set; } + public Gee.Collection? diagnostics { get; set; } + public bool isPreferred { get; set; } + public WorkspaceEdit? edit { get; set; } + public Command? command { get; set; } + public Object? data { get; set; } + + protected void add_diagnostic (Diagnostic diag) { + if (diagnostics == null) + diagnostics = new Gee.ArrayList (); + diagnostics.add (diag); + } + + public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) { + if (property_name != "diagnostics") + return default_serialize_property (property_name, value, pspec); + + var array = new Json.Array (); + if (diagnostics != null) + foreach (var text_edit in diagnostics) + array.add_element (Json.gobject_serialize (text_edit)); + return new Json.Node.alloc ().init_array (array); + } + } + + public class WorkspaceEdit : Object, Json.Serializable { + public Gee.List? documentChanges { get; set; } + + public Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) { + if (property_name != "documentChanges") + return default_serialize_property (property_name, value, pspec); + + var node = new Json.Node (Json.NodeType.ARRAY); + node.init_array (new Json.Array ()); + if (documentChanges != null) { + var array = node.get_array (); + foreach (var text_edit in documentChanges) { + array.add_element (Json.gobject_serialize (text_edit)); + } + } + return node; + } + } + + [Flags] + public enum SymbolTags { + NONE, + DEPRECATED + } + + public class CallHierarchyItem : Object, Json.Serializable { + public string name { get; set; } + public SymbolKind kind { get; set; } + public SymbolTags tags { get; set; } + public string? detail { get; set; } + public string uri { get; set; } + public Range range { get; set; } + public Range selectionRange { get; set; } + + public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) { + if (property_name != "tags") + return default_serialize_property (property_name, value, pspec); + var array = new Json.Array (); + if (SymbolTags.DEPRECATED in tags) + array.add_int_element (SymbolTags.DEPRECATED); + return new Json.Node.alloc ().init_array (array); + } +/* + public CallHierarchyItem.from_symbol (Vala.Symbol symbol) { + this.name = symbol.get_full_name (); + if (symbol is Vala.Method) { + if (symbol.parent_symbol is Vala.Namespace) + this.kind = SymbolKind.Function; + else + this.kind = SymbolKind.Method; + } else if (symbol is Vala.Signal) { + this.kind = SymbolKind.Event; + } else if (symbol is Vala.Constructor) { + this.kind = SymbolKind.Constructor; + } else { + this.kind = SymbolKind.Method; + } + var version = symbol.get_attribute ("Version"); + if (version != null && (version.get_bool ("deprecated") || version.get_string ("deprecated_since") != null)) { + this.tags |= SymbolTags.DEPRECATED; + } + this.detail = Vls.CodeHelp.get_symbol_representation (null, symbol, null, true); + this.uri = File.new_for_commandline_arg (symbol.source_reference.file.filename).get_uri (); + this.range = new Range.from_sourceref (symbol.source_reference); + if (symbol.comment != null) + this.range = new Range.from_sourceref (symbol.comment.source_reference).union (this.range); + if (symbol is Vala.Subroutine && ((Vala.Subroutine)symbol).body != null) + this.range = new Range.from_sourceref (((Vala.Subroutine)symbol).body.source_reference).union (this.range); + this.selectionRange = new Range.from_sourceref (symbol.source_reference); + } + */ + } + + public class CallHierarchyIncomingCall : Json.Serializable, Object { + /** + * The method that calls the query method. + */ + public CallHierarchyItem from { get; set; } + + /** + * The ranges at which the query method is called by `from`. + */ + public Gee.ArrayList fromRanges { get; set; default = new Gee.ArrayList (); } + + public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) { + if (property_name == "from") + return default_serialize_property (property_name, value, pspec); + var array = new Json.Array (); + foreach (var range in fromRanges) + array.add_element (Json.gobject_serialize (range)); + return new Json.Node.alloc ().init_array (array); + } + } + + public class CallHierarchyOutgoingCall : Json.Serializable, Object { + /** + * The method that the query method calls. + */ + public CallHierarchyItem to { get; set; } + + /** + * The ranges at which the method is called by the query method. + */ + public Gee.ArrayList fromRanges { get; set; default = new Gee.ArrayList (); } + + public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) { + if (property_name == "to") + return default_serialize_property (property_name, value, pspec); + var array = new Json.Array (); + foreach (var range in fromRanges) + array.add_element (Json.gobject_serialize (range)); + return new Json.Node.alloc ().init_array (array); + } + } + + public class InlayHintParams : Json.Serializable, Object { + public TextDocumentIdentifier textDocument { get; set; } + public Range range { get; set; } + } + + public enum InlayHintKind { + UNSET, + TYPE, + PARAMETER + } + + public class InlayHint : Object { + public Position position { get; set; } + public string label { get; set; } + public InlayHintKind kind { get; set; } + public string? tooltip { get; set; } + public bool paddingLeft { get; set; } + public bool paddingRight { get; set; } + } + + public class TypeHierarchyItem : Object, Json.Serializable { + /** + * The name of this item + */ + public string name { get; set; } + + /** + * The kind of this item + */ + public SymbolKind kind { get; set; } + + /** + * Tags for this item + */ + public SymbolTags tags { get; set; } + + /** + * More detail for this item, e.g. the signature of a function. + */ + public string? detail { get; set; } + + /** + * The resource identifier of this item. + */ + public string uri { get; set; } + + /** + * The range enclosing this symbol not including leading/trailing + * whitespace, but everything else, e.g. comments and code. + */ + public Range range { get; set; } + + /** + * The range that should be selected and revealed when this symbol + * is being picked, e.g. the name of a function. Must be contained + * by {@link TypeHierarchyItem.range} + */ + public Range selectionRange { get; set; } + + private TypeHierarchyItem () {} +/* + public TypeHierarchyItem.from_symbol (Vala.TypeSymbol symbol) { + this.name = symbol.get_full_name (); + if (symbol is Vala.Class) + this.kind = SymbolKind.Class; + else if (symbol is Vala.Delegate) + this.kind = SymbolKind.Interface; + else if (symbol is Vala.Enum) + this.kind = SymbolKind.Enum; + else if (symbol is Vala.ErrorCode) + this.kind = SymbolKind.EnumMember; + else if (symbol is Vala.ErrorDomain) + this.kind = SymbolKind.Enum; + else if (symbol is Vala.Interface) + this.kind = SymbolKind.Interface; + else if (symbol is Vala.Struct) + this.kind = SymbolKind.Struct; + else if (symbol is Vala.TypeParameter) + this.kind = SymbolKind.TypeParameter; + else { + this.kind = SymbolKind.Module; + warning ("unexpected symbol kind in type hierarchy: `%s'", symbol.type_name); + } + + var version = symbol.get_attribute ("Version"); + if (version != null && (version.get_bool ("deprecated") || version.get_string ("deprecated_since") != null)) { + this.tags |= SymbolTags.DEPRECATED; + } + this.detail = Vls.CodeHelp.get_symbol_representation (null, symbol, null, true); + this.uri = File.new_for_commandline_arg (symbol.source_reference.file.filename).get_uri (); + this.range = new Range.from_sourceref (symbol.source_reference); + this.selectionRange = this.range; + + // widen range to include all members + if (symbol is Vala.ObjectTypeSymbol) { + foreach (var member in ((Vala.ObjectTypeSymbol)symbol).get_members ()) { + if (member.source_reference != null) + this.range = this.range.union (new Range.from_sourceref (member.source_reference)); + } + } else if (symbol is Vala.Enum) { + foreach (var member in ((Vala.Enum)symbol).get_values ()) { + if (member.source_reference != null) + this.range = this.range.union (new Range.from_sourceref (member.source_reference)); + } + foreach (var method in ((Vala.Enum)symbol).get_methods ()) { + if (method.source_reference != null) + this.range = this.range.union (new Range.from_sourceref (method.source_reference)); + } + } else if (symbol is Vala.ErrorDomain) { + foreach (var member in ((Vala.ErrorDomain)symbol).get_codes ()) { + if (member.source_reference != null) + this.range = this.range.union (new Range.from_sourceref (member.source_reference)); + } + foreach (var method in ((Vala.ErrorDomain)symbol).get_methods ()) { + if (method.source_reference != null) + this.range = this.range.union (new Range.from_sourceref (method.source_reference)); + } + } else if (symbol is Vala.Struct) { + foreach (var field in ((Vala.Struct)symbol).get_fields ()) { + if (field.source_reference != null) + this.range = this.range.union (new Range.from_sourceref (field.source_reference)); + } + foreach (var method in ((Vala.Struct)symbol).get_methods ()) { + if (method.source_reference != null) + this.range = this.range.union (new Range.from_sourceref (method.source_reference)); + } + } + } + */ + } +} \ No newline at end of file diff --git a/src/Main.vala b/src/Main.vala index 7c08df79c..82465d657 100644 --- a/src/Main.vala +++ b/src/Main.vala @@ -14,6 +14,7 @@ int main (string[] args) { var app = BuilderApplication.singleton( args); Gtk.init (); + GtkSource.init(); // not sure why this was done?? - it caused crash bugs on gtk_Box_gadget so removed critical. diff --git a/src/Makefile.am b/src/Makefile.am index 0c53e8de5..2d5836a1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -149,6 +149,8 @@ roobuilder_PKGS = --pkg glib-2.0 \ --pkg gobject-introspection-1.0 \ --pkg libsoup-3.0 \ --pkg roojspacker-1.4 \ + --pkg jsonrpc-glib-1.0 \ + --pkg gio-unix-2.0 \ $(roobuilder_LIBVALA) \ $(roobuilder_GDA) \ $(roobuilder_WEBKKIT) \ @@ -187,8 +189,10 @@ BUIDERPALETE = Palete/Gir.vala \ Palete/CompletionProvider.vala \ Palete/CompileError.vala \ Palete/ValaCompileRequest.vala \ - Palete/ValaCompileQueue.vala \ Palete/Javascript.vala \ + Palete/LanguageClient.vala \ + Palete/LanguageClientVala.vala \ + Palete/LanguageClientDummy.vala \ $(roobuilder_CODEGEN) # c/jscore_object_call_as_function.c \ @@ -233,6 +237,7 @@ roobuilder_SOURCES = Application.vala \ Main.vala \ Spawn.vala \ Resources.vala \ + Lsp.vala \ $(BUIDERJSRENDER) \ $(BUIDERPALETE) \ $(BUIDERPROJECT) \ diff --git a/src/Palete/CompileError.vala b/src/Palete/CompileError.vala index f78d7e8ce..ef8fcea93 100644 --- a/src/Palete/CompileError.vala +++ b/src/Palete/CompileError.vala @@ -13,14 +13,48 @@ namespace Palete { public JsRender.JsRender file = null; public string title = ""; - public GLib.ListStore lines; + public GLib.ListStore lines { get; set ; } // so it triggers updates? - public CompileError? parent = null; - public string category; - public string msg; + //public CompileError? parent = null; + public string category = ""; + public string msg = ""; public int line { get; set; default = -1; } - public CompileError.new_line(CompileError parent, int line, string msg) + + public CompileError.new_jserror(JsRender.JsRender file, string category, int line, string msg) + { + this.lines = new GLib.ListStore(typeof(CompileError)); + this.line = line; + this.msg = msg; + this.file = file; + this.category = category; + + + } + + public CompileError.new_from_diagnostic(JsRender.JsRender file, Lsp.Diagnostic diag) + { + this.file = file; + this.category = diag.category; + this.line = (int) diag.range.start.line; + this.msg = diag.message; + this.lines = new GLib.ListStore(typeof(CompileError)); + GLib.debug("new error %s : %d %s %s", file.path, this.line, this.category, this.msg); + + + + } + + public CompileError.new_from_file(JsRender.JsRender file, string category) + { + this.file = file; + this.category = category; + this.lines = file.getErrors(category); + this.title = file.relpath + " (" + lines.get_n_items().to_string() + ")"; + } + +/* + public CompileError.new_line(CompileError? parent, int line, string msg) { this.lines = new GLib.ListStore(typeof(CompileError)); this.parent = parent; @@ -31,10 +65,6 @@ namespace Palete { } - - - - public CompileError.new_file(JsRender.JsRender file, Json.Object jlines, string category) { this.file = file; @@ -59,28 +89,35 @@ namespace Palete { }); } - + */ public string file_line { // sorting? set {} owned get { - return this.parent == null ? this.file.relpath : + return this.line == -1 ? this.file.relpath : (this.file.relpath + ":" + this.line.to_string("%09d")); } } - public string line_msg { + public string linemsg { set {} owned get { - return this.parent == null ? + return this.line == -1 ? GLib.Markup.escape_text( this.file.relpath + "(" + this.lines.n_items.to_string() + ")") : GLib.Markup.escape_text(this.line.to_string() + ": " + this.msg); } } - - + + public bool hasErrors() { + return this.lines.get_n_items() > 0; + } + + /* + public static void parseCompileResults (ValaCompileRequest req, Json.Object tree) { - req.errorByFile = new Gee.HashMap(); - req.errorByType = new Gee.HashMap(); + //req.errorByFile = new Gee.HashMap(); + //req.errorByType = new Gee.HashMap(); + + req.errorByType.set("ERR", new GLib.ListStore(typeof(CompileError))); req.errorByType.set("WARN", new GLib.ListStore(typeof(CompileError))); @@ -92,6 +129,7 @@ namespace Palete { } + public static void jsonToListStoreProp(ValaCompileRequest req, string prop, Json.Object tree) { @@ -135,7 +173,7 @@ namespace Palete { req.errorByType.set(prop,ls); } - + // only used by javascript /roo errors.. public static GLib.ListStore jsonToListStore(Project.Project project, Json.Object tree) { @@ -158,7 +196,7 @@ namespace Palete { } - + */ } diff --git a/src/Palete/CompletionProvider.vala b/src/Palete/CompletionProvider.vala index f71cb4351..74cca1f0b 100644 --- a/src/Palete/CompletionProvider.vala +++ b/src/Palete/CompletionProvider.vala @@ -1,18 +1,25 @@ -using Gtk; +//using Gtk; // not sure why - but extending Gtk.SourceCompletionProvider seems to give an error.. namespace Palete { public class CompletionProvider : Object, GtkSource.CompletionProvider { + + public JsRender.JsRender file { + get { return this.editor.file; } + private set {} + } public Editor editor; //public WindowState windowstate; public CompletionModel model; + global::Gtk.StringFilter filter; public CompletionProvider(Editor editor) { this.editor = editor; + // this.windowstate = null; // not ready until the UI is built. } @@ -29,17 +36,19 @@ namespace Palete { public void activate (GtkSource.CompletionContext context, GtkSource.CompletionProposal proposal) { + GLib.debug("compelte activate"); var p = (CompletionProposal) proposal; - TextMark end_mark = null; - TextIter begin, end; + global::Gtk.TextMark end_mark = null; + global::Gtk.TextIter begin, end; if (!context.get_bounds(out begin, out end)) { return; } var buffer = begin.get_buffer(); - var word = p.get_typed_text(); + var word = p.label; var len = -1; + /* If the insertion cursor is within a word and the trailing characters * of the word match the suffix of the proposal, then limit how much @@ -53,7 +62,9 @@ namespace Palete { if (word_end.forward_word_end ()) { var text = end.get_slice(word_end); - + if (text.length > word.length) { + return; + } if (word.has_suffix (text)) { //g_assert (strlen (word) >= strlen (text)); len = word.length - text.length; @@ -80,70 +91,67 @@ namespace Palete { public void display (GtkSource.CompletionContext context, GtkSource.CompletionProposal proposal, GtkSource.CompletionCell cell) { + GLib.debug("compelte display"); var col = cell.get_column(); - //var p = (CompletionProposal) proposal; + + var p = (CompletionProposal) proposal; switch(col) { case GtkSource.CompletionColumn.TYPED_TEXT: - cell.set_icon_name("completion-snippet-symbolic"); + cell.set_text(p.label); break; case GtkSource.CompletionColumn.ICON: - cell.set_text(cell.text); + cell.set_icon_name("completion-snippet-symbolic"); break; case GtkSource.CompletionColumn.COMMENT: - cell.set_text(cell.text); + cell.set_text(p.info); break; case GtkSource.CompletionColumn.DETAILS: - cell.set_text(cell.text); + cell.set_text(p.text); break; default: - cell.set_text(cell.text); + cell.set_text(null); break; } } - public async GLib.ListModel populate_async (GtkSource.CompletionContext context, GLib.Cancellable? cancelleble) + + + internal async GLib.ListModel populate_async (GtkSource.CompletionContext context, GLib.Cancellable? cancellable) { + GLib.debug("pupoulate async"); + + global::Gtk.TextIter begin, end; + Lsp.CompletionList res; + if (context.get_bounds (out begin, out end)) { + yield this.file.getLanguageServer().completion(this.file, end.get_line(), end.get_line_offset(), 1, out res); + } else { + res = null; + } + this.model = new CompletionModel(this, context, res, cancellable); + var word = context.get_word(); - this.model = new CompletionModel(this, context, cancelleble); - return this.model; + + var expression = new global::Gtk.PropertyExpression(typeof(CompletionProposal), null, "label"); + this.filter = new global::Gtk.StringFilter(expression); + this.filter.set_search( word); + var filter_model = new global::Gtk.FilterListModel(this.model, this.filter); + filter.match_mode = global::Gtk.StringFilterMatchMode.PREFIX; + filter_model.set_incremental(true); + return filter_model; + + } - public void refilter (GtkSource.CompletionContext context, GLib.ListModel in_model) + internal void refilter (GtkSource.CompletionContext context, GLib.ListModel in_model) { - - //GtkFilterListModel *filter_model = NULL; - //G//tkExpression *expression = NULL; - //GtkStringFilter *filter = NULL; - //GListModel *replaced_model = NULL; - //char *word; - - var model = in_model; + GLib.debug("pupoulate refilter"); + var word = context.get_word(); - if (model is FilterListModel) { - model = model.get_model (); - } - - - if (!this.model.can_filter(word)) { - this.model.cancel(); - var replaced_model = new CompletionModel(this, context, this.model.cancellable); - context.set_proposals_for_provider(this, replaced_model); - - context.set_proposals_for_provider(this, replaced_model); - return; - } - - var expression = new PropertyExpression(typeof(CompletionProposal), null, "word"); - var filter = new StringFilter(expression); - filter.set_search( word); - var filter_model = new FilterListModel(in_model, filter); - filter_model.set_incremental(true); - context.set_proposals_for_provider(this, filter_model); + this.filter.set_search(word); - } @@ -178,31 +186,25 @@ namespace Palete { Gee.ArrayList items; string search; int minimum_word_size = 2; - public Cancellable cancellable; - public CompletionModel(CompletionProvider provider, GtkSource.CompletionContext context, Cancellable cancellable) + public Cancellable? cancellable; + + public CompletionModel(CompletionProvider provider, GtkSource.CompletionContext context, Lsp.CompletionList? res, Cancellable? cancellable) { this.provider = provider; this.cancellable = cancellable; this.items = new Gee.ArrayList(); - this.search = context.get_word(); - if (this.search.length < this.minimum_word_size) { - return; - } - var prov = this.provider; - - if (prov.editor.window.windowstate == null) { - GLib.debug("Warning - provider windowstate not set?"); - return; - } - // now do our magic.. - this.items = prov.editor.window.windowstate.file.palete().suggestComplete( - prov.editor.window.windowstate.file, - prov.editor.node, - prov.editor.prop, - this.search - ); - + + var word = context.get_word(); + GLib.debug("looking for %s", word); + this.search = word; + if (res != null) { + foreach(var comp in res.items) { + + this.items.add(new CompletionProposal(comp)); + + } + } print("GOT %d results\n", (int) items.size); // WHY TWICE? if (this.items.size < this.minimum_word_size) { @@ -242,11 +244,14 @@ namespace Palete { /* If the new word starts with our initial word, then we can simply * refilter outside this model using a GtkFilterListModel. */ + return word.has_prefix(this.search); } public void cancel () { - this.cancellable.cancel(); + if (this.cancellable != null) { + this.cancellable.cancel(); + } } @@ -255,15 +260,18 @@ namespace Palete { public class CompletionProposal : Object, GtkSource.CompletionProposal { - string label; + public string label { get; set; default = ""; } - public string text; - string info; - public CompletionProposal(string label, string text, string info) + public string text { get; set; default = ""; } + public string info { get; set; default = ""; } + public CompletionProposal(Lsp.CompletionItem ci) //string label, string text, string info) { - this.text = text; - this.label = label; - this.info = info; + + + this.text = ci.detail == null ? "" : ci.detail ; + this.label = ci.label; + this.info = ci.documentation == null ? "": ci.documentation.value; + GLib.debug("SET: text=%s, label = %s; info =%s", ci.detail, ci.label, "to long.."); } } diff --git a/src/Palete/Gtk.vala b/src/Palete/Gtk.vala index 9d17b09ae..53873b2e9 100644 --- a/src/Palete/Gtk.vala +++ b/src/Palete/Gtk.vala @@ -673,6 +673,8 @@ namespace Palete { ) { var ret = new Gee.ArrayList(); + return ret; + /* // completion rules?? // make sure data is loaded @@ -911,6 +913,7 @@ namespace Palete { return ret; + */ } diff --git a/src/Palete/Javascript.vala b/src/Palete/Javascript.vala index ead98520a..4edd52124 100644 --- a/src/Palete/Javascript.vala +++ b/src/Palete/Javascript.vala @@ -78,7 +78,7 @@ namespace Palete { } - public Json.Object validate(string code, string fn) + public void validate(string code, JsRender.JsRender file) { JSC.Exception? ex; @@ -87,40 +87,21 @@ namespace Palete { //GLib.debug("Check syntax %s", code); ctx.check_syntax(code, code.length, JSC.CheckSyntaxMode.SCRIPT, "", 1 ,out ex); - + var ar = file.getErrors("ERR"); + ar.remove_all(); if (ex == null) { - return new Json.Object(); // this.compressionErrors(code, fn); << to slow on large files? - + return ; // this.compressionErrors(code, fn); << to slow on large files? } - //GLib.debug("got error %d %s", (int)ex.get_line_number() , ex.get_message() ); - - var ar = new Json.Array(); - ar.add_string_element(ex.get_message()); + //GLib.debug("go t error %d %s", (int)ex.get_line_number() , ex.get_message() ); - - - var line_to_err = new Json.Object(); - line_to_err.set_array_member(ex.get_line_number().to_string(), ar); - var file_to_line = new Json.Object(); - file_to_line.set_object_member(fn, line_to_err); - var ret = new Json.Object(); - ret.set_object_member("ERR", file_to_line); + var ret = new CompileError.new_jserror(file, "ERR", (int) ex.get_line_number(), ex.get_message()); + + ar.append(ret); - /* - var g = new Json.Generator (); - - g.pretty = true; - g.indent = 2; - var n = new Json.Node(Json.NodeType.OBJECT); - n.set_object(ret); - g.set_root (n); - - GLib.debug("got %s", g.to_data (null)); - */ - return ret; + } diff --git a/src/Palete/LanguageClient.vala b/src/Palete/LanguageClient.vala new file mode 100644 index 000000000..d3dd0928f --- /dev/null +++ b/src/Palete/LanguageClient.vala @@ -0,0 +1,350 @@ +/** + generic interface to language server + ?? first of will be for vala... but later? + based on gvls-client-jsonrpc (loosly) + and vala-language-server + + +*/ + +namespace Palete { + + + + public abstract class LanguageClient : Jsonrpc.Server { + + public Project.Project project; + private GLib.SubprocessLauncher launcher; + private GLib.Subprocess subprocess; + private IOStream subprocess_stream; + public Jsonrpc.Client? jsonrpc_client = null; + + protected LanguageClient(Project.Project project) + { + // extend versions will proably call initialize to start and connect to server. + this.project = project; + + + } + + public bool initProcess(string process_path) + { + this.launcher = new GLib.SubprocessLauncher (SubprocessFlags.STDIN_PIPE | SubprocessFlags.STDOUT_PIPE); + this.launcher.set_environ(GLib.Environ.get()); + try { + this.subprocess = launcher.spawnv ({ process_path }); + var input_stream = this.subprocess.get_stdout_pipe (); + var output_stream = this.subprocess.get_stdin_pipe (); + + if (input_stream is GLib.UnixInputStream && output_stream is GLib.UnixOutputStream) { + // set nonblocking + if (!GLib.Unix.set_fd_nonblocking(((GLib.UnixInputStream)input_stream).fd, true) + || !GLib.Unix.set_fd_nonblocking (((GLib.UnixOutputStream)output_stream).fd, true)) + { + GLib.debug("could not set pipes to nonblocking"); + return false; + } + } + this.subprocess_stream = new SimpleIOStream (input_stream, output_stream); + this.accept_io_stream ( this.subprocess_stream); + } catch (GLib.Error e) { + GLib.debug("subprocess startup error %s", e.message); + return false; + } + return true; + } + + /** + utility method to build variant based queries + */ + public Variant buildDict (...) { + var builder = new GLib.VariantBuilder (new GLib.VariantType ("a{sv}")); + var l = va_list (); + while (true) { + string? key = l.arg (); + if (key == null) { + break; + } + Variant val = l.arg (); + builder.add ("{sv}", key, val); + } + return builder.end (); + } + + public override void client_accepted (Jsonrpc.Client client) + { + if (this.jsonrpc_client == null) { + this.jsonrpc_client = client; + + GLib.debug("client accepted connection - calling init server"); + + + this.jsonrpc_client.notification.connect((method, paramz) => { + this.onNotification(method, paramz); + }); + + this.jsonrpc_client.failed.connect(() => { + GLib.debug("language server server has failed"); + }); + + this.initialize_server (); + } + + + } + public bool isReady() + { + if (!this.initialized) { + GLib.debug("Server has not been initialized"); + return false; + } + if (this.sent_shutdown) { + GLib.debug("Server has been started its shutting down process"); + return false; + } + return true; + } + + + public abstract void initialize_server(); + + //public abstract void initialize_server() ; + + protected bool initialized = false; + bool sent_shutdown = false; + + + public void onNotification(string method, Variant? return_value) + { + switch (method) { + case "textDocument/publishDiagnostics": + this.onDiagnostic(return_value); + return; + default: + break; + + } + GLib.debug("got notification %s : %s", method , Json.to_string (Json.gvariant_serialize (return_value), true)); + + } + + /*** + + */ + public void onDiagnostic(Variant? return_value) + { + var dg = Json.gobject_deserialize (typeof (Lsp.Diagnostics), Json.gvariant_serialize (return_value)) as Lsp.Diagnostics; + var f = this.project.getByPath(dg.filename); + if (f == null) { + GLib.debug("no file %s", dg.uri); + return; + } + foreach(var v in f.errorsByType.values) { + v.remove_all(); + } + foreach(var diag in dg.diagnostics) { + var ce = new CompileError.new_from_diagnostic(f, diag); + if (!f.errorsByType.has_key(ce.category)) { + f.errorsByType.set(ce.category, new GLib.ListStore(typeof(CompileError))); + } + f.errorsByType.get(ce.category).append(ce); + } + f.project.updateErrorsforFile(f); + + } + + public void document_open (JsRender.JsRender file) + { + if (!this.isReady()) { + return; + } + GLib.debug ("LS sent open"); + try { + this.jsonrpc_client.send_notification ( + "textDocument/didOpen", + this.buildDict ( + textDocument : this.buildDict ( + uri: new Variant.string (file.to_url()), + languageId : new Variant.string (file.language_id()), + version : new GLib.Variant.uint64 ( (uint64) file.version), + text : new Variant.string (file.toSource()) + ) + ), + null + ); + } catch( GLib.Error e) { + GLib.debug ("LS sent open err %s", e.message); + } + + } + + public void document_save (JsRender.JsRender file) + { + if (!this.isReady()) { + return; + } + GLib.debug ("LS send save"); + try { + this.jsonrpc_client.send_notification ( + "textDocument/didChange", + this.buildDict ( + textDocument : this.buildDict ( ///TextDocumentItem; + uri: new GLib.Variant.string (file.to_url()) + + ) + ), + null + ); + } catch( GLib.Error e) { + GLib.debug ("LS sent save err %s", e.message); + } + + + } + public void document_close (JsRender.JsRender file) + { + if (!this.isReady()) { + return; + } + GLib.debug ("LS send close"); + try { + this.jsonrpc_client.send_notification ( + "textDocument/didChange", + this.buildDict ( + textDocument : this.buildDict ( ///TextDocumentItem; + uri: new GLib.Variant.string (file.to_url()) + + ) + ), + null + ); + } catch( GLib.Error e) { + GLib.debug ("LS sent close err %s", e.message); + } + + + } + public void document_change (JsRender.JsRender file) + { + if (!this.isReady()) { + return; + } + GLib.debug ("LS send change"); + var ar = new Json.Array(); + var obj = new Json.Object(); + obj.set_string_member("text", file.toSource()); + ar.add_object_element(obj); + var node = new Json.Node(Json.NodeType.ARRAY); + node.set_array(ar); + try { + this.jsonrpc_client.send_notification ( + "textDocument/didChange", + this.buildDict ( + textDocument : this.buildDict ( ///TextDocumentItem; + uri: new GLib.Variant.string (file.to_url()), + version : new GLib.Variant.uint64 ( (uint64) file.version) + ), + contentChanges : Json.gvariant_deserialize (node, null) + + ), + null + ); + } catch( GLib.Error e) { + GLib.debug ("LS sent close err %s", e.message); + } + + + } + public void exit () throws GLib.Error + { + if (!this.isReady()) { + return; + } + this.sent_shutdown = true; + + this.jsonrpc_client.send_notification_async ( + "exit", + null, + null + ); + + } + public async void shutdown () throws GLib.Error + { + if (!this.isReady()) { + return; + } + this.sent_shutdown = true; + Variant? return_value; + yield this.jsonrpc_client.call_async ( + "shutdown", + null, + null, + out return_value + ); + GLib.debug ("LS replied with %s", Json.to_string (Json.gvariant_serialize (return_value), true)); + } + //public async ??/symbol (string symbol) throws GLib.Error { + + // and now for the important styff.. + + /* + + @triggerType 1 = typing or ctl-spac, 2 = tiggercharactres? 3= inside completion? + */ + public async void completion (JsRender.JsRender file, int line, int offset , int triggerType = 1, out Lsp.CompletionList? ret) throws GLib.Error + { + /* partial_result_token , work_done_token context = null) */ + GLib.debug("get completion %s @ %d:%d", file.relpath, line, offset); + + ret = null; + if (!this.isReady()) { + return; + } + Variant? return_value; + yield this.jsonrpc_client.call_async ( + "textDocument/completion", + this.buildDict ( + context : this.buildDict ( ///CompletionContext; + triggerKind: new GLib.Variant.int32 (triggerType) + // triggerCharacter : new GLib.Variant.string ("") + ), + textDocument : this.buildDict ( ///TextDocumentItem; + uri: new GLib.Variant.string (file.to_url()), + version : new GLib.Variant.uint64 ( (uint64) file.version) + ), + position : this.buildDict ( + line : new GLib.Variant.uint64 ( (uint64) line) , + character : new GLib.Variant.uint64 ( (uint64) offset) + ) + ), + null, + out return_value + ); + + + //GLib.debug ("LS replied with %s", Json.to_string (Json.gvariant_serialize (return_value), true)); + var json = Json.gvariant_serialize (return_value); + var ar = json.get_array(); + + if (ar == null) { + ret = Json.gobject_deserialize (typeof (Lsp.CompletionList), json) as Lsp.CompletionList; + return; + } + ret = new Lsp.CompletionList(); + for(var i = 0; i < ar.get_length(); i++ ) { + var add= Json.gobject_deserialize ( typeof (Lsp.CompletionItem), ar.get_element(i)) as Lsp.CompletionItem; + ret.items.add( add); + + } + + + + + } + //CompletionListInfo.itmems.parse_varient or CompletionListInfo.parsevarient + + + + } +} diff --git a/src/Palete/LanguageClientDummy.vala b/src/Palete/LanguageClientDummy.vala new file mode 100644 index 000000000..f540d4f3f --- /dev/null +++ b/src/Palete/LanguageClientDummy.vala @@ -0,0 +1,19 @@ + +namespace Palete { + public class LanguageClientDummy: LanguageClient { + + + public LanguageClientDummy(Project.Project project) + { + // extend versions will proably call initialize to start and connect to server. + base(project); + + + } + public override void initialize_server() { + GLib.debug("initialize dummy server"); + } + + } + +} \ No newline at end of file diff --git a/src/Palete/LanguageClientVala.vala b/src/Palete/LanguageClientVala.vala new file mode 100644 index 000000000..5a9327f06 --- /dev/null +++ b/src/Palete/LanguageClientVala.vala @@ -0,0 +1,38 @@ + +namespace Palete { + public class LanguageClientVala : LanguageClient { + + + public LanguageClientVala(Project.Project project) + { + // extend versions will proably call initialize to start and connect to server. + base(project); + + this.initProcess("/usr/bin/vala-language-server"); + + + } + public override void initialize_server() { + try { + Variant? return_value; + this.jsonrpc_client.call ( + "initialize", + this.buildDict ( + processId: new Variant.int32 ((int32) Posix.getpid ()), + rootPath: new Variant.string (this.project.path), + rootUri: new Variant.string (File.new_for_path (this.project.path).get_uri ()) + ), + null, + out return_value + ); + GLib.debug ("LS replied with %s", Json.to_string (Json.gvariant_serialize (return_value), true)); + this.initialized = true; + } catch (GLib.Error e) { + GLib.debug ("LS replied with error %s", e.message); + } + + } + + } + +} \ No newline at end of file diff --git a/src/Palete/Roo.vala b/src/Palete/Roo.vala index 82515c31b..e0b913177 100644 --- a/src/Palete/Roo.vala +++ b/src/Palete/Roo.vala @@ -381,6 +381,8 @@ namespace Palete { ) { var ret = new Gee.ArrayList(); + return ret; + /* // completion rules?? // Roo...... @@ -566,6 +568,7 @@ namespace Palete { return ret; + */ } diff --git a/src/Palete/ValaCompileQueue.vala b/src/Palete/ValaCompileQueue.vala index a66f21d04..ce9199779 100644 --- a/src/Palete/ValaCompileQueue.vala +++ b/src/Palete/ValaCompileQueue.vala @@ -4,7 +4,7 @@ */ namespace Palete { - public class ValaCompileQueue : Object + public class ValaCompileQueueX : Object { ValaCompileRequest? next_request = null; @@ -23,13 +23,13 @@ namespace Palete { - public ValaCompileQueue() + public ValaCompileQueueX() { //start timeout for compiler. } - public void addFile( ValaCompileRequestType reqtype, JsRender.JsRender file , string alt_code, bool force) + public void addFileX( ValaCompileRequestType reqtype, JsRender.JsRender file , string alt_code, bool force) { var add = new ValaCompileRequest( reqtype, @@ -53,7 +53,7 @@ namespace Palete { } - public void addProp( ValaCompileRequestType requestType, + public void addPropX( ValaCompileRequestType requestType, JsRender.JsRender file, JsRender.Node node, JsRender.NodeProp prop, @@ -172,7 +172,7 @@ namespace Palete { public void onCompileComplete(ValaCompileRequest req) { this.cur_request = null; - req.file.project.last_request = req; // technically it should update compile group. + //req.file.project.last_request = req; // technically it should update compile group. this.last_request = req; this.showSpinner(false); // update errors diff --git a/src/Palete/ValaCompileRequest.vala b/src/Palete/ValaCompileRequest.vala index 3a5a562d6..19beca5a3 100644 --- a/src/Palete/ValaCompileRequest.vala +++ b/src/Palete/ValaCompileRequest.vala @@ -9,7 +9,7 @@ namespace Palete { RUN } - public class ValaCompileRequest : Object + public class ValaCompileRequest : Object { ValaCompileRequestType requestType; @@ -19,7 +19,7 @@ namespace Palete { string alt_code = ""; string tmpfile = ""; Spawn? compiler = null; - ValaCompileQueue? queue = null; + /// ValaCompileQueue? queue = null; @@ -27,7 +27,7 @@ namespace Palete { public Gee.HashMap? errorByFile = null; - public ValaCompileRequest( + public ValaCompileRequest ( ValaCompileRequestType requestType, JsRender.JsRender file , JsRender.Node? node, @@ -107,9 +107,9 @@ namespace Palete { return true; } - public bool run(ValaCompileQueue queue) + public bool run() { - this.queue = queue; + //this.queue = queue; if ( this.target() == "") { GLib.debug("missing target"); this.onCompileFail(); @@ -196,7 +196,7 @@ namespace Palete { this.compiler.isZombie(); GLib.debug("compile got %s", output); if (output == "") { - this.queue.onCompileFail(); + BuilderApplication.showSpinner(false); return; } @@ -208,12 +208,12 @@ namespace Palete { var node = pa.get_root(); if (node.get_node_type () != Json.NodeType.OBJECT) { - this.queue.onCompileFail(); + BuilderApplication.showSpinner(false); return; } var ret = node.get_object (); - CompileError.parseCompileResults(this,ret); - this.queue.onCompileComplete(this); + //CompileError.parseCompileResults(this,ret); + BuilderApplication.showSpinner(false); @@ -221,12 +221,12 @@ namespace Palete { } catch (GLib.Error e) { GLib.debug("parsing output got error %s", e.message); - this.queue.onCompileFail(); + BuilderApplication.showSpinner(false); return; } if (this.requestType == ValaCompileRequestType.RUN) { - this.queue.execResult(this); + this.execResult(); } } @@ -262,21 +262,109 @@ namespace Palete { return ret; } - public void runJavascript(ValaCompileQueue queue) + public void runJavascript( ) { - this.queue = queue; + //this.queue = queue; var contents = this.alt_code == "" ? this.file.toSourceCode() : this.generateTempContents(); - var ret = Javascript.singleton().validate(contents, this.file.targetName()); - - CompileError.parseCompileResults(this,ret); - this.queue.onCompileComplete(this); + Javascript.singleton().validate(contents, this.file ); + + + + BuilderApplication.showSpinner(false); + BuilderApplication.updateCompileResults(); + + //this.queue.onCompileComplete(this); // see pack file (from palete/palete..palete_palete_javascriptHasCompressionErrors.) } + public void killChildren(int pid) + { + if (pid < 1) { + return; + } + var cn = "/proc/%d/task/%d/children".printf(pid,pid); + if (!FileUtils.test(cn, GLib.FileTest.EXISTS)) { + GLib.debug("%s doesnt exist - killing %d", cn, pid); + Posix.kill(pid, 9); + return; + } + string cpids = ""; + try { + FileUtils.get_contents(cn, out cpids); + + + if (cpids.length > 0) { + this.killChildren(int.parse(cpids)); + } + + } catch (GLib.FileError e) { + // skip + } + GLib.debug("killing %d", pid); + Posix.kill(pid, 9); + } + + int terminal_pid = 0; + public void execResult() + { + + this.killChildren(this.terminal_pid); + this.terminal_pid = 0; + + var exe = this.target(); + var pr = (Project.Gtk) this.file.project; + var cg = pr.compilegroups.get(exe); + + if (!GLib.FileUtils.test(exe, GLib.FileTest.EXISTS)) { + print("Missing output file: %s\n",exe); + return; + } + var gdb_cfg= pr.path + "/build/.gdb-script"; + if (!GLib.FileUtils.test(gdb_cfg, GLib.FileTest.EXISTS)) { + pr.writeFile("build/.gdb-script", "set debuginfod enabled off\nr"); + } + + + + string[] args = "/usr/bin/gnome-terminal --disable-factory --wait -- /usr/bin/gdb -x".split(" "); + + args+= gdb_cfg; + + args += exe; + if (cg.execute_args.length > 0) { + args+= "--args"; + var aa = cg.execute_args.split(" "); + for (var i =0; i < aa.length; i++) { + args += aa[i]; + } + } + + + + // should be home directory... + + + try { + + var exec = new Spawn(pr.path , args); + exec.env = GLib.Environ.get(); + + exec.detach = true; + exec.run(); + + this.terminal_pid = exec.pid; + GLib.debug("Child PID = %d", this.terminal_pid); + + } catch(GLib.Error e) { + GLib.debug("Failed to spawn: %s", e.message); + return; + } + + } } diff --git a/src/Project/Gtk.vala b/src/Project/Gtk.vala index b44208d53..a502648f5 100644 --- a/src/Project/Gtk.vala +++ b/src/Project/Gtk.vala @@ -207,7 +207,32 @@ namespace Project { return this.pathsMatching("vapi", false); } + + + + public override Palete.LanguageClient getLanguageServer(string lang) + { + if (this.language_servers.has_key(lang)) { + return this.language_servers.get(lang); + } + switch( lang ) { + case "vala": + this.language_servers.set(lang, new Palete.LanguageClientVala(this)); + break; + default : + return this.language_servers.get("dummy"); + + } + return this.language_servers.get(lang); + + } + + + + + + // ------------------ new project stufff public override void initialize() { string[] dirs = { @@ -367,10 +392,10 @@ namespace Project - public override void initDatabase() - { - // nOOP - } + public override void initDatabase() + { + // nOOP + } } diff --git a/src/Project/Project.vala b/src/Project/Project.vala index 361648b6a..d10c23af4 100644 --- a/src/Project/Project.vala +++ b/src/Project/Project.vala @@ -83,7 +83,12 @@ namespace Project { private bool is_scanned = false; public Gee.HashMap gir_cache = null; // used by Gir ??? is this used by Roo? - public Palete.ValaCompileRequest last_request = null; + //public Palete.ValaCompileRequest last_request = null; // depricated? + public Gee.HashMap? errorsByType = null; + + + + protected Gee.HashMap language_servers; protected Project (string path) { @@ -96,8 +101,9 @@ namespace Project { //XObject.extend(this, cfg); //this.files = { }; this.path = path; - - + this.language_servers = new Gee.HashMap(); + this.language_servers.set("dummy", new Palete.LanguageClientDummy(this)); + this.errorsByType = new Gee.HashMap(); } @@ -116,7 +122,7 @@ namespace Project { try { dir.make_directory(); } catch(GLib.Error e) { - GLib.error("could not make builder directory"); + GLib.error("could not make builder directory %s", e.message); } return; } @@ -595,10 +601,10 @@ namespace Project { - public JsRender.JsRender? getByName(string name) + public JsRender.JsRender? getByRelPath(string relpath) { foreach(var f in this.files.values) { - if (f.name == name) { + if (f.relpath == relpath || f.relTargetName() == relpath) { return f; } }; @@ -611,7 +617,7 @@ namespace Project { // keys are not paths... foreach(var f in this.files.values) { - GLib.debug("check %s = %s ? %s", path, f.path, f.targetName()); + //GLib.debug("check %s = %s ? %s", path, f.path, f.targetName()); if (f.path == path || f.targetName() == path) { return f; } @@ -987,6 +993,50 @@ namespace Project { return ret; } + public void updateErrorsforFile(JsRender.JsRender f) + { + var n = this.updateErrorsByType(f, "WARN"); + n += this.updateErrorsByType(f, "ERR"); + n += this.updateErrorsByType(f, "DEPR"); + + if (n > 0) { + BuilderApplication.updateCompileResults(); + } + + } + public int updateErrorsByType(JsRender.JsRender f, string n) + { + var ls = this.getErrors(n); + + // remove thie file from the list. + for(var i =0; i < ls.get_n_items(); i++) { + var ce = ls.get_item(i) as Palete.CompileError; + if (ce.file.path == f.path) { + ls.remove(i); + break; + } + } + var add = new Palete.CompileError.new_from_file(f, n); + if (add.hasErrors()) { + ls.append(add); + return 1; + } + return 0; + } + public GLib.ListStore getErrors(string n) + { + var ls = this.errorsByType.get(n); + if (ls == null) { + ls = new GLib.ListStore(typeof(Palete.CompileError)); + this.errorsByType.set(n, ls ); + } + return ls; + } + + + public abstract Palete.LanguageClient getLanguageServer(string lang); + + public abstract void onSave(); // write meson? public abstract void initDatabase(); public abstract void initialize(); // for new projects (make dirs?); diff --git a/src/Project/Roo.vala b/src/Project/Roo.vala index 04de67661..1c5dec478 100644 --- a/src/Project/Roo.vala +++ b/src/Project/Roo.vala @@ -86,6 +86,11 @@ public class Project.Roo : Project { // nope } + public override Palete.LanguageClient getLanguageServer(string lang) + { + return this.language_servers.get("dummy"); + } + } \ No newline at end of file