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

[Question] Preventing omnisharp from changing solution file automatically #869

Closed
sim590 opened this issue Jan 29, 2025 · 14 comments
Closed

Comments

@sim590
Copy link
Contributor

sim590 commented Jan 29, 2025

I have this in a .vim file:

let g:OmniSharp_start_server = 0
let g:OmniSharp_port = 2000

let s:OmnisharpStarted = 0
fun s:StartServer()
  if s:OmnisharpStarted == 0
    OmniSharpStartServer C:\path\to\my\project.sln
    let s:OmnisharpStarted = 1
  endif
endf

augroup OmnisharpServer
  autocmd!
  autocmd BufRead,BufNewFile *.cs call s:StartServer()
augroup END

And whenever I navigate to another csharp file and I open the log with OmniSharpOpenLog, then the solution file displayed as TARGET in the log is not the same as the one that I configured in my .vim file. It is correctly configured if I open the log in the first buffer that I opened. But the second buffer seems to change the requested solution for the server. I want that to stop.

@sim590
Copy link
Contributor Author

sim590 commented Jan 29, 2025

Actually, it seems like the buffer PID in both logs are different, so it seems like Omnisharp-vim starts another server EVEN though I set let g:OmniSharp_start_server = 0. What's going on ???

@nickspoons
Copy link
Member

What's happening is that OS-vim is starting multiple servers, which is by design. If you run :OmniSharpStatus you will see a list of the servers that are running against which solutions, how many projects the server has, how long it's been running and the PID.

But your script only has a single s:OmnisharpStarted variable, so it can't handle this properly

@sim590
Copy link
Contributor Author

sim590 commented Jan 29, 2025

I don't know what's going on because, I got this output from :OmniSharpStatus in both my buffers (two files):

C:\path\to\my\project.sln
  pid: 33440                                                                                                                                                                                                                                                running (11 projects) for 1 minute 

The command yields the same output in both buffers. In the first buffer, I'm able to use <Plug>(omnisharp_find_usages), but in the second buffer, it doesn't work. I can't even see No usages at the bottom. It just doesn't do anything.

Both files are under the same project (csproj).

@sim590
Copy link
Contributor Author

sim590 commented Jan 29, 2025

I don't really care about the vim config that I wrote above. If there's a way to make sure that OmniSharp only uses a single solution file and doesn't change it depending on the buffer, I would appreciate being directed towards the documentation for it (if there is). Otherwise, if someone can just explain to me how to do that.

@nickspoons
Copy link
Member

Oh no with your config, the 2nd server won't be started immediately. The 2nd buffer has no server associated with it so no, it won't respond to mappings. The strange thing is that you say there is a log with a different PID - that buffer should not have a log at all, :OmniSharpLog from a buffer with no server running should just open the directory containing the log files.

I don't really care about the vim config that I wrote above. If there's a way to make sure that OmniSharp only uses a single solution file and doesn't change it depending on the buffer, I would appreciate being directed towards the documentation for it (if there is). Otherwise, if someone can just explain to me how to do that.

There isn't really I'm afraid. There have been a few attempts to do it but nobody did it well.

The way to do it is to allow the function that finds the correct server, to be overridden by the user. So you can have your own function which in your case will only ever return "C:\path\to\my\project.sln". But this option doesn't currently exist.

@sim590
Copy link
Contributor Author

sim590 commented Jan 29, 2025

Oh no with your config, the 2nd server won't be started immediately. The 2nd buffer has no server associated with it so no, it won't respond to mappings. The strange thing is that you say there is a log with a different PID - that buffer should not have a log at all, :OmniSharpLog from a buffer with no server running should just open the directory containing the log files.

Sometimes it did that, sometimes it opened a random log I guess? I don't know what happened.

There isn't really I'm afraid. There have been a few attempts to do it but nobody did it well.

Well, this means that it's impossible to find functions that use a given function (with <Plug>(omnisharp_find_usages)) if the solution omnisharp selects is the callee solution that doesn't contain the caller function?

The way to do it is to allow the function that finds the correct server, to be overridden by the user. So you can have your own function which in your case will only ever return "C:\path\to\my\project.sln". But this option doesn't currently exist.

It seems to me that this functionality should be a core one since the use case I just shared a paragraph above is recurrent and obvious one once you start to split big projects in smaller ones. Some projects are gonna call some other and then we're screwed if we can't go up in the call tree...

