diff --git a/src/main/java/spoon/support/JavaOutputProcessor.java b/src/main/java/spoon/support/JavaOutputProcessor.java index 2f7e9b051ec..e0b8b70f00e 100644 --- a/src/main/java/spoon/support/JavaOutputProcessor.java +++ b/src/main/java/spoon/support/JavaOutputProcessor.java @@ -22,9 +22,9 @@ import spoon.support.compiler.SpoonProgress; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintStream; +import java.nio.charset.Charset; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; @@ -39,6 +39,8 @@ public class JavaOutputProcessor extends AbstractProcessor imple List printedFiles = new ArrayList<>(); + private Charset charset = Charset.defaultCharset(); + /** * @param printer the PrettyPrinter to use for written the files */ @@ -75,6 +77,22 @@ public File getOutputDirectory() { return this.getEnvironment().getSourceOutputDirectory(); } + /** + * Gets the charset. + * @return the charset used for processed source code. + */ + public Charset getCharset() { + return this.charset; + } + + /** + * Sets the charset. + * @param charset the charset used for processed source code. + */ + public void setCharset(Charset charset) { + this.charset = charset; + } + @Override public void init() { // Skip loading properties @@ -123,7 +141,7 @@ public void createJavaFile(CtType element) { printedFiles.add(file); } // print type - try (PrintStream stream = new PrintStream(file)) { + try (PrintStream stream = new PrintStream(file, charset)) { stream.print(printer.getResult()); for (CtType t : toBePrinted) { lineNumberMappings.put(t.getQualifiedName(), printer.getLineNumberMapping()); @@ -161,9 +179,9 @@ private void createPackageFile(CtPackage pack) { if (!printedFiles.contains(packageAnnot)) { printedFiles.add(packageAnnot); } - try (PrintStream stream = new PrintStream(packageAnnot)) { + try (PrintStream stream = new PrintStream(packageAnnot, charset)) { stream.println(getPrinter().printPackageInfo(pack)); - } catch (FileNotFoundException e) { + } catch (IOException e) { Launcher.LOGGER.error(e.getMessage(), e); } } @@ -174,9 +192,9 @@ private void createModuleFile(CtModule module) { if (!printedFiles.contains(moduleFile)) { printedFiles.add(moduleFile); } - try (PrintStream stream = new PrintStream(moduleFile)) { + try (PrintStream stream = new PrintStream(moduleFile, charset)) { stream.println(getPrinter().printModuleInfo(module)); - } catch (FileNotFoundException e) { + } catch (IOException e) { Launcher.LOGGER.error(e.getMessage(), e); } } diff --git a/src/test/java/spoon/support/JavaOutputProcessorTest.java b/src/test/java/spoon/support/JavaOutputProcessorTest.java index c7d2880cd68..ada432e4798 100644 --- a/src/test/java/spoon/support/JavaOutputProcessorTest.java +++ b/src/test/java/spoon/support/JavaOutputProcessorTest.java @@ -7,12 +7,63 @@ import spoon.reflect.factory.Factory; import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class JavaOutputProcessorTest { + @Test + void testCreateJavaFileAssertFileCreated(@TempDir File tempDir) { + // contract : createJavaFile creates a Java file and prints it + + // arrange + Launcher launcher = new Launcher(); + launcher.setSourceOutputDirectory(tempDir.getAbsolutePath()); + launcher.getEnvironment().setComplianceLevel(9); + Factory factory = launcher.getFactory(); + + CtClass ctClass = factory.Class().create("spoon.support.EmptyClass"); + JavaOutputProcessor javaOutputProcessor = new JavaOutputProcessor(); + javaOutputProcessor.setFactory(factory); + + // act + javaOutputProcessor.process(ctClass); + + // assert + File expectedFile = tempDir.toPath().resolve("spoon/support/EmptyClass.java").toFile(); + assertTrue(expectedFile.exists()); + assertEquals(1, javaOutputProcessor.printedFiles.size()); + } + + @Test + void testCreateJavaFileAssertFileEncodingChanged(@TempDir File tempDir) throws Exception { + + // arrange + Launcher launcher = new Launcher(); + launcher.setSourceOutputDirectory(tempDir.getAbsolutePath()); + launcher.getEnvironment().setComplianceLevel(9); + Factory factory = launcher.getFactory(); + + // use characters encoded differently in ISO-8859-01 and UTFs + String code = "class ÈmptyÇlàss {}"; + CtClass ctClass = Launcher.parseClass(code); + + JavaOutputProcessor javaOutputProcessor = new JavaOutputProcessor(); + javaOutputProcessor.setCharset(StandardCharsets.ISO_8859_1); + javaOutputProcessor.setFactory(factory); + + // act + javaOutputProcessor.process(ctClass); + + // assert + File expectedFile = tempDir.toPath().resolve("ÈmptyÇlàss.java").toFile(); + + byte[] bytes = Files.readAllBytes(expectedFile.toPath()); + assertEquals(code, new String(bytes, StandardCharsets.ISO_8859_1)); + } @Test void testCreateModuleFileAssertAnnotationFileCreated(@TempDir File tempDir) {