diff --git a/build/paket.references b/build/paket.references index 89dc76af..1c8b5b0e 100644 --- a/build/paket.references +++ b/build/paket.references @@ -14,6 +14,5 @@ Fake.IO.Zip Fake.Api.GitHub Fake.Tools.Git Fake.JavaScript.Yarn -Octokit - +Octokit MSBuild.StructuredLogger \ No newline at end of file diff --git a/paket.dependencies b/paket.dependencies index 4dcb82f5..8cff75eb 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -1,51 +1,51 @@ -source https://api.nuget.org/v3/index.json -storage: none -framework: netstandard2.0 - -nuget Fable.Core -nuget Fable.Promise -nuget Fable.Node -nuget Fable.Browser.Dom - -nuget Fable.HtmlConverter - -nuget Thoth.Json 7.0 - -git https://github.com/ionide/ionide-fsgrammar.git master - -github ionide/ionide-vscode-helpers:8e81bc03f11f07b8e0811b3d4598eadc78f32f2f src/Fable.Import.VSCode.fs -github ionide/ionide-vscode-helpers:8e81bc03f11f07b8e0811b3d4598eadc78f32f2f src/Helpers.fs -github ionide/ionide-vscode-helpers:8e81bc03f11f07b8e0811b3d4598eadc78f32f2f src/Fable.Import.Showdown.fs -github ionide/ionide-vscode-helpers:8e81bc03f11f07b8e0811b3d4598eadc78f32f2f src/Fable.Import.VSCode.LanguageServer.fs - -group fsac - source https://api.nuget.org/v3/index.json - storage: packages - framework: netstandard2.0 - nuget fsautocomplete - -group build - source https://api.nuget.org/v3/index.json - storage: none - framework: net7.0 - - nuget Fake.Core.Target - nuget Fake.Core.Process - nuget Fake.Core.ReleaseNotes - nuget Fake.Core.Environment - nuget Fake.Core.UserInput - nuget Fake.DotNet.Cli - nuget Fake.DotNet.AssemblyInfoFile - nuget Fake.DotNet.Paket - nuget Fake.DotNet.MsBuild - nuget Fake.IO.FileSystem - nuget Fake.IO.Zip - nuget Fake.Api.GitHub - nuget Fake.Tools.Git - nuget Fake.JavaScript.Yarn - nuget Octokit <= 0.49.0 - - // Enforce updated binlog parser until Fake gets an update, so we're not stuck - // on an old sdk version. - // ref: https://github.com/fsprojects/FAKE/issues/2744 - nuget MSBuild.StructuredLogger >= 2.1.784 \ No newline at end of file +source https://api.nuget.org/v3/index.json +storage: none +framework: netstandard2.0 + +nuget Fable.Core +nuget Fable.Promise +nuget Fable.Node +nuget Fable.Browser.Dom + +nuget Fable.HtmlConverter + +nuget Thoth.Json 7.0 + +git https://github.com/ionide/ionide-fsgrammar.git master + +github ionide/ionide-vscode-helpers:8e81bc03f11f07b8e0811b3d4598eadc78f32f2f src/Fable.Import.VSCode.fs +github ionide/ionide-vscode-helpers:8e81bc03f11f07b8e0811b3d4598eadc78f32f2f src/Helpers.fs +github ionide/ionide-vscode-helpers:8e81bc03f11f07b8e0811b3d4598eadc78f32f2f src/Fable.Import.Showdown.fs +github ionide/ionide-vscode-helpers:8e81bc03f11f07b8e0811b3d4598eadc78f32f2f src/Fable.Import.VSCode.LanguageServer.fs + +group fsac + source https://api.nuget.org/v3/index.json + storage: packages + framework: netstandard2.0 + nuget fsautocomplete + +group build + source https://api.nuget.org/v3/index.json + storage: none + framework: net7.0 + + nuget Fake.Core.Target + nuget Fake.Core.Process + nuget Fake.Core.ReleaseNotes + nuget Fake.Core.Environment + nuget Fake.Core.UserInput + nuget Fake.DotNet.Cli + nuget Fake.DotNet.AssemblyInfoFile + nuget Fake.DotNet.Paket + nuget Fake.DotNet.MsBuild + nuget Fake.IO.FileSystem + nuget Fake.IO.Zip + nuget Fake.Api.GitHub + nuget Fake.Tools.Git + nuget Fake.JavaScript.Yarn + nuget Octokit <= 0.49.0 + + // Enforce updated binlog parser until Fake gets an update, so we're not stuck + // on an old sdk version. + // ref: https://github.com/fsprojects/FAKE/issues/2744 + nuget MSBuild.StructuredLogger >= 2.1.784 diff --git a/release/package.json b/release/package.json index 1870e207..234b42e3 100644 --- a/release/package.json +++ b/release/package.json @@ -328,7 +328,8 @@ "dark": "./images/debug-mono-dark.svg", "light": "./images/debug-mono-light.svg" }, - "title": "Debug" + "title": "Debug", + "enablement": "fsharp.debugger.available" }, { "command": "fsharp.explorer.project.setDefault", @@ -350,7 +351,8 @@ { "command": "fsharp.debugDefaultProject", "icon": "./images/debug.png", - "title": "F#: Debug Default Project" + "title": "F#: Debug Default Project", + "enablement": "fsharp.debugger.available" }, { "command": "fsharp.chooseDefaultProject", @@ -1218,7 +1220,7 @@ }, { "command": "fsharp.debugDefaultProject", - "when": "fsharp.project.any" + "when": "fsharp.project.any \u0026\u0026 fsharp.debugger.available" }, { "command": "fsharp.chooseDefaultProject", @@ -1266,7 +1268,7 @@ { "command": "fsharp.debugDefaultProject", "group": "fsharp", - "when": "fsharp.project.any \u0026\u0026 config.FSharp.enableTouchBar" + "when": "fsharp.project.any \u0026\u0026 config.FSharp.enableTouchBar \u0026\u0026 fsharp.debugger.available" }, { "command": "fsharp.runDefaultProject", @@ -1461,7 +1463,7 @@ { "command": "fsharp.explorer.solution.clean", "group": "1_navigation@3", - "when": "viewItem == ionide.projectExplorer.solution" + "when": "viewItem == ionide.projectExplorer.solution " }, { "command": "fsharp.explorer.solution.restore", @@ -1541,12 +1543,12 @@ { "command": "fsharp.explorer.project.debug", "group": "1_run@2", - "when": "viewItem == ionide.projectExplorer.projectExe" + "when": "viewItem == ionide.projectExplorer.projectExe \u0026\u0026 fsharp.debugger.available" }, { "command": "fsharp.explorer.project.debug", "group": "inline@2", - "when": "viewItem == ionide.projectExplorer.projectExe" + "when": "viewItem == ionide.projectExplorer.projectExe \u0026\u0026 fsharp.debugger.available" }, { "command": "fsharp.explorer.project.setDefault", @@ -1744,9 +1746,7 @@ "engines": { "vscode": "^0.10.0" }, - "extensionDependencies": [ - "ms-dotnettools.csharp" - ], + "extensionDependencies": [], "homepage": "http://ionide.io", "icon": "images/logo.png", "license": "MIT", diff --git a/src/Components/CSharpExtensionSupport.fs b/src/Components/CSharpExtensionSupport.fs new file mode 100644 index 00000000..f8ea8ef5 --- /dev/null +++ b/src/Components/CSharpExtensionSupport.fs @@ -0,0 +1,86 @@ +namespace Ionide.VSCode.FSharp + +open Fable.Import.VSCode +open Fable.Import.VSCode.Vscode + +module CSharpExtension = + + let private msCSharpExtensionName = "ms-dotnettools.csharp" + let private openvsixCSharpExtensionName = "muhammad-sammy.csharp" + + let private resolvedCSharpExtensionName = + if env.appName = "Visual Studio Code" then + msCSharpExtensionName + else + openvsixCSharpExtensionName + + let mutable private hasLookedForCSharp = false + let mutable private hasCSharp = false + let mutable private csharpExtension: Extension = null + let mutable private hasWarned = false + + let private csharpAvailableContext: bool -> unit = + let fn = Context.cachedSetter "fsharp.debugger.available" + + fun value -> + hasCSharp <- value + fn value + + let isCSharpAvailable () = hasCSharp + + let tryFindCSharpExtension () = + if not hasLookedForCSharp then + match extensions.getExtension resolvedCSharpExtensionName with + | None -> csharpAvailableContext false + | Some e -> + csharpExtension <- e + csharpAvailableContext true + + hasLookedForCSharp <- true + + hasCSharp + + let warnAboutMissingCSharpExtension () = + if not hasWarned then + window.showWarningMessage ( + $"The C# extension isn't installed, so debugging and some build tools will not be available. Consider installing the C# extension to enable those features.", + [| "Install C# Extension" |] + ) + |> Promise.ofThenable + |> Promise.bind (fun c -> + if c = Some "Install C# Extension" then + commands.executeCommand ("extension.open", [| Some(box resolvedCSharpExtensionName) |]) + |> Promise.ofThenable + else + Promise.empty) + |> Promise.catch (fun e -> + printfn $"Error installing C# extension: {Fable.Core.JS.JSON.stringify e}" + Promise.empty) + |> ignore> + + hasWarned <- true + + let private notifyUserThatDebuggingWorks () = + window.showInformationMessage ( + $"The C# extension is installed, so debugging and build tools are now available for F# projects." + ) + |> ignore> + + let activate (context: ExtensionContext) = + // when extensions are installed or removed we need to update our state for the C# extension + // so enablement/disablement works correctly + context.Subscribe( + extensions.onDidChange.Invoke(fun _ -> + let previousCSharpValue = hasCSharp + hasLookedForCSharp <- false + let currentCSharpValue = tryFindCSharpExtension () + + match previousCSharpValue, currentCSharpValue with + | false, true -> notifyUserThatDebuggingWorks () + | true, false -> + hasWarned <- false + warnAboutMissingCSharpExtension () + | _ -> () + + None) + ) diff --git a/src/Components/Debugger.fs b/src/Components/Debugger.fs index cb944034..2aa9cf05 100644 --- a/src/Components/Debugger.fs +++ b/src/Components/Debugger.fs @@ -336,34 +336,39 @@ module Debugger = { new DebugConfigurationProvider with override x.provideDebugConfigurations(folder: option, token: option) = let generate () = - promise { - logger.Info("Evaluating launch settings configurations for %O", folder) - let projects = Project.getLoaded () - let! msbuildTasks = tasks.fetchTasks (msbuildTasksFilter) - - let tasks = - projects - |> List.collect (fun (p: Project) -> - [ let projectFile = node.path.basename p.Project - - let buildTaskForProject = - msbuildTasks - |> Seq.tryFind (fun t -> - t.group = Some vscode.TaskGroup.Build && t.name = projectFile) - // emit configurations for any launchsettings for this project - match readSettingsForProject p with - | Some launchSettings -> - yield! configsForProject (p, launchSettings, buildTaskForProject) - | None -> () - // emit a default configuration for this project if it is an executable - match defaultConfigForProject (p, buildTaskForProject) with - | Some p -> yield p - | None -> () ]) - - return ResizeArray tasks - } - - generate () // this bix/unbox is a hack because JS types + match CSharpExtension.tryFindCSharpExtension () with + | false -> + CSharpExtension.warnAboutMissingCSharpExtension () + promise { return ResizeArray() } + | true -> + promise { + logger.Info("Evaluating launch settings configurations for %O", folder) + let projects = Project.getLoaded () + let! msbuildTasks = tasks.fetchTasks (msbuildTasksFilter) + + let tasks = + projects + |> List.collect (fun (p: Project) -> + [ let projectFile = node.path.basename p.Project + + let buildTaskForProject = + msbuildTasks + |> Seq.tryFind (fun t -> + t.group = Some vscode.TaskGroup.Build && t.name = projectFile) + // emit configurations for any launchsettings for this project + match readSettingsForProject p with + | Some launchSettings -> + yield! configsForProject (p, launchSettings, buildTaskForProject) + | None -> () + // emit a default configuration for this project if it is an executable + match defaultConfigForProject (p, buildTaskForProject) with + | Some p -> yield p + | None -> () ]) + + return ResizeArray tasks + } + + generate () // this box/unbox is a hack because JS types |> box |> unbox @@ -386,6 +391,7 @@ module Debugger = ProviderResult.Some(U2.Case1 debugConfiguration) } let activate (c: ExtensionContext) = + commands.registerCommand ("fsharp.runDefaultProject", (buildAndRunDefault) |> objfy2) |> c.Subscribe diff --git a/src/Components/MSBuild.fs b/src/Components/MSBuild.fs index 5c685048..85c96829 100644 --- a/src/Components/MSBuild.fs +++ b/src/Components/MSBuild.fs @@ -486,19 +486,6 @@ module MSBuild = let registerCommand com (action: unit -> _) = commands.registerCommand (com, action |> objfy2) |> context.Subscribe - let registerCommand2 com (action: obj -> obj -> _) = - commands.registerCommand (com, action |> objfy3) |> context.Subscribe - - /// typed msbuild cmd. Optional project and msbuild host - let typedMsbuildCmd f projOpt = - let p = - if JS.isDefined projOpt then - Some(unbox (projOpt)) - else - None - - fun _ -> f p - tasks.registerTaskProvider ("msbuild", msbuildBuildTaskProvider) |> context.Subscribe diff --git a/src/Ionide.FSharp.fsproj b/src/Ionide.FSharp.fsproj index 6389a4f4..2f17c46d 100644 --- a/src/Ionide.FSharp.fsproj +++ b/src/Ionide.FSharp.fsproj @@ -1,57 +1,58 @@ - - - - netstandard2.0 - false - - - - True - paket-files/Fable.Import.VSCode.fs - - - True - paket-files/Helpers.fs - - - True - paket-files/Fable.Import.Showdown.fs - - - True - paket-files/Fable.Import.VSCode.LanguageServer.fs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + netstandard2.0 + false + + + + True + paket-files/Fable.Import.VSCode.fs + + + True + paket-files/Helpers.fs + + + True + paket-files/Fable.Import.Showdown.fs + + + True + paket-files/Fable.Import.VSCode.LanguageServer.fs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/fsharp.fs b/src/fsharp.fs index f0117aef..f1441a62 100644 --- a/src/fsharp.fs +++ b/src/fsharp.fs @@ -33,6 +33,8 @@ let activate (context: ExtensionContext) : JS.Promise = logger.Error $"Error while activating feature '{label}': {ex}" Unchecked.defaultof<_> + CSharpExtension.activate (context) + LanguageService.start context |> Promise.catch (fun e -> logger.Error $"Error activating FSAC: %A{e}") // prevent unhandled rejected promises |> Promise.onSuccess (fun _ ->