Search in sources :

Example 1 with NonCodeUsageInfo

use of com.intellij.refactoring.util.NonCodeUsageInfo in project intellij-community by JetBrains.

the class MoveFilesOrDirectoriesProcessor method retargetUsages.

protected void retargetUsages(UsageInfo[] usages, Map<PsiElement, PsiElement> oldToNewMap) {
    final List<NonCodeUsageInfo> nonCodeUsages = new ArrayList<>();
    for (UsageInfo usageInfo : usages) {
        if (usageInfo instanceof MyUsageInfo) {
            final MyUsageInfo info = (MyUsageInfo) usageInfo;
            final PsiElement element = myElementsToMove[info.myIndex];
            if (info.getReference() instanceof FileReference || info.getReference() instanceof PsiDynaReference) {
                final PsiElement usageElement = info.getElement();
                if (usageElement != null) {
                    final PsiFile usageFile = usageElement.getContainingFile();
                    final PsiFile psiFile = usageFile.getViewProvider().getPsi(usageFile.getViewProvider().getBaseLanguage());
                    if (psiFile != null && psiFile.equals(element)) {
                        // already processed in MoveFilesOrDirectoriesUtil.doMoveFile
                        continue;
                    }
                }
            }
            final PsiElement refElement = info.myReference.getElement();
            if (refElement != null && refElement.isValid()) {
                info.myReference.bindToElement(element);
            }
        } else if (usageInfo instanceof NonCodeUsageInfo) {
            nonCodeUsages.add((NonCodeUsageInfo) usageInfo);
        }
    }
    for (PsiFile movedFile : myFoundUsages.keySet()) {
        MoveFileHandler.forElement(movedFile).retargetUsages(myFoundUsages.get(movedFile), oldToNewMap);
    }
    myNonCodeUsages = nonCodeUsages.toArray(new NonCodeUsageInfo[nonCodeUsages.size()]);
}
Also used : PsiDynaReference(com.intellij.openapi.paths.PsiDynaReference) NonCodeUsageInfo(com.intellij.refactoring.util.NonCodeUsageInfo) ArrayList(java.util.ArrayList) PsiFile(com.intellij.psi.PsiFile) FileReference(com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference) UsageInfo(com.intellij.usageView.UsageInfo) NonCodeUsageInfo(com.intellij.refactoring.util.NonCodeUsageInfo) PsiElement(com.intellij.psi.PsiElement)

Example 2 with NonCodeUsageInfo

use of com.intellij.refactoring.util.NonCodeUsageInfo in project intellij-community by JetBrains.

the class CommonMoveUtil method retargetUsages.

