📄 modulesmanager.java
字号:
/*
* Created on May 24, 2005
*
* @author Fabio Zadrozny
*/
package org.python.pydev.editor.codecompletion.revisited;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
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.editor.codecompletion.revisited.modules.AbstractModule;
import org.python.pydev.editor.codecompletion.revisited.modules.CompiledModule;
import org.python.pydev.editor.codecompletion.revisited.modules.EmptyModule;
import org.python.pydev.editor.codecompletion.revisited.modules.SourceModule;
/**
* This class manages the modules that are available
*
* @author Fabio Zadrozny
*/
public abstract class ModulesManager implements IModulesManager, Serializable {
private final static boolean DEBUG_BUILD = false;
private final static boolean DEBUG_IO = false;
public ModulesManager(){
}
/**
* This class is a cache to help in getting the managers that are referenced or referred.
*
* It will not actually make any computations (the managers must be set from the outside)
*/
protected static class CompletionCache{
public ModulesManager[] referencedManagers;
public ModulesManager[] referredManagers;
public ModulesManager[] getManagers(boolean referenced) {
if(referenced){
return this.referencedManagers;
}else{
return this.referredManagers;
}
}
public void setManagers(ModulesManager[] ret, boolean referenced) {
if(referenced){
this.referencedManagers = ret;
}else{
this.referredManagers = ret;
}
}
}
/**
* A stack for keeping the completion cache
*/
protected transient volatile CompletionCache completionCache = null;
private transient volatile int completionCacheI=0;
/**
* This method starts a new cache for this manager, so that needed info is kept while the request is happening
* (so, some info may not need to be re-asked over and over for requests)
*/
public synchronized boolean startCompletionCache(){
if(completionCache == null){
completionCache = new CompletionCache();
}
completionCacheI += 1;
return true;
}
public synchronized void endCompletionCache(){
completionCacheI -= 1;
if(completionCacheI == 0){
completionCache = null;
}else if(completionCacheI < 0){
throw new RuntimeException("Completion cache negative (request unsynched)");
}
}
/**
* Modules that we have in memory. This is persisted when saved.
*
* Keys are ModulesKey with the name of the module. Values are AbstractModule objects.
*
* Implementation changed to contain a cache, so that it does not grow to much (some out of memo errors
* were thrown because of the may size when having too many modules).
*
* It is sorted so that we can get things in a 'subtree' faster
*/
protected transient SortedMap<ModulesKey, ModulesKey> modulesKeys = new TreeMap<ModulesKey, ModulesKey>();
protected static transient ModulesManagerCache cache = createCache();
private static ModulesManagerCache createCache(){
return new ModulesManagerCache();
}
/**
* This is the set of files that was found just right after unpickle (it should not be changed after that,
* and serves only as a reference cache).
*/
protected transient Set<File> files = new HashSet<File>();
/**
* Helper for using the pythonpath. Also persisted.
*/
protected PythonPathHelper pythonPathHelper = new PythonPathHelper();
public PythonPathHelper getPythonPathHelper(){
return pythonPathHelper;
}
/**
* The version for deserialization
*/
private static final long serialVersionUID = 2L;
/**
* Custom deserialization is needed.
*/
private void readObject(ObjectInputStream aStream) throws IOException, ClassNotFoundException {
modulesKeys = new TreeMap<ModulesKey, ModulesKey>();
files = new HashSet<File>();
aStream.defaultReadObject();
Set<ModulesKey> set = (Set<ModulesKey>) aStream.readObject();
if(DEBUG_IO){
for (ModulesKey key : set) {
System.out.println("Read:"+key);
}
}
for (Iterator iter = set.iterator(); iter.hasNext();) {
ModulesKey key = (ModulesKey) iter.next();
//restore with empty modules.
modulesKeys.put(key, key);
if(key.file != null){
files.add(key.file);
}
}
}
/**
* Custom serialization is needed.
*/
private void writeObject(ObjectOutputStream aStream) throws IOException {
synchronized (modulesKeys) {
aStream.defaultWriteObject();
//write only the keys
HashSet<ModulesKey> set = new HashSet<ModulesKey>(modulesKeys.keySet());
if(DEBUG_IO){
for (ModulesKey key : set) {
System.out.println("Write:"+key);
}
}
aStream.writeObject(set);
}
}
/**
* @param modules The modules to set.
*/
private void setModules(SortedMap<ModulesKey, ModulesKey> keys) {
this.modulesKeys = keys;
}
/**
* @return Returns the modules.
*/
protected Map<ModulesKey, AbstractModule> getModules() {
throw new RuntimeException("Deprecated");
}
/**
* Must be overriden so that the available builtins (forced or not) are returned.
* @param defaultSelectedInterpreter
*/
public abstract String[] getBuiltins(String defaultSelectedInterpreter);
/**
*
* @param monitor this is the monitor
* @param pythonpathList this is the pythonpath
* @param completions OUT - the files that were gotten as valid python modules
* @param fromJar OUT - the names of the modules that were found inside a jar
* @return the total number of modules found (that's completions + fromJar)
*/
private int listFilesForCompletion(IProgressMonitor monitor, List<String> pythonpathList, List<File> completions, List<String> fromJar) {
int total = 0;
//first thing: get all files available from the python path and sum them up.
for (Iterator iter = pythonpathList.iterator(); iter.hasNext() && monitor.isCanceled() == false;) {
String element = (String) iter.next();
//the slow part is getting the files... not much we can do (I think).
File root = new File(element);
List<File>[] below = pythonPathHelper.getModulesBelow(root, monitor);
if(below != null){
completions.addAll(below[0]);
total += below[0].size();
}else{ //ok, it was null, so, maybe this is not a folder, but zip file with java classes...
List<String> currFromJar = PythonPathHelper.getFromJar(root, monitor);
if(currFromJar != null){
fromJar.addAll(currFromJar);
total += currFromJar.size();
}
}
}
return total;
}
public void changePythonPath(String pythonpath, final IProject project, IProgressMonitor monitor, String defaultSelectedInterpreter) {
List<String> pythonpathList = pythonPathHelper.setPythonPath(pythonpath);
List<File> completions = new ArrayList<File>();
List<String> fromJar = new ArrayList<String>();
int total = listFilesForCompletion(monitor, pythonpathList, completions, fromJar);
changePythonPath(pythonpath, project, monitor, pythonpathList, completions, fromJar, total, defaultSelectedInterpreter);
}
/**
* @param pythonpath string with the new pythonpath (separated by |)
* @param project may be null if there is no associated project.
*/
private void changePythonPath(String pythonpath, final IProject project, IProgressMonitor monitor,
List<String> pythonpathList, List<File> completions, List<String> fromJar, int total, String defaultSelectedInterpreter) {
SortedMap<ModulesKey, ModulesKey> keys = new TreeMap<ModulesKey, ModulesKey>();
int j = 0;
//now, create in memory modules for all the loaded files (empty modules).
for (Iterator<File> iterator = completions.iterator(); iterator.hasNext() && monitor.isCanceled() == false; j++) {
File f = iterator.next();
String fileAbsolutePath = REF.getFileAbsolutePath(f);
String m = pythonPathHelper.resolveModule(fileAbsolutePath);
monitor.setTaskName(new StringBuffer("Module resolved: ").append(j).append(" of ").append(total).append(" (").append(m)
.append(")").toString());
monitor.worked(1);
if (m != null) {
//we don't load them at this time.
ModulesKey modulesKey = new ModulesKey(m, f);
//ok, now, let's resolve any conflicts that we might find...
boolean add = false;
//no conflict (easy)
if(!keys.containsKey(modulesKey)){
add = true;
}else{
//we have a conflict, so, let's resolve which one to keep (the old one or this one)
if(PythonPathHelper.isValidSourceFile(fileAbsolutePath)){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -