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: Combining CtSuperAccess and CtUnaryOperator lead to SpoonException with Sniper #4021

Closed
gtoison opened this issue Jul 1, 2021 · 5 comments · Fixed by #4092
Closed
Labels

Comments

@gtoison
Copy link
Contributor

gtoison commented Jul 1, 2021

Hello,

I'm trying to analyze and refactor some code containing the following line (note that is has a "super" access and an unary "minus" operator) :

Date limitTradeDateBeforeIssue = super.computeSettleDate(getIssueDate(), -days);

When pretty printing the code with Sniper I get an exception which seems to be coming from this specific line of code:

Exception in thread "main" spoon.SpoonException: Cannot compare this: [151, 192] with other: ["191", "196"]
	at spoon.support.sniper.internal.ElementSourceFragment.compare(ElementSourceFragment.java:371)
	at spoon.support.sniper.internal.ElementSourceFragment.add(ElementSourceFragment.java:285)
	at spoon.support.sniper.internal.ElementSourceFragment.addChild(ElementSourceFragment.java:317)
	at spoon.support.sniper.internal.ElementSourceFragment.addChild(ElementSourceFragment.java:243)
	at spoon.support.sniper.internal.ElementSourceFragment.access$000(ElementSourceFragment.java:51)
	at spoon.support.sniper.internal.ElementSourceFragment$1.enter(ElementSourceFragment.java:200)
	at spoon.reflect.visitor.CtScanner.visitCtUnaryOperator(CtScanner.java:808)
	at spoon.support.reflect.code.CtUnaryOperatorImpl.accept(CtUnaryOperatorImpl.java:36)
	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.CtScanner.visitCtInvocation(CtScanner.java:505)
	at spoon.support.reflect.code.CtInvocationImpl.accept(CtInvocationImpl.java:46)
	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.CtScanner.visitCtLocalVariable(CtScanner.java:532)
	at spoon.support.sniper.internal.ElementSourceFragment$1.visitCtLocalVariable(ElementSourceFragment.java:181)
	at spoon.support.reflect.code.CtLocalVariableImpl.accept(CtLocalVariableImpl.java:51)
	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.CtScanner.visitCtBlock(CtScanner.java:300)
	at spoon.support.reflect.code.CtBlockImpl.accept(CtBlockImpl.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.CtScanner.visitCtMethod(CtScanner.java:566)
	at spoon.support.reflect.declaration.CtMethodImpl.accept(CtMethodImpl.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.CtScanner.visitCtClass(CtScanner.java:336)
	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:150)
	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:789)
	at fr.tobam.SpoonRefactor.main(SpoonRefactor.java:45)

The input is a fairly large codebase but I was able to reproduce the exception with that input:


public class Aaa {

	public static void main(String[] args) {
		Date limitTradeDateBeforeIssue = super.computeSettleDate(getIssueDate(), -days);
	}
}

The code I'm using to reproduce the error is:


	public static void main(String[] args) throws IOException {
		final Launcher launcher = new Launcher();

		launcher.addInputResource("./src/main/resources/source");
		launcher.setSourceOutputDirectory("./_target/main/java/");

		launcher.getEnvironment().setAutoImports(true);
		launcher.getEnvironment().setPreserveLineNumbers(true);

		launcher.getEnvironment().setPrettyPrinterCreator(() -> {
			return new SniperJavaPrettyPrinter(launcher.getEnvironment());
		});

		launcher.buildModel();

		final Factory factory = launcher.getFactory();
		final ProcessingManager processingManager = new QueueProcessingManager(factory);
		processingManager.process(factory.Class().getAll());

		launcher.prettyprint();
	}

Can you please advise if there's something I'm doing incorrectly or if that's an issue in Spoon?

@slarse slarse added the bug label Jul 1, 2021
@slarse
Copy link
Collaborator

slarse commented Jul 1, 2021

Hi @gtoison,

Thanks for the bug report!

This is definitely a bug in the sniper printer. It's trying to compare to source fragments that are, in terms of source position, overlapping. It may be trying to compare source fragments from different files, which I've previously fixed a bug for with static method imports (see #3743).

I will look at this as soon as possible, but I'm a bit swamped right now so if anyone else has the time to look into it, feel free!

@gtoison
Copy link
Contributor Author

gtoison commented Jul 1, 2021

Thank you very much for the confirmation!

@monperrus monperrus changed the title Combining CtSuperAccess and CtUnaryOperator lead to SpoonException with Sniper bug: Combining CtSuperAccess and CtUnaryOperator lead to SpoonException with Sniper Jul 6, 2021
gtoison added a commit to gtoison/spoon that referenced this issue Jul 6, 2021
Combining CtSuperAccess and CtUnaryOperator leads to SpoonException with
Sniper
@gtoison
Copy link
Contributor Author

gtoison commented Jul 6, 2021

@slarse I've submitted a small PR with a failing unit test reproducing the issue.
Hopefully this helps, if not feel free to reject it!

@slarse
Copy link
Collaborator

slarse commented Jul 6, 2021

@gtoison That's very helpful, thank you!

@slarse
Copy link
Collaborator

slarse commented Aug 12, 2021

Finally found the time to look into this.

The cause of the crash is that the end source position given by JDT is off for the super reference, it always includes the - (or any other unary operator). However, if one omits the unary operator, then suddenly the source position is correct. Very strange behavior, probably a bug in JDT.

For now we can easily work around it as the start position of the reference is correct, and the length of it is known.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants
  NODES
COMMUNITY 2
INTERN 9
Note 1
Project 3
USERS 1