Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: Sniper printer crashes on printing method import for which the method source is available #3743

Closed
slarse opened this issue Jan 7, 2021 · 0 comments · Fixed by #3744

Comments

@slarse
Copy link
Collaborator

slarse commented Jan 7, 2021

Hi,

There's currently a problem where the sniper printer always crashes if there's a method import in a class, and the class from which the method is imported is also available in the source code. Here's a minimal example:

File with the static method:

package pkg;

public class SomeClass {

    public static void printMeaning() {
        System.out.println(42);
    }
}

File that imports the static method:

package otherpkg;
import static pkg.SomeClass.printMeaning;

public class OtherClass {
    public static void main(String[] args) {
        printMeaning();
    }
}

When sniper printing OtherClass, without changing anything in it, there's a crash when printing import static pkg.SomeClass.printMeaning;.

spoon.SpoonException: Cannot compare this: [18, 62] with other: ["61", "163"]

	at spoon.support.sniper.internal.ElementSourceFragment.compare(ElementSourceFragment.java:359)
	at spoon.support.sniper.internal.ElementSourceFragment.add(ElementSourceFragment.java:273)
	at spoon.support.sniper.internal.ElementSourceFragment.addNextSibling(ElementSourceFragment.java:313)
	at spoon.support.sniper.internal.ElementSourceFragment.add(ElementSourceFragment.java:277)
	at spoon.support.sniper.internal.ElementSourceFragment.addChild(ElementSourceFragment.java:305)
	at spoon.support.sniper.internal.ElementSourceFragment.addChild(ElementSourceFragment.java:241)
	at spoon.support.sniper.internal.ElementSourceFragment.access$0(ElementSourceFragment.java:237)
	at spoon.support.sniper.internal.ElementSourceFragment$1.enter(ElementSourceFragment.java:200)
	at spoon.reflect.visitor.CtScanner.visitCtClass(CtScanner.java:331)
	at spoon.support.reflect.declaration.CtClassImpl.accept(CtClassImpl.java:58)
	at spoon.reflect.visitor.EarlyTerminatingScanner.doScan(EarlyTerminatingScanner.java:145)
	at spoon.reflect.visitor.EarlyTerminatingScanner.scan(EarlyTerminatingScanner.java:121)
	at spoon.reflect.visitor.CtScanner.scan(CtScanner.java:170)
	at spoon.reflect.visitor.EarlyTerminatingScanner.scan(EarlyTerminatingScanner.java:106)
	at spoon.reflect.visitor.EarlyTerminatingScanner.scan(EarlyTerminatingScanner.java:83)
	at spoon.reflect.visitor.EarlyTerminatingScanner.visitCtCompilationUnit(EarlyTerminatingScanner.java:160)
	at spoon.support.reflect.declaration.CtCompilationUnitImpl.accept(CtCompilationUnitImpl.java:407)
	at spoon.reflect.visitor.EarlyTerminatingScanner.doScan(EarlyTerminatingScanner.java:145)
	at spoon.reflect.visitor.EarlyTerminatingScanner.scan(EarlyTerminatingScanner.java:121)
	at spoon.reflect.visitor.CtScanner.scan(CtScanner.java:170)
	at spoon.reflect.visitor.EarlyTerminatingScanner.scan(EarlyTerminatingScanner.java:106)
	at spoon.support.sniper.internal.ElementSourceFragment.createSourceFragmentsFrom(ElementSourceFragment.java:228)
	at spoon.support.reflect.declaration.CtCompilationUnitImpl.getOriginalSourceFragment(CtCompilationUnitImpl.java:359)
	at spoon.support.sniper.internal.IndentationDetector.detectIndentation(IndentationDetector.java:34)
	at spoon.support.sniper.SniperJavaPrettyPrinter.calculate(SniperJavaPrettyPrinter.java:139)
	at spoon.test.sourcePosition.SourcePositionTest.testImportSourcePosition2(SourcePositionTest.java:179)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)


Process finished with exit code 255

This crash is caused by the source end position of the import statement being resolved incorrectly:

/**
* @return offset of character after this fragment
*/
public int getEnd() {
if (firstChild != null) {
return Math.max(getSourcePosition().getSourceEnd() + 1, firstChild.getLastSibling().getEnd());
}
return getSourcePosition().getSourceEnd() + 1;
}

The reason it's resolved incorrectly is that the method reference to printMeaning() has a type reference void as a child (the return type), and that type reference has its source position in the SomeClass file, rather than in the OtherClass file where it's used. As it is a static import, I suppose this makes sense, and the problem is that the sniper printer doesn't deal with it. It could also be the case that this doesn't make sense, and then the problem isn't really in the sniper printer.

I'm working on a fix with the assumption that the problem is in the sniper printer. If anyone thinks that the problem is that the type reference has an incorrect source position, then please let me know so we can discuss it.

@slarse slarse changed the title bug: Sniper printer crashes on static method imports that are present in the source bug: Sniper printer crashes on printing method import for which the method source is available Jan 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant
  NODES
COMMUNITY 2
Idea 4
idea 4
INTERN 16
Project 3
USERS 1