Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docgen does not distinguish between module and functor #1012

Open
woeps opened this issue Jun 7, 2024 · 0 comments
Open

docgen does not distinguish between module and functor #1012

woeps opened this issue Jun 7, 2024 · 0 comments

Comments

@woeps
Copy link
Contributor

woeps commented Jun 7, 2024

Currently a functor is treated exactly like a module (but ignores existent docstrings).

Example Functor to test docgen
/***
this module provides "convenient" utilities for logging  
NOTE: this is not a good example of a functor,
    but just to test docgen for functors
*/

module type Input = {
  /***
  input module type of the functor
  */

  /**
  type of the input
  */
  type t
  /**
  converts the input to a string
  */
  let toString: t => string
}

module type Logger = {
  /***
  returned type of the functor
  */

  /**
  type of the input
  */
  type t
  /**
  logs the input
  */
  let log: t => unit
}

module String = {
  /***
  input module of the functor to hanle strings
  */

  /**
  type of the input
  */
  type t = string

  /**
  converts the input to a string
  */
  let toString = (x: t) => x
}

module Int = {
  /***
  input module of the functor to handle integers
  */

  /**
  type of the input
  */
  type t = int

  /**
  converts the input to a string
  */
  let toString = (x: t) => x->Int.toString
}

/**
 functor that logs the input
 */
module MakeLogger = (I: Input): (Logger with type t := I.t) => {
  /***
  functor that logs the input
  */

  /**
   logs the Input
   */
  let log = (x: I.t) => I.toString(x)->Console.log
}

/**
the module that contains the functions to log strings
*/
module StringLogger = MakeLogger(String)
/**
the module that contains the functions to log integers
*/
module IntLogger = MakeLogger(Int)

module Var = {
  /***
  another input module for the Logger functor to handle a Variant of type type 
  */

  /**
  type of the input
  */
  type t = Yes | No

  /**
  converts the input to a string
  */
  let toString = x =>
    switch x {
    | Yes => "Yes"
    | No => "No"
    }
}

