localscope.java
来自「Python Development Environment (Python I」· Java 代码 · 共 376 行
JAVA
376 行
/*
* Created on Jan 20, 2005
*
* @author Fabio Zadrozny
*/
package org.python.pydev.editor.codecompletion.revisited.visitors;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.python.pydev.core.FullRepIterable;
import org.python.pydev.core.ILocalScope;
import org.python.pydev.core.IToken;
import org.python.pydev.core.structure.FastStack;
import org.python.pydev.editor.codecompletion.revisited.modules.SourceToken;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.Assert;
import org.python.pydev.parser.jython.ast.Attribute;
import org.python.pydev.parser.jython.ast.Call;
import org.python.pydev.parser.jython.ast.ClassDef;
import org.python.pydev.parser.jython.ast.FunctionDef;
import org.python.pydev.parser.jython.ast.Name;
import org.python.pydev.parser.jython.ast.Tuple;
import org.python.pydev.parser.jython.ast.exprType;
import org.python.pydev.parser.visitors.NodeUtils;
import org.python.pydev.parser.visitors.scope.ASTEntry;
import org.python.pydev.parser.visitors.scope.SequencialASTIteratorVisitor;
/**
* @author Fabio Zadrozny
*/
public class LocalScope implements ILocalScope {
//the first node from the stack is always the module itself (if it's not there, it means it is a compiled module scope)
public FastStack<SimpleNode> scope = new FastStack<SimpleNode>();
public int scopeEndLine = -1;
public int ifMainLine = -1;
public LocalScope(FastStack<SimpleNode> scope){
this.scope.addAll(scope);
}
public FastStack<SimpleNode> getScopeStack(){
return scope;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (!(obj instanceof LocalScope)) {
return false;
}
LocalScope s = (LocalScope) obj;
if(this.scope.size() != s.scope.size()){
return false;
}
return checkIfScopesMatch(s);
}
/**
* @see org.python.pydev.core.ILocalScope#isOuterOrSameScope(org.python.pydev.editor.codecompletion.revisited.visitors.LocalScope)
*/
public boolean isOuterOrSameScope(ILocalScope s){
if(this.scope.size() > s.getScopeStack().size()){
return false;
}
return checkIfScopesMatch(s);
}
/**
* @param s the scope we're checking for
* @return if the scope passed as a parameter starts with the same scope we have here. It should not be
* called if the size of the scope we're checking is bigger than the size of 'this' scope.
*/
@SuppressWarnings("unchecked")
private boolean checkIfScopesMatch(ILocalScope s) {
Iterator<SimpleNode> otIt = s.getScopeStack().iterator();
for (Iterator<SimpleNode> iter = this.scope.iterator(); iter.hasNext();) {
SimpleNode element = iter.next();
SimpleNode otElement = otIt.next();
if(element.beginColumn != otElement.beginColumn)
return false;
if(element.beginLine != otElement.beginLine)
return false;
if(! element.getClass().equals(otElement.getClass()))
return false;
String rep1 = NodeUtils.getFullRepresentationString(element);
String rep2 = NodeUtils.getFullRepresentationString(otElement);
if(rep1 == null || rep2 == null){
if(rep1 != rep2){
return false;
}
}else if(!rep1.equals(rep2))
return false;
}
return true;
}
/**
* @see org.python.pydev.core.ILocalScope#getAllLocalTokens()
*/
public IToken[] getAllLocalTokens(){
return getLocalTokens(Integer.MAX_VALUE, Integer.MAX_VALUE, false);
}
/**
* @see org.python.pydev.core.ILocalScope#getLocalTokens(int, int, boolean)
*/
public IToken[] getLocalTokens(int endLine, int col, boolean onlyArgs){
Set<SourceToken> comps = new HashSet<SourceToken>();
for (Iterator<SimpleNode> iter = this.scope.iterator(); iter.hasNext();) {
SimpleNode element = iter.next();
if (element instanceof FunctionDef) {
FunctionDef f = (FunctionDef) element;
for (int i = 0; i < f.args.args.length; i++) {
String s = NodeUtils.getRepresentationString(f.args.args[i]);
comps.add(new SourceToken(f.args.args[i], s, "", "", "", IToken.TYPE_PARAM));
}
if(onlyArgs){
continue;
}
try {
for (int i = 0; i < f.body.length; i++) {
GlobalModelVisitor visitor = new GlobalModelVisitor(GlobalModelVisitor.GLOBAL_TOKENS, "");
f.body[i].accept(visitor);
List<IToken> t = visitor.tokens;
for (Iterator<IToken> iterator = t.iterator(); iterator.hasNext();) {
SourceToken tok = (SourceToken) iterator.next();
//if it is found here, it is a local type
tok.type = IToken.TYPE_LOCAL;
if(tok.getAst().beginLine <= endLine){
comps.add(tok);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
return (SourceToken[]) comps.toArray(new SourceToken[0]);
}
/**
*
* @param argName this is the argument (cannot have dots)
* @param activationToken this is the actual activation token we're looking for
* (may have dots).
*
* Note that argName == activationToken first part before the dot (they may be equal)
* @return a list of tokens for the local
*/
public Collection<IToken> getInterfaceForLocal(String activationToken) {
Set<SourceToken> comps = new HashSet<SourceToken>();
Iterator<SimpleNode> it = this.scope.topDownIterator();
if(!it.hasNext()){
return new ArrayList<IToken>();
}
SimpleNode element = it.next();
String dottedActTok = activationToken+'.';
//ok, that's the scope we have to analyze
SequencialASTIteratorVisitor visitor = SequencialASTIteratorVisitor.create(element);
Iterator<ASTEntry> iterator = visitor.getIterator(Attribute.class);
while(iterator.hasNext()){
ASTEntry entry = iterator.next();
String rep = NodeUtils.getFullRepresentationString(entry.node);
if(rep.startsWith(dottedActTok)){
rep = rep.substring(dottedActTok.length());
comps.add(new SourceToken(entry.node, FullRepIterable.getFirstPart(rep), "", "", "", IToken.TYPE_OBJECT_FOUND_INTERFACE));
}
}
return new ArrayList<IToken>(comps);
}
/**
* @see org.python.pydev.core.ILocalScope#getLocalImportedModules(int, int, java.lang.String)
*/
public List<IToken> getLocalImportedModules(int line, int col, String moduleName) {
ArrayList<IToken> importedModules = new ArrayList<IToken>();
for (Iterator<SimpleNode> iter = this.scope.iterator(); iter.hasNext();) {
SimpleNode element = iter.next();
if (element instanceof FunctionDef) {
FunctionDef f = (FunctionDef) element;
for (int i = 0; i < f.body.length; i++) {
importedModules.addAll(GlobalModelVisitor.getTokens(f.body[i], GlobalModelVisitor.ALIAS_MODULES, moduleName, null));
}
}
}
return importedModules;
}
/**
* @see org.python.pydev.core.ILocalScope#getClassDef()
*/
public ClassDef getClassDef() {
for(Iterator<SimpleNode> it = this.scope.topDownIterator(); it.hasNext();){
SimpleNode node = it.next();
if(node instanceof ClassDef){
return (ClassDef) node;
}
}
return null;
}
/**
* @see org.python.pydev.core.ILocalScope#isLastClassDef()
*/
public boolean isLastClassDef() {
if(this.scope.size() > 0 && this.scope.peek() instanceof ClassDef){
return true;
}
return false;
}
@SuppressWarnings("unchecked")
public Iterator iterator() {
return scope.topDownIterator();
}
public int getIfMainLine() {
return ifMainLine;
}
public int getScopeEndLine() {
return scopeEndLine;
}
public void setIfMainLine(int original) {
this.ifMainLine = original;
}
public void setScopeEndLine(int beginLine) {
this.scopeEndLine = beginLine;
}
/**
* Constant containing the calls that are checked for implementations.
*
* Couldn't find anything similar for pyprotocols.
*
* Zope has a different heuristic which is also checked:
* assert Interface.implementedBy(foo)
*
* maps the method name to check -> index of the class in the call (or negative if class is the caller)
*
* TODO: This should be made public to the user...
*/
public static final Map<String, Integer> ISINSTANCE_POSSIBILITIES = new HashMap<String, Integer>();
static{
ISINSTANCE_POSSIBILITIES.put("isinstance".toLowerCase(), 2);
ISINSTANCE_POSSIBILITIES.put("IsImplementation".toLowerCase(), 2);
ISINSTANCE_POSSIBILITIES.put("IsInterfaceDeclared".toLowerCase(), 2);
ISINSTANCE_POSSIBILITIES.put("implementedBy".toLowerCase(), -1);
}
/**
* @see {@link ILocalScope#getPossibleClassesForActivationToken(String)}
*/
public List<String> getPossibleClassesForActivationToken(String actTok) {
ArrayList<String> ret = new ArrayList<String>();
Iterator<SimpleNode> it = this.scope.topDownIterator();
if(!it.hasNext()){
return ret;
}
SimpleNode element = it.next();
//ok, that's the scope we have to analyze
SequencialASTIteratorVisitor visitor = SequencialASTIteratorVisitor.create(element);
Iterator<ASTEntry> iterator = visitor.getIterator(Assert.class);
while(iterator.hasNext()){
ASTEntry entry = iterator.next();
Assert ass = (Assert) entry.node;
if(ass.test instanceof Call){
Call call = (Call) ass.test;
String rep = NodeUtils.getFullRepresentationString(call.func);
if(rep == null){
continue;
}
Integer classIndex = ISINSTANCE_POSSIBILITIES.get(FullRepIterable.getLastPart(rep).toLowerCase());
if(classIndex != null){
if(call.args != null && (call.args.length >= Math.max(classIndex, 1))){
//in all cases, the instance is the 1st parameter.
String foundActTok = NodeUtils.getFullRepresentationString(call.args[0]);
if(foundActTok != null && foundActTok.equals(actTok)){
if(classIndex > 0){
exprType type = call.args[classIndex-1];
if(type instanceof Tuple){
//case: isinstance(obj, (Class1,Class2))
Tuple tuple = (Tuple) type;
for(exprType expr : tuple.elts){
addRepresentationIfPossible(ret, expr);
}
} else{
//case: isinstance(obj, Class)
addRepresentationIfPossible(ret, type);
}
}else{
//zope case Interface.implementedBy(obj) -> Interface added
ret.add(FullRepIterable.getWithoutLastPart(rep));
}
}
}
}
}
}
return ret;
}
/**
* @param ret the list where the representation should be added
* @param expr the Name or Attribute that determines the class that should be added
*/
private void addRepresentationIfPossible(ArrayList<String> ret, exprType expr) {
if(expr instanceof Name || expr instanceof Attribute){
String string = NodeUtils.getFullRepresentationString(expr);
if(string != null){
ret.add(string);
}
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?