Search in sources :

Example 21 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.

the class ImportToggleAliasIntention method doInvoke.

@Override
public void doInvoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
    // sanity check: isAvailable must have set it.
    final IntentionState state = IntentionState.fromContext(editor, file);
    //
    // we set in in the source
    final String target_name;
    // we replace it in the source
    final String remove_name;
    PyReferenceExpression reference = sure(state.myImportElement.getImportReferenceExpression());
    // search for references to us with the right name
    try {
        String imported_name = PyPsiUtils.toPath(reference);
        if (state.myAlias != null) {
            // have to remove alias, rename everything to original
            target_name = imported_name;
            remove_name = state.myAlias;
        } else {
            // ask for and add alias
            Application application = ApplicationManager.getApplication();
            if (application != null && !application.isUnitTestMode()) {
                String alias = Messages.showInputDialog(project, PyBundle.message("INTN.alias.for.$0.dialog.title", imported_name), "Add Alias", Messages.getQuestionIcon(), "", new InputValidator() {

                    @Override
                    public boolean checkInput(String inputString) {
                        return PyNames.isIdentifier(inputString);
                    }

                    @Override
                    public boolean canClose(String inputString) {
                        return PyNames.isIdentifier(inputString);
                    }
                });
                if (alias == null) {
                    return;
                }
                target_name = alias;
            } else {
                // test mode
                target_name = "alias";
            }
            remove_name = imported_name;
        }
        final PsiElement referee = reference.getReference().resolve();
        if (referee != null && imported_name != null) {
            final Collection<PsiReference> references = new ArrayList<>();
            final ScopeOwner scope = PsiTreeUtil.getParentOfType(state.myImportElement, ScopeOwner.class);
            PsiTreeUtil.processElements(scope, new PsiElementProcessor() {

                public boolean execute(@NotNull PsiElement element) {
                    getReferences(element);
                    if (element instanceof PyStringLiteralExpression) {
                        final PsiLanguageInjectionHost host = (PsiLanguageInjectionHost) element;
                        final List<Pair<PsiElement, TextRange>> files = InjectedLanguageManager.getInstance(project).getInjectedPsiFiles(host);
                        if (files != null) {
                            for (Pair<PsiElement, TextRange> pair : files) {
                                final PsiElement first = pair.getFirst();
                                if (first instanceof ScopeOwner) {
                                    final ScopeOwner scopeOwner = (ScopeOwner) first;
                                    PsiTreeUtil.processElements(scopeOwner, new PsiElementProcessor() {

                                        public boolean execute(@NotNull PsiElement element) {
                                            getReferences(element);
                                            return true;
                                        }
                                    });
                                }
                            }
                        }
                    }
                    return true;
                }

                private void getReferences(PsiElement element) {
                    if (element instanceof PyReferenceExpression && PsiTreeUtil.getParentOfType(element, PyImportElement.class) == null) {
                        PyReferenceExpression ref = (PyReferenceExpression) element;
                        if (remove_name.equals(PyPsiUtils.toPath(ref))) {
                            // filter out other names that might resolve to our target
                            PsiElement resolved = ref.getReference().resolve();
                            if (resolved == referee)
                                references.add(ref.getReference());
                        }
                    }
                }
            });
            // no references here is OK by us.
            if (showConflicts(project, findDefinitions(target_name, references, Collections.<PsiElement>emptySet()), target_name, null)) {
                // got conflicts
                return;
            }
            // alter the import element
            PyElementGenerator generator = PyElementGenerator.getInstance(project);
            final LanguageLevel languageLevel = LanguageLevel.forElement(state.myImportElement);
            if (state.myAlias != null) {
                // remove alias
                ASTNode node = sure(state.myImportElement.getNode());
                ASTNode parent = sure(node.getTreeParent());
                // this is the reference
                node = sure(node.getFirstChildNode());
                // things past the reference: space, 'as', and alias
                node = sure(node.getTreeNext());
                parent.removeRange(node, null);
            } else {
                // add alias
                ASTNode my_ielt_node = sure(state.myImportElement.getNode());
                PyImportElement fountain = generator.createFromText(languageLevel, PyImportElement.class, "import foo as " + target_name, new int[] { 0, 2 });
                // at import elt
                ASTNode graft_node = sure(fountain.getNode());
                // at ref
                graft_node = sure(graft_node.getFirstChildNode());
                // space
                graft_node = sure(graft_node.getTreeNext());
                my_ielt_node.addChild((ASTNode) graft_node.clone());
                // 'as'
                graft_node = sure(graft_node.getTreeNext());
                my_ielt_node.addChild((ASTNode) graft_node.clone());
                // space
                graft_node = sure(graft_node.getTreeNext());
                my_ielt_node.addChild((ASTNode) graft_node.clone());
                // alias
                graft_node = sure(graft_node.getTreeNext());
                my_ielt_node.addChild((ASTNode) graft_node.clone());
            }
            // alter references
            for (PsiReference ref : references) {
                ASTNode ref_name_node = sure(sure(ref.getElement()).getNode());
                ASTNode parent = sure(ref_name_node.getTreeParent());
                ASTNode new_name_node = generator.createExpressionFromText(languageLevel, target_name).getNode();
                assert new_name_node != null;
                parent.replaceChild(ref_name_node, new_name_node);
            }
        }
    } catch (IncorrectOperationException ignored) {
        PyUtil.showBalloon(project, PyBundle.message("QFIX.action.failed"), MessageType.WARNING);
    }
}
Also used : ArrayList(java.util.ArrayList) PsiReference(com.intellij.psi.PsiReference) TextRange(com.intellij.openapi.util.TextRange) NotNull(org.jetbrains.annotations.NotNull) PsiElementProcessor(com.intellij.psi.search.PsiElementProcessor) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) InputValidator(com.intellij.openapi.ui.InputValidator) PsiLanguageInjectionHost(com.intellij.psi.PsiLanguageInjectionHost) ASTNode(com.intellij.lang.ASTNode) ArrayList(java.util.ArrayList) List(java.util.List) IncorrectOperationException(com.intellij.util.IncorrectOperationException) Application(com.intellij.openapi.application.Application) PsiElement(com.intellij.psi.PsiElement) Pair(com.intellij.openapi.util.Pair)

