Type-directed autocompletion with editor integration

I did some more work on the Type-Directed Autocomplete project and this is kind of a status update for what I showed in an earlier post. As explained there, the goal is to generate completions for Elm code which satisfy given type constraints, so that your editor only suggests code to you, which would actually lead to a compiling Elm file.

So, I already had some functions for generating the suggestions, but I also wanted a way to actually test these out in actual projects within the editor, to be able to see if the suggestions make sense and to further improve them. To do this, you need a tool that can infer the type of any expression within an Elm file and also collect all available values at this position. For example, given

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
  case msg of
    NoOp ->
      ( model
      , Cmd.none
      )

    NameChanged name ->
      ( whatGoesHere
      , Cmd.none
      )

that tool should tell me that whatGoesHere is of the type Model, and that at this position one can use the values name : String, msg : Msg, model : Model and all the top-level values which are defined elsewhere in the module or imported from other modules. Given that information, the completion generator can then suggest { model | name = name }, for example.

That sounded like a good learning opportunity, so I started writing such a tool. And as it seems to be in a state where one can at least try it out on smaller files/projects, I wanted to share it here. :slight_smile:

So, my plan for this right now is to improve the actual completion generator. It seems that there is a lot of stuff which can be explored! For example: better ranking (based on how “far away” the available
values are), generating encoders and decoders, incorporating placeholders (which a lot of snippet plugins support), etc. I’m happy for feedback and ideas for this! :slight_smile:

On the other hand I’m wondering, what would be a good way to proceed with this local-type-inference tool. Although it is fun to write your own inference algorithm, I feel like it may be beneficial to actually
start from the Elm compiler itself and see how one could modify it to get this type information. I just saw that the recommendation for the elm-find project is to
actually start with the Elm compiler. So my question here is, if that also makes sense for this tool?

10 Likes

The elm-find proposal is problematic as far as I’m concerned. We already have those features via the language server. (there might be some corner cases)

And starting from the elm compiler might also mean significant work, as it’s designed to run on compile-able code. You don’t want your feature to break as soon as some file does not compile anymore, that’s the reason I got into the whole tree sitter thing as that’s designed to deal with leaves of your ast breaking without breaking your whole ast. https://github.com/Razzeee/tree-sitter-elm

1 Like

I think that’s a good point. So there are probably two stages to this: syntactical correctness and sound types. For the first, it might be ok to require that all files on which the currently edited file depends on can be successfully parsed. And the current file may only have a syntax error at the position which one is currently editing. (At least, that is how I usually try to work, especially since elm-format only works on syntactically correct files.) So for example, I’m thinking about a situation where my code looks like this

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        NameChanged name ->
            ( { model | name =

where the cursor is currently at the end of the last line. So, I was thinking that it may be possible to adjust the parser, such it can recover from these syntax errors in a sensefull way. I feel like that because of the way the Elm syntax works (for example, that function declarations must not be indented and function bodies must be indented) it might be possible to resolve most of these syntax errors which occur while one is writing code. I would be very interested if that is actually the case. :slight_smile:

For the type checking part, I believe it may make also sense to require all dependencies to be compilable, since the type-directed suggestions might not be that good if you have contradictions in parts of your code base you are depending on. When the current file contains type errors somewhere, that might be ok, I guess, as the inference algorithm may still be able to assign some type to the value one is currently interested in. At least, that is what I assume, as one usually gets type-checking errors for a lot of places in one file at the same time.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.