Skip to content

Commit

Permalink
Merge pull request #155 from razzmatazz/integrate-more-of-rework-from…
Browse files Browse the repository at this point in the history
…-tcx4c70

Integrate refactoring changes (pt. XI)
  • Loading branch information
razzmatazz authored May 16, 2024
2 parents 56a5c63 + ff48508 commit 16e100c
Show file tree
Hide file tree
Showing 16 changed files with 226 additions and 114 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
matrix:
os: [windows-latest, ubuntu-22.04]
dotnet: [8.0.200]
dotnet: [8.0.300]
fail-fast: false

runs-on: ${{ matrix.os }}
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]
* Stop collecting symbols in method body
- By Adam Tao @tcx4c70
* Fix TypeHierarchy registration
- By Adam Tao @tcx4c70
* Fix wrong references number
- By Adam Tao @tcx4c70
* Add progress reporting when loading a solution/project
- By Adam Tao @tcx4c70
* More refactoring and fixes from rework branch:
- By Adam Tao @tcx4c70, from https://github.com/tcx4c70/csharp-language-server/commits/rework/
* Bump Ionide.LanguageServerProtocol to 0.5.1, fix some of the types used for dynamic registration

## [0.13.0] - 2024-05-08 / Baltoji Vokė
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.200",
"version": "8.0.300",
"rollForward": "minor"
}
}
3 changes: 2 additions & 1 deletion src/CSharpLanguageServer/CSharpLanguageServer.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
<Compile Include="Util.fs" />
<Compile Include="Conversions.fs" />
<Compile Include="FormatUtil.fs" />
<Compile Include="Types.fs" />
<Compile Include="ProgressReporter.fs" />
<Compile Include="RoslynHelpers.fs" />
<Compile Include="DocumentationUtil.fs" />
<Compile Include="Types.fs" />
<Compile Include="Lsp/Client.fs" />
<Compile Include="State/ServerState.fs" />
<Compile Include="State/ServerRequestContext.fs" />
Expand Down
1 change: 1 addition & 0 deletions src/CSharpLanguageServer/Handlers/CallHierarchy.fs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ module CallHierarchy =
callers
|> Seq.filter (fun info -> info.IsDirect && isCallableSymbol info.CallingSymbol)
|> Seq.collect toCallHierarchyIncomingCalls
|> Seq.distinct
|> Seq.toArray
|> Some
|> success
Expand Down
32 changes: 14 additions & 18 deletions src/CSharpLanguageServer/Handlers/CodeLens.fs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ type private DocumentSymbolCollectorForCodeLens(semanticModel: SemanticModel) =

override __.VisitEnumMemberDeclaration(node) =
collect node node.Identifier.Span
base.VisitEnumMemberDeclaration(node)

override __.VisitClassDeclaration(node) =
collect node node.Identifier.Span
Expand All @@ -53,35 +52,27 @@ type private DocumentSymbolCollectorForCodeLens(semanticModel: SemanticModel) =

override __.VisitDelegateDeclaration(node) =
collect node node.Identifier.Span
base.VisitDelegateDeclaration(node)

override __.VisitConstructorDeclaration(node) =
collect node node.Identifier.Span
base.VisitConstructorDeclaration(node)

override __.VisitDestructorDeclaration(node) =
collect node node.Identifier.Span
base.VisitDestructorDeclaration(node)

override __.VisitOperatorDeclaration(node) =
collect node node.OperatorToken.Span
base.VisitOperatorDeclaration(node)

override __.VisitIndexerDeclaration(node) =
collect node node.ThisKeyword.Span
base.VisitIndexerDeclaration(node)

override __.VisitConversionOperatorDeclaration(node) =
collect node node.Type.Span
base.VisitConversionOperatorDeclaration(node)

override __.VisitMethodDeclaration(node) =
collect node node.Identifier.Span
base.VisitMethodDeclaration(node)

override __.VisitPropertyDeclaration(node) =
collect node node.Identifier.Span
base.VisitPropertyDeclaration(node)