Example 22 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.

the class PyUnusedLocalInspectionVisitor method visitPyStringLiteralExpression.

@Override
public void visitPyStringLiteralExpression(PyStringLiteralExpression pyString) {
    final ScopeOwner owner = ScopeUtil.getScopeOwner(pyString);
    if (owner != null && !(owner instanceof PsiFile)) {
        final PyStatement instrAnchor = PsiTreeUtil.getParentOfType(pyString, PyStatement.class);
        if (instrAnchor == null)
            return;
        final Instruction[] instructions = ControlFlowCache.getControlFlow(owner).getInstructions();
        final int startInstruction = ControlFlowUtil.findInstructionNumberByElement(instructions, instrAnchor);
        if (startInstruction < 0)
            return;
        final Project project = pyString.getProject();
        final List<Pair<PsiElement, TextRange>> pairs = InjectedLanguageManager.getInstance(project).getInjectedPsiFiles(pyString);
        if (pairs != null) {
            for (Pair<PsiElement, TextRange> pair : pairs) {
                pair.getFirst().accept(new PyRecursiveElementVisitor() {

                    @Override
                    public void visitPyReferenceExpression(PyReferenceExpression expr) {
                        final PyExpression qualifier = expr.getQualifier();
                        if (qualifier != null) {
                            qualifier.accept(this);
                            return;
                        }
                        final String name = expr.getName();
                        if (name != null) {
                            analyzeReadsInScope(name, owner, instructions, startInstruction, pyString);
                        }
                    }
                });
            }
        }
    }
}
Also used : TextRange(com.intellij.openapi.util.TextRange) ReadWriteInstruction(com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction) Instruction(com.intellij.codeInsight.controlflow.Instruction) Project(com.intellij.openapi.project.Project) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) PsiFile(com.intellij.psi.PsiFile) PsiElement(com.intellij.psi.PsiElement) Pair(com.intellij.openapi.util.Pair)

Example 23 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.

the class PyUnusedLocalInspectionVisitor method analyzeReadsInScope.

