mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
inline chained calls: ensure qualifiers with side effects are preserved (IDEA-199990; IDEA-147989)
This commit is contained in:
+3
-3
@@ -54,9 +54,9 @@ public class RemoveUnusedVariableUtil {
|
||||
return !writes.isEmpty();
|
||||
}
|
||||
|
||||
static PsiElement replaceElementWithExpression(PsiExpression expression,
|
||||
PsiElementFactory factory,
|
||||
PsiElement element) throws IncorrectOperationException {
|
||||
public static PsiElement replaceElementWithExpression(PsiExpression expression,
|
||||
PsiElementFactory factory,
|
||||
PsiElement element) throws IncorrectOperationException {
|
||||
PsiElement elementToReplace = element;
|
||||
PsiElement expressionToReplaceWith = expression;
|
||||
if (element.getParent() instanceof PsiExpressionStatement) {
|
||||
|
||||
@@ -1026,8 +1026,14 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
|
||||
private void inlineParmOrThisVariable(PsiLocalVariable variable, boolean strictlyFinal) throws IncorrectOperationException {
|
||||
PsiReference firstRef = ReferencesSearch.search(variable).findFirst();
|
||||
|
||||
PsiExpression initializer = variable.getInitializer();
|
||||
if (firstRef == null) {
|
||||
variable.getParent().delete(); //Q: side effects?
|
||||
if (initializer != null && SideEffectChecker.mayHaveSideEffects(initializer)) {
|
||||
RemoveUnusedVariableUtil.replaceElementWithExpression(initializer, PsiElementFactory.SERVICE.getInstance(myProject), variable);
|
||||
}
|
||||
else {
|
||||
variable.getParent().delete();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1043,7 +1049,6 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
PsiExpression initializer = variable.getInitializer();
|
||||
boolean shouldBeFinal = variable.hasModifierProperty(PsiModifier.FINAL) && strictlyFinal;
|
||||
if (canInlineParmOrThisVariable(initializer, shouldBeFinal, strictlyFinal, refs.size(), isAccessedForWriting)) {
|
||||
if (shouldBeFinal) {
|
||||
@@ -1153,7 +1158,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
|
||||
return false;
|
||||
}
|
||||
else if (initializer instanceof PsiCallExpression) {
|
||||
if (accessCount > 1) return false;
|
||||
if (accessCount != 1) return false;//don't allow deleting probable side effects or multiply those side effects
|
||||
if (initializer instanceof PsiNewExpression) {
|
||||
final PsiArrayInitializerExpression arrayInitializer = ((PsiNewExpression)initializer).getArrayInitializer();
|
||||
if (arrayInitializer != null) {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
class MyObjBuilder {
|
||||
private NewType memberVar1;
|
||||
|
||||
public NewType convertToNewType(LegacyType arg) {
|
||||
return new NewType();
|
||||
}
|
||||
|
||||
public MyObjBuilder memberVar1(LegacyType arg) {
|
||||
memberVar1(convertToNewType(arg));
|
||||
return this;
|
||||
}
|
||||
|
||||
public MyObjBuilder memberVar1(NewType arg) {
|
||||
this.memberVar1 = arg;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MyObj memberVar2() {
|
||||
return new MyObj();
|
||||
}
|
||||
}
|
||||
|
||||
class Main {
|
||||
public static void main(String[] args) {
|
||||
LegacyType lt = new LegacyType();
|
||||
MyObj obj = MyObj.builder()
|
||||
.mem<caret>berVar1(lt)
|
||||
.memberVar2();
|
||||
}
|
||||
}
|
||||
|
||||
class NewType {
|
||||
}
|
||||
|
||||
class MyObj {
|
||||
public static MyObjBuilder builder() {
|
||||
return new MyObjBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
class LegacyType {}
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
class MyObjBuilder {
|
||||
private NewType memberVar1;
|
||||
|
||||
public NewType convertToNewType(LegacyType arg) {
|
||||
return new NewType();
|
||||
}
|
||||
|
||||
public MyObjBuilder memberVar1(NewType arg) {
|
||||
this.memberVar1 = arg;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MyObj memberVar2() {
|
||||
return new MyObj();
|
||||
}
|
||||
}
|
||||
|
||||
class Main {
|
||||
public static void main(String[] args) {
|
||||
LegacyType lt = new LegacyType();
|
||||
MyObjBuilder myObjBuilder = MyObj.builder();
|
||||
myObjBuilder.memberVar1(myObjBuilder.convertToNewType(lt));
|
||||
MyObj obj = myObjBuilder
|
||||
.memberVar2();
|
||||
}
|
||||
}
|
||||
|
||||
class NewType {
|
||||
}
|
||||
|
||||
class MyObj {
|
||||
public static MyObjBuilder builder() {
|
||||
return new MyObjBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
class LegacyType {}
|
||||
@@ -4,6 +4,7 @@ import java.util.function.Function;
|
||||
class B<T> {
|
||||
|
||||
void foo(B<? extends CharSequence> sequences){
|
||||
sequences.bar(t -> t);
|
||||
Object t1 = null;
|
||||
}
|
||||
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
class Outer {
|
||||
|
||||
public void checkIt() {
|
||||
Inner inner = new Inner();
|
||||
inner.step1().step2().st<caret>ep3();
|
||||
System.out.println(" INNER.I = " + inner.i);
|
||||
}
|
||||
|
||||
class Inner {
|
||||
int i = 3;
|
||||
|
||||
public Inner step1() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Inner step2() {
|
||||
i = 2;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void step3() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
class Outer {
|
||||
|
||||
public void checkIt() {
|
||||
Inner inner = new Inner();
|
||||
inner.step1().step2();
|
||||
System.out.println(" INNER.I = " + inner.i);
|
||||
}
|
||||
|
||||
class Inner {
|
||||
int i = 3;
|
||||
|
||||
public Inner step1() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Inner step2() {
|
||||
i = 2;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -416,6 +416,14 @@ public class InlineMethodTest extends LightRefactoringTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testChainedBuilderCall() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testMissedQualifierWithSideEffectsOnInliningEmptyMethod() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNotTailCallInsideIf() {
|
||||
doTestAssertBadReturn();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user