-
Notifications
You must be signed in to change notification settings - Fork 52
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
Remove unused record named pattern quick fix #463
base: net233
Are you sure you want to change the base?
Remove unused record named pattern quick fix #463
Conversation
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.
@edgarfgp This is nice work!
The quick fix may remove extra nodes in some cases, and it would be better not to do it. I left a suggestion on how to better calculate the tree range to remove.
ReSharper.FSharp/src/FSharp.Psi.Intentions/src/QuickFixes/RemoveUnusedNamedPatternFix.fs
Outdated
Show resolved
Hide resolved
...a/features/quickFixes/removeUnusedNamedPattern/Unused record named pattern first position.fs
Outdated
Show resolved
Hide resolved
let rangeToDelete = | ||
let rangeStart = fieldPat | ||
let rangeEnd = | ||
nextFieldPat.PrevSibling | ||
TreeRange(rangeStart, rangeEnd) |
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.
This approach doesn't look at what could be between the field patterns, and there are some important cases to consider when using it:
We probably don't want to remove the new line between the fields here:
match r with
| { F1 = 1; F2 = f2
F3 = 3; F4 = 4 } -> ()
While here we would not want to keep an empty line:
match r with
| { F1 = 1
F2 = f2
F3 = 3 } -> ()
What I'd suggest trying to do here is this:
- get the field pattern node
- check if it's the last field pattern on the line, i.e. if
fieldPat.EndLine <> nextPattern.StartLine
- if it's the last one: try to go left from it and possibly include the previous new line token, like in the last example, using
getFirstMatchingNodeBefore isInlineSpace fieldPat |> getThisOrPrevNewLine
helpers
- if it's the last one: try to go left from it and possibly include the previous new line token, like in the last example, using
- try to move to the right using
getLastMatchingNodeAfter isInlineSpace
Please check existing usages of these helpers.
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.
Some more cases to add a test for:
match r with
| { F1 = 1; F2 = 2
F3 = f3; F4 = 4 } -> ()
match r with
| { F1 = 1; F2 = 2
F3 = f3 } -> ()
match r with
| { F1 = 1; F2 = f2 // comment
F3 = 3 } -> ()
ReSharper.FSharp/src/FSharp.Psi.Intentions/src/QuickFixes/RemoveUnusedNamedPatternFix.fs
Outdated
Show resolved
Hide resolved
ReSharper.FSharp/src/FSharp.Psi.Services/src/Daemon/Highlightings/FcsErrors.xml
Outdated
Show resolved
Hide resolved
ReSharper.FSharp/src/FSharp.Psi.Intentions/src/QuickFixes/RemoveUnusedNamedPatternFix.fs
Outdated
Show resolved
Hide resolved
7032111
to
d1e2379
Compare
a693bd6
to
f47d73a
Compare
f47d73a
to
beaf9f3
Compare
919f0f5
to
f889b43
Compare
.../quickFixes/removeUnusedNamedPattern/Unused record named pattern with a single field.fs.gold
Outdated
Show resolved
Hide resolved
type R = | R of a: int | ||
match R(0) with | ||
| _{caret} -> () |
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.
This changes the code meaning when there're other branches or union cases (included when they are added in the future). This is the case we've discussed previously. You should not remove the whole union case pattern when removing its last field.
In the following example the value of x
is going to be different after this quick fix is applied:
type U =
| A of i: int
| B
let x =
match B with
| A(i = i) -> 1
| B -> 2
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.
Ok I see. So in this case after applying the quick fix the result would be ?:
let x =
match B with
| A _ -> 1
| B -> 2
let fieldPatterns = | ||
NamedPatternsListPatNavigator.GetByFieldPattern(warning.Pat.IgnoreInnerParens().Parent.As<IFieldPat>()).FieldPatterns |
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.
warning.Pat.IgnoreInnerParens()
Could you explain why this was needed, please?
UnusedValueWarning
is currently only created with IReferencePattern
, never with IParenPat
.
resharper-fsharp/ReSharper.FSharp/src/FSharp.Psi.Daemon/src/Stages/FcsErrorsStageProcessBase.fs
Line 293 in c62d6a9
UnusedValueWarning(refPat) :> _ |
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.
warning.Pat.IgnoreInnerParens().Parent
Please use FieldPatNavigator
, not the lower level direct parent access.
override x.Text = "Remove unused value" | ||
|
||
override x.IsAvailable _ = | ||
fieldPatterns |> Seq.exists isValid |
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.
What checking other patterns is needed for?
fieldPatterns |> Seq.exists isValid | ||
|
||
override x.ExecutePsiTransaction(_, _) = | ||
let fieldPat = warning.Pat.IgnoreInnerParens().Parent.As<IFieldPat>() |
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.
Please use FieldPatNavigator
instead of accessing Parent
directly.
| :? INamedUnionCaseFieldsPat as fieldPat -> | ||
let factory = fieldPat.CreateElementFactory() | ||
let wildPat = factory.CreateWildPat() | ||
replace (fieldPat.IgnoreParentChameleonExpr()) wildPat |
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.
Why IgnoreParentChameleonExpr
is called here?
To my knowledge, there should be no cases where a fieldPat
may be a direct child of a chameleon expression node.
b45e72b
to
f9d776b
Compare
This PR adds a new quick to
Remove unused record named pattern quick fix
. This can be extended to work with named union types in a separate PR :)