diff --git a/VSFSharpExtension.sln b/VSFSharpExtension.sln index a4e19ff2fae..126e0cf5476 100644 --- a/VSFSharpExtension.sln +++ b/VSFSharpExtension.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.10806.39 main MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B4A1E626-4A48-4977-B291-219882DB3413}" EndProject @@ -17,6 +17,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager.Nu EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Editor", "vsintegration\src\FSharp.Editor\FSharp.Editor.fsproj", "{3D4A95CB-1563-CD9A-3949-FE01922CD5BD}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.LanguageServer.Tests", "tests\FSharp.Compiler.LanguageServer.Tests\FSharp.Compiler.LanguageServer.Tests.fsproj", "{ECB3A7E8-824B-6769-6A01-754555E89E27}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -61,6 +63,12 @@ Global {3D4A95CB-1563-CD9A-3949-FE01922CD5BD}.Proto|Any CPU.Build.0 = Debug|Any CPU {3D4A95CB-1563-CD9A-3949-FE01922CD5BD}.Release|Any CPU.ActiveCfg = Release|Any CPU {3D4A95CB-1563-CD9A-3949-FE01922CD5BD}.Release|Any CPU.Build.0 = Release|Any CPU + {ECB3A7E8-824B-6769-6A01-754555E89E27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ECB3A7E8-824B-6769-6A01-754555E89E27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ECB3A7E8-824B-6769-6A01-754555E89E27}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {ECB3A7E8-824B-6769-6A01-754555E89E27}.Proto|Any CPU.Build.0 = Debug|Any CPU + {ECB3A7E8-824B-6769-6A01-754555E89E27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ECB3A7E8-824B-6769-6A01-754555E89E27}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/FSharp.Compiler.LanguageServer/Common/CapabilitiesManager.fs b/src/FSharp.Compiler.LanguageServer/Common/CapabilitiesManager.fs index 556a1d96edc..d85debebb1b 100644 --- a/src/FSharp.Compiler.LanguageServer/Common/CapabilitiesManager.fs +++ b/src/FSharp.Compiler.LanguageServer/Common/CapabilitiesManager.fs @@ -31,21 +31,9 @@ type CapabilitiesManager(config: FSharpLanguageServerConfig, scOverrides: IServe InterFileDependencies = true, Identifier = "potato", WorkspaceDiagnostics = true - )), + )) //CompletionProvider = CompletionOptions(TriggerCharacters = [| "."; " " |], ResolveProvider = true, WorkDoneProgress = true), //HoverProvider = SumType(HoverOptions(WorkDoneProgress = true)) - SemanticTokensOptions = - addIf - config.EnabledFeatures.SemanticHighlighting - - (SemanticTokensOptions( - Legend = - SemanticTokensLegend( - TokenTypes = (SemanticTokenTypes.AllTypes |> Seq.toArray), // XXX should be extended - TokenModifiers = (SemanticTokenModifiers.AllModifiers |> Seq.toArray) - ), - Range = false - )) ) interface IInitializeManager with diff --git a/src/FSharp.Compiler.LanguageServer/Common/FSharpRequestContext.fs b/src/FSharp.Compiler.LanguageServer/Common/FSharpRequestContext.fs index fd096d3e582..2ca2d10ddc3 100644 --- a/src/FSharp.Compiler.LanguageServer/Common/FSharpRequestContext.fs +++ b/src/FSharp.Compiler.LanguageServer/Common/FSharpRequestContext.fs @@ -17,150 +17,11 @@ open FSharp.Compiler.CodeAnalysis.Workspace #nowarn "57" -module TokenTypes = - - [] - let (|LexicalClassification|_|) (tok: FSharpToken) = - if tok.IsKeyword then - ValueSome SemanticTokenTypes.Keyword - elif tok.IsNumericLiteral then - ValueSome SemanticTokenTypes.Number - elif tok.IsCommentTrivia then - ValueSome SemanticTokenTypes.Comment - elif tok.IsStringLiteral then - ValueSome SemanticTokenTypes.String - else - ValueNone - - // Tokenizes the source code and returns a list of token ranges and their SemanticTokenTypes - let GetSyntacticTokenTypes (source: FSharp.Compiler.Text.ISourceText) (fileName: string) = - let mutable tokRangesAndTypes = [] - - let tokenCallback = - fun (tok: FSharpToken) -> - match tok with - | LexicalClassification tokType -> tokRangesAndTypes <- (tok.Range, tokType) :: tokRangesAndTypes - | _ -> () - - FSharpLexer.Tokenize( - source, - tokenCallback, - flags = - (FSharpLexerFlags.Default - &&& ~~~FSharpLexerFlags.Compiling - &&& ~~~FSharpLexerFlags.UseLexFilter), - filePath = fileName - ) - - tokRangesAndTypes - - let FSharpTokenTypeToLSP (fst: SemanticClassificationType) = - // XXX kinda arbitrary mapping - match fst with - | SemanticClassificationType.ReferenceType -> SemanticTokenTypes.Class - | SemanticClassificationType.ValueType -> SemanticTokenTypes.Struct - | SemanticClassificationType.UnionCase -> SemanticTokenTypes.Enum - | SemanticClassificationType.UnionCaseField -> SemanticTokenTypes.EnumMember - | SemanticClassificationType.Function -> SemanticTokenTypes.Function - | SemanticClassificationType.Property -> SemanticTokenTypes.Property - | SemanticClassificationType.Module -> SemanticTokenTypes.Type - | SemanticClassificationType.Namespace -> SemanticTokenTypes.Namespace - | SemanticClassificationType.Interface -> SemanticTokenTypes.Interface - | SemanticClassificationType.TypeArgument -> SemanticTokenTypes.TypeParameter - | SemanticClassificationType.Operator -> SemanticTokenTypes.Operator - | SemanticClassificationType.Method -> SemanticTokenTypes.Method - | SemanticClassificationType.ExtensionMethod -> SemanticTokenTypes.Method - | SemanticClassificationType.Field -> SemanticTokenTypes.Property - | SemanticClassificationType.Event -> SemanticTokenTypes.Event - | SemanticClassificationType.Delegate -> SemanticTokenTypes.Function - | SemanticClassificationType.NamedArgument -> SemanticTokenTypes.Parameter - | SemanticClassificationType.LocalValue -> SemanticTokenTypes.Variable - | SemanticClassificationType.Plaintext -> SemanticTokenTypes.String - | SemanticClassificationType.Type -> SemanticTokenTypes.Type - | SemanticClassificationType.Printf -> SemanticTokenTypes.Keyword - | _ -> SemanticTokenTypes.Comment - - let toIndex (x: string) = - SemanticTokenTypes.AllTypes |> Seq.findIndex (fun y -> y = x) - type FSharpRequestContext(lspServices: ILspServices, logger: ILspLogger, workspace: FSharpWorkspace) = member _.LspServices = lspServices member _.Logger = logger member _.Workspace = workspace - member this.GetSemanticTokensForFile(file) = - task { - let! scv = this.Workspace.Query.GetSemanticClassification file - let! source = this.Workspace.Query.GetSource file - - match scv, source with - | Some view, Some source -> - - let tokens = ResizeArray() - - view.ForEach(fun item -> - let range = item.Range - let tokenType = item.Type |> TokenTypes.FSharpTokenTypeToLSP |> TokenTypes.toIndex - tokens.Add(range, tokenType)) - - let syntacticClassifications = - TokenTypes.GetSyntacticTokenTypes source file.LocalPath - |> Seq.map (fun (r, t) -> (r, TokenTypes.toIndex t)) - - let allTokens = Seq.append tokens syntacticClassifications - - let lspFormatTokens = - allTokens - |> Seq.map (fun (r, tokType) -> - let length = r.EndColumn - r.StartColumn // XXX Does not deal with multiline tokens? - - {| - startLine = r.StartLine - 1 - startCol = r.StartColumn - length = length - tokType = tokType - tokMods = 0 - |}) - //(startLine, startCol, length, tokType, tokMods)) - |> Seq.sortWith (fun x1 x2 -> - let c = x1.startLine.CompareTo(x2.startLine) - if c <> 0 then c else x1.startCol.CompareTo(x2.startCol)) - - let tokensRelative = - lspFormatTokens - |> Seq.append - [| - {| - startLine = 0 - startCol = 0 - length = 0 - tokType = 0 - tokMods = 0 - |} - |] - |> Seq.pairwise - |> Seq.map (fun (prev, this) -> - {| - startLine = this.startLine - prev.startLine - startCol = - (if prev.startLine = this.startLine then - this.startCol - prev.startCol - else - this.startCol) - length = this.length - tokType = this.tokType - tokMods = this.tokMods - |}) - - return - tokensRelative - |> Seq.map (fun tok -> [| tok.startLine; tok.startCol; tok.length; tok.tokType; tok.tokMods |]) - |> Seq.concat - |> Seq.toArray - - | _ -> return [||] - } - type ContextHolder(workspace, lspServices: ILspServices) = let logger = lspServices.GetRequiredService() diff --git a/src/FSharp.Compiler.LanguageServer/FSharpLanguageServer.fs b/src/FSharp.Compiler.LanguageServer/FSharpLanguageServer.fs index 3aadb29b2b7..459b8530dc0 100644 --- a/src/FSharp.Compiler.LanguageServer/FSharpLanguageServer.fs +++ b/src/FSharp.Compiler.LanguageServer/FSharpLanguageServer.fs @@ -1,10 +1,12 @@ namespace FSharp.Compiler.LanguageServer +open System +open System.Diagnostics open System.Runtime.CompilerServices + open FSharp.Compiler.LanguageServer.Common open FSharp.Compiler.LanguageServer.Handlers -open System open Microsoft.CommonLanguageServerProtocol.Framework.Handlers open Microsoft.CommonLanguageServerProtocol.Framework open Microsoft.Extensions.DependencyInjection @@ -12,7 +14,6 @@ open Microsoft.VisualStudio.LanguageServer.Protocol open StreamJsonRpc open Nerdbank.Streams -open System.Diagnostics open FSharp.Compiler.CodeAnalysis.Workspace #nowarn "57" diff --git a/src/FSharp.Compiler.LanguageServer/FSharpLanguageServerConfig.fs b/src/FSharp.Compiler.LanguageServer/FSharpLanguageServerConfig.fs index a1acd2b88da..4e599902aa0 100644 --- a/src/FSharp.Compiler.LanguageServer/FSharpLanguageServerConfig.fs +++ b/src/FSharp.Compiler.LanguageServer/FSharpLanguageServerConfig.fs @@ -3,13 +3,11 @@ namespace FSharp.Compiler.LanguageServer type FSharpLanguageServerFeatures = { Diagnostics: bool - SemanticHighlighting: bool } static member Default = { Diagnostics = true - SemanticHighlighting = true } type FSharpLanguageServerConfig = diff --git a/src/FSharp.Compiler.LanguageServer/Handlers/LanguageFeaturesHandler.fs b/src/FSharp.Compiler.LanguageServer/Handlers/LanguageFeaturesHandler.fs index 474758924d0..48f1fa38351 100644 --- a/src/FSharp.Compiler.LanguageServer/Handlers/LanguageFeaturesHandler.fs +++ b/src/FSharp.Compiler.LanguageServer/Handlers/LanguageFeaturesHandler.fs @@ -48,12 +48,3 @@ type LanguageFeaturesHandler() = ) } |> CancellableTask.start cancellationToken - - interface IRequestHandler with - [] - member _.HandleRequestAsync(request: SemanticTokensParams, context: FSharpRequestContext, cancellationToken: CancellationToken) = - cancellableTask { - let! tokens = context.GetSemanticTokensForFile(request.TextDocument.Uri) - return SemanticTokens(Data = tokens) - } - |> CancellableTask.start cancellationToken diff --git a/src/FSharp.Compiler.LanguageServer/Utils.fs b/src/FSharp.Compiler.LanguageServer/Utils.fs index c5283b6fb76..031c46e6bb6 100644 --- a/src/FSharp.Compiler.LanguageServer/Utils.fs +++ b/src/FSharp.Compiler.LanguageServer/Utils.fs @@ -47,9 +47,16 @@ type FSharpDiagnosticExtensions = [] static member ToLspDiagnostic(this: FSharpDiagnostic) = + let severity = + match this.Severity with + | FSharpDiagnosticSeverity.Error -> DiagnosticSeverity.Error + | FSharpDiagnosticSeverity.Warning -> DiagnosticSeverity.Warning + | FSharpDiagnosticSeverity.Info -> DiagnosticSeverity.Information + // TODO consider not emitting this diagnostic if severity is Hidden + | FSharpDiagnosticSeverity.Hidden -> DiagnosticSeverity.Hint Diagnostic( Range = this.Range.ToLspRange(), - Severity = DiagnosticSeverity.Error, + Severity = severity, Message = $"LSP: {this.Message}", //Source = "Intellisense", Code = SumType this.ErrorNumberText diff --git a/src/FSharp.VisualStudio.Extension/.vsextension/string-resources.json b/src/FSharp.VisualStudio.Extension/.vsextension/string-resources.json index 5f1633293d7..5e669b53287 100644 --- a/src/FSharp.VisualStudio.Extension/.vsextension/string-resources.json +++ b/src/FSharp.VisualStudio.Extension/.vsextension/string-resources.json @@ -1,4 +1,10 @@ { - "FSharpLspExtension.FSharpLanguageServerProvider.DisplayName": "FSharp Analyzer LSP server" - + "FSharpLspExtension.FSharpLanguageServerProvider.DisplayName": "FSharp Analyzer LSP server", + "F#": "F# LSP", + "FSharpSettings.Old": "Old extension (devenv process)", + "FSharpSettings.Both": "Both extensions", + "FSharpSettings.LSP": "LSP (separate process)", + "FSharpSettings.Unset": "Default", + "FSharpSettings.GetDiagnosticsFrom": "Get diagnostics from", + "FSharpSettings.GetDiagnosticsFrom.Description": "Which extension provides diagnostics (restart required)" } diff --git a/src/FSharp.VisualStudio.Extension/ExtensionEntrypoint.cs b/src/FSharp.VisualStudio.Extension/ExtensionEntrypoint.cs index ba47320b925..6611bace471 100644 --- a/src/FSharp.VisualStudio.Extension/ExtensionEntrypoint.cs +++ b/src/FSharp.VisualStudio.Extension/ExtensionEntrypoint.cs @@ -5,6 +5,7 @@ using System.Threading; using System; using Extension = Microsoft.VisualStudio.Extensibility.Extension; +using System.Diagnostics; /// /// Extension entrypoint for the VisualStudio.Extensibility extension. @@ -21,7 +22,11 @@ internal class ExtensionEntrypoint : Extension version: this.ExtensionAssemblyVersion, publisherName: "Publisher name", displayName: "FSharp.VisualStudio.Extension", - description: "Extension description"), + description: "Extension description") + { + // TODO: Probably should be replaced by a range of versions + InstallationTargetVersion = "[17.14, 18.0]", + }, }; /// diff --git a/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj b/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj index fae776deb73..386d3104091 100644 --- a/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj +++ b/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj @@ -4,16 +4,18 @@ enable 12 en-US + false + LSPComponent - - + + - - + +