On 13 June 2017 at 05:48, <philip.chime...@gmail.com> wrote: > On Mon, Jun 12, 2017 at 2:36 PM Sam Jansen <sam.jan...@starleaf.com> > wrote: > >> On 11 June 2017 at 00:04, <philip.chime...@gmail.com> wrote: >> >>> On Fri, Jun 9, 2017 at 2:29 PM Sam Jansen <sam.jan...@starleaf.com> >>> wrote: >>> >>>> Hello, >>>> >>>> I've been following in the steps of some others [1] [2] who have >>>> attempted to produce Typescript definitions for Gtk and Gjs. I believe I >>>> have something more complete than any other effort I've found, so I thought >>>> it was time to share my work, and a couple of questions. >>>> >>>> Starting with gir2dts [2], I tried to write a basic application... And >>>> failed. Due to various limitations (no constructors, interfaces, etc.) So I >>>> went about at fixing any limitation I found and have ended up with a fairly >>>> thorough description in Typescript of the GI interfaces presented by Gjs. >>>> >>>> Examples of some features I'm particularly happy with: >>>> >>>> - Signals, via the connect() function, are checked using >>>> Typescript's string literal type checking [3] >>>> - The above includes the "notify::attribute" syntax >>>> - All possible parameters for a class are described in an >>>> interface, and this is used in the default Gjs constructor. This allows >>>> editors like Visual Studio Code to provide code completion and type >>>> checking for the arguments to this object >>>> - Classes are decomposed into static and instance sides. The static >>>> side is used to describe the Gjs constructor, and then extended with the >>>> other GI constructor functions >>>> - Ability to include the documentation, such that it will be shown >>>> in code completion popups >>>> - Multiple return values described correctly >>>> >>>> >>>> All of this is possible due to the excellent work of the original >>>> project, gir2dts, that I have simply forked and added extra support to. >>>> >>>> This project is available at: https://github.com/sammydre/gir2dts >>>> >>> >>> This is *fantastic*. >>> >>> >> >> Thanks :) >> >> >>> I'm still not sure it's all that useful generally just yet -- largely >>>> due to me not knowing how such code should be distributed, or work with >>>> module systems. Any comments on how to structure this would be appreciated. >>>> >>> >>> I admit I don't know much about Typescript. If I understand correctly, >>> this would be a plugin for the Typescript compiler, so it should be >>> distributed in whatever way is usual there. >>> >>> >> >> It seems the way most people are using it now is via "@typings", which is >> supported by npm. >> >> I think the best thing for me to do is document what I have at the moment >> / write a good example and point to it here to solicit further discussion. >> So I'll come back to this at some point in the future, all going well. >> > > Yes, an example and/or "getting started" document would be quite useful! > > Well, this led me down quite the rabbit-hole...
The end result is that I've completely rewritten the tool, this time in Typescript, and with *much* fewer hacks, and I believe overall a more correct approach. The tool is now at: https://github.com/sammydre/ts-for-gjs This includes sample output, e.g.: https://github.com/sammydre/ts-for-gjs/blob/master/out/GLib.d.ts And a couple of sample programs: https://github.com/sammydre/ts-for-gjs/blob/master/examples/browser/main.ts https://github.com/sammydre/ts-for-gjs/blob/master/examples/editor/main.ts The example programs are fairly boring -- they are pretty much just JS. The magic comes in the type-checking, autocompletion, etc. which isn't really easy to see without using it! If anyone wants to play; check out the github project then open the directory in visual studio code, "npm install", and it should all "just work". You'll also see here how I've implemented modules: just with relative path imports in typescript. Typescript then compiles this to "require" statements, which I bundle together with webpack right now; but this isn't strictly required. > [...] > >> >>>> - I've sometimes found that derived functions have different >>>> signatures, with Typescript does not like. An example of this is the >>>> "activate" symbol used in Gtk; consider "Widget.activate()" vs. >>>> "Button.activate(button: Button)" -- Button derives from Widget, but >>>> has a >>>> different signature for this method. What does Gjs do about this? "let >>>> a = >>>> new Gtk.Button({}); a.activate()" >>>> >>>> There is no Gtk.Button.activate() method. I guess you are probably >>> referring to the virtual method, which is called vfunc_activate() in GJS. >>> Virtual methods are not called directly from JS code, instead you would add >>> a vfunc_activate() method to a subclass of Gtk.Button if you wanted your >>> subclass to have different or additional behaviour from the default >>> Gtk.Button. (And the button parameter is lopped off, since it's bound to >>> "this" inside the method.) This method would only be called internally by >>> GTK. >>> >>> If you execute new Gtk.Button().activate() it calls >>> gtk_widget_activate(). >>> >>> The documentation in our DevDocs instance might shed some light here >>> [8]; as far as I know it generates all the method signatures correctly, and >>> you can feel free to borrow from that code. >>> >> >> I chose a bad example here. It showed that I had completely misunderstood >> the GI "virtual functions" and their mapping to GJS. Based on your input, >> I've now fixed that. >> >> But my question still stands, albeit with slightly different classes. >> Consider: >> >> - Gtk.MenuItem.activate() : http://devdocs.baznga.org/ >> gtk30~3.22.12/gtk.menuitem#method-activate >> <http://devdocs.baznga.org/gtk30~3.22.12/gtk.menuitem#method-activate> >> - Gtk.Widget.activate() : http://devdocs.baznga.org/ >> gtk30~3.22.12/gtk.widget#method-activate >> <http://devdocs.baznga.org/gtk30~3.22.12/gtk.widget#method-activate> >> >> >> MenuItem derives from Widget (via Bin via Container). >> >> The activate() method has a different signature. For widget, it returns a >> boolean. For MenuItem, it returns void. >> >> What does GJS do in this case? Will calling activate() always result in >> calling the MenuItem version on a MenuItem instance, making it impossible >> to call the Widget version directly? Or something else? >> > > Oh, I see now what you mean. I didn't even know this gotcha existed! Like > properties and methods with the same name, I would consider that a bug in > GTK. > > I'm not sure off the top of my head which one will take priority. I > suspect the one from the "most derived" class (Gtk.MenuItem) would hide the > Gtk.Widget method. > > However, you can call either one explicitly by executing > Gtk.Widget.prototype.activate.call(widget) or Gtk.MenuItem.prototype. > activate.call(widget). > That makes sense, it's very helpful. I eventually came to the conclusion that there is fundamentally a mismatch here between the "inheritance" one can describe in Typescript, and that used today in the GI bindings to especially GTK. There are a number of cases where the derived method/property doesn't match exactly. Rather than try and enumerate these all by hand and hack around them, I decided it's best not to use Typescript's inheritance, and just describe the complete set of methods and properties, resolving them all from the inheritance tree I look up in the GI info. Hence you'll see the Gtk.d.ts file is rather large (i.e. 6MB!) Finally, a problem I created for myself with types was wanting a vaguely safe way to down/up-cast. So I invented the rather hacky "giCast" function as defined here: https://github.com/sammydre/ts-for-gjs/blob/master/out/cast.ts#L691 I have a question: is there a better way to figure out what actual class an instance is at run-time? You can see here what I do is call toString() on it, then parse out the resulting string that has a "GIName:" in it. This works, but feels rather brittle... As things stand, this works well for me, and I'll continue to fix up bugs and limitations in the declarations as I find them (or they're reported to me). Cheers, Sam > > >> BTW, the devdocs is very useful - I didn't know that existed before your >> email! >> > > The docs have not spread so wide yet; we had them up for a while, then > they were gone for a while, and now they're back up, hopefully for good. > > [1]: https://github.com/niagr/GIR2TS / https://github.com/niagr/gjs-ts >>>> [2]: https://www.npmjs.com/package/gir2dts >>>> [3]: https://www.typescriptlang.org/docs/handbook/advanced-types.html >>>> [4]: https://people.gnome.org/~gcampagna/docs/Gtk-3.0/Gtk. >>>> Window.is_active.html >>>> [5]: https://people.gnome.org/~gcampagna/docs/Gtk-3.0/Gtk. >>>> Window-is-active.html >>>> >>> >>> [6] https://bugzilla.gnome.org/show_bug.cgi?id=690450#c30 >>> [7] https://bugzilla.gnome.org/show_bug.cgi?id=688650 >>> [8] http://devdocs.baznga.org/gtk30~3.22.12/gtk.button#vfunc-activate >>> >>
_______________________________________________ javascript-list mailing list javascript-list@gnome.org https://mail.gnome.org/mailman/listinfo/javascript-list