From 6fa1003475f2523f58c100d00a211b99b3fb5af1 Mon Sep 17 00:00:00 2001
From: Tomas Matousek <tomat@microsoft.com>
Date: Mon, 14 Feb 2022 15:01:22 -0800
Subject: [PATCH] CodeFixContext

---
 .../Services/Refactoring/FixUsingService.cs   |  9 ++--
 .../Refactoring/RunFixAllCodeActionService.cs | 12 +++++-
 .../CSharpDiagnosticWorkerWithAnalyzers.cs    |  9 +---
 .../Workers/Formatting/FormattingWorker.cs    |  4 +-
 .../Workers/Refactoring/FixUsingsWorker.cs    |  9 +++-
 .../Utilities/CodeFixContextFactory.cs        | 41 +++++++++++++++++++
 6 files changed, 67 insertions(+), 17 deletions(-)
 create mode 100644 src/OmniSharp.Roslyn/Utilities/CodeFixContextFactory.cs

diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/FixUsingService.cs b/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/FixUsingService.cs
index 0c2fafb766..eee336d7fe 100644
--- a/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/FixUsingService.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/FixUsingService.cs
@@ -5,6 +5,7 @@
 using Microsoft.Extensions.Logging;
 using OmniSharp.Mef;
 using OmniSharp.Models.FixUsings;
+using OmniSharp.Options;
 using OmniSharp.Roslyn.Utilities;
 using OmniSharp.Services;
 
