-
-
Notifications
You must be signed in to change notification settings - Fork 282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Break direct C# dependency and instead light up debug/build functionality at runtime #1903
base: main
Are you sure you want to change the base?
Conversation
Ok, this is ready for other folks to poke at it. The build-related commands (restore, clean, build, rebuild) are always available, and the |
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<Fable.Core.JS.Promise<_>> | ||
|
||
hasWarned <- true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two are designed to be cheap to call, so that components that rely on the debugger can match/call them inside processing loops naievely instead of having to be truly 'reactive'
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 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all the same logic, just wrapped in a 'if debugging exists then .. else' block
None | ||
|
||
fun _ -> f p | ||
|
||
tasks.registerTaskProvider ("msbuild", msbuildBuildTaskProvider) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two functions were unused.
<Compile Include="fsharp.fs" /> | ||
</ItemGroup> | ||
<Import Project="..\.paket\Paket.Restore.targets" /> | ||
<?xml version="1.0" encoding="utf-8"?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No actual change here - just line endings maybe?
If you're going to take this for a test drive, start by uninstalling C# and then reloading your environment. Debugging shouldn't work at all, but building/launching should. |
@TheAngryByrd pointed out that the extension list query for "@category:debuggers F#" doesn't point directly to the C# extension (the vehicle for the functionality). We should reach out to that team to see what we can do. Alternatively we could keep the commands enabled on our side, but have their implementations simply send the notification to install the C# extension directly. |
We get some disappointing first generated {
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"WARNING01": "*********************************************************************************",
"WARNING02": "The C# extension was unable to automatically decode projects in the current",
"WARNING03": "workspace to create a runnable launch.json file. A template launch.json file has",
"WARNING04": "been created as a placeholder.",
"WARNING05": "",
"WARNING06": "If the server is currently unable to load your project, you can attempt to",
"WARNING07": "resolve this by restoring any missing project dependencies (example: run 'dotnet",
"WARNING08": "restore') and by fixing any reported errors from building the projects in your",
"WARNING09": "workspace.",
"WARNING10": "If this allows the server to now load your project then --",
"WARNING11": " * Delete this file",
"WARNING12": " * Open the Visual Studio Code command palette (View->Command Palette)",
"WARNING13": " * run the command: '.NET: Generate Assets for Build and Debug'.",
"WARNING14": "",
"WARNING15": "If your project requires a more complex launch configuration, you may wish to",
"WARNING16": "delete this configuration and pick a different template using the 'Add",
"WARNING17": "Configuration...' button at the bottom of this file.",
"WARNING18": "*********************************************************************************",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/<insert-target-framework-here>/<insert-project-name-here>.dll",
"args": [],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
} Doubt this is something we can do but it will be a concern for newer people trying to debug a project. |
Also trying to run a project from the Solution Explorer fails: debugging-icedtasks.mp4Where it does seem to work in the current version. |
Wonder if there's gonna be complications with #1927 |
good spot - I'm assuming #1927 will go first. If it does then I'll do the same checks I've done here for the debugging commands. |
I think if we can get the C# extension to add |
WHAT
🤖 Generated by Copilot at f225697
This pull request adds a feature to make the
ms-dotnettools.csharp
extension optional for debugging and building F# projects in VS Code. It introduces a new context variablefsharp.debuggerAvailable
that depends on the availability and status of the C# extension, and uses it to conditionally activate various commands and shortcuts in thepackage.json
file. It also adds a new moduleCSharpExtension
that provides the logic for checking and warning about the C# extension, and modifies theDebugger
andMSBuild
modules to use it.🤖 Generated by Copilot at f225697
🚨🔧🚀
WHY
Ok, so we have a nonzero amount of folks that just want to get going with F#, and right now our hard dependency on the C# extension can introduce a source of instability. What if we could detect the presence of the C# extension at run time and light up debug/launch tasks support if it is found, while notifying the user that those features will not be available until they install that extension?
Basic plan of attack:
when
condition for lots of the commands we declare in package.jsonTODO:
HOW
🤖 Generated by Copilot at f225697
when
property of the MSBuild and F# commands in thepackage.json
file, using thefsharp.debuggerAvailable
context variable (link, link, link, link, link, link)ms-dotnettools.csharp
extension from theextensionDependencies
array in thepackage.json
file (link)CSharpExtension
insrc/Components/CSharpExtensionSupport.fs
that defines functions and variables to check, set, and warn about the C# extension availability (link, link)activate
functions in theDebugger
andMSBuild
modules insrc/Components/Debugger.fs
andsrc/Components/MSBuild.fs
to use theCSharpExtension
module and only register the commands and providers if the C# extension is available (link, link)package.json
file (link)