/** * 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 Nov 10, 2004 * * @author Fabio Zadrozny */ package org.python.pydev.editor.codecompletion.revisited; import java.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.text.IDocument; import org.python.pydev.builder.PyDevBuilderVisitor; import org.python.pydev.core.FileUtilsFileBuffer; import org.python.pydev.core.ICodeCompletionASTManager; import org.python.pydev.core.callbacks.ICallback0; import org.python.pydev.plugin.nature.PythonNature; /** * @author Fabio Zadrozny * * This class updates our internal code-completion related structures. */ public class PyCodeCompletionVisitor extends PyDevBuilderVisitor { public static final int PRIORITY_CODE_COMPLETION = PRIORITY_DEFAULT; @Override protected int getPriority() { return PRIORITY_CODE_COMPLETION; } /** * The code completion visitor is responsible for checking the changed resources in order to * update the code completion cache for the project. * * This visitor just passes one resource and updates the code completion cache for it. */ @Override public void visitChangedResource(IResource resource, ICallback0<IDocument> document, IProgressMonitor monitor) { PythonNature pythonNature = getPythonNature(resource); if (pythonNature != null) { ICodeCompletionASTManager astManager = pythonNature.getAstManager(); if (astManager != null) { IPath location = resource.getLocation(); astManager.rebuildModule(new File(location.toOSString()), document, resource.getProject(), new NullProgressMonitor(), pythonNature); } } } @Override public void visitAddedResource(IResource resource, ICallback0<IDocument> document, IProgressMonitor monitor) { visitChangedResource(resource, document, monitor); if (PythonPathHelper.isValidInitFile(resource.getName())) { //When some init file is added, we have to visit the whole structure below it as we'll have to enable //code-completion for all of that! Long originalTime = (Long) memo.get(PyDevBuilderVisitor.DOCUMENT_TIME); try { IResource[] initDependents = getInitDependents(resource); for (int i = 0; i < initDependents.length; i++) { IResource dependent = initDependents[i]; memo.put(PyDevBuilderVisitor.DOCUMENT_TIME, System.currentTimeMillis()); this.visitChangedResource(dependent, FileUtilsFileBuffer.getDocOnCallbackFromResource(dependent), monitor); } } finally { memo.put(PyDevBuilderVisitor.DOCUMENT_TIME, originalTime); } } } @Override public void visitRemovedResource(IResource resource, ICallback0<IDocument> document, IProgressMonitor monitor) { PythonNature pythonNature = getPythonNature(resource); if (pythonNature != null) { ICodeCompletionASTManager astManager = pythonNature.getAstManager(); if (astManager != null) { IPath location = resource.getLocation(); astManager.removeModule(new File(location.toOSString()), resource.getProject(), new NullProgressMonitor()); } } } /** * @return all the IFiles that are below the folder where initResource is located. */ protected IResource[] getInitDependents(IResource initResource) { List<IResource> toRet = new ArrayList<IResource>(); IContainer parent = initResource.getParent(); try { //Remove the __init__ that originated this request. IResource[] members = parent.members(); ArrayList<IResource> lst = new ArrayList<IResource>(members.length - 1); for (int i = 0; i < members.length; i++) { IResource resource = members[i]; if (!PythonPathHelper.isValidInitFile(resource.getName())) { lst.add(resource); } } fillWithMembers(toRet, parent, lst.toArray(new IResource[lst.size()])); } catch (CoreException e) { //That's OK: it may not exist anymore. } return toRet.toArray(new IResource[0]); } private void fillWithMembers(List<IResource> toRet, IContainer parent, IResource[] resources) { for (int i = 0; i < resources.length; i++) { IResource resource = resources[i]; if (resource.getType() == IResource.FILE) { if (PythonPathHelper.isValidSourceFile(resource.getName())) { toRet.add(resource); } } else if (resource.getType() == IResource.FOLDER) { IFolder folder = (IFolder) resource; IResource[] members; try { members = folder.members(); for (int j = 0; j < members.length; j++) { if (PythonPathHelper.isValidInitFile(members[j].getName())) { fillWithMembers(toRet, folder, members); break; } } } catch (CoreException e) { //That's OK: it may not exist anymore. } } } } }