Skip to content
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

Minor improvements to an old code fix #16048

Merged
merged 6 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading