Search in sources :

Example 31 with ScopeOwner

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

the class PyTargetExpressionImpl method getUseScope.

@NotNull
@Override
public SearchScope getUseScope() {
    if (isQualified()) {
        return super.getUseScope();
    }
    final ScopeOwner owner = ScopeUtil.getScopeOwner(this);
    if (owner != null) {
        final Scope scope = ControlFlowCache.getScope(owner);
        if (scope.isGlobal(getName())) {
            return GlobalSearchScope.projectScope(getProject());
        }
        if (scope.isNonlocal(getName())) {
            return new LocalSearchScope(getContainingFile());
        }
    }
    // find highest level function containing our var
    PyElement container = this;
    while (true) {
        PyElement parentContainer = PsiTreeUtil.getParentOfType(container, PyFunction.class, PyClass.class);
        if (parentContainer instanceof PyClass) {
            if (isQualified()) {
                return super.getUseScope();
            }
            break;
        }
        if (parentContainer == null) {
            break;
        }
        container = parentContainer;
    }
    if (container instanceof PyFunction) {
        return new LocalSearchScope(container);
    }
    return super.getUseScope();
}
Also used : LocalSearchScope(com.intellij.psi.search.LocalSearchScope) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) SearchScope(com.intellij.psi.search.SearchScope) LocalSearchScope(com.intellij.psi.search.LocalSearchScope) Scope(com.jetbrains.python.codeInsight.dataflow.scope.Scope) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) NotNull(org.jetbrains.annotations.NotNull)

Example 32 with ScopeOwner

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

the class PyTargetExpressionImpl method resolveAssignedValue.

@Nullable
@Override
public PsiElement resolveAssignedValue(@NotNull PyResolveContext resolveContext) {
    final TypeEvalContext context = resolveContext.getTypeEvalContext();
    if (context.maySwitchToAST(this)) {
        final PyExpression value = findAssignedValue();
        if (value != null) {
            final List<PsiElement> results = PyUtil.multiResolveTopPriority(value, resolveContext);
            return !results.isEmpty() ? results.get(0) : null;
        }
        return null;
    } else {
        final QualifiedName qName = getAssignedQName();
        if (qName != null) {
            final ScopeOwner owner = ScopeUtil.getScopeOwner(this);
            if (owner instanceof PyTypedElement) {
                final List<String> components = qName.getComponents();
                if (!components.isEmpty()) {
                    PsiElement resolved = owner;
                    for (String component : components) {
                        if (!(resolved instanceof PyTypedElement)) {
                            return null;
                        }
                        final PyType qualifierType = context.getType((PyTypedElement) resolved);
                        if (qualifierType == null) {
                            return null;
                        }
                        final List<? extends RatedResolveResult> results = qualifierType.resolveMember(component, null, AccessDirection.READ, resolveContext);
                        if (results == null || results.isEmpty()) {
                            return null;
                        }
                        resolved = results.get(0).getElement();
                    }
                    return resolved;
                }
            }
        }
        return null;
    }
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) QualifiedName(com.intellij.psi.util.QualifiedName) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

Example 33 with ScopeOwner

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

the class ScopeUtil method calculateScopeOwnerByAST.

