-
Notifications
You must be signed in to change notification settings - Fork 54
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
Add IgnoreUnusedBindingExpression quick-fix #164
base: net203
Are you sure you want to change the base?
Changes from all commits
4616e5d
3b76841
3f6ba0c
4a52a42
8c3cc84
ff0e2d6
897ea98
26ad7b8
e96f5c2
e4bf2ec
3afd493
4de5072
fcc1190
f4f065e
cf9332e
918fcbb
e1403fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes | ||
|
||
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings | ||
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl | ||
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree | ||
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree | ||
open JetBrains.ReSharper.Plugins.FSharp.Psi | ||
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util | ||
open JetBrains.ReSharper.Psi | ||
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree | ||
open JetBrains.ReSharper.Psi.Tree | ||
open JetBrains.ReSharper.Resources.Shell | ||
|
||
type IgnoreUnusedBindingExpressionFix(warning: UnusedValueWarning) = | ||
inherit FSharpQuickFixBase() | ||
|
||
let pat = warning.Pat.IgnoreParentParens() | ||
let binding = BindingNavigator.GetByHeadPattern(pat) | ||
let letOrUseExpr = LetOrUseExprNavigator.GetByBinding(binding) | ||
|
||
let rec getCorrectAnchor (expr: ITreeNode): ITreeNode = | ||
match expr with | ||
| :? ISequentialExpr as seqExpr when not (seqExpr.ExpressionsEnumerable.IsEmpty()) -> | ||
let last = seqExpr.ExpressionsEnumerable.LastOrDefault() | ||
if last :? ILetOrUseExpr then getCorrectAnchor last else last :> _ | ||
|
||
| :? ILetOrUseExpr as letExpr when isNotNull letExpr.InExpression -> getCorrectAnchor letExpr.InExpression | ||
| _ -> | ||
|
||
let exprCopy = expr.Copy() | ||
let seqExpr = ModificationUtil.ReplaceChild(expr, ElementType.SEQUENTIAL_EXPR.Create()) | ||
ModificationUtil.AddChild(seqExpr, exprCopy) | ||
|
||
override x.Text = "Ignore expression" | ||
|
||
override x.IsAvailable _ = | ||
isValid pat && not (pat :? IParametersOwnerPat) && isValid letOrUseExpr && letOrUseExpr.Bindings.Count = 1 && | ||
isValid binding.Expression && not (binding.Expression :? IDoExpr) | ||
|
||
override x.ExecutePsiTransaction _ = | ||
use writeLock = WriteLockCookie.Create(pat.IsPhysical()) | ||
use formatter = FSharpRegistryUtil.AllowFormatterCookie.Create() | ||
|
||
if not (binding.Expression.Type().IsVoid()) then | ||
ignoreInnermostExpression binding.Expression false | ||
|
||
let inExpr = letOrUseExpr.InExpression | ||
let newLine = NewLine(letOrUseExpr.GetLineEnding()) | ||
|
||
let bindingExpr = ModificationUtil.ReplaceChild(letOrUseExpr, binding.Expression) | ||
addNodesAfter (getCorrectAnchor bindingExpr) [ | ||
newLine | ||
newLine | ||
inExpr | ||
] |> ignore |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using JetBrains.ReSharper.Psi; | ||
|
||
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree | ||
{ | ||
internal partial class TryFinallyExpr | ||
{ | ||
public override IType Type() => TryExpression.Type(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using JetBrains.ReSharper.Psi; | ||
|
||
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree | ||
{ | ||
internal partial class TryWithExpr | ||
{ | ||
public override IType Type() => TryExpression.Type(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module Module | ||
|
||
let a = | ||
let b{caret} = | ||
1 | ||
1 | ||
|
||
() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
IFSharpImplFile | ||
INamedModuleDeclaration | ||
FSharpTokenType+ModuleTokenElement(type:MODULE, text:module) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
FSharpIdentifierToken(type:IDENTIFIER, text:Module) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
ILetModuleDecl | ||
FSharpTokenType+LetTokenElement(type:LET, text:let) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
ITopBinding | ||
ITopReferencePat | ||
IExpressionReferenceName | ||
FSharpIdentifierToken(type:IDENTIFIER, text:a) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
FSharpTokenType+EqualsTokenElement(type:EQUALS, text:=) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IChameleonExpression | ||
ISequentialExpr | ||
ILiteralExpr | ||
FSharpToken(type:INT32, text:1) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IBinaryAppExpr | ||
ILiteralExpr | ||
FSharpToken(type:INT32, text:1) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IReferenceExpr | ||
FSharpIdentifierToken(type:SYMBOLIC_OP, text:|>) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IReferenceExpr | ||
FSharpIdentifierToken(type:IDENTIFIER, text:ignore) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IUnitExpr | ||
FSharpTokenType+LparenTokenElement(type:LPAREN, text:() | ||
FSharpTokenType+RparenTokenElement(type:RPAREN, text:)) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module Module | ||
|
||
let a = | ||
1{caret} | ||
1 |> ignore | ||
|
||
() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please make sure it's a correct sequence expression node after the modification, i.e. it should be something like
and not like
It'd be great to have this logic reused in InlineVar refactoring later. We should probably dump the resulting tree in some of the tests with modifications. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module Module | ||
|
||
let a = | ||
let b{caret} = | ||
let c = 1 | ||
c + c | ||
|
||
() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
IFSharpImplFile | ||
INamedModuleDeclaration | ||
FSharpTokenType+ModuleTokenElement(type:MODULE, text:module) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
FSharpIdentifierToken(type:IDENTIFIER, text:Module) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
ILetModuleDecl | ||
FSharpTokenType+LetTokenElement(type:LET, text:let) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
ITopBinding | ||
ITopReferencePat | ||
IExpressionReferenceName | ||
FSharpIdentifierToken(type:IDENTIFIER, text:a) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
FSharpTokenType+EqualsTokenElement(type:EQUALS, text:=) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IChameleonExpression | ||
ILetOrUseExpr | ||
FSharpTokenType+LetTokenElement(type:LET, text:let) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
ILocalBinding | ||
ILocalReferencePat | ||
IExpressionReferenceName | ||
FSharpIdentifierToken(type:IDENTIFIER, text:c) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
FSharpTokenType+EqualsTokenElement(type:EQUALS, text:=) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
ILiteralExpr | ||
FSharpToken(type:INT32, text:1) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
ISequentialExpr | ||
IBinaryAppExpr | ||
IBinaryAppExpr | ||
IReferenceExpr | ||
FSharpIdentifierToken(type:IDENTIFIER, text:c) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IReferenceExpr | ||
FSharpIdentifierToken(type:PLUS, text:+) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IReferenceExpr | ||
FSharpIdentifierToken(type:IDENTIFIER, text:c) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IReferenceExpr | ||
FSharpIdentifierToken(type:SYMBOLIC_OP, text:|>) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IReferenceExpr | ||
FSharpIdentifierToken(type:IDENTIFIER, text:ignore) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IUnitExpr | ||
FSharpTokenType+LparenTokenElement(type:LPAREN, text:() | ||
FSharpTokenType+RparenTokenElement(type:RPAREN, text:)) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module Module | ||
|
||
let a = | ||
let {caret}c = 1 | ||
c + c |> ignore | ||
|
||
() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same as above:
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module Module | ||
|
||
let a = | ||
let b{caret} = | ||
if true then | ||
1 | ||
else | ||
2 | ||
|
||
() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
IFSharpImplFile | ||
INamedModuleDeclaration | ||
FSharpTokenType+ModuleTokenElement(type:MODULE, text:module) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
FSharpIdentifierToken(type:IDENTIFIER, text:Module) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
ILetModuleDecl | ||
FSharpTokenType+LetTokenElement(type:LET, text:let) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
ITopBinding | ||
ITopReferencePat | ||
IExpressionReferenceName | ||
FSharpIdentifierToken(type:IDENTIFIER, text:a) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
FSharpTokenType+EqualsTokenElement(type:EQUALS, text:=) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IChameleonExpression | ||
ISequentialExpr | ||
IBinaryAppExpr | ||
IIfThenElseExpr | ||
FSharpTokenType+IfTokenElement(type:IF, text:if) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
ILiteralExpr | ||
FSharpTokenType+TrueTokenElement(type:TRUE, text:true) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
FSharpTokenType+ThenTokenElement(type:THEN, text:then) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
ILiteralExpr | ||
FSharpToken(type:INT32, text:1) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
FSharpTokenType+ElseTokenElement(type:ELSE, text:else) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
ILiteralExpr | ||
FSharpToken(type:INT32, text:2) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IReferenceExpr | ||
FSharpIdentifierToken(type:SYMBOLIC_OP, text:|>) | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IReferenceExpr | ||
FSharpIdentifierToken(type:IDENTIFIER, text:ignore) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" | ||
Whitespace(type:WHITE_SPACE, text: ) spaces:" " | ||
IUnitExpr | ||
FSharpTokenType+LparenTokenElement(type:LPAREN, text:() | ||
FSharpTokenType+RparenTokenElement(type:RPAREN, text:)) | ||
NewLine(type:NEW_LINE, text:\n) spaces:"\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could save up to a half of the dump by using
do
statement instead of the top-level binding.A bonus point would be replacing the top-level module with a anon module, but it'd require more changes in test project options, so I'd rather do it separately.