Skip to content

Commit

Permalink
Traverse from the outside in.
Browse files Browse the repository at this point in the history
  • Loading branch information
nojaf committed Mar 25, 2024
1 parent 8bd8182 commit a6e028f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 48 deletions.
50 changes: 16 additions & 34 deletions src/FsAutoComplete/CodeFixes/NegateBooleanExpression.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ open FsAutoComplete.LspHelpers

let title = "Negate boolean expression"

let booleanOperators = set [ "||"; "&&"; "=" ] // TODO: probably some others
let booleanOperators = set [ "||"; "&&"; "="; "<>" ]

[<return: Struct>]
let (|BooleanOperator|_|) =
Expand Down Expand Up @@ -76,65 +76,47 @@ let fix (getParseResultsForFile: GetParseResultsForFile) : CodeFix =
getParseResultsForFile fileName fcsPos

let optFixData =
ParsedInput.tryNode fcsPos parseAndCheckResults.GetParseResults.ParseTree
|> Option.bind (fun (node, path) ->

(fcsPos, parseAndCheckResults.GetParseResults.ParseTree)
||> ParsedInput.tryPick (fun path node ->
match node with
| SyntaxNode.SynExpr e ->
match e, path with
// &&
| BooleanOperator operator,
SyntaxNode.SynExpr(SynExpr.App(isInfix = true)) :: SyntaxNode.SynExpr(SynExpr.App(isInfix = false) as e) :: rest ->
match e with
// a && b
| SynExpr.App(isInfix = false; funcExpr = SynExpr.App(isInfix = true; funcExpr = BooleanOperator operator)) ->
Some
{ Expr = e
Ident = operator
Path = rest
NeedsParensAfterNot = true }

// $0X().Y
| SynExpr.Ident _,
SyntaxNode.SynExpr(SynExpr.App _) :: SyntaxNode.SynExpr(SynExpr.DotGet(
longDotId = LastIdentFromSynLongIdent ident) as e) :: rest ->
Some
{ Expr = e
Ident = ident
Path = rest
Path = path
NeedsParensAfterNot = true }

// X$0()
| SynExpr.Ident ident, SyntaxNode.SynExpr(SynExpr.App _ as e) :: rest ->
Some
{ Expr = e
Ident = ident
Path = rest
NeedsParensAfterNot = true }
// X().Y()
| SynExpr.App(funcExpr = SynExpr.DotGet(longDotId = LastIdentFromSynLongIdent ident))

// X()$0
| (SynExpr.Const(constant = SynConst.Unit) | SynExpr.Paren _),
SyntaxNode.SynExpr(SynExpr.App(funcExpr = SynExpr.Ident ident) as e) :: rest ->
// X().Y
| SynExpr.DotGet(longDotId = LastIdentFromSynLongIdent ident) ->
Some
{ Expr = e
Ident = ident
Path = rest
Path = path
NeedsParensAfterNot = true }

// X().Y$0
| SynExpr.DotGet(longDotId = LastIdentFromSynLongIdent ident), path ->
// X()
| SynExpr.App(funcExpr = SynExpr.Ident ident) ->
Some
{ Expr = e
Ident = ident
Path = path
NeedsParensAfterNot = true }

// a.Y
| SynExpr.LongIdent(isOptional = false; longDotId = LastIdentFromSynLongIdent ident), path ->
| SynExpr.LongIdent(isOptional = false; longDotId = LastIdentFromSynLongIdent ident) ->
Some
{ Expr = e
Ident = ident
Path = path
NeedsParensAfterNot = false }
// a
| SynExpr.Ident ident, path ->
| SynExpr.Ident ident ->
Some
{ Expr = e
Ident = ident
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let tests state =
(fun server ->
[ let selectCodeFix = CodeFix.withTitle NegateBooleanExpression.title

ftestCaseAsync "negate single identifier"
testCaseAsync "negate single identifier"
<| CodeFix.check
server
"let a = false
Expand All @@ -26,7 +26,7 @@ let b = a$0"
"let a = false
let b = not a"

ftestCaseAsync "negate boolean expression"
testCaseAsync "negate boolean expression"
<| CodeFix.check
server
"let a = false
Expand All @@ -36,7 +36,7 @@ let b = a $0|| false"
"let a = false
let b = not (a || false)"

ftestCaseAsync "negate longdotident expression"
testCaseAsync "negate longdotident expression"
<| CodeFix.check
server
"
Expand All @@ -52,7 +52,7 @@ module A =
let b = not A.a"

ftestCaseAsync "negate record field"
testCaseAsync "negate record field"
<| CodeFix.check
server
"
Expand All @@ -68,7 +68,7 @@ type X = { Y: bool }
let a = { Y = true }
let b = not a.Y"

ftestCaseAsync "negate class property"
testCaseAsync "negate class property"
<| CodeFix.check
server
"
Expand All @@ -84,7 +84,7 @@ type X() =
let b = not (X().Y)"

ftestCaseAsync "negate class property, cursor at start"
testCaseAsync "negate class property, cursor at start"
<| CodeFix.check
server
"
Expand All @@ -100,7 +100,7 @@ type X() =
let b = not (X().Y)"

ftestCaseAsync "negate unit function call"
testCaseAsync "negate unit function call"
<| CodeFix.check
server
"
Expand All @@ -112,7 +112,7 @@ let b = a$0 ()"
let a () = false
let b = not (a ())"

ftestCaseAsync "negate unit function call, cursor at end"
testCaseAsync "negate unit function call, cursor at end"
<| CodeFix.check
server
"
Expand All @@ -124,7 +124,7 @@ let b = a ()$0"
let a () = false
let b = not (a ())"

ftestCaseAsync "negate unit function call, cursor at end"
testCaseAsync "negate non-unit function call, cursor at end"
<| CodeFix.check
server
"
Expand All @@ -136,19 +136,19 @@ let b = a 4$0"
let a _ = false
let b = not (a 4)"

ftestCaseAsync "negate unit function call, cursor at end"
testCaseAsync "negate non-unit function call, cursor in middle"
<| CodeFix.check
server
"
let a _ = false
let b = a 4$0"
let b = a $0 4"
Diagnostics.acceptAll
selectCodeFix
"
let a _ = false
let b = not (a 4)"
let b = not (a 4)"

ftestCaseAsync "negate unit member invocation"
testCaseAsync "negate unit member invocation"
<| CodeFix.check
server
"
Expand All @@ -164,7 +164,7 @@ type X() =
let b = not (X().Y())"

ftestCaseAsync "negate unit member invocation, cursor at end"
testCaseAsync "negate unit member invocation, cursor at end"
<| CodeFix.check
server
"
Expand Down

0 comments on commit a6e028f

Please sign in to comment.