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
Refactor the architecture #102
Conversation
Hey @tcx4c70! |
hey @tcx4c70 thanks so much for your hard dedicated work! |
Hi @ckangnz , when you say "smarter to understand the root folder better", do you mean the big changes 3? If so and you're eager to get the fix, maybe I can cherry-pick it without the mutiple workspace folder support to master branch. BTW, I think the responsibility of understanding the root folder should be in language client rather than language server. What language server shoud do is to reuse the knowledge of root folder client tells ( |
Hey thanks for the response! I'm just waiting for this to be updated..! No need to rush though. Take your time. Really appreciate your contribution and I'm looking forward to be able to code c# with vim again |
I just pulled down the latest version and it works! Thank you so much 🙂 |
hey @tcx4c70 @razzmatazz 🙋 happy holidays!! Any ideas when this will be merged? I'd like to give implementing progress a go while I have some time off, but I wanted to figure out whether I should base off of this branch or master. Also more than willing to help chunk this up despite my piss poor F# skills, because this tool is invaluable to me for work |
Thats really good changes ! Hope it would be merged soon , @tcx4c70 do you test these changes on large projects in terms of response speed or it's still in development ? |
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
It can do nothing now. Signed-off-by: Adam Tao <tcx4c70@gmail.com>
… disk To avoid saving Solution obj every time (every change will create a new Solution obj), we use MSBuildWorkspace in WorkspaceManager. However, MSBuildWorkspace.TryApplyChanges will write all changes to disk, which is not we want for a language server. I have tried the following ways, but all fails: 1. Inherit MSBuildWorkspace and override all callers of MSBuildWorkspace.TryApplyChanges: MSBuildWorkspace is sealed so it can't be inherited. 2. Use Castle.Core to generate a proxy and avoid calling MSBuildWorkspace.TryApplyChanges: MSBuildWorkspace hasn't default constructor so Castle.Core will throw a System.NotSupportedException. 3. Inherit WorkSpace and implement OpenSolutionAsync & OpenProjectAsync ourself: The implementations of MSBuildWorkspace.OpenSolutionAsync & MSBuildWorkspace.OpenProjectAsync use many `internal` methods. If we rewrite them all, then we will rewrite the whole Microsoft.CodeAnalysis & Microsoft.CodeAnalysis.MSBuild, which is a huge work and is not suitable for a language server implementation. For now, Harmony is the only way I find that can work. But it also has some limitations: 1. Harmony doesn't support all .Net version. If we want to upgrade .Net version, we need to wait Harmony releases a version that support the .Net version we want to upgrade to. Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Just copy & paste. Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
…ticTokens/range Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
For now, we will response None/empty to client until we finish loading solution/projects. For some requests, client will retry. But for others, client won't. And LSP spec doesn't say client must retry until receiving a non-empty response. Hence, we should block all reqeusts until we can handle it. Signed-off-by: Adam Tao <tcx4c70@gmail.com>
workspaces itself is not mutable, only the elements inside it are mutable. Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Just like what Castle doc suggests [1]. [1] https://github.com/castleproject/Core/blob/master/docs/dynamicproxy.md Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Mock HostWorkspaceServices as early as possible to make sure that `document.Project.Solution.Workspace.Services` and `document.Project.Solution.Services.WorkspaceServices` are the same object (to make sure that both of them are mocked). Signed-off-by: Adam Tao <tcx4c70@gmail.com>
It's based on PR razzmatazz#123. Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Signed-off-by: Adam Tao <tcx4c70@gmail.com>
Hey @tcx4c70 What I want to do is to pull changes gradually (w/ cherrypicks), while testing on my own. Q1. Would you agree with this approach? (Instead of merging the whole PR at once) Q2. I am seeing problems running this on my machine (dotnet8 on an arm64 mac):
|
I began work to ingest this PR by cherry-picking commits to master |
Sure, please go ahead with any way you like. I will rebase to rewrite git history to make cherrypick easier.
I don't have a macbook, but I'll test it on my orange 5 plus, which has an arm64 CPU. |
This PR is a huge rework that almost refactors the whole architecture of the software.
background
Server.fs
andRoslynHelpers.fs
are very large (both of them have more than 1000 lines). I don't think it's a good smell so I try to split them.textDocument/didChange
needs read-write access, every time I type two or three chars, csharp-ls will block other requests until the currenttextDocument/didChange
has been done. But we really need such strong consistency? IMO, eventual consistency is enough. Even if some unconsistency occur because of the order of handlingtextDocument/didChange
,textDocument/didSave
will correct them. But eventual consistency will improve perfromance significantly.big changes
The biggest change is the architecture. After 6427f98, I find that the architecture I'm thinking is a bit like MVC:
Workspace
project: The mode module. It's responsible to maintain the state ofMSWorkspace
s.Lsp
project: The view module. It routes the requests toHandlers
module and implements the listeners such thatWorkspace
can notify LSP client easily.Handlers
project: The controller module. It handles all requests. Usually it gets some status fromWorkspace
module and convert it to LSP types. And it will notify the status changes toWorkspace
module. For now, most code of this module are just copy & paste from the original code then apply some formatting & refactoring.Common
project: Some common type definitions, type conversions, type extensions, etc.Remove the scope concept. All requests can be handled concurrently after
Workspace
initializes.Remove
csharp.solution
setting andworkspace/didChangeConfiguration
handler. If we wants to support multiple workspace folders, it seems thatcsharp.solution
is not suitable. So I remove the setting and theworkspace/didChangeConfiguration
. And csharp-ls will find and load.sln
/.csproj
from:workspaceFolders
rootUri
rootPath
I think it should fix Cant seem to understand .sln with multiple .csproj #62, No parent project could be resolved #57
Log to a real logger. Change to use FsLibLog instead of sending all logs/information to client.
Register the handlers after initialization if client support dynamic registration. During the initialization, client might send lots of requests to us but we can't handle them before finishing initialization. If client doesn't receive the response in some time, it might cancel the requests and send new ones. Defering the registration of capabilities to avoid the unnecessary requests during initialization.
small changes
Besides the big changes, there are some small big fixes/enhancements in this PR. For example:
workspace/symbols
(https://github.com/tcx4c70/csharp-language-server/blob/621b8a576b946a4787a972fd29cf108799375442/src/Workspace/WorkspaceManager.fs#L281C1-L286C129).`
in the markdown documentation (621b8a5).item.Tags
(9e92165).I think these fixes can be cherry-picked to master branch, but I didn't do that.(These changes have already been merged to master branch)some TODOs need to be done in this PR
workspace/didChangeWatchedFiles
.src/Lsp/bin/Release/net7.0/CSharpLanguageServer.Lsp
. Add a new argument--legacy/-L
to switch between them.some TODOs I'm going to do in further PRs
Handlers
module. I think a very long function is hard to read in a functional language, while there are some functions inHandlers
module that are very long.workspace/semanticTokens/refresh
andworkspace/inlayHint/refresh
) to client at apposite timesrc/CSharpLanguageServer
if there is no big regression.