Skip to content

Commit

Permalink
Add skeleton CSharpLanguageServer.Lsp.Server.CSharpLspServer implemen…
Browse files Browse the repository at this point in the history
…tation
  • Loading branch information
razzmatazz committed Feb 17, 2024
1 parent 5ca02fc commit ae54599
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 21 deletions.
1 change: 1 addition & 0 deletions src/CSharpLanguageServer/CSharpLanguageServer.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="FSharpPlus" />
<PackageReference Include="Argu" />
<PackageReference Include="Castle.Core" />
<PackageReference Include="ICSharpCode.Decompiler" />
Expand Down
189 changes: 183 additions & 6 deletions src/CSharpLanguageServer/Lsp/Server.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,64 @@ namespace CSharpLanguageServer.Lsp

open System
open System.Diagnostics
open System.Reflection

open Ionide.LanguageServerProtocol.Server
open Ionide.LanguageServerProtocol
open Ionide.LanguageServerProtocol.Types
open FSharpPlus

open CSharpLanguageServer.Types
open CSharpLanguageServer.Handlers
open CSharpLanguageServer.Logging

type CSharpLspServer(lspClient: ICSharpLspClient) =
module LspUtils =
/// Return the JSON-RPC "not implemented" error
let notImplemented<'t> = async.Return LspResult.notImplemented<'t>

/// Do nothing and ignore the notification
let ignoreNotification: Async<unit> = async.Return(())


open LspUtils

type CSharpLspServer() =

let logger = LogProvider.getLoggerByName "LSP"

let mutable workspaceFolders: WorkspaceFolder list = []

module Server =
let logger = LogProvider.getLoggerByName "LSP"
interface ICSharpLspServer with
override __.Dispose() = ()

override __.Initialize(p) = async {
let serverName = "csharp-ls"
logger.info (
Log.setMessage "initializing, {name} version {version}"
>> Log.addContext "name" serverName
>> Log.addContext "version" (Assembly.GetExecutingAssembly().GetName().Version)
)
logger.info (
Log.setMessage "{name} is released under MIT license and is not affiliated with Microsoft Corp.; see https://github.com/razzmatazz/csharp-language-server"
>> Log.addContext "name" serverName
)

//lspClient.Capabilities <- p.Capabilities
let lspClient = p

(*
workspaceFolders <-
map Array.toList p.WorkspaceFolders
// Can't simplify it to (:: []) like Haskell :(
|> Option.orElse (map (Uri.toWorkspaceFolder >> (flip List.cons [])) p.RootUri)
|> Option.orElse (map (Path.toWorkspaceFolder >> (flip List.cons [])) p.RootPath)
|> Option.defaultValue [Path.toWorkspaceFolder (Directory.GetCurrentDirectory())]
*)

let getServerCapabilities (lspClient: InitializeParams) =
let serverCapabilities =
// TODO: Monitor the lsp client process (via processId in InitializeParams) and shutdown if the
// lsp client dies.

let serverCapabilities =
{ ServerCapabilities.Default with
TextDocumentSync = TextDocumentSync.provider lspClient.Capabilities
CompletionProvider = Completion.provider lspClient.Capabilities
Expand Down Expand Up @@ -55,7 +93,146 @@ module Server =
// DiagnosticProvider = Diagnostic.provider lspClient.Capabilities
WorkspaceSymbolProvider = WorkspaceSymbol.provider lspClient.Capabilities }

serverCapabilities
// TODO: Report server info to client (name, version)
let initializeResult =
{ InitializeResult.Default with
Capabilities = serverCapabilities }

return initializeResult |> LspResult.success
}

override __.Initialized(p) = ignoreNotification

override __.Shutdown() = ignoreNotification

override __.Exit() = ignoreNotification

override this.TextDocumentHover(p) = notImplemented

override this.TextDocumentDidOpen(p) = ignoreNotification

override this.TextDocumentDidChange(p) = ignoreNotification

override this.TextDocumentDidClose(p) = ignoreNotification

override this.TextDocumentWillSave(p) = ignoreNotification

override this.TextDocumentWillSaveWaitUntil(p) = notImplemented

override this.TextDocumentDidSave(p) = ignoreNotification

override this.TextDocumentCompletion(p) = notImplemented

override this.CompletionItemResolve(p) = notImplemented

override this.TextDocumentPrepareRename(p) = notImplemented

override this.TextDocumentRename(p) = notImplemented

override this.TextDocumentDefinition(p) = notImplemented

override this.TextDocumentReferences(p) = notImplemented

override this.TextDocumentDocumentHighlight(p) = notImplemented

override this.TextDocumentDocumentLink(p) = notImplemented

override this.DocumentLinkResolve(p) = notImplemented

override this.TextDocumentTypeDefinition(p) = notImplemented

override this.TextDocumentImplementation(p) = notImplemented

override this.TextDocumentCodeAction(p) = notImplemented

override this.CodeActionResolve(p) = notImplemented

override this.TextDocumentCodeLens(p) = notImplemented

override this.CodeLensResolve(p) = notImplemented

override this.TextDocumentSignatureHelp(p) = notImplemented

override this.TextDocumentDocumentColor(p) = notImplemented

override this.TextDocumentColorPresentation(p) = notImplemented

