⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 finddefinitionmodelvisitor.java

📁 Python Development Environment (Python IDE plugin for Eclipse). Features editor, code completion, re
💻 JAVA
字号:
/*
 * Created on Jan 19, 2005
 *
 * @author Fabio Zadrozny
 */
package org.python.pydev.editor.codecompletion.revisited.visitors;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import org.python.pydev.core.ILocalScope;
import org.python.pydev.core.IModule;
import org.python.pydev.core.docutils.PySelection;
import org.python.pydev.core.structure.FastStack;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.Assign;
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.Global;
import org.python.pydev.parser.jython.ast.ImportFrom;
import org.python.pydev.parser.jython.ast.Module;
import org.python.pydev.parser.jython.ast.Name;
import org.python.pydev.parser.jython.ast.NameTok;
import org.python.pydev.parser.jython.ast.NameTokType;
import org.python.pydev.parser.jython.ast.aliasType;
import org.python.pydev.parser.jython.ast.exprType;
import org.python.pydev.parser.visitors.NodeUtils;

/**
 * @author Fabio Zadrozny
 */
public class FindDefinitionModelVisitor extends AbstractVisitor{

    /**
     * This is the token to find.
     */
    private String tokenToFind;
    
    /**
     * List of definitions.
     */
    public List<Definition> definitions = new ArrayList<Definition>();
    
    /**
     * Stack of classes / methods to get to a definition.
     */
    private FastStack<SimpleNode> defsStack = new FastStack<SimpleNode>();
    
    /**
     * This is a stack that will keep the globals for each stack
     */
    private FastStack<Set<String>> globalDeclarationsStack = new FastStack<Set<String>>();
    
    /**
     * This is the module we are visiting
     */
    private IModule module;
    
    /**
     * It is only available if the cursor position is upon a NameTok in an import (it represents the complete
     * path for finding the module from the current module -- it can be a regular or relative import).
     */
    public String moduleImported;

	private int line;

	private int col;
    
    private boolean foundAsDefinition = false;
    
    private Definition definitionFound;

    /**
     * Call is stored for the context for a keyword parameter
     */
	private Stack<Call> call = new Stack<Call>();
    
    /**
     * Constructor
     * @param line: starts at 1
     * @param col: starts at 1
     */
    public FindDefinitionModelVisitor(String token, int line, int col, IModule module){
        this.tokenToFind = token;
        this.module = module;
        this.line = line;
        this.col = col;
        this.moduleName = module.getName();
        //we may have a global declared in the global scope
        globalDeclarationsStack.push(new HashSet<String>());
    }
    
    @Override
    public Object visitImportFrom(ImportFrom node) throws Exception {
    	String modRep = NodeUtils.getRepresentationString(node.module);
		if( NodeUtils.isWithin(line, col, node.module) ){
    		//it is a token in the definition of a module
    		int startingCol = node.module.beginColumn;
			int endingCol = startingCol;
    		while(endingCol < this.col){
    			endingCol++;
    		}
    		int lastChar = endingCol-startingCol;
    		moduleImported = modRep.substring(0, lastChar);
    		int i = lastChar;
    		while(i < modRep.length()){
    			if(Character.isJavaIdentifierPart(modRep.charAt(i))){
    				i++;
    			}else{
    				break;
    			}
    		}
    		moduleImported += modRep.substring(lastChar, i);
    	}else{
    		//it was not the module, so, we have to check for each name alias imported
    		for (aliasType alias: node.names){
    			//we do not check the 'as' because if it is some 'as', it will be gotten as a global in the module
    			if( NodeUtils.isWithin(line, col, alias.name) ){
    				moduleImported = modRep + "." + NodeUtils.getRepresentationString(alias.name);
    			}
    		}
    	}
    	return super.visitImportFrom(node);
    }

    /**
     * @see org.python.pydev.parser.jython.ast.VisitorBase#unhandled_node(org.python.pydev.parser.jython.SimpleNode)
     */
    protected Object unhandled_node(SimpleNode node) throws Exception {
        return null;
    }

    /**
     * @see org.python.pydev.parser.jython.ast.VisitorBase#traverse(org.python.pydev.parser.jython.SimpleNode)
     */
    public void traverse(SimpleNode node) throws Exception {
        node.traverse(this);
    }
    
    /**
     * @see org.python.pydev.parser.jython.ast.VisitorBase#visitClassDef(org.python.pydev.parser.jython.ast.ClassDef)
     */
    public Object visitClassDef(ClassDef node) throws Exception {
        globalDeclarationsStack.push(new HashSet<String>());
        defsStack.push(node);
        
        node.traverse(this);
        
        defsStack.pop();
        globalDeclarationsStack.pop();
        
        checkDeclaration(node, (NameTok) node.name);
        return null;
    }
    
    /**
     * @see org.python.pydev.parser.jython.ast.VisitorBase#visitFunctionDef(org.python.pydev.parser.jython.ast.FunctionDef)
     */
    public Object visitFunctionDef(FunctionDef node) throws Exception {
        globalDeclarationsStack.push(new HashSet<String>());
        defsStack.push(node);
        
        if(node.args != null && node.args.args != null){
	        for(exprType arg:node.args.args){
	        	if(arg instanceof Name){
	        		checkParam((Name) arg);
	        	}
	        }
        }
        node.traverse(this);
        
        defsStack.pop();
        globalDeclarationsStack.pop();
        
        checkDeclaration(node, (NameTok) node.name);
        return null;
    }
    
