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

📄 pythonnature.java

📁 Python Development Environment (Python IDE plugin for Eclipse). Features editor, code completion, re
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * License: Common Public License v1.0
 * Created on Mar 11, 2004
 * 
 * @author Fabio Zadrozny
 * @author atotic
 */
package org.python.pydev.plugin.nature;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.part.FileEditorInput;
import org.python.pydev.builder.PyDevBuilderPrefPage;
import org.python.pydev.core.ExtensionHelper;
import org.python.pydev.core.ICodeCompletionASTManager;
import org.python.pydev.core.IInterpreterManager;
import org.python.pydev.core.IModule;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.core.IPythonPathNature;
import org.python.pydev.core.IToken;
import org.python.pydev.core.REF;
import org.python.pydev.core.log.Log;
import org.python.pydev.editor.codecompletion.revisited.ASTManager;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.ui.interpreters.IInterpreterObserver;
import org.python.pydev.utils.JobProgressComunicator;

/**
 * PythonNature is currently used as a marker class.
 * 
 * When python nature is present, project gets extra properties. Project gets assigned python nature when: - a python file is edited - a
 * python project wizard is created
 * 
 *  
 */
public class PythonNature extends AbstractPythonNature implements IPythonNature {

    /**
     * This is the job that is used to rebuild the python nature modules.
     * 
     * @author Fabio
     */
    protected class RebuildPythonNatureModules extends Job {
        private String paths;

        private String defaultSelectedInterpreter;

        private PythonNature nature;

        protected RebuildPythonNatureModules(String name, String paths, String defaultSelectedInterpreter, PythonNature nature) {
            super(name);
            this.paths = paths;
            this.defaultSelectedInterpreter = defaultSelectedInterpreter;
            this.nature = nature;
        }

        @SuppressWarnings("unchecked")
        protected IStatus run(IProgressMonitor monitorArg) {

            try {
                JobProgressComunicator jobProgressComunicator = new JobProgressComunicator(monitorArg, "Rebuilding modules", IProgressMonitor.UNKNOWN, this);
                try {
                	ICodeCompletionASTManager tempAstManager = astManager;
                    if (tempAstManager == null) {
                    	tempAstManager = new ASTManager();
                    }
                    synchronized(tempAstManager){
                    	astManager = tempAstManager;
                    	tempAstManager.setProject(getProject(), false); //it is a new manager, so, remove all deltas

                        //begins task automatically
                    	tempAstManager.changePythonPath(paths, project, jobProgressComunicator, defaultSelectedInterpreter);
                        saveAstManager();

                        List<IInterpreterObserver> participants = ExtensionHelper.getParticipants(ExtensionHelper.PYDEV_INTERPRETER_OBSERVER);
                        for (IInterpreterObserver observer : participants) {
                            try {
                                observer.notifyProjectPythonpathRestored(nature, jobProgressComunicator, defaultSelectedInterpreter);
                            } catch (Exception e) {
                            	//let's keep it safe
                                PydevPlugin.log(e);
                            }
                        }
                    }
                } catch (Throwable e) {
                    PydevPlugin.log(e);
                }

                initializationFinished = true;
                PythonNatureListenersManager.notifyPythonPathRebuilt(project, nature.pythonPathNature.getCompleteProjectPythonPath(null)); //default
                //end task
                jobProgressComunicator.done();
            }catch (Exception e) {
                Log.log(e);
            } finally {
                rebuildJob = null;
            }
            return Status.OK_STATUS;
        }
    }

    /**
     * This is the nature ID
     */
    public static final String PYTHON_NATURE_ID = "org.python.pydev.pythonNature";

    /**
     * This is the nature name
     */
    public static final String PYTHON_NATURE_NAME = "pythonNature";

    /**
     * Builder id for pydev (code completion todo and others)
     */
    public static final String BUILDER_ID = "org.python.pydev.PyDevBuilder";
    
    /**
     * Project associated with this nature.
     */
    private IProject project;

    /**
     * This is the completions cache for the nature represented by this object (it is associated with a project).
     */
    private ICodeCompletionASTManager astManager;

    /**
     * We have to know if it has already been initialized.
     */
    private boolean initializationStarted;
    
    /**
     * We have to know if it has already been initialized.
     */
    private boolean initializationFinished;

    /**
     * Manages pythonpath things
     */
    private IPythonPathNature pythonPathNature = new PythonPathNature();
    
    /**
     * Used to actually store settings for the pythonpath
     */
    private IPythonNatureStore pythonNatureStore = new PythonNatureStore();
    
    
    /**
     * constant that stores the name of the python version we are using for the project with this nature
     */
    private static QualifiedName pythonProjectVersion = null;
    static QualifiedName getPythonProjectVersionQualifiedName() {
        if(pythonProjectVersion == null){
            //we need to do this because the plugin ID may not be known on 'static' time
            pythonProjectVersion = new QualifiedName(PydevPlugin.getPluginID(), "PYTHON_PROJECT_VERSION");
        }
        return pythonProjectVersion;
    }

    /**
     * This method is called only when the project has the nature added..
     * 
     * @see org.eclipse.core.resources.IProjectNature#configure()
     */
    public void configure() throws CoreException {
    }

    /**
     * @see org.eclipse.core.resources.IProjectNature#deconfigure()
     */
    public void deconfigure() throws CoreException {
    }

    /**
     * Returns the project
     * 
     * @see org.eclipse.core.resources.IProjectNature#getProject()
     */
    public IProject getProject() {
        return project;
    }

