// ===================================================================== // // Copyright (C) 2012 - 2016, Philip Graf // // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // which accompanies this distribution, and is available at // http://www.eclipse.org/legal/epl-v10.html // // ===================================================================== package ch.acanda.eclipse.pmd.builder; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.SubMonitor; import ch.acanda.eclipse.pmd.PMDPlugin; import ch.acanda.eclipse.pmd.cache.RuleSetsCache; import ch.acanda.eclipse.pmd.cache.RuleSetsCacheLoader; import net.sourceforge.pmd.RuleSets; /** * Builder for PMD enabled projects. * * @author Philip Graf */ public class PMDBuilder extends IncrementalProjectBuilder { public static final String ID = "ch.acanda.eclipse.pmd.builder.PMDBuilder"; private static final RuleSetsCache CACHE = new RuleSetsCache(new RuleSetsCacheLoader(), PMDPlugin.getDefault().getWorkspaceModel()); @Override @SuppressWarnings("PMD.ReturnEmptyArrayRatherThanNull") protected IProject[] build(final int kind, @SuppressWarnings("rawtypes") final Map args, final IProgressMonitor monitor) throws CoreException { final IProgressMonitor subMonitor = SubMonitor.convert(monitor); if (kind == FULL_BUILD) { fullBuild(subMonitor); } else { final IResourceDelta delta = getDelta(getProject()); if (delta == null) { fullBuild(subMonitor); } else { incrementalBuild(delta, subMonitor); } } return null; } protected void fullBuild(final IProgressMonitor monitor) { try { getProject().accept(new ResourceVisitor(monitor)); } catch (final CoreException e) { PMDPlugin.getDefault().error("Could not run a full PMD build", e); } } protected void incrementalBuild(final IResourceDelta delta, final IProgressMonitor monitor) throws CoreException { delta.accept(new DeltaVisitor(monitor)); } void analyze(final IResource resource, final boolean includeMembers, final IProgressMonitor monitor) throws CoreException { if (resource instanceof IFile) { monitor.setTaskName("PMD analyzing file: " + ((IFile) resource).getName()); final RuleSets ruleSets = CACHE.getRuleSets(resource.getProject().getName()); new Analyzer().analyze((IFile) resource, ruleSets, new ViolationProcessor()); } else if (resource instanceof IFolder && includeMembers) { final IFolder folder = (IFolder) resource; for (final IResource member : folder.members()) { analyze(member, includeMembers, monitor); } } } class DeltaVisitor implements IResourceDeltaVisitor { private final IProgressMonitor monitor; public DeltaVisitor(final IProgressMonitor monitor) { this.monitor = monitor; } @Override public boolean visit(final IResourceDelta delta) throws CoreException { final IResource resource = delta.getResource(); switch (delta.getKind()) { case IResourceDelta.ADDED: case IResourceDelta.CHANGED: analyze(resource, (delta.getFlags() & IResourceDelta.DERIVED_CHANGED) != 0, monitor); break; default: break; } if (monitor.isCanceled()) { throw new OperationCanceledException(); } return true; } } class ResourceVisitor implements IResourceVisitor { private final IProgressMonitor monitor; public ResourceVisitor(final IProgressMonitor monitor) { this.monitor = monitor; } @Override public boolean visit(final IResource resource) throws CoreException { analyze(resource, false, monitor); if (monitor.isCanceled()) { throw new OperationCanceledException(); } return true; } } }