    /**
     * @param node the declaration node we're interested in (class or function)
     * @param name the token that represents the name of that declaration
     */
    private void checkParam(Name name) {
    	String rep = NodeUtils.getRepresentationString(name);
    	if(rep.equals(tokenToFind) && line == name.beginLine && col >= name.beginColumn && col <= name.beginColumn+rep.length()){
    		foundAsDefinition = true;
    		// if it is found as a definition it is an 'exact' match, so, erase all the others.
    		ILocalScope scope = new LocalScope(this.defsStack);
    		for (Iterator<Definition> it = definitions.iterator(); it.hasNext();) {
    			Definition d = it.next();
    			if(!d.scope.equals(scope)){
    				it.remove();
    			}
    		}
    		
    		
    		definitionFound = new Definition(line, name.beginColumn, rep, name, scope, module);
    		definitions.add(definitionFound);
    	}
    }
    
    @Override
    public Object visitCall(Call node) throws Exception {
    	this.call.push(node);
    	Object r = super.visitCall(node);
    	this.call.pop();
		return r;
    }
    
    
    @Override
    public Object visitNameTok(NameTok node) throws Exception {
    	if(node.ctx == NameTok.KeywordName){
    		if(this.line == node.beginLine){
    			String rep = NodeUtils.getRepresentationString(node);

    			if(PySelection.isInside(col, node.beginColumn, rep.length())){
    	    		foundAsDefinition = true;
    	    		// if it is found as a definition it is an 'exact' match, so, erase all the others.
    	    		ILocalScope scope = new LocalScope(this.defsStack);
    	    		for (Iterator<Definition> it = definitions.iterator(); it.hasNext();) {
    	    			Definition d = it.next();
    	    			if(!d.scope.equals(scope)){
    	    				it.remove();
    	    			}
    	    		}
    	    		
    	    		definitions.clear();
    	    		
					definitionFound = new KeywordParameterDefinition(line, node.beginColumn, rep, node, scope, module, this.call.peek());
    	    		definitions.add(definitionFound);
    	    		throw new StopVisitingException();
    			}
    		}
    	}
    	return null;
    }

    /**
     * @param node the declaration node we're interested in (class or function)
     * @param name the token that represents the name of that declaration
     */
    private void checkDeclaration(SimpleNode node, NameTok name) {
        String rep = NodeUtils.getRepresentationString(node);
        if(rep.equals(tokenToFind) && line == name.beginLine && col >= name.beginColumn && col <= name.beginColumn+rep.length()){
            foundAsDefinition = true;
            // if it is found as a definition it is an 'exact' match, so, erase all the others.
            ILocalScope scope = new LocalScope(this.defsStack);
            for (Iterator<Definition> it = definitions.iterator(); it.hasNext();) {
                Definition d = it.next();
                if(!d.scope.equals(scope)){
                    it.remove();
                }
            }
            
            
            definitionFound = new Definition(line, name.beginColumn, rep, node, scope, module);
            definitions.add(definitionFound);
        }
    }
    
    @Override
    public Object visitGlobal(Global node) throws Exception {
        for(NameTokType n:node.names){
            globalDeclarationsStack.peek().add(NodeUtils.getFullRepresentationString(n));
        }
        return null;
    }
    
    @Override
    public Object visitModule(Module node) throws Exception {
        this.defsStack.push(node);
        return super.visitModule(node);
    }
    /**
     * @see org.python.pydev.parser.jython.ast.VisitorBase#visitAssign(org.python.pydev.parser.jython.ast.Assign)
     */
    public Object visitAssign(Assign node) throws Exception {
        ILocalScope scope = new LocalScope(this.defsStack);
        if(foundAsDefinition && !scope.equals(definitionFound.scope)){ //if it is found as a definition it is an 'exact' match, so, we do not keep checking it
            return null;
        }
        
        for (int i = 0; i < node.targets.length; i++) {
            String rep = NodeUtils.getFullRepresentationString(node.targets[i]);
	        
            if(rep != null && rep.equals(tokenToFind)){
	            String value = NodeUtils.getFullRepresentationString(node.value);
                if(value == null){
                    value = "";
                }
	            AssignDefinition definition;
	            int line = NodeUtils.getLineDefinition(node.value);
	            int col = NodeUtils.getColDefinition(node.value);
	            
	            if (node.targets != null && node.targets.length > 0){
	            	line = NodeUtils.getLineDefinition(node.targets[0]);
	            	col = NodeUtils.getColDefinition(node.targets[0]);
	            }

                definition = new AssignDefinition(value, rep, i, node, line, col, scope, module);
                
                for(Set<String> globals: globalDeclarationsStack){
                    if(globals.contains(rep)){
                        definition.foundAsGlobal = true;
                    }
                }
                
	            definitions.add(definition);
	        }
        }
        
        return null;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -