Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imports not detected when client sends only textDocument/didOpen on newly created file (Unity project, neovim client) #2250

Open
mjlbach opened this issue Oct 19, 2021 · 30 comments

Comments

@mjlbach
Copy link

mjlbach commented Oct 19, 2021

Hi!

I'm trying to troubleshoot some issues the client I work on has with omnisharp-roslyn, and I was hoping I could ping you all for help.

The issue is, when opening a unity project, say one containing the following file:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Everything is fine, our client detects the imports no problem.

However, the minute we open a new file (for which we send the requisite textDocument/didOpen notification) with the exact same content, in the exact same subdirectory, the server returns import error messages:

The type or namespace name 'UnityEngine' could not be found (are you missing a using directive or an assembly reference?) irective or an assembly reference?)

Other servers seem to be fine recognizing new files this way. Do we need to send an additional notification when creating a new file such as workspace/didChangeWatchedFiles?

@mjlbach mjlbach changed the title Imports not detected when client sends only textDocumnet/didOpen on newly created file Imports not detected when client sends only textDocument/didOpen on newly created file (Unity project, neovim client) Oct 19, 2021
@ChimpSpin
Copy link

Having the same issue in Helix.

@JoeRobich
Copy link
Member

JoeRobich commented Jan 25, 2022

Unity projects are Full Framework style projects and require each code file to have a corresponding <Compile Include="{filename}" /> element in the .csproj to be included in the project. If you have added a new file without adding the <Compile> element, then I would expect O# to open the file in its "Miscellaneous" project which does not include any Unity dependencies.

Edit: After reviewing what happens when the FileChangeWatcher fires, there is a heuristic in O# that will match a new code file to an existing project based on whether the code file exists alongside or beneath the project file on the filesystem. This matching would not persist between sessions unless the project file was updated with the appropriate <Compile> element.

@JoeRobich
Copy link
Member

However, the minute we open a new file

Is this a new file that has been saved and exists on disk?

Do we need to send an additional notification when creating a new file such as workspace/didChangeWatchedFiles?

If the file was added to the filesystem, then I expect that file watchers would need to be updated.

@mjlbach
Copy link
Author

mjlbach commented Jan 25, 2022

Is this a new file that has been saved and exists on disk?

It's a new file that has not been added to the project. If I'm understanding you correctly then you must regenerate the solution files after the addition of a new file for omnisharp to pick up the imports correctly?

It seems to work fine in vscode creating a new file without regenerating the solution file in unity, no errors are thrown (left).
Opening the same file in neovim (right) yields a bunch of errors.

image

Edit: After reviewing what happens when the FileChangeWatcher fires, there is a heuristic in O# that will match a new code file to an existing project based on whether the code file exists alongside or beneath the project file on the filesystem. This matching would not persist between sessions unless the project file was updated with the appropriate element.

Is it possible that vscode is doing something on each startup that adds this file?

It seems like, on further glance, that vscode is not providing completion candidates (or hover) for UnityEngine on the newly added file without regenerating the solution file.

@nyngwang

This comment was marked as duplicate.

@niscolas
Copy link

