mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Scope implementation for Python
This commit is contained in:
@@ -3,7 +3,6 @@ package com.jetbrains.python.codeInsight.controlflow;
|
||||
import com.intellij.codeInsight.controlflow.ControlFlowBuilder;
|
||||
import com.intellij.codeInsight.controlflow.ControlFlow;
|
||||
import com.intellij.codeInsight.controlflow.Instruction;
|
||||
import com.intellij.codeInsight.controlflow.impl.ControlFlowImpl;
|
||||
import com.intellij.codeInsight.controlflow.impl.InstructionImpl;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
@@ -26,7 +25,7 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
|
||||
//// Control flow builder staff
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public ControlFlow buildControlFlow(@NotNull final ControlFlowOwner owner) {
|
||||
public ControlFlow buildControlFlow(@NotNull final ScopeOwner owner) {
|
||||
return myBuilder.build(this, owner);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,11 +1,13 @@
|
||||
package com.jetbrains.python.codeInsight.controlflow;
|
||||
|
||||
import com.intellij.codeInsight.controlflow.ControlFlow;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public interface ControlFlowOwner extends PyElement {
|
||||
public interface ScopeOwner extends PyElement {
|
||||
ControlFlow getControlFlow();
|
||||
Scope getScope();
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import com.intellij.codeInsight.dataflow.DfaInstance;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.codeInsight.controlflow.WriteInstruction;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeVariable;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.impl.ScopeVariableImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -5,6 +5,8 @@ import com.intellij.codeInsight.dataflow.Semilattice;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeVariable;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.impl.ScopeVariableImpl;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.jetbrains.python.codeInsight.dataflow.scope;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public interface Scope {
|
||||
/*
|
||||
* @return defined scope local/instance/class variables and parameters, using reaching defs
|
||||
*/
|
||||
Collection<ScopeVariable> getDeclaredVariables(@NotNull PsiElement anchorElement);
|
||||
|
||||
|
||||
/*
|
||||
* @return defined scope local/instance/class variables and parameters, using reaching defs
|
||||
*/
|
||||
@Nullable
|
||||
ScopeVariable getDeclaredVariable(@NotNull PsiElement anchorElement, @NotNull String name);
|
||||
}
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
package com.jetbrains.python.codeInsight.dataflow;
|
||||
package com.jetbrains.python.codeInsight.dataflow.scope;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowOwner;
|
||||
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;
|
||||
@@ -35,7 +35,7 @@ public class ScopeUtil {
|
||||
return listCompExpression;
|
||||
}
|
||||
|
||||
final ControlFlowOwner owner = PsiTreeUtil.getParentOfType(element, ControlFlowOwner.class, false);
|
||||
final ScopeOwner owner = PsiTreeUtil.getParentOfType(element, ScopeOwner.class, false);
|
||||
assert owner != null : "element should have not null controlflow owner";
|
||||
return owner;
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.jetbrains.python.codeInsight.dataflow;
|
||||
package com.jetbrains.python.codeInsight.dataflow.scope;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.jetbrains.python.codeInsight.dataflow.scope.impl;
|
||||
|
||||
import com.intellij.codeInsight.controlflow.Instruction;
|
||||
import com.intellij.codeInsight.dataflow.DFAEngine;
|
||||
import com.intellij.codeInsight.dataflow.DFAMap;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.PyReachingDefsDfaInstance;
|
||||
import com.jetbrains.python.codeInsight.dataflow.PyReachingDefsSemilattice;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeVariable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public class ScopeImpl implements Scope {
|
||||
private final Instruction[] myFlow;
|
||||
private List<DFAMap<ScopeVariable>> myCachedScopeVariables;
|
||||
|
||||
public ScopeImpl(final ScopeOwner flowOwner) {
|
||||
myFlow = flowOwner.getControlFlow().getInstructions();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<ScopeVariable> getDeclaredVariables(@NotNull final PsiElement anchorElement) {
|
||||
computeScopeVariables();
|
||||
for (int i = 0; i < myFlow.length; i++) {
|
||||
Instruction instruction = myFlow[i];
|
||||
final PsiElement element = instruction.getElement();
|
||||
if (element == anchorElement) {
|
||||
return myCachedScopeVariables.get(i).values();
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public ScopeVariable getDeclaredVariable(@NotNull final PsiElement anchorElement,
|
||||
@NotNull final String name) {
|
||||
computeScopeVariables();
|
||||
for (int i = 0; i < myFlow.length; i++) {
|
||||
Instruction instruction = myFlow[i];
|
||||
final PsiElement element = instruction.getElement();
|
||||
if (element == anchorElement) {
|
||||
return myCachedScopeVariables.get(i).get(name);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<DFAMap<ScopeVariable>> computeScopeVariables() {
|
||||
if (myCachedScopeVariables == null) {
|
||||
final PyReachingDefsDfaInstance dfaInstance = new PyReachingDefsDfaInstance();
|
||||
final PyReachingDefsSemilattice semilattice = new PyReachingDefsSemilattice();
|
||||
final DFAEngine<ScopeVariable> engine = new DFAEngine<ScopeVariable>(myFlow, dfaInstance, semilattice);
|
||||
myCachedScopeVariables = engine.performDFA();
|
||||
}
|
||||
return myCachedScopeVariables;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package com.jetbrains.python.codeInsight.dataflow;
|
||||
package com.jetbrains.python.codeInsight.dataflow.scope.impl;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeVariable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -3,7 +3,7 @@ package com.jetbrains.python.psi;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowOwner;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.psi.stubs.PyClassStub;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -12,8 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* Represents a class declaration in source.
|
||||
*/
|
||||
public interface PyClass extends PsiNamedElement, PyStatement, NameDefiner, PyDocStringOwner, StubBasedPsiElement<PyClassStub>,
|
||||
ControlFlowOwner {
|
||||
public interface PyClass extends PsiNamedElement, PyStatement, NameDefiner, PyDocStringOwner, StubBasedPsiElement<PyClassStub>, ScopeOwner {
|
||||
@NotNull
|
||||
PyStatementList getStatementList();
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ package com.jetbrains.python.psi;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowOwner;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PyFile extends PyElement, PsiFile, PyDocStringOwner, ControlFlowOwner {
|
||||
public interface PyFile extends PyElement, PsiFile, PyDocStringOwner, ScopeOwner {
|
||||
|
||||
Key<Boolean> KEY_IS_DIRECTORY = Key.create("Dir impersonated by __init__.py");
|
||||
Key<Boolean> KEY_EXCLUDE_BUILTINS = Key.create("Don't include builtins to processDeclaration results");
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.jetbrains.python.psi;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowOwner;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.psi.stubs.PyFunctionStub;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @author yole
|
||||
*/
|
||||
public interface PyFunction extends PsiNamedElement, PyStatement, NameDefiner, PyDocStringOwner, StubBasedPsiElement<PyFunctionStub>,
|
||||
ControlFlowOwner {
|
||||
ScopeOwner {
|
||||
PyFunction[] EMPTY_ARRAY = new PyFunction[0];
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,8 @@ import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonDosStringFinder;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.impl.ScopeImpl;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.codeInsight.controlflow.PyControlFlowBuilder;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveUtil;
|
||||
@@ -355,6 +357,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
|
||||
private SoftReference<ControlFlow> myControlFlowRef;
|
||||
|
||||
|
||||
@NotNull
|
||||
public ControlFlow getControlFlow() {
|
||||
ControlFlow flow = getRefValue(myControlFlowRef);
|
||||
@@ -365,6 +368,19 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
return flow;
|
||||
}
|
||||
|
||||
private SoftReference<Scope> myScopeRef;
|
||||
|
||||
@NotNull
|
||||
public Scope getScope() {
|
||||
Scope scope = getRefValue(myScopeRef);
|
||||
if (scope == null) {
|
||||
scope = new ScopeImpl(this);
|
||||
myScopeRef = new SoftReference<Scope>(scope);
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static<T> T getRefValue(final SoftReference<T> reference){
|
||||
return reference != null ? reference.get() : null;
|
||||
|
||||
@@ -17,6 +17,8 @@ import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PythonDosStringFinder;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.impl.ScopeImpl;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.codeInsight.controlflow.PyControlFlowBuilder;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveUtil;
|
||||
@@ -270,6 +272,18 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
|
||||
return flow;
|
||||
}
|
||||
|
||||
private SoftReference<Scope> myScopeRef;
|
||||
|
||||
@NotNull
|
||||
public Scope getScope() {
|
||||
Scope scope = getRefValue(myScopeRef);
|
||||
if (scope == null) {
|
||||
scope = new ScopeImpl(this);
|
||||
myScopeRef = new SoftReference<Scope>(scope);
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static<T> T getRefValue(final SoftReference<T> reference){
|
||||
return reference != null ? reference.get() : null;
|
||||
|
||||
@@ -28,6 +28,8 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonDosStringFinder;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.impl.ScopeImpl;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.codeInsight.controlflow.PyControlFlowBuilder;
|
||||
import com.jetbrains.python.psi.stubs.PyClassStub;
|
||||
@@ -195,6 +197,18 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
|
||||
return flow;
|
||||
}
|
||||
|
||||
private SoftReference<Scope> myScopeRef;
|
||||
|
||||
@NotNull
|
||||
public Scope getScope() {
|
||||
Scope scope = getRefValue(myScopeRef);
|
||||
if (scope == null) {
|
||||
scope = new ScopeImpl(this);
|
||||
myScopeRef = new SoftReference<Scope>(scope);
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static<T> T getRefValue(final SoftReference<T> reference){
|
||||
return reference != null ? reference.get() : null;
|
||||
|
||||
Reference in New Issue
Block a user