@Nullable
private static ScopeOwner calculateScopeOwnerByAST(@Nullable PsiElement element) {
    final ScopeOwner firstOwner = getParentOfType(element, ScopeOwner.class);
    if (firstOwner == null) {
        return null;
    }
    final ScopeOwner nextOwner = getParentOfType(firstOwner, ScopeOwner.class);
    // References in decorator expressions are resolved outside of the function (if the lambda is not inside the decorator)
    final PyElement decoratorAncestor = getParentOfType(element, PyDecorator.class);
    if (decoratorAncestor != null && !isAncestor(decoratorAncestor, firstOwner, true)) {
        return nextOwner;
    }
    // References in default values or in annotations of parameters are resolved outside of the function (if the lambda is not inside the
    // default value)
    final PyNamedParameter parameterAncestor = getParentOfType(element, PyNamedParameter.class);
    if (parameterAncestor != null && !isAncestor(parameterAncestor, firstOwner, true)) {
        final PyExpression defaultValue = parameterAncestor.getDefaultValue();
        final PyAnnotation annotation = parameterAncestor.getAnnotation();
        if (isAncestor(defaultValue, element, false) || isAncestor(annotation, element, false)) {
            return nextOwner;
        }
    }
    // Superclasses are resolved outside of the class
    final PyClass containingClass = getParentOfType(element, PyClass.class);
    if (containingClass != null && isAncestor(containingClass.getSuperClassExpressionList(), element, false)) {
        return nextOwner;
    }
    // Function return annotations are resolved outside of the function
    if (firstOwner instanceof PyFunction) {
        final PyFunction function = (PyFunction) firstOwner;
        final PyAnnotation annotation = function.getAnnotation();
        if (isAncestor(annotation, element, false)) {
            return nextOwner;
        }
    }
    return firstOwner;
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) Nullable(org.jetbrains.annotations.Nullable)

Example 34 with ScopeOwner

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

the class PyInlineLocalHandler method invoke.

