Skip to content

Commit 24b7f87

Browse files
committed
Replace regex based class parsing with JavaParser
1 parent 302be73 commit 24b7f87

File tree

5 files changed

+75
-42
lines changed

5 files changed

+75
-42
lines changed

build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ repositories {
2525

2626
dependencies {
2727
compileOnly(libs.jetbrains.annotations)
28-
implementation(libs.jcommander)
2928
implementation(libs.jackson.dataformat.xml)
29+
implementation(libs.java.parser)
30+
implementation(libs.jcommander)
3031
implementation(libs.logback.classic)
3132
}
3233

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
assertj = "3.27.3"
33
equalsVerifier = "3.18.1"
44
jackson = "2.18.2"
5+
java-parser = "3.26.3"
56
jcommander = "1.82"
67
jetbrains-annotations = "26.0.2"
78
junit = "5.11.4"
@@ -12,6 +13,7 @@ systemStubs = "2.1.7"
1213
assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" }
1314
equalsVerifier = { module = "nl.jqno.equalsverifier:equalsverifier", version.ref = "equalsVerifier" }
1415
jackson-dataformat-xml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-xml", version.ref = "jackson" }
16+
java-parser = { module = "com.github.javaparser:javaparser-core", version.ref = "java-parser" }
1517
jcommander = { module = "com.beust:jcommander", version.ref = "jcommander" }
1618
jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrains-annotations" }
1719
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }

src/main/java/de/donnerbart/split/TestSplit.java

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package de.donnerbart.split;
22

33
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
4+
import com.github.javaparser.JavaParser;
5+
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
46
import org.jetbrains.annotations.NotNull;
57
import org.jetbrains.annotations.Nullable;
68
import org.slf4j.Logger;
@@ -18,17 +20,13 @@
1820
import java.util.HashSet;
1921
import java.util.Set;
2022
import java.util.function.Consumer;
21-
import java.util.regex.Pattern;
2223
import java.util.stream.Collectors;
2324

2425
import static de.donnerbart.split.Util.formatIndex;
2526
import static de.donnerbart.split.Util.formatTime;
2627

