Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions VSFSharpExtension.sln
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool, HoverOptions>(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<InitializeParams, InitializeResult> with
Expand Down
139 changes: 0 additions & 139 deletions src/FSharp.Compiler.LanguageServer/Common/FSharpRequestContext.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,150 +17,11 @@ open FSharp.Compiler.CodeAnalysis.Workspace

#nowarn "57"

module TokenTypes =

[<return: Struct>]
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<ILspLogger>()
Expand Down
5 changes: 3 additions & 2 deletions src/FSharp.Compiler.LanguageServer/FSharpLanguageServer.fs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
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
open Microsoft.VisualStudio.LanguageServer.Protocol

open StreamJsonRpc
open Nerdbank.Streams
open System.Diagnostics
open FSharp.Compiler.CodeAnalysis.Workspace

#nowarn "57"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ namespace FSharp.Compiler.LanguageServer
type FSharpLanguageServerFeatures =
{
Diagnostics: bool
SemanticHighlighting: bool
}

static member Default =
{
Diagnostics = true
SemanticHighlighting = true
}

type FSharpLanguageServerConfig =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,3 @@ type LanguageFeaturesHandler() =
)
}
|> CancellableTask.start cancellationToken

interface IRequestHandler<SemanticTokensParams, SemanticTokens, FSharpRequestContext> with
[<LanguageServerEndpoint(Methods.TextDocumentSemanticTokensFullName, LanguageServerConstants.DefaultLanguageName)>]
member _.HandleRequestAsync(request: SemanticTokensParams, context: FSharpRequestContext, cancellationToken: CancellationToken) =
cancellableTask {
let! tokens = context.GetSemanticTokensForFile(request.TextDocument.Uri)
return SemanticTokens(Data = tokens)
}
|> CancellableTask.start cancellationToken
9 changes: 8 additions & 1 deletion src/FSharp.Compiler.LanguageServer/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,16 @@ type FSharpDiagnosticExtensions =

[<Extension>]
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<int, _> this.ErrorNumberText
Expand Down
Original file line number Diff line number Diff line change
@@ -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)"
}
7 changes: 6 additions & 1 deletion src/FSharp.VisualStudio.Extension/ExtensionEntrypoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading;
using System;
using Extension = Microsoft.VisualStudio.Extensibility.Extension;
using System.Diagnostics;

/// <summary>
/// Extension entrypoint for the VisualStudio.Extensibility extension.
Expand All @@ -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]",
},
};

/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<NeutralLanguage>en-US</NeutralLanguage>
<CreateVsixContainer>false</CreateVsixContainer>
<AssemblyVSIXSubPath>LSPComponent</AssemblyVSIXSubPath>
<!-- The VisualStudio.Extensibility preview packages are available from the azure-public/vside/msft_consumption feed -->

</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.13.39620" />
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.13.39620" />
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.14.40313" />
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.14.40313" />
<PackageReference Include="Microsoft.VisualStudio.LanguageServer.Protocol.Internal" Version="17.13.9" />
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.Query" Version="17.13.66" />
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="17.13.2" />
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.Query" Version="17.14.143" />
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="$(MicrosoftVisualStudioThreadingVersion)" />
<!--<PackageReference Include="Microsoft.VisualStudio.OpenTelemetry.ClientExtensions" Version="0.1.718-beta" />
<PackageReference Include="Microsoft.VisualStudio.OpenTelemetry.Collector" Version="0.1.718-beta" />
<PackageReference Include="OpenTelemetry" Version="1.10.0" />
Expand Down
14 changes: 1 addition & 13 deletions src/FSharp.VisualStudio.Extension/FSharpExtensionSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,12 @@ internal static class FSharpExtensionSettings
ExtensionChoice,
defaultValue: UNSET)
{
Description = "%Which extension should be used to provide diagnostics%",
};

[VisualStudioContribution]
public static Setting.Enum GetSemanticHighlightingFrom { get; } = new(
"getSemanticHighlightingFrom",
"%FSharpSettings.GetSemanticHighlightingFrom%",
FSharpCategory,
ExtensionChoice,
defaultValue: UNSET)
{
Description = "%Which extension should be used to provide semantic highlighting%",
Description = "%FSharpSettings.GetDiagnosticsFrom.Description%",
};

public static Setting<string>[] AllStringSettings { get; } =
[
GetDiagnosticsFrom,
GetSemanticHighlightingFrom,
];
}
}
Loading
Loading