| package com.jetbrains.python.refactoring.classes.membersManager; |
| |
| import com.google.common.collect.Collections2; |
| import com.google.common.collect.Lists; |
| import com.intellij.refactoring.RefactoringBundle; |
| import com.intellij.util.containers.MultiMap; |
| import com.jetbrains.NotNullPredicate; |
| import com.jetbrains.python.PyNames; |
| import com.jetbrains.python.psi.*; |
| import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; |
| import com.jetbrains.python.refactoring.classes.ui.PyClassCellRenderer; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.*; |
| |
| /** |
| * Plugin that moves superclasses from one class to another |
| * |
| * @author Ilya.Kazakevich |
| */ |
| class SuperClassesManager extends MembersManager<PyClass> { |
| |
| private static final NoFakeSuperClasses NO_FAKE_SUPER_CLASSES = new NoFakeSuperClasses(); |
| |
| SuperClassesManager() { |
| super(PyClass.class); |
| } |
| |
| |
| @NotNull |
| @Override |
| protected Collection<PyElement> getDependencies(@NotNull final MultiMap<PyClass, PyElement> usedElements) { |
| return Lists.<PyElement>newArrayList(usedElements.keySet()); |
| } |
| |
| @NotNull |
| protected MultiMap<PyClass, PyElement> getDependencies(@NotNull PyElement member) { |
| return MultiMap.emptyInstance(); |
| } |
| |
| @Override |
| public boolean hasConflict(@NotNull final PyClass member, @NotNull final PyClass aClass) { |
| final List<PyExpression> expressionList = getExpressionsBySuperClass(aClass, Collections.singleton(member)); |
| return !expressionList.isEmpty(); |
| } |
| |
| @NotNull |
| @Override |
| protected List<PyElement> getMembersCouldBeMoved(@NotNull final PyClass pyClass) { |
| return Lists.<PyElement>newArrayList(Collections2.filter(Arrays.asList(pyClass.getSuperClasses()), NO_FAKE_SUPER_CLASSES)); |
| } |
| |
| @Override |
| protected Collection<PyElement> moveMembers(@NotNull final PyClass from, |
| @NotNull final Collection<PyMemberInfo<PyClass>> members, |
| @NotNull final PyClass... to) { |
| final Collection<PyClass> elements = fetchElements(members); |
| for (final PyClass destClass : to) { |
| PyClassRefactoringUtil.addSuperclasses(from.getProject(), destClass, elements.toArray(new PyClass[members.size()])); |
| } |
| |
| final List<PyExpression> expressionsToDelete = getExpressionsBySuperClass(from, elements); |
| for (final PyExpression expressionToDelete : expressionsToDelete) { |
| expressionToDelete.delete(); |
| } |
| |
| return Collections.emptyList(); //Hack: we know that "superclass expression" can't have reference |
| } |
| |
| /** |
| * Returns superclass expressions that are resolved to one or more classes from collection |
| * @param from class to get superclass expressions from |
| * @param classes classes to check superclasses against |
| * @return collection of expressions that are resolved to one or more class from classes param |
| */ |
| @NotNull |
| private static List<PyExpression> getExpressionsBySuperClass(@NotNull final PyClass from, @NotNull final Collection<PyClass> classes) { |
| final List<PyExpression> expressionsToDelete = new ArrayList<PyExpression>(classes.size()); |
| |
| for (final PyExpression expression : from.getSuperClassExpressions()) { |
| // Remove all superclass expressions that point to class from memberinfo |
| if (!(expression instanceof PyQualifiedExpression)) { |
| continue; |
| } |
| final PyReferenceExpression reference = (PyReferenceExpression)expression; |
| for (final PyClass element : classes) { |
| if (reference.getReference().isReferenceTo(element)) { |
| expressionsToDelete.add(expression); |
| } |
| } |
| } |
| return expressionsToDelete; |
| } |
| |
| @NotNull |
| @Override |
| public PyMemberInfo<PyClass> apply(@NotNull final PyClass input) { |
| final String name = RefactoringBundle.message("member.info.extends.0", PyClassCellRenderer.getClassText(input)); |
| //TODO: Check for "overrides" |
| return new PyMemberInfo<PyClass>(input, false, name, false, this, false); |
| } |
| |
| private static class NoFakeSuperClasses extends NotNullPredicate<PyClass> { |
| @Override |
| protected boolean applyNotNull(@NotNull final PyClass input) { |
| return !PyNames.FAKE_OLD_BASE.equals(input.getName()); |
| } |
| } |
| } |