@@ -14,17 +15,17 @@ namespace OmniSharp.Roslyn.CSharp.Services.Refactoring
     public class FixUsingService : IRequestHandler<FixUsingsRequest, FixUsingsResponse>
     {
         private readonly OmniSharpWorkspace _workspace;
-        private readonly ILoggerFactory _loggerFactory;
+        private readonly OmniSharpOptions _options;
         private readonly IEnumerable<ICodeActionProvider> _providers;
 
         [ImportingConstructor]
         public FixUsingService(
             OmniSharpWorkspace workspace,
-            ILoggerFactory loggerFactory,
+            OmniSharpOptions options,
             [ImportMany] IEnumerable<ICodeActionProvider> codeActionProviders)
         {
             _workspace = workspace;
-            _loggerFactory = loggerFactory;
+            _options = options;
             _providers = codeActionProviders;
         }
 
@@ -35,7 +36,7 @@ public async Task<FixUsingsResponse> Handle(FixUsingsRequest request)
             var oldDocument = _workspace.GetDocument(request.FileName);
             if (oldDocument != null)
             {
-                var fixUsingsResponse = await new FixUsingsWorker(_providers)
+                var fixUsingsResponse = await new FixUsingsWorker(_providers, _options)
                     .FixUsingsAsync(oldDocument);
 
                 response.AmbiguousResults = fixUsingsResponse.AmbiguousResults;
diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/RunFixAllCodeActionService.cs b/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/RunFixAllCodeActionService.cs
index 7b2c168cb6..0472eaad10 100644
--- a/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/RunFixAllCodeActionService.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/RunFixAllCodeActionService.cs
@@ -13,6 +13,8 @@
 using Microsoft.Extensions.Logging;
 using OmniSharp.Abstractions.Models.V1.FixAll;
 using OmniSharp.Mef;
+using OmniSharp.Options;
+using OmniSharp.Roslyn.CodeActions;
 using OmniSharp.Roslyn.CSharp.Services.Refactoring.V2;
 using OmniSharp.Roslyn.CSharp.Workers.Diagnostics;
 using OmniSharp.Services;
@@ -26,12 +28,14 @@ public class RunFixAllCodeActionService : BaseCodeActionService<RunFixAllRequest
     {
         private readonly ILogger<RunFixAllCodeActionService> _logger;
         private readonly FixAllDiagnosticProvider _fixAllDiagnosticProvider;
+        private readonly OmniSharpOptions _options;
 
         [ImportingConstructor]
         public RunFixAllCodeActionService(ICsDiagnosticWorker diagnosticWorker,
             [ImportMany] IEnumerable<ICodeActionProvider> providers,
             CachingCodeFixProviderForProjects codeFixProvider,
             OmniSharpWorkspace workspace,
+            OmniSharpOptions options,
             ILoggerFactory loggerFactory) :
             base(
                 workspace,
@@ -42,6 +46,7 @@ public RunFixAllCodeActionService(ICsDiagnosticWorker diagnosticWorker,
         {
             _logger = loggerFactory.CreateLogger<RunFixAllCodeActionService>();
             _fixAllDiagnosticProvider = new FixAllDiagnosticProvider(diagnosticWorker);
+            _options = options;
         }
 
         public async override Task<RunFixAllResponse> Handle(RunFixAllRequest request)
@@ -134,8 +139,12 @@ private async Task<Document> FixSpecificDiagnosticIdAsync(Document document, str
             }
 
             _logger.LogTrace("{0} is still present in the document. Getting fixes.", diagnosticId);
+
             CodeAction action = null;
-            var context = new CodeFixContext(document, primaryDiagnostic,
+            var context = CodeFixContextFactory.Create(
+                document,
+                primaryDiagnostic.Location.SourceSpan,
+                ImmutableArray.Create(primaryDiagnostic),
                 (a, _) =>
                 {
                     if (action == null)
@@ -143,6 +152,7 @@ private async Task<Document> FixSpecificDiagnosticIdAsync(Document document, str
                         action = a;
                     }
                 },
+                _options, 
                 cancellationToken);
 
             await codeFixProvider.RegisterCodeFixesAsync(context).ConfigureAwait(false);
diff --git a/src/OmniSharp.Roslyn.CSharp/Workers/Diagnostics/CSharpDiagnosticWorkerWithAnalyzers.cs b/src/OmniSharp.Roslyn.CSharp/Workers/Diagnostics/CSharpDiagnosticWorkerWithAnalyzers.cs
index e065ca2bd8..b04cdac505 100644
--- a/src/OmniSharp.Roslyn.CSharp/Workers/Diagnostics/CSharpDiagnosticWorkerWithAnalyzers.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Workers/Diagnostics/CSharpDiagnosticWorkerWithAnalyzers.cs
@@ -212,14 +212,7 @@ private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs changeEv
         }
 
         private AnalyzerOptions CreateAnalyzerOptions(Project project)
-        {
-            var ideOptions = new OmniSharpIdeAnalyzerOptions(
-                ImplementTypeOptions: new OmniSharpImplementTypeOptions(
-                    (OmniSharpImplementTypeInsertionBehavior)_options.ImplementTypeOptions.InsertionBehavior,
-                    (OmniSharpImplementTypePropertyGenerationBehavior)_options.ImplementTypeOptions.PropertyGenerationBehavior));
-
-            return OmniSharpWorkspaceAnalyzerOptionsFactory.Create(project.Solution, project.AnalyzerOptions, ideOptions);
-        }
+            => OmniSharpWorkspaceAnalyzerOptionsFactory.Create(project.Solution, project.AnalyzerOptions);
 
         public async Task<IEnumerable<Diagnostic>> AnalyzeDocumentAsync(Document document, CancellationToken cancellationToken)
         {
diff --git a/src/OmniSharp.Roslyn.CSharp/Workers/Formatting/FormattingWorker.cs b/src/OmniSharp.Roslyn.CSharp/Workers/Formatting/FormattingWorker.cs
index cb53dc1300..fc3eeb2d21 100644
--- a/src/OmniSharp.Roslyn.CSharp/Workers/Formatting/FormattingWorker.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Workers/Formatting/FormattingWorker.cs
@@ -24,7 +24,7 @@ public static class FormattingWorker
     {
         public static async Task<IEnumerable<LinePositionSpanTextChange>> GetFormattingChangesAfterKeystroke(Document document, int position, char character, OmniSharpOptions omnisharpOptions)
         {
-            if (await GetDocumentationCommentChanges(document, position, character, omnisharpOptions) is LinePositionSpanTextChange change)
+            if (await GetDocumentationCommentChanges(document, position, character) is LinePositionSpanTextChange change)
             {
                 return new[] { change };
             }
@@ -202,7 +202,7 @@ private static OmniSharpBinaryOperatorSpacingOptions BinaryOperatorSpacingOption
                 _ => OmniSharpBinaryOperatorSpacingOptions.Single,
             };
 
-        private static async Task<LinePositionSpanTextChange?> GetDocumentationCommentChanges(Document document, int position, char character, OmniSharpOptions omnisharpOptions)
+        private static async Task<LinePositionSpanTextChange?> GetDocumentationCommentChanges(Document document, int position, char character)
         {
             if (character != '\n' && character != '/')
             {
diff --git a/src/OmniSharp.Roslyn.CSharp/Workers/Refactoring/FixUsingsWorker.cs b/src/OmniSharp.Roslyn.CSharp/Workers/Refactoring/FixUsingsWorker.cs
index d64b17a659..485435f1dd 100644
--- a/src/OmniSharp.Roslyn.CSharp/Workers/Refactoring/FixUsingsWorker.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Workers/Refactoring/FixUsingsWorker.cs
@@ -11,6 +11,8 @@
 using Microsoft.CodeAnalysis.CSharp.Syntax;
 using Microsoft.CodeAnalysis.Text;
 using OmniSharp.Models;
+using OmniSharp.Options;
+using OmniSharp.Roslyn.CodeActions;
 using OmniSharp.Roslyn.CSharp.Services.CodeActions;
 using OmniSharp.Services;
 
@@ -27,8 +29,9 @@ public class FixUsingsWorker
         private readonly IEnumerable<ICodeActionProvider> _providers;
         private readonly CodeFixProvider _addImportProvider;
         private readonly CodeFixProvider _removeUnnecessaryUsingsProvider;
+        private readonly OmniSharpOptions _options;
 
-        public FixUsingsWorker(IEnumerable<ICodeActionProvider> providers)
+        public FixUsingsWorker(IEnumerable<ICodeActionProvider> providers, OmniSharpOptions options)
         {
             _providers = providers;
 
@@ -36,6 +39,7 @@ public FixUsingsWorker(IEnumerable<ICodeActionProvider> providers)
 
             _addImportProvider = FindCodeFixProviderByTypeFullName(codeFixProviders, CodeActionHelper.AddImportProviderName);
             _removeUnnecessaryUsingsProvider = FindCodeFixProviderByTypeFullName(codeFixProviders, CodeActionHelper.RemoveUnnecessaryUsingsProviderName);
+            _options = options;
         }
 
         private static CodeFixProvider FindCodeFixProviderByTypeFullName(IEnumerable<CodeFixProvider> providers, string fullName)
@@ -238,9 +242,10 @@ private async Task<ImmutableArray<CodeActionOperation>> GetCodeFixOperationsAsyn
             ImmutableArray<Diagnostic> diagnostics)
         {
             var codeFixes = new List<CodeAction>();
-            var context = new CodeFixContext(
+            var context = CodeFixContextFactory.Create(
                 document, span, diagnostics,
                 registerCodeFix: (a, d) => codeFixes.Add(a),
+                _options,
                 cancellationToken: CancellationToken.None);
 
             // Note: We're intentionally not checking CodeFixProvider.FixableDiagnosticIds here.
diff --git a/src/OmniSharp.Roslyn/Utilities/CodeFixContextFactory.cs b/src/OmniSharp.Roslyn/Utilities/CodeFixContextFactory.cs
new file mode 100644
index 0000000000..67fdbb5baa
--- /dev/null
+++ b/src/OmniSharp.Roslyn/Utilities/CodeFixContextFactory.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.CodeActions;
+using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.ImplementType;
+using OmniSharp.Options;
+using Microsoft.CodeAnalysis;
+using System.Collections.Immutable;
+using System.Threading;
+using Microsoft.CodeAnalysis.Text;
+
+namespace OmniSharp.Roslyn.CodeActions
+{
+    internal static class CodeFixContextFactory
+    {
+        public static CodeFixContext Create(
+            Document document,
+            TextSpan span,
+            ImmutableArray<Diagnostic> diagnostics,
+            Action<CodeAction, ImmutableArray<Diagnostic>> registerCodeFix,
+            OmniSharpOptions options,
+            CancellationToken cancellationToken)
+        {
+            var implementTypeOptions = new OmniSharpImplementTypeOptions(
+                    (OmniSharpImplementTypeInsertionBehavior)options.ImplementTypeOptions.InsertionBehavior,
+                    (OmniSharpImplementTypePropertyGenerationBehavior)options.ImplementTypeOptions.PropertyGenerationBehavior);
+
+            return OmniSharpCodeFixContextFactory.Create(
+                document,
+                span,
+                diagnostics,
+                registerCodeFix,
+                implementTypeOptions,
+                cancellationToken);
+        }
+    }
+}