elixir-lsp / vscode-elixir-ls

Elixir language support and debugger for VS Code, powered by ElixirLS.
https://marketplace.visualstudio.com/items?itemName=JakeBecker.elixir-ls
MIT License
546 stars 106 forks source link

Getting invalid association warning when using belongs_to #20

Closed thiagomajesk closed 4 years ago

thiagomajesk commented 4 years ago

Hi! I'm getting what I believe is a false-positive warning:

I have a schema called "regions" that defines many "zones":

# region.ex
schema "regions" do
    field :name, :string
    has_many :zones, Zone
    timestamps()
end

# zone.ex
schema "zones" do
    field :name, :string
    belongs_to :region, Region
    timestamps()
end

I'm receiving the warning:

invalid association `zones` in schema Region: associated schema Zone does not have field `region_id`

Since the field region_id in the "zones" schema is inferred from the belongs_to association, I don't understand why this warning is necessary. Is this a problem!?

axelson commented 4 years ago

This looks like a standard compiler error so you'd be better off asking on https://elixirforum.com/ or in the Slack or Discord. If this is an error that only appears in the language server (after deleting your .elixir_ls, _build, and deps directories) then we could try and investigate.

thiagomajesk commented 4 years ago

It' seems that the error got stuck in vscode since it first happened (a couple of days ago). I've run mix clean and mix compile --force and no warnings were shown. Then, I did what you said and deleted .elixir_ls, _build and deps, recompiled and the warning was gone 😄.

I noticed that this happens sometimes. What I've been doing is comment/uncomment code to force refreshing, but this one got stuck for days.

axelson commented 4 years ago

Yeah there definitely is a bug there where the compilation gets stuck. If you could help find some reliable reproduction steps then that would be very helpful!

thiagomajesk commented 4 years ago

Ok, I think I got it:

1- Comment the belongs_to and has_many relationships 2- Uncomment just the has_many relationship and close the file without saving it - even though vscode will not recognize a file change because it's the previous state of the file (this part is important because it seems that saving is a trigger). Now you should see the error 3- Uncomment the belongs_to relationship and close the file 4- The error should be stuck in the "problems" section of the terminal until you open the file and "force-save" it (ctrl + s), then the error is gone.

axelson commented 4 years ago

I'm having a little trouble reproducing the error. Are you saving on any step besides step 4? For example after step 1 or step 3?

thiagomajesk commented 4 years ago

@axelson My bad, I should have been a little more specific. I've tried to reproduce again like this, see if it helps:

1- Comment the belongs_to and has_many relationships and save both files 2- Uncomment just the has_many relationship and save the file (Right now, you are probably already seeing the error message) 3- Uncomment the belongs_to relationship and save the file (If you go to the other file, you'll see that the error's still there) 4- Now, if you close both files, the error will get stuck on the "problems" section of the terminal 5- Open the file with the problem and even though it's already been saved, press ctrl + s

axelson commented 4 years ago

Okay, those reproduction steps are helpful. Unfortunately I'm not sure we can handle this case well. Ecto uses Macro.expand to avoid a compile-time dependency between these two files. That was introduced here https://github.com/elixir-ecto/ecto/pull/1670

This means that when you save zone.ex in step 3, region.ex is not compiled and thus does not get it's warnings updated. You can kind of see that by manually running mix compile after step 2 and 3:

$ mix compile
Compiling 1 file (.ex)
warning: invalid association `zones` in schema MyZones.Context.Region: associated schema MyZones.Context.Zone does not have field `region_id`
  lib/my_zones/context/region.ex:1: MyZones.Context.Region (module)

$ mix compile
Compiling 1 file (.ex)

From this you can see that zone.ex is not recompiled (if it was you would see "Compiling 2 files (.ex)" for the second command)

thiagomajesk commented 4 years ago

I don't know if I understood it correctly. But I have a question:

Shouldn't the compilation be triggered when you save the files at the end of both step 2 and step 3? (I didn't quite get why it just compiles in step 3, to be honest)

If I run mix compile after step 2, I get the said error in the terminal and if I do it again after step 3 everything is fine in the cli. However, vscode still keeps showing the error until I open the file and save (even though it's already saved).

PS.: I'm sorry if I'm being naive. I guess that to be more helpful here I probably should know a little bit more how that works under the hood.