override __.VisitVariableDeclarator(node) =
let grandparent =
Expand All @@ -91,13 +82,9 @@ type private DocumentSymbolCollectorForCodeLens(semanticModel: SemanticModel) =
// Only show field variables and ignore local variables
if grandparent.IsSome && grandparent.Value :? FieldDeclarationSyntax then
collect node node.Identifier.Span
base.VisitVariableDeclarator(node)
else
base.VisitVariableDeclarator(node)

override __.VisitEventDeclaration(node) =
collect node node.Identifier.Span
base.VisitEventDeclaration(node)

[<RequireQualifiedAccess>]
module CodeLens =
Expand Down Expand Up @@ -144,7 +131,8 @@ module CodeLens =
let! docText = doc.GetTextAsync(ct) |> Async.AwaitTask

let collector = DocumentSymbolCollectorForCodeLens(semanticModel)
collector.Visit(syntaxTree.GetRoot())
let! root = syntaxTree.GetRootAsync(ct) |> Async.AwaitTask
collector.Visit(root)

let makeCodeLens (_symbol: ISymbol, nameSpan: TextSpan) : CodeLens =
let start = nameSpan.Start |> docText.Lines.GetLinePosition
Expand Down Expand Up @@ -176,14 +164,22 @@ module CodeLens =
let! refs = context.FindReferences symbol
// FIXME: refNum is wrong. There are lots of false positive even if we distinct locations by
// (l.Location.SourceTree.FilePath, l.Location.SourceSpan)
let refNum = refs |> Seq.map (fun r -> r.Locations |> Seq.length) |> Seq.fold (+) 0
let refNum =
refs
|> Seq.collect (fun r -> r.Locations)
|> Seq.distinctBy (fun l -> (l.Location.SourceTree.FilePath, l.Location.SourceSpan))
|> Seq.length

let title = sprintf "%d Reference(s)" refNum

let arg: ReferenceParams =
{ TextDocument = { Uri = lensData.DocumentUri }
Position = lensData.Position
Context = { IncludeDeclaration = true } }
let command =
{ Title = title
Command = "csharp.showReferences"
// TODO: we really want to pass some more info to the client
Arguments = None }
Command = "textDocument/references"
Arguments = Some [| arg |> serialize |] }

return { p with Command = Some command } |> success
}
4 changes: 3 additions & 1 deletion src/CSharpLanguageServer/Handlers/DocumentSymbol.fs
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,9 @@ module DocumentSymbol =

let collector = DocumentSymbolCollector(docText, semanticModel)
collector.Init(doc.Name)
collector.Visit(syntaxTree.GetRoot())

let! root = syntaxTree.GetRootAsync(ct) |> Async.AwaitTask
collector.Visit(root)

return collector.GetDocumentSymbols(canEmitDocSymbolHierarchy)
|> U2.Second
Expand Down
8 changes: 6 additions & 2 deletions src/CSharpLanguageServer/Handlers/Initialization.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace CSharpLanguageServer.Handlers
open System
open System.IO
open System.Reflection
open System.Diagnostics

open Microsoft.Build.Locator
open Ionide.LanguageServerProtocol
Expand Down Expand Up @@ -87,10 +88,13 @@ module Initialization =
// setup timer so actors get period ticks
setupTimer()

// TODO: Report server info to client (name, version)
let initializeResult =
{ InitializeResult.Default with
Capabilities = serverCapabilities }
Capabilities = serverCapabilities
ServerInfo =
Some
{ Name = Process.GetCurrentProcess().ProcessName
Version = Some (Assembly.GetExecutingAssembly().GetName().Version.ToString()) }}