public static NonCodeUsageInfo[] retargetUsages(final UsageInfo[] usages, final Map<PsiElement, PsiElement> oldToNewElementsMapping) throws IncorrectOperationException {
    Arrays.sort(usages, (o1, o2) -> {
        final VirtualFile file1 = o1.getVirtualFile();
        final VirtualFile file2 = o2.getVirtualFile();
        if (Comparing.equal(file1, file2)) {
            final ProperTextRange rangeInElement1 = o1.getRangeInElement();
            final ProperTextRange rangeInElement2 = o2.getRangeInElement();
            if (rangeInElement1 != null && rangeInElement2 != null) {
                return rangeInElement2.getStartOffset() - rangeInElement1.getStartOffset();
            }
            return 0;
        }
        if (file1 == null)
            return -1;
        if (file2 == null)
            return 1;
        return Comparing.compare(file1.getPath(), file2.getPath());
    });
    List<NonCodeUsageInfo> nonCodeUsages = new ArrayList<>();
    for (UsageInfo usage : usages) {
        if (usage instanceof NonCodeUsageInfo) {
            nonCodeUsages.add((NonCodeUsageInfo) usage);
        } else if (usage instanceof MoveRenameUsageInfo) {
            final MoveRenameUsageInfo moveRenameUsage = (MoveRenameUsageInfo) usage;
            final PsiElement oldElement = moveRenameUsage.getReferencedElement();
            final PsiElement newElement = oldToNewElementsMapping.get(oldElement);
            LOG.assertTrue(newElement != null, oldElement);
            final PsiReference reference = moveRenameUsage.getReference();
            if (reference != null) {
                try {
                    reference.bindToElement(newElement);
                } catch (IncorrectOperationException e) {
                //
                }
            }
        }
    }
    return nonCodeUsages.toArray(new NonCodeUsageInfo[nonCodeUsages.size()]);
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) ProperTextRange(com.intellij.openapi.util.ProperTextRange) NonCodeUsageInfo(com.intellij.refactoring.util.NonCodeUsageInfo) MoveRenameUsageInfo(com.intellij.refactoring.util.MoveRenameUsageInfo) PsiReference(com.intellij.psi.PsiReference) IncorrectOperationException(com.intellij.util.IncorrectOperationException) NonCodeUsageInfo(com.intellij.refactoring.util.NonCodeUsageInfo) MoveRenameUsageInfo(com.intellij.refactoring.util.MoveRenameUsageInfo) UsageInfo(com.intellij.usageView.UsageInfo) PsiElement(com.intellij.psi.PsiElement)

Example 3 with NonCodeUsageInfo

use of com.intellij.refactoring.util.NonCodeUsageInfo in project intellij-community by JetBrains.

the class MoveDirectoryWithClassesProcessor method performRefactoring.

@Override
public void performRefactoring(@NotNull UsageInfo[] usages) {
    //try to create all directories beforehand
    try {
        //top level directories should be created even if they are empty
        for (PsiDirectory directory : myDirectories) {
            getResultDirectory(directory).findOrCreateTargetDirectory();
        }
        for (PsiDirectory directory : myNestedDirsToMove.keySet()) {
            myNestedDirsToMove.get(directory).findOrCreateTargetDirectory();
        }
        for (PsiFile psiFile : myFilesToMove.keySet()) {
            myFilesToMove.get(psiFile).findOrCreateTargetDirectory();
        }
        DumbService.getInstance(myProject).completeJustSubmittedTasks();
        final List<PsiFile> movedFiles = new ArrayList<>();
        final Map<PsiElement, PsiElement> oldToNewElementsMapping = new HashMap<>();
        for (PsiFile psiFile : myFilesToMove.keySet()) {
            for (MoveDirectoryWithClassesHelper helper : MoveDirectoryWithClassesHelper.findAll()) {
                helper.beforeMove(psiFile);
            }
            final RefactoringElementListener listener = getTransaction().getElementListener(psiFile);
            final PsiDirectory moveDestination = myFilesToMove.get(psiFile).getTargetDirectory();
            for (MoveDirectoryWithClassesHelper helper : MoveDirectoryWithClassesHelper.findAll()) {
                boolean processed = helper.move(psiFile, moveDestination, oldToNewElementsMapping, movedFiles, listener);
                if (processed) {
                    break;
                }
            }
        }
        for (PsiElement newElement : oldToNewElementsMapping.values()) {
            for (MoveDirectoryWithClassesHelper helper : MoveDirectoryWithClassesHelper.findAll()) {
                helper.afterMove(newElement);
            }
        }
        // fix references in moved files to outer files
        for (PsiFile movedFile : movedFiles) {
            MoveFileHandler.forElement(movedFile).updateMovedFile(movedFile);
            FileReferenceContextUtil.decodeFileReferences(movedFile);
        }
        myNonCodeUsages = CommonMoveUtil.retargetUsages(usages, oldToNewElementsMapping);
        for (MoveDirectoryWithClassesHelper helper : MoveDirectoryWithClassesHelper.findAll()) {
            helper.postProcessUsages(usages, dir -> getResultDirectory(dir).findOrCreateTargetDirectory());
        }
        for (PsiDirectory directory : myDirectories) {
            final TargetDirectoryWrapper wrapper = myNestedDirsToMove.get(directory);
            final PsiDirectory targetDirectory = wrapper.getTargetDirectory();
            if (targetDirectory == null || !PsiTreeUtil.isAncestor(directory, targetDirectory, false)) {
                directory.delete();
            }
        }
    } catch (IncorrectOperationException e) {
        myNonCodeUsages = new NonCodeUsageInfo[0];
        RefactoringUIUtil.processIncorrectOperation(myProject, e);
    }
}
Also used : RefactoringElementListener(com.intellij.refactoring.listeners.RefactoringElementListener) NonCodeUsageInfo(com.intellij.refactoring.util.NonCodeUsageInfo) PsiDirectory(com.intellij.psi.PsiDirectory) PsiFile(com.intellij.psi.PsiFile) IncorrectOperationException(com.intellij.util.IncorrectOperationException) PsiElement(com.intellij.psi.PsiElement)

