package com.google.dart.tools.core.internal.analysis.model; import com.google.dart.engine.context.AnalysisContext; import com.google.dart.engine.context.AnalysisDelta; import com.google.dart.engine.context.AnalysisDelta.AnalysisLevel; import com.google.dart.engine.context.AnalysisErrorInfo; import com.google.dart.engine.index.Index; import com.google.dart.engine.source.Source; 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.AnalysisManager; import com.google.dart.tools.core.internal.builder.AnalysisMarkerManager; import com.google.dart.tools.core.internal.builder.DeltaAdapter; import com.google.dart.tools.core.internal.builder.DeltaProcessor; import com.google.dart.tools.core.internal.builder.ResourceDeltaEvent; import com.google.dart.tools.core.internal.builder.SourceDeltaEvent; 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 org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Path; import java.io.File; /** * Instances of {@code ProjectManagerIgnoreListener} listen for changes broadcast by the * {@link DartIgnoreManager} and update the contexts affected by that change. */ public class ProjectManagerIgnoreListener implements DartIgnoreListener { private final ProjectManager projectManager; private final IWorkspaceRoot workspaceRoot; private final AnalysisManager analysisManager; private final AnalysisMarkerManager markerManager; private final Index index; public ProjectManagerIgnoreListener(ProjectManager projectManager, IWorkspaceRoot workspaceRoot, AnalysisManager analysisManager, AnalysisMarkerManager markerManager, Index index) { this.projectManager = projectManager; this.workspaceRoot = workspaceRoot; this.analysisManager = analysisManager; this.markerManager = markerManager; this.index = index; } @Override public void ignoresChanged(DartIgnoreEvent event) { String[] ignoresAdded = event.getAdded(); String[] ignoresRemoved = event.getRemoved(); if (ignoresAdded.length > 0) { processIgnoresAdded(ignoresAdded); } if (ignoresRemoved.length > 0) { processIgnoresRemoved(ignoresRemoved); } } /** * Answer the resource with the given path. * * @param path the absolute path to the resource, not <code>null</code> * @return the resource or <code>null</code> if no match is found */ private IResource getResourceFromPath(String path) { Path location = new Path(path); if (isFilePath(location)) { return workspaceRoot.getFileForLocation(location); } else { return workspaceRoot.getContainerForLocation(location); } } /** * Determine if the given path represents an existing file. If no such file or directory exists, * then return true if the specified path has a file extension. * * @param location the path * @return <code>true</code> if the path is for a file */ private boolean isFilePath(Path location) { File file = location.toFile(); if (file.isFile()) { return true; } if (file.isDirectory()) { return false; } // File does not exist, so guess based upon the extension return location.getFileExtension() != null; } /** * Update all contexts based upon the specified paths to be ignored. * * @param paths an array of zero or more paths to be ignored, not <code>null</code> */ private void processIgnoresAdded(String[] paths) { for (String path : paths) { IResource resource = getResourceFromPath(path); if (resource != null) { // // Visit each source and notify the appropriate context that it should not be analyzed // final Project project = projectManager.getProject(resource.getProject()); if (project != null) { DeltaProcessor processor = new DeltaProcessor(project); DeltaAdapter visitor = new DeltaAdapter() { AnalysisContext context; AnalysisDelta delta; @Override public void packageSourceAdded(SourceDeltaEvent event) { Source source = event.getSource(); if (source != null) { delta.setAnalysisLevel(source, AnalysisLevel.NONE); index.removeSource(context, source); } } @Override public void sourceAdded(SourceDeltaEvent event) { Source source = event.getSource(); if (source != null) { delta.setAnalysisLevel(source, AnalysisLevel.NONE); index.removeSource(context, source); } } @Override public void visitContext(ResourceDeltaEvent event) { if (context != null) { context.applyAnalysisDelta(delta); } if (event != null) { context = event.getContext(); delta = new AnalysisDelta(); } } }; processor.addDeltaListener(visitor); try { processor.traverse(resource); } catch (CoreException e) { DartCore.logError("Failed to ignore " + resource, e); } visitor.visitContext(null); } markerManager.clearMarkers(resource); } } } /** * Update all contexts based upon the specified paths to be analyzed. * * @param paths an array of zero or more paths to be included in analysis, not <code>null</code> */ private void processIgnoresRemoved(String[] paths) { for (String path : paths) { IResource resource = getResourceFromPath(path); if (resource != null && resource.isAccessible()) { // // Visit each source and notify the appropriate context that it should be analyzed // final Project project = projectManager.getProject(resource.getProject()); if (project != null) { DeltaProcessor processor = new DeltaProcessor(project); DeltaAdapter visitor = new DeltaAdapter() { AnalysisContext context; AnalysisDelta delta; @Override public void packageSourceAdded(SourceDeltaEvent event) { Source source = event.getSource(); if (source != null) { delta.setAnalysisLevel(source, AnalysisLevel.RESOLVED); } } @Override public void sourceAdded(SourceDeltaEvent event) { Source source = event.getSource(); if (source != null) { delta.setAnalysisLevel(source, AnalysisLevel.ALL); AnalysisErrorInfo errorInfo = context.getErrors(source); markerManager.queueErrors( projectManager.getResource(source), errorInfo.getLineInfo(), errorInfo.getErrors()); } } @Override public void visitContext(ResourceDeltaEvent event) { if (context != null) { context.applyAnalysisDelta(delta); analysisManager.performAnalysisInBackground(project, context); } if (event != null) { context = event.getContext(); delta = new AnalysisDelta(); } } }; processor.addDeltaListener(visitor); try { processor.traverse(resource); } catch (CoreException e) { DartCore.logError("Failed to analyze " + resource, e); } visitor.visitContext(null); } } } } }