bug: Sniper printer does not handle statements that declare multiple variables correctly
- Dominant language
- Java
- Stars
- 2k
- Forks
- 392
- Avg merge
- 11h 24m
- Merged PRs (30d)
- 36
Description
We found that the sniper printer sometimes throws an `IllegalStateException` when running an experiment (see spoonlabs/sorald#337). I've managed to find a minimal example that reproduces the issue:
```java
public class CausesIllegalStateExceptionForSniper {
protected class Internal {
public int a;
public int b, c;
public int d;
}
long a;
}
```
If you remove the field from the enclosing type (`long a`), and then try to sniper print, there's an `IllegalStateException` like so. Note that removing `long a` really has nothing to do with the exception, it's just so that the outer type definition becomes modified, thus forcing the sniper to print it's type members one-by-one instead of just taking the original source code of all of it. Here's the stacktrace:
```
Caused by: java.lang.IllegalStateException
at spoon.support.sniper.internal.ModificationStatus.toBoolean(ModificationStatus.java:30)
at spoon.support.sniper.SniperJavaPrettyPrinter$2.printSourceFragment(SniperJavaPrettyPrinter.java:287)
at spoon.support.sniper.internal.AbstractSourceFragmentPrinter.print(AbstractSourceFragmentPrinter.java:64)
at spoon.support.sniper.internal.SourceFragmentContextNormal.print(SourceFragmentContextNormal.java:38)
at spoon.support.sniper.SniperJavaPrettyPrinter.executePrintEventInContext(SniperJavaPrettyPrinter.java:334)
at spoon.support.sniper.SniperJavaPrettyPrinter.scan(SniperJavaPrettyPrinter.java:269)
at spoon.support.sniper.SniperJavaPrettyPrinter.scan(SniperJavaPrettyPrinter.java:57)
at spoon.reflect.visitor.ElementPrinterHelper.writeElementList(ElementPrinterHelper.java:184)
at spoon.reflect.visitor.DefaultJavaPrettyPrinter.visitCtClass(DefaultJavaPrettyPrinter.java:633)
at spoon.support.reflect.declaration.CtClassImpl.accept(CtClassImpl.java:58)
at spoon.reflect.visitor.DefaultJavaPrettyPrinter.scan(DefaultJavaPrettyPrinter.java:381)
at spoon.support.sniper.SniperJavaPrettyPrinter.lambda$superScanInContext$6(SniperJavaPrettyPrinter.java:384)
at spoon.support.sniper.SniperJavaPrettyPrinter.runInContext(SniperJavaPrettyPrinter.java:395)
at spoon.support.sniper.SniperJavaPrettyPrinter.superScanInContext(SniperJavaPrettyPrinter.java:384)
at spoon.support.sniper.SniperJavaPrettyPrinter.access$300(SniperJavaPrettyPrinter.java:58)
at spoon.support.sniper.SniperJavaPrettyPrinter$2.printSourceFragment(SniperJavaPrettyPrinter.java:309)
at spoon.support.sniper.internal.AbstractSourceFragmentPrinter.print(AbstractSourceFragmentPrinter.java:64)
at spoon.support.sniper.internal.SourceFragmentContextList.print(SourceFragmentContextList.java:19)
at spoon.support.sniper.SniperJavaPrettyPrinter$2.printSourceFragment(SniperJavaPrettyPrinter.java:298)
at spoon.support.sniper.internal.AbstractSourceFragmentPrinter.print(AbstractSourceFragmentPrinter.java:64)
at spoon.support.sniper.internal.SourceFragmentContextNormal.print(SourceFragmentContextNormal.java:38)
at spoon.support.sniper.SniperJavaPrettyPrinter.executePrintEventInContext(SniperJavaPrettyPrinter.java:334)
at spoon.support.sniper.SniperJavaPrettyPrinter.scan(SniperJavaPrettyPrinter.java:269)
at spoon.support.sniper.SniperJavaPrettyPrinter.scan(SniperJavaPrettyPrinter.java:57)
at spoon.reflect.visitor.ElementPrinterHelper.writeElementList(ElementPrinterHelper.java:184)
at spoon.reflect.visitor.DefaultJavaPrettyPrinter.visitCtClass(DefaultJavaPrettyPrinter.java:633)
at spoon.support.reflect.declaration.CtClassImpl.accept(CtClassImpl.java:58)
at spoon.reflect.visitor.DefaultJavaPrettyPrinter.scan(DefaultJavaPrettyPrinter.java:381)
at spoon.support.sniper.SniperJavaPrettyPrinter.lambda$superScanInContext$6(SniperJavaPrettyPrinter.java:384)
at spoon.support.sniper.SniperJavaPrettyPrinter.runInContext(SniperJavaPrettyPrinter.java:395)
at spoon.support.sniper.SniperJavaPrettyPrinter.superScanInContext(SniperJavaPrettyPrinter.java:384)
at spoon.support.sniper.SniperJavaPrettyPrinter.access$300(SniperJavaPrettyPrinter.java:58)
at spoon.support.sniper.SniperJavaPrettyPrinter$2.printSourceFragment(SniperJavaPrettyPrinter.java:309)
at spoon.support.sniper.internal.AbstractSourceFragmentPrinter.print(AbstractSourceFragmentPrinter.java:64)
at spoon.support.sniper.internal.SourceFragmentContextList.print(SourceFragmentContextList.java:19)
at spoon.support.sniper.SniperJavaPrettyPrinter$2.printSourceFragment(SniperJavaPrettyPrinter.java:298)
at spoon.support.sniper.internal.AbstractSourceFragmentPrinter.print(AbstractSourceFragmentPrinter.java:64)
at spoon.support.sniper.internal.SourceFragmentContextNormal.print(SourceFragmentContextNormal.java:38)
at spoon.support.sniper.SniperJavaPrettyPrinter.executePrintEventInContext(SniperJavaPrettyPrinter.java:334)
at spoon.support.sniper.SniperJavaPrettyPrinter.scan(SniperJavaPrettyPrinter.java:269)
at spoon.support.sniper.SniperJavaPrettyPrinter.scan(SniperJavaPrettyPrinter.java:57)
at spoon.reflect.visitor.DefaultJavaPrettyPrinter.visitCtCompilationUnit(DefaultJavaPrettyPrinter.java:1099)
at spoon.support.reflect.declaration.CtCompilationUnitImpl.accept(CtCompilationUnitImpl.java:407)
at spoon.reflect.visitor.DefaultJavaPrettyPrinter.scan(DefaultJavaPrettyPrinter.java:381)
at spoon.support.sniper.SniperJavaPrettyPrinter.lambda$superScanInContext$6(SniperJavaPrettyPrinter.java:384)
at spoon.support.sniper.SniperJavaPrettyPrinter.runInContext(SniperJavaPrettyPrinter.java:395)
at spoon.support.sniper.SniperJavaPrettyPrinter.superScanInContext(SniperJavaPrettyPrinter.java:384)
at spoon.support.sniper.SniperJavaPrettyPrinter.access$300(SniperJavaPrettyPrinter.java:58)
at spoon.support.sniper.SniperJavaPrettyPrinter$2.printSourceFragment(SniperJavaPrettyPrinter.java:309)
at spoon.support.sniper.internal.AbstractSourceFragmentPrinter.print(AbstractSourceFragmentPrinter.java:64)
at spoon.support.sniper.internal.SourceFragmentContextList.print(SourceFragmentContextList.java:19)
at spoon.support.sniper.SniperJavaPrettyPrinter.executePrintEventInContext(SniperJavaPrettyPrinter.java:334)
at spoon.support.sniper.SniperJavaPrettyPrinter.scan(SniperJavaPrettyPrinter.java:269)
at spoon.support.sniper.SniperJavaPrettyPrinter.scan(SniperJavaPrettyPrinter.java:57)
at spoon.reflect.visitor.DefaultJavaPrettyPrinter.calculate(DefaultJavaPrettyPrinter.java:2064)
at spoon.support.sniper.SniperJavaPrettyPrinter.lambda$calculate$4(SniperJavaPrettyPrinter.java:148)
at spoon.support.sniper.SniperJavaPrettyPrinter.runInContext(SniperJavaPrettyPrinter.java:395)
at spoon.support.sniper.SniperJavaPrettyPrinter.calculate(SniperJavaPrettyPrinter.java:143)
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.getCompilationUnitInputStream(JDTBasedSpoonCompiler.java:683)
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.generateProcessedSourceFilesUsingCUs(JDTBasedSpoonCompiler.java:565)
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.generateProcessedSourceFiles(JDTBasedSpoonCompiler.java:211)
at spoon.Launcher.prettyprint(Launcher.java:788)
... 28 more
Process finished with exit code 255
```
This occurs when trying to print the first field of the inner type `Internal`, `public int a;`. Its modification status is `UNKNOWN`, and that causes an exception on the call to `ModificationStatus.toBoolean()`. I've not been able to figure out how this happens, just reliably reproducing the issue took a good while :)
It's not a super common problem, but it occurs in at least 5 out of ~100 projects. I'll probably not have time to spend more time on this problem until next week.
Contributor guide
Assessment
This issue has not been assessed yet.