use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.
the class AddGlobalQuickFix method applyFix.
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
PsiElement problemElt = descriptor.getPsiElement();
if (problemElt instanceof PyReferenceExpression) {
final PyReferenceExpression expression = (PyReferenceExpression) problemElt;
final String name = expression.getReferencedName();
final ScopeOwner owner = PsiTreeUtil.getParentOfType(problemElt, ScopeOwner.class);
assert owner instanceof PyClass || owner instanceof PyFunction : "Add global quickfix is available only inside class or function, but applied for " + owner;
final Ref<Boolean> added = new Ref<>(false);
owner.accept(new PyRecursiveElementVisitor() {
@Override
public void visitElement(PsiElement element) {
if (!added.get()) {
super.visitElement(element);
}
}
@Override
public void visitPyGlobalStatement(final PyGlobalStatement node) {
if (!added.get()) {
node.addGlobal(name);
added.set(true);
}
}
});
if (added.get()) {
return;
}
final PyGlobalStatement globalStatement = PyElementGenerator.getInstance(project).createFromText(LanguageLevel.getDefault(), PyGlobalStatement.class, "global " + name);
final PyStatementList statementList;
boolean hasDocString = false;
if (owner instanceof PyClass) {
statementList = ((PyClass) owner).getStatementList();
if (((PyClass) owner).getDocStringExpression() != null)
hasDocString = true;
} else {
statementList = ((PyFunction) owner).getStatementList();
if (((PyFunction) owner).getDocStringExpression() != null)
hasDocString = true;
}
PyStatement first = statementList.getStatements()[0];
if (hasDocString)
first = statementList.getStatements()[1];
statementList.addBefore(globalStatement, first);
}
}
use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.
the class PyRenameUnresolvedRefQuickFix method applyFix.
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (!(element instanceof PyReferenceExpression)) {
return;
}
final PyReferenceExpression referenceExpression = (PyReferenceExpression) element;
ScopeOwner parentScope = ScopeUtil.getScopeOwner(referenceExpression);
if (parentScope == null)
return;
List<PyReferenceExpression> refs = collectExpressionsToRename(referenceExpression, parentScope);
LookupElement[] items = collectLookupItems(parentScope);
final String name = referenceExpression.getReferencedName();
ReferenceNameExpression refExpr = new ReferenceNameExpression(items, name);
TemplateBuilderImpl builder = (TemplateBuilderImpl) TemplateBuilderFactory.getInstance().createTemplateBuilder(parentScope);
for (PyReferenceExpression expr : refs) {
if (!expr.equals(referenceExpression)) {
builder.replaceElement(expr, name, name, false);
} else {
builder.replaceElement(expr, name, refExpr, true);
}
}
Editor editor = getEditor(project, element.getContainingFile(), parentScope.getTextRange().getStartOffset());
if (editor != null) {
Template template = builder.buildInlineTemplate();
TemplateManager.getInstance(project).startTemplate(editor, template);
}
}
use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.
the class PyReferenceImpl method resolvesToSameLocal.
private boolean resolvesToSameLocal(PsiElement element, String elementName, ScopeOwner ourScopeOwner, ScopeOwner theirScopeOwner) {
final PsiElement ourContainer = findContainer(getElement());
final PsiElement theirContainer = findContainer(element);
if (ourContainer != null) {
if (ourContainer == theirContainer) {
return true;
}
if (PsiTreeUtil.isAncestor(theirContainer, ourContainer, true)) {
if (ourContainer instanceof PyComprehensionElement && containsDeclaration((PyComprehensionElement) ourContainer, elementName)) {
return false;
}
ScopeOwner owner = ourScopeOwner;
while (owner != theirScopeOwner && owner != null) {
if (ControlFlowCache.getScope(owner).containsDeclaration(elementName)) {
return false;
}
owner = ScopeUtil.getScopeOwner(owner);
}
return true;
}
}
return false;
}
use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.
the class PyReferenceImpl method findResolveRoof.
private PsiElement findResolveRoof(String referencedName, PsiElement realContext) {
if (PyUtil.isClassPrivateName(referencedName)) {
// a class-private name; limited by either class or this file
PsiElement one = myElement;
do {
one = ScopeUtil.getScopeOwner(one);
} while (one instanceof PyFunction);
if (one instanceof PyClass) {
PyArgumentList superClassExpressionList = ((PyClass) one).getSuperClassExpressionList();
if (superClassExpressionList == null || !PsiTreeUtil.isAncestor(superClassExpressionList, myElement, false)) {
return one;
}
}
}
if (myElement instanceof PyTargetExpression) {
final ScopeOwner scopeOwner = PsiTreeUtil.getParentOfType(myElement, ScopeOwner.class);
final Scope scope;
if (scopeOwner != null) {
scope = ControlFlowCache.getScope(scopeOwner);
final String name = myElement.getName();
if (scope.isNonlocal(name)) {
final ScopeOwner nonlocalOwner = ScopeUtil.getDeclarationScopeOwner(myElement, referencedName);
if (nonlocalOwner != null && !(nonlocalOwner instanceof PyFile)) {
return nonlocalOwner;
}
}
if (!scope.isGlobal(name)) {
return scopeOwner;
}
}
}
return realContext.getContainingFile();
}
use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.
the class PyReferenceImpl method isReferenceTo.
@Override
public boolean isReferenceTo(PsiElement element) {
if (element instanceof PsiFileSystemItem) {
// may be import via alias, so don't check if names match, do simple resolve check instead
PsiElement resolveResult = resolve();
if (resolveResult instanceof PyImportedModule) {
resolveResult = resolveResult.getNavigationElement();
}
if (element instanceof PsiDirectory) {
if (resolveResult instanceof PyFile) {
final PyFile file = (PyFile) resolveResult;
if (PyUtil.isPackage(file) && file.getContainingDirectory() == element) {
return true;
}
} else if (resolveResult instanceof PsiDirectory) {
final PsiDirectory directory = (PsiDirectory) resolveResult;
if (PyUtil.isPackage(directory, null) && directory == element) {
return true;
}
}
}
return resolveResult == element;
}
if (element instanceof PsiNamedElement) {
final String elementName = ((PsiNamedElement) element).getName();
if ((Comparing.equal(myElement.getReferencedName(), elementName) || PyNames.INIT.equals(elementName))) {
if (!haveQualifiers(element)) {
final ScopeOwner ourScopeOwner = ScopeUtil.getScopeOwner(getElement());
final ScopeOwner theirScopeOwner = ScopeUtil.getScopeOwner(element);
if (element instanceof PyParameter || element instanceof PyTargetExpression) {
// Check if the reference is in the same or inner scope of the element scope, not shadowed by an intermediate declaration
if (resolvesToSameLocal(element, elementName, ourScopeOwner, theirScopeOwner)) {
return true;
}
}
final PsiElement resolveResult = resolve();
if (resolveResult == element) {
return true;
}
// we shadow their name or they shadow ours (PY-6241)
if (resolveResult instanceof PsiNamedElement && resolveResult instanceof ScopeOwner && element instanceof ScopeOwner && theirScopeOwner == ScopeUtil.getScopeOwner(resolveResult)) {
return true;
}
if (!haveQualifiers(element) && ourScopeOwner != null && theirScopeOwner != null) {
if (resolvesToSameGlobal(element, elementName, ourScopeOwner, theirScopeOwner, resolveResult))
return true;
}
if (resolvesToWrapper(element, resolveResult)) {
return true;
}
}
if (element instanceof PyExpression) {
final PyExpression expr = (PyExpression) element;
if (PyUtil.isClassAttribute(myElement) && (PyUtil.isClassAttribute(expr) || PyUtil.isInstanceAttribute(expr))) {
final PyClass c1 = PsiTreeUtil.getParentOfType(element, PyClass.class);
final PyClass c2 = PsiTreeUtil.getParentOfType(myElement, PyClass.class);
final TypeEvalContext context = myContext.getTypeEvalContext();
if (c1 != null && c2 != null && (c1.isSubclass(c2, context) || c2.isSubclass(c1, context))) {
return true;
}
}
}
}
}
return false;
}
Aggregations