Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
5550: INSP: add quick fix to convert immutable reference to mutable reference r=mchernyavsky a=Kobzol This PR adds a quick fix to convert an immutable reference to a mutable one: ![refmut](https://user-images.githubusercontent.com/4539057/84370594-c125ff80-abd8-11ea-96ff-dbd407d3455c.gif) The last test should be enabled if/after #5548 gets merged. Umbrella issue: #1730 Fixes: #2472 Co-authored-by: Jakub Beránek <berykubik@gmail.com>
- Loading branch information
Showing
3 changed files
with
133 additions
and
6 deletions.
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
src/main/kotlin/org/rust/ide/inspections/fixes/ChangeRefToMutableFix.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.rust.ide.inspections.fixes | ||
|
||
import com.intellij.codeInspection.LocalQuickFixOnPsiElement | ||
import com.intellij.openapi.project.Project | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.PsiFile | ||
import org.rust.lang.core.psi.RsPsiFactory | ||
import org.rust.lang.core.psi.RsUnaryExpr | ||
import org.rust.lang.core.psi.ext.RsElement | ||
import org.rust.lang.core.psi.ext.UnaryOperator | ||
import org.rust.lang.core.psi.ext.operatorType | ||
|
||
|
||
/** | ||
* Fix that converts the given immutable reference to a mutable reference. | ||
* @param expr An element, that represents an immutable reference. | ||
*/ | ||
class ChangeRefToMutableFix(expr: RsElement) : LocalQuickFixOnPsiElement(expr) { | ||
override fun getText() = "Change reference to mutable" | ||
override fun getFamilyName() = text | ||
|
||
override fun invoke(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement) { | ||
val ref = startElement as? RsUnaryExpr ?: return | ||
if (ref.operatorType != UnaryOperator.REF) return | ||
val innerExpr = ref.expr ?: return | ||
|
||
val mutableExpr = RsPsiFactory(project).tryCreateExpression("&mut ${innerExpr.text}") ?: return | ||
startElement.replace(mutableExpr) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
src/test/kotlin/org/rust/ide/inspections/typecheck/ChangeRefToMutableFixTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.rust.ide.inspections.typecheck | ||
|
||
import org.rust.ide.inspections.RsInspectionsTestBase | ||
import org.rust.ide.inspections.RsTypeCheckInspection | ||
|
||
class ChangeRefToMutableFixTest : RsInspectionsTestBase(RsTypeCheckInspection::class) { | ||
fun `test simple`() = checkFixByText("Change reference to mutable", """ | ||
fn foo(t: &mut u32) {} | ||
fn bar() { | ||
let mut x: u32 = 5; | ||
foo(/*caret*/<error>&x</error>); | ||
} | ||
""", """ | ||
fn foo(t: &mut u32) {} | ||
fn bar() { | ||
let mut x: u32 = 5; | ||
foo(&mut x); | ||
} | ||
""") | ||
|
||
fun `test immutable variable`() = checkFixByText("Change reference to mutable", """ | ||
fn foo(t: &mut u32) {} | ||
fn bar() { | ||
let x: u32 = 5; | ||
foo(/*caret*/<error>&x</error>); | ||
} | ||
""", """ | ||
fn foo(t: &mut u32) {} | ||
fn bar() { | ||
let x: u32 = 5; | ||
foo(&mut x); | ||
} | ||
""") | ||
|
||
fun `test nested references`() = checkFixByText("Change reference to mutable", """ | ||
fn foo(t: &mut &u32) {} | ||
fn bar() { | ||
let mut x: u32 = 5; | ||
foo(/*caret*/<error>&x</error>); | ||
} | ||
""", """ | ||
fn foo(t: &mut &u32) {} | ||
fn bar() { | ||
let mut x: u32 = 5; | ||
foo(&mut x); | ||
} | ||
""") | ||
|
||
fun `test unknown inner type`() = checkFixByText("Change reference to mutable", """ | ||
struct S<T>(T); | ||
impl<T> S<T> { | ||
fn new() -> Self { unreachable!() } | ||
} | ||
fn foo(t: &mut S<u32>) {} | ||
fn bar() { | ||
let mut x = S::new(); | ||
foo(/*caret*/<error>&x</error>); | ||
} | ||
""", """ | ||
struct S<T>(T); | ||
impl<T> S<T> { | ||
fn new() -> Self { unreachable!() } | ||
} | ||
fn foo(t: &mut S<u32>) {} | ||
fn bar() { | ||
let mut x = S::new(); | ||
foo(&mut x); | ||
} | ||
""") | ||
|
||
fun `test unavailable on mut reference`() = checkFixIsUnavailable("Change reference to mutable", """ | ||
fn foo(t: &mut u32) {} | ||
fn bar() { | ||
let mut x: u32 = 5; | ||
foo(/*caret*/&mut x); | ||
} | ||
""") | ||
} |