Skip to content
Merged
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
7 changes: 7 additions & 0 deletions FsAutoComplete.sln
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsAutoComplete.Logging", "s
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "OptionAnalyzer", "test\OptionAnalyzer\OptionAnalyzer.fsproj", "{14C55B44-2063-4891-98BE-8184CAB1BE87}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsAutoComplete.DependencyManager.Dummy", "test\FsAutoComplete.DependencyManager.Dummy\FsAutoComplete.DependencyManager.Dummy.fsproj", "{C58701B0-D8E3-4B68-A7DE-8524C95F86C0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -80,6 +82,10 @@ Global
{14C55B44-2063-4891-98BE-8184CAB1BE87}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14C55B44-2063-4891-98BE-8184CAB1BE87}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14C55B44-2063-4891-98BE-8184CAB1BE87}.Release|Any CPU.Build.0 = Release|Any CPU
{C58701B0-D8E3-4B68-A7DE-8524C95F86C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C58701B0-D8E3-4B68-A7DE-8524C95F86C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C58701B0-D8E3-4B68-A7DE-8524C95F86C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C58701B0-D8E3-4B68-A7DE-8524C95F86C0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -88,6 +94,7 @@ Global
{6FE2E08A-9F3F-4C7C-B190-77C46AE147D7} = {443E0B8D-9AD0-436E-A331-E8CC12965F07}
{38C1F619-3E1E-4784-9833-E8A2AA95CDAE} = {BA56455D-4AEA-45FC-A569-027A68A76BA6}
{14C55B44-2063-4891-98BE-8184CAB1BE87} = {443E0B8D-9AD0-436E-A331-E8CC12965F07}
{C58701B0-D8E3-4B68-A7DE-8524C95F86C0} = {443E0B8D-9AD0-436E-A331-E8CC12965F07}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1C4EE83B-632A-4929-8C96-38F14254229E}
Expand Down
1 change: 1 addition & 0 deletions src/FsAutoComplete.Core/CompilerServiceInterface.fs
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,7 @@ type FSharpCompilerServiceChecker(backgroundServiceEnabled) =
member __.GetDotnetRoot () = sdkRoot

member __.SetFSIAdditionalArguments args =
//TODO: UX - if preview-required features are set, then auto-add langversion:preview for the user.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to go ahead and tackle this now?

if fsiAdditionalArguments = args
then ()
else
Expand Down
3 changes: 2 additions & 1 deletion src/FsAutoComplete/FsAutoComplete.Lsp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ type FsharpLspServer(commands: Commands, lspClient: FSharpLspClient) =

/// centralize any state changes when the config is updated here
let updateConfig (newConfig: FSharpConfig) =
let toCompilerToolArgument (path: string) = sprintf "--compilertool:%s" path
config <- newConfig
commands.SetDotnetSDKRoot config.DotNetRoot
commands.SetFSIAdditionalArguments config.FSIExtraParameters
commands.SetFSIAdditionalArguments [| yield! config.FSICompilerToolLocations |> Array.map toCompilerToolArgument; yield! config.FSIExtraParameters |]
commands.SetLinterConfigRelativePath config.LinterConfig
#if ANALYZER_SUPPORT
match config.AnalyzersPath with
Expand Down
7 changes: 6 additions & 1 deletion src/FsAutoComplete/LspHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ type FSharpConfigDto = {
UseSdkScripts: bool option
DotNetRoot: string option
FSIExtraParameters: string [] option
FSICompilerToolLocations: string [] option
TooltipMode : string option
}

Expand Down Expand Up @@ -466,6 +467,7 @@ type FSharpConfig = {
UseSdkScripts: bool
DotNetRoot: string
FSIExtraParameters: string []
FSICompilerToolLocations: string []
TooltipMode : string
}
with
Expand Down Expand Up @@ -500,6 +502,7 @@ with
UseSdkScripts = false
DotNetRoot = Environment.dotnetSDKRoot.Value
FSIExtraParameters = [||]
FSICompilerToolLocations = [||]
TooltipMode = "full"
}

Expand Down Expand Up @@ -537,10 +540,11 @@ with
|> Option.bind (fun s -> if String.IsNullOrEmpty s then None else Some s)
|> Option.defaultValue Environment.dotnetSDKRoot.Value
FSIExtraParameters = defaultArg dto.FSIExtraParameters FSharpConfig.Default.FSIExtraParameters
FSICompilerToolLocations = defaultArg dto.FSICompilerToolLocations FSharpConfig.Default.FSICompilerToolLocations
TooltipMode = defaultArg dto.TooltipMode "full"
}

