Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache classloader per project #55

Merged
merged 3 commits into from
Aug 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ public Color colorFor(RGB rgb) {
return color;
}

@Deprecated // use IProjectProperties#getAuxclasspath() instead
public static void setJavaClassLoader(PMDConfiguration config, IProject project) {

IPreferences preferences = getDefault().loadPreferences();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,9 @@ protected final void reviewResource(IResource resource) {
}
LOG.debug("discovered language: " + languageVersion);

PMDPlugin.setJavaClassLoader(configuration(), resource.getProject());
if (PMDPlugin.getDefault().loadPreferences().isProjectBuildPathEnabled()) {
configuration().setClassLoader(projectProperties.getAuxClasspath());
}

final File sourceCodeFile = file.getRawLocation().toFile();
if (included && getRuleSet().applies(sourceCodeFile) && isFileInWorkingSet(file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -96,7 +96,7 @@ public class ReviewCodeCmd extends AbstractDefaultCommand {

private static final Logger LOG = Logger.getLogger(ReviewCodeCmd.class);

private final List<ISchedulingRule> resources = new ArrayList<ISchedulingRule>();
private final List<IResource> resources = new ArrayList<IResource>();
private IResourceDelta resourceDelta;
private Map<IFile, Set<MarkerInfo2>> markersByFile = new HashMap<IFile, Set<MarkerInfo2>>();
private boolean taskMarker;
Expand Down Expand Up @@ -138,7 +138,7 @@ public Set<IFile> markedFiles() {

/**
* Easy way to refresh a set of files.
*
*
* @param files
* @throws CommandException
*/
Expand Down Expand Up @@ -254,6 +254,7 @@ public void run(IProgressMonitor monitor) throws CoreException {
// Switch to the PMD perspective if required
if (openPmdPerspective) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
switchToPmdPerspective();
}
Expand All @@ -263,7 +264,7 @@ public void run() {
if (openPmdViolationsOverviewView) {
PMDPlugin.getDefault().showView(PMDPlugin.VIOLATIONS_OVERVIEW_ID);
}

if (openPmdViolationsOutlineView) {
PMDPlugin.getDefault().showView(PMDPlugin.VIOLATIONS_OUTLINE_ID);
}
Expand All @@ -277,12 +278,12 @@ public void run() {

// Log performance information
if (fileCount > 0 && ruleCount > 0) {
logInfo("Review code command terminated. " + ruleCount + " rules were executed against " + fileCount
logInfo("Review code command finished. " + ruleCount + " rules were executed against " + fileCount
+ " files. Actual PMD duration is about " + pmdDuration + "ms, that is about "
+ (float) pmdDuration / fileCount + " ms/file, " + (float) pmdDuration / ruleCount
+ " ms/rule, " + (float) pmdDuration / ((long) fileCount * (long) ruleCount) + " ms/filerule");
} else {
logInfo("Review code command terminated. " + ruleCount + " rules were executed against " + fileCount
logInfo("Review code command finished. " + ruleCount + " rules were executed against " + fileCount
+ " files. PMD was not executed.");
}
}
Expand Down Expand Up @@ -351,19 +352,19 @@ public void setRunAlways(boolean runAlways) {
public void setOpenPmdPerspective(boolean openPmdPerspective) {
this.openPmdPerspective = openPmdPerspective;
}

/**
* Set the open violations view to run after code review.
*
*
* @param openPmdViolationsView should open
*/
public void setOpenPmdViolationsOverviewView(boolean openPmdViolationsView) {
this.openPmdViolationsOverviewView = openPmdViolationsView;
}

/**
* Set the open violations outline view to run after code review.
*
*
* @param openPmdViolationsOutlineView should open
*/
public void setOpenPmdViolationsOutlineView(boolean openPmdViolationsOutlineView) {
Expand Down Expand Up @@ -420,10 +421,13 @@ private ISchedulingRule getSchedulingRule() {
* @throws CommandException
*/
private void processResources() throws CommandException {
final Iterator<ISchedulingRule> i = resources.iterator();
while (i.hasNext()) {
final IResource resource = (IResource) i.next();
Set<String> projects = new HashSet<String>();
for (IResource resource : resources) {
projects.add(resource.getProject().getName());
}
logInfo("ReviewCodeCmd started with " + resources.size() + " selected resources on projects " + projects);

for (IResource resource : resources) {
// if resource is a project, visit only its source folders
if (resource instanceof IProject) {
processProject((IProject) resource);
Expand Down Expand Up @@ -508,7 +512,8 @@ private void processResource(IResource resource) throws CommandException {
private void processProject(IProject project) throws CommandException {
try {
setStepCount(countResourceElement(project));
LOG.debug("Visiting project " + project.getName() + " : " + getStepCount());
logInfo("ReviewCodeCmd: visiting project " + project.getName() + ": " + getStepCount() + " resources found.");
LOG.debug("Visiting project " + project.getName() + " : " + getStepCount() + " resources found.");

if (project.hasNature(JavaCore.NATURE_ID)) {
processJavaProject(project);
Expand Down Expand Up @@ -609,6 +614,7 @@ private void processResourceDelta() throws CommandException {
IResource resource = resourceDelta.getResource();
final IProject project = resource.getProject();
final IProjectProperties properties = getProjectProperties(project);
logInfo("ReviewCodeCmd started on resource delta " + resource.getName() + " in project " + project.getName());

RuleSet ruleSet = rulesetFromResourceDelta(); // properties.getProjectRuleSet();

Expand Down Expand Up @@ -680,7 +686,7 @@ private void applyMarkers() {
} finally {
timer.stop();
int count = markersByFile.size();
logInfo("" + violationCount + " markers applied on " + count + " files in " + timer.getDuration() + "ms.");
LOG.info("" + violationCount + " markers applied on " + count + " files in " + timer.getDuration() + "ms.");
LOG.info("End of processing marker directives. " + violationCount + " violations for " + count + " files.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,13 @@ public interface IProjectProperties {
* @return include patterns
*/
Set<String> getBuildPathIncludePatterns();

/**
* Determines the auxiliary classpath needed for type resolution.
* The classloader is cached and used for all PMD executions for the same project.
* The classloader is not stored to the project properties file.
*
* @return the classpath or <code>null</code> if the project is not a java project
*/
ClassLoader getAuxClasspath();
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.ui.IWorkingSet;

import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.eclipse.plugin.PMDPlugin;
import net.sourceforge.pmd.eclipse.runtime.cmd.JavaProjectClassLoader;
import net.sourceforge.pmd.eclipse.runtime.properties.IProjectProperties;
import net.sourceforge.pmd.eclipse.runtime.properties.IProjectPropertiesManager;
import net.sourceforge.pmd.eclipse.runtime.properties.PropertiesException;
Expand Down Expand Up @@ -89,6 +92,7 @@ public class ProjectPropertiesImpl implements IProjectProperties {
private boolean fullBuildEnabled = true; // default in case didn't come from properties
private Set<String> buildPathExcludePatterns = new HashSet<String>();
private Set<String> buildPathIncludePatterns = new HashSet<String>();
private ClassLoader auxclasspath;

/**
* The default constructor takes a project as an argument
Expand Down Expand Up @@ -452,4 +456,21 @@ public Set<String> getBuildPathExcludePatterns() {
public Set<String> getBuildPathIncludePatterns() {
return buildPathIncludePatterns;
}

@Override
public ClassLoader getAuxClasspath() {
try {
if (project != null && project.hasNature(JavaCore.NATURE_ID)) {
if (auxclasspath == null) {
PMDPlugin.getDefault().logInformation("Creating new auxclasspath class loader for project " + project.getName());
auxclasspath = new JavaProjectClassLoader(PMD.class.getClassLoader(), project);
}
return auxclasspath;
}
} catch (CoreException e) {
LOG.error("Error determining aux classpath", e);
PMDPlugin.getDefault().logError("Error determining aux classpath", e);
}
return null;
}
}