Skip to content

Commit

Permalink
Minor improvements to an old code fix (#16048)
Browse files Browse the repository at this point in the history
* Minor improvement to an old code fix

* Update MissingReference.fs

* temp rename

* Update MissingReferenceCodeFixProvider.fs

* Renamed the file

---------

Co-authored-by: Adam Boniecki <20281641+abonie@users.noreply.github.com>
  • Loading branch information
psfinaki and abonie authored Oct 4, 2023
1 parent e33a8b2 commit f469631
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 97 deletions.
102 changes: 102 additions & 0 deletions vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// 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

// 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.
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = CodeFix.MissingReference); Shared>]
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

This file was deleted.

3 changes: 3 additions & 0 deletions vsintegration/src/FSharp.Editor/Common/Constants.fs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ module internal CodeFix =
[<Literal>]
let MakeDeclarationMutable = "MakeDeclarationMutable"

[<Literal>]
let MissingReference = "MissingReference"

[<Literal>]
let ChangePrefixNegationToInfixSubtraction =
"ChangePrefixNegationToInfixSubtraction"
Expand Down
2 changes: 1 addition & 1 deletion vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
<Compile Include="CodeFixes\ImplementInterfaceCodeFixProvider.fs" />
<Compile Include="CodeFixes\SimplifyName.fs" />
<Compile Include="CodeFixes\RemoveUnusedOpens.fs" />
<Compile Include="CodeFixes\MissingReferenceCodeFixProvider.fs" />
<Compile Include="CodeFixes\MissingReference.fs" />
<Compile Include="CodeFixes\FixIndexerAccessLegacy.fs" />
<Compile Include="CodeFixes\FixIndexerAccess.fs" />
<Compile Include="CodeFixes\RenameParamToMatchSignature.fs" />
Expand Down

0 comments on commit f469631

Please sign in to comment.