private static <T> void processConstructor(CtConstructor<T> c, CtClass<T> toMerge) { CtStatement firstStmt = c.getBody().getStatements().get(0); if (firstStmt instanceof CtInvocation) { CtInvocation<?> superConstructorCall = (CtInvocation) firstStmt; if (!(superConstructorCall.getExecutable().getDeclaration() instanceof CtConstructor)) return; CtConstructor superConstructor = (CtConstructor) superConstructorCall.getExecutable().getDeclaration(); if (superConstructor.getDeclaringType() == toMerge) { CtBlock superConstructorBody = c.getFactory().Core().clone(superConstructor.getBody()); superConstructorBody.accept( new CtScanner() { @Override public <T> void visitCtParameterReference(CtParameterReference<T> ref) { int parameterOrder = superConstructor.getParameters().indexOf(ref.getDeclaration()); ref.setDeclaringExecutable(c.getReference()); CtExpression<?> arg = superConstructorCall.getArguments().get(parameterOrder); if (!(arg instanceof CtVariableAccess)) throw sgce("super() should be directly called in " + c); CtVariable param = ((CtVariableAccess) arg).getVariable().getDeclaration(); if (!(param instanceof CtParameter)) throw sgce("super() should be directly called in " + c); ref.setSimpleName(param.getSimpleName()); super.visitCtParameterReference(ref); } }); c.getBody().removeStatement(firstStmt); List<CtStatement> superConstructorBodyStatements = superConstructorBody.getStatements(); for (int i = superConstructorBodyStatements.size() - 1; i >= 0; i--) { c.getBody().insertBegin(superConstructorBodyStatements.get(i)); } } } }
@Test public void testTransformationOnConstructorWithInsertBegin() throws Exception { final CtConstructor<?> ctConstructor = aClass.getElements(new TypeFilter<CtConstructor<?>>(CtConstructor.class)).get(0); ctConstructor.getBody().insertBegin(factory.Code().createCodeSnippetStatement("int i = 0")); assertEquals(2, ctConstructor.getBody().getStatements().size()); assertEquals("super()", ctConstructor.getBody().getStatement(0).toString()); TestUtils.canBeBuilt("./target/spooned/spoon/test/constructor/testclasses/", 8); }
@Test public void testTransformationOnConstructorWithInsertBefore() throws Exception { final CtConstructor<?> ctConstructor = aClass.getElements(new TypeFilter<CtConstructor<?>>(CtConstructor.class)).get(0); try { ctConstructor .getBody() .getStatement(0) .insertBefore(factory.Code().createCodeSnippetStatement("int i = 0")); fail(); } catch (RuntimeException ignore) { } assertEquals(1, ctConstructor.getBody().getStatements().size()); assertEquals("super()", ctConstructor.getBody().getStatement(0).toString()); }
@Test public void callParamConstructor() throws Exception { CtClass<Object> aClass = factory.Class().get(AClass.class); CtConstructor<Object> constructor = aClass.getConstructors().iterator().next(); assertEquals( "{" + System.lineSeparator() + " enclosingInstance.super();" + System.lineSeparator() + "}", constructor.getBody().toString()); }