package com.google.dart.tools.core.internal.analysis.model;
import com.google.dart.engine.context.AnalysisContext;
import com.google.dart.tools.core.DartCore;
import com.google.dart.tools.core.analysis.model.Project;
import com.google.dart.tools.core.analysis.model.ProjectManager;
import com.google.dart.tools.core.internal.builder.AnalysisWorker;
import com.google.dart.tools.core.internal.builder.DeltaProcessor;
import com.google.dart.tools.core.internal.builder.IgnoreResourceFilter;
import com.google.dart.tools.core.internal.builder.IndexUpdater;
import com.google.dart.tools.core.internal.builder.ProjectUpdater;
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.runtime.CoreException;
/**
* The {@code WorkspaceDeltaProcessor} receives resource changes from Eclipse and updates the
* associated {@link ProjectManager} based on those changes. In addition, it traverses changes in
* the "packages" directory hierarchy because the builder does not receive resources changes for
* symlinked folders (e.g. packages).
*
* @coverage dart.tools.core.model
*/
public class WorkspaceDeltaProcessor implements IResourceChangeListener {
/**
* The associated project manager updated by the receiver (not {@code null})
*/
private final ProjectManager manager;
public WorkspaceDeltaProcessor(ProjectManager manager) {
this.manager = manager;
}
@Override
public void resourceChanged(IResourceChangeEvent event) {
IResourceDelta delta = event.getDelta();
if (delta != null) {
try {
delta.accept(new IResourceDeltaVisitor() {
@Override
public boolean visit(IResourceDelta delta) throws CoreException {
IResource res = delta.getResource();
if (res == null) {
return false;
} else if (res.getType() == IResource.ROOT) {
return true;
} else if (res.getType() == IResource.PROJECT) {
if (delta.getKind() == IResourceDelta.REMOVED) {
manager.projectRemoved((IProject) res);
return false;
}
return true;
} else if (res.getType() == IResource.FOLDER) {
if (res.getName().equals(DartCore.PACKAGES_DIRECTORY_NAME)) {
// The builder is not notified about changes in symlinked folders (e.g. packages)
// thus we traverse those changes here using the same mechanism as the builder
Project project = manager.getProject(res.getProject());
ProjectUpdater updater = new ProjectUpdater();
IndexUpdater indexUpdater = new IndexUpdater(manager.getIndex());
DeltaProcessor processor = new DeltaProcessor(project);
IgnoreResourceFilter filter = new IgnoreResourceFilter();
filter.addDeltaListener(updater);
filter.addDeltaListener(indexUpdater);
processor.addDeltaListener(filter);
processor.traverse(delta);
updater.applyChanges();
AnalysisContext context = manager.getContext(res);
startBackgroundAnalysis(project, context);
return false;
}
return true;
} else {
return false;
}
}
});
} catch (CoreException e) {
DartCore.logError(e);
}
}
}
/**
* Kick off a background analysis worker for the given context.
*
* @param project the project (not {@code null}) containing the context
* @param context the context to be analyzed (not {@code null})
*/
protected void startBackgroundAnalysis(Project project, AnalysisContext context) {
new AnalysisWorker(project, context).performAnalysisInBackground();
}
}