Search in sources :

Example 1 with GrClassMemberReferenceVisitor

use of org.jetbrains.plugins.groovy.refactoring.classMembers.GrClassMemberReferenceVisitor in project intellij-community by JetBrains.

the class GrPullUpConflictsUtil method checkConflicts.

public static MultiMap<PsiElement, String> checkConflicts(final MemberInfoBase<? extends GrMember>[] infos, @NotNull final PsiClass subclass, @Nullable PsiClass superClass, @NotNull final PsiPackage targetPackage, @NotNull PsiDirectory targetDirectory, final InterfaceContainmentVerifier interfaceContainmentVerifier, boolean movedMembers2Super) {
    final PsiElement targetRepresentativeElement;
    final boolean isInterfaceTarget;
    if (superClass != null) {
        isInterfaceTarget = superClass.isInterface();
        targetRepresentativeElement = superClass;
    } else {
        isInterfaceTarget = false;
        targetRepresentativeElement = targetDirectory;
    }
    final Set<GrMember> movedMembers = ContainerUtil.newHashSet();
    final Set<GrMethod> abstractMethods = ContainerUtil.newHashSet();
    for (MemberInfoBase<? extends GrMember> info : infos) {
        GrMember member = info.getMember();
        if (member instanceof GrMethod) {
            if (!info.isToAbstract() && !isInterfaceTarget) {
                movedMembers.add(member);
            } else {
                abstractMethods.add((GrMethod) member);
            }
        } else {
            movedMembers.add(member);
        }
    }
    final Set<PsiMethod> allAbstractMethods = new HashSet<>(abstractMethods);
    if (superClass != null) {
        for (PsiMethod method : subclass.getMethods()) {
            if (!movedMembers.contains(method) && !method.hasModifierProperty(PsiModifier.PRIVATE)) {
                if (method.findSuperMethods(superClass).length > 0) {
                    allAbstractMethods.add(method);
                }
            }
        }
    }
    final MultiMap<PsiElement, String> conflicts = new MultiMap<>();
    GrRefactoringConflictsUtil.analyzeAccessibilityConflicts(movedMembers, superClass, conflicts, VisibilityUtil.ESCALATE_VISIBILITY, targetRepresentativeElement, allAbstractMethods);
    if (superClass != null) {
        if (movedMembers2Super) {
            checkSuperclassMembers(superClass, infos, conflicts);
            if (isInterfaceTarget) {
                checkInterfaceTarget(infos, conflicts);
            }
        } else {
            final String qualifiedName = superClass.getQualifiedName();
            assert qualifiedName != null;
            if (superClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) {
                if (!Comparing.strEqual(StringUtil.getPackageName(qualifiedName), targetPackage.getQualifiedName())) {
                    conflicts.putValue(superClass, RefactoringUIUtil.getDescription(superClass, true) + " won't be accessible from " + RefactoringUIUtil.getDescription(targetPackage, true));
                }
            }
        }
    }
    // check if moved methods use other members in the classes between Subclass and Superclass
    List<PsiElement> checkModuleConflictsList = new ArrayList<>();
    for (PsiMember member : movedMembers) {
        if (member instanceof PsiMethod || member instanceof PsiClass && !(member instanceof PsiCompiledElement)) {
            GrClassMemberReferenceVisitor visitor = movedMembers2Super ? new ConflictingUsagesOfSubClassMembers(member, movedMembers, abstractMethods, subclass, superClass, superClass != null ? null : targetPackage, conflicts, interfaceContainmentVerifier) : new ConflictingUsagesOfSuperClassMembers(member, subclass, targetPackage, movedMembers, conflicts);
            ((GroovyPsiElement) member).accept(visitor);
        }
        checkModuleConflictsList.add(member);
    }
    for (final PsiMethod method : abstractMethods) {
        ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getParameterList());
        ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getReturnTypeElement());
        ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getTypeParameterList());
    }
    GrRefactoringConflictsUtil.analyzeModuleConflicts(subclass.getProject(), checkModuleConflictsList, UsageInfo.EMPTY_ARRAY, targetRepresentativeElement, conflicts);
    final String fqName = subclass.getQualifiedName();
    final String packageName;
    if (fqName != null) {
        packageName = StringUtil.getPackageName(fqName);
    } else {
        final PsiFile psiFile = PsiTreeUtil.getParentOfType(subclass, PsiFile.class);
        if (psiFile instanceof PsiClassOwner) {
            packageName = ((PsiClassOwner) psiFile).getPackageName();
        } else {
            packageName = null;
        }
    }
    final boolean toDifferentPackage = !Comparing.strEqual(targetPackage.getQualifiedName(), packageName);
    for (final GrMethod abstractMethod : abstractMethods) {
        abstractMethod.accept(new GrClassMemberReferenceVisitor(subclass) {

            @Override
            protected void visitClassMemberReferenceElement(GrMember classMember, GrReferenceElement classMemberReference) {
                if (classMember != null && willBeMoved(classMember, movedMembers)) {
                    boolean isAccessible = false;
                    if (classMember.hasModifierProperty(PsiModifier.PRIVATE)) {
                        isAccessible = true;
                    } else if (classMember.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) && toDifferentPackage) {
                        isAccessible = true;
                    }
                    if (isAccessible) {
                        String message = RefactoringUIUtil.getDescription(abstractMethod, false) + " uses " + RefactoringUIUtil.getDescription(classMember, true) + " which won't be accessible from the subclass.";
                        message = CommonRefactoringUtil.capitalize(message);
                        conflicts.putValue(classMember, message);
                    }
                }
            }
        });
        if (abstractMethod.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) && toDifferentPackage) {
            if (!isInterfaceTarget) {
                String message = "Can't make " + RefactoringUIUtil.getDescription(abstractMethod, false) + " abstract as it won't be accessible from the subclass.";
                message = CommonRefactoringUtil.capitalize(message);
                conflicts.putValue(abstractMethod, message);
            }
        }
    }
    return conflicts;
}
Also used : GrClassMemberReferenceVisitor(org.jetbrains.plugins.groovy.refactoring.classMembers.GrClassMemberReferenceVisitor) ArrayList(java.util.ArrayList) MultiMap(com.intellij.util.containers.MultiMap) GroovyPsiElement(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement) GrReferenceElement(org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement) HashSet(java.util.HashSet) GroovyPsiElement(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement) GrMember(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember) GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod)

Aggregations

MultiMap (com.intellij.util.containers.MultiMap)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 GrReferenceElement (org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement)1 GroovyPsiElement (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement)1 GrMember (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember)1 GrMethod (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod)1 GrClassMemberReferenceVisitor (org.jetbrains.plugins.groovy.refactoring.classMembers.GrClassMemberReferenceVisitor)1