Is there a convenient way to turn behaviour callbacks into specs?

I love using behaviours and using mox to quickly generate mocks to use in testing, but something that I find rather inconvenient is having to redefine @callback and @spec for every function. Type hinting is a must in my workflow, so I end up needing to write both more often that I’d like to. This is also especially inconvenient when I am still deciding my signatures.

Is there a tool or method I can use that will save me from this function spec duplication?

TypedStruct has worked wonders for me for handling struct types, so I’m kind of hoping something else exists for my callbacks and specs.

Thank you for any help!

2 Likes

Hi @Tam !

I am not sure I follow. You don’t need to redefine the spec in every function. You can define it once in file where you define the behaviour (mox/README.md at master · dashbitco/mox · GitHub) and then use @impl BehaviourModuleName by the function (mox/README.md at master · dashbitco/mox · GitHub).

Does that make sense?

2 Likes

Hey thanks for the note. Sorry, I should have been a bit more clear: I use spec and callback to help me mainly with type hinting, as well as with mox, but more so the type hint portion is what I’m craving.

Without a spec on functions, elixir-ls in VSCode almost exclusively claims all functions only have any() params. This is what I’d like to change

Perhaps maybe I can make it more clear with an explicit example:

Notice here that VS code is auto-specing my execute function with

@spec execute(any) :: any

Even though I have a callback that describes the function, it seems like I have to also write the spec for it as well, despite already having the spec laid out to begin with. Just trying to reduce the amount of code that I need to type, but if it’s not possible, no problem; just wanted to ask, since hours of googling “type hinting” and “specs” plus “elixir” on and off over the past few months hasn’t netted a clear answer or understanding.

Does the type-hinting change if you add @impl true just above def execute?

Did not; just added a few more yellow squiggles instead, haha. Which is great, though. I appreciate the explicit interface implementation (something I missed while working with golang recently).

The spec hint you get in vscode is based on what dialyzer infered for the function. Given dialyzer isn’t aware of callbacks/behaviour afaik there’s probably no way to make those hints any better based on the implemented callback.

1 Like

Ok, thanks for clarifying. I suppose the only way to get that behaviour would be to create a separate plugin for VSCode that can index the @callback and @behaviour tags at the VSCode layer?

Or extend how the existing tooling fetches the info for the hint.