ScalablyTyped / Converter

Typescript to Scala.js converter
https://scalablytyped.org
GNU General Public License v3.0
222 stars 44 forks source link

[Documentation] Advice to users on how to explore generated typings #141

Closed benhutchison closed 4 years ago

benhutchison commented 4 years ago

With the recent fix to #109 I was able to import Babylonjs (using an interim locally built converter).

When sbt fastOptJS completed OK, as a new user I was baffled where to look to explore the generated facade, and the current docs don't really address that.

Suggest:

  1. Emit user-focussed message at the end of facade generation in SBT saying "Facade for '\<name>' generated at \<prefix>/.ivy2/local/org.scalablytyped/\<somepath>.jar". There's some warn logging ATM but it resembles debug info not a user-oriented msg, ie colored blue & purple and lots of debug info:
[warn] Phase3Compile.scala:248 Built /Users/ben/.ivy2/local/org.scalablytyped/babylonjs_sjs1_2.13/4.1.0-35693c/jars/babylonjs_sjs1_2.13.jar in 49706 ms [thread => 216, project => Scala.js/ScalablyTyped/Babylonjs example, ms => 123390, phase => build, id => babylonjs, flavour => Normal]
  1. Adding a section in the docs covering:

    • How to view facade code from shell. AFAICT, the generated jar is binary only, so Im not actually sure what to advise. I found some generated source under target/streams/_global/stImport/_global/streams/sources/b/babylonjs/src/main/scala/typings/babylonjs/... maybe point them at that..?

    • How to view facade in Intellij, metals etc. In Intellij, sbt refresh project then displays the generated facade as part of dependencies. I can see the facade there, complete with Scaladocs. I'm not sure if the view is decompiled by Intellij or its resolved the code against the target/streams/_global/stImport/_global/streams/sources/... path above.

benhutchison commented 4 years ago

Maybe a nicer solution to viewing facade than looking under target/streams/_global/stImport/etc.. from users POV is to generate a babylonjs_sjs1_2.13-sources.jar in ivy cache

oyvindberg commented 4 years ago

This is very good input, thank you! There should be some "how to get started" instructions once the conversion is done. Let's figure out what form it can take.

First though, do you not get source jars? They should be setup in intellij and metals just fine already.

$ find ~/.ivy2/local/org.scalablytyped/babylonjs_sjs0.6_2.13/4.1.0-8e2e43/
/home/olvind/.ivy2/local/org.scalablytyped/babylonjs_sjs0.6_2.13/4.1.0-8e2e43/jars/babylonjs_sjs0.6_2.13.jar
/home/olvind/.ivy2/local/org.scalablytyped/babylonjs_sjs0.6_2.13/4.1.0-8e2e43/ivys/ivy.xml
/home/olvind/.ivy2/local/org.scalablytyped/babylonjs_sjs0.6_2.13/4.1.0-8e2e43/poms/babylonjs_sjs0.6_2.13.pom
/home/olvind/.ivy2/local/org.scalablytyped/babylonjs_sjs0.6_2.13/4.1.0-8e2e43/srcs/babylonjs_sjs0.6_2.13-sources.jar

What's under target/streams/_global should probably be deleted. I've left it in place now largely because they are referenced in the source maps, meaning you might have working source maps until you clean. But that's a problem for another day, #117 .

And for all the debug output I'd love to replace all of it with a nice text animation or something while it works, and only dump things to console with a given flag set. That flag already exists as stQuiet, we just need to flip it.

oyvindberg commented 4 years ago

Also I'm not sure we should do anything to encourage people to read scala code in a shell, or manually dig around jarfiles with strange version numbers.

Everything of that has already been set up, so the next step for a user should be something like where do I import code from? how can I discover what code has been generated, and which part is more useful

benhutchison commented 4 years ago

Doh! confirming I get sources. I was just looking in the jars folder for them..

BenHutchisonSeek commented 4 years ago

I'm not sure we should do anything to encourage people to read scala code in a shell, or manually dig around jarfiles with strange version numbers.

For intellij IDE users, there's a nice option in mounting the typings library into the project and browsing around.

Metals IDE Im not confident about; found it to be pretty fragile when anything is broken/non-compiling in the project.

Then there's the non-IDE people, vim, emacs etc. Can't see any alternative for them to open up and browsing the generated sources.. Except maybe regular users can mentally translate from TS and infer what the Scala facade will be. For myself, Im waaaaay off from that ATM but I can envisage it happening eventually with practice.

oyvindberg commented 4 years ago

Vim/emacs users will use metals as well, and if not that's a form of self harm I won't be helping to enable :D

I'm thinking a get started guide. We already have how to setup the plugin, and the next chapter would be how to find and use stuff. And after the conversion is done we can just output a link to it. Wdyt @benhutchison ?

benhutchison commented 4 years ago

Yes, there's a need for another section about finding and navigating the generated typings.

