https://github.com/pmd/pmd-scm
Source Code Minimizer
https://github.com/pmd/pmd-scm
Last synced: 6 months ago
JSON representation
Source Code Minimizer
- Host: GitHub
- URL: https://github.com/pmd/pmd-scm
- Owner: pmd
- Created: 2019-12-23T09:38:57.000Z (about 6 years ago)
- Default Branch: main
- Last Pushed: 2025-01-31T17:35:06.000Z (12 months ago)
- Last Synced: 2025-07-09T11:29:11.071Z (6 months ago)
- Language: Java
- Size: 162 KB
- Stars: 2
- Watchers: 7
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Source code minimizer (pmd-scm)
[](https://github.com/pmd/pmd-scm/actions?query=workflow%3Abuild)
This is a tool based on [PMD](https://pmd.github.io). It is intended to minimize one or several source code files, while retaining some invariant (such as a specific compiler error message).
See
* [#2103 [core] Feature request: compiler-crashing test case minimization](https://github.com/pmd/pmd/issues/2103)
* [#2142 [core] Initial implementation of Source Code Minimizer](https://github.com/pmd/pmd/pull/2142)
for thoughts and discussions.
## Building
Just run
./mvnw clean verify
This will generate a binary distribution zip which contains all dependencies. The file is
in `pmd-scm-dist/target/pmd-scm-bin-1.0.0-SNAPSHOT.zip`. Just unzip it.
## Running
Drop all annotations from the source file:
path/to/bin/run.sh scm --language java \
--input-file pmd-scm/src/main/java/net/sourceforge/pmd/scm/SCMConfiguration.java \
--output-file test.java \
--strategy xpath --xpath-expression "//Annotation"
Let's look at more real-life example. Suppose, we have two files:
**TestResource-orig.java:**
```java
class TestResource {
int func() {
System.err.println("Hello World!");
return 123;
}
void unused() {
// unused
}
}
```
**Main-orig.java:**
```java
class Main {
public static void main(String[] args) {
String str = new TestResource().func();
return 123;
}
}
```
If we try compiling it, we get:
$ javac TestResource.java Main.java
Main.java:3: error: incompatible types: int cannot be converted to String
String str = new TestResource().func();
^
Main.java:5: error: incompatible types: unexpected return value
return 123;
^
2 errors
Suppose, we want to minimize these two Java source files simultaneously, while retaining the invariant: the compiler should print
error: incompatible types: int cannot be converted to String
Then, we could run
$ path/to/bin/run.sh scm --language java \
--input-file TestResource-orig.java Main-orig.java \
--output-file TestResource.java Main.java \
--invariant message --printed-message "error: incompatible types: int cannot be converted to String" \
--command-line "javac TestResource.java Main.java" \
--strategy greedy
Original file(s): 290 bytes, 77 nodes.
After initial white-space cleanup: size 258 bytes (88%), 77 nodes (100%)
After pass #1: size 255 bytes (87%), 64 nodes (83%)
After pass #2: size 244 bytes (84%), 57 nodes (74%)
After pass #3: size 205 bytes (70%), 51 nodes (66%)
After pass #4: size 192 bytes (66%), 46 nodes (59%)
After pass #5: size 181 bytes (62%), 39 nodes (50%)
After pass #6: size 179 bytes (61%), 39 nodes (50%)
After final white-space cleanup: size 149 bytes (51%), 39 nodes (50%)
After blank line clean up: size 147 bytes (50%), 39 nodes (50%)
Now, we get the following files:
**TestResource.java:**
```java
class TestResource {
int func() {
}
}
```
**Main.java:**
```java
class Main {
public static void main() {
String str = new TestResource().func();
}
}
```
$ javac TestResource.java Main.java
TestResource.java:3: error: missing return statement
}
^
Main.java:3: error: incompatible types: int cannot be converted to String
String str = new TestResource().func();
^
2 errors