erlang-ls / erlang_ls

The Erlang Language Server
https://erlang-ls.github.io/
Apache License 2.0
620 stars 136 forks source link

Cannot find definition for function 'Mod':module_info/1 #1471

Closed carlotm closed 5 months ago

carlotm commented 6 months ago

Describe the bug

Got Cannot find definition for function 'Mod':module_info/1 from this snippet

attr(Mod, K) when is_atom(Mod) and is_atom(K) ->
    Attrs = Mod:module_info(attributes),
    proplists:get_value(K, Attrs).

To Reproduce

Just use the module_info/1 function

Expected behavior

Don't get the error message

Actual behavior

Got Cannot find definition for function 'Mod':module_info/1

Context

fridayy commented 6 months ago

Can confirm. I reckon a possible solution could be to skip the index lookup if Mod is a variable?

POI  = #{data =>
           #{mod_range => #{from => {14,13},to => {14,16}},
                 name_range => #{from => {14,17},to => {14,28}},
                 fun_is_variable => false,mod_is_variable => true},
           id => {'Mod',module_info,1},
           range => #{from => {14,13},to => {14,28}},
           kind => application}.

%% els_crossref_diagnostics.erl
has_definition(#{kind := application, id := {_Module, module_info, _Arity}, data := #{mod_is_variable := true}}) -> 
    true;
robertoaloi commented 6 months ago

@fridayy the has_definition clause you mention is used for the "XRef-like" diagnostics. It basically means that, if the module name is a variable, the language server assumes that a definition exists and does not complain about not existing functions.

The issue that @carlotm is reporting refers to the fact that no definition is found for the module_info/1 function. I'd say this is expected, since that function is a special function inserted by the compiler for each module. There's no place we can "jump to", so the "Cannot find definition" message seems legit. We could of course rephrase the message for those special functions.

fridayy commented 6 months ago

@robertoaloi thanks for the feedback!

I quickly skimmed through the code and found the has_definition clause that apparently handles module_info for "conventional" (not passed as function args) modules and thought this could be extended to handle this case as well. Happy to learn more about erlang-ls :)

But I see your point, in this particular case Mod might not even be an actual module so I think the error is reasonable and legit or maybe a warning would be more appropriate (if worth the hassle).

carlotm commented 5 months ago

@robertoaloi Thank you. Getting an error for valid code is a bit odd IMHO, but whatever... I'll live with it

robertoaloi commented 5 months ago

@carlotm Could you show where this surfaces as an error (e.g. via a screenshot)? I would expect the server, when no definition is found, to just return a [] or null according to the spec. I wonder if it's the client (yegapeppan) doing something weird here.

fridayy commented 5 months ago

module-info-error

carlotm commented 5 months ago

Mine is similar, just a little less fancy :)

Screenshot_2024-01-08_09-22-42

robertoaloi commented 5 months ago

Ah, I see what's happening. So this is in fact coming from the XRef diagnostics. From the message I assumed it was a regular go-to-definition. Then yes, we can tweak that case.

carlotm commented 5 months ago

And how does it compare with the case where, for example, you invoke a function which does not exist?

Screenshot_2024-01-08_09-50-12

If the function does not exist in Mod, no errors. In case of a non existing function, same exact error.

plux commented 5 months ago

Yep, this is a bug in CrossRef diagnostics.

carlotm commented 5 months ago

Thas was quick! Thank you!