Example 4 with NonCodeUsageInfo

use of com.intellij.refactoring.util.NonCodeUsageInfo in project intellij-community by JetBrains.

the class UsageViewUtil method removeDuplicatedUsages.

@NotNull
public static UsageInfo[] removeDuplicatedUsages(@NotNull UsageInfo[] usages) {
    Set<UsageInfo> set = new LinkedHashSet<>(Arrays.asList(usages));
    // Replace duplicates of move rename usage infos in injections from non code usages of master files
    String newTextInNonCodeUsage = null;
    for (UsageInfo usage : usages) {
        if (!(usage instanceof NonCodeUsageInfo))
            continue;
        newTextInNonCodeUsage = ((NonCodeUsageInfo) usage).newText;
        break;
    }
    if (newTextInNonCodeUsage != null) {
        for (UsageInfo usage : usages) {
            if (!(usage instanceof MoveRenameUsageInfo))
                continue;
            PsiFile file = usage.getFile();
            if (file != null) {
                PsiElement context = InjectedLanguageManager.getInstance(file.getProject()).getInjectionHost(file);
                if (context != null) {
                    PsiElement usageElement = usage.getElement();
                    if (usageElement == null)
                        continue;
                    PsiReference psiReference = usage.getReference();
                    if (psiReference == null)
                        continue;
                    int injectionOffsetInMasterFile = InjectedLanguageManager.getInstance(usageElement.getProject()).injectedToHost(usageElement, usageElement.getTextOffset());
                    TextRange rangeInElement = usage.getRangeInElement();
                    assert rangeInElement != null : usage;
                    TextRange range = rangeInElement.shiftRight(injectionOffsetInMasterFile);
                    PsiFile containingFile = context.getContainingFile();
                    //move package to another package
                    if (containingFile == null)
                        continue;
                    set.remove(NonCodeUsageInfo.create(containingFile, range.getStartOffset(), range.getEndOffset(), ((MoveRenameUsageInfo) usage).getReferencedElement(), newTextInNonCodeUsage));
                }
            }
        }
    }
    return set.toArray(new UsageInfo[set.size()]);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) NonCodeUsageInfo(com.intellij.refactoring.util.NonCodeUsageInfo) MoveRenameUsageInfo(com.intellij.refactoring.util.MoveRenameUsageInfo) PsiReference(com.intellij.psi.PsiReference) PsiFile(com.intellij.psi.PsiFile) TextRange(com.intellij.openapi.util.TextRange) MoveRenameUsageInfo(com.intellij.refactoring.util.MoveRenameUsageInfo) NonCodeUsageInfo(com.intellij.refactoring.util.NonCodeUsageInfo) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with NonCodeUsageInfo

use of com.intellij.refactoring.util.NonCodeUsageInfo in project intellij-community by JetBrains.

the class MoveInnerProcessor method performRefactoring.

