-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdocs.json
1 lines (1 loc) · 24.5 KB
/
docs.json
1
[{"name":"CodeGenerator","comment":" This module let's you define type-oriented principled code generators.\n\nBy type oriented we mean generators that are driven by a type definition provided by the user.\n\nBy principled we mean that the generated code will for the foremost follow compositional patterns to be able to express (almost) any type.\n\n@docs CodeGenerator, define\n\n\n### Defining code generators\n\n@docs Definition, ifUserHasDependency\n\n\n### Using existing functions\n\nThe code generator will find matching functions in the users code and dependencies. It will divided them into multiple levels and prioritise like this:\n\n1. Values defined in the current file\n2. Values defined in other project modules that the current file imports.\n3. Values defined in dependency modules that the current file imports.\n4. Values defined in dependencies.\n5. Values defined in other project modules.\n6. Values hard-coded in the code generator definition.\n\nHowever, it will reject functions where multiple matching functions\nexists at the same level.\n\n@docs use\n\n\n### Primitives\n\n@docs bool, int, float, string, char, list, array, set, dict, maybe, customDict\n\n\n### Tuples\n\n@docs unit, tuple, triple\n\n\n### Combining values\n\n@docs succeed, map, mapN, pipeline, combiner\n\n\n### Dealing with custom types\n\n@docs customType, lambdaBreaker\n\n\n### Going crazy\n\n@docs custom\n\n\n## Advanced use\n\n@docs defineWithComputation, combinerWithInput, customTypeWithInput\n\n","unions":[{"name":"Definition","comment":" Definitions are a way to to generate and compose small snippets of code to handle specific situations that might occur in an Elm type.\nFundamentally you can think of all the definitions put together as forming a rather sophisticated function `ResolvedType -> Expression`, however this library will handle a large number of gotcha's for you, so it's more convenient to define the function piece-meal.\n","args":["a"],"cases":[]}],"aliases":[{"name":"CodeGenerator","comment":" Represents a code generator configuration.\n","args":[],"type":"Internal.CodeGenerator.CodeGenerator"}],"values":[{"name":"array","comment":" Handle a `List a` type. You will be given code that handles the `a` subtype.\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"bool","comment":" Handle an `Bool` type.\n","type":"Elm.Syntax.Expression.Expression -> CodeGenerator.Definition a"},{"name":"char","comment":" Handle a `Char` type.\n","type":"Elm.Syntax.Expression.Expression -> CodeGenerator.Definition a"},{"name":"combiner","comment":" If map, mapN, succeed, pipeline don't work for you, this is a more custom way to combine these.\n\nThe arguments that the function you pass will recieve are:\n\n1. Information about the type being constructed (e.g. `Foo Int`).\n2. An expression representing a function that creates the type in question (e.g. `makeFoo : Int -> Foo`).\n3. A list of expressions that have already been generated (e.g. `[ Decode.int ]`)\n\n","type":"(ResolvedType.ResolvedType -> Elm.Syntax.Expression.Expression -> List.List Elm.Syntax.Expression.Expression -> Maybe.Maybe Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"combinerWithInput","comment":" Like combiner, but allows you to control how input flows to the children and also receives input from its parent.\n","type":"(a -> ResolvedType.ResolvedType -> List.List ResolvedType.ResolvedType -> List.List a) -> (a -> ResolvedType.ResolvedType -> Elm.Syntax.Expression.Expression -> List.List Elm.Syntax.Expression.Expression -> Maybe.Maybe Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"custom","comment":" This allows you complete freedom in generating expressions, however it also doesn't give you much help.\n\nThe recommendation here is to use the normal definitions and only use this for exceptional cases.\n\n","type":"(ResolvedType.ResolvedType -> Maybe.Maybe Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"customDict","comment":" Handle a `Dict`, but get information about the types. This is useful, since sometimes we need the type of the keys.\n","type":"(( ResolvedType.ResolvedType, Elm.Syntax.Expression.Expression ) -> ( ResolvedType.ResolvedType, Elm.Syntax.Expression.Expression ) -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"customType","comment":" Deal with custom types. You will get a list of `( constructorName, expressionThatGeneratesTheTypeWithThatConstructor )`.\n\nThe challenge is to work out which of the branches should be chosen. You can solve that with a `andThen`, or the library might have a different mechanism for disjunctions.\n\n","type":"(List.List ( ResolvedType.Reference, List.List ResolvedType.ResolvedType ) -> List.List ( String.String, Elm.Syntax.Expression.Expression ) -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"customTypeWithInput","comment":" Like customType, but allows you to control how input flows to the children and also receives input from its parent.\n","type":"(a -> List.List ( ResolvedType.Reference, List.List ResolvedType.ResolvedType ) -> List.List a) -> (a -> List.List ( ResolvedType.Reference, List.List ResolvedType.ResolvedType ) -> List.List ( String.String, Elm.Syntax.Expression.Expression ) -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"define","comment":" Create a code generator. This requires the following pieces:\n\n - a unique id. This id can be used to extend the generator later.\n - a dependency name which specifies what this generator deals with. This generator will only be active if the user has that dependency installed.\n - a [`TypePattern`](TypePattern) that is used to figure out which type the function should work on.\n - a function that generates names if the generator needs to make an auxiliary definition\n - a list of Definitions that determine how code is actually generated. Note that later definitions will override previous ones.\n\n","type":"{ id : String.String, dependency : String.String, typePattern : TypePattern.TypePattern, makeName : String.String -> String.String } -> List.List (CodeGenerator.Definition ()) -> CodeGenerator.CodeGenerator"},{"name":"defineWithComputation","comment":" Like `define`, but this allows you to compute as you progress down the tree of types. Also note that `makeName` now takes a `Maybe`.\nIf you pass `Nothing`, than the generator will not create any auxiliary definitions, but will rather generate everything inline.\n","type":"{ id : String.String, dependency : String.String, typePattern : TypePattern.TypePattern, makeName : Maybe.Maybe (String.String -> String.String), input : a } -> List.List (CodeGenerator.Definition a) -> CodeGenerator.CodeGenerator"},{"name":"dict","comment":" Handle a `Dict`.\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"float","comment":" Handle a `Float` type.\n","type":"Elm.Syntax.Expression.Expression -> CodeGenerator.Definition a"},{"name":"ifUserHasDependency","comment":" Apply this definition conditionally if the user has this specific dependency installed (can be chained). Intended for things like json-pipeline or random-extra.\n","type":"String.String -> CodeGenerator.Definition a -> CodeGenerator.Definition a"},{"name":"int","comment":" Handle an `Int` type.\n","type":"Elm.Syntax.Expression.Expression -> CodeGenerator.Definition a"},{"name":"lambdaBreaker","comment":" Elm only allows recursive definitions if there is a lambda somewhere in the chain. For instance:\n\n naiveListDecoder : Decoder (List Int)\n naiveListDecoder =\n Decode.oneOf\n [ Decode.map2 (::) (Decode.index 0 Decode.int) (Decode.index 1 naiveListDecoder)\n , Decode.null []\n ]\n\nwould fail to compile, as this would crash immediately on calling the program with an infinite loop. Incidentally this would compile:\n\n naiveListDecoder2 : Decoder a -> Decoder (List a)\n naiveListDecoder2 childDecoder =\n Decode.oneOf\n [ Decode.map2 (::) (Decode.index 0 childDecoder) (Decode.index 1 (naiveListDecoder2 childDecoder))\n , Decode.null []\n ]\n\nBut the code would fail at runtime with a Maximum Call Stack Exceeded exception. However, this version would work fine:\n\n smartListDecoder : Decoder (List Int)\n smartListDecoder =\n Decode.field \"length\" Decode.int\n |> Decode.andThen\n (\\l ->\n case l of\n 0 ->\n Decode.succeed []\n\n 2 ->\n Decode.map2 (::) (Decode.index 0 Decode.int) (Decode.index 1 smartListDecoder)\n\n _ ->\n Decode.fail \"Unexpected list length\"\n )\n\nThe reason being the lambda, that is only evaluated when a preceding step succeeds, hence there will be no infinite evaluation.\n\nOf course, most libraries have a solution to this problem, typically called `lazy`, which we could use here:\n\n smartListDecoder2 : Decoder (List Int)\n smartListDecoder2 =\n Decode.oneOf\n [ Decode.map2 (::) (Decode.index 0 Decode.int) (Decode.index 1 (Decode.lazy (\\() -> smartListDecoder2))\n , Decode.null []\n ]\n\nHowever, if there is no `lazy` function, it can be implemented in terms of `andThen` and `succeed`:\n\n lazy fn =\n andThen fn (succeed ())\n\nWe call this `lazy` function a `lambdaBreaker`, since it's purpose it to break recursion with a lambda. Implementing it will enable the code generator to deal with recursive types.\n\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"list","comment":" Handle a `List a` type. You will be given code that handles the `a` subtype.\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"map","comment":" Transform a value inside a type. You will be handed the arguments.\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"mapN","comment":" A convenient way to specify `map2`, `map3`, `map4`, etc.\n\nThe first argument specifies up to what number of arguments you want to specify the `mapN`.\n\nThe first argument in the callback is the standard name, so for 3 arguments you will get `\"map3\"`.\n\n","type":"Basics.Int -> (String.String -> Elm.Syntax.Expression.Expression -> List.List Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"maybe","comment":" Handle a `Maybe a` type. You will be given code that handles the `a` subtype.\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"pipeline","comment":" Deal with any number of arguments using applicative style. The first argument is like for succeed, the second is a partially applied `andMap`.\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> (Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"set","comment":" Handle a `List a` type. You will be given code that handles the `a` subtype.\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"string","comment":" Handle a `String` type.\n","type":"Elm.Syntax.Expression.Expression -> CodeGenerator.Definition a"},{"name":"succeed","comment":" Wrap a value in the type. This is called different things in different libraries (i.e. `List.singleton`, `Random.constant`, etc.)\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"triple","comment":" Deals with 3-tuples (i.e. triples). No need to implement if you have `map3`, as it will automatically be used.\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"tuple","comment":" Deals with 2-tuples (i.e. pairs). No need to implement if you have `map2`, as it will automatically be used.\n","type":"(Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression -> Elm.Syntax.Expression.Expression) -> CodeGenerator.Definition a"},{"name":"unit","comment":" Handle the unit `()` type.\n","type":"Elm.Syntax.Expression.Expression -> CodeGenerator.Definition a"},{"name":"use","comment":" If there are multiple existing functions at the same level, this allows you to bless one of these to be used as the default implementation. Takes a fully qualified name.\n","type":"String.String -> CodeGenerator.Definition a"}],"binops":[]},{"name":"CodeGenerator.Test","comment":" Testing code generators can be tricky, but very rewarding as it makes developing CodeGenerators much easier.\n\n@docs codeGenTest, codeGenTestFailsWith, codeGenIncrementalTest, fakeDependency, FakeDependency\n\n","unions":[{"name":"FakeDependency","comment":" Represents a dependency that the user has in their project.\n","args":[],"cases":[]}],"aliases":[],"values":[{"name":"codeGenIncrementalTest","comment":" Like `codeGenTest`, but runs in incremental mode. Only looks for a fix for the first `Debug.todo` found.\n","type":"String.String -> List.List CodeGenerator.Test.FakeDependency -> List.List CodeGenerator.CodeGenerator -> List.List String.String -> String.String -> Test.Test"},{"name":"codeGenTest","comment":" Tests that a single `Debug.todo` gets replaced with a particular piece of code.\n\n codeGenTest \"Generates a generator for a int\"\n [ fakeDependency \"elm/random\" ]\n [ elmRandomCodeGeneratorUnderTest ]\n [ \"\"\"module A exposing (..)\n import Random\n\n generator : Random.Generator Int\n generator =\n Debug.todo \"\"\n \"\"\" ]\n \"\"\"module A exposing (..)\n import Random\n\n generator : Random.Generator Int\n generator =\n Random.int Random.minInt Random.maxInt\n \"\"\"\n\nThe arguments are:\n\n1. Description (i.e. what you would normally pass to `Test.test`)\n2. A list of dependencies. Note that this rule will only activate code generators based on dependencies in the user's project. This allows you to control which dependencies are present.\n3. A list of code generators. Typically this will be the code generator under test, but can also be used to test interactions between multiple.\n4. A list of code modules that form the project the rule is being run on. Exactly one of these must have a single top level `Debug.todo` that the test is trying to replace.\n5. The expected source code of the module containing the `Debug.todo` after running the code generator.\n\n","type":"String.String -> List.List CodeGenerator.Test.FakeDependency -> List.List CodeGenerator.CodeGenerator -> List.List String.String -> String.String -> Test.Test"},{"name":"codeGenTestFailsWith","comment":" Like `codeGenTest`, but expects the code generator to not be able to generate code. The final string is the expected error message.\n","type":"String.String -> List.List CodeGenerator.Test.FakeDependency -> List.List CodeGenerator.CodeGenerator -> List.List String.String -> String.String -> Test.Test"},{"name":"fakeDependency","comment":" Creates a fake elm review dependency type. This should only be used with the other helpers in this module, as the information inside the returned type is mostly rubbish.\n\nHow do you get this value without too much pain? I usually go to package.elm-lang.or, find the package I'm interested in, open the dev tools, in the Network tab find the `docs.json`,\nselect Preview, right-click and \"Store as global variable\", then run the following snippet:\n\n copy(\n `fakeDependency \\n { name = ${JSON.stringify(\n window.location.pathname.split(\"/\").slice(2, 4).join(\"/\")\n )}\\n , dependencies = []\\n , modules =\\n [ ${temp1\n .map(\n (mod) =>\n `{ name = ${JSON.stringify(mod.name)}\\n , values =\\n [ ${mod.values\n .map((v) => `( ${JSON.stringify(v.name)}, ${JSON.stringify(v.type)})`)\n .join(\"\\n , \")}\\n ]\\n }`\n )\n .join(\"\\n , \")}\\n ]\\n}`\n );\n\n","type":"{ name : String.String, dependencies : List.List String.String, modules : List.List { name : String.String, values : List.List ( String.String, String.String ) } } -> CodeGenerator.Test.FakeDependency"}],"binops":[]},{"name":"Derive","comment":"\n\n@docs rule\n\n\n### Pro-tip for VSCode users\n\nOpen your command palette and select `Preferences: Open Keyboard Shortcuts (JSON)` and add the following object to the array:\n\n```json\n {\n \"key\": \"ctrl+alt+d\",\n \"command\": \"runCommands\",\n \"when\": \"editorTextFocus\",\n \"args\": {\n \"commands\": [\n {\n \"command\": \"editor.action.insertSnippet\",\n \"args\": {\n \"snippet\": \"${TM_CURRENT_LINE/(.*):.+/\\n$1 =\\n Debug.todo \\\"\\\"/}\",\n \"langId\": \"elm\"\n }\n },\n { \"command\": \"workbench.action.files.save\" },\n { \"command\": \"workbench.action.terminal.focus\" },\n {\n \"command\": \"workbench.action.terminal.sendSequence\",\n \"args\": {\n \"text\": \"npx elm-review --fix --template gampleman/elm-review-derive/preview\\n\"\n }\n }\n ]\n }\n```\n\nThen whenever you type a type signature, you can hit `ctrl+alt+d` (you can customize the keybinding above).\n\nFor instance if you typed:\n\n decodeUserProfile : Decoder UserProfile\n\nThen running this will modify it to read:\n\n decodeUserProfile : Decoder UserProfile\n decodeUserProfile =\n Debug.todo \"\"\n\nIt will then save the file, open the integrated terminal and run `npx elm-review --fix --template gampleman/elm-review-derive/preview` in it.\n\n","unions":[],"aliases":[],"values":[{"name":"rule","comment":" Forbids the use of [`Debug.todo`] and uses type information at the top-level to fix.\n\n config =\n [ NoDebug.TodoItForMe.rule []\n ]\n\n🔧 Running with `--fix` will automatically generate code to replace some `Debug.todo` uses.\n\nIn particular it will generate code when `Debug.todo` is used in a top-level definition with an explicit\ntype annotation, like so:\n\n someFunction : Decoder SomeType\n someFunction =\n Debug.todo \"\"\n\nThere is an ever-expanding list of type signatures that this rule supports, however, it is relatively straightforward to\nadd your own. See [`CodeGenerator`](CodeGenerator) for details.\n\n\n## Try it out\n\nYou can try this rule out by running the following command:\n\n```bash\nelm-review --template gampleman/elm-review-derive/preview --fix\n```\n\n[`Debug.todo`]: https://package.elm-lang.org/packages/elm/core/latest/Debug#todo\n\n","type":"Basics.Bool -> List.List CodeGenerator.CodeGenerator -> Review.Rule.Rule"}],"binops":[]},{"name":"ResolvedType","comment":" This module is at the heart of the code generation process.\nThis library works by gathering all the information necessary to build this type,\nthen the code generator's job is to translate this type into an AST.\n\n@docs ResolvedType, Reference\n\n","unions":[{"name":"ResolvedType","comment":" Represents an Elm type that has been fully resolved:\n\n - all references are now in absolute module format\n - type variable applications have been applied\n - custom type and type alias information has been added\n\nThe constructors are:\n\n - `GenericType \"foo\" ref` represents an unfilled type variable `foo`\n - `Opaque ref vars` represents a custom type (or built in type)\n - `Function args return` represents a function type\n - `TypeAliasRecord ref args definition` represents a record where we have a type alias (and therefore a constructor) available\n - `AnonymouseRecord extensionVar definition` represents an anonymous record\n - `CustomType ref args [(constructorRef, arguments)]` represents a reference to an exposed (or accessible) custom type\n - `Tuple args` represents a tuple.\n\nLet's look at some simple examples and see how they would be represented:\n\n Int --> Opaque { modulePath = [\"Basics\"], name = \"Int\" } []\n\n List Int --> Opaque { modulePath = [\"Basics\"], name = \"List\" } [Opaque { modulePath = [\"Basics\"], name = \"Int\" } []]\n\n List a --> Opaque { modulePath = [\"Basics\"], name = \"List\" } [ GenericType \"a\" Nothing ]\n\n Int -> String --> Function [ Opaque { modulePath = [\"Basics\"], name = \"Int\" } [] ] Opaque { modulePath = [\"String\"], name = \"String\" } []\n\n { foo : Int } --> AnonymousRecord Nothing [ ( \"foo\", Opaque { modulePath = [\"Basics\"], name = \"Int\" } [] ) ]\n\n { x | foo : Int } --> AnonymousRecord (Just \"x\") [ ( \"foo\", Opaque { modulePath = [\"Basics\"], name = \"Int\" } [] ) ]\n\n () -> Tuple []\n\n ( Int, String ) --> Tuple [ Opaque { modulePath = [\"Basics\"], name = \"Int\" } [], Opaque { modulePath = [\"String\"], name = \"String\" } [] ]\n\nNow for some more complex examples:\n\n type Foo a =\n Bar a\n\n Foo a --> CustomType { modulePath = [], name = \"Foo\" } [ \"a\" ] [ ( { modulePath = [], name = \"Bar\" }, [ GenericType \"a\" Nothing ] ) ]\n\n Foo Int --> CustomType { modulePath = [], name = \"Foo\" } [ \"a\" ] [ ( { modulePath = [], name = \"Bar\" }, [ GenericType \"a\" (Just (Opaque { modulePath = [\"Basics\"], name = \"Int\" } [] ))] ) ]\n\nNote how in `Foo Int` the `Int` value is replaced in the definition.\n\n type alias Qux a =\n { foo : a }\n\n Qux a --> TypeAlias { modulePath = [], name = \"Qux\" } [ \"a\" ] [( \"foo\", GenericType \"a\" Nothing )]\n Qux Int --> TypeAliasRecord { modulePath = [], name = \"Qux\" } [ \"a\" ] [( \"foo\", GenericType \"a\" (Just (Opaque { modulePath = [\"Basics\"], name = \"Int\" } [] )))]\n\n","args":[],"cases":[["GenericType",["String.String","Maybe.Maybe ResolvedType.ResolvedType"]],["Opaque",["ResolvedType.Reference","List.List ResolvedType.ResolvedType"]],["Function",["List.List ResolvedType.ResolvedType","ResolvedType.ResolvedType"]],["TypeAlias",["ResolvedType.Reference","List.List String.String","ResolvedType.ResolvedType"]],["AnonymousRecord",["Maybe.Maybe String.String","List.List ( String.String, ResolvedType.ResolvedType )"]],["CustomType",["ResolvedType.Reference","List.List String.String","List.List ( ResolvedType.Reference, List.List ResolvedType.ResolvedType )"]],["Tuple",["List.List ResolvedType.ResolvedType"]]]}],"aliases":[{"name":"Reference","comment":" Represents a fully qualified name in Elm source code.\n","args":[],"type":"{ modulePath : List.List String.String, name : String.String }"}],"values":[],"binops":[]},{"name":"TypePattern","comment":"\n\n@docs TypePattern\n\n","unions":[{"name":"TypePattern","comment":" A type pattern represents a query over a type annotation. We use these to identify objects of interest in the users code, namely:\n\n1. Definitions with `Debug.todo` that we want to turn into code.\n2. Definitions that provide functionality that generated code might want to hook into.\n\nHowever, patterns can also be run in reverse, i.e. these can also be used to generate type annotations for auxiliary defintions.\n\nThe most important constructor here is `Target`, which denotes the type that will drive the code generation process.\n\n`Typed modulePath name arguments` represents a type application, like `Random.Generator target` could be `Typed [\"Random\"] \"Generator\" [ Target ]`.\n\n`Function` represents a `->` in a type. These are right-associative so `a -> b -> c` would be `Function (GenericType \"a\") (Function (GenericType \"b\") (GenericType \"c\"))`.\n\n`GenericType` takes a variable name. This name doesn't need to match the name of a type (so `Typed [] \"List\" (GenericType \"A\")` **will match** `List x`), but **do** need to match each other. So `Function (GenericType \"a\") (GenericType \"a\")` will match `x -> x` but will not match `x -> y`.\n\n","args":[],"cases":[["Target",[]],["Typed",["List.List String.String","String.String","List.List TypePattern.TypePattern"]],["Function",["TypePattern.TypePattern","TypePattern.TypePattern"]],["GenericType",["String.String"]],["Tuple",["List.List TypePattern.TypePattern"]],["Record",["List.List ( String.String, TypePattern.TypePattern )"]]]}],"aliases":[],"values":[],"binops":[]}]