2728
public class TestSplit {
2829

29-
private static final @NotNull Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([\\S.]+?)\\s*;");
30-
private static final @NotNull Pattern CLASS_NAME_PATTERN = Pattern.compile("class\\s+(\\S+?)\\s+");
31-
3230
private static final @NotNull Logger LOG = LoggerFactory.getLogger(TestSplit.class);
3331

3432
private final int splitIndex;
@@ -181,26 +179,21 @@ public void run() throws Exception {
181179

182180
private static @NotNull Set<String> fileToClassName(
183181
final @NotNull Set<Path> testPaths,
184-
final @NotNull Consumer<Integer> exitCodeConsumer)
185-
throws Exception {
182+
final @NotNull Consumer<Integer> exitCodeConsumer) {
183+
final var javaParser = new JavaParser();
186184
final var classNames = new HashSet<String>();
187185
for (final var testPath : testPaths) {
188-
final var testClassContent = Files.readString(testPath);
189-
final var packagematcher = PACKAGE_PATTERN.matcher(testClassContent);
190-
if (!packagematcher.find()) {
191-
LOG.error("Found no package in file '{}'", testPath);
192-
exitCodeConsumer.accept(1);
193-
continue;
194-
}
195-
final var packageName = packagematcher.group(1);
196-
final var classNameMatcher = CLASS_NAME_PATTERN.matcher(testClassContent);
197-
if (!classNameMatcher.find()) {
198-
LOG.error("Found no class name in file '{}'", testPath);
186+
try {
187+
final var compilationUnit = javaParser.parse(testPath).getResult().orElseThrow();
188+
final var className = compilationUnit.findFirst(ClassOrInterfaceDeclaration.class)
189+
.map(ClassOrInterfaceDeclaration::getFullyQualifiedName)
190+
.orElseThrow()
191+
.orElseThrow();
192+
classNames.add(className);
193+
} catch (final Exception e) {
194+
LOG.error("Failed to parse test class: {}", testPath, e);
199195
exitCodeConsumer.accept(1);
200-
continue;
201196
}
202-
final var className = classNameMatcher.group(1);
203-
classNames.add(packageName + "." + className);
204197
}
205198
return classNames;
206199
}

src/test/java/de/donnerbart/split/TestSplitTest.java

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -213,21 +213,51 @@ void run_withJUnit_withFourSplits() throws Exception {
213213
}
214214

215215
@Test
216-
void run_noTests() throws Exception {
217-
final var projectFolder = tmp.resolve("no-tests-project").resolve("src").resolve("main").resolve("java");
216+
void run_whitespaceClassDefinition() throws Exception {
217+
final var projectFolder =
218+
tmp.resolve("multiline-class-definition-project").resolve("src").resolve("main").resolve("java");
219+
copyResourceToTarget(projectFolder,
220+
"tests/WhitespaceClassDefinitionTest.java",
221+
"WhitespaceClassDefinitionTest.java",
222+
PERMISSIONS);
218223

219224
final var testSplit = new TestSplit(0,
220225
1,
221-
"**/no-tests-project/**/*Test.java",
226+
"**/multiline-class-definition-project/**/*Test.java",
222227
null,
223228
null,
224229
projectFolder,
225230
true,
226231
exitCode::set);
227232
testSplit.run();
228233

229-
assertThat(systemOut.getLinesNormalized()).isEmpty();
230-
assertThat(exitCode).hasValue(1);
234+
assertThat(systemOut.getLines()).singleElement()
235+
.isEqualTo("de.donnerbart.example.WhitespaceClassDefinitionTest");
236+
assertThat(exitCode).hasNullValue();
237+
}
238+
239+
@Test
240+
void run_thirdPartyLibrary() throws Exception {
241+
final var projectFolder =
242+
tmp.resolve("third-party-library-project").resolve("src").resolve("main").resolve("java");
243+
copyResourceToTarget(projectFolder,
244+
"tests/ThirdPartyLibraryTest.java",
245+
"ThirdPartyLibraryTest.java",
246+
PERMISSIONS);
247+
248+
final var testSplit = new TestSplit(0,
249+
1,
250+
"**/third-party-library-project/**/*Test.java",
251+
null,
252+
null,
253+
projectFolder,
254+
true,
255+
exitCode::set);
256+
testSplit.run();
257+
258+
assertThat(systemOut.getLines()).singleElement()
259+
.isEqualTo("de.donnerbart.example.ThirdPartyLibraryTest");
260+
assertThat(exitCode).hasNullValue();
231261
}
232262

233263
@Test
@@ -245,18 +275,17 @@ void run_noPackage() throws Exception {
245275
exitCode::set);
246276
testSplit.run();
247277

248-
assertThat(systemOut.getLinesNormalized()).isEmpty();
249-
assertThat(exitCode).hasValue(1);
278+
assertThat(systemOut.getLines()).singleElement().isEqualTo("NoPackageTest");
279+
assertThat(exitCode).hasNullValue();
250280
}
251281

252282
@Test
253-
void run_noClassName() throws Exception {
254-
final var projectFolder = tmp.resolve("no-classname-project").resolve("src").resolve("main").resolve("java");
255-
copyResourceToTarget(projectFolder, "tests/NoClassNameTest.java", "NoClassNameTest.java", PERMISSIONS);
283+
void run_noTests() throws Exception {
284+
final var projectFolder = tmp.resolve("no-tests-project").resolve("src").resolve("main").resolve("java");
256285

257286
final var testSplit = new TestSplit(0,
258287
1,
259-
"**/no-classname-project/**/*Test.java",
288+
"**/no-tests-project/**/*Test.java",
260289
null,
261290
null,
262291
projectFolder,
@@ -269,25 +298,21 @@ void run_noClassName() throws Exception {
269298
}
270299

271300
@Test
272-
void run_whitespaceClassDefinition() throws Exception {
273-
final var projectFolder =
274-
tmp.resolve("multiline-class-definition-project").resolve("src").resolve("main").resolve("java");
275-
copyResourceToTarget(projectFolder, "tests/WhitespaceClassDefinitionTest.java",
276-
"WhitespaceClassDefinitionTest.java",
277-
PERMISSIONS);
301+
void run_noClassName() throws Exception {
302+
final var projectFolder = tmp.resolve("no-classname-project").resolve("src").resolve("main").resolve("java");
303+
copyResourceToTarget(projectFolder, "tests/NoClassNameTest.java", "NoClassNameTest.java", PERMISSIONS);
278304

279305
final var testSplit = new TestSplit(0,
280306
1,
281-
"**/multiline-class-definition-project/**/*Test.java",
307+
"**/no-classname-project/**/*Test.java",
282308
null,
283309
null,
284310
projectFolder,
285311
true,
286312
exitCode::set);
287313
testSplit.run();
288314

289-
assertThat(systemOut.getLines()).singleElement()
290-
.isEqualTo("de.donnerbart.example.WhitespaceClassDefinitionTest");
291-
assertThat(exitCode).hasNullValue();
315+
assertThat(systemOut.getLinesNormalized()).isEmpty();
316+
assertThat(exitCode).hasValue(1);
292317
}
293318
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package de.donnerbart.example;
2+
3+
import com.example.test.Util;
4+
import org.junit.jupiter.api.Test;
5+
6+
class ThirdPartyLibraryTest {
7+
8+
@Test
9+
void testThirdPartyLibraryMethod() {
10+
Util.test();
11+
}
12+
}

0 commit comments

Comments
 (0)