protected void performRefactoring(@NotNull final UsageInfo[] usages) {
    final PsiManager manager = PsiManager.getInstance(myProject);
    final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
    final RefactoringElementListener elementListener = getTransaction().getElementListener(myInnerClass);
    try {
        PsiField field = null;
        if (myParameterNameOuterClass != null) {
            // pass outer as a parameter
            field = factory.createField(myFieldNameOuterClass, factory.createType(myOuterClass));
            field = addOuterField(field);
            myInnerClass = field.getContainingClass();
            addFieldInitializationToConstructors(myInnerClass, field, myParameterNameOuterClass);
        }
        ChangeContextUtil.encodeContextInfo(myInnerClass, false);
        myInnerClass = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(myInnerClass);
        final MoveInnerOptions moveInnerOptions = new MoveInnerOptions(myInnerClass, myOuterClass, myTargetContainer, myNewClassName);
        final MoveInnerHandler handler = MoveInnerHandler.EP_NAME.forLanguage(myInnerClass.getLanguage());
        final PsiClass newClass;
        try {
            newClass = handler.copyClass(moveInnerOptions);
        } catch (IncorrectOperationException e) {
            RefactoringUIUtil.processIncorrectOperation(myProject, e);
            return;
        }
        // replace references in a new class to old inner class with references to itself
        for (PsiReference ref : ReferencesSearch.search(myInnerClass, new LocalSearchScope(newClass), true)) {
            PsiElement element = ref.getElement();
            if (element.getParent() instanceof PsiJavaCodeReferenceElement) {
                PsiJavaCodeReferenceElement parentRef = (PsiJavaCodeReferenceElement) element.getParent();
                PsiElement parentRefElement = parentRef.resolve();
                if (parentRefElement instanceof PsiClass) {
                    // reference to inner class inside our inner
                    final PsiReferenceList referenceList = PsiTreeUtil.getTopmostParentOfType(parentRef, PsiReferenceList.class);
                    if (referenceList == null || referenceList.getParent() != newClass) {
                        parentRef.getQualifier().delete();
                        continue;
                    }
                }
            }
            ref.bindToElement(newClass);
        }
        List<PsiReference> referencesToRebind = new ArrayList<>();
        for (UsageInfo usage : usages) {
            if (usage.isNonCodeUsage)
                continue;
            PsiElement refElement = usage.getElement();
            PsiReference[] references = refElement.getReferences();
            for (PsiReference reference : references) {
                if (reference.isReferenceTo(myInnerClass)) {
                    referencesToRebind.add(reference);
                }
            }
        }
        myInnerClass.delete();
        // correct references in usages
        for (UsageInfo usage : usages) {
            // should pass outer as parameter
            if (usage.isNonCodeUsage || myParameterNameOuterClass == null)
                continue;
            MoveInnerClassUsagesHandler usagesHandler = MoveInnerClassUsagesHandler.EP_NAME.forLanguage(usage.getElement().getLanguage());
            if (usagesHandler != null) {
                usagesHandler.correctInnerClassUsage(usage, myOuterClass);
            }
        }
        for (PsiReference reference : referencesToRebind) {
            reference.bindToElement(newClass);
        }
        for (UsageInfo usage : usages) {
            final PsiElement element = usage.getElement();
            final PsiElement parent = element != null ? element.getParent() : null;
            if (parent instanceof PsiNewExpression) {
                final PsiMethod resolveConstructor = ((PsiNewExpression) parent).resolveConstructor();
                for (PsiMethod method : newClass.getConstructors()) {
                    if (resolveConstructor == method) {
                        final PsiElement place = usage.getElement();
                        if (place != null) {
                            VisibilityUtil.escalateVisibility(method, place);
                        }
                        break;
                    }
                }
            }
        }
        if (field != null) {
            final PsiExpression paramAccessExpression = factory.createExpressionFromText(myParameterNameOuterClass, null);
            for (final PsiMethod constructor : newClass.getConstructors()) {
                final PsiStatement[] statements = constructor.getBody().getStatements();
                if (statements.length > 0) {
                    if (statements[0] instanceof PsiExpressionStatement) {
                        PsiExpression expression = ((PsiExpressionStatement) statements[0]).getExpression();
                        if (expression instanceof PsiMethodCallExpression) {
                            @NonNls String text = ((PsiMethodCallExpression) expression).getMethodExpression().getText();
                            if ("this".equals(text) || "super".equals(text)) {
                                ChangeContextUtil.decodeContextInfo(expression, myOuterClass, paramAccessExpression);
                            }
                        }
                    }
                }
            }
            PsiExpression accessExpression = factory.createExpressionFromText(myFieldNameOuterClass, null);
            ChangeContextUtil.decodeContextInfo(newClass, myOuterClass, accessExpression);
        } else {
            ChangeContextUtil.decodeContextInfo(newClass, null, null);
        }
        if (myOpenInEditor) {
            EditorHelper.openInEditor(newClass);
        }
        if (myMoveCallback != null) {
            myMoveCallback.refactoringCompleted();
        }
        elementListener.elementMoved(newClass);
        List<NonCodeUsageInfo> nonCodeUsages = new ArrayList<>();
        for (UsageInfo usage : usages) {
            if (usage instanceof NonCodeUsageInfo) {
                nonCodeUsages.add((NonCodeUsageInfo) usage);
            }
        }
        myNonCodeUsages = nonCodeUsages.toArray(new NonCodeUsageInfo[nonCodeUsages.size()]);
    } catch (IncorrectOperationException e) {
        LOG.error(e);
    }
}
Also used : NonCodeUsageInfo(com.intellij.refactoring.util.NonCodeUsageInfo) UsageInfo(com.intellij.usageView.UsageInfo) NonCodeUsageInfo(com.intellij.refactoring.util.NonCodeUsageInfo) LocalSearchScope(com.intellij.psi.search.LocalSearchScope) NonNls(org.jetbrains.annotations.NonNls) RefactoringElementListener(com.intellij.refactoring.listeners.RefactoringElementListener) IncorrectOperationException(com.intellij.util.IncorrectOperationException)

