diff --git a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java index 5f8430475b8..9f3546defa3 100644 --- a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java +++ b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java @@ -757,15 +757,21 @@ public void visitCtThisAccess(CtThisAccess thisAccess) { } // complex case of qualifed this - if (context.currentThis.peekLast() != null - && !context.currentThis.peekLast().type.getQualifiedName().equals(targetType.getQualifiedName())) { - printer.snapshotLength(); - visitCtTypeReferenceWithoutGenerics(targetType); - if (printer.hasNewContent()) { - printer.write("."); + if (!context.currentThis.isEmpty()) { + + CtType lastType = context.currentThis.peekFirst().type; + String lastTypeQualifiedName = lastType.getQualifiedName(); + String targetTypeQualifiedName = targetType.getQualifiedName(); + + if (!lastTypeQualifiedName.equals(targetTypeQualifiedName)) { + printer.snapshotLength(); + visitCtTypeReferenceWithoutGenerics(targetType); + if (printer.hasNewContent()) { + printer.write("."); + } + printer.write("this"); + return; } - printer.write("this"); - return; } // the default super simple case only comes at the end diff --git a/src/main/java/spoon/reflect/visitor/PrintingContext.java b/src/main/java/spoon/reflect/visitor/PrintingContext.java index ef041c05e24..35aff05de91 100644 --- a/src/main/java/spoon/reflect/visitor/PrintingContext.java +++ b/src/main/java/spoon/reflect/visitor/PrintingContext.java @@ -114,7 +114,7 @@ private TypeContext getCurrentTypeContext() { } public void pushCurrentThis(CtType type) { - currentThis.add(new TypeContext(type)); + currentThis.push(new TypeContext(type)); } public void popCurrentThis() { currentThis.pop(); diff --git a/src/test/java/spoon/test/prettyprinter/PrinterTest.java b/src/test/java/spoon/test/prettyprinter/PrinterTest.java index 3ff9db9965e..515023beb20 100644 --- a/src/test/java/spoon/test/prettyprinter/PrinterTest.java +++ b/src/test/java/spoon/test/prettyprinter/PrinterTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static spoon.testing.utils.ModelUtils.canBeBuilt; import org.junit.Test; @@ -75,4 +76,44 @@ public void testFQNModeWriteFQNConstructorInCtVisitor() { assertTrue("The result should not contain reduced constructors: "+result, !result.contains("new ReplacementVisitor(")); } + @Test + public void testRuleCanBeBuild() { + Launcher spoon = new Launcher(); + PrettyPrinter printer = spoon.createPrettyPrinter(); + spoon.getEnvironment().setAutoImports(true); + String output = "./target/spoon-rule/"; + spoon.addInputResource("./src/test/java/spoon/test/prettyprinter/testclasses/Rule.java"); + spoon.setSourceOutputDirectory(output); + spoon.run(); + + CtType element = spoon.getFactory().Class().getAll().get(0); + List> toPrint = new ArrayList<>(); + toPrint.add(element); + printer.calculate(element.getPosition().getCompilationUnit(), toPrint); + String result = printer.getResult(); + + assertTrue("The result should contain direct this accessor for field: "+result, !result.contains("Rule.Phoneme.this.phonemeText")); + canBeBuilt(output, 7); + } + + @Test + public void testJDTBatchCompilerCanBeBuild() { + Launcher spoon = new Launcher(); + PrettyPrinter printer = spoon.createPrettyPrinter(); + spoon.getEnvironment().setAutoImports(false); + String output = "./target/spoon-jdtbatchcompiler/"; + spoon.addInputResource("./src/main/java/spoon/support/compiler/jdt/JDTBatchCompiler.java"); + spoon.setSourceOutputDirectory(output); + spoon.run(); + + CtType element = spoon.getFactory().Class().getAll().get(0); + List> toPrint = new ArrayList<>(); + toPrint.add(element); + printer.calculate(element.getPosition().getCompilationUnit(), toPrint); + String result = printer.getResult(); + + //assertTrue("The result should contain direct this accessor for field: "+result, !result.contains("Rule.Phoneme.this.phonemeText")); + canBeBuilt(output, 7); + } + } diff --git a/src/test/java/spoon/test/prettyprinter/testclasses/Rule.java b/src/test/java/spoon/test/prettyprinter/testclasses/Rule.java new file mode 100644 index 00000000000..03d9c6bd53a --- /dev/null +++ b/src/test/java/spoon/test/prettyprinter/testclasses/Rule.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2006-2016 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 that you accept its terms. + */ + +package spoon.test.prettyprinter.testclasses; + +import java.util.*; + +/** + * Created by urli on 19/12/2016. + */ +public class Rule { + public enum Language { + DTD, WSDL, OTHER + } + public static final class Phoneme implements PhonemeExpr { + public interface Bidule {} + + public static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(final Phoneme o1, final Phoneme o2) { + for (int i = 0; i < o1.phonemeText.length(); i++) { + if (i >= o2.phonemeText.length()) { + return +1; + } + final int c = o1.phonemeText.charAt(i) - o2.phonemeText.charAt(i); + if (c != 0) { + return c; + } + } + + if (o1.phonemeText.length() < o2.phonemeText.length()) { + return -1; + } + + return 0; + } + }; + + private final StringBuilder phonemeText; + private final Language language; + + public Phoneme(final CharSequence phonemeText, final Language language) { + this.phonemeText = new StringBuilder(phonemeText); + this.language = language; + } + + @Override + public Iterable getPhonemes() { + return Collections.singleton(this); + } + } + + public interface PhonemeExpr { + Iterable getPhonemes(); + } + + public static final class PhonemeList implements PhonemeExpr { + private final List phonemes; + + public PhonemeList(final List phonemes) { + this.phonemes = phonemes; + } + + @Override + public List getPhonemes() { + return this.phonemes; + } + } + + public static final String ALL = "ALL"; + + private static final String DOUBLE_QUOTE = "\""; + + private static final String HASH_INCLUDE = "#include"; + + private static Phoneme parsePhoneme(final String ph) { + final int open = ph.indexOf("["); + if (open >= 0) { + if (!ph.endsWith("]")) { + throw new IllegalArgumentException("Phoneme expression contains a '[' but does not end in ']'"); + } + final String before = ph.substring(0, open); + final String in = ph.substring(open + 1, ph.length() - 1); + final Set langs = new HashSet(Arrays.asList(in.split("[+]"))); + + return new Phoneme(before, Language.DTD); + } + return new Phoneme(ph, Language.WSDL); + } +}