Skip to content

Commit

Permalink
Cache and reuse project's aux classpath classloader
Browse files Browse the repository at this point in the history
Cherry-Picked. See also #55
  • Loading branch information
adangel committed Aug 1, 2018
1 parent 396b94a commit 5b17c4c
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 16 deletions.
2 changes: 2 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Eclipse Update Site:

### Fixed Issues

* [#52](https://github.com/pmd/pmd-eclipse-plugin/issues/52): Eclipse Internal Error - Out of Memory

### External Contributions


Expand Down
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;
}
}

0 comments on commit 5b17c4c

Please sign in to comment.