Aggregations

NonCodeUsageInfo (com.intellij.refactoring.util.NonCodeUsageInfo)7 PsiElement (com.intellij.psi.PsiElement)4 UsageInfo (com.intellij.usageView.UsageInfo)4 PsiFile (com.intellij.psi.PsiFile)3 RefactoringElementListener (com.intellij.refactoring.listeners.RefactoringElementListener)3 MoveRenameUsageInfo (com.intellij.refactoring.util.MoveRenameUsageInfo)3 IncorrectOperationException (com.intellij.util.IncorrectOperationException)3 PsiReference (com.intellij.psi.PsiReference)2 DescriptiveNameUtil (com.intellij.lang.findUsages.DescriptiveNameUtil)1 JSReferenceExpression (com.intellij.lang.javascript.psi.JSReferenceExpression)1 JSVarStatement (com.intellij.lang.javascript.psi.JSVarStatement)1 JSVariable (com.intellij.lang.javascript.psi.JSVariable)1 JSClass (com.intellij.lang.javascript.psi.ecmal4.JSClass)1 JSQualifiedNamedElement (com.intellij.lang.javascript.psi.ecmal4.JSQualifiedNamedElement)1 FormatFixer (com.intellij.lang.javascript.refactoring.FormatFixer)1 ApplicationManager (com.intellij.openapi.application.ApplicationManager)1 ModalityState (com.intellij.openapi.application.ModalityState)1 Logger (com.intellij.openapi.diagnostic.Logger)1 Extensions (com.intellij.openapi.extensions.Extensions)1 OpenFileDescriptor (com.intellij.openapi.fileEditor.OpenFileDescriptor)1