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

📄 modulesmanager.java

📁 Python Development Environment (Python IDE plugin for Eclipse). Features editor, code completion, re
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -