- 
                Notifications
    
You must be signed in to change notification settings  - Fork 56
 
Add IgnoreUnusedBindingExpression quick-fix #164
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
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" | 
Uh oh!
There was an error while loading. Please reload this page.
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
dostatement 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.