I actually was able to maintain a sustainable workflow by creating a second class (let's say Foo.cs) on a already "Synced File" (where the LSP features work normally) and using the Code Action Move type to Foo.cs.
That way it's possible to work on Foo.cs without problems.
But that's just a workaround, but maybe it can lead us somewhere.

@crissNb
Copy link

crissNb commented Oct 14, 2022

A workaround I have found is to add the following line to Assembly-CSharp.csproj:
<Compile Include="**/*.cs" />

As mentioned above, each Unity code file needs to have <Compile..../> element in the .csproj file.
On neovim (using OmniSharp Roslyn LSP server), it seems like the .csproj file (specifically Assembly-CSharp.csproj) does not get automatically "refreshed" after it changes. The changes to .csproj file only seem to be applied after restarting neovim (and omnisharp).
This doesn't seem to be the case with vscode, however. When making changes to .csproj file (adding the compile element), vscode directly picks up the change and omnisharp server seems to be working as intended.

I believe "Regenerate Project Files" button on Unity just ensures there's the <Compile.../> tag in the .csproj file for newly created/renamed files. There is a Unity plugin for vscode (and a modified version to work with neovim) that automatically regenerates the project files when there's a new file. This is done in Unity though.

I doubt my workaround is going to be a good solution in the long run, mostly because Unity generates this file, which will override the line I've described above.

@niscolas
Copy link

I'll test that approach later.
But what I've found is it seems like there're 2 different problems.
There're some repos on GitHub mimicking the behavior of Unity plugins for VSCode and JetBrains Rider, like this: neovim/neovim#17808 (comment)
I even tried to improve on it myself, but even using Unity's API to Regenerate Project Files automatically on file changed, the behavior described in this issue still occurs.

@nickspoons
Copy link
Member

I've been looking into this in a similar issue for OmniSharp-vim. From what I've seen, I believe omnisharp-vscode has a file watcher watching the .csproj file, and when it is modified (by Unity, which adds a new <Compile ...> element for the new file) then vscode sends a /filesChanged request for the csproj to OmniSharp-roslyn, which then reloads the project.

I've tried to mimic this /filesChanged request from OmniSharp-vim and works - the new file is now part of the project, without requiring a full OmniSharp-roslyn restart.

@niscolas
Copy link

That's great to hear! Is this change on the repo yet?

@nickspoons
Copy link
Member

Which repo? OmniSharp-vim? Not yet. But I'm just adding it as a command, :OmniSharpRelosdProject, there aren't file watchers in OmniSharp-vim.

I was letting you know what my findings were in case you wanted to investigate making that /filesChanged request from neovim lsp

@nickspoons
Copy link
Member

Oh... 1 issue may be that OmniSharp-vim doesn't run OmniSharp-roslyn on LSP mode. I'm not sure if omnisharp-vscode has switched to LSP mode either? So I don't know if the /filesChanged endpoint will have the same effect from neovim LSP. Hopefully?

@gsihaj5
Copy link

gsihaj5 commented Oct 27, 2022

is it possible to watch the files from nvim and send request when the document is changed and document created

for unity i notice the .csproj file is changing after adding, removing and renaming files. is it possible to watch this .csproj file ?

if it possible did the request to server reload all the index ?

@crissNb
Copy link

crissNb commented Nov 19, 2022

Is there any update to this issue? Adding on to what has been previously said:
From my testing, although I'm not entirely certain, I've noticed that making changes (i.e. adding a new line of <Compile> tag) to the .csproj does not queue the project file for ProjectManager to process. Is this an expected behavior from file watchers?

Another combination I've tested is adding the <Compile> tag before adding the .cs file itself in a same session. This also didn't work, as .csproj did not get queued (according to my assumption).

@niscolas
Copy link

Following the idea from @nickspoons above (with my little knowledge of LSPs) I tried to find if there's a way to make a similar request to this /filesChanged in to the Omnisharp LSP client.
Unfortunately, it seems that this endpoint doesn't exist for the LSP side.
These are the endpoints for Omnisharp, it's listed on the "v1", but I think these endpoints are only really valid for non LSP stuff, these are the handlers for the LSP part
The closest I could find was this: OmnisharpOnDidChangeWatchedFilesHandler
But doesn't seem that there's a way to request something from it, and I don't really know how to interact with it.
Sorry for the dumbness but I don't really know much about LSP, just leaving my little research.

@nyngwang
Copy link

nyngwang commented Feb 1, 2023

@niscolas I finally found something related: neovim/neovim#21293, which is a PR that could be an important factor in finding/creating the solution to the problem.

@0rphee
Copy link

0rphee commented Feb 9, 2023

@ChimpSpin have you managed to get it working on helix? I see that some people above (#2250 (comment)) have vscode as their configured editor, and it seems it generates some files (seemingly config files) that may be involved in allowing the lsp to work correctly.

As a note, I don't even have basic functionality for a single file... so I would really thank you, if you could help me :)

Screenshot 2023-02-09 at 5 56 16 p m

@niscolas
Copy link

@0rphee
I think that for being able to work without major issues with Unity (except the one discussed in this issue), you need:

  • A properly working Neovim + LSP setup
  • Have the Omnisharp LSP server installed and configured (I recommend Mason for that)
  • Have a secondary editor directly supported by Unity and with an official integration plugin (either Visual Studio or Jetbrains Rider, since Unity seems to be dropping support for VSCode - link)
    That's what I've always done and had no problems besides this one

@niscolas
Copy link

@nyngwang

@niscolas I finally found something related: neovim/neovim#21293, which is a PR that could be an important factor in finding/creating the solution to the problem.

That's super interesting!
That seems to indeed solve the issue here, have you tested the solution on that PR?

@0rphee
Copy link

0rphee commented Feb 10, 2023

@niscolas thanks, though I forgot to mention that I don't use nvim! I use helix... anyway, maybe I will take a look at the links that you talk about. They may help, thanks!

@ChimpSpin
Copy link

@0rphee
I had to download https://github.com/OmniSharp/omnisharp-roslyn and add this to my languages.toml

[[language]]
name = "c-sharp"
language-server = { command = "<Your path to>/OmniSharp.exe", args = ["--languageserver" ] }

@0rphee
Copy link

0rphee commented Feb 14, 2023

@ChimpSpin
I already have that in my languages.toml, but omnisharp doesnt seem to find UnityEngine as shown in the image from my first comment (#2250 (comment)). Did you have to change any other settings specifically to get it working with Unity?

sorry for bothering :( its just that I am a bit lost with this...

Screenshot 2023-02-09 at 5 56 16 p m

@ChimpSpin
Copy link

@0rphee
Aside from that, I just had to generate the project files from within unity.

Edit > Preferences > External Tools > Regenerate project files

I don't think there was anything else to it.

@0rphee
Copy link

0rphee commented Feb 14, 2023

@ChimpSpin thank you!

and sorry for bothering...

@nyngwang
Copy link

nyngwang commented Mar 6, 2023

@niscolas FYI: The linked PR I mentioned 3 weeks ago had been merged into Neovim recently: neovim/neovim#21293. (Haven't tested it though, but definitely usable for Nvim-Unity plugin author.)

@niscolas
Copy link

niscolas commented Mar 6, 2023

Yay, that's great!
I'll be taking a look as soon as I can to check whether it solves the issue and if we will still need some kind of plugin in either side (Neovim / Unity)

@steventhorne
Copy link

@nyngwang How would one use this new feature to solve the new file issue?

@dimixar
Copy link

dimixar commented Apr 6, 2023

@nyngwang How would one use this new feature to solve the new file issue?

Bump, I also wanna know. Kinda a newb in all this.

@niscolas
Copy link

niscolas commented Apr 6, 2023

I believe that I just got it to work.

  • You should be using a build for Neovim that includes the changes in the PR above (link), I recommend just using bob to install Neovim nightly
  • Your LSP Capabilities table should include workspace.didChangeWatchedFiles.dynamicRegistration = true (Neovim news.txt), example:
local cmp_nvim_lsp = require("cmp_nvim_lsp")
local capabilities = cmp_nvim_lsp.default_capabilities()
capabilities = vim.tbl_deep_extend("force", capabilities, {
    workspace = {
        didChangeWatchedFiles = {
            dynamicRegistration = true,
        },
    },
})
// pass `capabilities` to your LSP server `setup()`

@niscolas
Copy link

niscolas commented Apr 6, 2023

I only tested this by creating the file through Unity, so I think it automatically adds the file to the Assembly-CSharp.csproj.
If creating files directly from Neovim, there's the need of using a package in the Unity side, like this one: https://github.com/niscolas/com.unity.ide.neovim-fork
I didn't test it recently, but it should work, it also adds Neovim as an External Editor option in Unity's settings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests