Custom javascript code completion for "this" in monaco editor - javascript

The scenario:
We are using the monaco editor in a javascript application to let the users enter custom javascript code (sort of a js-fiddle thing for an internal dashboarding application)
Within the javascript code that the users edit this is bound to a custom framework-provided object when the code is executed.
Question:
Is there a way to configure monaco so that it will provide code completion when the users type this.?
The this object is compiled from a TypeScript class with type annotation. Is it possible to use the typescript compiler to produce data that the custom monaco code completion can use?

If I understood you correctly, you may use registerCompletionItemProvider. But I'm not sure if you are using any other library or something you've created. Because each autocomplete item needs to be defined one by one. If the library created dynamically maybe you can add this definition process to your main compilation process.
I'm guessing you might end up with more work than you expected to do.
https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html#registercompletionitemprovider
If you are expecting a cross-file autocompletion I believe your answer is here.
Monaco Editor intellisense from multiple files

You can reference this link. There are many apis for what you want.
https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ieditorconstructionoptions.html#acceptsuggestiononenter

Related

VSCode extension for Javascript types

Is there a VSCode extension that shows data type of a variable (like if we hover above that variable)? Presumably by detecting the type of a variable by looking at its initialization, and maybe even follow subsequent re-assignments? I know that using Typescript will give me great tooling which will do what I am seeking, but I don't want to use Typescript.
No not really, that's the nature of dynamic programming. VS Code itself can sort of guess, but it's mostly based on frequent strings used within the file or directory.
The closest is JSDoc (which has more uses than just types, you should probably already be using this) and indirectly using Typescript in your plain .js files to help VS Code.
At the top of your files add this:
// #ts-check
https://code.visualstudio.com/docs/nodejs/working-with-javascript#_type-checking-javascript

Extending JavaScript syntax in Monaco Editor with full integration

I'm trying to extend Monaco Editor to allow users to write in a hybrid of JavaScript and another language, using delimiters to separate them within the same file, similarly to how Markdown allows writing multiple languages using fenced code blocks.
The difference is that I want to keep all the other IDE features that Monaco has built in for JavaScript, such as linting (done via diagnostics), smart auto-completion, jump-to-definition, auto-formatting helpers, and every other IDE feature that comes with Monaco's built-in JavaScript mode. I'd like these features to still work within the JavaScript portion of the code that Monaco is editing, and be disabled for the sub-language portion.
My first attempt was to call setMonarchTokensProvider, passing in a modified version of TypeScript's tokenizer rules. Specifically, I was able to add the beginning-fence delimiter to the root rule and create a new rule for the sub-language in the same way the documentation for Monarch (Monaco's syntax highligher) describes, using #nextEmbedded. (For testing purposes, I've been hard-coding CSS as the embedded language.)
When I call setMonarchTokensProvider like this for the language "javascript", it completely ignores this syntax highlighting tokenizer, and colors the code-fences of CSS as invalid JavaScript, indicating that you cannot override the built-in JavaScript mode this way.
When I call setMonarchTokensProvider with a new language (e.g. "mylang") and set the editor to use that language, it provides correct syntax highlighting (!) for this CSS-in-JS hybrid language. But all other advanced features that were found in the JavaScript mode are no longer present. The editor didn't have any smart auto-completion for methods defined on classes in the same file, or any in-editor error-reporting for invalid syntax, or any of its trademark JavaScript IDE features.
So my next attempt was to modify the pre-bundled Monaco code's TypeScript definition to include my custom syntax highlighting rules. This correctly highlighted my CSS-in-JS code completely (!), when setting the language to "typescript", and left all the other features intact (!) including diagnostics reporting (live-validation and underlining of errors), auto-completion, all of it! (I didn't try it with "javascript" but it's safe to assume it probably works or is trivial to get it working, since JavaScript is actually implemented as a variant configuration of the TypeScript mode in Monaco.)
Unfortunately, it also considered the entire CSS portion of it, including the fence around it, to be invalid JavaScript code.
I know that this is theoretically doable, because within HTML mode, you can embed CSS or JS with full support for proper validation and auto-completion and every other IDE feature; basically, every sub-language in an HTML file works like it's in its own file: HTML features in the root of the file, CSS features within style tags, JS features within script tags.
But digging into the TypeScript plugin's implementation inside Monaco, it's not clear where to begin editing this, either as a user of Monaco the library, or by forking it and patching it up where necessary. I started at trying to modify the DiagnostcsAdapter [sic] and tracing where it's actually implemented, but I got stuck two function-calls deep, where it seems to push a promise of syntax validation that returns a value that's used later, but the implementation of getSyntacticDiagnostics just shells the work out to some other implementation that I can't find anywhere else in the repo, nor in the monaco-languages repo or the vscode repo.
I make the similar thing. My solution is to place non-JS code inside a block comment:
regularJsCode()
/*
[your-syntax-identifying-start-token]
place any syntax you want here
[your-syntax-identifying-end-token]
*/
regularJsCode()
Then you can process it with your tools, parsers, IDE extension etc. And the coolest part you can make VSCode to syntax-highlight it like you want so it won't seem like some hack.
This approach is preferrable because your JS file still remains a 100% valid JS file.
If you still don't want to put your syntax into comments, then you should create your own file extension like .jsx/.tsx. In practical, VSCode terms this means you need to create VSCode extension with language server and stuff. This is not so easy, but the documentation is good. You could assemble your own JS highlighting code inside your VSCode extension using language server: https://github.com/sourcegraph/javascript-typescript-langserver
According to the creator of Monaco:
Architecturally, you can do the following:
use monaco-editor-core directly
define a new language to the editor
fork monaco-typescript and change it to work with your newly defined langauge id. Then, modify the TS language host code to not pass the original models to TypeScript, but first run a preprocess which strips your custom language out of the text, and then only passes on valid TypeScript to the TS compiler. One idea is to replace each character that you remove with a space. This will leave all the position/offset computation work without any effort on your side.
Good luck!

