package org.erlide.test_support;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.erlide.engine.model.root.SourcePathProvider;
import org.erlide.util.ErlLogger;
import org.erlide.util.SystemConfiguration;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
public class TestSourcePathProvider
implements SourcePathProvider, IResourceChangeListener {
Map<IProject, Set<IPath>> pathsMap;
public TestSourcePathProvider() {
pathsMap = Maps.newHashMap();
try {
computeSourcePaths();
} catch (final CoreException e) {
ErlLogger.warn(e);
pathsMap = Maps.newHashMap();
}
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
}
@Override
public Collection<IPath> getSourcePathsForModel(final IProject project) {
return getProjectPaths(project);
}
@Override
public Collection<IPath> getSourcePathsForBuild(final IProject project) {
return getProjectPaths(project);
}
@Override
public Collection<IPath> getSourcePathsForExecution(final IProject project) {
return getProjectPaths(project);
}
@Override
public Collection<IPath> getIncludePaths(final IProject project) {
return getProjectPaths(project);
}
private void computeSourcePaths() throws CoreException {
ResourcesPlugin.getWorkspace().getRoot().accept(new IResourceVisitor() {
@Override
public boolean visit(final IResource resource) throws CoreException {
final IProject project = resource.getProject();
if (project != null && isTestDir(resource)) {
final Set<IPath> ps = getProjectPaths(project);
ps.add(resource.getProjectRelativePath());
pathsMap.put(project, ps);
}
return true;
}
});
}
private Set<IPath> getProjectPaths(final IProject project) {
Set<IPath> ps = pathsMap.get(project);
if (ps == null) {
ps = Sets.newHashSet();
}
return ps;
}
@Override
public void resourceChanged(final IResourceChangeEvent event) {
// TODO keep 'paths' updated
final IResourceDelta delta = event.getDelta();
if (delta == null) {
return;
}
try {
final long time = System.currentTimeMillis();
delta.accept(new IResourceDeltaVisitor() {
@Override
public boolean visit(final IResourceDelta theDelta) throws CoreException {
final IResource resource = theDelta.getResource();
if (!(resource instanceof IContainer)) {
return false;
}
final IContainer container = (IContainer) resource;
final IPath location = container.getLocation();
final Set<IPath> paths = getProjectPaths(resource.getProject());
if (theDelta.getKind() == IResourceDelta.ADDED
&& !paths.contains(location) && isTestDir(container)) {
paths.add(location);
}
if (theDelta.getKind() == IResourceDelta.REMOVED
&& paths.contains(location)) {
paths.remove(location);
}
return true;
}
});
if (SystemConfiguration.hasFeatureEnabled("erlide.debug.tspp")) {
ErlLogger.debug("TSPP took " + (System.currentTimeMillis() - time));
}
} catch (final CoreException e) {
ErlLogger.error(e);
}
}
static boolean isTestDir(final IResource resource) {
if (!(resource instanceof IContainer)) {
return false;
}
final String path = resource.getFullPath().toPortableString();
if (path.contains("garbage")) {
return false;
}
if (path.contains("lost+found")) {
return false;
}
try {
for (final IResource res : ((IContainer) resource).members()) {
if (res.getName().contains("_SUITE.erl")) {
return true;
}
}
} catch (final CoreException e) {
}
return false;
}
}