elixir_sense icon indicating copy to clipboard operation
elixir_sense copied to clipboard

Expansion of Application.compile_env/3 doesn't work with paths

Open xxdavid opened this issue 3 years ago • 3 comments

First, thank you so much for the amazing ElixirLS and the underlying ElixirSense. ❤️

I really like the feature of inference of application env variables when using modules attributes, which was introduced by #133. The only thing I miss is the support for expressions like Application.compile_env(:my_app, [:key, :foo, :bar]) (see Application.compile_env/3 docs). The PR treats compile_env/3 and get_env/3 the same (and similarly the bang versions) but the functions differ in whether they support paths/list in the second argument (get_env does not). Thus, the inference for expression like the one mentioned does not work.

As compile_env is a macro, it cannot be called with apply. But maybe in case we get compile_env with a path, we can call get_env with the first element of the path and then traverse the returned expression on our own (similarly to how it is done in the compile_env macro itself).

Would a PR be welcomed?

xxdavid avatar Jul 15 '22 13:07 xxdavid

Would a PR be welcomed?

Yes

lukaszsamson avatar Jul 18 '22 07:07 lukaszsamson

A quick way to do it is to define a new function, like this one and pattern match on args when it's a non-empty list. In that case, you can use apply with the first element on the list, and then use get_in(result, rest_of_path)

gugahoa avatar Aug 12 '22 15:08 gugahoa

A quick way to do it is to define a new function, like this one and pattern match on args when it's a non-empty list. In that case, you can use apply with the first element on the list, and then use get_in(result, rest_of_path)

This cannot be easily implemented. List comprehension has landed only recently in https://github.com/elixir-lsp/elixir_sense/pull/168 but the type system of the Binding module is not powerful enough to handle this case. It makes a simplified guess of lists type basing on the first element.

the type of this expression

Application.compile_env(:my_app, [:key, :foo, :bar])

is

{
   :call,
   {:atom, Application},
   :compile_env,
   [atom: :my_app, list: {:atom, :key}]
}

lukaszsamson avatar Oct 30 '22 06:10 lukaszsamson