From b0a00b64a2ba4b495d4f6d04ec1db8498553e81d Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 5 Sep 2023 19:46:05 +0200 Subject: [PATCH 1/5] Small cleanup in code fixes --- .../Service/ServiceCompilerDiagnostics.fs | 2 - .../Service/ServiceCompilerDiagnostics.fsi | 1 - ...ervice.SurfaceArea.netstandard20.debug.bsl | 5 -- ...vice.SurfaceArea.netstandard20.release.bsl | 5 -- ...peAnnotationToObjectOfIndeterminateType.fs | 7 +-- .../FSharp.Editor/CodeFixes/CodeFixHelpers.fs | 47 ++++++++--------- .../CodeFixes/FixIndexerAccessLegacy.fs | 52 ------------------- .../CodeFixes/MakeDeclarationMutable.fs | 3 +- .../CodeFixes/ReplaceWithSuggestion.fs | 5 +- .../UseMutationWhenValueIsMutable.fs | 3 +- .../src/FSharp.Editor/FSharp.Editor.fsproj | 1 - 11 files changed, 27 insertions(+), 104 deletions(-) delete mode 100644 vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs diff --git a/src/Compiler/Service/ServiceCompilerDiagnostics.fs b/src/Compiler/Service/ServiceCompilerDiagnostics.fs index 0380f456c65..a40afde22d2 100644 --- a/src/Compiler/Service/ServiceCompilerDiagnostics.fs +++ b/src/Compiler/Service/ServiceCompilerDiagnostics.fs @@ -6,7 +6,6 @@ open FSharp.Compiler.DiagnosticResolutionHints [] type FSharpDiagnosticKind = - | AddIndexerDot | ReplaceWithSuggestion of suggestion: string | RemoveIndexerDot @@ -15,7 +14,6 @@ module CompilerDiagnostics = let GetErrorMessage diagnosticKind = match diagnosticKind with - | FSharpDiagnosticKind.AddIndexerDot -> FSComp.SR.addIndexerDot () | FSharpDiagnosticKind.ReplaceWithSuggestion s -> FSComp.SR.replaceWithSuggestion (s) | FSharpDiagnosticKind.RemoveIndexerDot -> FSComp.SR.tcIndexNotationDeprecated () |> snd diff --git a/src/Compiler/Service/ServiceCompilerDiagnostics.fsi b/src/Compiler/Service/ServiceCompilerDiagnostics.fsi index f3536054c65..46ad0e0d46e 100644 --- a/src/Compiler/Service/ServiceCompilerDiagnostics.fsi +++ b/src/Compiler/Service/ServiceCompilerDiagnostics.fsi @@ -5,7 +5,6 @@ namespace FSharp.Compiler.Diagnostics /// Supported kinds of diagnostics by this service. [] type FSharpDiagnosticKind = - | AddIndexerDot | ReplaceWithSuggestion of suggestion: string | RemoveIndexerDot diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index 9f3b2c381aa..ee1b1b1ea61 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -2404,22 +2404,17 @@ FSharp.Compiler.Diagnostics.FSharpDiagnostic: System.String get_Message() FSharp.Compiler.Diagnostics.FSharpDiagnostic: System.String get_Subcategory() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion: System.String get_suggestion() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion: System.String suggestion -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 AddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 RemoveIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 ReplaceWithSuggestion FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(FSharp.Compiler.Diagnostics.FSharpDiagnosticKind) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(System.Object) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsAddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsRemoveIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsReplaceWithSuggestion -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsAddIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsRemoveIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsReplaceWithSuggestion() -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind AddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind NewReplaceWithSuggestion(System.String) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind RemoveIndexerDot -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind get_AddIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind get_RemoveIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index 9f3b2c381aa..ee1b1b1ea61 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -2404,22 +2404,17 @@ FSharp.Compiler.Diagnostics.FSharpDiagnostic: System.String get_Message() FSharp.Compiler.Diagnostics.FSharpDiagnostic: System.String get_Subcategory() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion: System.String get_suggestion() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion: System.String suggestion -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 AddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 RemoveIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 ReplaceWithSuggestion FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(FSharp.Compiler.Diagnostics.FSharpDiagnosticKind) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(System.Object) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsAddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsRemoveIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsReplaceWithSuggestion -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsAddIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsRemoveIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsReplaceWithSuggestion() -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind AddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind NewReplaceWithSuggestion(System.String) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind RemoveIndexerDot -FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind get_AddIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind get_RemoveIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/AddTypeAnnotationToObjectOfIndeterminateType.fs b/vsintegration/src/FSharp.Editor/CodeFixes/AddTypeAnnotationToObjectOfIndeterminateType.fs index b14f080aea9..4accffe94bd 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/AddTypeAnnotationToObjectOfIndeterminateType.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/AddTypeAnnotationToObjectOfIndeterminateType.fs @@ -10,7 +10,6 @@ open Microsoft.CodeAnalysis.Text open Microsoft.CodeAnalysis.CodeFixes open FSharp.Compiler.EditorServices -open FSharp.Compiler.Text open FSharp.Compiler.Symbols open CancellableTasks @@ -43,10 +42,7 @@ type internal AddTypeAnnotationToObjectOfIndeterminateTypeFixProvider [ return ValueNone | Some lexerSymbol -> - let! sourceText = context.GetSourceTextAsync() - let textLine = sourceText.Lines.GetLineFromPosition position - let textLinePos = sourceText.Lines.GetLinePosition position - let fcsTextLineNumber = Line.fromZ textLinePos.Line + let! fcsTextLineNumber, textLine = context.GetLineNumberAndText position let! _, checkFileResults = document.GetFSharpParseAndCheckResultsAsync(nameof AddTypeAnnotationToObjectOfIndeterminateTypeFixProvider) @@ -62,6 +58,7 @@ type internal AddTypeAnnotationToObjectOfIndeterminateTypeFixProvider [ + let! sourceText = context.GetSourceTextAsync() let declSpan = RoslynHelpers.FSharpRangeToTextSpan(sourceText, declRange) let declTextLine = sourceText.Lines.GetLineFromPosition declSpan.Start diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/CodeFixHelpers.fs b/vsintegration/src/FSharp.Editor/CodeFixes/CodeFixHelpers.fs index 426715ee4ca..0a54de176dd 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/CodeFixHelpers.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/CodeFixHelpers.fs @@ -3,7 +3,6 @@ namespace Microsoft.VisualStudio.FSharp.Editor open System -open System.Threading open System.Collections.Immutable open System.Diagnostics @@ -20,13 +19,6 @@ open FSharp.Compiler.Text open CancellableTasks -module internal MutableCodeFixHelper = - let getLineNumberAndText (sourceText: SourceText) position = - let textLine = sourceText.Lines.GetLineFromPosition position - let textLinePos = sourceText.Lines.GetLinePosition position - let fcsTextLineNumber = Line.fromZ textLinePos.Line - fcsTextLineNumber, textLine.ToString() - module internal UnusedCodeFixHelper = let getUnusedSymbol textSpan (document: Document) (sourceText: SourceText) codeFixName = let ident = sourceText.ToString textSpan @@ -80,34 +72,30 @@ module internal CodeFixHelpers = TelemetryReporter.ReportSingleEvent(TelemetryEvents.CodefixActivated, props) - let createTextChangeCodeFix (name: string, title: string, context: CodeFixContext, changes: TextChange seq) = + let createTextChangeCodeFix (codeFix, context: CodeFixContext) = CodeAction.Create( - title, - (fun (cancellationToken: CancellationToken) -> - backgroundTask { - let! sourceText = context.Document.GetTextAsync(cancellationToken) - let doc = context.Document.WithText(sourceText.WithChanges(changes)) - reportCodeFixTelemetry context.Diagnostics context.Document name [||] + codeFix.Message, + (fun cancellationToken -> + cancellableTask { + let! sourceText = context.Document.GetTextAsync cancellationToken + let doc = context.Document.WithText(sourceText.WithChanges(codeFix.Changes)) + reportCodeFixTelemetry context.Diagnostics context.Document codeFix.Name [||] return doc - }), - name + } + |> CancellableTask.start cancellationToken), + codeFix.Name ) [] module internal CodeFixExtensions = type CodeFixContext with - member ctx.RegisterFsharpFix(staticName, title, changes, ?diagnostics) = - let codeAction = - CodeFixHelpers.createTextChangeCodeFix (staticName, title, ctx, changes) - - let diag = diagnostics |> Option.defaultValue ctx.Diagnostics - ctx.RegisterCodeFix(codeAction, diag) - member ctx.RegisterFsharpFix(codeFix: IFSharpCodeFixProvider) = cancellableTask { match! codeFix.GetCodeFixIfAppliesAsync ctx with - | ValueSome codeFix -> ctx.RegisterFsharpFix(codeFix.Name, codeFix.Message, codeFix.Changes) + | ValueSome codeFix -> + let codeAction = CodeFixHelpers.createTextChangeCodeFix (codeFix, ctx) + ctx.RegisterCodeFix(codeAction, ctx.Diagnostics) | ValueNone -> () } |> CancellableTask.startAsTask ctx.CancellationToken @@ -130,6 +118,15 @@ module internal CodeFixExtensions = return RoslynHelpers.TextSpanToFSharpRange(ctx.Document.FilePath, ctx.Span, sourceText) } + member ctx.GetLineNumberAndText position = + cancellableTask { + let! sourceText = ctx.GetSourceTextAsync() + let textLine = sourceText.Lines.GetLineFromPosition position + let textLinePos = sourceText.Lines.GetLinePosition position + let fcsTextLineNumber = Line.fromZ textLinePos.Line + return fcsTextLineNumber, textLine.ToString() + } + // This cannot be an extension on the code fix context // because the underlying GetFixAllProvider method doesn't take the context in. #nowarn "3511" // state machine not statically compilable diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs b/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs deleted file mode 100644 index 9b37c396473..00000000000 --- a/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs +++ /dev/null @@ -1,52 +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.Composition -open System.Collections.Immutable -open System.Threading.Tasks - -open Microsoft.CodeAnalysis.Text -open Microsoft.CodeAnalysis.CodeFixes -open FSharp.Compiler.Diagnostics - -[] -type internal LegacyFixAddDotToIndexerAccessCodeFixProvider() = - inherit CodeFixProvider() - - static let title = CompilerDiagnostics.GetErrorMessage FSharpDiagnosticKind.AddIndexerDot - - override _.FixableDiagnosticIds = ImmutableArray.Create("FS3217") - - override _.RegisterCodeFixesAsync context : Task = - async { - let! sourceText = context.Document.GetTextAsync() |> Async.AwaitTask - - context.Diagnostics - |> Seq.iter (fun diagnostic -> - - let span, replacement = - try - let mutable span = context.Span - - let notStartOfBracket (span: TextSpan) = - let t = sourceText.GetSubText(TextSpan(span.Start, span.Length + 1)) - t.[t.Length - 1] <> '[' - - // skip all braces and blanks until we find [ - while span.End < sourceText.Length && notStartOfBracket span do - span <- TextSpan(span.Start, span.Length + 1) - - span, sourceText.GetSubText(span).ToString() - with _ -> - context.Span, sourceText.GetSubText(context.Span).ToString() - - do - context.RegisterFsharpFix( - CodeFix.FixIndexerAccess, - title, - [| TextChange(span, replacement.TrimEnd() + ".") |], - ImmutableArray.Create(diagnostic) - )) - } - |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/MakeDeclarationMutable.fs b/vsintegration/src/FSharp.Editor/CodeFixes/MakeDeclarationMutable.fs index 3de1e34fb72..307b8ad0be1 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/MakeDeclarationMutable.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/MakeDeclarationMutable.fs @@ -46,8 +46,7 @@ type internal MakeDeclarationMutableCodeFixProvider [] () | Some lexerSymbol -> let! sourceText = context.GetSourceTextAsync() - let fcsTextLineNumber, textLine = - MutableCodeFixHelper.getLineNumberAndText sourceText position + let! fcsTextLineNumber, textLine = context.GetLineNumberAndText position let! parseFileResults, checkFileResults = document.GetFSharpParseAndCheckResultsAsync(nameof MakeDeclarationMutableCodeFixProvider) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/ReplaceWithSuggestion.fs b/vsintegration/src/FSharp.Editor/CodeFixes/ReplaceWithSuggestion.fs index 6c0b5ef77db..3807848630e 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/ReplaceWithSuggestion.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/ReplaceWithSuggestion.fs @@ -12,7 +12,6 @@ open Microsoft.CodeAnalysis.CodeFixes open FSharp.Compiler.Diagnostics open FSharp.Compiler.EditorServices open FSharp.Compiler.Syntax -open FSharp.Compiler.Text open CancellableTasks @@ -38,9 +37,7 @@ type internal ReplaceWithSuggestionCodeFixProvider [] () = let! unresolvedIdentifierText = context.GetSquigglyTextAsync() let pos = context.Span.End let caretLinePos = sourceText.Lines.GetLinePosition(pos) - let caretLine = sourceText.Lines.GetLineFromPosition(pos) - let fcsCaretLineNumber = Line.fromZ caretLinePos.Line - let lineText = caretLine.ToString() + let! fcsCaretLineNumber, lineText = context.GetLineNumberAndText pos let partialName = QuickParse.GetPartialLongNameEx(lineText, caretLinePos.Character - 1) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/UseMutationWhenValueIsMutable.fs b/vsintegration/src/FSharp.Editor/CodeFixes/UseMutationWhenValueIsMutable.fs index 27ad14755a2..2e3e686ada9 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/UseMutationWhenValueIsMutable.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/UseMutationWhenValueIsMutable.fs @@ -54,8 +54,7 @@ type internal UseMutationWhenValueIsMutableCodeFixProvider [ return ValueNone | Some lexerSymbol -> - let fcsTextLineNumber, textLine = - MutableCodeFixHelper.getLineNumberAndText sourceText adjustedPosition + let! fcsTextLineNumber, textLine = context.GetLineNumberAndText adjustedPosition let! _, checkFileResults = document.GetFSharpParseAndCheckResultsAsync(nameof UseMutationWhenValueIsMutableCodeFixProvider) diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index b73a33b690d..7c70d5957eb 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -134,7 +134,6 @@ - From 6faa2bad77cd53a670655ca4a668833aca62d94a Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 12 Sep 2023 13:38:21 +0200 Subject: [PATCH 2/5] revert breaking --- src/Compiler/Service/ServiceCompilerDiagnostics.fs | 2 ++ src/Compiler/Service/ServiceCompilerDiagnostics.fsi | 1 + ...harp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl | 5 +++++ ...rp.Compiler.Service.SurfaceArea.netstandard20.release.bsl | 5 +++++ 4 files changed, 13 insertions(+) diff --git a/src/Compiler/Service/ServiceCompilerDiagnostics.fs b/src/Compiler/Service/ServiceCompilerDiagnostics.fs index a40afde22d2..0380f456c65 100644 --- a/src/Compiler/Service/ServiceCompilerDiagnostics.fs +++ b/src/Compiler/Service/ServiceCompilerDiagnostics.fs @@ -6,6 +6,7 @@ open FSharp.Compiler.DiagnosticResolutionHints [] type FSharpDiagnosticKind = + | AddIndexerDot | ReplaceWithSuggestion of suggestion: string | RemoveIndexerDot @@ -14,6 +15,7 @@ module CompilerDiagnostics = let GetErrorMessage diagnosticKind = match diagnosticKind with + | FSharpDiagnosticKind.AddIndexerDot -> FSComp.SR.addIndexerDot () | FSharpDiagnosticKind.ReplaceWithSuggestion s -> FSComp.SR.replaceWithSuggestion (s) | FSharpDiagnosticKind.RemoveIndexerDot -> FSComp.SR.tcIndexNotationDeprecated () |> snd diff --git a/src/Compiler/Service/ServiceCompilerDiagnostics.fsi b/src/Compiler/Service/ServiceCompilerDiagnostics.fsi index 46ad0e0d46e..f3536054c65 100644 --- a/src/Compiler/Service/ServiceCompilerDiagnostics.fsi +++ b/src/Compiler/Service/ServiceCompilerDiagnostics.fsi @@ -5,6 +5,7 @@ namespace FSharp.Compiler.Diagnostics /// Supported kinds of diagnostics by this service. [] type FSharpDiagnosticKind = + | AddIndexerDot | ReplaceWithSuggestion of suggestion: string | RemoveIndexerDot diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index ee1b1b1ea61..9f3b2c381aa 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -2404,17 +2404,22 @@ FSharp.Compiler.Diagnostics.FSharpDiagnostic: System.String get_Message() FSharp.Compiler.Diagnostics.FSharpDiagnostic: System.String get_Subcategory() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion: System.String get_suggestion() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion: System.String suggestion +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 AddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 RemoveIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 ReplaceWithSuggestion FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(FSharp.Compiler.Diagnostics.FSharpDiagnosticKind) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(System.Object) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsAddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsRemoveIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsReplaceWithSuggestion +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsAddIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsRemoveIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsReplaceWithSuggestion() +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind AddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind NewReplaceWithSuggestion(System.String) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind RemoveIndexerDot +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind get_AddIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind get_RemoveIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index ee1b1b1ea61..9f3b2c381aa 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -2404,17 +2404,22 @@ FSharp.Compiler.Diagnostics.FSharpDiagnostic: System.String get_Message() FSharp.Compiler.Diagnostics.FSharpDiagnostic: System.String get_Subcategory() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion: System.String get_suggestion() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion: System.String suggestion +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 AddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 RemoveIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags: Int32 ReplaceWithSuggestion FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(FSharp.Compiler.Diagnostics.FSharpDiagnosticKind) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(System.Object) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsAddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsRemoveIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean IsReplaceWithSuggestion +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsAddIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsRemoveIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: Boolean get_IsReplaceWithSuggestion() +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind AddIndexerDot FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind NewReplaceWithSuggestion(System.String) FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind RemoveIndexerDot +FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind get_AddIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind get_RemoveIndexerDot() FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+ReplaceWithSuggestion FSharp.Compiler.Diagnostics.FSharpDiagnosticKind: FSharp.Compiler.Diagnostics.FSharpDiagnosticKind+Tags From e8b6e79c4a3e2301223cc468144b6eca7b9540cc Mon Sep 17 00:00:00 2001 From: Petr Date: Wed, 13 Sep 2023 21:41:43 +0200 Subject: [PATCH 3/5] add tests --- .../CodeFixes/FixIndexerAccessLegacy.fs | 50 +++++++++++++++++++ .../src/FSharp.Editor/FSharp.Editor.fsproj | 1 + .../CodeFixes/FixIndexerAccessLegacyTests.fs | 33 ++++++++++++ .../FSharp.Editor.Tests.fsproj | 1 + 4 files changed, 85 insertions(+) create mode 100644 vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs create mode 100644 vsintegration/tests/FSharp.Editor.Tests/CodeFixes/FixIndexerAccessLegacyTests.fs diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs b/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs new file mode 100644 index 00000000000..73664b8392c --- /dev/null +++ b/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.VisualStudio.FSharp.Editor + +open System.Composition +open System.Collections.Immutable + +open Microsoft.CodeAnalysis.Text +open Microsoft.CodeAnalysis.CodeFixes +open FSharp.Compiler.Diagnostics + +open CancellableTasks + +[] +type internal LegacyFixAddDotToIndexerAccessCodeFixProvider() = + inherit CodeFixProvider() + + static let title = CompilerDiagnostics.GetErrorMessage FSharpDiagnosticKind.AddIndexerDot + + override _.FixableDiagnosticIds = ImmutableArray.Create "FS3217" + + override this.RegisterCodeFixesAsync context = context.RegisterFsharpFix this + + interface IFSharpCodeFixProvider with + member _.GetCodeFixIfAppliesAsync context = + cancellableTask { + let! sourceText = context.GetSourceTextAsync() + + let span, replacement = + try + let mutable span = context.Span + + let notStartOfBracket (span: TextSpan) = + let t = sourceText.GetSubText(TextSpan(span.Start, span.Length + 1)) + t[t.Length - 1] <> '[' + + // skip all braces and blanks until we find [ + while span.End < sourceText.Length && notStartOfBracket span do + span <- TextSpan(span.Start, span.Length + 1) + + span, sourceText.GetSubText(span).ToString() + with _ -> + context.Span, context.GetSquigglyTextAsync() + + return ValueSome { + Name = CodeFix.FixIndexerAccess, + Message = title, + Changes = [ TextChange(span, replacement.TrimEnd() + ".") ] + } + } diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 7c70d5957eb..b73a33b690d 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -134,6 +134,7 @@ + diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/FixIndexerAccessLegacyTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/FixIndexerAccessLegacyTests.fs new file mode 100644 index 00000000000..e23b25dfb73 --- /dev/null +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/FixIndexerAccessLegacyTests.fs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module FSharp.Editor.Tests.CodeFixes.FixIndexerAccessLegacyTests + +open Microsoft.VisualStudio.FSharp.Editor +open Xunit + +open CodeFixTestFramework + +let private codeFix = LegacyFixAddDotToIndexerAccessCodeFixProvider() + +[] +let ``Fixes FS3217`` () = + let code = + """ +let list = [ 1; 2; 3 ] +let first = list[2] +""" + + let expected = + Some + { + Message = "Add . for indexer access." + FixedCode = + """ +let list = [ 1; 2; 3 ] +let first = list.[2] +""" + } + + let actual = codeFix |> tryFix code (WithOption "--langversion:5") + + Assert.Equal(expected, actual) diff --git a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj index 415567694a6..a75a982ae77 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj +++ b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj @@ -65,6 +65,7 @@ + From 7e54fe3ba34d7dbad1561ae0d898749129f1419b Mon Sep 17 00:00:00 2001 From: Petr Date: Wed, 13 Sep 2023 22:09:30 +0200 Subject: [PATCH 4/5] up --- .../src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs | 6 +++--- .../tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs b/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs index 73664b8392c..769d22f66b9 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs @@ -40,11 +40,11 @@ type internal LegacyFixAddDotToIndexerAccessCodeFixProvider() = span, sourceText.GetSubText(span).ToString() with _ -> - context.Span, context.GetSquigglyTextAsync() + context.Span, sourceText.GetSubText(context.Span).ToString() return ValueSome { - Name = CodeFix.FixIndexerAccess, - Message = title, + Name = CodeFix.FixIndexerAccess + Message = title Changes = [ TextChange(span, replacement.TrimEnd() + ".") ] } } diff --git a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj index a75a982ae77..e8d25a75fb9 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj +++ b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj @@ -53,6 +53,7 @@ + @@ -65,7 +66,6 @@ - From 4a5a9bb2cb3dba83b7eb4518e5e4b14f2921b4cb Mon Sep 17 00:00:00 2001 From: Petr Date: Wed, 13 Sep 2023 22:10:03 +0200 Subject: [PATCH 5/5] Update FixIndexerAccessLegacy.fs --- .../CodeFixes/FixIndexerAccessLegacy.fs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs b/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs index 769d22f66b9..aefd2df9ebd 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/FixIndexerAccessLegacy.fs @@ -25,7 +25,7 @@ type internal LegacyFixAddDotToIndexerAccessCodeFixProvider() = member _.GetCodeFixIfAppliesAsync context = cancellableTask { let! sourceText = context.GetSourceTextAsync() - + let span, replacement = try let mutable span = context.Span @@ -42,9 +42,11 @@ type internal LegacyFixAddDotToIndexerAccessCodeFixProvider() = with _ -> context.Span, sourceText.GetSubText(context.Span).ToString() - return ValueSome { - Name = CodeFix.FixIndexerAccess - Message = title - Changes = [ TextChange(span, replacement.TrimEnd() + ".") ] - } + return + ValueSome + { + Name = CodeFix.FixIndexerAccess + Message = title + Changes = [ TextChange(span, replacement.TrimEnd() + ".") ] + } }