mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
type migration: migrate getter return type and setter parameter anyway if initial- and target-types are assignable IDEA-119901
This commit is contained in:
+42
-8
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.refactoring.typeMigration;
|
||||
|
||||
import com.intellij.codeInsight.generation.GetterSetterPrototypeProvider;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -22,10 +23,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -83,7 +81,7 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor {
|
||||
break;
|
||||
|
||||
case TypeInfection.LEFT_INFECTED:
|
||||
myLabeler.migrateExpressionType(rExpression, ltype, myStatement, TypeConversionUtil.isAssignable(ltype, rtype), true);
|
||||
myLabeler.migrateExpressionType(rExpression, ltype, myStatement, TypeConversionUtil.isAssignable(ltype, rtype) && !isSetter(expression), true);
|
||||
break;
|
||||
|
||||
case TypeInfection.RIGHT_INFECTED:
|
||||
@@ -178,7 +176,7 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReturnStatement(PsiReturnStatement statement) { // has to change method return type corresponding to new value type
|
||||
public void visitReturnStatement(final PsiReturnStatement statement) { // has to change method return type corresponding to new value type
|
||||
super.visitReturnStatement(statement);
|
||||
|
||||
final PsiElement method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class, PsiLambdaExpression.class);
|
||||
@@ -191,9 +189,8 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor {
|
||||
}
|
||||
final PsiType returnType = ((PsiMethod)method).getReturnType();
|
||||
final PsiType valueType = myTypeEvaluator.evaluateType(value);
|
||||
|
||||
if (returnType != null && valueType != null) {
|
||||
if (!myLabeler.addMigrationRoot(method, valueType, myStatement, TypeConversionUtil.isAssignable(returnType, valueType), true, true)
|
||||
if (!myLabeler.addMigrationRoot(method, valueType, myStatement, TypeConversionUtil.isAssignable(returnType, valueType) && !isGetter(value, method), true, true)
|
||||
&& TypeMigrationLabeler.typeContainsTypeParameters(returnType)) {
|
||||
value.accept(this);
|
||||
}
|
||||
@@ -594,4 +591,41 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor {
|
||||
return (left.isChanged() ? 1 : 0) + (right.isChanged() ? 2 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSetter(PsiAssignmentExpression expression) {
|
||||
final PsiExpression lExpression = expression.getLExpression();
|
||||
if (lExpression instanceof PsiReferenceExpression) {
|
||||
final PsiElement resolved = ((PsiReferenceExpression)lExpression).resolve();
|
||||
if (resolved instanceof PsiField) {
|
||||
PsiField field = (PsiField) resolved;
|
||||
final NavigatablePsiElement containingMethod = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, PsiLambdaExpression.class);
|
||||
if (containingMethod instanceof PsiMethod) {
|
||||
final PsiMethod setter = PropertyUtil.findPropertySetter(field.getContainingClass(), field.getName(), field.hasModifierProperty(PsiModifier.STATIC), false);
|
||||
if (containingMethod.isEquivalentTo(setter)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isGetter(PsiExpression returnValue, PsiElement containingMethod) {
|
||||
if (returnValue instanceof PsiReferenceExpression) {
|
||||
final PsiElement resolved = ((PsiReferenceExpression)returnValue).resolve();
|
||||
if (resolved instanceof PsiField) {
|
||||
PsiField field = (PsiField)resolved;
|
||||
final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
|
||||
final PsiMethod[] getters = GetterSetterPrototypeProvider.findGetters(field.getContainingClass(), field.getName(), isStatic);
|
||||
if (getters != null) {
|
||||
for (PsiMethod getter : getters) {
|
||||
if (containingMethod.isEquivalentTo(getter)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,6 +906,14 @@ public class TypeMigrationTest extends TypeMigrationTestBase {
|
||||
doTestFirstParamType("meth", myFactory.createTypeFromText("java.lang.String", null), myFactory.createTypeFromText("java.lang.Long", null));
|
||||
}
|
||||
|
||||
public void testAssignableGetter() {
|
||||
doTestFieldType("foo", "Test", PsiType.LONG, PsiType.INT);
|
||||
}
|
||||
|
||||
public void testAssignableSetter() {
|
||||
doTestFieldType("foo", "Test", PsiType.INT, PsiType.LONG);
|
||||
}
|
||||
|
||||
private void doTestForeachParameter(final PsiType rootType, final PsiType migrationType) {
|
||||
start(new RulesProvider() {
|
||||
@Override
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
Types:
|
||||
PsiField:foo : int
|
||||
PsiLocalVariable:someNumber1 : int
|
||||
PsiMethod:getFoo : int
|
||||
PsiMethodCallExpression:someClass.getFoo() : int
|
||||
PsiParameter:foo : int
|
||||
PsiReferenceExpression:foo : int
|
||||
PsiReferenceExpression:foo : int
|
||||
PsiReferenceExpression:someNumber1 : int
|
||||
PsiReferenceExpression:this.foo : int
|
||||
|
||||
Conversions:
|
||||
|
||||
New expression type changes:
|
||||
Fails:
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
public class Test {
|
||||
|
||||
private int foo;
|
||||
|
||||
public int getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(int foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
static void m(Test someClass) {
|
||||
long someNumber = someClass.getFoo();
|
||||
System.out.println(someNumber + 10);
|
||||
|
||||
int someNumber1 = 1123;
|
||||
someClass.setFoo(someNumber1);
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
public class Test {
|
||||
|
||||
private long foo;
|
||||
|
||||
public long getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(long foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
static void m(Test someClass) {
|
||||
long someNumber = someClass.getFoo();
|
||||
System.out.println(someNumber + 10);
|
||||
|
||||
long someNumber1 = 1123;
|
||||
someClass.setFoo(someNumber1);
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
Types:
|
||||
PsiField:foo : long
|
||||
PsiLocalVariable:someNumber : long
|
||||
PsiMethod:getFoo : long
|
||||
PsiMethodCallExpression:someClass.getFoo() : long
|
||||
PsiParameter:foo : long
|
||||
PsiReferenceExpression:foo : long
|
||||
PsiReferenceExpression:foo : long
|
||||
PsiReferenceExpression:someNumber : long
|
||||
PsiReferenceExpression:this.foo : long
|
||||
|
||||
Conversions:
|
||||
someNumber + 10 -> $
|
||||
someNumber1 -> $
|
||||
|
||||
New expression type changes:
|
||||
Fails:
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
public class Test {
|
||||
|
||||
private long foo;
|
||||
|
||||
public long getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(long foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
static void m(Test someClass) {
|
||||
long someNumber = someClass.getFoo();
|
||||
System.out.println(someNumber + 10);
|
||||
|
||||
int someNumber1 = 1123;
|
||||
someClass.setFoo(someNumber1);
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
public class Test {
|
||||
|
||||
private int foo;
|
||||
|
||||
public int getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(int foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
static void m(Test someClass) {
|
||||
int someNumber = someClass.getFoo();
|
||||
System.out.println(someNumber + 10);
|
||||
|
||||
int someNumber1 = 1123;
|
||||
someClass.setFoo(someNumber1);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
Types:
|
||||
PsiField:foo : int
|
||||
PsiMethod:getFoo : int
|
||||
PsiParameter:foo : int
|
||||
PsiReferenceExpression:foo : int
|
||||
PsiReferenceExpression:foo : int
|
||||
|
||||
@@ -2,7 +2,7 @@ class Test {
|
||||
private int foo;
|
||||
private long bar;
|
||||
|
||||
public long getFoo() {
|
||||
public int getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user