private static void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PyTargetExpression local, @Nullable PyReferenceExpression refExpr) {
    if (!CommonRefactoringUtil.checkReadOnlyStatus(project, local))
        return;
    final HighlightManager highlightManager = HighlightManager.getInstance(project);
    final TextAttributes writeAttributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES);
    final String localName = local.getName();
    final ScopeOwner containerBlock = getContext(local);
    LOG.assertTrue(containerBlock != null);
    final Pair<PyStatement, Boolean> defPair = getAssignmentToInline(containerBlock, refExpr, local, project);
    final PyStatement def = defPair.first;
    if (def == null || getValue(def) == null) {
        final String key = defPair.second ? "variable.has.no.dominating.definition" : "variable.has.no.initializer";
        final String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message(key, localName));
        CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HELP_ID);
        return;
    }
    if (def instanceof PyAssignmentStatement && ((PyAssignmentStatement) def).getTargets().length > 1) {
        highlightManager.addOccurrenceHighlights(editor, new PsiElement[] { def }, writeAttributes, true, null);
        final String message = RefactoringBundle.getCannotRefactorMessage(PyBundle.message("refactoring.inline.local.multiassignment", localName));
        CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HELP_ID);
        return;
    }
    final PsiElement[] refsToInline = PyDefUseUtil.getPostRefs(containerBlock, local, getObject(def));
    if (refsToInline.length == 0) {
        final String message = RefactoringBundle.message("variable.is.never.used", localName);
        CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HELP_ID);
        return;
    }
    final TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
    if (!ApplicationManager.getApplication().isUnitTestMode()) {
        highlightManager.addOccurrenceHighlights(editor, refsToInline, attributes, true, null);
        final int occurrencesCount = refsToInline.length;
        final String occurrencesString = RefactoringBundle.message("occurrences.string", occurrencesCount);
        final String question = RefactoringBundle.message("inline.local.variable.prompt", localName) + " " + occurrencesString;
        final RefactoringMessageDialog dialog = new RefactoringMessageDialog(REFACTORING_NAME, question, HELP_ID, "OptionPane.questionIcon", true, project);
        if (!dialog.showAndGet()) {
            WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
            return;
        }
    }
    final PsiFile workingFile = local.getContainingFile();
    for (PsiElement ref : refsToInline) {
        final PsiFile otherFile = ref.getContainingFile();
        if (!otherFile.equals(workingFile)) {
            final String message = RefactoringBundle.message("variable.is.referenced.in.multiple.files", localName);
            CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HELP_ID);
            return;
        }
    }
    for (final PsiElement ref : refsToInline) {
        final List<PsiElement> elems = new ArrayList<>();
        final List<Instruction> latestDefs = PyDefUseUtil.getLatestDefs(containerBlock, local.getName(), ref, false, false);
        for (Instruction i : latestDefs) {
            elems.add(i.getElement());
        }
        final PsiElement[] defs = elems.toArray(new PsiElement[elems.size()]);
        boolean isSameDefinition = true;
        for (PsiElement otherDef : defs) {
            isSameDefinition &= isSameDefinition(def, otherDef);
        }
        if (!isSameDefinition) {
            highlightManager.addOccurrenceHighlights(editor, defs, writeAttributes, true, null);
            highlightManager.addOccurrenceHighlights(editor, new PsiElement[] { ref }, attributes, true, null);
            final String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.is.accessed.for.writing.and.used.with.inlined", localName));
            CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HELP_ID);
            WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
            return;
        }
    }
    CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> {
        try {
            final RefactoringEventData afterData = new RefactoringEventData();
            afterData.addElement(local);
            project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(getRefactoringId(), afterData);
            final PsiElement[] exprs = new PsiElement[refsToInline.length];
            final PyExpression value = prepareValue(def, localName, project);
            final PyExpression withParenthesis = PyElementGenerator.getInstance(project).createExpressionFromText("(" + value.getText() + ")");
            final PsiElement lastChild = def.getLastChild();
            if (lastChild != null && lastChild.getNode().getElementType() == PyTokenTypes.END_OF_LINE_COMMENT) {
                final PsiElement parent = def.getParent();
                if (parent != null)
                    parent.addBefore(lastChild, def);
            }
            for (int i = 0, refsToInlineLength = refsToInline.length; i < refsToInlineLength; i++) {
                final PsiElement element = refsToInline[i];
                if (PyReplaceExpressionUtil.isNeedParenthesis((PyExpression) element, value)) {
                    exprs[i] = element.replace(withParenthesis);
                } else {
                    exprs[i] = element.replace(value);
                }
            }
            final PsiElement next = def.getNextSibling();
            if (next instanceof PsiWhiteSpace) {
                PyPsiUtils.removeElements(next);
            }
            PyPsiUtils.removeElements(def);
            final List<TextRange> ranges = ContainerUtil.mapNotNull(exprs, element -> {
                final PyStatement parentalStatement = PsiTreeUtil.getParentOfType(element, PyStatement.class, false);
                return parentalStatement != null ? parentalStatement.getTextRange() : null;
            });
            PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
            CodeStyleManager.getInstance(project).reformatText(workingFile, ranges);
            if (!ApplicationManager.getApplication().isUnitTestMode()) {
                highlightManager.addOccurrenceHighlights(editor, exprs, attributes, true, null);
                WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
            }
        } finally {
            final RefactoringEventData afterData = new RefactoringEventData();
            afterData.addElement(local);
            project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(getRefactoringId(), afterData);
        }
    }), RefactoringBundle.message("inline.command", localName), null);
}
Also used : Language(com.intellij.lang.Language) EditorColorsManager(com.intellij.openapi.editor.colors.EditorColorsManager) RefactoringBundle(com.intellij.refactoring.RefactoringBundle) PythonLanguage(com.jetbrains.python.PythonLanguage) RefactoringEventListener(com.intellij.refactoring.listeners.RefactoringEventListener) ContainerUtil(com.intellij.util.containers.ContainerUtil) PyPsiUtils(com.jetbrains.python.psi.impl.PyPsiUtils) ArrayList(java.util.ArrayList) Query(com.intellij.util.Query) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) HighlightManager(com.intellij.codeInsight.highlighting.HighlightManager) Project(com.intellij.openapi.project.Project) com.jetbrains.python.psi(com.jetbrains.python.psi) RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData) Logger(com.intellij.openapi.diagnostic.Logger) Instruction(com.intellij.codeInsight.controlflow.Instruction) PyDefUseUtil(com.jetbrains.python.refactoring.PyDefUseUtil) Extensions(com.intellij.openapi.extensions.Extensions) ReferencesSearch(com.intellij.psi.search.searches.ReferencesSearch) PyBundle(com.jetbrains.python.PyBundle) InlineActionHandler(com.intellij.lang.refactoring.InlineActionHandler) PyReplaceExpressionUtil(com.jetbrains.python.refactoring.PyReplaceExpressionUtil) WindowManager(com.intellij.openapi.wm.WindowManager) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) PyTokenTypes(com.jetbrains.python.PyTokenTypes) TextRange(com.intellij.openapi.util.TextRange) RefactoringMessageDialog(com.intellij.refactoring.util.RefactoringMessageDialog) Editor(com.intellij.openapi.editor.Editor) CommandProcessor(com.intellij.openapi.command.CommandProcessor) CommonRefactoringUtil(com.intellij.refactoring.util.CommonRefactoringUtil) Nullable(org.jetbrains.annotations.Nullable) CodeStyleManager(com.intellij.psi.codeStyle.CodeStyleManager) List(java.util.List) EditorColors(com.intellij.openapi.editor.colors.EditorColors) TextAttributes(com.intellij.openapi.editor.markup.TextAttributes) Function(com.intellij.util.Function) Pair(com.intellij.openapi.util.Pair) TargetElementUtil(com.intellij.codeInsight.TargetElementUtil) ApplicationManager(com.intellij.openapi.application.ApplicationManager) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) com.intellij.psi(com.intellij.psi) NotNull(org.jetbrains.annotations.NotNull) RefactoringMessageDialog(com.intellij.refactoring.util.RefactoringMessageDialog) HighlightManager(com.intellij.codeInsight.highlighting.HighlightManager) ArrayList(java.util.ArrayList) Instruction(com.intellij.codeInsight.controlflow.Instruction) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData) TextAttributes(com.intellij.openapi.editor.markup.TextAttributes) ArrayList(java.util.ArrayList) List(java.util.List)

