siku2 / rust-monaco

Rust WASM bindings for the Monaco Editor
Apache License 2.0
77 stars 25 forks source link

Update monaco editor #41

Open ctron opened 1 year ago

ctron commented 1 year ago

I was trying to update the monaco editor. This crate has version 0.31, where 0.41 is the most recent one.

It was mostly straight forward, but I do fail generating the wasm bindings with ts2rs. And I am a bit stuck with this. I am willing to help, I just don't know "how". Especially, how the monaco.d.ts file got created. Because it doesn't seem to be the original one.

PawelPerek commented 1 year ago

Hi @ctron, I found fresh monaco.d.ts in package I downloaded from official website https://microsoft.github.io/monaco-editor/. Unfortunately it seems like an old regexp doesn't work on new monaco.d.ts. I tried a few simple changes to fix it, but unfortunately none of them work, seems like Microsoft changed a bit structure of their type declarations. It still might be easy to fix, just not trivial.

ctron commented 1 year ago

I don't think they did. I took the version out of the npm package from version 0.31, and it looks similar to the structure of the newer ones, but different to the structure of what is in this repository. So I assume it got manually edited even with the old version.

I would just like to understand the process. And I am also wondering if this couldn't be replaced with some typescript script (instead of python) which seems to have some tooling for loading/parsing typescript files. Which should make it easier to generate stuff.

But before jumping into creating new code, I would like to learn more. Maybe I miss something obvious :)

PawelPerek commented 1 year ago

Yeah, I think you're right, taking a look at git blame makes me believe that monaco.d.ts from 0.31 package also was modified by hand to fit ts2rs logic, check it out here: https://github.com/siku2/rust-monaco/commit/3a2eafd4748bd9174378aab193304917e2e32708#diff-f84dea6d704c4dddfdf36cf15c360cead903c814e935d37f634d92a83bc8e6a8. Both reverse engineering all the changes that needs to be done in new monaco.d.ts and rewriting parser to typescript sounds like a loads of work but certainly possible

ctron commented 1 year ago

Yes, that's the problem. I was considering to use something like this https://github.com/dsherret/ts-morph instead of python. Trying to walk the AST and emit some Rust code. Which might be the same time to invest, but should be more stable long term.

ctron commented 1 year ago

:facepalm: Should have searched first, maybe the solution already exists: https://github.com/ratchetdesigns/ts-bindgen

PawelPerek commented 1 year ago

I tried to copy-paste .d.ts into https://github.com/ratchetdesigns/ts-bindgen without any modifications and got following error

// Error generating typescript rust bindings.
binding generation error: enums with non-literal initializers not supported
/example.d.ts:275:29: 275:31: -1

But at least we know what to modify by hand now 😄

ctron commented 1 year ago

Yea, you will see a panic next :) … but I think that's something to move forward with. Actually their playground uses this crate :smile:

siku2 commented 1 year ago

Sorry I didn't chime in sooner, but yes, as you were able to tell the typing declarations file in this repo was hand modified. The bulk of this was to reduce the amount of different syntax constructs that the parser needed to handle since typescript has a lot of ways to write out semantically equivalent statements.

Anyway, the whole ts2rs was really only supposed to be a quick and dirty solution to build a proof of concept, which would then pave the way for a more advanced translator. Unfortunately I never got to that point. I was gonna mention ts-bindgen, but I see you already found it as well. I would love if we could replace the generated code in this repo with a version generated by ts-bindgen, but that will probably require some additional work on it first.

siku2 commented 1 year ago

Btw, a lot of the required changes to the declaration file are actually described in the ts2rs/README.md file

PawelPerek commented 1 year ago

I also found other way with more indirection layers (https://www.reddit.com/r/rust/comments/uy1a3i/transpiling_typescript_into_rust/). We could transpile .d.ts into JSON schema using https://github.com/YousefED/typescript-json-schema and then use https://github.com/quicktype/quicktype to generate the .rs definition. The pros are that it has slightly more stars, so it should be more complete, but cons are obvious.

ctron commented 1 year ago

Btw, a lot of the required changes to the declaration file are actually described in the ts2rs/README.md file

Yea, I still my trouble with really understanding what was required. But I do understand that it's tricky.

I played a bit with ts-bindgen and got some output after fixing an issue and ignoring others. But the output of what is generated looks vastly different. And I am not sure this is going to work.

ctron commented 1 year ago

I played a bit with typescript and its compiler API. But that gets pretty complex. Then I found https://github.com/swc-project/swc … which looks promising.

With a few lines of code, I can run visitors across the AST and trigger on modules, namespaces, interfaces, and classes.

I am sure it's a long way from there. But I am positive.

ctron commented 1 year ago

The approach with swc looks promising:

pub enum MarkerSeverity {
    Hint = 1,
    Info = 2,
    Warning = 4,
    Error = 8,
}

#[wasm_bindgen]
extern "C" {
  pub type CancellationTokenSource;

  #[wasm_bindgen(constructor, js_class = "CancellationTokenSource")]
  pub fn new() -> CancellationTokenSource;

  #[wasm_bindgen(js_class = "CancellationTokenSource", js_name = "token", getter = token, method)]
  pub fn token(this: &CancellationTokenSource, )-> CancellationToken;

  #[wasm_bindgen(js_class = "CancellationTokenSource", js_name = "cancel", method)]
  pub fn cancel(this: &CancellationTokenSource, )-> JsValue;

  #[wasm_bindgen(js_class = "CancellationTokenSource", js_name = "dispose", method)]
  pub fn dispose(this: &CancellationTokenSource, cancel: Option<bool>, )-> JsValue;

}

#[wasm_bindgen]
extern "C" {
  pub type Uri;

  #[wasm_bindgen(js_class = "Uri", js_name = "is_uri", static_method_of = Uri)]
  pub fn is_uri(thing: JsValue, )-> JsValue;

  #[wasm_bindgen(js_class = "Uri", js_name = "fs_path", getter = fs_path, method)]
  pub fn fs_path(this: &Uri, )-> String;

  #[wasm_bindgen(js_class = "Uri", js_name = "with", method)]
  pub fn with(this: &Uri, change: js_sys::Object, )-> Uri;
siku2 commented 1 year ago

That looks very promising :)

ctron commented 1 year ago

That looks very promising :)

Indeed! A lot of work still waiting. But it feels like that requires only "writing it down". My goal is to bring it to a point where this matches what is already there. And it's based on the original monaco.d.ts file. So no manual pre-processing required.

ctron commented 1 year ago

I created a draft PR with the current state. It's not ready yet, but heading in the right direction I think: https://github.com/siku2/rust-monaco/pull/46