|
From: <caw...@us...> - 2007-01-06 21:23:22
|
Revision: 1756
http://svn.sourceforge.net/rubyeclipse/?rev=1756&view=rev
Author: cawilliams
Date: 2007-01-06 13:23:21 -0800 (Sat, 06 Jan 2007)
Log Message:
-----------
get test to pass for Rubyproject (adding Project Prerequisites), add new test for corresponding resource for script
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyProject.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/DeltaProcessingState.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/DeltaProcessor.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelManager.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelOperation.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyProject.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MarkerManager.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyBuilder.java
trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/core/tests/AbstractRubyModelTest.java
trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/core/tests/ModifyingResourceTest.java
trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/TC_RubyProject.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-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyProject.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -131,4 +131,6 @@
void setRawLoadpath(ILoadpathEntry[] entries, IPath outputLocation, IProgressMonitor monitor)
throws RubyModelException;
+
+ public abstract ISourceFolderRoot getSourceFolderRoot(String rootPath);
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/DeltaProcessingState.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/DeltaProcessingState.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/DeltaProcessingState.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -14,25 +14,25 @@
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
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.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
-import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
import org.rubypeople.rdt.core.IElementChangedListener;
import org.rubypeople.rdt.core.ILoadpathEntry;
+import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IRubyModel;
import org.rubypeople.rdt.core.IRubyProject;
import org.rubypeople.rdt.core.RubyCore;
@@ -183,7 +183,7 @@
public void handleException(Throwable exception) {
Util
.log(exception,
- "Exception occurred in listener of pre Java resource change notification"); //$NON-NLS-1$
+ "Exception occurred in listener of pre Ruby resource change notification"); //$NON-NLS-1$
}
public void run() throws Exception {
@@ -501,4 +501,43 @@
}
}
+
+ /*
+ * Update the roots that are affected by the addition or the removal of the given container resource.
+ */
+ public synchronized void updateRoots(IPath containerPath, IResourceDelta containerDelta, DeltaProcessor deltaProcessor) {
+ Map updatedRoots;
+ Map otherUpdatedRoots;
+ if (containerDelta.getKind() == IResourceDelta.REMOVED) {
+ updatedRoots = this.oldRoots;
+ otherUpdatedRoots = this.oldOtherRoots;
+ } else {
+ updatedRoots = this.roots;
+ otherUpdatedRoots = this.otherRoots;
+ }
+ Iterator iterator = updatedRoots.keySet().iterator();
+ while (iterator.hasNext()) {
+ IPath path = (IPath)iterator.next();
+ if (containerPath.isPrefixOf(path) && !containerPath.equals(path)) {
+ IResourceDelta rootDelta = containerDelta.findMember(path.removeFirstSegments(1));
+ if (rootDelta == null) continue;
+ DeltaProcessor.RootInfo rootInfo = (DeltaProcessor.RootInfo)updatedRoots.get(path);
+
+ if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
+ deltaProcessor.updateCurrentDeltaAndIndex(rootDelta, IRubyElement.SOURCE_FOLDER_ROOT, rootInfo);
+ }
+
+ ArrayList rootList = (ArrayList)otherUpdatedRoots.get(path);
+ if (rootList != null) {
+ Iterator otherProjects = rootList.iterator();
+ while (otherProjects.hasNext()) {
+ rootInfo = (DeltaProcessor.RootInfo)otherProjects.next();
+ if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
+ deltaProcessor.updateCurrentDeltaAndIndex(rootDelta, IRubyElement.SOURCE_FOLDER_ROOT, rootInfo);
+ }
+ }
+ }
+ }
+ }
+ }
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/DeltaProcessor.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/DeltaProcessor.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/DeltaProcessor.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -15,6 +15,7 @@
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
@@ -23,6 +24,7 @@
import org.eclipse.core.runtime.SafeRunner;
import org.rubypeople.rdt.core.ElementChangedEvent;
import org.rubypeople.rdt.core.IElementChangedListener;
+import org.rubypeople.rdt.core.ILoadpathEntry;
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IRubyElementDelta;
import org.rubypeople.rdt.core.IRubyModel;
@@ -49,7 +51,7 @@
this.exclusionPatterns = exclusionPatterns;
this.entryKind = entryKind;
}
- ISourceFolderRoot getPackageFragmentRoot(IResource resource) {
+ ISourceFolderRoot getSourceFolderRoot(IResource resource) {
if (this.root == null) {
if (resource != null) {
this.root = this.project.getSourceFolderRoot(resource);
@@ -145,7 +147,7 @@
* Queue of deltas created explicily by the Ruby Model that have yet to be
* fired.
*/
- public ArrayList javaModelDeltas = new ArrayList();
+ public ArrayList rubyModelDeltas = new ArrayList();
/*
* Queue of reconcile deltas on working copies that have yet to be fired.
@@ -159,7 +161,10 @@
* and using the various get*(...) to push it.
*/
private Openable currentElement;
-
+
+ /* A set of IRubyProject whose source folder roots need to be refreshed */
+ private HashSet rootsToRefresh = new HashSet();
+
/*
* The <code>RubyElementDelta</code> corresponding to the <code>IResourceDelta</code>
* being translated.
@@ -178,13 +183,13 @@
}
public void registerRubyModelDelta(IRubyElementDelta delta) {
- this.javaModelDeltas.add(delta);
+ this.rubyModelDeltas.add(delta);
}
public void updateRubyModel(IRubyElementDelta customDelta) {
if (customDelta == null) {
- for (int i = 0, length = this.javaModelDeltas.size(); i < length; i++) {
- IRubyElementDelta delta = (IRubyElementDelta) this.javaModelDeltas.get(i);
+ for (int i = 0, length = this.rubyModelDeltas.size(); i < length; i++) {
+ IRubyElementDelta delta = (IRubyElementDelta) this.rubyModelDeltas.get(i);
this.modelUpdater.processRubyDelta(delta);
}
} else {
@@ -207,7 +212,7 @@
IRubyElementDelta deltaToNotify;
if (customDelta == null) {
- deltaToNotify = this.mergeDeltas(this.javaModelDeltas);
+ deltaToNotify = this.mergeDeltas(this.rubyModelDeltas);
} else {
deltaToNotify = customDelta;
}
@@ -331,7 +336,7 @@
* Flushes all deltas without firing them.
*/
public void flush() {
- this.javaModelDeltas = new ArrayList();
+ this.rubyModelDeltas = new ArrayList();
}
private void notifyListeners(IRubyElementDelta deltaToNotify, int eventType,
@@ -411,6 +416,10 @@
try {
stopDeltas();
checkProjectsBeingAddedOrRemoved(delta);
+ if (this.refreshedElements != null) {
+ // TODO Actually update external references too
+// createExternalArchiveDelta(null);
+ }
IRubyElementDelta translatedDelta = processResourceDelta(delta);
if (translatedDelta != null) {
registerRubyModelDelta(translatedDelta);
@@ -418,9 +427,14 @@
} finally {
startDeltas();
}
- // notifyTypeHierarchies(this.state.elementChangedListeners,
- // this.state.elementChangedListenerCount);
- fire(null, ElementChangedEvent.POST_CHANGE);
+ IElementChangedListener[] listeners;
+ int listenerCount;
+ synchronized (this.state) {
+ listeners = this.state.elementChangedListeners;
+ listenerCount = this.state.elementChangedListenerCount;
+ }
+// notifyTypeHierarchies(listeners, listenerCount);
+ fire(null, ElementChangedEvent.POST_CHANGE);
} finally {
// workaround for bug 15168 circular errors not reported
this.state.resetOldRubyProjectNames();
@@ -443,7 +457,7 @@
// this.processPostChange = false;
if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
// FIXME Update the loadpath markers
-// updateLoadpathMarkers(delta, updates);
+ updateLoadpathMarkers(delta, updates);
// RubyBuilder.buildStarting();
}
// does not fire any deltas
@@ -453,6 +467,162 @@
}
/*
+ * Update the .loadpath format, missing entries and cycle markers for the projects affected by the given delta.
+ */
+ private void updateLoadpathMarkers(IResourceDelta delta, DeltaProcessingState.ProjectUpdateInfo[] updates) {
+
+ Map preferredClasspaths = new HashMap(5);
+ Map preferredOutputs = new HashMap(5);
+ HashSet affectedProjects = new HashSet(5);
+
+ // read .loadpath files that have changed, and create markers if format is wrong or if an entry cannot be found
+ RubyModel.flushExternalFileCache();
+ updateLoadpathMarkers(delta, affectedProjects, preferredClasspaths, preferredOutputs);
+
+ // update .loadpath format markers for affected projects (dependent projects
+ // or projects that reference a library in one of the projects that have changed)
+ if (!affectedProjects.isEmpty()) {
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IProject[] projects = workspaceRoot.getProjects();
+ int length = projects.length;
+ for (int i = 0; i < length; i++){
+ IProject project = projects[i];
+ RubyProject rubyProject = (RubyProject)RubyCore.create(project);
+ if (preferredClasspaths.get(rubyProject) == null) { // not already updated
+ try {
+ IPath projectPath = project.getFullPath();
+ ILoadpathEntry[] classpath = rubyProject.getResolvedLoadpath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/); // allowed to reuse model cache
+ for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
+ ILoadpathEntry entry = classpath[j];
+ switch (entry.getEntryKind()) {
+ case ILoadpathEntry.CPE_PROJECT:
+ if (affectedProjects.contains(entry.getPath())) {
+ rubyProject.updateLoadpathMarkers(null, null);
+ }
+ break;
+ case ILoadpathEntry.CPE_LIBRARY:
+ IPath entryPath = entry.getPath();
+ IPath libProjectPath = entryPath.removeLastSegments(entryPath.segmentCount()-1);
+ if (!libProjectPath.equals(projectPath) // if library contained in another project
+ && affectedProjects.contains(libProjectPath)) {
+ rubyProject.updateLoadpathMarkers(null, null);
+ }
+ break;
+ }
+ }
+ } catch(RubyModelException e) {
+ // project no longer exists
+ }
+ }
+ }
+ }
+ if (!affectedProjects.isEmpty() || updates != null) {
+ // update all cycle markers since the given delta may have affected cycles
+ if (updates != null) {
+ for (int i = 0, length = updates.length; i < length; i++) {
+ DeltaProcessingState.ProjectUpdateInfo info = updates[i];
+ if (!preferredClasspaths.containsKey(info.project))
+ preferredClasspaths.put(info.project, info.newResolvedPath);
+ }
+ }
+ try {
+ RubyProject.updateAllCycleMarkers(preferredClasspaths);
+ } catch (RubyModelException e) {
+ // project no longer exist
+ }
+ }
+ }
+
+ /*
+ * Check whether .classpath files are affected by the given delta.
+ * Creates/removes problem markers if needed.
+ * Remember the affected projects in the given set.
+ */
+ private void updateLoadpathMarkers(IResourceDelta delta, HashSet affectedProjects, Map preferredClasspaths, Map preferredOutputs) {
+ IResource resource = delta.getResource();
+ boolean processChildren = false;
+
+ switch (resource.getType()) {
+
+ case IResource.ROOT :
+ if (delta.getKind() == IResourceDelta.CHANGED) {
+ processChildren = true;
+ }
+ break;
+ case IResource.PROJECT :
+ IProject project = (IProject)resource;
+ int kind = delta.getKind();
+ boolean isRubyProject = RubyProject.hasRubyNature(project);
+ switch (kind) {
+ case IResourceDelta.ADDED:
+ processChildren = isRubyProject;
+ affectedProjects.add(project.getFullPath());
+ break;
+ case IResourceDelta.CHANGED:
+ processChildren = isRubyProject;
+ if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
+ // project opened or closed: remember project and its dependents
+ affectedProjects.add(project.getFullPath());
+ if (isRubyProject) {
+ RubyProject rubyProject = (RubyProject)RubyCore.create(project);
+ rubyProject.updateLoadpathMarkers(preferredClasspaths, preferredOutputs); // in case .loadpath got modified while closed
+ }
+ } else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
+ boolean wasRubyProject = this.state.findRubyProject(project.getName()) != null;
+ if (wasRubyProject && !isRubyProject) {
+ // project no longer has Ruby nature, discard Ruby related obsolete markers
+ affectedProjects.add(project.getFullPath());
+ // flush loadpath markers
+ RubyProject javaProject = (RubyProject)RubyCore.create(project);
+ javaProject.
+ flushLoadpathProblemMarkers(
+ true, // flush cycle markers
+ true //flush loadpath format markers
+ );
+
+ // remove problems and tasks created by the builder
+ RubyBuilder.removeProblemsAndTasksFor(project);
+ }
+ } else if (isRubyProject) {
+ // check if all entries exist
+ try {
+ RubyProject javaProject = (RubyProject)RubyCore.create(project);
+ javaProject.getResolvedLoadpath(true/*ignoreUnresolvedEntry*/, true/*generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ } catch (RubyModelException e) {
+ // project doesn't exist: ignore
+ }
+ }
+ break;
+ case IResourceDelta.REMOVED:
+ affectedProjects.add(project.getFullPath());
+ break;
+ }
+ break;
+ case IResource.FILE :
+ /* check loadpath file change */
+ IFile file = (IFile) resource;
+ if (file.getName().equals(RubyProject.LOADPATH_FILENAME)) {
+ affectedProjects.add(file.getProject().getFullPath());
+ RubyProject rubyProject = (RubyProject)RubyCore.create(file.getProject());
+ rubyProject.updateLoadpathMarkers(preferredClasspaths, preferredOutputs);
+ break;
+ }
+// /* check custom preference file change */
+// if (file.getName().equals(JavaProject.PREF_FILENAME)) {
+// reconcilePreferenceFileUpdate(delta, file, project);
+// break;
+// }
+ break;
+ }
+ if (processChildren) {
+ IResourceDelta[] children = delta.getAffectedChildren();
+ for (int i = 0; i < children.length; i++) {
+ updateLoadpathMarkers(children[i], affectedProjects, preferredClasspaths, preferredOutputs);
+ }
+ }
+ }
+
+ /*
* Converts a <code>IResourceDelta</code> rooted in a <code>Workspace</code>
* into the corresponding set of <code>IRubyElementDelta</code>, rooted
* in the relevant <code>RubyModel</code>s.
@@ -483,18 +653,24 @@
IResource res = delta.getResource();
// find out the element type
+ RootInfo rootInfo = null;
int elementType;
IProject proj = (IProject) res;
- boolean wasJavaProject = this.manager.getRubyModel().findRubyProject(proj) != null;
+ boolean wasJavaProject = this.state.findRubyProject(proj.getName()) != null;
boolean isJavaProject = RubyProject.hasRubyNature(proj);
if (!wasJavaProject && !isJavaProject) {
elementType = NON_RUBY_RESOURCE;
} else {
- elementType = IRubyElement.RUBY_PROJECT;
+ rootInfo = this.enclosingRootInfo(res.getFullPath(), delta.getKind());
+ if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
+ elementType = IRubyElement.SOURCE_FOLDER_ROOT;
+ } else {
+ elementType = IRubyElement.RUBY_PROJECT;
+ }
}
-
+
// traverse delta
- this.traverseDelta(delta, elementType);
+ this.traverseDelta(delta, elementType, rootInfo);
if (elementType == NON_RUBY_RESOURCE
|| (wasJavaProject != isJavaProject && (delta.getKind()) == IResourceDelta.CHANGED)) { // project
@@ -518,9 +694,44 @@
return this.currentDelta;
} finally {
this.currentDelta = null;
+ this.rootsToRefresh.clear();
this.projectCachesToReset.clear();
}
}
+
+ /*
+ * Finds the root info this path is included in.
+ * Returns null if not found.
+ */
+ private RootInfo enclosingRootInfo(IPath path, int kind) {
+ while (path != null && path.segmentCount() > 0) {
+ RootInfo rootInfo = this.rootInfo(path, kind);
+ if (rootInfo != null) return rootInfo;
+ path = path.removeLastSegments(1);
+ }
+ return null;
+ }
+
+ /*
+ * Returns the root info for the given path. Look in the old roots table if kind is REMOVED.
+ */
+ private RootInfo rootInfo(IPath path, int kind) {
+ if (kind == IResourceDelta.REMOVED) {
+ return (RootInfo)this.state.oldRoots.get(path);
+ }
+ return (RootInfo)this.state.roots.get(path);
+ }
+
+ /*
+ * Refresh source folder roots of projects that were affected
+ */
+ private void refreshSourceFolderRoots() {
+ Iterator iterator = this.rootsToRefresh.iterator();
+ while (iterator.hasNext()) {
+ RubyProject project = (RubyProject)iterator.next();
+ project.updateSourceFolderRoots();
+ }
+ }
private RubyElementDelta currentDelta() {
if (this.currentDelta == null) {
@@ -757,14 +968,37 @@
RubyProject rubyProject = (RubyProject) RubyCore.create(project);
switch (delta.getKind()) {
case IResourceDelta.ADDED:
+ this.manager.batchContainerInitializations = true;
+
+ // remember project and its dependents
+ this.addToRootsToRefreshWithDependents(rubyProject);
+
// workaround for bug 15168 circular errors not reported
if (RubyProject.hasRubyNature(project)) {
this.addToParentInfo(rubyProject);
- }
- break;
+ // ensure project references are updated (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=121569)
+ try {
+ this.state.updateProjectReferences(
+ rubyProject,
+ null/*no old loadpath*/,
+ null/*compute new resolved loadpath later*/,
+ null/*read raw loadpath later*/,
+ false/*cannot change resources*/);
+ } catch (RubyModelException e1) {
+ // project always exists
+ }
+ }
+
+ this.state.rootsAreStale = true;
+ break;
case IResourceDelta.CHANGED:
if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
+ this.manager.batchContainerInitializations = true;
+
+ // project opened or closed: remember project and its dependents
+ this.addToRootsToRefreshWithDependents(rubyProject);
+
// workaround for bug 15168 circular errors not reported
if (project.isOpen()) {
if (RubyProject.hasRubyNature(project)) {
@@ -778,11 +1012,18 @@
}
this.removeFromParentInfo(rubyProject);
this.manager.removePerProjectInfo(rubyProject);
+ this.manager.containerRemove(rubyProject);
}
+ this.state.rootsAreStale = true;
} else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
- boolean wasJavaProject = this.manager.getRubyModel().findRubyProject(project) != null;
+ boolean wasJavaProject = this.state.findRubyProject(project.getName()) != null;
boolean isJavaProject = RubyProject.hasRubyNature(project);
if (wasJavaProject != isJavaProject) {
+ this.manager.batchContainerInitializations = true;
+
+ // ruby nature added or removed: remember project and its dependents
+ this.addToRootsToRefreshWithDependents(rubyProject);
+
// workaround for bug 15168 circular errors not reported
if (isJavaProject) {
this.addToParentInfo(rubyProject);
@@ -791,14 +1032,17 @@
// will not consider the project has a classpath
this.manager.removePerProjectInfo((RubyProject) RubyCore
.create(project));
+// remove container cache for this project
+ this.manager.containerRemove(rubyProject);
// close project
try {
rubyProject.close();
} catch (RubyModelException e) {
- // java project doesn't exist: ignore
+ // ruby project doesn't exist: ignore
}
this.removeFromParentInfo(rubyProject);
}
+ this.state.rootsAreStale = true;
} else {
// in case the project was removed then added then
// changed (see bug 19799)
@@ -819,11 +1063,15 @@
break;
case IResourceDelta.REMOVED:
-
- // remove classpath cache so that initializeRoots() will not
- // consider the project has a classpath
- this.manager.removePerProjectInfo((RubyProject) RubyCore.create(resource));
- break;
+ this.manager.batchContainerInitializations = true;
+
+ // remove classpath cache so that initializeRoots() will not consider the project has a classpath
+ this.manager.removePerProjectInfo(rubyProject);
+ // remove container cache for this project
+ this.manager.containerRemove(rubyProject);
+
+ this.state.rootsAreStale = true;
+ break;
}
// in all cases, refresh the external jars for this project
@@ -847,6 +1095,14 @@
}
}
}
+
+ /*
+ * Adds the given project and its dependents to the list of the roots to refresh.
+ */
+ private void addToRootsToRefreshWithDependents(IRubyProject javaProject) {
+ this.rootsToRefresh.add(javaProject);
+ this.addDependentProjects(javaProject, this.state.projectDependencies, this.rootsToRefresh);
+ }
/*
* Adds the given element to the list of elements used as a scope for
@@ -878,15 +1134,25 @@
* Converts an <code>IResourceDelta</code> and its children into the
* corresponding <code>IRubyElementDelta</code>s.
*/
- private void traverseDelta(IResourceDelta delta, int elementType) {
+ private void traverseDelta(IResourceDelta delta, int elementType, RootInfo rootInfo) {
IResource res = delta.getResource();
+
+ // set stack of elements
+ if (this.currentElement == null && rootInfo != null) {
+ this.currentElement = rootInfo.project;
+ }
// process current delta
boolean processChildren = true;
if (res instanceof IProject) {
- processChildren = updateCurrentDeltaAndIndex(delta, elementType);
- } else {
+ processChildren = updateCurrentDeltaAndIndex(delta,
+ elementType == IRubyElement.SOURCE_FOLDER_ROOT ?
+ IRubyElement.RUBY_PROJECT : // case of prj=src,
+ elementType, rootInfo);
+ } else if (rootInfo != null) {
+ processChildren = this.updateCurrentDeltaAndIndex(delta, elementType, rootInfo);
+ } else {
// not yet inside a package fragment root
processChildren = true;
}
@@ -935,49 +1201,64 @@
* delta must be processed. @throws a RubyModelException if the delta
* doesn't correspond to a ruby element of the given type.
*/
- public boolean updateCurrentDeltaAndIndex(IResourceDelta delta, int elementType) {
+ public boolean updateCurrentDeltaAndIndex(IResourceDelta delta, int elementType, RootInfo rootInfo) {
Openable element;
switch (delta.getKind()) {
case IResourceDelta.ADDED:
IResource deltaRes = delta.getResource();
- element = createElement(deltaRes, elementType);
- if (element == null) { return false; }
- elementAdded(element, delta);
- return false;
+ element = createElement(deltaRes, elementType, rootInfo);
+ if (element == null) {
+ // resource might be containing shared roots (see bug 19058)
+ this.state.updateRoots(deltaRes.getFullPath(), delta, this);
+ return rootInfo != null && rootInfo.inclusionPatterns != null;
+ }
+ elementAdded(element, delta, rootInfo);
+ return elementType == IRubyElement.SOURCE_FOLDER;
case IResourceDelta.REMOVED:
deltaRes = delta.getResource();
- element = createElement(deltaRes, elementType);
- if (element == null) { return false; }
- elementRemoved(element, delta);
+ element = createElement(deltaRes, elementType, rootInfo);
+ if (element == null) {
+ // resource might be containing shared roots (see bug 19058)
+ this.state.updateRoots(deltaRes.getFullPath(), delta, this);
+ return rootInfo != null && rootInfo.inclusionPatterns != null;
+ }
+ elementRemoved(element, delta, rootInfo);
if (deltaRes.getType() == IResource.PROJECT) {
// reset the corresponding project built state, since cannot
// reuse if added back
if (RubyBuilder.DEBUG)
System.out.println("Clearing last state for removed project : " + deltaRes); //$NON-NLS-1$
+ this.manager.setLastBuiltState((IProject)deltaRes, null /*no state*/);
+
+ // clean up previous session containers (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=89850)
+ this.manager.previousSessionContainers.remove(element);
}
- return false;
+ return elementType == IRubyElement.SOURCE_FOLDER;
case IResourceDelta.CHANGED:
int flags = delta.getFlags();
if ((flags & IResourceDelta.CONTENT) != 0 || (flags & IResourceDelta.ENCODING) != 0) {
// content or encoding has changed
- element = createElement(delta.getResource(), elementType);
+ element = createElement(delta.getResource(), elementType, rootInfo);
if (element == null) return false;
contentChanged(element);
} else if (elementType == IRubyElement.RUBY_PROJECT) {
if ((flags & IResourceDelta.OPEN) != 0) {
// project has been opened or closed
IProject res = (IProject) delta.getResource();
- element = createElement(res, elementType);
+ element = createElement(res, elementType, rootInfo);
if (element == null) { return false; }
if (res.isOpen()) {
if (RubyProject.hasRubyNature(res)) {
addToParentInfo(element);
currentDelta().opened(element);
-
- // refresh pkg fragment roots and caches of the
- // project (and its dependents)
- this.projectCachesToReset.add(element);
+ this.state.updateRoots(element.getPath(), delta, this);
+
+ // refresh src folder roots and caches of the project (and its dependents)
+ this.rootsToRefresh.add(element);
+ this.projectCachesToReset.add(element);
+
+// this.manager.indexManager.indexAll(res);
}
} else {
RubyModel javaModel = this.manager.getRubyModel();
@@ -998,16 +1279,16 @@
boolean isJavaProject = RubyProject.hasRubyNature(res);
if (wasJavaProject != isJavaProject) {
// project's nature has been added or removed
- element = this.createElement(res, elementType);
+ element = this.createElement(res, elementType, rootInfo);
if (element == null) return false; // note its
// resources are
// still visible as
// roots to other
// projects
if (isJavaProject) {
- elementAdded(element, delta);
+ elementAdded(element, delta, rootInfo);
} else {
- elementRemoved(element, delta);
+ elementRemoved(element, delta, rootInfo);
// reset the corresponding project built state,
// since cannot reuse if added back
if (RubyBuilder.DEBUG)
@@ -1041,7 +1322,7 @@
* Creates the openables corresponding to this resource. Returns null if
* none was found.
*/
- private Openable createElement(IResource resource, int elementType) {
+ private Openable createElement(IResource resource, int elementType, RootInfo rootInfo) {
if (resource == null) return null;
IPath path = resource.getFullPath();
@@ -1060,6 +1341,12 @@
if (this.currentElement != null
&& this.currentElement.getElementType() == IRubyElement.RUBY_PROJECT
&& ((IRubyProject) this.currentElement).getProject().equals(resource)) { return this.currentElement; }
+
+ if (rootInfo != null && rootInfo.project.getProject().equals(resource)){
+ element = rootInfo.project;
+ break;
+ }
+
IProject proj = (IProject) resource;
if (RubyProject.hasRubyNature(proj)) {
element = RubyCore.create(proj);
@@ -1071,6 +1358,38 @@
}
}
break;
+ case IRubyElement.SOURCE_FOLDER_ROOT:
+ element = rootInfo == null ? RubyCore.create(resource) : rootInfo.getSourceFolderRoot(resource);
+ break;
+ case IRubyElement.SOURCE_FOLDER:
+ if (rootInfo != null) {
+ if (rootInfo.project.contains(resource)) {
+ SourceFolderRoot root = (SourceFolderRoot) rootInfo.getSourceFolderRoot(null);
+ // create package handle
+ IPath pkgPath = path.removeFirstSegments(rootInfo.rootPath.segmentCount());
+ String[] pkgName = pkgPath.segments();
+ element = root.getSourceFolder(pkgName);
+ }
+ } else {
+ // find the element that encloses the resource
+ this.popUntilPrefixOf(path);
+
+ if (this.currentElement == null) {
+ element = RubyCore.create(resource);
+ } else {
+ // find the root
+ SourceFolderRoot root = this.currentElement.getSourceFolderRoot();
+ if (root == null) {
+ element = RubyCore.create(resource);
+ } else if (((RubyProject)root.getRubyProject()).contains(resource)) {
+ // create package handle
+ IPath pkgPath = path.removeFirstSegments(root.getPath().segmentCount());
+ String[] pkgName = pkgPath.segments();
+ element = root.getSourceFolder(pkgName);
+ }
+ }
+ }
+ break;
case IRubyElement.SCRIPT:
// find the element that encloses the resource
this.popUntilPrefixOf(path);
@@ -1104,12 +1423,12 @@
* <li>If the elemet is not a project, process it as added (see <code>basicElementAdded</code>.
* </ul> Delta argument could be null if processing an external JAR change
*/
- private void elementAdded(Openable element, IResourceDelta delta) {
+ private void elementAdded(Openable element, IResourceDelta delta, RootInfo rootInfo) {
int elementType = element.getElementType();
if (elementType == IRubyElement.RUBY_PROJECT) {
// project add is handled by RubyProject.configure() because
- // when a project is created, it does not yet have a java nature
+ // when a project is created, it does not yet have a ruby nature
if (delta != null && RubyProject.hasRubyNature((IProject) delta.getResource())) {
addToParentInfo(element);
if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
@@ -1119,9 +1438,11 @@
} else {
currentDelta().added(element);
}
-
+ this.state.updateRoots(element.getPath(), delta, this);
+
// refresh pkg fragment roots and caches of the project (and its
// dependents)
+ this.rootsToRefresh.add(element);
this.projectCachesToReset.add(element);
}
} else {
@@ -1179,8 +1500,8 @@
// create the moved from element
Openable movedFromElement = elementType != IRubyElement.RUBY_PROJECT
&& movedFromType == IRubyElement.RUBY_PROJECT ? null : // outside
- // classpath
- this.createElement(movedFromRes, movedFromType);
+ // loadpath
+ this.createElement(movedFromRes, movedFromType, rootInfo);
if (movedFromElement == null) {
// moved from outside classpath
currentDelta().added(element);
@@ -1188,6 +1509,24 @@
currentDelta().movedTo(element, movedFromElement);
}
}
+
+ switch (elementType) {
+ case IRubyElement.SOURCE_FOLDER_ROOT :
+ // when a root is added, and is on the loadpath, the project must be updated
+ RubyProject project = (RubyProject) element.getRubyProject();
+
+ // refresh src folder roots and caches of the project (and its dependents)
+ this.rootsToRefresh.add(project);
+ this.projectCachesToReset.add(project);
+
+ break;
+ case IRubyElement.SOURCE_FOLDER :
+ // reset project's source folder cache
+ project = (RubyProject) element.getRubyProject();
+ this.projectCachesToReset.add(project);
+
+ break;
+ }
}
}
@@ -1209,7 +1548,7 @@
* parent's cache of children <li>Add a REMOVED entry in the delta </ul>
* Delta argument could be null if processing an external JAR change
*/
- private void elementRemoved(Openable element, IResourceDelta delta) {
+ private void elementRemoved(Openable element, IResourceDelta delta, RootInfo rootInfo) {
int elementType = element.getElementType();
if (delta == null || (delta.getFlags() & IResourceDelta.MOVED_TO) == 0) {
@@ -1257,8 +1596,8 @@
// create the moved To element
Openable movedToElement = elementType != IRubyElement.RUBY_PROJECT
&& movedToType == IRubyElement.RUBY_PROJECT ? null : // outside
- // classpath
- this.createElement(movedToRes, movedToType);
+ // loadpath
+ this.createElement(movedToRes, movedToType, rootInfo);
if (movedToElement == null) {
// moved outside classpath
currentDelta().removed(element);
@@ -1268,13 +1607,31 @@
}
switch (elementType) {
- case IRubyElement.RUBY_PROJECT:
+ case IRubyElement.RUBY_MODEL :
+// this.manager.indexManager.reset();
+ break;
+ case IRubyElement.RUBY_PROJECT :
+ this.state.updateRoots(element.getPath(), delta, this);
- // refresh pkg fragment roots and caches of the project (and its
- // dependents)
- this.projectCachesToReset.add(element);
+ // refresh pkg fragment roots and caches of the project (and its dependents)
+ this.rootsToRefresh.add(element);
+ this.projectCachesToReset.add(element);
- break;
+ break;
+ case IRubyElement.SOURCE_FOLDER_ROOT :
+ RubyProject project = (RubyProject) element.getRubyProject();
+
+ // refresh src folder roots and caches of the project (and its dependents)
+ this.rootsToRefresh.add(project);
+ this.projectCachesToReset.add(project);
+
+ break;
+ case IRubyElement.SOURCE_FOLDER :
+ // reset sourc folder cache
+ project = (RubyProject) element.getRubyProject();
+ this.projectCachesToReset.add(project);
+
+ break;
}
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelManager.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelManager.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelManager.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -1548,4 +1548,25 @@
this.containers.remove(project);
}
+ /**
+ * Sets the last built state for the given project, or null to reset it.
+ */
+ public void setLastBuiltState(IProject project, Object state) {
+ if (RubyProject.hasRubyNature(project)) {
+ // should never be requested on non-Ruby projects
+ PerProjectInfo info = getPerProjectInfo(project, true /*create if missing*/);
+ info.triedRead = true; // no point trying to re-read once using setter
+ info.savedState = state;
+ }
+ if (state == null) { // delete state file to ensure a full build happens if the workspace crashes
+ try {
+ File file = getSerializationFile(project);
+ if (file != null && file.exists())
+ file.delete();
+ } catch(SecurityException se) {
+ // could not delete file: cannot do much more
+ }
+ }
+ }
+
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelOperation.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelOperation.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelOperation.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -664,7 +664,7 @@
public void run(IProgressMonitor monitor) throws CoreException {
RubyModelManager manager = RubyModelManager.getRubyModelManager();
DeltaProcessor deltaProcessor = manager.getDeltaProcessor();
- int previousDeltaCount = deltaProcessor.javaModelDeltas.size();
+ int previousDeltaCount = deltaProcessor.rubyModelDeltas.size();
try {
progressMonitor = monitor;
pushOperation(this);
@@ -687,8 +687,8 @@
deltaProcessor = manager.getDeltaProcessor();
// update RubyModel using deltas that were recorded during this operation
- for (int i = previousDeltaCount, size = deltaProcessor.javaModelDeltas.size(); i < size; i++) {
- deltaProcessor.updateRubyModel((IRubyElementDelta)deltaProcessor.javaModelDeltas.get(i));
+ for (int i = previousDeltaCount, size = deltaProcessor.rubyModelDeltas.size(); i < size; i++) {
+ deltaProcessor.updateRubyModel((IRubyElementDelta)deltaProcessor.rubyModelDeltas.get(i));
}
// close the parents of the created elements and reset their project's cache (in case we are in an
@@ -707,7 +707,7 @@
// - the operation did produce some delta(s)
// - but the operation has not modified any resource
if (this.isTopLevelOperation()) {
- if ((deltaProcessor.javaModelDeltas.size() > previousDeltaCount || !deltaProcessor.reconcileDeltas.isEmpty())
+ if ((deltaProcessor.rubyModelDeltas.size() > previousDeltaCount || !deltaProcessor.reconcileDeltas.isEmpty())
&& !this.hasModifiedResource()) {
deltaProcessor.fire(null, DeltaProcessor.DEFAULT_CHANGE_EVENT);
} // else deltas are fired while processing the resource delta
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyProject.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyProject.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyProject.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -2145,5 +2145,34 @@
}
}
}
+ }
+
+ public void updateLoadpathMarkers(Map preferredClasspaths, Map preferredOutputs) {
+ this.flushLoadpathProblemMarkers(false/*cycle*/, true/*format*/);
+ this.flushLoadpathProblemMarkers(false/*cycle*/, false/*format*/);
+
+ ILoadpathEntry[] classpath = this.readLoadpathFile(true/*marker*/, false/*log*/);
+
+ // remember invalid path so as to avoid reupdating it again later on
+ if (preferredClasspaths != null) {
+ preferredClasspaths.put(this, classpath == null ? INVALID_LOADPATH : classpath);
+ }
+ if (preferredOutputs != null) {
+ preferredOutputs.put(this, null);
+ }
+
+ // force classpath marker refresh
+ if (classpath != null) {
+ for (int i = 0; i < classpath.length; i++) {
+ IRubyModelStatus status = LoadpathEntry.validateLoadpathEntry(this, classpath[i], false/*src attach*/, true /*recurse in container*/);
+ if (!status.isOK()) {
+ if (status.getCode() == IRubyModelStatusConstants.INVALID_CLASSPATH && ((LoadpathEntry) classpath[i]).isOptional())
+ continue; // ignore this entry
+ this.createLoadpathProblemMarker(status);
+ }
+ }
+ IRubyModelStatus status = LoadpathEntry.validateLoadpath(this, classpath, null);
+ if (!status.isOK()) this.createLoadpathProblemMarker(status);
+ }
}
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MarkerManager.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MarkerManager.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MarkerManager.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -17,23 +17,15 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.jruby.lexer.yacc.SyntaxException;
-import org.rubypeople.rdt.core.IRubyModelMarker;
+import org.rubypeople.rdt.internal.core.parser.Error;
import org.rubypeople.rdt.internal.core.parser.MarkerUtility;
import org.rubypeople.rdt.internal.core.parser.RdtPosition;
import org.rubypeople.rdt.internal.core.parser.Warning;
-import org.rubypeople.rdt.internal.core.parser.Error;
class MarkerManager implements IMarkerManager {
public void removeProblemsAndTasksFor(IResource resource) {
- try {
- if (resource != null && resource.exists()) {
- resource.deleteMarkers(IRubyModelMarker.RUBY_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
- resource.deleteMarkers(IRubyModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE);
- }
- } catch (CoreException e) {
- // assume there were no problems
- }
+ RubyBuilder.removeProblemsAndTasksFor(resource);
}
public void createSyntaxError(IFile file, SyntaxException e) {
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyBuilder.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyBuilder.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyBuilder.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -13,13 +13,18 @@
import java.io.DataOutputStream;
import java.util.Date;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.rubypeople.rdt.core.IRubyModelMarker;
import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.internal.core.RubyModelManager;
import org.rubypeople.rdt.internal.core.symbols.SymbolIndex;
@@ -71,4 +76,22 @@
public static void writeState(Object savedState, DataOutputStream out) {
// TODO Actually write out build state to the stream!
}
+
+ public static void removeProblemsAndTasksFor(IResource resource) {
+ try {
+ if (resource != null && resource.exists()) {
+ resource.deleteMarkers(IRubyModelMarker.RUBY_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+ resource.deleteMarkers(IRubyModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE);
+
+ // delete managed markers
+// Set markerTypes = RubyModelManager.getRubyModelManager().compilationParticipants.managedMarkerTypes();
+// if (markerTypes.size() == 0) return;
+// Iterator iterator = markerTypes.iterator();
+// while (iterator.hasNext())
+// resource.deleteMarkers((String) iterator.next(), false, IResource.DEPTH_INFINITE);
+ }
+ } catch (CoreException e) {
+ // assume there were no problems
+ }
+ }
}
Modified: trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/core/tests/AbstractRubyModelTest.java
===================================================================
--- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/core/tests/AbstractRubyModelTest.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/core/tests/AbstractRubyModelTest.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -15,6 +15,7 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
@@ -28,7 +29,11 @@
import org.eclipse.core.runtime.jobs.Job;
import org.rubypeople.rdt.core.ILoadpathEntry;
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.RubyCore;
+import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.internal.core.util.CharOperation;
import org.rubypeople.rdt.internal.core.util.Util;
@@ -37,6 +42,23 @@
protected IRubyProject currentProject;
protected String endChar = ",";
+ public AbstractRubyModelTest(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ // TODO Make it so this stuff is only run once per suite, not before every method
+ super.setUp();
+
+ // ensure autobuilding is turned off
+ IWorkspaceDescription description = getWorkspace().getDescription();
+ if (description.isAutoBuilding()) {
+ description.setAutoBuilding(false);
+ getWorkspace().setDescription(description);
+ }
+ }
+
protected IRubyProject setUpRubyProject(final String projectName) throws CoreException, IOException {
this.currentProject = setUpRubyProject(projectName, "1.8.4");
return this.currentProject;
@@ -143,8 +165,8 @@
}
};
getWorkspace().run(populate, null);
- IRubyProject javaProject = RubyCore.create(project);
- return javaProject;
+ IRubyProject rubyProject = RubyCore.create(project);
+ return rubyProject;
}
/**
@@ -527,4 +549,86 @@
description.setNatureIds(new String[] {RubyCore.NATURE_ID});
project.setDescription(description, null);
}
+
+ /**
+ * Returns the specified ruby script in the given project, root, and
+ * source folder or <code>null</code> if it does not exist.
+ */
+ public IRubyScript getRubyScript(String projectName, String rootPath, String packageName, String cuName) throws RubyModelException {
+ ISourceFolder pkg= getSourceFolder(projectName, rootPath, packageName);
+ if (pkg == null) {
+ return null;
+ }
+ return pkg.getRubyScript(cuName);
+ }
+
+ /**
+ * Returns the specified package fragment in the given project and root, or
+ * <code>null</code> if it does not exist.
+ * The rootPath must be specified as a project relative path. The empty
+ * path refers to the default package fragment.
+ */
+ public ISourceFolder getSourceFolder(String projectName, String rootPath, String packageName) throws RubyModelException {
+ ISourceFolderRoot root= getSourceFolderRoot(projectName, rootPath);
+ if (root == null) {
+ return null;
+ }
+ return root.getSourceFolder(packageName);
+ }
+
+ /**
+ * Returns the specified package fragment root in the given project, or
+ * <code>null</code> if it does not exist.
+ * If relative, the rootPath must be specified as a project relative path.
+ * The empty path refers to the package fragment root that is the project
+ * folder iteslf.
+ * If absolute, the rootPath refers to either an external jar, or a resource
+ * internal to the workspace
+ */
+ public ISourceFolderRoot getSourceFolderRoot(
+ String projectName,
+ String rootPath)
+ throws RubyModelException {
+
+ IRubyProject project = getRubyProject(projectName);
+ if (project == null) {
+ return null;
+ }
+ IPath path = new Path(rootPath);
+ if (path.isAbsolute()) {
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IResource resource = workspaceRoot.findMember(path);
+ ISourceFolderRoot root;
+ if (resource == null) {
+ // external jar
+ root = project.getSourceFolderRoot(rootPath);
+ } else {
+ // resource in the workspace
+ root = project.getSourceFolderRoot(resource);
+ }
+ return root;
+ } else {
+ ISourceFolderRoot[] roots = project.getSourceFolderRoots();
+ if (roots == null || roots.length == 0) {
+ return null;
+ }
+ for (int i = 0; i < roots.length; i++) {
+ ISourceFolderRoot root = roots[i];
+ if (!root.isExternal()
+ && root.getUnderlyingResource().getProjectRelativePath().equals(path)) {
+ return root;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the Ruby Project with the given name in this test
+ * suite's model. This is a convenience method.
+ */
+ public IRubyProject getRubyProject(String name) {
+ IProject project = getProject(name);
+ return RubyCore.create(project);
+ }
}
Modified: trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/core/tests/ModifyingResourceTest.java
===================================================================
--- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/core/tests/ModifyingResourceTest.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/core/tests/ModifyingResourceTest.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -8,6 +8,11 @@
import org.eclipse.core.runtime.CoreException;
public class ModifyingResourceTest extends AbstractRubyModelTest {
+
+ public ModifyingResourceTest(String name) {
+ super(name);
+ }
+
protected IFile editFile(String path, String content) throws CoreException {
IFile file = this.getFile(path);
InputStream input = new ByteArrayInputStream(content.getBytes());
Modified: trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/TC_RubyProject.java
===================================================================
--- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/TC_RubyProject.java 2007-01-06 17:59:37 UTC (rev 1755)
+++ trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/TC_RubyProject.java 2007-01-06 21:23:21 UTC (rev 1756)
@@ -1,28 +1,33 @@
package org.rubypeople.rdt.internal.core;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.core.tests.ModifyingResourceTest;
public class TC_RubyProject extends ModifyingResourceTest {
-
-// public void testGetLibraryPathXML() {
-// ShamRubyProject rubyProject = new ShamRubyProject();
-// rubyProject.setProject(new ShamProject("TheWorkingProject"));
-//
-// IProject referencedProject = new ShamProject(new ShamIPath("TheReferencedProject"), "TheReferencedProject");
-// rubyProject.addLoadPathEntry(referencedProject);
-// assertEquals("XML should indicate only one referenced project.", "<?xml version=\"1.0\" encoding=\"UTF-8\"?><loadpath><pathentry type=\"project\" path=\"" + referencedProject.getFullPath() + "\"/></loadpath>", rubyProject.getLoadPathXML());
-//
-// IProject anotherReferencedProject = new ShamProject("AnotherReferencedProject");
-// rubyProject.addLoadPathEntry(anotherReferencedProject);
-// assertEquals("XML should indicate two referenced projects.", "<?xml version=\"1.0\" encoding=\"UTF-8\"?><loadpath><pathentry type=\"project\" path=\"" + referencedProject.getFullPath() + "\"/><pathentry type=\"project\" path=\"" + anotherReferencedProject.getFullPath() + "\"/></loadpath>", rubyProject.getLoadPathXML());
-//
-// rubyProject.removeLoadPathEntry(referencedProject);
-// assertEquals("XML should indicate one referenced project after removing one.", "<?xml version=\"1.0\" encoding=\"UTF-8\"?><loadpath><pathentry type=\"project\" path=\"" + anotherReferencedProject.getFullPath() + "\"/></loadpath>", rubyProject.getLoadPathXML());
-// }
+ public TC_RubyProject(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ // TODO Only run once per suite/class, not every method
+ super.setUp();
+ setUpRubyProject("RubyProjectTests");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+// TODO Only run once per suite/class, not every method
+ deleteProject("RubyProjectTests");
+ super.tearDown();
+ }
+
public void testGetRequiredProjectNames() throws CoreException {
try {
IRubyProject p2 = createRubyProject("P2");
@@ -54,7 +59,7 @@
"/P2/.loadpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<loadpath>\n" +
- " <loadpathentry kind=\"src\" path=\"/P1\"/>\n" +
+ " <pathentry type=\"src\" path=\"/P1\"/>\n" +
"</loadpath>"
);
waitForAutoBuild();
@@ -67,4 +72,16 @@
deleteProjects(new String[] {"P1", "P2"});
}
}
+
+ /**
+ * Test that a ruby script
+ * has a corresponding resource.
+ */
+ public void testRubyScriptCorrespondingResource() throws RubyModelException {
+ IRubyScript element= getRubyScript("RubyProjectTests", "", "q", "A.rb");
+ IResource corr= element.getCorrespondingResource();
+ IResource res= getWorkspace().getRoot().getProject("RubyProjectTests").getFolder("q").getFile("A.rb");
+ assertTrue("incorrect corresponding resource", corr.equals(res));
+ assertEquals("Project is incorrect for the ruby script", "RubyProjectTests", corr.getProject().getName());
+ }
}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|