|
From: <caw...@us...> - 2007-07-17 14:37:53
|
Revision: 2768
http://svn.sourceforge.net/rubyeclipse/?rev=2768&view=rev
Author: cawilliams
Date: 2007-07-17 07:37:49 -0700 (Tue, 17 Jul 2007)
Log Message:
-----------
more type hierarchy work
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyProject.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IType.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/RubyCore.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyType.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/HierarchyBuilder.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/CreateTypeHierarchyOperation.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyProject.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyProject.java 2007-07-16 17:16:44 UTC (rev 2767)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyProject.java 2007-07-17 14:37:49 UTC (rev 2768)
@@ -182,4 +182,19 @@
* @since 1.0
*/
IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) throws RubyModelException;
+
+ /**
+ * Creates and returns a type hierarchy for all types in the given
+ * region, considering subtypes within that region.
+ *
+ * @param monitor the given progress monitor
+ * @param region the given region
+ * @exception RubyModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @exception IllegalArgumentException if region is <code>null</code>
+ * @return a type hierarchy for all types in the given
+ * region, considering subtypes within that region
+ */
+ ITypeHierarchy newTypeHierarchy(IRegion region, IProgressMonitor monitor)
+ throws RubyModelException;
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IType.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IType.java 2007-07-16 17:16:44 UTC (rev 2767)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IType.java 2007-07-17 14:37:49 UTC (rev 2768)
@@ -25,7 +25,6 @@
package org.rubypeople.rdt.core;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.rubypeople.rdt.internal.core.RubyMethod;
/**
* @author Chris
@@ -33,7 +32,7 @@
*/
public interface IType extends IRubyElement, IMember {
- public RubyMethod getMethod(String name, String[] parameterNames);
+ public IMethod getMethod(String name, String[] parameterNames);
/**
* Returns the methods and constructors declared by this type. For binary
@@ -199,4 +198,16 @@
*/
ITypeHierarchy newSupertypeHierarchy(IProgressMonitor monitor) throws RubyModelException;
+ /**
+ * Creates and returns a type hierarchy for this type containing
+ * this type, all of its supertypes, and all its subtypes in the workspace.
+ *
+ * @param monitor the given progress monitor
+ * @exception RubyModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return a type hierarchy for this type containing
+ * this type, all of its supertypes, and all its subtypes in the workspace
+ */
+ ITypeHierarchy newTypeHierarchy(IProgressMonitor monitor) throws RubyModelException;
+
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/RubyCore.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/RubyCore.java 2007-07-16 17:16:44 UTC (rev 2767)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/RubyCore.java 2007-07-17 14:37:49 UTC (rev 2768)
@@ -47,8 +47,6 @@
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.FrameworkListener;
import org.rubypeople.rdt.core.search.IRubySearchConstants;
import org.rubypeople.rdt.core.search.SearchEngine;
import org.rubypeople.rdt.core.search.SearchMatch;
@@ -59,6 +57,7 @@
import org.rubypeople.rdt.internal.core.DefaultWorkingCopyOwner;
import org.rubypeople.rdt.internal.core.LoadpathAttribute;
import org.rubypeople.rdt.internal.core.LoadpathEntry;
+import org.rubypeople.rdt.internal.core.Region;
import org.rubypeople.rdt.internal.core.RubyCorePreferenceInitializer;
import org.rubypeople.rdt.internal.core.RubyModel;
import org.rubypeople.rdt.internal.core.RubyModelManager;
@@ -1469,4 +1468,13 @@
// ignore
}
}
+
+ /**
+ * Returns a new empty region.
+ *
+ * @return a new empty region
+ */
+ public static IRegion newRegion() {
+ return new Region();
+ }
}
Added: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/CreateTypeHierarchyOperation.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/CreateTypeHierarchyOperation.java (rev 0)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/CreateTypeHierarchyOperation.java 2007-07-17 14:37:49 UTC (rev 2768)
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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.rubypeople.rdt.internal.core;
+
+import org.rubypeople.rdt.core.IRegion;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IRubyModelStatus;
+import org.rubypeople.rdt.core.IRubyModelStatusConstants;
+import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.core.ITypeHierarchy;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+import org.rubypeople.rdt.internal.core.hierarchy.RegionBasedTypeHierarchy;
+import org.rubypeople.rdt.internal.core.hierarchy.TypeHierarchy;
+
+/**
+ * This operation creates an <code>ITypeHierarchy</code> for a specific type within
+ * a specified region, or for all types within a region. The specified
+ * region limits the number of resolved subtypes (to the subset of
+ * types in the specified region). The resolved supertypes may go outside
+ * of the specified region in order to reach the root(s) of the type
+ * hierarchy. A Ruby Project is required to provide a context (classpath)
+ * to use while resolving supertypes and subtypes.
+ *
+ * @see ITypeHierarchy
+ */
+
+public class CreateTypeHierarchyOperation extends RubyModelOperation {
+ /**
+ * The generated type hierarchy
+ */
+ protected TypeHierarchy typeHierarchy;
+
+/**
+ * Constructs an operation to create a type hierarchy for the
+ * given type within the specified region, in the context of
+ * the given project.
+ */
+public CreateTypeHierarchyOperation(IRegion region, IRubyScript[] workingCopies, IType element, boolean computeSubtypes) {
+ super(element);
+ this.typeHierarchy = new RegionBasedTypeHierarchy(region, workingCopies, element, computeSubtypes);
+}
+/**
+ * Constructs an operation to create a type hierarchy for the
+ * given type and working copies.
+ */
+public CreateTypeHierarchyOperation(IType element, IRubyScript[] workingCopies, IRubySearchScope scope, boolean computeSubtypes) {
+ super(element);
+ IRubyScript[] copies;
+ if (workingCopies != null) {
+ int length = workingCopies.length;
+ copies = new IRubyScript[length];
+ System.arraycopy(workingCopies, 0, copies, 0, length);
+ } else {
+ copies = null;
+ }
+ this.typeHierarchy = new TypeHierarchy(element, copies, scope, computeSubtypes);
+}
+/**
+ * Constructs an operation to create a type hierarchy for the
+ * given type and working copies.
+ */
+public CreateTypeHierarchyOperation(IType element, IRubyScript[] workingCopies, IRubyProject project, boolean computeSubtypes) {
+ super(element);
+ IRubyScript[] copies;
+ if (workingCopies != null) {
+ int length = workingCopies.length;
+ copies = new IRubyScript[length];
+ System.arraycopy(workingCopies, 0, copies, 0, length);
+ } else {
+ copies = null;
+ }
+ this.typeHierarchy = new TypeHierarchy(element, copies, project, computeSubtypes);
+}
+/**
+ * Performs the operation - creates the type hierarchy
+ * @exception RubyModelException The operation has failed.
+ */
+protected void executeOperation() throws RubyModelException {
+ this.typeHierarchy.refresh(this);
+}
+/**
+ * Returns the generated type hierarchy.
+ */
+public ITypeHierarchy getResult() {
+ return this.typeHierarchy;
+}
+/**
+ * @see RubyModelOperation
+ */
+public boolean isReadOnly() {
+ return true;
+}
+/**
+ * Possible failures: <ul>
+ * <li>NO_ELEMENTS_TO_PROCESS - at least one of a type or region must
+ * be provided to generate a type hierarchy.
+ * <li>ELEMENT_NOT_PRESENT - the provided type or type's project does not exist
+ * </ul>
+ */
+public IRubyModelStatus verify() {
+ IRubyElement elementToProcess= getElementToProcess();
+ if (elementToProcess == null && !(this.typeHierarchy instanceof RegionBasedTypeHierarchy)) {
+ return new RubyModelStatus(IRubyModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
+ }
+ if (elementToProcess != null && !elementToProcess.exists()) {
+ return new RubyModelStatus(IRubyModelStatusConstants.ELEMENT_DOES_NOT_EXIST, elementToProcess);
+ }
+ IRubyProject project = this.typeHierarchy.javaProject();
+ if (project != null && !project.exists()) {
+ return new RubyModelStatus(IRubyModelStatusConstants.ELEMENT_DOES_NOT_EXIST, project);
+ }
+ return RubyModelStatus.VERIFIED_OK;
+}
+}
Property changes on: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/CreateTypeHierarchyOperation.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyType.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyType.java 2007-07-16 17:16:44 UTC (rev 2767)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyType.java 2007-07-17 14:37:49 UTC (rev 2768)
@@ -38,6 +38,7 @@
import org.rubypeople.rdt.core.ITypeHierarchy;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.core.WorkingCopyOwner;
+import org.rubypeople.rdt.core.search.SearchEngine;
import org.rubypeople.rdt.internal.core.util.MementoTokenizer;
/**
@@ -112,7 +113,7 @@
return array;
}
- public RubyMethod getMethod(String name, String[] parameterNames) {
+ public IMethod getMethod(String name, String[] parameterNames) {
return new RubyMethod(this, name, parameterNames);
}
@@ -320,6 +321,15 @@
/**
* @see IType
*/
+ public ITypeHierarchy newTypeHierarchy(IProgressMonitor monitor) throws RubyModelException {
+ CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, null, SearchEngine.createWorkspaceScope(), true);
+ op.runOperation(monitor);
+ return op.getResult();
+ }
+
+ /**
+ * @see IType
+ */
public ITypeHierarchy newSupertypeHierarchy(IProgressMonitor monitor) throws RubyModelException {
return this.newSupertypeHierarchy(DefaultWorkingCopyOwner.PRIMARY, monitor);
}
@@ -333,11 +343,9 @@
throws RubyModelException {
IRubyScript[] workingCopies = RubyModelManager.getRubyModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
-// CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), false);
-// op.runOperation(monitor);
-// return op.getResult();
- // XXX Implement!
- return null;
+ CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), false);
+ op.runOperation(monitor);
+ return op.getResult();
}
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/HierarchyBuilder.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/HierarchyBuilder.java 2007-07-16 17:16:44 UTC (rev 2767)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/HierarchyBuilder.java 2007-07-17 14:37:49 UTC (rev 2768)
@@ -14,6 +14,8 @@
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
import org.rubypeople.rdt.core.IType;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.internal.core.RubyElement;
@@ -165,4 +167,14 @@
this.hierarchy.addRootClass(focusType);
}
}
+
+ protected void worked(IProgressMonitor monitor, int work) {
+ if (monitor != null) {
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ } else {
+ monitor.worked(work);
+ }
+ }
+ }
}
Added: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java (rev 0)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java 2007-07-17 14:37:49 UTC (rev 2768)
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ * 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.rubypeople.rdt.internal.core.hierarchy;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.core.ISourceFolder;
+import org.rubypeople.rdt.core.ISourceFolderRoot;
+import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.internal.core.Openable;
+import org.rubypeople.rdt.internal.core.RubyProject;
+
+public class RegionBasedHierarchyBuilder extends HierarchyBuilder {
+
+ public RegionBasedHierarchyBuilder(TypeHierarchy hierarchy)
+ throws RubyModelException {
+
+ super(hierarchy);
+ }
+
+public void build(boolean computeSubtypes) {
+
+// RubyModelManager manager = RubyModelManager.getRubyModelManager();
+ try {
+ // optimize access to zip files while building hierarchy
+// manager.cacheZipFiles();
+
+ if (this.hierarchy.focusType == null || computeSubtypes) {
+ IProgressMonitor typeInRegionMonitor =
+ this.hierarchy.progressMonitor == null ?
+ null :
+ new SubProgressMonitor(this.hierarchy.progressMonitor, 30);
+ HashMap allOpenablesInRegion = determineOpenablesInRegion(typeInRegionMonitor);
+ this.hierarchy.initialize(allOpenablesInRegion.size());
+ IProgressMonitor buildMonitor =
+ this.hierarchy.progressMonitor == null ?
+ null :
+ new SubProgressMonitor(this.hierarchy.progressMonitor, 70);
+ createTypeHierarchyBasedOnRegion(allOpenablesInRegion, buildMonitor);
+ ((RegionBasedTypeHierarchy)this.hierarchy).pruneDeadBranches();
+ } else {
+ this.hierarchy.initialize(1);
+ this.buildSupertypes();
+ }
+ } finally {
+// manager.flushZipFiles();
+ }
+}
+/**
+ * Configure this type hierarchy that is based on a region.
+ */
+private void createTypeHierarchyBasedOnRegion(HashMap allOpenablesInRegion, IProgressMonitor monitor) {
+
+ int size = allOpenablesInRegion.size();
+ if (size == 0) {
+ if (monitor != null) monitor.done();
+ return;
+ }
+
+ this.infoToHandle = new HashMap(size);
+ Iterator javaProjects = allOpenablesInRegion.keySet().iterator();
+ while (javaProjects.hasNext()) {
+ RubyProject project = (RubyProject) javaProjects.next();
+ ArrayList allOpenables = (ArrayList) allOpenablesInRegion.get(project);
+ Openable[] openables = new Openable[allOpenables.size()];
+ allOpenables.toArray(openables);
+
+ try {
+ // resolve
+ if (monitor != null) monitor.beginTask("", size * 2/* 1 for build binding, 1 for connect hierarchy*/); //$NON-NLS-1$
+// SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(this.hierarchy.workingCopies);
+// this.nameLookup = searchableEnvironment.nameLookup;
+ this.hierarchyResolver.resolve(openables, null, monitor);
+// } catch (RubyModelException e) {
+ // project doesn't exit: ignore
+ } finally {
+ if (monitor != null) monitor.done();
+ }
+ }
+}
+
+ /**
+ * Returns all of the openables defined in the region of this type hierarchy.
+ * Returns a map from IRubyProject to ArrayList of Openable
+ */
+ private HashMap determineOpenablesInRegion(IProgressMonitor monitor) {
+
+ try {
+ HashMap allOpenables = new HashMap();
+ IRubyElement[] roots =
+ ((RegionBasedTypeHierarchy) this.hierarchy).region.getElements();
+ int length = roots.length;
+ if (monitor != null) monitor.beginTask("", length); //$NON-NLS-1$
+ for (int i = 0; i <length; i++) {
+ IRubyElement root = roots[i];
+ IRubyProject javaProject = root.getRubyProject();
+ ArrayList openables = (ArrayList) allOpenables.get(javaProject);
+ if (openables == null) {
+ openables = new ArrayList();
+ allOpenables.put(javaProject, openables);
+ }
+ switch (root.getElementType()) {
+ case IRubyElement.RUBY_PROJECT :
+ injectAllOpenablesForRubyProject((IRubyProject) root, openables);
+ break;
+ case IRubyElement.SOURCE_FOLDER_ROOT :
+ injectAllOpenablesForSourceFolderRoot((ISourceFolderRoot) root, openables);
+ break;
+ case IRubyElement.SOURCE_FOLDER :
+ injectAllOpenablesForSourceFolder((ISourceFolder) root, openables);
+ break;
+ case IRubyElement.SCRIPT :
+ openables.add(root);
+ break;
+ case IRubyElement.TYPE :
+ IType type = (IType)root;
+ openables.add(type.getRubyScript());
+ break;
+ default :
+ break;
+ }
+ worked(monitor, 1);
+ }
+ return allOpenables;
+ } finally {
+ if (monitor != null) monitor.done();
+ }
+ }
+
+ /**
+ * Adds all of the openables defined within this java project to the
+ * list.
+ */
+ private void injectAllOpenablesForRubyProject(
+ IRubyProject project,
+ ArrayList openables) {
+ try {
+ ISourceFolderRoot[] devPathRoots =
+ ((RubyProject) project).getSourceFolderRoots();
+ if (devPathRoots == null) {
+ return;
+ }
+ for (int j = 0; j < devPathRoots.length; j++) {
+ ISourceFolderRoot root = devPathRoots[j];
+ injectAllOpenablesForSourceFolderRoot(root, openables);
+ }
+ } catch (RubyModelException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * Adds all of the openables defined within this package fragment to the
+ * list.
+ */
+ private void injectAllOpenablesForSourceFolder(
+ ISourceFolder packFrag,
+ ArrayList openables) {
+
+ try {
+ IRubyScript[] cus = packFrag.getRubyScripts();
+ for (int i = 0, length = cus.length; i < length; i++) {
+ openables.add(cus[i]);
+ }
+ } catch (RubyModelException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * Adds all of the openables defined within this package fragment root to the
+ * list.
+ */
+ private void injectAllOpenablesForSourceFolderRoot(
+ ISourceFolderRoot root,
+ ArrayList openables) {
+ try {
+ IRubyElement[] packFrags = root.getChildren();
+ for (int k = 0; k < packFrags.length; k++) {
+ ISourceFolder packFrag = (ISourceFolder) packFrags[k];
+ injectAllOpenablesForSourceFolder(packFrag, openables);
+ }
+ } catch (RubyModelException e) {
+ return;
+ }
+ }
+
+}
Property changes on: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java (rev 0)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java 2007-07-17 14:37:49 UTC (rev 2768)
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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.rubypeople.rdt.internal.core.hierarchy;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.runtime.CoreException;
+import org.rubypeople.rdt.core.IOpenable;
+import org.rubypeople.rdt.core.IRegion;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IRubyElementDelta;
+import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.core.ISourceFolderRoot;
+import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+import org.rubypeople.rdt.internal.core.Openable;
+import org.rubypeople.rdt.internal.core.Region;
+import org.rubypeople.rdt.internal.core.RubyElement;
+import org.rubypeople.rdt.internal.core.RubyScript;
+import org.rubypeople.rdt.internal.core.TypeVector;
+
+public class RegionBasedTypeHierarchy extends TypeHierarchy {
+ /**
+ * The region of types for which to build the hierarchy
+ */
+ protected IRegion region;
+
+/**
+ * Creates a TypeHierarchy on the types in the specified region,
+ * considering first the given working copies,
+ * using the projects in the given region for a name lookup context. If a specific
+ * type is also specified, the type hierarchy is pruned to only
+ * contain the branch including the specified type.
+ */
+public RegionBasedTypeHierarchy(IRegion region, IRubyScript[] workingCopies, IType type, boolean computeSubtypes) {
+ super(type, workingCopies, (IRubySearchScope)null, computeSubtypes);
+
+ Region newRegion = new Region() {
+ public void add(IRubyElement element) {
+ if (!contains(element)) {
+ //"new" element added to region
+ removeAllChildren(element);
+ fRootElements.add(element);
+ if (element.getElementType() == IRubyElement.RUBY_PROJECT) {
+ // add jar roots as well so that jars don't rely on their parent to know
+ // if they are contained in the region
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=146615)
+ try {
+ ISourceFolderRoot[] roots = ((IRubyProject) element).getSourceFolderRoots();
+ for (int i = 0, length = roots.length; i < length; i++) {
+ if (roots[i].isArchive() && !fRootElements.contains(roots[i]))
+ fRootElements.add(roots[i]);
+ }
+ } catch (RubyModelException e) {
+ // project doesn't exist
+ }
+ }
+ fRootElements.trimToSize();
+ }
+ }
+ };
+ IRubyElement[] elements = region.getElements();
+ for (int i = 0, length = elements.length; i < length; i++) {
+ newRegion.add(elements[i]);
+
+ }
+ this.region = newRegion;
+ if (elements.length > 0)
+ this.project = elements[0].getRubyProject();
+}
+/*
+ * @see TypeHierarchy#initializeRegions
+ */
+protected void initializeRegions() {
+ super.initializeRegions();
+ IRubyElement[] roots = this.region.getElements();
+ for (int i = 0; i < roots.length; i++) {
+ IRubyElement root = roots[i];
+ if (root instanceof IOpenable) {
+ this.files.put(root, new ArrayList());
+ } else {
+ Openable o = (Openable) ((RubyElement) root).getOpenableParent();
+ if (o != null) {
+ this.files.put(o, new ArrayList());
+ }
+ }
+ checkCanceled();
+ }
+}
+/**
+ * Compute this type hierarchy.
+ */
+protected void compute() throws RubyModelException, CoreException {
+ HierarchyBuilder builder = new RegionBasedHierarchyBuilder(this);
+ builder.build(this.computeSubtypes);
+}
+protected boolean isAffectedByOpenable(IRubyElementDelta delta, IRubyElement element) {
+ // change to working copy
+ if (element instanceof RubyScript && ((RubyScript)element).isWorkingCopy()) {
+ return super.isAffectedByOpenable(delta, element);
+ }
+
+ // if no focus, hierarchy is affected if the element is part of the region
+ if (this.focusType == null) {
+ return this.region.contains(element);
+ } else {
+ return super.isAffectedByOpenable(delta, element);
+ }
+}
+/**
+ * Returns the java project this hierarchy was created in.
+ */
+public IRubyProject javaProject() {
+ return this.project;
+}
+public void pruneDeadBranches() {
+ pruneDeadBranches(getRootClasses());
+ pruneDeadBranches(getRootInterfaces());
+}
+/*
+ * Returns whether all subtypes of the given type have been pruned.
+ */
+private boolean pruneDeadBranches(IType type) {
+ TypeVector subtypes = (TypeVector)this.typeToSubtypes.get(type);
+ if (subtypes == null) return true;
+ pruneDeadBranches(subtypes.copy().elements());
+ subtypes = (TypeVector)this.typeToSubtypes.get(type);
+ return (subtypes == null || subtypes.size == 0);
+}
+private void pruneDeadBranches(IType[] types) {
+ for (int i = 0, length = types.length; i < length; i++) {
+ IType type = types[i];
+ if (pruneDeadBranches(type) && !this.region.contains(type)) {
+ removeType(type);
+ }
+ }
+}
+/**
+ * Removes all the subtypes of the given type from the type hierarchy,
+ * removes its superclass entry and removes the references from its super types.
+ */
+protected void removeType(IType type) {
+ IType[] subtypes = this.getSubtypes(type);
+ this.typeToSubtypes.remove(type);
+ if (subtypes != null) {
+ for (int i= 0; i < subtypes.length; i++) {
+ this.removeType(subtypes[i]);
+ }
+ }
+ IType superclass = (IType)this.classToSuperclass.remove(type);
+ if (superclass != null) {
+ TypeVector types = (TypeVector)this.typeToSubtypes.get(superclass);
+ if (types != null) types.remove(type);
+ }
+ IType[] superinterfaces = (IType[])this.typeToSuperInterfaces.remove(type);
+ if (superinterfaces != null) {
+ for (int i = 0, length = superinterfaces.length; i < length; i++) {
+ IType superinterface = superinterfaces[i];
+ TypeVector types = (TypeVector)this.typeToSubtypes.get(superinterface);
+ if (types != null) types.remove(type);
+ }
+ }
+ this.interfaces.remove(type);
+}
+
+}
Property changes on: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|