Skip to content

Commit 9d3c40c

Browse files
committed
Merge pull request #152 from adangel:issue-150-regex
Fix eclipse source folder patterns conversion #152
2 parents 70e2933 + b996397 commit 9d3c40c

File tree

5 files changed

+160
-10
lines changed

5 files changed

+160
-10
lines changed

ReleaseNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ This is a minor release.
1515

1616
### Fixed Issues
1717

18+
* [#150](https://github.com/pmd/pmd-eclipse-plugin/issues/150): Error executing command ReviewCode: java.util.regex.PatternSyntaxException: Illegal/unsupported escape sequence near index
19+
1820
### API Changes
1921

2022
### External Contributions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3+
*/
4+
5+
6+
package net.sourceforge.pmd.eclipse.runtime.properties.impl;
7+
8+
import java.util.ArrayList;
9+
import java.util.Collection;
10+
import java.util.List;
11+
import java.util.Set;
12+
import java.util.regex.Pattern;
13+
14+
import org.eclipse.core.resources.IFile;
15+
import org.eclipse.core.resources.IMarker;
16+
import org.eclipse.core.resources.IProject;
17+
import org.eclipse.core.resources.IResource;
18+
import org.eclipse.core.runtime.NullProgressMonitor;
19+
import org.eclipse.core.runtime.Path;
20+
import org.eclipse.jdt.core.IClasspathEntry;
21+
import org.eclipse.jdt.core.IJavaProject;
22+
import org.eclipse.jdt.core.JavaCore;
23+
import org.junit.After;
24+
import org.junit.Assert;
25+
import org.junit.Before;
26+
import org.junit.Test;
27+
28+
import net.sourceforge.pmd.eclipse.EclipseUtils;
29+
import net.sourceforge.pmd.eclipse.plugin.PMDPlugin;
30+
import net.sourceforge.pmd.eclipse.runtime.PMDRuntimeConstants;
31+
import net.sourceforge.pmd.eclipse.runtime.cmd.ReviewCodeCmd;
32+
import net.sourceforge.pmd.eclipse.runtime.properties.IProjectProperties;
33+
import net.sourceforge.pmd.eclipse.ui.actions.internal.InternalRuleSetUtil;
34+
35+
public class ProjectPropertiesImplTest {
36+
private IProject testProject;
37+
38+
@Before
39+
public void setUp() throws Exception {
40+
// 1. Create a Java project
41+
this.testProject = EclipseUtils.createJavaProject("ProjectPropertiesImplTest");
42+
Assert.assertTrue("A test project cannot be created; the tests cannot be performed.",
43+
this.testProject != null && this.testProject.exists() && this.testProject.isAccessible());
44+
}
45+
46+
@After
47+
public void tearDown() throws Exception {
48+
if (this.testProject != null) {
49+
if (this.testProject.exists() && this.testProject.isAccessible()) {
50+
EclipseUtils.removePMDNature(this.testProject);
51+
this.testProject.refreshLocal(IResource.DEPTH_INFINITE, null);
52+
this.testProject.delete(true, true, null);
53+
this.testProject = null;
54+
} else {
55+
System.out.println("WARNING: Test Project has not been deleted!");
56+
}
57+
}
58+
}
59+
60+
@Test
61+
public void projectWithIncludesExcludes() throws Exception {
62+
testProject.getFolder("/src/main").create(true, true, new NullProgressMonitor());
63+
testProject.getFolder("/src/main/java").create(true, true, new NullProgressMonitor());
64+
testProject.getFolder("/src/main/resources").create(true, true, new NullProgressMonitor());
65+
IFile testFile = EclipseUtils.createTestSourceFile(testProject);
66+
testFile.move(testProject.getFile("/src/main/java/Test.java").getFullPath(),
67+
true, new NullProgressMonitor());
68+
testFile = testProject.getFile("/src/main/java/Test.java");
69+
70+
IJavaProject javaProject = JavaCore.create(testProject);
71+
IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
72+
List<IClasspathEntry> newClasspath = new ArrayList<>();
73+
for (IClasspathEntry entry : rawClasspath) {
74+
if (entry.getEntryKind() != IClasspathEntry.CPE_SOURCE) {
75+
newClasspath.add(entry);
76+
}
77+
}
78+
newClasspath.add(JavaCore.newSourceEntry(new Path("/ProjectPropertiesImplTest/src/main/java"),
79+
new Path[] {new Path("**/*.java")},
80+
new Path[0], null));
81+
newClasspath.add(JavaCore.newSourceEntry(new Path("/ProjectPropertiesImplTest/src/main/resources"),
82+
new Path[0],
83+
new Path[] {new Path("**")}, null));
84+
javaProject.setRawClasspath(newClasspath.toArray(new IClasspathEntry[0]), new NullProgressMonitor());
85+
86+
String expectedPattern = testProject.getFolder("/src/main/java").getLocation().toPortableString();
87+
expectedPattern += "/.*/[^/]*\\.java";
88+
89+
IProjectProperties projectProperties = PMDPlugin.getDefault().getPropertiesManager().loadProjectProperties(testProject);
90+
Set<String> includePatterns = projectProperties.getBuildPathIncludePatterns();
91+
Collection<Pattern> patterns = InternalRuleSetUtil.convertStringPatterns(includePatterns);
92+
93+
Assert.assertEquals(1, includePatterns.size());
94+
Assert.assertEquals(1, patterns.size());
95+
Assert.assertEquals(includePatterns.toString(), patterns.toString());
96+
Assert.assertEquals("[" + expectedPattern + "]", patterns.toString());
97+
98+
// now run a review
99+
projectProperties.setPmdEnabled(true);
100+
ReviewCodeCmd cmd = new ReviewCodeCmd();
101+
cmd.addResource(testProject);
102+
cmd.performExecute();
103+
cmd.join();
104+
105+
IMarker[] markers = testFile.findMarkers(PMDRuntimeConstants.PMD_MARKER, true, 1);
106+
Assert.assertTrue(markers.length > 0);
107+
boolean found = false;
108+
for (IMarker marker : markers) {
109+
if ("EmptyCatchBlock".equals(marker.getAttribute(PMDRuntimeConstants.KEY_MARKERATT_RULENAME))) {
110+
found = true;
111+
}
112+
}
113+
Assert.assertTrue("EmptyCatchBlock marker is missing", found);
114+
}
115+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3+
*/
4+
5+
6+
package net.sourceforge.pmd.eclipse.ui.actions.internal;
7+
8+
import java.util.Collection;
9+
import java.util.HashSet;
10+
import java.util.Set;
11+
import java.util.regex.Pattern;
12+
13+
import org.junit.Assert;
14+
import org.junit.Test;
15+
16+
public class InternalRuleSetUtilTest {
17+
18+
@Test
19+
public void convertStringPatterns() {
20+
Set<String> stringPatterns = new HashSet<>();
21+
stringPatterns.add(".*src/main/java.*");
22+
23+
Collection<Pattern> patterns = InternalRuleSetUtil.convertStringPatterns(stringPatterns);
24+
Assert.assertEquals(1, patterns.size());
25+
Assert.assertEquals(stringPatterns.toString(), patterns.toString());
26+
}
27+
}

net.sourceforge.pmd.eclipse.plugin/META-INF/MANIFEST.MF

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ Export-Package: ch.qos.logback.classic;x-friends:="net.sourceforge.pmd.eclipse.p
125125
org.eclipse.jface.viewers,
126126
net.sourceforge.pmd,
127127
org.eclipse.core.commands",
128+
net.sourceforge.pmd.eclipse.ui.actions.internal;x-friends:="net.sourceforge.pmd.eclipse.plugin.test",
128129
net.sourceforge.pmd.eclipse.ui.model;uses:="org.eclipse.jdt.core,org.eclipse.core.resources,net.sourceforge.pmd.lang.ast",
129130
net.sourceforge.pmd.eclipse.ui.preferences.br;
130131
uses:="net.sourceforge.pmd.eclipse.ui.preferences,

net.sourceforge.pmd.eclipse.plugin/src/main/java/net/sourceforge/pmd/eclipse/runtime/properties/impl/ProjectPropertiesImpl.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,27 +90,21 @@ private void determineBuildPathIncludesExcludes() {
9090
IClasspathEntry source = PMDPlugin.buildSourceClassPathEntryFor(project);
9191
if (source != null) {
9292
try {
93-
String basePath = new File(project.getWorkspace().getRoot().getLocation().toOSString()
94-
+ java.io.File.separator + source.getPath().toOSString()).getCanonicalPath();
93+
String basePath = new File(project.getWorkspace().getRoot()
94+
.getFolder(source.getPath()).getLocation().toOSString()).getCanonicalPath();
9595
if (!basePath.endsWith(File.separator)) {
9696
basePath += File.separator;
9797
}
9898
if (source.getExclusionPatterns() != null) {
9999
for (IPath path : source.getExclusionPatterns()) {
100100
String pathString = path.toOSString();
101-
if (!pathString.endsWith(File.separator)) {
102-
pathString += File.separator;
103-
}
104-
buildPathExcludePatterns.add(basePath + pathString + ".*");
101+
buildPathExcludePatterns.add(basePath + convertPatternToRegex(pathString));
105102
}
106103
}
107104
if (source.getInclusionPatterns() != null) {
108105
for (IPath path : source.getInclusionPatterns()) {
109106
String pathString = path.toOSString();
110-
if (!pathString.endsWith(File.separator)) {
111-
pathString += File.separator;
112-
}
113-
buildPathIncludePatterns.add(basePath + pathString + ".*");
107+
buildPathIncludePatterns.add(basePath + convertPatternToRegex(pathString));
114108
}
115109
}
116110
} catch (IOException e) {
@@ -119,6 +113,17 @@ private void determineBuildPathIncludesExcludes() {
119113
}
120114
}
121115

116+
/**
117+
* Simple conversion from the Ant-like pattern to regex pattern.
118+
*/
119+
private String convertPatternToRegex(String pattern) {
120+
String regex = pattern.replaceAll("\\.", "\\\\."); // replace "." with "\\."
121+
regex = regex.replaceAll("\\*\\*", ".*"); // replace "**" with ".*"
122+
regex = regex.replaceAll("/\\*", "/[^/]*"); // replace "/*" with "/[^/]"
123+
regex = regex.replaceAll("\\?", "."); // replace "?" with "."
124+
return regex;
125+
}
126+
122127
/**
123128
* @see net.sourceforge.pmd.eclipse.runtime.properties.IProjectProperties#getProject()
124129
*/

0 commit comments

Comments
 (0)