    /**
     * Sets this nature's project - called from the eclipse platform.
     * 
     * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
     */
    public void setProject(IProject project) {
    	this.getStore().setProject(project);
        this.pythonPathNature.setProject(project);
        this.project = project;
    }

    public static synchronized IPythonNature addNature(IEditorInput element) {
        if(element instanceof FileEditorInput){
			IFile file = (IFile)((FileEditorInput)element).getAdapter(IFile.class);
			if (file != null){
				try {
	                return PythonNature.addNature(file.getProject(), null, null, null);
	            } catch (CoreException e) {
	                PydevPlugin.log(e);
	            }
			}
		}
        return null;
    }
    
    /**
     * Utility routine to remove a PythonNature from a project.
     */
    public static synchronized void removeNature(IProject project, IProgressMonitor monitor) throws CoreException {
        if(monitor == null){
            monitor = new NullProgressMonitor();
        }
        
        PythonNature nature = PythonNature.getPythonNature(project);
        if (nature == null) {
            return;
        }
        
        try {
            //we have to set the nature store to stop listening changes to .pydevproject
            nature.pythonNatureStore.setProject(null);
        } catch (Exception e) {
            PydevPlugin.log(e);
        }
        
        try {
            //we have to remove the project from the pythonpath nature too...
            nature.pythonPathNature.setProject(null);
        } catch (Exception e) {
            PydevPlugin.log(e);
        }
        
        //notify listeners that the pythonpath nature is now empty for this project
        try {
            PythonNatureListenersManager.notifyPythonPathRebuilt(project, new ArrayList<String>()); 
        } catch (Exception e) {
            PydevPlugin.log(e);
        }
        
        try {
            //actually remove the pydev configurations
            IResource member = project.findMember(".pydevproject");
            member.delete(true, null);
        } catch (Exception e) {
            PydevPlugin.log(e);
        }

        //and finally... remove the nature
        
        IProjectDescription description = project.getDescription();
        List<String> natures = new ArrayList<String>(Arrays.asList(description.getNatureIds()));
        natures.remove(PYTHON_NATURE_ID);
        description.setNatureIds((String[]) natures.toArray(new String[natures.size()]));
        project.setDescription(description, monitor);
    }

    /**
     * Utility routine to add PythonNature to the project
     * @return 
     */
    public static synchronized IPythonNature addNature(IProject project, IProgressMonitor monitor, String version, String projectPythonpath) throws CoreException {
        if (project == null || !project.isOpen()) {
            return null;
        }
        if(monitor == null){
            monitor = new NullProgressMonitor();
        }

        IProjectDescription desc = project.getDescription();

        //only add the nature if it still hasn't been added.
        if (project.hasNature(PYTHON_NATURE_ID) == false) {

            String[] natures = desc.getNatureIds();
            String[] newNatures = new String[natures.length + 1];
            System.arraycopy(natures, 0, newNatures, 0, natures.length);
            newNatures[natures.length] = PYTHON_NATURE_ID;
            desc.setNatureIds(newNatures);
            project.setDescription(desc, monitor);
        }

        //add the builder. It is used for pylint, pychecker, code completion, etc.
        ICommand[] commands = desc.getBuildSpec();

        //now, add the builder if it still hasn't been added.
        if (hasBuilder(commands) == false && PyDevBuilderPrefPage.usePydevBuilders()) {

            ICommand command = desc.newCommand();
            command.setBuilderName(BUILDER_ID);
            ICommand[] newCommands = new ICommand[commands.length + 1];

            System.arraycopy(commands, 0, newCommands, 1, commands.length);
            newCommands[0] = command;
            desc.setBuildSpec(newCommands);
            project.setDescription(desc, monitor);
        }

        IProjectNature n = project.getNature(PYTHON_NATURE_ID);
        if (n instanceof PythonNature) {
            PythonNature nature = (PythonNature) n;
            //call initialize always - let it do the control.
            nature.init(version, projectPythonpath);
            return nature;
        }
        return null;
    }

    /**
     * Utility to know if the pydev builder is in one of the commands passed.
     * 
     * @param commands
     */
    private static boolean hasBuilder(ICommand[] commands) {
        for (int i = 0; i < commands.length; i++) {
            if (commands[i].getBuilderName().equals(BUILDER_ID)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Initializes the python nature if it still has not been for this session.
     * 
     * Actions includes restoring the dump from the code completion cache
     * @param projectPythonpath this is the project python path to be used (may be null)  -- if not null, this nature is being created
     * @param version this is the version (project type) to be used (may be null) -- if not null, this nature is being created
     */
    private void init(String version, String projectPythonpath) {
        if(version != null || projectPythonpath != null){
            this.getStore().startInit();
            try {
                if(projectPythonpath != null){
                    this.getPythonPathNature().setProjectSourcePath(projectPythonpath);
                }
                if(version != null){
                    this.setVersion(version);
                }
            } catch (CoreException e) {
                PydevPlugin.log(e);
            }finally{
                this.getStore().endInit();
            }
        }
        final PythonNature nature = this;
        if (initializationStarted == false) {
            initializationStarted = true;
            
            Job codeCompletionLoadJob = new Job("Pydev code completion") {

                @SuppressWarnings("unchecked")
                protected IStatus run(IProgressMonitor monitorArg) {
                    //begins task automatically
                    JobProgressComunicator jobProgressComunicator = new JobProgressComunicator(monitorArg, "Pydev restoring cache info...", IProgressMonitor.UNKNOWN, this);

⌨️ 快捷键说明

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