Example 35 with ScopeOwner

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

the class PyMoveFileHandler method updateRelativeImportsInModule.

private static void updateRelativeImportsInModule(@NotNull PyFile module) {
    final String originalLocation = module.getUserData(ORIGINAL_FILE_LOCATION);
    if (originalLocation == null) {
        return;
    }
    //module.putUserData(ORIGINAL_FILE_LOCATION, null);
    for (PyFromImportStatement statement : module.getFromImports()) {
        if (!canBeRelative(statement)) {
            continue;
        }
        final int relativeLevel = Math.max(statement.getRelativeLevel(), 1);
        final PsiFileSystemItem sourceElement = resolveRelativeImportFromModuleLocation(statement.getManager(), originalLocation, statement.getImportSource(), relativeLevel);
        if (sourceElement == null) {
            continue;
        }
        final QualifiedName newName = QualifiedNameFinder.findShortestImportableQName(sourceElement);
        replaceRelativeImportSourceWithQualifiedExpression(statement, newName);
    }
    for (PyImportElement importElement : module.getImportTargets()) {
        final PyReferenceExpression referenceExpr = importElement.getImportReferenceExpression();
        if (!canBeRelative(importElement) || referenceExpr == null) {
            continue;
        }
        final PsiFileSystemItem resolved = resolveRelativeImportFromModuleLocation(importElement.getManager(), originalLocation, referenceExpr, 1);
        if (resolved == null) {
            continue;
        }
        final QualifiedName newName = QualifiedNameFinder.findShortestImportableQName(resolved);
        replaceWithQualifiedExpression(referenceExpr, newName);
        final QualifiedName oldQualifiedName = referenceExpr.asQualifiedName();
        if (!Comparing.equal(oldQualifiedName, newName)) {
            final ScopeOwner scopeOwner = ScopeUtil.getScopeOwner(importElement);
            if (scopeOwner == null) {
                continue;
            }
            scopeOwner.accept(new PyRecursiveElementVisitor() {

                @Override
                public void visitPyReferenceExpression(PyReferenceExpression node) {
                    if (Comparing.equal(node.asQualifiedName(), oldQualifiedName)) {
                        replaceWithQualifiedExpression(node, newName);
                    } else {
                        super.visitPyReferenceExpression(node);
                    }
                }
            });
        }
    }
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) QualifiedName(com.intellij.psi.util.QualifiedName)

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