Is #JsName annotation required for every method?

I was trying to make NodeJs work with Kotlin for a HelloWorld example here.
As per the Kotlin JS documentation, #JsName annotation is required for overloaded methods. But in my experience, it is required even for a single method. Without this annotation the compiler adds a suffix to the method name as shown in the screenshot.
Is this a bug? Or am I missing something?
I'm using Kotlin 1.1.0 module provided by NPM (please check the GitHub link above for the complete codebase if required).
Kotlin compiler mangles names all functions, except for those which don't take any parameters. The motivation is: you can add overloaded function later, and this should not break binary compatibility of the code. As for #JsName: it depends on your goal. I don't know it and hence I can't tell whether you shuold put #JsName annotation on each method. If you are developing a library which is intended to be used from JavaScript, yes, you probably need to put #JsName on each function you want to be accessible from JavaScript. We are going to add another annotation which turns off mangling on entire class or file.

Does anyone know of a way to dynamically load a qooxdoo module?

I'm using the latest qooxdoo SDK (3.5) and am trying to find a way to dynamically load a module. Each module would implement an "init" function which creates a window in the application and, from that point, is self-contained.
What I would need is the ability to call an arbitrary init function without knowing the module existed beforehand. For example, someone uploads a custom module and tries to run it--I just need to call the module's init function (or error out if the call fails).
Any ideas?
Edit:
Something like:
function loadModule(modName) {
var mod = new qx.something.loadModule(modName);
mod.init();
}
I found 3 ways that Qooxdoo has to run dynamic code. The first way is via the built-in parts loader. "Parts" are basically portions of an application that qooxdoo will load "just-in-time" when you actually need them--for example, a class that operates a rarely used form or dialog box. This method is not truly dynamic (in my opinion) in that it requires the code to be included in the build process that Qooxdoo provides. Explaining exactly how it works is out of scope for this answer and, frankly, I'm not yet all that familiar with it myself.
The second way is via the qx.Class.getByName() function call. It works like so:
qx.Class.define("Bacon", {
extend: qx.core.Object,
construct: function(foo, bar) {
this.foo = foo;
this.bar = bar;
}
});
var klass = qx.Class.getByName("Bacon");
var obj = new klass("foo", "bar");
this.debug(obj.foo);
This method was found on the Qooxdoo mailing list here. This method will work for code included in the build process and for code introduced dynamically but, in my opinion, is trumped by the third method for the simple reason that if you are introducing a new class dynamically, you'll have to use the third method anyway.
The final method I located was actually revealed to me via studying the source code for the Qooxdoo playground. (The source code is available as part of the desktop download.)
The playground reads the code in from the editor and creates an anonymous function out of it, then executes the function. There is a bunch of setup and tear-down the playground does surrounding the following code, but I've removed it for brevity and clarity. If you are interested in doing something similar yourself, I highly recommend viewing the source code for the playground application. The dynamic code execution is contained within the __updatePlayground function starting on line 810 (Qooxdoo v3.5).
var fun;
try {
fun = qx.event.GlobalError.observeMethod(new Function(code));
} catch(ex) {
//do something with the exception
}
try {
fun.call();
} catch(ex) {
//do something with the exception
}
The code is straightforward and uses the built-in Javascript function "call" to execute the anonymous function.
Please define module.
Qooxdoo source code uses the same convention as Java - one class per file. Do you really want to load classes individually and deal with dependencies? If not, what's your definition of a module?
Other than that, qooxdoo has a notion of packages, which are groups of classes, interfaces and mixins, framework, contribs, including the framework itself, packed by the generator in an optimized way, so that the classes used earlier are loaded earlier. Using qooxdoo's own packaging mechanism requires no more effort than running build with custom arguments or customizing the config.json - all described in detail in the manual.
If your idea of a module is sort of a sub-application, mostly decoupled from everything else in the big application, I'm not sure it's achievable without either significantly modifying the generator code (what ./generate.py calls) or accepting some size overhead.
I won't go into details of modifying the generator - if you go this route you'll need to dig deeply anyway, and you'll learn more than I know about the generator.
What you can do while staying within what qooxdoo allows is to create a separate island application for each module, build your own infrastructure for inter-modules communication via JavaScript attached to the top window, and run the modules inside the main page, with some manually added magic to make the various modules behave like tab panes or qooxdoo windows. The overhead you'll have to take, besides some awkward custom, non-qooxdoo code, is that all modules will re-load the qooxdoo framework code.

