mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Type Cook Advanced
This commit is contained in:
@@ -64,7 +64,8 @@ public abstract class RefactoringFactory {
|
||||
boolean dropObsoleteCasts,
|
||||
boolean leaveObjectsRaw,
|
||||
boolean preserveRawArrays,
|
||||
boolean exhaustive);
|
||||
boolean exhaustive,
|
||||
boolean cookObjects);
|
||||
|
||||
/**
|
||||
* Creates Introduce Parameter refactoring that replaces local variable with parameter.
|
||||
|
||||
@@ -55,6 +55,7 @@ public class RefactoringSettings implements JDOMExternalizable, ApplicationCompo
|
||||
public boolean TYPE_COOK_PRESERVE_RAW_ARRAYS = true;
|
||||
public boolean TYPE_COOK_LEAVE_OBJECT_PARAMETERIZED_TYPES_RAW = true;
|
||||
public boolean TYPE_COOK_EXHAUSTIVE = false;
|
||||
public final boolean TYPE_COOK_COOK_OBJECTS = false;
|
||||
|
||||
public boolean TYPE_MIGRATION_PREVIEW_USAGES = true;
|
||||
|
||||
|
||||
@@ -113,8 +113,9 @@ public class RefactoringFactoryImpl extends RefactoringFactory implements Projec
|
||||
boolean dropObsoleteCasts,
|
||||
boolean leaveObjectsRaw,
|
||||
boolean preserveRawArrays,
|
||||
boolean exhaustive) {
|
||||
return new TypeCookRefactoringImpl(myProject, elements, dropObsoleteCasts, leaveObjectsRaw, preserveRawArrays, exhaustive);
|
||||
boolean exhaustive,
|
||||
boolean cookObjects) {
|
||||
return new TypeCookRefactoringImpl(myProject, elements, dropObsoleteCasts, leaveObjectsRaw, preserveRawArrays, exhaustive, cookObjects);
|
||||
}
|
||||
|
||||
public IntroduceParameterRefactoring createIntroduceParameterRefactoring(PsiMethod methodToReplaceIn,
|
||||
|
||||
@@ -22,7 +22,8 @@ public class TypeCookRefactoringImpl extends RefactoringImpl<TypeCookProcessor>
|
||||
final boolean dropObsoleteCasts,
|
||||
final boolean leaveObjectsRaw,
|
||||
final boolean preserveRawArrays,
|
||||
final boolean exh) {
|
||||
final boolean exhaustiveSearch,
|
||||
final boolean cookObjects) {
|
||||
super(new TypeCookProcessor(project, elements, new Settings() {
|
||||
public boolean dropObsoleteCasts() {
|
||||
return dropObsoleteCasts;
|
||||
@@ -33,7 +34,11 @@ public class TypeCookRefactoringImpl extends RefactoringImpl<TypeCookProcessor>
|
||||
}
|
||||
|
||||
public boolean exhaustive() {
|
||||
return exh;
|
||||
return exhaustiveSearch;
|
||||
}
|
||||
|
||||
public boolean cookObjects() {
|
||||
return cookObjects;
|
||||
}
|
||||
|
||||
public boolean preserveRawArrays() {
|
||||
|
||||
@@ -12,4 +12,5 @@ public interface Settings {
|
||||
boolean preserveRawArrays();
|
||||
boolean leaveObjectParameterizedTypesRaw();
|
||||
boolean exhaustive();
|
||||
boolean cookObjects();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public class TypeCookDialog extends RefactoringDialog {
|
||||
private JCheckBox myCbPreserveRawArrays = new JCheckBox("Preserve raw arrays");
|
||||
private JCheckBox myCbLeaveObjectParameterizedTypesRaw = new JCheckBox("Leave Object-parameterized types raw");
|
||||
private JCheckBox myCbExhaustive = new JCheckBox("Perform exhaustive search");
|
||||
private JCheckBox myCbCookObjects = new JCheckBox("Generify Objects");
|
||||
|
||||
public TypeCookDialog(Project project, PsiElement[] elements) {
|
||||
super(project, true);
|
||||
@@ -96,10 +97,16 @@ public class TypeCookDialog extends RefactoringDialog {
|
||||
RefactoringSettings.getInstance().TYPE_COOK_EXHAUSTIVE);
|
||||
}
|
||||
|
||||
if (myCbCookObjects.isEnabled()) {
|
||||
myCbCookObjects.setSelected(
|
||||
RefactoringSettings.getInstance().TYPE_COOK_COOK_OBJECTS);
|
||||
}
|
||||
|
||||
myCbDropCasts.setMnemonic('D');
|
||||
myCbPreserveRawArrays.setMnemonic('P');
|
||||
myCbLeaveObjectParameterizedTypesRaw.setMnemonic('L');
|
||||
myCbExhaustive.setMnemonic('E');
|
||||
myCbCookObjects.setMnemonic('O');
|
||||
|
||||
gbConstraints.insets = new Insets(4, 8, 4, 8);
|
||||
|
||||
@@ -129,6 +136,10 @@ public class TypeCookDialog extends RefactoringDialog {
|
||||
gbConstraints.gridwidth = 2;
|
||||
optionsPanel.add(myCbExhaustive, gbConstraints);
|
||||
|
||||
gbConstraints.gridx = 0;
|
||||
gbConstraints.gridwidth = 2;
|
||||
optionsPanel.add(myCbCookObjects, gbConstraints);
|
||||
|
||||
return optionsPanel;
|
||||
}
|
||||
|
||||
@@ -145,7 +156,8 @@ public class TypeCookDialog extends RefactoringDialog {
|
||||
final boolean dropCasts = myCbDropCasts.isSelected();
|
||||
final boolean preserveRawArrays = true; //myCbPreserveRawArrays.isSelected();
|
||||
final boolean leaveObjectParameterizedTypesRaw = myCbLeaveObjectParameterizedTypesRaw.isSelected();
|
||||
final boolean exh = myCbExhaustive.isSelected();
|
||||
final boolean exhaustive = myCbExhaustive.isSelected();
|
||||
final boolean cookObjects = myCbCookObjects.isSelected();
|
||||
|
||||
return new Settings() {
|
||||
public boolean dropObsoleteCasts() {
|
||||
@@ -161,7 +173,11 @@ public class TypeCookDialog extends RefactoringDialog {
|
||||
}
|
||||
|
||||
public boolean exhaustive() {
|
||||
return exh;
|
||||
return exhaustive;
|
||||
}
|
||||
|
||||
public boolean cookObjects() {
|
||||
return cookObjects;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,6 +87,8 @@ public class TypeCookProcessor extends BaseRefactoringProcessor {
|
||||
|
||||
myResult.apply (victims);
|
||||
|
||||
java.lang.System.out.println(myResult.getReport());
|
||||
|
||||
UndoManager.getInstance(myProject).undoableActionPerformed(new DummyComplexUndoableAction()); // force confirmation dialog for undo
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.intellij.refactoring.typeCook;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
@@ -117,7 +118,11 @@ public class Util {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isRaw(PsiType t, boolean arrays) {
|
||||
public static boolean isRaw(PsiType t, final Settings settings) {
|
||||
return isRaw(t, settings, true);
|
||||
}
|
||||
|
||||
private static boolean isRaw(PsiType t, final Settings settings, final boolean upper) {
|
||||
if (t instanceof PsiClassType) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = resolveType(t);
|
||||
|
||||
@@ -131,18 +136,24 @@ public class Util {
|
||||
|
||||
final PsiSubstitutor subst = resolveResult.getSubstitutor();
|
||||
final PsiClass element = resolveResult.getElement();
|
||||
final PsiManager manager = element.getManager();
|
||||
|
||||
if (settings.cookObjects() && upper &&
|
||||
t.equals(PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(manager.getProject())))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final PsiTypeParameter[] parameters = getTypeParametersList(element);
|
||||
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
final PsiType actual = subst.substitute(parameters[i]);
|
||||
if (!(actual instanceof PsiTypeParameter) && isRaw(actual, arrays)) return true;
|
||||
if (!(actual instanceof PsiTypeParameter) && isRaw(actual, settings, false)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (t instanceof PsiArrayType) {
|
||||
return arrays ? false : isRaw(((PsiArrayType)t).getComponentType(), arrays);
|
||||
return settings.preserveRawArrays() ? false : isRaw(((PsiArrayType)t).getComponentType(), settings, upper);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -308,9 +319,20 @@ public class Util {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static PsiType createParameterizedType(final PsiType t, final PsiTypeVariableFactory factory, final PsiElement context) {
|
||||
return createParameterizedType(t, factory, true, context);
|
||||
}
|
||||
|
||||
public static PsiType createParameterizedType(final PsiType t, final PsiTypeVariableFactory factory) {
|
||||
if (t == null) {
|
||||
return factory.create();
|
||||
return createParameterizedType(t, factory, true, null);
|
||||
}
|
||||
|
||||
private static PsiType createParameterizedType(final PsiType t,
|
||||
final PsiTypeVariableFactory factory,
|
||||
final boolean upper,
|
||||
final PsiElement context) {
|
||||
if (t == null || (upper && t.getCanonicalText().equals("java.lang.Object"))) {
|
||||
return factory.create(context);
|
||||
}
|
||||
|
||||
if (t instanceof PsiClassType) {
|
||||
@@ -324,7 +346,7 @@ public class Util {
|
||||
|
||||
for (Iterator<PsiTypeParameter> i = aSubst.getSubstitutionMap().keySet().iterator(); i.hasNext();) {
|
||||
final PsiTypeParameter parm = i.next();
|
||||
final PsiType type = createParameterizedType(aSubst.substitute(parm), factory);
|
||||
final PsiType type = createParameterizedType(aSubst.substitute(parm), factory, false, context);
|
||||
|
||||
if (type instanceof PsiTypeVariable) {
|
||||
cluster.add((PsiTypeVariable)type);
|
||||
@@ -340,7 +362,7 @@ public class Util {
|
||||
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
|
||||
}
|
||||
else if (t instanceof PsiArrayType) {
|
||||
return createParameterizedType(((PsiArrayType)t).getComponentType(), factory).createArrayType();
|
||||
return createParameterizedType(((PsiArrayType)t).getComponentType(), factory, upper, context).createArrayType();
|
||||
}
|
||||
|
||||
return t;
|
||||
@@ -463,7 +485,7 @@ public class Util {
|
||||
final PsiSubstitutor subst = result.getSubstitutor();
|
||||
final PsiTypeParameter[] parms = Util.getTypeParametersList(result.getElement());
|
||||
|
||||
if (parms.length >= 0 && subst.substitute(parms[0]) != null) {
|
||||
if (parms.length > 0 && subst.substitute(parms[0]) != null) {
|
||||
PsiJavaCodeReferenceElement classReference = newx.getClassReference();
|
||||
PsiReferenceParameterList list = null;
|
||||
|
||||
@@ -488,7 +510,7 @@ public class Util {
|
||||
for (int i = 0; i < parms.length; i++) {
|
||||
PsiType aType = subst.substitute(parms[i]);
|
||||
|
||||
if (aType instanceof PsiWildcardType){
|
||||
if (aType instanceof PsiWildcardType) {
|
||||
aType = ((PsiWildcardType)aType).getBound();
|
||||
}
|
||||
|
||||
@@ -497,7 +519,7 @@ public class Util {
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG.error ("Unexpected element type " + element.getClass().getName());
|
||||
LOG.error("Unexpected element type " + element.getClass().getName());
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.intellij.refactoring.typeCook.deductive;
|
||||
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.PsiTypeVisitor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -28,8 +29,8 @@ public class PsiTypeVariableFactory {
|
||||
public final void registerCluster(final HashSet<PsiTypeVariable> cluster) {
|
||||
myClusters.add(cluster);
|
||||
|
||||
for (final Iterator<PsiTypeVariable> v=cluster.iterator(); v.hasNext();){
|
||||
myVarCluster.put (new Integer(v.next().getIndex()), cluster);
|
||||
for (final Iterator<PsiTypeVariable> v = cluster.iterator(); v.hasNext();) {
|
||||
myVarCluster.put(new Integer(v.next().getIndex()), cluster);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,13 +38,101 @@ public class PsiTypeVariableFactory {
|
||||
return myClusters;
|
||||
}
|
||||
|
||||
public final HashSet<PsiTypeVariable> getClusterOf (final int var){
|
||||
return myVarCluster.get(new Integer (var));
|
||||
public final HashSet<PsiTypeVariable> getClusterOf(final int var) {
|
||||
return myVarCluster.get(new Integer(var));
|
||||
}
|
||||
|
||||
public final PsiTypeVariable create() {
|
||||
return create(null);
|
||||
}
|
||||
|
||||
public final PsiTypeVariable create(final PsiElement context) {
|
||||
return new PsiTypeVariable() {
|
||||
private int myIndex = myCurrent++;
|
||||
private final PsiElement myContext = context;
|
||||
|
||||
public boolean isValidInContext(final PsiType type) {
|
||||
if (myContext == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return type.accept(new PsiTypeVisitor<Boolean>() {
|
||||
public Boolean visitType(final PsiType type) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
public Boolean visitArrayType(final PsiArrayType arrayType) {
|
||||
return arrayType.getDeepComponentType().accept(this);
|
||||
}
|
||||
|
||||
public Boolean visitWildcardType(final PsiWildcardType wildcardType) {
|
||||
final PsiType bound = wildcardType.getBound();
|
||||
|
||||
if (bound != null) {
|
||||
bound.accept(this);
|
||||
}
|
||||
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
public Boolean visitClassType(final PsiClassType classType) {
|
||||
final PsiClassType.ClassResolveResult result = classType.resolveGenerics();
|
||||
final PsiClass aClass = result.getElement();
|
||||
final PsiSubstitutor aSubst = result.getSubstitutor();
|
||||
final PsiManager manager = aClass.getManager();
|
||||
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) {
|
||||
final PsiTypeParameterListOwner owner =
|
||||
PsiTreeUtil.getParentOfType(myContext, PsiTypeParameterListOwner.class);
|
||||
|
||||
if (owner != null) {
|
||||
boolean found = false;
|
||||
|
||||
for (final Iterator<PsiTypeParameter> p = PsiUtil.typeParametersIterator(owner);
|
||||
p.hasNext() && !found;) {
|
||||
final PsiTypeParameter parm = p.next();
|
||||
|
||||
found = manager.areElementsEquivalent(parm, aClass);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
else if (!manager.getResolveHelper().isAccessible(aClass, myContext, null)) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
for (final Iterator<PsiTypeParameter> p = aSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();) {
|
||||
final PsiTypeParameter parm = p.next();
|
||||
final PsiType type = aSubst.substitute(parm);
|
||||
|
||||
if (type != null){
|
||||
final Boolean b = type.accept(this);
|
||||
|
||||
if (! b.booleanValue()){
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
else {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
}).booleanValue();
|
||||
}
|
||||
|
||||
public String getPresentableText() {
|
||||
return "$" + myIndex;
|
||||
|
||||
@@ -53,11 +53,19 @@ public class Result {
|
||||
}
|
||||
|
||||
public PsiType getCookedType(final PsiElement element) {
|
||||
final PsiType originalType = Util.getType(element);
|
||||
|
||||
if (myBinding != null) {
|
||||
return myBinding.substitute(myTypes.get(element));
|
||||
final PsiType type = myBinding.substitute(myTypes.get(element));
|
||||
|
||||
if (type == null && originalType.getCanonicalText().equals("java.lang.Object")){
|
||||
return originalType;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
return Util.getType(element);
|
||||
return originalType;
|
||||
}
|
||||
|
||||
public HashSet<PsiElement> getCookedElements() {
|
||||
|
||||
@@ -170,7 +170,7 @@ public class SystemBuilder {
|
||||
|
||||
t = Util.getType(e);
|
||||
|
||||
final PsiType parameterizedType = Util.createParameterizedType(t, myTypeVariableFactory);
|
||||
final PsiType parameterizedType = Util.createParameterizedType(t, myTypeVariableFactory, e);
|
||||
|
||||
myTypes.put(e, parameterizedType);
|
||||
|
||||
@@ -810,6 +810,10 @@ public class SystemBuilder {
|
||||
}
|
||||
}
|
||||
}.brrrr(definedType, elemenType);
|
||||
|
||||
if (mySettings.cookObjects() && elemenType.getCanonicalText().equals("java.lang.Object")){
|
||||
system.addSubtypeConstraint(definedType, elemenType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,4 +40,6 @@ public abstract class Binding {
|
||||
public abstract HashSet<PsiTypeVariable> getBoundVariables();
|
||||
|
||||
public abstract int getWidth();
|
||||
|
||||
public abstract boolean isValid();
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public class BindingFactory {
|
||||
return theClass.getManager().getElementFactory().createType(theClass, theSubst);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
return type;
|
||||
}
|
||||
}
|
||||
else if (type instanceof PsiWildcardType) {
|
||||
@@ -541,6 +541,19 @@ public class BindingFactory {
|
||||
return w;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
for (final Iterator<PsiTypeVariable> v = myBoundVariables.iterator(); v.hasNext();) {
|
||||
final PsiTypeVariable var = v.next();
|
||||
final PsiType type = substitute(var);
|
||||
|
||||
if (!var.isValidInContext(type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public PsiType substitute(final PsiType t) {
|
||||
if (t instanceof PsiWildcardType) {
|
||||
final PsiWildcardType wcType = (PsiWildcardType)t;
|
||||
@@ -677,6 +690,7 @@ public class BindingFactory {
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
return balancer.varType((PsiTypeVariable)x, y);
|
||||
|
||||
@@ -47,7 +47,7 @@ public class SolutionHolder {
|
||||
final Binding binding = b.next();
|
||||
final int w = binding.getWidth();
|
||||
|
||||
if (w > width) {
|
||||
if (w > width && binding.isValid()) {
|
||||
width = w;
|
||||
best = binding;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,11 @@ public class VictimCollector extends Visitor {
|
||||
}
|
||||
|
||||
private void testNAdd(final PsiElement element, final PsiType t) {
|
||||
if (Util.isRaw(t, mySettings.preserveRawArrays())) {
|
||||
if (Util.isRaw(t, mySettings)) {
|
||||
if (element instanceof PsiNewExpression && t.getCanonicalText().equals("java.lang.Object")){
|
||||
return;
|
||||
}
|
||||
|
||||
myVictims.add(element);
|
||||
}
|
||||
}
|
||||
@@ -48,7 +52,7 @@ public class VictimCollector extends Visitor {
|
||||
testNAdd(parms[i], parms[i].getType());
|
||||
}
|
||||
|
||||
if (Util.isRaw(method.getReturnType(), mySettings.preserveRawArrays())) {
|
||||
if (Util.isRaw(method.getReturnType(), mySettings)) {
|
||||
myVictims.add(method);
|
||||
}
|
||||
|
||||
|
||||
@@ -649,6 +649,10 @@ public class TypeCookTest extends MultiFileTestCase {
|
||||
public boolean exhaustive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean cookObjects(){
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
final com.intellij.refactoring.typeCook.deductive.builder.System commonSystem = b.build(new PsiElement[]{aClass});
|
||||
|
||||
Reference in New Issue
Block a user