Skip to content

Commit

Permalink
add codefix "replace dotLambda to lambda" (#1264)
Browse files Browse the repository at this point in the history
* add replace dotLambda to lambda

* fix test

* fix
  • Loading branch information
ijklam authored Apr 15, 2024
1 parent b5fa4aa commit fe9eae5
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 7 deletions.
51 changes: 46 additions & 5 deletions src/FsAutoComplete/CodeFixes/ReplaceLambdaWithDotLambda.fs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ type ReplaceInfo =
| RawLambda of range
| ParenLambda of lpr: range * lambdaRange: range * rpr: range

[<RequireQualifiedAccess; NoComparison; NoEquality; Struct>]
type DotLambdaReplaceInfo =
| NotNeedParen of range
| NeedParen of underscoreRange: range * endRange: range

[<RequireQualifiedAccess; NoComparison; NoEquality; Struct>]
type FixType =
| ReplaceToDotLambda of replaceInfo: ReplaceInfo
| ReplaceToLambda of dotLambdaReplaceInfo: DotLambdaReplaceInfo

let tryFindLambda (cursor: pos) (tree: ParsedInput) =
(cursor, tree)
||> ParsedInput.tryPick (fun path node ->
Expand All @@ -46,12 +56,24 @@ let tryFindLambda (cursor: pos) (tree: ParsedInput) =

match List.tryHead path with
| Some(SyntaxNode.SynExpr(SynExpr.Paren(leftParenRange = lpr; rightParenRange = Some rpr))) ->
Some(ReplaceInfo.ParenLambda(lpr, mLambda, rpr))
| _ -> Some(ReplaceInfo.RawLambda mLambda)
ReplaceInfo.ParenLambda(lpr, mLambda, rpr) |> FixType.ReplaceToDotLambda |> Some
| _ -> ReplaceInfo.RawLambda mLambda |> FixType.ReplaceToDotLambda |> Some
| _ -> None

| SyntaxNode.SynExpr(SynExpr.DotLambda(
range = mLambda; trivia = { FSharp.Compiler.SyntaxTrivia.SynExprDotLambdaTrivia.UnderscoreRange = m })) ->

match List.tryHead path with
| Some(SyntaxNode.SynExpr(SynExpr.Paren _)) ->
DotLambdaReplaceInfo.NotNeedParen m |> FixType.ReplaceToLambda |> Some
| _ ->
DotLambdaReplaceInfo.NeedParen(m, mkRange m.FileName mLambda.End mLambda.End)
|> FixType.ReplaceToLambda
|> Some
| _ -> None)

let title = "Replace lambda with _."
let titleReplaceToDotLambda = "Replace lambda with _."
let titleReplaceToLambda = "Replace _. with lambda"

let languageFeature = lazy LanguageFeatureShim("AccessorFunctionShorthand")

Expand All @@ -72,7 +94,7 @@ let fix (getLanguageVersion: GetLanguageVersion) (getParseResultsForFile: GetPar

match tryFindLambda fcsPos parseAndCheckResults.GetParseResults.ParseTree with
| None -> return []
| Some replaceInfo ->
| Some(FixType.ReplaceToDotLambda replaceInfo) ->
let edits =
match replaceInfo with
| ReplaceInfo.RawLambda m ->
Expand All @@ -88,7 +110,26 @@ let fix (getLanguageVersion: GetLanguageVersion) (getParseResultsForFile: GetPar

return
[ { SourceDiagnostic = None
Title = title
Title = titleReplaceToDotLambda
File = codeActionParams.TextDocument
Edits = edits
Kind = FixKind.Fix } ]
| Some(FixType.ReplaceToLambda replaceInfo) ->
let edits =
match replaceInfo with
| DotLambdaReplaceInfo.NeedParen(m, mEnd) ->
[| { Range = fcsRangeToLsp m
NewText = "(fun _i -> _i" }
{ Range = fcsRangeToLsp mEnd
NewText = ")" } |]

| DotLambdaReplaceInfo.NotNeedParen m ->
[| { Range = fcsRangeToLsp m
NewText = "fun _i -> _i" } |]

return
[ { SourceDiagnostic = None
Title = titleReplaceToLambda
File = codeActionParams.TextDocument
Edits = edits
Kind = FixKind.Fix } ]
Expand Down
3 changes: 2 additions & 1 deletion src/FsAutoComplete/CodeFixes/ReplaceLambdaWithDotLambda.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ module FsAutoComplete.CodeFix.ReplaceLambdaWithDotLambda

open FsAutoComplete.CodeFix.Types

val title: string
val titleReplaceToDotLambda: string
val titleReplaceToLambda: string
val fix: getLanguageVersion: GetLanguageVersion -> getParseResultsForFile: GetParseResultsForFile -> CodeFix
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ open FsAutoComplete.CodeFix

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

testCaseAsync "Simple property"
<| CodeFix.check
Expand Down Expand Up @@ -42,4 +42,39 @@ let tests state =
selectCodeFix
"let a6 = _.ToString()"

// -------------------- from dot lambda to lambda test ----------------------

let selectCodeFix = CodeFix.withTitle ReplaceLambdaWithDotLambda.titleReplaceToLambda

testCaseAsync "Simple property (from dot lambda to lambda)"
<| CodeFix.check
server
"let x = \"\" |> $0_.Length"
Diagnostics.acceptAll
selectCodeFix
"let x = \"\" |> (fun _i -> _i.Length)"

testCaseAsync "Property of application (from dot lambda to lambda)"
<| CodeFix.check
server
"let a5 : {| Foo : int -> {| X : string |} |} -> string = _.$0Foo(5).X"
Diagnostics.acceptAll
selectCodeFix
"let a5 : {| Foo : int -> {| X : string |} |} -> string = (fun _i -> _i.Foo(5).X)"

testCaseAsync "Application (from dot lambda to lambda)"
<| CodeFix.check
server
"let a6 = [1] |> List.map _$0.ToString()"
Diagnostics.acceptAll
selectCodeFix
"let a6 = [1] |> List.map (fun _i -> _i.ToString())"

testCaseAsync "fun x -> x.ToString() (from dot lambda to lambda)"
<| CodeFix.check
server
"let a6 = _.ToStri$0ng()"
Diagnostics.acceptAll
selectCodeFix
"let a6 = (fun _i -> _i.ToString())"
])

0 comments on commit fe9eae5

Please sign in to comment.