Typescript specific methods for saving data online?

I'm thinking about using TypeScript to create an online app, and this will require saving of data online.
What are my options in regards to that?
Is there anything specific to using TypeScript which makes that easier or harder?
Ideally I would use a service like Parse.com to save data, can Typescript be connected to Parse or would I have to rely upon plain JS?
TypeScript runs wherever javascript runs. So
Your options are the same as javascript.
Typescript compiles down to javascript. And it is designed to be a superset of javascript so your javascript will be valid typescript as long as you have variables declared and sometimes types mentioned.
Optional static typing + easier syntax is what makes developing in TypeScript easier.
Static typing makes refactoring and intellisense more reliable. Having an easier syntax for classes / modules means you are more likely to structure your code better.
Yes you can use parse.com with typescript
The recommended way to do that is to create a declaration file describing your javascript code. In the beginning it can be as simple as:
declare var parse:any;
I wrote some guidance on the matter here : http://basarat.github.io/TypeScriptDeepDive/#/declarations
There is a huge resource of declaration files you can find at https://github.com/borisyankov/DefinitelyTyped . In particular check out FireBase : https://www.firebase.com/ and its declaration file : https://github.com/borisyankov/DefinitelyTyped/tree/master/firebase However there isn't one on parse.com yet which is why I mentioned the way to write your own.
Additionally you don't need a declaration file if you do not want any impressive static checking of the typescript code that interacts with the parse.com's api.

Categories