| package com.google.dart.tools.core.internal.analysis.model; |
| |
| import com.google.common.collect.Lists; |
| import com.google.dart.server.generated.AnalysisServer; |
| import com.google.dart.tools.core.DartCore; |
| import com.google.dart.tools.core.internal.model.DartIgnoreManager; |
| import com.google.dart.tools.core.model.DartIgnoreEvent; |
| import com.google.dart.tools.core.model.DartIgnoreListener; |
| import com.google.dart.tools.core.pub.IPackageRootProvider; |
| |
| 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.IWorkspaceRoot; |
| import org.eclipse.core.runtime.Path; |
| |
| import java.io.File; |
| import java.util.HashMap; |
| import java.util.List; |
| |
| /** |
| * There is a single instance of {@code DartProjectManager} which updates {@link AnalysisServer}'s |
| * analysis roots as projects are created, opened, closed, and deleted, and as resources are marked |
| * as analyze or don't analyze. |
| */ |
| public class DartProjectManager { |
| |
| private final IWorkspaceRoot root; |
| private final AnalysisServer server; |
| private final DartIgnoreManager ignoreManager; |
| |
| /** |
| * Calls {@link #setAnalysisRoots()} when a project is added or removed. |
| */ |
| IResourceChangeListener resourceChangeListener = new IResourceChangeListener() { |
| @Override |
| public void resourceChanged(IResourceChangeEvent event) { |
| if (shouldSetAnalysisRoots(event)) { |
| setAnalysisRoots(); |
| } |
| } |
| |
| private boolean shouldSetAnalysisRoots(IResourceChangeEvent event) { |
| if (event.getType() == IResourceChangeEvent.POST_CHANGE) { |
| IResourceDelta delta = event.getDelta(); |
| // Toplevel project added or removed. |
| if (delta.getAffectedChildren(IResourceDelta.REMOVED).length > 0) { |
| return true; |
| } |
| if (delta.getAffectedChildren(IResourceDelta.ADDED).length > 0) { |
| IResource resource = delta.getAffectedChildren(IResourceDelta.ADDED)[0].getResource(); |
| if (resource instanceof IProject && hasPubspecAndLoc((IProject) resource)) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| for (IResourceDelta child : delta.getAffectedChildren(IResourceDelta.CHANGED)) { |
| if (child.findMember(new Path(".settings/com.google.dart.tools.core.prefs")) != null) { |
| // Toplevel project had its package root changed. |
| // TODO(paulberry): is there a better way to detect this, perhaps with |
| // IPreferenceChangeListener? |
| return true; |
| } |
| if (child.findMember(new Path(DartCore.PUBSPEC_LOCK_FILE_NAME)) != null) { |
| return true; |
| } |
| |
| IResource resource = child.getResource(); |
| // for project open and close |
| if (resource instanceof IProject && ((child.getFlags() & IResourceDelta.OPEN) != 0)) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| }; |
| |
| /** |
| * Calls {@link #setAnalysisRoots()} when the set of ignored resources has changed. |
| */ |
| DartIgnoreListener ignoreManagerListener = new DartIgnoreListener() { |
| @Override |
| public void ignoresChanged(DartIgnoreEvent event) { |
| setAnalysisRoots(); |
| } |
| }; |
| |
| public DartProjectManager(IWorkspaceRoot root, AnalysisServer server, |
| DartIgnoreManager ignoreManager) { |
| this.root = root; |
| this.server = server; |
| this.ignoreManager = ignoreManager; |
| } |
| |
| /** |
| * Set the collection of resources that should be analyzed. |
| */ |
| public void setAnalysisRoots() { |
| List<String> includedPaths = Lists.newArrayList(); |
| List<String> excludedPaths = Lists.newArrayList(); |
| HashMap<String, String> packageRoots = new HashMap<String, String>(); |
| for (IProject proj : DartCore.getDartProjects()) { |
| String projPath = proj.getLocation().toOSString(); |
| includedPaths.add(projPath); |
| File packageRoot = IPackageRootProvider.DEFAULT.getPackageRoot(proj); |
| if (packageRoot != null) { |
| packageRoots.put(projPath, packageRoot.getPath()); |
| } |
| } |
| for (String path : ignoreManager.getExclusionPatterns()) { |
| excludedPaths.add(path.replace('/', File.separatorChar)); |
| } |
| server.analysis_setAnalysisRoots(includedPaths, excludedPaths, packageRoots); |
| } |
| |
| /** |
| * Set the {@link AnalysisServer}'s analysis roots and hook resources and ignore manager to keep |
| * the analysis roots updated as things change. |
| */ |
| public void start() { |
| setAnalysisRoots(); |
| root.getWorkspace().addResourceChangeListener(resourceChangeListener); |
| ignoreManager.addListener(ignoreManagerListener); |
| } |
| |
| /** |
| * Check that if pubspec is present, there is also a lock file, indicating pub get has run, and |
| * project is ready for analysis. |
| */ |
| private boolean hasPubspecAndLoc(IProject proj) { |
| if (proj.findMember(DartCore.PUBSPEC_FILE_NAME) == null |
| || !DartCore.getPlugin().isAutoRunPubEnabled()) { |
| return true; |
| } |
| |
| if (proj.findMember(DartCore.PUBSPEC_FILE_NAME) != null |
| && proj.findMember(DartCore.PUBSPEC_LOCK_FILE_NAME) != null) { |
| return true; |
| } |
| return false; |
| } |
| } |