return initializeResult |> LspResult.success
}
Expand Down
2 changes: 1 addition & 1 deletion src/CSharpLanguageServer/Handlers/References.fs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ module References =
| None -> return None |> success
| Some symbol ->
let! refs = context.FindReferences symbol
// FIXME: refs is wrong. There are lots of false positive even if we add Seq.distinct before Seq.toArray
return
refs
|> Seq.collect (fun r -> r.Locations)
|> Seq.map (fun rl -> Location.fromRoslynLocation rl.Location)
|> Seq.distinct
|> Seq.toArray
|> Some
|> success
Expand Down
2 changes: 2 additions & 0 deletions src/CSharpLanguageServer/Handlers/Rename.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.CSharp.Syntax
open Microsoft.CodeAnalysis.FindSymbols
open Microsoft.CodeAnalysis.Rename
open FSharpPlus
open Ionide.LanguageServerProtocol.Server
open Ionide.LanguageServerProtocol.Types
open Ionide.LanguageServerProtocol.Types.LspResult
Expand Down Expand Up @@ -56,6 +57,7 @@ module Rename =
|> Seq.collect (fun projectChange -> projectChange.GetChangedDocuments())
|> Seq.map (getEdits originalSolution updatedSolution)
|> Async.Parallel
|> map (Seq.distinct >> Array.ofSeq)

let private dynamicRegistration (clientCapabilities: ClientCapabilities option) =
clientCapabilities
Expand Down
4 changes: 2 additions & 2 deletions src/CSharpLanguageServer/Handlers/TypeHierarchy.fs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ module TypeHierarchy =

let registration (clientCapabilities: ClientCapabilities option) : Registration option =
match dynamicRegistration clientCapabilities with
| true -> None
| false ->
| false -> None
| true ->
let registerOptions: TypeHierarchyRegistrationOptions =
{ DocumentSelector = Some defaultDocumentSelector }
Some
Expand Down
11 changes: 11 additions & 0 deletions src/CSharpLanguageServer/Lsp/Client.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ namespace CSharpLanguageServer.Lsp

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

open CSharpLanguageServer.Types

type CSharpLspClient(sendServerNotification: ClientNotificationSender, sendServerRequest: ClientRequestSender) =
inherit LspClient()
Expand Down Expand Up @@ -40,3 +43,11 @@ type CSharpLspClient(sendServerNotification: ClientNotificationSender, sendServe

override __.TextDocumentPublishDiagnostics(p) =
sendServerNotification "textDocument/publishDiagnostics" (box p) |> Async.Ignore

override __.WorkDoneProgressCreate(token) =
let param: WorkDoneProgressCreateParams = { token = token }
sendServerRequest.Send "window/workDoneProgress/create" (box param)

override __.Progress(token, value) =
let param: ProgressParams<_> = { token = token; value = value }
sendServerNotification "$/progress" (box param) |> Async.Ignore
47 changes: 47 additions & 0 deletions src/CSharpLanguageServer/ProgressReporter.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace CSharpLanguageServer

open System
open Ionide.LanguageServerProtocol
open Ionide.LanguageServerProtocol.Types
open Ionide.LanguageServerProtocol.Client

type ProgressReporter(client: ILspClient) =
let mutable canReport = false

let mutable endSent = false

member val Token = ProgressToken.Second(Guid.NewGuid().ToString())

member this.Begin(title, ?cancellable, ?message, ?percentage) = async {
match! client.WorkDoneProgressCreate this.Token with
| Error _ ->
canReport <- false
| Ok() ->
canReport <- true
let param = WorkDoneProgressBegin.Create(
title = title,
?cancellable = cancellable,
?message = message,
?percentage = percentage
)
do! client.Progress(this.Token, param)
}

member this.Report(?cancellable, ?message, ?percentage) = async {
if canReport && not endSent then
let param = WorkDoneProgressReport.Create(
?cancellable = cancellable,
?message = message,
?percentage = percentage
)
do! client.Progress(this.Token, param)
}

member this.End(?message) = async {
if canReport && not endSent then
endSent <- true
let param = WorkDoneProgressEnd.Create(
?message = message
)
do! client.Progress(this.Token, param)
}
Loading

0 comments on commit 16e100c

Please sign in to comment.