com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of python-community Show documentation
Show all versions of python-community Show documentation
A packaging of the IntelliJ Community Edition python-community library.
This is release number 1 of trunk branch 142.
The newest version!
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.codeInsight.dataflow.scope;
import com.intellij.codeInsight.controlflow.ControlFlow;
import com.intellij.codeInsight.controlflow.Instruction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.StubBasedPsiElement;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyExceptPartNavigator;
import com.jetbrains.python.psi.impl.PyForStatementNavigator;
import com.jetbrains.python.psi.impl.PyListCompExpressionNavigator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import static com.intellij.psi.util.PsiTreeUtil.getParentOfType;
import static com.intellij.psi.util.PsiTreeUtil.isAncestor;
/**
* @author oleg
*/
public class ScopeUtil {
private ScopeUtil() {
}
@Nullable
public static PsiElement getParameterScope(final PsiElement element){
if (element instanceof PyNamedParameter){
final PyFunction function = getParentOfType(element, PyFunction.class, false);
if (function != null){
return function;
}
}
final PyExceptPart exceptPart = PyExceptPartNavigator.getPyExceptPartByTarget(element);
if (exceptPart != null){
return exceptPart;
}
final PyForStatement forStatement = PyForStatementNavigator.getPyForStatementByIterable(element);
if (forStatement != null){
return forStatement;
}
final PyListCompExpression listCompExpression = PyListCompExpressionNavigator.getPyListCompExpressionByVariable(element);
if (listCompExpression != null){
return listCompExpression;
}
return null;
}
/**
* Return the scope owner for the element.
*
* Scope owner is not always the first ScopeOwner parent of the element. Some elements are resolved in outer scopes.
*/
@Nullable
public static ScopeOwner getScopeOwner(@Nullable PsiElement element) {
if (element instanceof StubBasedPsiElement) {
final StubElement stub = ((StubBasedPsiElement)element).getStub();
if (stub != null) {
StubElement parentStub = stub.getParentStub();
while (parentStub != null) {
final PsiElement parent = parentStub.getPsi();
if (parent instanceof ScopeOwner) {
return (ScopeOwner)parent;
}
parentStub = parentStub.getParentStub();
}
return null;
}
}
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;
}
@Nullable
public static ScopeOwner getDeclarationScopeOwner(PsiElement anchor, String name) {
PsiElement element = anchor;
if (name != null) {
final ScopeOwner originalScopeOwner = getScopeOwner(element);
ScopeOwner scopeOwner = originalScopeOwner;
while (scopeOwner != null) {
if (!(scopeOwner instanceof PyClass) || scopeOwner == originalScopeOwner) {
Scope scope = ControlFlowCache.getScope(scopeOwner);
if (scope.containsDeclaration(name)) {
return scopeOwner;
}
}
scopeOwner = getScopeOwner(scopeOwner);
}
}
return null;
}
@NotNull
public static Collection getReadWriteElements(@NotNull String name, @NotNull ScopeOwner scopeOwner, boolean isReadAccess,
boolean isWriteAccess) {
ControlFlow flow = ControlFlowCache.getControlFlow(scopeOwner);
Collection result = new ArrayList();
for (Instruction instr : flow.getInstructions()) {
if (instr instanceof ReadWriteInstruction) {
ReadWriteInstruction rw = (ReadWriteInstruction)instr;
if (name.equals(rw.getName())) {
ReadWriteInstruction.ACCESS access = rw.getAccess();
if ((isReadAccess && access.isReadAccess()) || (isWriteAccess && access.isWriteAccess())) {
result.add(rw.getElement());
}
}
}
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy