use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.
the class PyReferenceImpl method getResultsFromProcessor.
protected List<RatedResolveResult> getResultsFromProcessor(@NotNull String referencedName, @NotNull PyResolveProcessor processor, @Nullable PsiElement realContext, @Nullable PsiElement resolveRoof) {
boolean unreachableLocalDeclaration = false;
boolean resolveInParentScope = false;
final ResolveResultList resultList = new ResolveResultList();
final ScopeOwner referenceOwner = ScopeUtil.getScopeOwner(realContext);
final TypeEvalContext typeEvalContext = myContext.getTypeEvalContext();
ScopeOwner resolvedOwner = processor.getOwner();
if (resolvedOwner != null && !processor.getResults().isEmpty()) {
final Collection<PsiElement> resolvedElements = processor.getElements();
final Scope resolvedScope = ControlFlowCache.getScope(resolvedOwner);
if (!resolvedScope.isGlobal(referencedName)) {
if (resolvedOwner == referenceOwner) {
final List<Instruction> instructions = PyDefUseUtil.getLatestDefs(resolvedOwner, referencedName, realContext, false, true);
// TODO: Use the results from the processor as a cache for resolving to latest defs
final ResolveResultList latestDefs = resolveToLatestDefs(instructions, realContext, referencedName, typeEvalContext);
if (!latestDefs.isEmpty()) {
return latestDefs;
} else if (resolvedOwner instanceof PyClass || instructions.isEmpty() && allInOwnScopeComprehensions(resolvedElements)) {
resolveInParentScope = true;
} else if (PyiUtil.isInsideStubAnnotation(myElement)) {
for (PsiElement element : resolvedElements) {
resultList.poke(element, getRate(element, typeEvalContext));
}
return resultList;
} else {
unreachableLocalDeclaration = true;
}
} else if (referenceOwner != null) {
final Scope referenceScope = ControlFlowCache.getScope(referenceOwner);
if (referenceScope.containsDeclaration(referencedName)) {
unreachableLocalDeclaration = true;
}
}
}
}
if (!unreachableLocalDeclaration) {
if (resolveInParentScope) {
processor = new PyResolveProcessor(referencedName);
resolvedOwner = ScopeUtil.getScopeOwner(resolvedOwner);
if (resolvedOwner != null) {
PyResolveUtil.scopeCrawlUp(processor, resolvedOwner, referencedName, resolveRoof);
}
}
for (Map.Entry<PsiElement, PyImportedNameDefiner> entry : processor.getResults().entrySet()) {
final PsiElement resolved = entry.getKey();
final PyImportedNameDefiner definer = entry.getValue();
if (resolved != null) {
if (typeEvalContext.maySwitchToAST(resolved) && isInnerComprehension(realContext, resolved)) {
continue;
}
if (skipClassForwardReferences(referenceOwner, resolved)) {
continue;
}
if (definer == null) {
resultList.poke(resolved, getRate(resolved, typeEvalContext));
} else {
resultList.poke(definer, getRate(definer, typeEvalContext));
resultList.add(new ImportedResolveResult(resolved, getRate(resolved, typeEvalContext), definer));
}
} else if (definer != null) {
resultList.add(new ImportedResolveResult(null, RatedResolveResult.RATE_LOW, definer));
}
}
if (!resultList.isEmpty()) {
return resultList;
}
}
return resolveByReferenceResolveProviders();
}
use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.
the class PyNamedParameterImpl method collectUsedAttributes.
@NotNull
private Set<String> collectUsedAttributes(@NotNull final TypeEvalContext context) {
final Set<String> result = new LinkedHashSet<>();
final ScopeOwner owner = ScopeUtil.getScopeOwner(this);
final String name = getName();
if (owner != null && name != null) {
owner.accept(new PyRecursiveElementVisitor() {
@Override
public void visitPyElement(PyElement node) {
if (node instanceof ScopeOwner && node != owner) {
return;
}
if (node instanceof PyQualifiedExpression) {
final PyQualifiedExpression expr = (PyQualifiedExpression) node;
final PyExpression qualifier = expr.getQualifier();
if (qualifier != null) {
final String attributeName = expr.getReferencedName();
final PyExpression referencedExpr = node instanceof PyBinaryExpression && PyNames.isRightOperatorName(attributeName) ? ((PyBinaryExpression) node).getRightExpression() : qualifier;
if (referencedExpr != null) {
final PsiReference ref = referencedExpr.getReference();
if (ref != null && ref.isReferenceTo(PyNamedParameterImpl.this)) {
if (attributeName != null && !result.contains(attributeName)) {
result.add(attributeName);
}
}
}
} else {
final PsiReference ref = expr.getReference();
if (ref != null && ref.isReferenceTo(PyNamedParameterImpl.this)) {
StreamEx.of(getParametersByCallArgument(expr, context)).nonNull().map(context::getType).select(PyStructuralType.class).forEach(type -> result.addAll(type.getAttributeNames()));
}
}
}
super.visitPyElement(node);
}
@Override
public void visitPyIfStatement(PyIfStatement node) {
final PyExpression ifCondition = node.getIfPart().getCondition();
if (ifCondition != null) {
ifCondition.accept(this);
}
for (PyIfPart part : node.getElifParts()) {
final PyExpression elseIfCondition = part.getCondition();
if (elseIfCondition != null) {
elseIfCondition.accept(this);
}
}
}
@Override
public void visitPyCallExpression(PyCallExpression node) {
Optional.ofNullable(node.getCallee()).filter(callee -> "len".equals(callee.getName())).map(PyExpression::getReference).map(PsiReference::resolve).filter(element -> PyBuiltinCache.getInstance(element).isBuiltin(element)).ifPresent(callable -> {
final PyReferenceExpression argument = node.getArgument(0, PyReferenceExpression.class);
if (argument != null && argument.getReference().isReferenceTo(PyNamedParameterImpl.this)) {
result.add(PyNames.LEN);
}
});
super.visitPyCallExpression(node);
}
@Override
public void visitPyForStatement(PyForStatement node) {
Optional.of(node.getForPart()).map(PyForPart::getSource).map(PyExpression::getReference).filter(reference -> reference.isReferenceTo(PyNamedParameterImpl.this)).ifPresent(reference -> result.add(PyNames.ITER));
super.visitPyForStatement(node);
}
});
}
return result;
}
use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.
the class AbstractPythonLegacyTestRunConfiguration method getRefactoringElementListener.
@Override
public RefactoringElementListener getRefactoringElementListener(PsiElement element) {
if (element instanceof PsiDirectory) {
VirtualFile vFile = ((PsiDirectory) element).getVirtualFile();
if ((myTestType == TestType.TEST_FOLDER && pathsEqual(vFile, myFolderName)) || pathsEqual(vFile, getWorkingDirectory())) {
return new RefactoringElementAdapter() {
@Override
protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
String newPath = FileUtil.toSystemDependentName(((PsiDirectory) newElement).getVirtualFile().getPath());
setWorkingDirectory(newPath);
if (myTestType == TestType.TEST_FOLDER) {
myFolderName = newPath;
}
}
@Override
public void undoElementMovedOrRenamed(@NotNull PsiElement newElement, @NotNull String oldQualifiedName) {
final String systemDependant = FileUtil.toSystemDependentName(oldQualifiedName);
setWorkingDirectory(systemDependant);
if (myTestType == TestType.TEST_FOLDER) {
myFolderName = systemDependant;
}
}
};
}
return null;
}
if (myTestType == TestType.TEST_FOLDER) {
return null;
}
File scriptFile = new File(myScriptName);
if (!scriptFile.isAbsolute()) {
scriptFile = new File(getWorkingDirectory(), myScriptName);
}
PsiFile containingFile = element.getContainingFile();
VirtualFile vFile = containingFile == null ? null : containingFile.getVirtualFile();
if (vFile != null && Comparing.equal(new File(vFile.getPath()).getAbsolutePath(), scriptFile.getAbsolutePath())) {
if (element instanceof PsiFile) {
return new RefactoringElementAdapter() {
@Override
protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
VirtualFile virtualFile = ((PsiFile) newElement).getVirtualFile();
if (virtualFile != null) {
myScriptName = FileUtil.toSystemDependentName(virtualFile.getPath());
}
}
@Override
public void undoElementMovedOrRenamed(@NotNull PsiElement newElement, @NotNull String oldQualifiedName) {
myScriptName = FileUtil.toSystemDependentName(oldQualifiedName);
}
};
}
if (element instanceof PyClass && (myTestType == TestType.TEST_CLASS || myTestType == TestType.TEST_METHOD) && Comparing.equal(((PyClass) element).getName(), myClassName)) {
return new RefactoringElementAdapter() {
@Override
protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
myClassName = ((PyClass) newElement).getName();
}
@Override
public void undoElementMovedOrRenamed(@NotNull PsiElement newElement, @NotNull String oldQualifiedName) {
myClassName = oldQualifiedName;
}
};
}
if (element instanceof PyFunction && Comparing.equal(((PyFunction) element).getName(), myMethodName)) {
ScopeOwner scopeOwner = PsiTreeUtil.getParentOfType(element, ScopeOwner.class);
if ((myTestType == TestType.TEST_FUNCTION && scopeOwner instanceof PyFile) || (myTestType == TestType.TEST_METHOD && scopeOwner instanceof PyClass && Comparing.equal(scopeOwner.getName(), myClassName))) {
return new RefactoringElementAdapter() {
@Override
protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
myMethodName = ((PyFunction) newElement).getName();
}
@Override
public void undoElementMovedOrRenamed(@NotNull PsiElement newElement, @NotNull String oldQualifiedName) {
final int methodIdx = oldQualifiedName.indexOf("#") + 1;
if (methodIdx > 0 && methodIdx < oldQualifiedName.length()) {
myMethodName = oldQualifiedName.substring(methodIdx);
}
}
};
}
}
}
return null;
}
use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.
the class PyUnreachableCodeInspection method hasAnyInterruptedControlFlowPaths.
public static boolean hasAnyInterruptedControlFlowPaths(@NotNull PsiElement element) {
final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
if (owner != null) {
final ControlFlow flow = ControlFlowCache.getControlFlow(owner);
final Instruction[] instructions = flow.getInstructions();
final int start = ControlFlowUtil.findInstructionNumberByElement(instructions, element);
if (start >= 0) {
final Ref<Boolean> resultRef = Ref.create(false);
ControlFlowUtil.iteratePrev(start, instructions, instruction -> {
if (instruction.allPred().isEmpty() && !isFirstInstruction(instruction)) {
resultRef.set(true);
return ControlFlowUtil.Operation.BREAK;
}
return ControlFlowUtil.Operation.NEXT;
});
return resultRef.get();
}
}
return false;
}
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);
}
}
Aggregations