module Included = {
  /***
  module which includes the Var Logger!
  */
  include MakeLogger(Var)
}
generated json
{
  "name": "Functor",
  "docstrings": ["this module provides \"convenient\" utilities for logging  \nNOTE: this is not a good example of a functor,\n    but just to test docgen for functors"],
  "source": {
    "filepath": "test/Functor.res",
    "line": 1,
    "col": 1
  },
  "items": [
  {
    "id": "Functor.Input",
    "name": "Input",
    "kind": "moduleType",
    "docstrings": [],
    "source": {
      "filepath": "test/Functor.res",
      "line": 7,
      "col": 13
    },
    "items": [
    {
      "id": "Functor.Input.t",
      "kind": "type",
      "name": "t",
      "signature": "type t",
      "docstrings": ["type of the input"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 15,
        "col": 3
      }
    }, 
    {
      "id": "Functor.Input.toString",
      "kind": "value",
      "name": "toString",
      "signature": "let toString: t => string",
      "docstrings": ["converts the input to a string"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 16,
        "col": 3
      }
    }]
  }, 
  {
    "id": "Functor.Logger",
    "name": "Logger",
    "kind": "moduleType",
    "docstrings": [],
    "source": {
      "filepath": "test/Functor.res",
      "line": 22,
      "col": 13
    },
    "items": [
    {
      "id": "Functor.Logger.t",
      "kind": "type",
      "name": "t",
      "signature": "type t",
      "docstrings": ["type of the input"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 30,
        "col": 3
      }
    }, 
    {
      "id": "Functor.Logger.log",
      "kind": "value",
      "name": "log",
      "signature": "let log: t => unit",
      "docstrings": ["logs the input"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 31,
        "col": 3
      }
    }]
  }, 
  {
    "id": "Functor.String",
    "name": "String",
    "kind": "module",
    "docstrings": ["input module of the functor to hanle strings"],
    "source": {
      "filepath": "test/Functor.res",
      "line": 37,
      "col": 8
    },
    "items": [
    {
      "id": "Functor.String.t",
      "kind": "type",
      "name": "t",
      "signature": "type t = string",
      "docstrings": ["type of the input"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 45,
        "col": 3
      }
    }, 
    {
      "id": "Functor.String.toString",
      "kind": "value",
      "name": "toString",
      "signature": "let toString: t => t",
      "docstrings": ["converts the input to a string"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 50,
        "col": 7
      }
    }]
  }, 
  {
    "id": "Functor.Int",
    "name": "Int",
    "kind": "module",
    "docstrings": ["input module of the functor to handle integers"],
    "source": {
      "filepath": "test/Functor.res",
      "line": 53,
      "col": 8
    },
    "items": [
    {
      "id": "Functor.Int.t",
      "kind": "type",
      "name": "t",
      "signature": "type t = int",
      "docstrings": ["type of the input"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 61,
        "col": 3
      }
    }, 
    {
      "id": "Functor.Int.toString",
      "kind": "value",
      "name": "toString",
      "signature": "let toString: t => string",
      "docstrings": ["converts the input to a string"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 66,
        "col": 7
      }
    }]
  }, 
  {
    "id": "Functor.MakeLogger",  <-- this is the functor
    "name": "MakeLogger",
    "kind": "module",
    "docstrings": [],  <-- empty docstrings
    "source": {
      "filepath": "test/Functor.res",
      "line": 1,
      "col": 1
    },
    "items": [
    {
      "id": "Functor.MakeLogger.log",
      "kind": "value",
      "name": "log",
      "signature": "let log: I.t => unit",
      "docstrings": ["logs the input"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 31,
        "col": 3
      }
    }]
  }, 
  {
    "id": "Functor.StringLogger",
    "kind": "moduleAlias",
    "name": "StringLogger",
    "docstrings": ["the module that contains the functions to log strings"],
    "source": {
      "filepath": "test/Functor.res",
      "line": 86,
      "col": 8
    },
    "items": []
  }, 
  {
    "id": "Functor.IntLogger",
    "kind": "moduleAlias",
    "name": "IntLogger",
    "docstrings": ["the module that contains the functions to log integers"],
    "source": {
      "filepath": "test/Functor.res",
      "line": 90,
      "col": 8
    },
    "items": []
  }, 
  {
    "id": "Functor.Var",
    "name": "Var",
    "kind": "module",
    "docstrings": ["another input module for the Logger functor to handle a Variant of type type"],
    "source": {
      "filepath": "test/Functor.res",
      "line": 92,
      "col": 8
    },
    "items": [
    {
      "id": "Functor.Var.t",
      "kind": "type",
      "name": "t",
      "signature": "type t = Yes | No",
      "docstrings": ["type of the input"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 100,
        "col": 3
      },
      "detail": 
      {
        "kind": "variant",
        "items": [
        {
          "name": "Yes",
          "docstrings": [],
          "signature": "Yes"
        }, 
        {
          "name": "No",
          "docstrings": [],
          "signature": "No"
        }]
      }
    }, 
    {
      "id": "Functor.Var.toString",
      "kind": "value",
      "name": "toString",
      "signature": "let toString: t => string",
      "docstrings": ["converts the input to a string"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 105,
        "col": 7
      }
    }]
  }, 
  {
    "id": "Functor.Included",
    "name": "Included",
    "kind": "module",
    "docstrings": ["module which includes the Var Logger!"],
    "source": {
      "filepath": "test/Functor.res",
      "line": 112,
      "col": 8
    },
    "items": [
    {
      "id": "Functor.Included.log",
      "kind": "value",
      "name": "log",
      "signature": "let log: Var.t => unit",
      "docstrings": ["logs the input"],
      "source": {
        "filepath": "test/Functor.res",
        "line": 31,
        "col": 3
      }
    }]
  }]
}

I guess we need to introduce a new kind called functor?
At least a "signature" field should be present (similar to items of kind value): "signature": "module MakeLogger = (I: Input) => (Logger with type t := I.t)". And docstrings should be taken into account.

Questions

  • What to show as return type for a functor with no explicit return type annotation?
  • How to handle (destructive) substitution (with type...:= / = e.g. Logger with type t := I.t)? Is there something to do at all?
  • How to make referenced module types machine readable? (should there be a json field with an array of referenced module type ids? (How) Is this related to docgen should name module type for explicitly annotated module type #1010?)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant