rescript-lang / rescript-vscode

Official VSCode plugin for ReScript

Repository from Github https://github.comrescript-lang/rescript-vscodeRepository from Github https://github.comrescript-lang/rescript-vscode

docgen id is ambiguous

woeps opened this issue · comments

The way docgen currently calculates the id is ambiguous if

  • a type and a value in the same module have the same name
  • a module type and a module in the same module have the same name

This defeats the purpose of having a (supposedly unique) id.

Value / Type Example

type x = int
let x = 42

generates

{
  "name": "Example",
  "docstrings": [],
  "source": {
    "filepath": "src/Example.res",
    "line": 1,
    "col": 1
  },
  "items": [
  {
    "id": "Example.x",   <-- here
    "kind": "type",
    "name": "x",
    "signature": "type x = int",
    "docstrings": [],
    "source": {
      "filepath": "src/Example.res",
      "line": 1,
      "col": 1
    }
  }, 
  {
    "id": "Example.x",    <-- here
    "kind": "value",
    "name": "x",
    "signature": "let x: int",
    "docstrings": [],
    "source": {
      "filepath": "src/Example.res",
      "line": 2,
      "col": 5
    }
  }]
}

Module (Type) Example

// Example.res
module type M = { type x = int}
module M = {
  let x = 42
}

generates

{
  "name": "Example",
  "docstrings": [],
  "source": {
    "filepath": "src/Example.res",
    "line": 1,
    "col": 1
  },
  "items": [
  {
    "id": "Example.M",  <-- here #1
    "name": "M",
    "kind": "moduleType",
    "docstrings": [],
    "source": {
      "filepath": "src/Example.res",
      "line": 6,
      "col": 13
    },
    "items": [
    {
      "id": "Example.M.x",  <-- here #2
      "kind": "type",
      "name": "x",
      "signature": "type x = int",
      "docstrings": [],
      "source": {
        "filepath": "src/Example.res",
        "line": 6,
        "col": 19
      }
    }]
  }, 
  {
    "id": "Example.M",  <-- here #1
    "name": "M",
    "kind": "module",
    "docstrings": [],
    "source": {
      "filepath": "src/Example.res",
      "line": 7,
      "col": 8
    },
    "items": [
    {
      "id": "Example.M.x",  <-- here #2
      "kind": "value",
      "name": "x",
      "signature": "let x: int",
      "docstrings": [],
      "source": {
        "filepath": "src/Example.res",
        "line": 8,
        "col": 7
      }
    }]
  }]
}

Proposal

Either we state an id is only unique per kind which will probably confuse people, or we extend the id.
The simplest thing would probably be to additionaly include kind in the id: <kind>.<modulePath>.<itemName>.

For the above examples:

  • type.Example.x / value.Example.x
  • moduleType.Example.M / module.Example.M
  • type.Example.M.x / value.Example.M.x

P.S: If above seems appropriate, I think I'd be able to send a PR to implement this:
I'd adapt the makeId function:

let makeId modulePath ~identifier =
identifier :: modulePath |> List.rev |> SharedTypes.ident

to take an additional optional labeled argument prefix and call it accordingly.

@zth do you have some thoughts on my proposal?

@woeps that looks good to me and should cover all use cases.