rescript-vscode icon indicating copy to clipboard operation
rescript-vscode copied to clipboard

WIP: dump asts

Open nojaf opened this issue 1 year ago • 5 comments

When calling bunx rescript-tools.exe doc MyFile.res I would like to have some more details about the binding signatures. Mainly what the parameter types and return type is.

Currently I get:

{
  "signature": "let createOrder: FirebaseFunctions.callableFunction<\n  Domain.createOrderRequest,\n  string,\n>",
}

After this PR:

{

 "signature": "let createOrder: FirebaseFunctions.callableFunction<\n  Domain.createOrderRequest,\n  string,\n>",
 "detail": {
      "returnType": {
        "path": "FirebaseFunctions.callableFunction",
        "genericTypeParameters": [{
          "path": "Domain.createOrderRequest"
        }, {
          "path": "string"
        }]
      }
    }
}

Using Tools_Docgen I want to detect FirebaseFunctions.callableFunction and what the type parameters are to generate client ReScript code in my project. I currently use a Regex to process this, but I would like to grab that information more easily from the JSON.

In order to figure out what on earth is present in Types.type_expr I wrote a helper file to dump the contents in friendly, JSON esque way:

Example:

type_desc.Tconstr(
  path = function$
  ts = [
    type_desc.Tarrow(
      t1 = type_desc.Tconstr(path = string, ts = [])
      t2 = type_desc.Tconstr(path = string, ts = [])
    )
    type_desc.Tvariant({
      row_fields = [ (label = Has_arity1, row_field = row_field.Rpresent) ]
      row_more = type_desc.Tnil
      row_closed = true
      row_fixed = false
    })
  ]
)

This is inspired by what we do in our F# ast viewer.

@zth although this is still WIP, I could already use a review to find out if I'm going in the right direction with this.

nojaf avatar Oct 08 '24 19:10 nojaf

Added some more code to do a dump of the full file.