I can't give much sensible input on how to do that yet, because I'm still just making sense of the typings myself. But I suspect some example case studies, possibly enumerating some "typical" structures found in TS modules as categories, will help people find their way into typings.

In the case of Babylonjs, the emitted typings are huge and include many types multiple times; eg typings.babylonjs.audioIndexMod.AudioEngine, typings.babylonjs.BABYLON.AudioEngine and typings.babylonjs.indexMod.AudioEngine. I get this is a consequence of the input TS structure, but its confusing nonetheless. It's going to take me a while yet to digest...

oyvindberg commented 4 years ago

I completely understand the problems you're having with that! I'll try to do a writeup one of the following days.

In the meantime though, let me describe how I see it, perhaps it can be a useful angle for that writeup.

Background

You probably understood most of this when minimizing @benhutchison , but for others here is the background.

Given a converted thing like AudioEngine, to follow your example, it exists a bunch of places:

$ find -name AudioEngine.scala
./typings/babylonjs/BABYLON/AudioEngine.scala
./typings/babylonjs/mod/AudioEngine.scala
./typings/babylonjs/legacyMod/AudioEngine.scala
./typings/babylonjs/audioIndexMod/AudioEngine.scala
./typings/babylonjs/audioEngineMod/AudioEngine.scala
./typings/babylonjs/indexMod/AudioEngine.scala

In Javascript the implementation of AudioEngine will be in one Javascript file rather deep in the hierarchy. Depending on packaging of the library (I haven't used it) it might me importable from there. In addition, it is reexported a bunch of times in the levels of the hierarchy above it, for what Javascript people call convenience.

This results in a bunch of possible paths through which it can be reached:

$ find -name AudioEngine.scala|xargs cat --|grep JSImport
@JSImport("babylonjs", "AudioEngine")
@JSImport("babylonjs/Legacy/legacy", "AudioEngine")
@JSImport("babylonjs/Audio/index", "AudioEngine")
@JSImport("babylonjs/Audio/audioEngine", "AudioEngine")
@JSImport("babylonjs/index", "AudioEngine")

In addition, it might be exported through the global namespace. Whether it actually is might depend on how the library was implemented and how it was bundled. If it exists, it'll be reachable here:

@JSGlobal("BABYLON.AudioEngine")

Note that all these might be valid. They might also all be exactly the same class instance, or they could be changed in any way. Which one you choose will affect tree shaking/dead code elimination at bundle-time.

This is all Javascript - quite a mess. It'll be no less of a mess in Scala.js.

So fine, where do we go from here then?

This last point is the key, the package name is the import. typings.babylon.mod.AudioEngine = import { AudioEngine } from 'babylonjs';; typings.babylon.legacyMod.AudioEngine = import { AudioEngine } from 'babylonjs/Legacy/legacy';; typings.babylon.audioIndexMod.AudioEngine = import { AudioEngine } from 'babylonjs/Audio/index; typings.babylon.audioEngineMod.AudioEngine = import { AudioEngine } from 'babylonjs/Audio/audioEngine; typings.babylon.indexMod.AudioEngine = import { AudioEngine } from 'babylonjs/index;

Unfortunately the connection between an import and a package name is a bit obfuscated. I met nothing but pushback on the long package names which kept the entire module path, so there is a strategy to shorten them.

Usage

So how do you use this? Like you would in Typescript. Import from the top-level module (typings.xxx.mod) unless you discover a good reason not to. Also note that only values are re-exported in this manner. Types are not, so whenever you come across a type or a trait you need, just let your IDE import it for you.

Does that help?

benhutchison commented 4 years ago

Does that help? It does. Thanks for explain. Worth folding this explanation into future docs I reckon.

For TS literate people who know the underlying lib well, they will probably have a intuitive sense of what to use.

Scala people used to type safe Scala APIs and not TS/JS will get a reality check, but that cant be helped

oyvindberg commented 4 years ago

The intuition is simply to use the top-level import, what ends up as mod in ScalablyTyped, because it's the easiest. Perhaps that summary is enough to get people started without looking too much into why there are poentially many versions.

oyvindberg commented 4 years ago

Ok, so this took a while. I just published a "what do I do now" page. What do you think @benhutchison . I'm closing this for now, but feel free to keep commenting or drop by gitter for a chat :)

benhutchison commented 4 years ago

Hi @oyvindberg, that's a really valuable addition to the docs that speaks to the kind of questions I had after spewing out all the BabylonJS typings.

Sadly I havent had time to play with Babylon or frontend/Scalajs in general these past few months.. Where does the time go!?

I didnt actually know there was a gitter for ScalablyTyped? maybe some more advertising of the topic name would help.

It vaguely on my TODO list to give a talk about Scalajs & Scalably Typed to Melbourne Scala meetup, there's been an uptick of interest with Scalajs going 1.x, although very little industrial use in Australia AFAIK

oyvindberg commented 4 years ago

Good point, I'll put the link in a more prominent place.

And yeah, feel free to reach out if you do - some talks would be good by now :)