@nickspoons
Copy link
Member

I don't really understand your use-case or what your project structure looks like, but it's certainly possible to break large projects up and have OS-vim run separate servers for them all. Every time you open a .cs file, that file is associated with a server and that server is (currently) selected by walking up the directory tree to find a .sln file.

If you're talking about finding usages of a library function in client projects, no you can't do that from the library solution. Have you seen this capability in other editors?

@sim590
Copy link
Contributor Author

sim590 commented Jan 29, 2025

If you're talking about finding usages of a library function in client projects, no you can't do that from the library solution. Have you seen this capability in other editors?

Visual Studio lets you do that. All that you have to do is to open a solution file that contains both the caller project and the callee's.

For instance:

  • Project A (MyRepo/ProjectA/ProjectA.csproj):
    • has ProjectA.sln that contains project A's csproj and its dependencies' csproj.
    • has function functionA.
  • Project B (MyRepo/ProjectB/ProjectB.csproj):
    • has ProjectB.sln file that contains project B's csproj and its dependencies' csproj. Its dependencies list contain ProjectA.csproj.
    • has function functionB. This function calls functionA.

Just step into project B's solution and navigate to functionA. Then press SHIFT+F12 and all the functions inside solution B that call functionA are going to be brought up in the list and the user is going to be able to select functionB.

If I try to do that with Omnisharp, then I won't be able because as soon as I navigate to functionA in its vim buffer, the selected solution will have changed and then it won't be able to find functionB anymore...

In Visual Studio, the solution the user is using doesn't change based on the file that you open. This concept is a bit weird since a solution is supposed to be a collection of projects that you wan to work with. It defines the scope of your work. The scope should be changed just because there exists "sub-scopes" in the tree of directories.

@sim590
Copy link
Contributor Author

sim590 commented Jan 29, 2025

Is there any issue with this patch?

diff --git a/autoload/OmniSharp.vim b/autoload/OmniSharp.vim
index e906410..b92364b 100644
--- a/autoload/OmniSharp.vim
+++ b/autoload/OmniSharp.vim
@@ -105,6 +105,9 @@ endfunction
 
 " Find the solution or directory for this file.
 function! OmniSharp#FindSolutionOrDir(...) abort
+  if g:OmniSharpSolutionFile != ''
+    return g:OmniSharpSolutionFile
+  endif
   let interactive = a:0 ? a:1 : 1
   let bufnr = a:0 > 1 ? a:2 : bufnr('%')
   if empty(getbufvar(bufnr, 'OmniSharp_buf_server'))

Because, this actually fixes my issue when I set g:OmniSharpSolutionFile = "C:\\path\\to\\the\\file.sln".

I can now get the list of callers from the callee in the sub project.

@nickspoons
Copy link
Member

Yeah Visual Studio and OmniSharp-roslyn take a different approach to how they start servers. VS starts from a solution. OS-roslyn starts from a directory.

The VS approach makes sense for VS because you use it from a GUI and the design is to pick a solution and go to work. That doesn't make so much sense in vim which is an editor and isn't supposed to work on just a "solution" of work but can quite happily work on files from many different solutions at once.

So OS-vim has to be able to work with .NET solutions but also be able to work in a larger scope. If we just find the solution of the first .cs file encountered and only ever work with that solution then that's a limitation, and would require people to be quite careful about how they start a session in a scenario like yours.

So basically in your situation you have the project file referenced in 2 different solutions, yes? And you would start Visual Studio by loading ProjectB.sln. If I was working with this code base I suppose I'd do something like temporarily remove ProjectA.sln and move ProjectB.sln to the parent directly of both projects, but I can see how that would be annoying to have to do constantly.

@nickspoons
Copy link
Member

Is there any issue with this patch?

I think this will work but it's still limiting - instead of just overriding with a .sln, what about making that option a function, like PR #317?

@sim590
Copy link
Contributor Author

sim590 commented Jan 29, 2025

I will try to refactor #317 so that it solves my case and upload the PR again.

@nickspoons
Copy link
Member

OK thanks. Please update the help to include the new option, with a very simple example

@sim590
Copy link
Contributor Author

sim590 commented Jan 30, 2025

This was fixed in #870.

@sim590 sim590 closed this as completed Jan 30, 2025
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

2 participants