diff --git a/VSFSharpExtension.sln b/VSFSharpExtension.sln new file mode 100644 index 00000000000..0c3c7d1a184 --- /dev/null +++ b/VSFSharpExtension.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B4A1E626-4A48-4977-B291-219882DB3413}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSharp.VisualStudio.Extension", "src\FSharp.VisualStudio.Extension\FSharp.VisualStudio.Extension.csproj", "{14B9AB0E-2FC0-43F1-9775-20C262202D12}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageServer", "src\FSharp.Compiler.LanguageServer\FSharp.Compiler.LanguageServer.fsproj", "{7EDDFB35-2428-4433-8ABF-47233480B746}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {14B9AB0E-2FC0-43F1-9775-20C262202D12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14B9AB0E-2FC0-43F1-9775-20C262202D12}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14B9AB0E-2FC0-43F1-9775-20C262202D12}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14B9AB0E-2FC0-43F1-9775-20C262202D12}.Release|Any CPU.Build.0 = Release|Any CPU + {7EDDFB35-2428-4433-8ABF-47233480B746}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EDDFB35-2428-4433-8ABF-47233480B746}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EDDFB35-2428-4433-8ABF-47233480B746}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EDDFB35-2428-4433-8ABF-47233480B746}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {14B9AB0E-2FC0-43F1-9775-20C262202D12} = {B4A1E626-4A48-4977-B291-219882DB3413} + EndGlobalSection +EndGlobal diff --git a/src/Compiler/Service/FSharpProjectSnapshot.fs b/src/Compiler/Service/FSharpProjectSnapshot.fs index 38d62f974f8..14fca7148b9 100644 --- a/src/Compiler/Service/FSharpProjectSnapshot.fs +++ b/src/Compiler/Service/FSharpProjectSnapshot.fs @@ -679,6 +679,9 @@ and [] FSha let compilerArgs = File.ReadAllLines responseFile.FullName + FSharpProjectSnapshot.FromCommandLineArgs(compilerArgs, responseFile.DirectoryName, projectFileName) + + static member FromCommandLineArgs(compilerArgs: string array, directoryPath: string, projectFileName) = let fsharpFileExtensions = set [| ".fs"; ".fsi"; ".fsx" |] let isFSharpFile (file: string) = @@ -693,7 +696,7 @@ and [] FSha None else - let fullPath = Path.Combine(responseFile.DirectoryName, line) + let fullPath = Path.Combine(directoryPath, line) if not (File.Exists fullPath) then None else Some fullPath) |> Array.toList diff --git a/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj b/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj index bbcbdb6e3af..bef467713a0 100644 --- a/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj +++ b/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj @@ -9,10 +9,12 @@ - - + + - + + + diff --git a/src/FSharp.VisualStudio.Extension/FSharpLanguageServerProvider.cs b/src/FSharp.VisualStudio.Extension/FSharpLanguageServerProvider.cs index d8880e08835..3a282fe12d3 100644 --- a/src/FSharp.VisualStudio.Extension/FSharpLanguageServerProvider.cs +++ b/src/FSharp.VisualStudio.Extension/FSharpLanguageServerProvider.cs @@ -157,13 +157,46 @@ internal class FSharpLanguageServerProvider : LanguageServerProvider public override async Task CreateServerConnectionAsync(CancellationToken cancellationToken) { var ws = this.Extensibility.Workspaces(); - //var result = what.QueryProjectsAsync(project => project.With(p => p.Kind == "6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705"), cancellationToken).Result; - IQueryResults? result = await ws.QueryProjectsAsync(project => project.With(p => new { p.ActiveConfigurations, p.Id, p.Guid }), cancellationToken); - var x = await ws.QuerySolutionAsync(solution => solution.With(s => new { s.Path, s.Guid, s.ActiveConfiguration, s.ActivePlatform }), cancellationToken); + IQueryResults? result = await ws.QueryProjectsAsync(project => project + .With(p => p.ActiveConfigurations + .With(c => c.RuleResultsByRuleName("CompilerCommandLineArgs") + .With(r => r.RuleName) + .With(r => r.Items))) + .With(p => new { p.ActiveConfigurations, p.Id, p.Guid }), cancellationToken); + + List<(string, string)> projectsAndCommandLineArgs = []; foreach (var project in result) { + project.Id.TryGetValue("ProjectPath", out var projectPath); + + List commandLineArgs = []; + if (projectPath != null) + { + // There can be multiple Active Configurations, e.g. one for net8.0 and one for net472 + // TODO For now taking any single one of them, but we might actually want to pick specific one + var config = project.ActiveConfigurations.FirstOrDefault(); + if (config != null) + { + foreach (var ruleResults in config.RuleResults) + { + // XXX Idk why `.Where` does not work with these IAsyncQuerable type + if (ruleResults?.RuleName == "CompilerCommandLineArguments") + { + // XXX Not sure why there would be more than one item for this rule result + // Taking first one, ignoring the rest + var args = ruleResults?.Items?.FirstOrDefault()?.Name; + if (args != null) commandLineArgs.Add(args); + } + } + } + if (commandLineArgs.Count > 0) + { + projectsAndCommandLineArgs.Add((projectPath, commandLineArgs[0])); + } + } + try { this.ProcessProject(project); @@ -178,15 +211,17 @@ internal class FSharpLanguageServerProvider : LanguageServerProvider try { - // Some hardcoded projects before we create them from the ProjectQuery - var projectsRoot = @"D:\code"; - var giraffe = FSharpProjectSnapshot.FromResponseFile( - new FileInfo(Path.Combine(projectsRoot, @"Giraffe\src\Giraffe\Giraffe.rsp")), - Path.Combine(projectsRoot, @"Giraffe\src\Giraffe\Giraffe.fsproj")); - var giraffeTests = FSharpProjectSnapshot.FromResponseFile( - new FileInfo(Path.Combine(projectsRoot, @"Giraffe\tests\Giraffe.Tests\Giraffe.Tests.rsp")), - Path.Combine(projectsRoot, @"Giraffe\tests\Giraffe.Tests\Giraffe.Tests.fsproj")); - workspace = FSharpWorkspace.Create([giraffe, giraffeTests]); + List snapshots = []; + foreach(var args in projectsAndCommandLineArgs) + { + var lines = args.Item2.Split(';'); // XXX Probably not robust enough + var path = args.Item1; + + var snapshot = FSharpProjectSnapshot.FromCommandLineArgs( + lines, Path.GetDirectoryName(path), Path.GetFileName(path)); + snapshots.Add(snapshot); + } + workspace = FSharpWorkspace.Create(snapshots); } catch {