INRIA / INRIA/spoon

bug: Sniper printer does not handle statements that declare multiple variables correctly

Open
#3,765 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.