📄 pythonnature.java
字号:
/*
* 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 + -