From 0a6c5a7a64ffc61eeef8b67861d43b7587bea0ad Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 25 Sep 2023 14:32:02 +0200 Subject: [PATCH 1/5] Minor improvement to an old code fix --- .../CodeFixes/MissingReference.fs | 94 ++++++++++++++++++ .../MissingReferenceCodeFixProvider.fs | 96 ------------------- .../src/FSharp.Editor/Common/Constants.fs | 3 + .../src/FSharp.Editor/FSharp.Editor.fsproj | 2 +- 4 files changed, 98 insertions(+), 97 deletions(-) create mode 100644 vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs delete mode 100644 vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs new file mode 100644 index 00000000000..abb78490d7f --- /dev/null +++ b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.VisualStudio.FSharp.Editor + +open System +open System.Composition +open System.Collections.Immutable +open System.IO + +open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.CodeFixes +open Microsoft.CodeAnalysis.CodeActions + +open CancellableTasks + +type private ReferenceType = + | AddProjectRef of ProjectReference + | AddMetadataRef of MetadataReference + +// This code fix only works for the legacy, non-SDK projects. +// In SDK projects, transitive references do this trick. +// See: https://github.com/dotnet/fsharp/pull/2743 +[] +type internal MissingReferenceCodeFixProvider() = + inherit CodeFixProvider() + + let createCodeFix (title: string, context: CodeFixContext, addReference: ReferenceType) = + CodeAction.Create( + title, + (fun cancellationToken -> + cancellableTask { + let project = context.Document.Project + let solution = project.Solution + + match addReference with + | AddProjectRef projectRef -> + let references = project.AllProjectReferences + let newReferences = references |> Seq.append [ projectRef ] + return solution.WithProjectReferences(project.Id, newReferences) + + | AddMetadataRef metadataRef -> + let references = project.MetadataReferences + let newReferences = references |> Seq.append [ metadataRef ] + return solution.WithProjectMetadataReferences(project.Id, newReferences) + } + |> CancellableTask.start cancellationToken) + ) + + override _.FixableDiagnosticIds = ImmutableArray.Create "FS0074" + + override _.RegisterCodeFixesAsync context = + cancellableTask { + let solution = context.Document.Project.Solution + + let diagnostic = context.Diagnostics[0] + let message = diagnostic.GetMessage() + let parts = message.Split([| '\'' |], StringSplitOptions.None) + + match parts with + | [| _; _type; _; assemblyName; _ |] -> + + let exactProjectMatches = + solution.Projects + |> Seq.tryFindV (fun project -> + String.Compare(project.AssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase) = 0) + + match exactProjectMatches with + | ValueSome refProject -> + let codefix = + createCodeFix ( + String.Format(SR.AddProjectReference(), refProject.Name), + context, + AddProjectRef(ProjectReference refProject.Id) + ) + + context.RegisterCodeFix(codefix, ImmutableArray.Create diagnostic) + | ValueNone -> + let metadataReferences = + solution.Projects + |> Seq.collect (fun project -> project.MetadataReferences) + |> Seq.tryFindV (fun ref -> + let referenceAssemblyName = Path.GetFileNameWithoutExtension(ref.Display) + String.Compare(referenceAssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase) = 0) + + match metadataReferences with + | ValueSome metadataRef -> + let codefix = + createCodeFix (String.Format(SR.AddAssemblyReference(), assemblyName), context, AddMetadataRef metadataRef) + + context.RegisterCodeFix(codefix, ImmutableArray.Create diagnostic) + | ValueNone -> () + | _ -> () + } + |> CancellableTask.startAsTask context.CancellationToken diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs deleted file mode 100644 index eabc0cd2880..00000000000 --- a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.VisualStudio.FSharp.Editor - -open System -open System.Composition -open System.Collections.Immutable -open System.Threading -open System.Threading.Tasks -open System.IO - -open Microsoft.CodeAnalysis -open Microsoft.CodeAnalysis.CodeFixes -open Microsoft.CodeAnalysis.CodeActions - -type private ReferenceType = - | AddProjectRef of ProjectReference - | AddMetadataRef of MetadataReference - -[] -type internal MissingReferenceCodeFixProvider() = - inherit CodeFixProvider() - - let fixableDiagnosticId = "FS0074" - - let createCodeFix (title: string, context: CodeFixContext, addReference: ReferenceType) = - CodeAction.Create( - title, - (fun (cancellationToken: CancellationToken) -> - async { - let project = context.Document.Project - let solution = project.Solution - - match addReference with - | AddProjectRef projectRef -> - let references = project.AllProjectReferences - let newReferences = references |> Seq.append [ projectRef ] - return solution.WithProjectReferences(project.Id, newReferences) - - | AddMetadataRef metadataRef -> - let references = project.MetadataReferences - let newReferences = references |> Seq.append [ metadataRef ] - return solution.WithProjectMetadataReferences(project.Id, newReferences) - } - |> RoslynHelpers.StartAsyncAsTask(cancellationToken)), - title - ) - - override _.FixableDiagnosticIds = Seq.toImmutableArray [ fixableDiagnosticId ] - - override _.RegisterCodeFixesAsync context : Task = - async { - let solution = context.Document.Project.Solution - - context.Diagnostics - |> Seq.filter (fun x -> x.Id = fixableDiagnosticId) - |> Seq.iter (fun diagnostic -> - let message = diagnostic.GetMessage() - let parts = message.Split([| '\'' |], StringSplitOptions.None) - - match parts with - | [| _; _type; _; assemblyName; _ |] -> - - let exactProjectMatches = - solution.Projects - |> Seq.tryFindV (fun project -> - String.Compare(project.AssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase) = 0) - - match exactProjectMatches with - | ValueSome refProject -> - let codefix = - createCodeFix ( - String.Format(SR.AddProjectReference(), refProject.Name), - context, - AddProjectRef(ProjectReference refProject.Id) - ) - - context.RegisterCodeFix(codefix, ImmutableArray.Create diagnostic) - | ValueNone -> - let metadataReferences = - solution.Projects - |> Seq.collect (fun project -> project.MetadataReferences) - |> Seq.tryFindV (fun ref -> - let referenceAssemblyName = Path.GetFileNameWithoutExtension(ref.Display) - String.Compare(referenceAssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase) = 0) - - match metadataReferences with - | ValueSome metadataRef -> - let codefix = - createCodeFix (String.Format(SR.AddAssemblyReference(), assemblyName), context, AddMetadataRef metadataRef) - - context.RegisterCodeFix(codefix, ImmutableArray.Create diagnostic) - | ValueNone -> () - | _ -> ()) - } - |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken) diff --git a/vsintegration/src/FSharp.Editor/Common/Constants.fs b/vsintegration/src/FSharp.Editor/Common/Constants.fs index d59b241b44e..8e529cf0319 100644 --- a/vsintegration/src/FSharp.Editor/Common/Constants.fs +++ b/vsintegration/src/FSharp.Editor/Common/Constants.fs @@ -163,6 +163,9 @@ module internal CodeFix = [] let MakeDeclarationMutable = "MakeDeclarationMutable" + [] + let MissingReference = "MissingReference" + [] let ChangePrefixNegationToInfixSubtraction = "ChangePrefixNegationToInfixSubtraction" diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index b73a33b690d..b2a685d2347 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -133,7 +133,7 @@ - + From 6dfbb83fd013e16716a88c45348f7618e49a47be Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 26 Sep 2023 15:17:03 +0200 Subject: [PATCH 2/5] Update MissingReference.fs --- .../src/FSharp.Editor/CodeFixes/MissingReference.fs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs index abb78490d7f..85806f3bef4 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs @@ -20,6 +20,14 @@ type private ReferenceType = // This code fix only works for the legacy, non-SDK projects. // In SDK projects, transitive references do this trick. // See: https://github.com/dotnet/fsharp/pull/2743 + +// Because this code fix is barely applicable anymore +// and because it's very different from other code fixes +// (applies to the projects files, not code itself), +// it's not implemented via IFSharpCodeFix interfaces +// and not tested automatically either. +// If we happen to create similar code fixes, +// it'd make sense to create some testing framework for them. [] type internal MissingReferenceCodeFixProvider() = inherit CodeFixProvider() From 20a47635f559fc037d14dd78105683d1534a6347 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 26 Sep 2023 15:27:43 +0200 Subject: [PATCH 3/5] temp rename --- .../{MissingReference.fs => MissingReferenceCodeFixProvider.fs} | 0 vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename vsintegration/src/FSharp.Editor/CodeFixes/{MissingReference.fs => MissingReferenceCodeFixProvider.fs} (100%) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs similarity index 100% rename from vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs rename to vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index b2a685d2347..b73a33b690d 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -133,7 +133,7 @@ - + From 391997fdb38b542d12e65f022a71457d70fec451 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 26 Sep 2023 15:28:06 +0200 Subject: [PATCH 4/5] Update MissingReferenceCodeFixProvider.fs --- .../FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs index 85806f3bef4..eb77d13c355 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs @@ -21,7 +21,7 @@ type private ReferenceType = // In SDK projects, transitive references do this trick. // See: https://github.com/dotnet/fsharp/pull/2743 -// Because this code fix is barely applicable anymore +// Because this code fix is barely applicable anymore // and because it's very different from other code fixes // (applies to the projects files, not code itself), // it's not implemented via IFSharpCodeFix interfaces From dc0e8ee51a7d2445b04e83cf8bfb64087f8b0dcb Mon Sep 17 00:00:00 2001 From: Petr Date: Wed, 4 Oct 2023 16:34:01 +0200 Subject: [PATCH 5/5] Renamed the file --- .../{MissingReferenceCodeFixProvider.fs => MissingReference.fs} | 0 vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename vsintegration/src/FSharp.Editor/CodeFixes/{MissingReferenceCodeFixProvider.fs => MissingReference.fs} (100%) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs similarity index 100% rename from vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs rename to vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index b73a33b690d..b2a685d2347 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -133,7 +133,7 @@ - +