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

Change codefix for "unused self reference" to single-underscore #795

Merged
merged 6 commits into from
Jun 25, 2021
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
3 changes: 2 additions & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"sdk": {
"version": "5.0.301"
"version": "5.0.301",
"rollForward": "feature"
}
}
6 changes: 3 additions & 3 deletions src/FsAutoComplete/CodeFixes/UnusedValue.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ let fix (getRangeText: GetRangeText) =
"is unused"
(fun diagnostic codeActionParams ->
asyncResult {
match getRangeText (codeActionParams.TextDocument.GetFilePath() |> Utils.normalizePath) diagnostic.Range with
match getRangeText (codeActionParams.TextDocument.GetFilePath() |> normalizePath) diagnostic.Range with
| Ok unusedExpression ->
match diagnostic.Code with
| Some _ ->
return
[ { SourceDiagnostic = Some diagnostic
File = codeActionParams.TextDocument
Title = "Replace with __"
Title = "Replace with _"
Edits =
[| { Range = diagnostic.Range
NewText = "__" } |]
NewText = "_" } |]
Kind = Refactor } ]
| None ->
let replaceSuggestion = "_"
Expand Down
103 changes: 103 additions & 0 deletions test/FsAutoComplete.Tests.Lsp/CodeFixTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,114 @@ let missingInstanceMemberTests state =
})
]

let unusedValueTests state =
let (|Refactor|_|) title newText action =
match action with
| { Title = title'
Kind = Some "refactor"
Edit = { DocumentChanges = Some [|
{ Edits = [| { NewText = newText' } |] }
|] }
}
when title' = title && newText' = newText -> Some ()
| _ -> None

let (|ActReplace|_|) = (|Refactor|_|) "Replace with _" "_"
baronfel marked this conversation as resolved.
Show resolved Hide resolved

let (|ActPrefix|_|) oldText = (|Refactor|_|) "Prefix with _" $"_{oldText}"

let server =
async {
let path = Path.Combine(__SOURCE_DIRECTORY__, "TestCases", "UnusedValue")
let cfg = { defaultConfigDto with UnusedDeclarationsAnalyzer = Some true }
let! (server, events) = serverInitialize path cfg state
do! waitForWorkspaceFinishedParsing events
let path = Path.Combine(path, "Script.fsx")
let tdop : DidOpenTextDocumentParams = { TextDocument = loadDocument path }
do! server.TextDocumentDidOpen tdop
let! diagnostics =
events
|> waitForFsacDiagnosticsForFile "Script.fsx"
|> AsyncResult.bimap (fun _ -> failtest "Should have had errors") id
return (server, path, diagnostics)
}
|> Async.Cache

let canReplaceUnusedSelfReference = testCaseAsync "can replace unused self-reference" (async {
let! server, file, diagnostics = server
let diagnostic =
diagnostics
|> Array.tryFind (fun d ->
d.Range.Start = { Line = 2; Character = 9 } &&
d.Range.End = { Line = 2; Character = 13 }
) |> Option.defaultWith (fun () -> failwith "could not find diagnostic with expected range")
let detected = {
CodeActionParams.TextDocument = { Uri = Path.FilePathToUri file }
Range = diagnostic.Range
Context = { Diagnostics = [| diagnostic |] }
}
match! server.TextDocumentCodeAction detected with
| Ok (Some (TextDocumentCodeActionResult.CodeActions [| ActReplace |])) -> ()
| Ok other ->
failtestf $"Should have generated _, but instead generated %A{other}"
| Error reason ->
failtestf $"Should have succeeded, but failed with %A{reason}"
})

let canReplaceUnusedBinding = testCaseAsync "can replace unused binding" (async {
let! server, file, diagnostics = server
let diagnostic =
diagnostics
|> Array.tryFind (fun d ->
d.Range.Start = { Line = 9; Character = 4 } &&
d.Range.End = { Line = 9; Character = 7 }
) |> Option.defaultWith (fun () -> failwith "could not find diagnostic with expected range")
let detected = {
CodeActionParams.TextDocument = { Uri = Path.FilePathToUri file }
Range = diagnostic.Range
Context = { Diagnostics = [| diagnostic |] }
}
match! server.TextDocumentCodeAction detected with
| Ok (Some (TextDocumentCodeActionResult.CodeActions [| ActReplace; ActPrefix "six" |])) -> ()
| Ok other ->
failtestf $"Should have generated _, but instead generated %A{other}"
| Error reason ->
failtestf $"Should have succeeded, but failed with %A{reason}"
})

let canReplaceUnusedParameter = testCaseAsync "can replace unused parameter" (async {
let! server, file, diagnostics = server
let diagnostic =
diagnostics
|> Array.tryFind (fun d ->
d.Range.Start = { Line = 15; Character = 16 } &&
d.Range.End = { Line = 15; Character = 21 }
) |> Option.defaultWith (fun () -> failwith "could not find diagnostic with expected range")
let detected = {
CodeActionParams.TextDocument = { Uri = Path.FilePathToUri file }
Range = diagnostic.Range
Context = { Diagnostics = [| diagnostic |] }
}
match! server.TextDocumentCodeAction detected with
| Ok (Some (TextDocumentCodeActionResult.CodeActions [| ActReplace; ActPrefix "three" |])) -> ()
| Ok other ->
failtestf $"Should have generated _, but instead generated %A{other}"
| Error reason ->
failtestf $"Should have succeeded, but failed with %A{reason}"
})

testList "unused value" [
canReplaceUnusedSelfReference
canReplaceUnusedBinding
canReplaceUnusedParameter
]

let tests state = testList "codefix tests" [
abstractClassGenerationTests state
generateMatchTests state
missingFunKeywordTests state
outerBindingRecursiveTests state
nameofInsteadOfTypeofNameTests state
missingInstanceMemberTests state
unusedValueTests state
]
5 changes: 5 additions & 0 deletions test/FsAutoComplete.Tests.Lsp/Helpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@ let waitForParseResultsForFile file =
>> diagnosticsToResult
>> Async.AwaitObservable

let waitForFsacDiagnosticsForFile file =
fsacDiagnostics file
>> diagnosticsToResult
>> Async.AwaitObservable

let waitForParsedScript (event: ClientEvents) =
event
|> typedEvents<LanguageServerProtocol.Types.PublishDiagnosticsParams> "textDocument/publishDiagnostics"
Expand Down
16 changes: 16 additions & 0 deletions test/FsAutoComplete.Tests.Lsp/TestCases/UnusedValue/Script.fsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
(* unused self reference *)
type MyClass() =
member this.DoAThing() = ()


(*
replace usused binding with _
prefix _ to unused binding
*)
let six = 6

(*
replace usused function parameter with _
prefix _ to unused function parameter
*)
let add one two three = one + two