package spoon.test.prettyprinter; import org.apache.commons.lang3.StringEscapeUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import spoon.Launcher; import spoon.compiler.SpoonResourceHelper; import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtInvocation; import spoon.reflect.code.CtLiteral; import spoon.reflect.code.CtStatement; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtTypeAccess; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtType; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtFieldReference; import spoon.reflect.reference.CtReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.DefaultJavaPrettyPrinter; import spoon.reflect.visitor.filter.TypeFilter; import spoon.support.reflect.code.CtFieldAccessImpl; import spoon.support.reflect.reference.CtFieldReferenceImpl; import spoon.test.delete.testclasses.Adobada; import spoon.test.prettyprinter.testclasses.QualifiedThisRef; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import static javax.swing.text.html.HTML.Tag.HEAD; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static spoon.testing.utils.ModelUtils.build; public class QualifiedThisRefTest { Factory factory; @Before public void setup() throws Exception { Launcher spoon = new Launcher(); factory = spoon.createFactory(); factory.getEnvironment().setComplianceLevel(8); spoon.createCompiler( factory, SpoonResourceHelper .resources( "./src/test/java/spoon/test/prettyprinter/testclasses/QualifiedThisRef.java")) .build(); factory.getEnvironment().setAutoImports(true); } @Test public void testQualifiedThisRef() { DefaultJavaPrettyPrinter printer = new DefaultJavaPrettyPrinter(factory.getEnvironment()); CtType<?> ctClass = factory.Type().get(QualifiedThisRef.class); Collection<CtReference> imports = printer.computeImports(ctClass); final List<CtType<?>> ctTypes = new ArrayList<>(); ctTypes.add(ctClass); printer.getElementPrinterHelper().writeHeader(ctTypes, imports); printer.scan(ctClass); Assert.assertTrue(printer.getResult().contains("Object o = this")); Assert.assertTrue(printer.getResult().contains("Object o2 = QualifiedThisRef.this")); } @Test public void testCloneThisAccess() throws Exception { // contract: the target of "this" is correct and can be cloned final Factory factory = build(Adobada.class); final CtClass<Adobada> adobada = factory.Class().get(Adobada.class); final CtMethod<?> m2 = adobada.getMethod("methodUsingjlObjectMethods"); CtThisAccess th = (CtThisAccess) m2.getElements(new TypeFilter(CtThisAccess.class)).get(0); assertEquals(true,th.isImplicit()); assertEquals("notify()",th.getParent().toString()); CtInvocation<?> clone = m2.clone().getBody().getStatement(0); // clone preserves implicitness assertEquals(true, clone.getTarget().isImplicit()); assertEquals("notify()", clone.toString()); // the original bug // note that this behavior means that you can only keep cloned "this" in the same class, // and you cannot "transplant" a cloned "this" to another class // it makes perfectly sense about the meaning of this. // to "transplant" a this, you have to first set the target to null } @Test public void testPrintCtFieldAccessWorkEvenWhenParentNotInitialized() throws Exception { CtClass zeclass = factory.Class().get(QualifiedThisRef.class); List<CtMethod> methods = zeclass.getMethodsByName("bla"); assertEquals(1, methods.size()); CtStatement invocation = methods.get(0).getBody().getStatement(0); assertTrue(invocation instanceof CtInvocation); CtInvocation<?> arg0 = (CtInvocation) invocation; CtExpression param = arg0.getArguments().get(0); CtExecutableReference execref = factory.Core().createExecutableReference(); execref.setDeclaringType(factory.Type().createReference("java.util.Map")); execref.setSimpleName("exorcise"); execref.setStatic(true); CtTypeReference tmp = param.getType(); CtExpression arg = null; CtFieldReference ctfe = new CtFieldReferenceImpl(); ctfe.setSimpleName("class"); ctfe.setDeclaringType(tmp.box()); arg = factory.Core().createFieldRead(); ((CtFieldAccessImpl) arg).setVariable(ctfe); CtLiteral location = factory.Core().createLiteral(); location.setType(factory.Type().createReference(String.class)); CtTypeReference tmpref = factory.Core().clone(tmp); CtInvocation invoc = factory.Core().createInvocation(); invoc.setExecutable(execref); invoc.setArguments(Arrays.asList(new CtExpression[]{param,arg,location})); execref.setActualTypeArguments(Arrays.asList(new CtTypeReference<?>[]{tmpref})); // succeeds arg0.getArguments().set(0, invoc); DefaultJavaPrettyPrinter printer = new DefaultJavaPrettyPrinter(factory.getEnvironment()); printer.visitCtClass(zeclass); assertFalse(printer.getResult().isEmpty()); } }