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();
}
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;
}
}
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;
}
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);
}
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);
}
}
});
}
}
}
Aggregations