/// called when a configuration change takes effect, so empty members here should revert options
/// called when a configuration change takes effect, so None-valued members here should revert options
/// back to their defaults
member x.AddDto(dto: FSharpConfigDto) =
{
Expand Down Expand Up @@ -576,6 +580,7 @@ with
|> Option.bind (fun s -> if String.IsNullOrEmpty s then None else Some s)
|> Option.defaultValue FSharpConfig.Default.DotNetRoot
FSIExtraParameters = defaultArg dto.FSIExtraParameters FSharpConfig.Default.FSIExtraParameters
FSICompilerToolLocations = defaultArg dto.FSICompilerToolLocations FSharpConfig.Default.FSICompilerToolLocations
TooltipMode = defaultArg dto.TooltipMode x.TooltipMode
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="Library.fs" />
</ItemGroup>

</Project>
55 changes: 55 additions & 0 deletions test/FsAutoComplete.DependencyManager.Dummy/Library.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module FsAutoComplete.DependencyManager.Dummy

open System

/// A marker attribute to tell FCS that this assembly contains a Dependency Manager, or
/// that a class with the attribute is a DependencyManager
[<AttributeUsage(AttributeTargets.Assembly ||| AttributeTargets.Class , AllowMultiple = false)>]
type DependencyManagerAttribute() =
inherit Attribute()

[<assembly: DependencyManager()>]
do ()

/// returned structure from the ResolveDependencies method call.
type ResolveDependenciesResult (success: bool, stdOut: string array, stdError: string array, resolutions: string seq, sourceFiles: string seq, roots: string seq) =

/// Succeded?
member __.Success = success

/// The resolution output log
member __.StdOut = stdOut

/// The resolution error log (* process stderror *)
member __.StdError = stdError

/// The resolution paths (will be treated as #r options)
member __.Resolutions = resolutions

/// The source code file paths (will be treated as #load options)
member __.SourceFiles = sourceFiles

/// The roots to package directories (will be treated like #I options)
member __.Roots = roots

type ScriptExtension = string
type HashRLines = string seq
type TFM = string

[<DependencyManager>]
/// the type _must_ take an optional output directory
type DummyDependencyManager(outputDir: string option) =

/// Name of the dependency manager
member val Name = "Dummy Dependency Manager" with get

/// Key that identifies the types of dependencies that this DependencyManager operates on
member val Key = "dummy" with get

/// Resolve the dependencies, for the given set of arguments, go find the .dll references, scripts and additional include values.
member _.ResolveDependencies(_scriptExt: ScriptExtension, _includeLines: HashRLines, _tfm: TFM): obj =
// generally, here we'd parse the includeLines to determine what to do,
// package those results into a `ResolveDepndenciesResult`,
// and return it boxed as obj.
// but here we will return a dummy
ResolveDependenciesResult(true, [|"Skipped processing of any hash-r references"|], [||], Seq.empty, Seq.empty, Seq.empty) :> _
1 change: 1 addition & 0 deletions test/FsAutoComplete.Tests.Lsp/Helpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ let defaultConfigDto : FSharpConfigDto =
UseSdkScripts = Some true
DotNetRoot = None
FSIExtraParameters = None
FSICompilerToolLocations = None
TooltipMode = None }

let clientCaps : ClientCapabilities =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#r "dummy: some stuff"

let number = 10
39 changes: 39 additions & 0 deletions test/FsAutoComplete.Tests.Lsp/Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,43 @@ let analyzerTests =
))
]

let dependencyManagerTests =
let serverStart useCorrectPaths =
let workingDir = Path.Combine(__SOURCE_DIRECTORY__, "TestCases", "DependencyManagement")
let dependencyManagerAssemblyDir = Path.Combine(__SOURCE_DIRECTORY__, "..", "FsAutoComplete.DependencyManager.Dummy", "bin", "Debug", "netstandard2.0")
let dependencyManagerEnabledConfig =
{ defaultConfigDto with
FSIExtraParameters = Some [| "--langversion:preview" |]
FSICompilerToolLocations = Some [| if useCorrectPaths then dependencyManagerAssemblyDir |] }
let (server, events) = serverInitialize workingDir dependencyManagerEnabledConfig
let scriptPath = Path.Combine(workingDir, "Script.fsx")
do waitForWorkspaceFinishedParsing events
do server.TextDocumentDidOpen { TextDocument = loadDocument scriptPath } |> Async.RunSynchronously
server, events, workingDir, scriptPath

let serverTest correctManagerPaths f = fun () -> f (serverStart correctManagerPaths)

testList "dependencyManager integrations" [
testCase "can typecheck script that depends on #r dummy dependency manager" (serverTest true (fun (server, events, workingDir, testFilePath) ->
do server.TextDocumentDidOpen { TextDocument = loadDocument testFilePath } |> Async.RunSynchronously
match waitForParseResultsForFile "Script.fsx" events with
| Ok _ -> ()
| Core.Result.Error e ->
failwithf "Error during typechecking: %A" e
))
testCase "fails to typecheck script when dependency manager is missing" (serverTest false (fun (server, events, workingDir, testFilePath) ->
do server.TextDocumentDidOpen { TextDocument = loadDocument testFilePath } |> Async.RunSynchronously
match waitForParseResultsForFile "Script.fsx" events with
| Ok _ ->
failwith "Expected to fail typechecking a script with a dependency manager that's missing"
| Core.Result.Error e ->
match e with
| [| { Code = Some "3216" } |] -> () // this is the error code that signals a missing dependency manager, so this is a 'success'
| e -> failwithf "Unexpected error during typechecking: %A" e
))
]


let highlightingTets =
let serverStart = lazy (
let path = Path.Combine(__SOURCE_DIRECTORY__, "TestCases", "CodeLensTest")
Expand All @@ -1099,6 +1136,7 @@ let highlightingTets =
// Expect.equal res.Length 2 "Document Symbol has all symbols"
))


///Global list of tests
let tests =
testSequenced <| testList "lsp" [
Expand All @@ -1119,5 +1157,6 @@ let tests =
formattingTests
fakeInteropTests
analyzerTests
dependencyManagerTests
highlightingTets
]