override this.TextDocumentFormatting(p) = notImplemented

override this.TextDocumentRangeFormatting(p) = notImplemented

override this.TextDocumentOnTypeFormatting(p) = notImplemented

override this.TextDocumentDocumentSymbol(p) = notImplemented

override this.WorkspaceDidChangeWatchedFiles(p) = ignoreNotification

override this.WorkspaceDidChangeWorkspaceFolders(p) = ignoreNotification

override this.WorkspaceDidChangeConfiguration(p) = ignoreNotification

override this.WorkspaceWillCreateFiles(p) = notImplemented

override this.WorkspaceDidCreateFiles(p) = ignoreNotification

override this.WorkspaceWillRenameFiles(p) = notImplemented

override this.WorkspaceDidRenameFiles(p) = ignoreNotification

override this.WorkspaceWillDeleteFiles(p) = notImplemented

override this.WorkspaceDidDeleteFiles(p) = ignoreNotification

override this.WorkspaceSymbol(p) = notImplemented

override this.WorkspaceExecuteCommand(p) = notImplemented

override this.TextDocumentFoldingRange(p) = notImplemented

override this.TextDocumentSelectionRange(p) = notImplemented

override this.TextDocumentSemanticTokensFull(p) = notImplemented

override this.TextDocumentSemanticTokensFullDelta(p) = notImplemented

override this.TextDocumentSemanticTokensRange(p) = notImplemented

override this.TextDocumentInlayHint(p) = notImplemented

override this.InlayHintResolve(p) = notImplemented

override __.WorkDoneProgressCancel(p) = ignoreNotification

override this.TextDocumentInlineValue(p) = notImplemented

override this.TextDocumentPrepareCallHierarchy(p) = notImplemented

override this.CallHierarchyIncomingCalls(p) = notImplemented

override this.CallHierarchyOutgoingCalls(p) = notImplemented

override this.TextDocumentPrepareTypeHierarchy(p) = notImplemented

override this.TypeHierarchySupertypes(p) = notImplemented

override this.TypeHierarchySubtypes(p) = notImplemented

override this.CSharpMetadata(p) = notImplemented

override this.TextDocumentDeclaration(p) = notImplemented

override this.WorkspaceDiagnostic(p) = notImplemented

override this.WorkspaceSymbolResolve(p) = notImplemented

override this.TextDocumentDiagnostic(p) = notImplemented

override this.TextDocumentLinkedEditingRange(p) = notImplemented

override this.TextDocumentMoniker(p) = notImplemented

module Server =
let logger = LogProvider.getLoggerByName "LSP"

let startCore setupServerHandlers options =
use input = Console.OpenStandardInput()
Expand Down
20 changes: 5 additions & 15 deletions src/CSharpLanguageServer/Server.fs
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,10 @@ let setupServerHandlers settings (lspClient: LspClient) =
logger.info (Log.setMessage message)
}

let handleInitialize (scope: ServerRequestScope) (p: InitializeParams): AsyncLspResult<InitializeResult> = async {
do! infoMessage (sprintf "initializing, csharp-ls version %s; cwd: \"%s\""
(typeof<CSharpLspClient>.Assembly.GetName().Version |> string)
(Directory.GetCurrentDirectory()))

do! infoMessage "csharp-ls is released under MIT license and is not affiliated with Microsoft Corp.; see https://github.com/razzmatazz/csharp-language-server"

// do! infoMessage (sprintf "`dotnet --version`: %s"
// (getDotnetCliVersion ()))
let lspServer: CSharpLanguageServer.Types.ICSharpLspServer =
CSharpLanguageServer.Lsp.CSharpLspServer()

Check warning on line 121 in src/CSharpLanguageServer/Server.fs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 8.0.200)

It is recommended that objects supporting the IDisposable interface are created using the syntax 'new Type(args)', rather than 'Type(args)' or 'Type' as a function value representing the constructor, to indicate that resources may be owned by the generated value

Check warning on line 121 in src/CSharpLanguageServer/Server.fs

View workflow job for this annotation

GitHub Actions / build (ubuntu-22.04, 8.0.200)

It is recommended that objects supporting the IDisposable interface are created using the syntax 'new Type(args)', rather than 'Type(args)' or 'Type' as a function value representing the constructor, to indicate that resources may be owned by the generated value

let handleInitialize (scope: ServerRequestScope) (p: InitializeParams): AsyncLspResult<InitializeResult> = async {
let vsInstanceQueryOpt = VisualStudioInstanceQueryOptions.Default
let vsInstanceList = MSBuildLocator.QueryVisualStudioInstances(vsInstanceQueryOpt)
if Seq.isEmpty vsInstanceList then
Expand Down Expand Up @@ -161,12 +155,8 @@ let setupServerHandlers settings (lspClient: LspClient) =
// setup timer so actors get period ticks
setupTimer ()

let initializeResult = {
InitializeResult.Default with
Capabilities = CSharpLanguageServer.Lsp.Server.getServerCapabilities p
}

return initializeResult |> success
let! initializeResult = lspServer.Initialize(p)
return initializeResult
}

let handleInitialized (scope: ServerRequestScope) (_p: InitializedParams): Async<LspResult<unit>> =
Expand Down

0 comments on commit ae54599

Please sign in to comment.