private void analyzeReadsInScope(@NotNull String name, @NotNull ScopeOwner owner, @NotNull Instruction[] instructions, int startInstruction, @Nullable PsiElement scopeAnchor) {
    // Check if the element is declared out of scope, mark all out of scope write accesses as used
    if (scopeAnchor != null) {
        final ScopeOwner declOwner = ScopeUtil.getDeclarationScopeOwner(scopeAnchor, name);
        if (declOwner != null && declOwner != owner) {
            final Collection<PsiElement> writeElements = ScopeUtil.getReadWriteElements(name, declOwner, false, true);
            for (PsiElement e : writeElements) {
                myUsedElements.add(e);
                myUnusedElements.remove(e);
            }
        }
    }
    ControlFlowUtil.iteratePrev(startInstruction, instructions, inst -> {
        final PsiElement instElement = inst.getElement();
        if (instElement instanceof PyFunction) {
            if (name.equals(((PyFunction) instElement).getName())) {
                myUsedElements.add(instElement);
                myUnusedElements.remove(instElement);
                return ControlFlowUtil.Operation.CONTINUE;
            }
        } else if (inst instanceof ReadWriteInstruction) {
            final ReadWriteInstruction rwInstruction = (ReadWriteInstruction) inst;
            if (rwInstruction.getAccess().isWriteAccess() && name.equals(rwInstruction.getName())) {
                if (instElement != null && PsiTreeUtil.isAncestor(owner, instElement, false)) {
                    myUsedElements.add(instElement);
                    myUnusedElements.remove(instElement);
                }
                return ControlFlowUtil.Operation.CONTINUE;
            }
        }
        return ControlFlowUtil.Operation.NEXT;
    });
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) ReadWriteInstruction(com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction) PsiElement(com.intellij.psi.PsiElement)

Example 24 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.

the class PyDocReference method getHostScopeOwner.

@Nullable
private ScopeOwner getHostScopeOwner() {
    final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(myElement.getProject());
    final PsiLanguageInjectionHost host = languageManager.getInjectionHost(myElement);
    if (host != null) {
        final PsiFile file = host.getContainingFile();
        ScopeOwner result = ScopeUtil.getScopeOwner(host);
        if (result == null && file instanceof ScopeOwner) {
            result = (ScopeOwner) file;
        }
        return result;
    }
    return null;
}
Also used : InjectedLanguageManager(com.intellij.lang.injection.InjectedLanguageManager) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) PsiLanguageInjectionHost(com.intellij.psi.PsiLanguageInjectionHost) PsiFile(com.intellij.psi.PsiFile) Nullable(org.jetbrains.annotations.Nullable)

Example 25 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.

the class PyDocReference method getVariants.

@NotNull
public Object[] getVariants() {
    final ArrayList<Object> ret = Lists.newArrayList(super.getVariants());
    final PsiElement originalElement = CompletionUtil.getOriginalElement(myElement);
    final PyQualifiedExpression element = originalElement instanceof PyQualifiedExpression ? (PyQualifiedExpression) originalElement : myElement;
    final ScopeOwner scopeOwner = getHostScopeOwner();
    if (scopeOwner != null) {
        final CompletionVariantsProcessor processor = new CompletionVariantsProcessor(element);
        PyResolveUtil.scopeCrawlUp(processor, scopeOwner, null, null);
        ret.addAll(processor.getResultList());
    }
    return ret.toArray();
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

ScopeOwner (com.jetbrains.python.codeInsight.controlflow.ScopeOwner)51 PsiElement (com.intellij.psi.PsiElement)25 Nullable (org.jetbrains.annotations.Nullable)18 NotNull (org.jetbrains.annotations.NotNull)14 Pair (com.intellij.openapi.util.Pair)6 QualifiedName (com.intellij.psi.util.QualifiedName)6 ArrayList (java.util.ArrayList)6 Instruction (com.intellij.codeInsight.controlflow.Instruction)4 TextRange (com.intellij.openapi.util.TextRange)4 PsiFile (com.intellij.psi.PsiFile)4 Scope (com.jetbrains.python.codeInsight.dataflow.scope.Scope)4 List (java.util.List)4 LookupElement (com.intellij.codeInsight.lookup.LookupElement)3 Project (com.intellij.openapi.project.Project)3 Ref (com.intellij.openapi.util.Ref)3 PsiLanguageInjectionHost (com.intellij.psi.PsiLanguageInjectionHost)3 GlobalSearchScope (com.intellij.psi.search.GlobalSearchScope)3 TypeEvalContext (com.jetbrains.python.psi.types.TypeEvalContext)3 CannotCreateCodeFragmentException (com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException)2 ASTNode (com.intellij.lang.ASTNode)2