/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.vjet.eclipse.internal.ui.refactoring.core; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.dltk.mod.core.DLTKCore; import org.eclipse.dltk.mod.core.DLTKLanguageManager; import org.eclipse.dltk.mod.core.IBuildpathEntry; import org.eclipse.dltk.mod.core.IMember; import org.eclipse.dltk.mod.core.IModelElement; import org.eclipse.dltk.mod.core.IProjectFragment; import org.eclipse.dltk.mod.core.IScriptProject; import org.eclipse.dltk.mod.core.ModelException; import org.eclipse.dltk.mod.core.search.IDLTKSearchScope; import org.eclipse.dltk.mod.core.search.SearchEngine; import org.eclipse.dltk.mod.internal.core.util.VjoFlags; public class RefactoringScopeFactory { /* * Adds to <code> projects </code> IJavaProject objects for all projects * directly or indirectly referencing focus. @param projects IJavaProjects * will be added to this set */ private static void addReferencingProjects(IScriptProject focus, Set projects) throws ModelException { IProject[] referencingProjects = focus.getProject() .getReferencingProjects(); for (int i = 0; i < referencingProjects.length; i++) { IScriptProject candidate = DLTKCore.create(referencingProjects[i]); if (candidate == null || projects.contains(candidate) || !candidate.exists()) continue; // break cycle IBuildpathEntry entry = getReferencingClassPathEntry(candidate, focus); if (entry != null) { projects.add(candidate); if (entry.isExported()) addReferencingProjects(candidate, projects); } } } // // private static void addRelatedReferencing(IJavaProject focus, Set // projects) // throws CoreException { // IProject[] referencingProjects = focus.getProject() // .getReferencingProjects(); // for (int i = 0; i < referencingProjects.length; i++) { // IJavaProject candidate = JavaCore.create(referencingProjects[i]); // if (candidate == null || projects.contains(candidate) // || !candidate.exists()) // continue; // break cycle // IClasspathEntry entry = getReferencingClassPathEntry(candidate, // focus); // if (entry != null) { // projects.add(candidate); // if (entry.isExported()) { // addRelatedReferencing(candidate, projects); // addRelatedReferenced(candidate, projects); // } // } // } // } // // private static void addRelatedReferenced(IJavaProject focus, Set // projects) // throws CoreException { // IProject[] referencedProjects = focus.getProject() // .getReferencedProjects(); // for (int i = 0; i < referencedProjects.length; i++) { // IJavaProject candidate = JavaCore.create(referencedProjects[i]); // if (candidate == null || projects.contains(candidate) // || !candidate.exists()) // continue; // break cycle // IClasspathEntry entry = getReferencingClassPathEntry(focus, // candidate); // if (entry != null) { // projects.add(candidate); // if (entry.isExported()) { // addRelatedReferenced(candidate, projects); // addRelatedReferencing(candidate, projects); // } // } // } // } // /** * Creates a new search scope with all compilation units possibly * referencing <code>javaElement</code>, considering the visibility of * the element. * * @param javaElement * the java element * @return the search scope * @throws ModelException * if an error occurs */ public static IDLTKSearchScope create(IModelElement javaElement) throws ModelException { return RefactoringScopeFactory.create(javaElement, true); } /** * Creates a new search scope with all compilation units possibly * referencing <code>javaElement</code>. * * @param javaElement * the java element * @param considerVisibility * consider visibility of javaElement iff <code>true</code> * @return the search scope * @throws ModelException * if an error occurs */ public static IDLTKSearchScope create(IModelElement javaElement, boolean considerVisibility) throws ModelException { if (considerVisibility & javaElement instanceof IMember) { IMember member = (IMember) javaElement; if (VjoFlags.isPrivate(member)) { if (member.getSourceModule() != null) return SearchEngine.createSearchScope(member .getSourceModule()); else return SearchEngine.createSearchScope(member); } // Removed code that does some optimizations regarding package // visible members. The problem is that // there can be a package fragment with the same name in a different // source folder or project. So we // have to treat package visible members like public or protected // members. } return create(javaElement.getScriptProject()); } private static IDLTKSearchScope create(IScriptProject javaProject) throws ModelException { return SearchEngine.createSearchScope(getAllScopeElements(javaProject), false, DLTKLanguageManager.getLanguageToolkit(javaProject)); } /** * Creates a new search scope comprising <code>members</code>. * * @param members * the members * @return the search scope * @throws ModelException * if an error occurs */ // public static IJavaSearchScope create(IMember[] members) // throws ModelException { // Assert.isTrue(members != null && members.length > 0); // IMember candidate = members[0]; // int visibility = getVisibility(candidate); // for (int i = 1; i < members.length; i++) { // int mv = getVisibility(members[i]); // if (mv > visibility) { // visibility = mv; // candidate = members[i]; // } // } // return create(candidate); // } // // /** // * Creates a new search scope with all projects possibly referenced from // the // * given <code>javaElements</code>. // * // * @param javaElements // * the java elements // * @return the search scope // */ // public static IJavaSearchScope createReferencedScope( // IJavaElement[] javaElements) { // Set projects = new HashSet(); // for (int i = 0; i < javaElements.length; i++) { // projects.add(javaElements[i].getJavaProject()); // } // IJavaProject[] prj = (IJavaProject[]) projects // .toArray(new IJavaProject[projects.size()]); // return SearchEngine.createJavaSearchScope(prj, true); // } // // /** // * Creates a new search scope with all projects possibly referenced from // the // * given <code>javaElements</code>. // * // * @param javaElements // * the java elements // * @param includeMask // * the include mask // * @return the search scope // */ // public static IJavaSearchScope createReferencedScope( // IJavaElement[] javaElements, int includeMask) { // Set projects = new HashSet(); // for (int i = 0; i < javaElements.length; i++) { // projects.add(javaElements[i].getJavaProject()); // } // IJavaProject[] prj = (IJavaProject[]) projects // .toArray(new IJavaProject[projects.size()]); // return SearchEngine.createJavaSearchScope(prj, includeMask); // } // // /** // * Creates a new search scope containing all projects which reference or // are // * referenced by the specified project. // * // * @param project // * the project // * @param includeMask // * the include mask // * @return the search scope // * @throws CoreException // * if a referenced project could not be determined // */ // public static IJavaSearchScope createRelatedProjectsScope( // IJavaProject project, int includeMask) throws CoreException { // IJavaProject[] projects = getRelatedProjects(project); // return SearchEngine.createJavaSearchScope(projects, includeMask); // } // private static IModelElement[] getAllScopeElements(IScriptProject project) throws ModelException { Collection sourceRoots = getAllSourceRootsInProjects(getReferencingProjects(project)); return (IProjectFragment[]) sourceRoots .toArray(new IProjectFragment[sourceRoots.size()]); } /* * @param projects a collection of IJavaProject @return Collection a * collection of IPackageFragmentRoot, one element for each * packageFragmentRoot which lies within a project in <code> projects * </code> . */ private static Collection getAllSourceRootsInProjects(Collection projects) throws ModelException { List result = new ArrayList(); for (Iterator it = projects.iterator(); it.hasNext();) result.addAll(getSourceRoots((IScriptProject) it.next())); return result; } /* * Finds, if possible, a classpathEntry in one given project such that this * classpath entry references another given project. If more than one entry * exists for the referenced project and at least one is exported, then an * exported entry will be returned. */ private static IBuildpathEntry getReferencingClassPathEntry( IScriptProject referencingProject, IScriptProject referencedProject) throws ModelException { IBuildpathEntry result = null; IPath path = referencedProject.getProject().getFullPath(); IBuildpathEntry[] classpath = referencingProject .getResolvedBuildpath(true); for (int i = 0; i < classpath.length; i++) { IBuildpathEntry entry = classpath[i]; if (entry.getEntryKind() == IBuildpathEntry.BPE_PROJECT && path.equals(entry.getPath())) { if (entry.isExported()) return entry; // Consider it as a candidate. May be there is another entry // that is // exported. result = entry; } } return result; } // // private static IJavaProject[] getRelatedProjects(IJavaProject focus) // throws CoreException { // final Set projects = new HashSet(); // // addRelatedReferencing(focus, projects); // addRelatedReferenced(focus, projects); // // projects.add(focus); // return (IJavaProject[]) projects.toArray(new IJavaProject[projects // .size()]); // } // private static Collection getReferencingProjects(IScriptProject focus) throws ModelException { Set projects = new HashSet(); addReferencingProjects(focus, projects); projects.add(focus); return projects; } // private static List getSourceRoots(IScriptProject javaProject) throws ModelException { List elements = new ArrayList(); IProjectFragment[] roots = javaProject.getProjectFragments(); // Add all package fragment roots except archives for (int i = 0; i < roots.length; i++) { IProjectFragment root = roots[i]; if (!root.isArchive()) elements.add(root); } return elements; } // // private static int getVisibility(IMember member) throws // ModelException { // if (JdtFlags.isPrivate(member)) // return 0; // if (JdtFlags.isPackageVisible(member)) // return 1; // if (JdtFlags.isProtected(member)) // return 2; // return 4; // } private RefactoringScopeFactory() { // no instances } }