X-Git-Url: http://git.roojs.org/?a=blobdiff_plain;f=src%2FPalete%2FLanguageClientJavascript.vala;h=b28383540c86630fb459ea15a4ddf26a730e2bf1;hb=HEAD;hp=19371a4ae1b84cc47d48c129cd4350b6fd482f75;hpb=eccffa50a972ff9cefeab353a5fede2d3f75564c;p=roobuilder diff --git a/src/Palete/LanguageClientJavascript.vala b/src/Palete/LanguageClientJavascript.vala index 19371a4ae..b28383540 100644 --- a/src/Palete/LanguageClientJavascript.vala +++ b/src/Palete/LanguageClientJavascript.vala @@ -2,45 +2,306 @@ namespace Palete { public class LanguageClientJavascript : LanguageClient { + Gee.HashMap file_contents; public LanguageClientJavascript(Project.Project project) { // extend versions will proably call initialize to start and connect to server. base(project); - + this.file_contents = new Gee.HashMap(); + GLib.debug(" START JAVASCRIPT LANG SERVER"); } public override void initialize_server() { GLib.debug("initialize javascript server"); } - public override void startServer() - { - } + public override bool isReady () { return true; } - - - - public new bool isReady() + public override void document_open (JsRender.JsRender file) { - return false; - } - public new void document_open (JsRender.JsRender file) - { - + this.file_contents.set(file.path, file.toSourceCode()); Javascript.singleton().validate(file.toSourceCode(), file ); BuilderApplication.updateCompileResults(); } - public new void document_save (JsRender.JsRender file) + public override async void document_save (JsRender.JsRender file) { + + this.file_contents.set(file.path, file.toSourceCode()); + GLib.debug("set file %s : %d chars", file.path, this.file_contents.get(file.path).length); Javascript.singleton().validate(file.toSourceCode(), file ); BuilderApplication.updateCompileResults(); } - public new void document_change (JsRender.JsRender file ) - { - Javascript.singleton().validate(file.toSourceCode(), file ); + public override async void document_change_force (JsRender.JsRender file, string contents ) { + this.file_contents.set(file.path, contents); + GLib.debug("set file %s : %d chars", file.path, this.file_contents.get(file.path).length); + Javascript.singleton().validate(contents, file ); BuilderApplication.updateCompileResults(); } + public override void document_change (JsRender.JsRender file ) + { + this.document_change_force.begin( file, file.toSourceCode(), (obj, res) => { + this.document_change_force.end(res); + });; + } + public override void document_close (JsRender.JsRender file) {} + public override void exit () throws GLib.Error { } + public override async void shutdown () throws GLib.Error { } + public override async Lsp.CompletionList? completion(JsRender.JsRender file, int line, int offset , int triggerType = 1) throws GLib.Error + { + + var ret = new Lsp.CompletionList(); + if (this.file_contents.get(file.path) == null) { + GLib.debug("got file %s : MISSING ", file.path); + return ret; + } + //GLib.debug("got file %s : %s ", file.path, this.file_contents.get(file.path)); + + var ar = this.file_contents.get(file.path).split("\n"); + var ln = line >= ar.length || line < 1 ? "" : ar[line-1]; + if (offset-1 >= ln.length) { + GLib.debug("request for complete on line %d @ pos %d > line length %d", line, offset, (int) ln.length); + return ret; + } + GLib.debug("got Line %d:%d '%s' ", line, offset, ln); + + var start = -1; + for (var i = offset - 1; i > 0; i--) { + GLib.debug("check char %d '%c'", i, ln[i]); + if (ln[i].isalpha() || ln[i] == '.' || ln[i] == '_') { // any other allowed chars? + start = i; + continue; + } + break; + } + + + var complete_string = ln.substring(start, offset - start); + GLib.debug("complete string = %s", complete_string); + + + + // completion rules?? + + // Roo...... + + // this. (based on the node type) + // this.xxx // Node and any determination. + + // keywords... // text does not contains "." + + if (!complete_string.contains(".")) { + // string does not have a '.' + // offer up this / Roo / javascript keywords... / look for var string = .. in the code.. + for(var i = 0; i < JsRender.Lang.match_strings.size ; i++) { + var str = JsRender.Lang.match_strings.get(i); + var sci = new Lsp.CompletionItem.keyword(str, str, "keywords : %s".printf(str)); + ret.items.add(sci); + + + + + } + if (complete_string != "Roo" && "Roo".has_prefix(complete_string) ) { + // should we ignore exact matches... ??? + var sci = new Lsp.CompletionItem.keyword("Roo", "Roo", "Roo - A Roo class" ); + ret.items.add(sci); + + + } + if (complete_string != "_this" && "_this".has_prefix( complete_string) ) { + // should we ignore exact matches... ??? + + var sci = new Lsp.CompletionItem.keyword("_this", "_this", "Reference to the global pointer to the files main class instance"); + ret.items.add(sci); + + + } + return ret; + } + // got at least one ".". + var parts = complete_string.split("."); + var curtype = ""; + var cur_instance = false; + if (parts[0] == "_this") { + if (file.tree == null) { + + GLib.debug("file has no tree"); + return ret; // no idea.. + } + curtype = file.tree.fqn(); + cur_instance = true; + // work out from the node, what the type is... + // fetch node from element. + + //curtype = node.fqn(); + cur_instance = true; + } + + + if (parts[0] == "this") { + // work out from the node, what the type is... + // fetch node from element. + var node = file.lineToNode(line -1); // hopefuly + if (node == null) { + GLib.debug("could nt find scope for 'this'"); + return ret; // no idea.. + } + curtype = node.fqn(); + cur_instance = true; + } + if (parts[0] == "Roo") { + curtype = "Roo"; + cur_instance = false; + } + + var prevbits = parts[0] + "."; + for(var i =1; i < parts.length; i++) { + GLib.debug("matching %d/%d\n", i, parts.length); + + var is_last = i == parts.length -1; + // look up all the properties of the type... + var cls = this.project.palete.getClass(curtype); + if (cls == null) { + GLib.debug("could not get class of curtype '%s'\n", curtype); + return ret; + } + + if (!is_last) { + + // only exact matches from here on... + if (cur_instance) { + if (cls.props.has_key(parts[i])) { + var prop = cls.props.get(parts[i]); + if (prop.type.index_of(".",0) > -1) { + // type is another roo object.. + curtype = prop.type; + prevbits += parts[i] + "."; + continue; + } + return ret; + } + + + + // check methods?? - we do not export that at present.. + return ret; //no idea... + } + + // not a instance.. + //look for child classes. + var citer = this.project.palete.classes.map_iterator(); + var foundit = false; + while (citer.next()) { + var scls = citer.get_key(); + var look = prevbits + parts[i]; + if (scls.index_of(look,0) != 0) { + continue; + } + // got a starting match.. + curtype = look; + cur_instance = false; + foundit =true; + break; + } + if (!foundit) { + return ret; + } + prevbits += parts[i] + "."; + continue; + } + // got to the last element.. + GLib.debug("Got last element\n"); + if (curtype == "") { // should not happen.. we would have returned already.. + return ret; + } + GLib.debug("Got last element type %s\n",curtype); + if (!cur_instance) { + GLib.debug("matching instance"); + // it's a static reference.. + var citer = this.project.palete.classes.map_iterator(); + while (citer.next()) { + var scls = citer.get_key(); + var look = prevbits + parts[i]; + if (parts[i].length > 0 && scls.index_of(look,0) != 0) { + continue; + } + var sci = new Lsp.CompletionItem.keyword(scls,scls, "doc??" ); + ret.items.add(sci); + + + } + return ret; + } + GLib.debug("matching property"); + + + + var citer = cls.methods.map_iterator(); + while (citer.next()) { + var prop = citer.get_value(); + // does the name start with ... + if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) { + continue; + } + // got a matching property... + // return type? + + var sci = new Lsp.CompletionItem.keyword( prop.name + "(", prop.name + "(" , prop.doctxt ); + ret.items.add(sci); + + + + } + + // get the properties / methods and subclasses.. of cls.. + // we have cls.. - see if the string matches any of the properties.. + citer = cls.props.map_iterator(); + while (citer.next()) { + var prop = citer.get_value(); + // does the name start with ... + //if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) { + // continue; + //} + + var sci = new Lsp.CompletionItem.keyword( prop.name, prop.name , prop.doctxt ); + ret.items.add(sci); + + + } + + + return ret; + + + + + + } + + + + return ret; + + } + + public override async Lsp.Hover hover (JsRender.JsRender file, int line, int offset) throws GLib.Error { + return new Lsp.Hover(); + } + public override void queueDocumentSymbols (JsRender.JsRender file) { } + public override async Gee.ArrayList documentSymbols (JsRender.JsRender file) throws GLib.Error { + var ret = new Gee.ArrayList(); + return ret; + } + public override async Gee.ArrayList signatureHelp (JsRender.JsRender file, int line, int offset) throws GLib.Error + { + return new Gee.ArrayList(); + } + public override async Gee.ArrayList symbol (string sym) throws GLib.Error + { + return new Gee.ArrayList(); + } + } } \ No newline at end of file