{
  package = { genericJsxModule = None }
  file = {
    uri = 
      "file:///home/nojaf/projects/tenmileselverdinge-tickets/functions/src/CreateOrder.res"
    moduleName = "CreateOrder"
    structure = {
      name = "CreateOrder"
      docstring = []
      items = [
        {
          kind = 
            SharedTypes.Module.Value(
              type_desc.Tconstr(
                path = function$
                ts = [
                  type_desc.Tarrow(
                    t1 = type_desc.Tconstr(path = string, ts = [])
                    t2 = type_desc.Tconstr(path = string, ts = [])
                  )
                  type_desc.Tvariant({
                    row_fields = [ (label = Has_arity1, row_field = row_field.Rpresent) ]
                    row_more = type_desc.Tnil
                    row_closed = true
                    row_fixed = false
                  })
                ]
              )
            )
          name = "encodeURIComponent"
          docstring = []
          deprecated = None
        }
        {
          kind = 
            SharedTypes.Module.Value(
              type_desc.Tlink(
                type_desc.Tconstr(
                  path = JsonCombinators.Json.Decode.t
                  ts = [ type_desc.Tlink(type_desc.Tconstr(path = bool, ts = [])) ]
                )
              )
            )
          name = "decodeTurnTile"
          docstring = []
          deprecated = None
        }
        {
          kind = 
            SharedTypes.Module.Value(
              type_desc.Tlink(
                type_desc.Tconstr(
                  path = function$
                  ts = [
                    type_desc.Tlink(
                      type_desc.Tarrow(
                        t1 = type_desc.Tlink(type_desc.Tconstr(path = string, ts = []))
                        t2 = 
                          type_desc.Tlink(
                            type_desc.Tconstr(
                              path = RescriptCore.Promise.t
                              ts = [ type_desc.Tlink(type_desc.Tconstr(path = bool, ts = [])) ]
                            )
                          )
                      )
                    )
                    type_desc.Tvariant({
                      row_fields = [ (label = Has_arity1, row_field = row_field.Rpresent) ]
                      row_more = type_desc.Tnil
                      row_closed = true
                      row_fixed = false
                    })
                  ]
                )
              )
            )
          name = "validateTurnTileToken"
          docstring = []
          deprecated = None
        }
        {
          kind = 
            SharedTypes.Module.Value(
              type_desc.Tlink(
                type_desc.Tconstr(
                  path = function$
                  ts = [
                    type_desc.Tlink(
                      type_desc.Tarrow(
                        t1 = type_desc.Tlink(type_desc.Tconstr(path = Domain.food, ts = []))
                        t2 = type_desc.Tlink(type_desc.Tconstr(path = Stripe.priceId, ts = []))
                      )
                    )
                    type_desc.Tvariant({
                      row_fields = [ (label = Has_arity1, row_field = row_field.Rpresent) ]
                      row_more = type_desc.Tnil
                      row_closed = true
                      row_fixed = false
                    })
                  ]
                )
              )
            )
          name = "stripePriceIdOfFood"
          docstring = []
          deprecated = None
        }
        {
          kind = 
            SharedTypes.Module.Value(
              type_desc.Tlink(
                type_desc.Tconstr(
                  path = function$
                  ts = [
                    type_desc.Tlink(
                      type_desc.Tarrow(
                        t1 = type_desc.Tlink(type_desc.Tconstr(path = Domain.ticket, ts = []))
                        t2 = type_desc.Tlink(type_desc.Tconstr(path = Stripe.priceId, ts = []))
                      )
                    )
                    type_desc.Tvariant({
                      row_fields = [ (label = Has_arity1, row_field = row_field.Rpresent) ]
                      row_more = type_desc.Tnil
                      row_closed = true
                      row_fixed = false
                    })
                  ]
                )
              )
            )
          name = "stripePriceIdOfTicket"
          docstring = []
          deprecated = None
        }
        {
          kind = 
            SharedTypes.Module.Value(
              type_desc.Tlink(
                type_desc.Tconstr(
                  path = FirebaseFunctions.callableFunction
                  ts = [
                    type_desc.Tlink(type_desc.Tconstr(path = Domain.createOrderRequest, ts = []))
                    type_desc.Tlink(type_desc.Tconstr(path = string, ts = []))
                  ]
                )
              )
            )
          name = "createOrder"
          docstring = []
          deprecated = None
        }
      ]
      deprecated = None
    }
  }
}

This is nice, and could hopefully someday turn into an ast viewer. I am bumping, however, into some OCaml limitations that make the recursive processing of mk_type_desc. It doesn't stack overflow but is very slow when called from mk_item.

nojaf avatar Oct 09 '24 08:10 nojaf

Alright, @zth, this is ready for review!

The original goal was to include more information about a function signature in the JSON. However, I got side-tracked and added a dump command to the tool, which will pretty print the SharedTypes.full type. This was very useful for determining what I needed to pattern match on to extract the signature information.

Please let me know your thoughts on this. If you believe this addition is worthwhile, I would greatly appreciate a thorough review, as I think this is my first OCaml PR. Thanks a bunch for your time!**

nojaf avatar Oct 12 '24 12:10 nojaf

I'm considering to split this PR in two, I want to experiment a bit further with the dump tool. Would like to extract the signature information part in a separate PR.

nojaf avatar Oct 18 '24 14:10 nojaf

I'm considering to split this PR in two, I want to experiment a bit further with the dump tool. Would like to extract the signature information part in a separate PR.

Sounds reasonable!

zth avatar Oct 18 '24 14:10 zth

I'm considering to split this PR in two, I want to experiment a bit further with the dump tool. Would like to extract the signature information part in a separate PR.

Sounds reasonable!

@zth I created https://github.com/rescript-lang/rescript-vscode/pull/1043 with the signature json changes.

nojaf avatar Oct 19 '24 10:10 nojaf