diff --git a/src/test/java/spoon/test/prettyprinter/PrinterTest.java b/src/test/java/spoon/test/prettyprinter/PrinterTest.java index 5e1debfa026..0172b30b028 100644 --- a/src/test/java/spoon/test/prettyprinter/PrinterTest.java +++ b/src/test/java/spoon/test/prettyprinter/PrinterTest.java @@ -320,7 +320,7 @@ public void testPrintingOfOrphanFieldReference() throws Exception { "catch extends int short try", "char final interface static void", "class finally long strictfp volatile", - "const float native super while" + "const float native super while var" }; private final Set javaKeywords = new HashSet<>(); @@ -355,7 +355,7 @@ public void testPrinterTokenListener() throws Exception { pp.calculate(t.getPosition().getCompilationUnit(), Collections.singletonList(t)); //result of printing using standard DefaultTokenWriter String standardPrintedResult = pp.getResult(); - + StringBuilder allTokens = new StringBuilder(); //print type with custom listener //1) register custom TokenWriter which checks the TokenWriter contract @@ -366,24 +366,24 @@ public void testPrinterTokenListener() throws Exception { @Override public TokenWriter writeSeparator(String separator) { checkRepeatingOfTokens("writeSeparator"); - checkTokenWhitespace(separator, false); + checkTokenWhitespace(separator, false); //one of the separators assertTrue(separators.contains(separator), "Unexpected separator: " + separator); handleTabs(); allTokens.append(separator); return this; } - + @Override public TokenWriter writeOperator(String operator) { checkRepeatingOfTokens("writeOperator"); - checkTokenWhitespace(operator, false); + checkTokenWhitespace(operator, false); assertTrue(operators.contains(operator), "Unexpected operator: " + operator); handleTabs(); allTokens.append(operator); return this; } - + @Override public TokenWriter writeLiteral(String literal) { checkRepeatingOfTokens("writeLiteral"); @@ -392,17 +392,17 @@ public TokenWriter writeLiteral(String literal) { allTokens.append(literal); return this; } - + @Override public TokenWriter writeKeyword(String keyword) { checkRepeatingOfTokens("writeKeyword"); - checkTokenWhitespace(keyword, false); + checkTokenWhitespace(keyword, false); assertTrue(javaKeywords.contains(keyword), "Unexpected java keyword: " + keyword); handleTabs(); allTokens.append(keyword); return this; } - + @Override public TokenWriter writeIdentifier(String identifier) { checkRepeatingOfTokens("writeIdentifier"); @@ -423,7 +423,7 @@ public TokenWriter writeIdentifier(String identifier) { allTokens.append(identifier); return this; } - + @Override public TokenWriter writeComment(CtComment comment) { checkRepeatingOfTokens("writeComment"); @@ -436,7 +436,7 @@ public TokenWriter writeComment(CtComment comment) { allTokens.append(sptw.getPrinterHelper().toString()); return this; } - + @Override public TokenWriter writeln() { checkRepeatingOfTokens("writeln"); @@ -444,10 +444,10 @@ public TokenWriter writeln() { lastTokenWasEOL = true; return this; } - + private boolean lastTokenWasEOL = true; private int tabCount = 0; - + public TokenWriter handleTabs() { if(lastTokenWasEOL) { lastTokenWasEOL = false; @@ -460,7 +460,7 @@ public TokenWriter handleTabs() { } } } - + } return this; } @@ -517,14 +517,14 @@ private void checkRepeatingOfTokens(String tokenType) { this.lastToken = tokenType; } }); - + //2) print type using PrettyPrinter with listener pp.calculate(t.getPosition().getCompilationUnit(), Collections.singletonList(t)); String withEmptyListenerResult = pp.getResult(); //contract: each printed character is handled by listener. PrinterHelper is not called directly //and because PrinterTokenListener above does not use PrinterHelper, the result must be empty assertEquals(0, withEmptyListenerResult.length()); - + //contract: result built manually from tokens is same like the one made by DefaultTokenWriter assertEquals(standardPrintedResult, allTokens.toString()); } @@ -606,7 +606,7 @@ public DefaultTokenWriter writeKeyword(String token) { assertTrue(FileUtils.readFileToString(new File("spooned/HelloWorld.java"), "UTF-8").contains(" class")); } - + @Test public void testTypeLostPrintingStringClassReference() { // contract: when a class reference is printed, the type is not lost diff --git a/src/test/java/spoon/test/prettyprinter/ToStringCommentTest.java b/src/test/java/spoon/test/prettyprinter/ToStringCommentTest.java new file mode 100644 index 00000000000..d9febb407db --- /dev/null +++ b/src/test/java/spoon/test/prettyprinter/ToStringCommentTest.java @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2006-2018 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and you accept the terms. + */ +package spoon.test.prettyprinter; + +import spoon.Launcher; +import spoon.reflect.declaration.CtType; +import spoon.testing.utils.ModelTest; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ToStringCommentTest { + + @ModelTest("./src/test/resources/spoon/test/prettyprinter/toStringCommentTest") + public void testToStringWithComplexComments(Launcher launcher) { + // contract: toString() should not crash when processing complex comments + // This is a regression test for issue #3382 where cleanComment method could crash + var types = launcher.getFactory().Class().getAll(); + assertThat(types).withFailMessage("Should load test resources").isNotEmpty(); + + for (CtType type : types) { + assertThat(type.toString()).withFailMessage("toString() should not return null for type: " + type.getQualifiedName()).isNotNull(); + } + } +} diff --git a/src/test/java/spoon/toStringBugTest/ToStringBugTest.java b/src/test/java/spoon/toStringBugTest/ToStringBugTest.java deleted file mode 100644 index c3b0dbfc102..00000000000 --- a/src/test/java/spoon/toStringBugTest/ToStringBugTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package spoon.toStringBugTest; - - -import java.util.List; - -import org.junit.jupiter.api.Test; -import spoon.Launcher; -import spoon.SpoonException; -import spoon.reflect.declaration.CtType; - -import static org.junit.jupiter.api.Assertions.fail; - -public class ToStringBugTest { - - @Test - public void testIssue3382() { - // contract: the cleanComment should not crash - final Launcher launcher = new Launcher(); - launcher.getEnvironment().setNoClasspath(true); - // folder with both classes - launcher.addInputResource("./src/test/resources/toStringBugTest"); - launcher.buildModel(); - List> all = launcher.getFactory().Class().getAll(); - - // first class of resources - CtType ctType0 = all.get(0); - try { - String s = ctType0.toString(); - } catch (SpoonException e) { - // spoon.SpoonException: Unexpected next line after last line - fail(e.toString()); - } - - // second class of resources - CtType ctType1 = all.get(1); - try { - String s = ctType1.toString(); - } catch (SpoonException e) { - fail(e.toString()); - } - } -} diff --git a/src/test/resources/toStringBugTest/TestClass.java b/src/test/resources/spoon/test/prettyprinter/toStringCommentTest/TestClass.java similarity index 100% rename from src/test/resources/toStringBugTest/TestClass.java rename to src/test/resources/spoon/test/prettyprinter/toStringCommentTest/TestClass.java diff --git a/src/test/resources/toStringBugTest/TestClass2.java b/src/test/resources/spoon/test/prettyprinter/toStringCommentTest/TestClass2.java similarity index 100% rename from src/test/resources/toStringBugTest/TestClass2.java rename to src/test/resources/spoon/test/prettyprinter/toStringCommentTest/TestClass2.java