/** * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ /* * Created on 11/09/2005 */ package org.python.pydev.builder; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.text.IDocument; import org.python.pydev.builder.pycremover.PycHandlerBuilderVisitor; import org.python.pydev.core.FileUtilsFileBuffer; import org.python.pydev.core.callbacks.ICallback0; import org.python.pydev.core.log.Log; import org.python.pydev.editor.codecompletion.revisited.PythonPathHelper; import org.python.pydev.plugin.nature.PythonNature; import com.aptana.shared_core.string.FastStringBuffer; public abstract class PydevInternalResourceDeltaVisitor extends PyDevBuilderVisitor implements IResourceDeltaVisitor { PydevInternalResourceDeltaVisitor(IProgressMonitor monitor, int totalResources) { this.monitor = monitor; this.totalResources = totalResources; } //variables used to communicate the progress /** * this monitor might be set externally so that we can comunicate the progress to the user * (set externally) */ public IProgressMonitor monitor; /** * number of total resources to be visited (only used when the monitor is set) * (set externally) */ public int totalResources; /** * number of resources visited to the moment * (updated in this class) */ public int currentResourcesVisited = 0; //end variables used to communicate the progress /** * Visits the resource delta tree determining which files to rebuild (*.py). * * Subclasses should only reimplement visitChanged, visitAdded and visitRemoved. This method will not be called * in the structure provided by pydev. * * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) */ public boolean visit(IResourceDelta delta) throws CoreException { if (delta == null) { return true; } IResource resource = delta.getResource(); if (resource == null) { return true; } int type = resource.getType(); //related bug https://sourceforge.net/tracker/index.php?func=detail&aid=1238850&group_id=85796&atid=577329 //the team-support plugins of eclipse use the IResource //method setTeamPrivateMember to indicate resources //that are only in the project for the team-stuff (e.g. .svn or //.cvs or _darcs directories). if (resource.isTeamPrivateMember()) { return true; } if (type == IResource.FOLDER) { switch (delta.getKind()) { case IResourceDelta.REMOVED: memo.put(PyDevBuilderVisitor.DOCUMENT_TIME, System.currentTimeMillis()); visitRemovedResource(resource, null, monitor); break; //for folders, we don't have to do anything if added or changed (we just treat their children, that should //resolve for modules -- we do, however have to treat __init__.py differently). } } else if (type == IResource.FILE) { String ext = resource.getFileExtension(); if (ext == null) { //resource.getFileExtension() may return null if it has none. if (resource instanceof IFile) { PythonPathHelper.markAsPyDevFileIfDetected((IFile) resource); } return true; } //only analyze projects with the python nature... IProject project = resource.getProject(); PythonNature nature = PythonNature.getPythonNature(project); if (project != null && nature != null) { //we just want to make the visit if it is a valid python file and it is in the pythonpath if (PythonPathHelper.isValidSourceFile("." + ext)) { boolean isAddOrChange = false; //document time is updated here isAddOrChange = chooseVisit(delta, resource, isAddOrChange); if (isAddOrChange) { //communicate the progress currentResourcesVisited++; FastStringBuffer bufferToCreateString = new FastStringBuffer(); PyDevBuilder.communicateProgress(monitor, totalResources, currentResourcesVisited, resource, this, bufferToCreateString); } } else if (ext.equals("pyc")) { if (delta.getKind() == IResourceDelta.ADDED) { handleAddedPycFiles(resource, nature); } } } } return true; } /** * When handling pyc files, we do a simpler handling and go directly to the pyc builder visitor to check * if the pyc should be removed. */ protected void handleAddedPycFiles(IResource resource, PythonNature nature) { try { //we do that because we may have an added .pyc without a correspondent .py file PycHandlerBuilderVisitor pycVisitor = new PycHandlerBuilderVisitor(); pycVisitor.visitingWillStart(monitor, false, nature); try { pycVisitor.visitAddedResource(resource, null, monitor); //doc is not used in pyc remover } finally { pycVisitor.visitingEnded(monitor); } } catch (Exception e) { Log.log(e); } } /** * This will use the internal builders to traverse the delta. Note that the resource is always a valid * python file and is also always located in the pythonpath. */ protected boolean chooseVisit(IResourceDelta delta, IResource resource, boolean isAddOrChange) { switch (delta.getKind()) { case IResourceDelta.ADDED: ICallback0<IDocument> doc = FileUtilsFileBuffer.getDocOnCallbackFromResource(resource); memo.put(PyDevBuilderVisitor.DOCUMENT_TIME, System.currentTimeMillis()); visitAddedResource(resource, doc, monitor); isAddOrChange = true; break; case IResourceDelta.CHANGED: doc = FileUtilsFileBuffer.getDocOnCallbackFromResource(resource); memo.put(PyDevBuilderVisitor.DOCUMENT_TIME, System.currentTimeMillis()); visitChangedResource(resource, doc, monitor); isAddOrChange = true; break; case IResourceDelta.REMOVED: memo.put(PyDevBuilderVisitor.DOCUMENT_TIME, System.currentTimeMillis()); visitRemovedResource(resource, null, monitor); break; } return isAddOrChange; } }