📄 abstractastmanager.java
字号:
package org.python.pydev.editor.codecompletion.revisited;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.python.pydev.core.ExtensionHelper;
import org.python.pydev.core.FullRepIterable;
import org.python.pydev.core.ICodeCompletionASTManager;
import org.python.pydev.core.ICompletionRequest;
import org.python.pydev.core.ICompletionState;
import org.python.pydev.core.ILocalScope;
import org.python.pydev.core.IModule;
import org.python.pydev.core.IModulesManager;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.core.IToken;
import org.python.pydev.core.ModulesKey;
import org.python.pydev.core.REF;
import org.python.pydev.core.Tuple;
import org.python.pydev.core.Tuple3;
import org.python.pydev.core.log.Log;
import org.python.pydev.core.structure.CompletionRecursionException;
import org.python.pydev.editor.actions.PyAction;
import org.python.pydev.editor.codecompletion.CompletionRequest;
import org.python.pydev.editor.codecompletion.IPyDevCompletionParticipant;
import org.python.pydev.editor.codecompletion.PyCodeCompletion;
import org.python.pydev.editor.codecompletion.revisited.modules.AbstractModule;
import org.python.pydev.editor.codecompletion.revisited.modules.SourceToken;
import org.python.pydev.parser.PyParser;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.ImportFrom;
import org.python.pydev.parser.jython.ast.NameTok;
import org.python.pydev.parser.visitors.NodeUtils;
public abstract class AbstractASTManager implements ICodeCompletionASTManager, Serializable {
private static final IToken[] EMPTY_ITOKEN_ARRAY = new IToken[0];
private transient AssignAnalysis assignAnalysis;
public AbstractASTManager(){
}
public AssignAnalysis getAssignAnalysis() {
if(assignAnalysis == null){
assignAnalysis = new AssignAnalysis();
}
return assignAnalysis;
}
/**
* This is the guy that will handle project things for us
*/
public IModulesManager modulesManager;
public IModulesManager getModulesManager(){
return modulesManager;
}
/**
* Set the nature this ast manager works with (if no project is available and a nature is).
*/
public void setNature(IPythonNature nature){
getModulesManager().setPythonNature(nature);
}
public IPythonNature getNature() {
return getModulesManager().getNature();
}
public abstract void setProject(IProject project, boolean restoreDeltas) ;
public abstract void rebuildModule(File file, IDocument doc, IProject project, IProgressMonitor monitor, IPythonNature nature) ;
public abstract void removeModule(File file, IProject project, IProgressMonitor monitor) ;
/**
* Returns the imports that start with a given string. The comparisson is not case dependent. Passes all the modules in the cache.
*
* @param original is the name of the import module eg. 'from toimport import ' would mean that the original is 'toimport'
* or something like 'foo.bar' or an empty string (if only 'import').
* @return a Set with the imports as tuples with the name, the docstring.
* @throws CompletionRecursionException
*/
public IToken[] getCompletionsForImport(ImportInfo importInfo, ICompletionRequest r) throws CompletionRecursionException {
String original = importInfo.importsTipperStr;
String afterDots = null;
int level = 0; //meaning: no absolute import
boolean onlyDots = true;
if(original.startsWith(".")){
//if the import has leading dots, this means it is something like
//from ...bar import xxx (new way to express the relative import)
for(int i = 0; i< original.length(); i++){
if(original.charAt(i) != '.'){
onlyDots = false;
afterDots = original.substring(i);
break;
}
//add one to the relative import level
level++;
}
}
CompletionRequest request = (CompletionRequest) r;
IPythonNature nature = request.nature;
String relative = null;
String moduleName = null;
if(request.editorFile != null){
moduleName = nature.getAstManager().getModulesManager().resolveModule(REF.getFileAbsolutePath(request.editorFile));
if(moduleName != null){
if(level > 0){
//ok, it is the import added on python 2.5 (from .. import xxx)
String[] moduleParts = FullRepIterable.dotSplit(moduleName);
if(moduleParts.length > level){
relative = FullRepIterable.joinParts(moduleParts, moduleParts.length-level);
}
if(!onlyDots){
//ok, we have to add the other part too, as we have more than the leading dots
//from ..bar import
relative += "."+afterDots;
}
}else{
String tail = FullRepIterable.headAndTail(moduleName)[0];
if(original.length() > 0){
relative = tail+"."+original;
}else{
relative = tail;
}
}
}
}
//set to hold the completion (no duplicates allowed).
Set<IToken> set = new HashSet<IToken>();
String absoluteModule = original;
if (absoluteModule.endsWith(".")) {
absoluteModule = absoluteModule.substring(0, absoluteModule.length() - 1);
}
if(level == 0){
//first we get the imports... that complete for the token.
getAbsoluteImportTokens(absoluteModule, set, IToken.TYPE_IMPORT, false);
//Now, if we have an initial module, we have to get the completions
//for it.
getTokensForModule(original, nature, absoluteModule, set);
}
if(relative != null && relative.equals(absoluteModule) == false){
getAbsoluteImportTokens(relative, set, IToken.TYPE_RELATIVE_IMPORT, false);
if(importInfo.hasImportSubstring){
getTokensForModule(relative, nature, relative, set);
}
}
if(level == 1 && moduleName != null){
//has returned itself, so, let's remove it
String strToRemove = FullRepIterable.getLastPart(moduleName);
for(Iterator<IToken> it=set.iterator();it.hasNext();){
IToken o = it.next();
if(o.getRepresentation().equals(strToRemove)){
it.remove();
//don't break because the token might be different, but not the representation...
}
}
}
return set.toArray(EMPTY_ITOKEN_ARRAY);
}
/**
* @param moduleToGetTokensFrom the string that represents the token from where we are getting the imports
* @param set the set where the tokens should be added
*/
protected void getAbsoluteImportTokens(String moduleToGetTokensFrom, Set<IToken> set, int type, boolean onlyFilesOnSameLevel) {
SortedMap<ModulesKey,ModulesKey> modulesStartingWith = modulesManager.getAllModulesStartingWith(moduleToGetTokensFrom);
Iterator<ModulesKey> itModules = modulesStartingWith.keySet().iterator();
while(itModules.hasNext()){
ModulesKey key = itModules.next();
String element = key.name;
// if (element.startsWith(moduleToGetTokensFrom)) { we don't check that anymore because we get all the modules starting with it already
if(onlyFilesOnSameLevel && key.file != null && key.file.isDirectory()){
continue; // we only want those that are in the same directory, and not in other directories...
}
element = element.substring(moduleToGetTokensFrom.length());
//we just want those that are direct
//this means that if we had initially element = testlib.unittest.anothertest
//and element became later = .unittest.anothertest, it will be ignored (we
//should only analyze it if it was something as testlib.unittest and became .unittest
//we only check this if we only want file modules (in
if(onlyFilesOnSameLevel && PyAction.countChars('.', element) > 1){
continue;
}
boolean goForIt = false;
//if initial is not empty only get those that start with a dot (submodules, not
//modules that start with the same name).
//e.g. we want xml.dom
//and not xmlrpclib
//if we have xml token (not using the qualifier here)
if (moduleToGetTokensFrom.length() != 0) {
if (element.length() > 0 && element.charAt(0) == ('.')) {
element = element.substring(1);
goForIt = true;
}
} else {
goForIt = true;
}
if (element.length() > 0 && goForIt) {
String[] splitted = FullRepIterable.dotSplit(element);
if (splitted.length > 0) {
//this is the completion
set.add(new ConcreteToken(splitted[0], "", "", moduleToGetTokensFrom, type));
}
}
// }
}
}
/**
* @param original this is the initial module where the completion should happen (may have class in it too)
* @param moduleToGetTokensFrom
* @param set set where the tokens should be added
* @throws CompletionRecursionException
*/
protected void getTokensForModule(String original, IPythonNature nature, String moduleToGetTokensFrom, Set<IToken> set) throws CompletionRecursionException {
if (moduleToGetTokensFrom.length() > 0) {
if (original.endsWith(".")) {
original = original.substring(0, original.length() - 1);
}
Tuple<IModule, String> modTok = findModuleFromPath(original, nature, false, null); //the current module name is not used as it is not relative
IModule m = modTok.o1;
String tok = modTok.o2;
if(m == null){
//we were unable to find it with the given path, so, there's nothing else to do here...
return;
}
IToken[] globalTokens;
if(tok != null && tok.length() > 0){
CompletionState state2 = new CompletionState(-1,-1,tok,nature,"");
state2.builtinsGotten = true; //we don't want to get builtins here
globalTokens = m.getGlobalTokens(state2, this);
}else{
CompletionState state2 = new CompletionState(-1,-1,"",nature,"");
state2.builtinsGotten = true; //we don't want to get builtins here
globalTokens = getCompletionsForModule(m, state2);
}
for (int i = 0; i < globalTokens.length; i++) {
IToken element = globalTokens[i];
//this is the completion
set.add(element);
}
}
}
/**
* @param file
* @param doc
* @param state
* @return
*/
public static IModule createModule(File file, IDocument doc, ICompletionState state, ICodeCompletionASTManager manager) {
IPythonNature pythonNature = state.getNature();
int line = state.getLine();
IModulesManager projModulesManager = manager.getModulesManager();
return AbstractModule.createModuleFromDoc(file, doc, pythonNature, line, projModulesManager);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -