Skip to content

Commit

Permalink
Got one example working.
Browse files Browse the repository at this point in the history
  • Loading branch information
nojaf committed Mar 7, 2024
1 parent 219cdde commit 8665f45
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
module FsAutoComplete.CodeFix.UpdateTypeAbbreviationInSignatureFile

open FSharp.Compiler.Symbols
open FSharp.Compiler.Syntax
open FSharp.Compiler.Text
open FsToolkit.ErrorHandling
open Ionide.LanguageServerProtocol.Types
open FsAutoComplete.CodeFix.Types
open FsAutoComplete
open FsAutoComplete.LspHelpers

// TODO: add proper title for code fix
let title = "UpdateTypeAbbreviationInSignatureFile Codefix"

let fix (getParseResultsForFile: GetParseResultsForFile) : CodeFix =
Run.ifDiagnosticByCode (Set.ofList [ "318" ]) (fun diagnostic codeActionParams ->
asyncResult {
let implFilePath = codeActionParams.TextDocument.GetFilePath()
let implFileName = Utils.normalizePath implFilePath

let! (implParseAndCheckResults: ParseAndCheckResults, _implLine: string, implSourceText: IFSACSourceText) =
getParseResultsForFile implFileName (protocolPosToPos diagnostic.Range.Start)

let mDiag =
protocolRangeToRange implParseAndCheckResults.GetParseResults.FileName diagnostic.Range

let implTypeName =
(mDiag.Start, implParseAndCheckResults.GetParseResults.ParseTree)
||> ParsedInput.tryPick (fun _ node ->
match node with
| SyntaxNode.SynTypeDefn(SynTypeDefn(
typeInfo = SynComponentInfo(longId = [ typeIdent ])
typeRepr = SynTypeDefnRepr.Simple(simpleRepr = SynTypeDefnSimpleRepr.TypeAbbrev _; range = mBody))) when
Range.equals typeIdent.idRange mDiag
->
Some(typeIdent, mBody)
| _ -> None)

match implTypeName with
| None -> return []
| Some(typeName, mImplBody) ->
match implParseAndCheckResults.TryGetSymbolUseFromIdent implSourceText typeName with
| None -> return []
| Some typeSymbolUse ->
match typeSymbolUse.Symbol with
| :? FSharpEntity as entity ->
match entity.SignatureLocation with
| None -> return []
| Some signatureLocation ->
if not (Utils.isSignatureFile signatureLocation.FileName) then
// A little weird
return []
else
let sigFilePath = $"%s{implFilePath}i"
let sigFileName = Utils.normalizePath sigFilePath

let sigTextDocumentIdentifier: TextDocumentIdentifier =
{ Uri = $"%s{codeActionParams.TextDocument.Uri}i" }

let! (sigParseAndCheckResults: ParseAndCheckResults, _sigLine: string, _sigSourceText: IFSACSourceText) =
getParseResultsForFile sigFileName (Position.mkPos 1 0)

let mSigTypeAbbrev =
(signatureLocation.Start, sigParseAndCheckResults.GetParseResults.ParseTree)
||> ParsedInput.tryPick (fun _path node ->
match node with
| SyntaxNode.SynTypeDefnSig(SynTypeDefnSig(
typeInfo = SynComponentInfo(longId = [ typeIdent ])
typeRepr = SynTypeDefnSigRepr.Simple(repr = SynTypeDefnSimpleRepr.TypeAbbrev _; range = m))) when
Range.equals typeIdent.idRange signatureLocation
->
Some m
| _ -> None)

match mSigTypeAbbrev with
| None -> return []
| Some mSigTypeAbbrev ->
let newText = implSourceText.GetSubTextFromRange mImplBody

return
[ { SourceDiagnostic = None
Title = title
File = sigTextDocumentIdentifier
Edits =
[| { Range = fcsRangeToLsp mSigTypeAbbrev
NewText = newText } |]
Kind = FixKind.Fix } ]
| _ -> return []
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module FsAutoComplete.CodeFix.UpdateTypeAbbreviationInSignatureFile

open FsAutoComplete.CodeFix.Types

val title: string
val fix: getParseResultsForFile: GetParseResultsForFile -> CodeFix
3 changes: 2 additions & 1 deletion src/FsAutoComplete/LspServers/AdaptiveServerState.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1903,7 +1903,8 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac
AdjustConstant.fix tryGetParseAndCheckResultsForFile
UpdateValueInSignatureFile.fix tryGetParseAndCheckResultsForFile
RemoveUnnecessaryParentheses.fix forceFindSourceText
AddTypeAliasToSignatureFile.fix forceGetFSharpProjectOptions tryGetParseAndCheckResultsForFile |])
AddTypeAliasToSignatureFile.fix forceGetFSharpProjectOptions tryGetParseAndCheckResultsForFile
UpdateTypeAbbreviationInSignatureFile.fix tryGetParseAndCheckResultsForFile |])

let forgetDocument (uri: DocumentUri) =
async {
Expand Down
3 changes: 2 additions & 1 deletion test/FsAutoComplete.Tests.Lsp/CodeFixTests/Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3433,4 +3433,5 @@ let tests textFactory state =
removePatternArgumentTests state
UpdateValueInSignatureFileTests.tests state
removeUnnecessaryParenthesesTests state
AddTypeAliasToSignatureFileTests.tests state ]
AddTypeAliasToSignatureFileTests.tests state
UpdateTypeAbbreviationInSignatureFileTests.tests state ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module private FsAutoComplete.Tests.CodeFixTests.UpdateTypeAbbreviationInSignatureFileTests

open Expecto
open Helpers
open Utils.ServerTests
open Utils.CursorbasedTests
open FsAutoComplete.CodeFix

let tests state =
serverTestList (nameof UpdateTypeAbbreviationInSignatureFile) state defaultConfigDto None (fun server ->
[ let selectCodeFix = CodeFix.withTitle UpdateTypeAbbreviationInSignatureFile.title

ftestCaseAsync "first unit test for UpdateTypeAbbreviationInSignatureFile"
<| CodeFix.check
server
"let a$0 b c = ()"
Diagnostics.acceptAll
selectCodeFix
"let Text replaced by UpdateTypeAbbreviationInSignatureFile b c = ()"
])

0 comments on commit 8665f45

Please sign in to comment.