package uk.co.badgersinfoil.metaas;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import uk.co.badgersinfoil.metaas.dom.ASBinaryExpression;
import uk.co.badgersinfoil.metaas.dom.ASBlock;
import uk.co.badgersinfoil.metaas.dom.ASBooleanLiteral;
import uk.co.badgersinfoil.metaas.dom.ASBreakStatement;
import uk.co.badgersinfoil.metaas.dom.ASCatchClause;
import uk.co.badgersinfoil.metaas.dom.ASClassType;
import uk.co.badgersinfoil.metaas.dom.ASCompilationUnit;
import uk.co.badgersinfoil.metaas.dom.ASContinueStatement;
import uk.co.badgersinfoil.metaas.dom.ASDeclarationStatement;
import uk.co.badgersinfoil.metaas.dom.ASDoWhileStatement;
import uk.co.badgersinfoil.metaas.dom.Expression;
import uk.co.badgersinfoil.metaas.dom.ASExpressionStatement;
import uk.co.badgersinfoil.metaas.dom.ASFieldAccessExpression;
import uk.co.badgersinfoil.metaas.dom.ASFinallyClause;
import uk.co.badgersinfoil.metaas.dom.ASForEachInStatement;
import uk.co.badgersinfoil.metaas.dom.ASForInStatement;
import uk.co.badgersinfoil.metaas.dom.ASForStatement;
import uk.co.badgersinfoil.metaas.dom.ASIfStatement;
import uk.co.badgersinfoil.metaas.dom.ASIntegerLiteral;
import uk.co.badgersinfoil.metaas.dom.ASInvocationExpression;
import uk.co.badgersinfoil.metaas.dom.ASMethod;
import uk.co.badgersinfoil.metaas.dom.ASNewExpression;
import uk.co.badgersinfoil.metaas.dom.ASPostfixExpression;
import uk.co.badgersinfoil.metaas.dom.ASReturnStatement;
import uk.co.badgersinfoil.metaas.dom.ASStringLiteral;
import uk.co.badgersinfoil.metaas.dom.ASSuperStatement;
import uk.co.badgersinfoil.metaas.dom.ASSwitchCase;
import uk.co.badgersinfoil.metaas.dom.ASSwitchDefault;
import uk.co.badgersinfoil.metaas.dom.ASSwitchStatement;
import uk.co.badgersinfoil.metaas.dom.ASThrowStatement;
import uk.co.badgersinfoil.metaas.dom.ASTryStatement;
import uk.co.badgersinfoil.metaas.dom.ASVarDeclarationFragment;
import uk.co.badgersinfoil.metaas.dom.ASWhileStatement;
import uk.co.badgersinfoil.metaas.dom.ASWithStatement;
import uk.co.badgersinfoil.metaas.dom.Statement;
import uk.co.badgersinfoil.metaas.dom.Visibility;
import junit.framework.TestCase;
public class StatementTests extends TestCase {
private ActionScriptFactory fact = new ActionScriptFactory();
private ASCompilationUnit unit;
private ASMethod meth;
private ASCompilationUnit reflect;
protected void setUp() {
unit = fact.newClass("Test");
ASClassType clazz = (ASClassType)unit.getType();
meth = clazz.newMethod("test", Visibility.PUBLIC, null);
reflect = null;
}
protected void tearDown() throws IOException {
if (reflect == null) {
reflect = assertReflection();
}
}
private ASCompilationUnit assertReflection() throws IOException {
return CodeMirror.assertReflection(fact, unit);
}
private void assertFirstReflectedStatementIsA(Class expectedClass) throws IOException {
reflect = assertReflection();
ASClassType clazz = (ASClassType)reflect.getType();
ASMethod meth = clazz.getMethod("test");
List statements = meth.getStatementList();
Object stmt = statements.get(0);
assertTrue("Expected instance of "+expectedClass.getName()+", got "+stmt.getClass().getName(),
expectedClass.isInstance(stmt));
}
public void testStatements() throws IOException {
meth.setDocComment("\n doc\n comment!\n");
}
public void testGenericStatement() {
meth.addStmt("a=1");
}
public void testExpressionStatement() throws IOException {
ASExpressionStatement exprStmt = meth.newExprStmt("go()");
assertEquals("go()", exprStmt.getExpressionString());
ExtraAssertions.assertInstanceof(exprStmt.getExpression(),
ASInvocationExpression.class);
exprStmt.setExpression("stop()");
assertEquals("stop()", exprStmt.getExpressionString());
assertFirstReflectedStatementIsA(ASExpressionStatement.class);
}
public void testIfStatement() {
ASIfStatement ifStmt = meth.newIf("a == b");
ifStmt.addStmt("trace('then true!')");
assertNull(ifStmt.getElseStatement());
ifStmt.elseBlock().addStmt("trace('else false!')");
assertEquals("a == b", ifStmt.getConditionString());
ifStmt.setCondition("b == a");
assertEquals("b == a", ifStmt.getConditionString());
ExtraAssertions.assertInstanceof(ifStmt.getCondition(),
ASBinaryExpression.class);
ifStmt.setCondition(fact.newBooleanLiteral(true));
assertTrue(((ASBooleanLiteral)ifStmt.getCondition()).getValue());
}
public void testParseIf() {
ASIfStatement ifStmt = (ASIfStatement)meth.addStmt("if (foo) blah();");
assertNotNull(ifStmt.getThenStatement());
ExtraAssertions.assertInstanceof(ifStmt.getThenStatement(), ASExpressionStatement.class);
try {
// no block in the 'if', so SyntaxException is expected,
ifStmt.getStatementList();
fail();
} catch (SyntaxException e) {
// expected
}
}
public void testParseIfElseIf() {
ASIfStatement ifStmt = (ASIfStatement)meth.addStmt("if (foo) {blah();} else if (bar) {other();}");
assertNotNull(ifStmt.getElseStatement());
ExtraAssertions.assertInstanceof(ifStmt.getElseStatement(), ASIfStatement.class);
try {
ifStmt.elseBlock();
fail("should not allow access to block from else-clause when else-cluase contains other stmt type");
} catch (SyntaxException e) {
// expected
}
}
public void testFor() {
ASForStatement forStmt = meth.newFor((String)null, null, null);
forStmt.addStmt("trace(\"forever\")");
assertNull(forStmt.getInitString());
assertNull(forStmt.getConditionString());
assertNull(forStmt.getUpdateString());
forStmt.setInit("var j");
forStmt.setCondition("j<10");
forStmt.setUpdate("j++");
assertEquals("var j", forStmt.getInitString());
assertEquals("j<10", forStmt.getConditionString());
assertEquals("j++", forStmt.getUpdateString());
ExtraAssertions.assertInstanceof(forStmt.getInit(), ASDeclarationStatement.class);
ExtraAssertions.assertInstanceof(forStmt.getCondition(), ASBinaryExpression.class);
ExtraAssertions.assertInstanceof(forStmt.getUpdate(), ASPostfixExpression.class);
forStmt = meth.newFor("const i", "i<10", "i++");
forStmt.addStmt("trace(i)");
assertEquals("const i", forStmt.getInitString());
assertEquals("i<10", forStmt.getConditionString());
assertEquals("i++", forStmt.getUpdateString());
forStmt.setInit(null);
forStmt.setCondition((String)null);
forStmt.setUpdate((String)null);
assertNull(forStmt.getInitString());
assertNull(forStmt.getConditionString());
assertNull(forStmt.getUpdateString());
forStmt.setInit("k=0");
assertEquals("k=0", forStmt.getInitString());
ExtraAssertions.assertInstanceof(forStmt.getInit(), Expression.class);
forStmt.setCondition(fact.newBooleanLiteral(true));
forStmt.setUpdate(fact.newExpression("++i"));
}
public void testForIn() {
ASForInStatement forInStmt = meth.newForIn("var i", "obj.arry");
forInStmt.addStmt("trace(i)");
assertEquals("var i", forInStmt.getVarString());
assertEquals("obj.arry", forInStmt.getIteratedString());
ExtraAssertions.assertInstanceof(forInStmt.getIterated(), ASFieldAccessExpression.class);
forInStmt.setVar("j");
forInStmt.setIterated("obj");
assertEquals("j", forInStmt.getVarString());
assertEquals("obj", forInStmt.getIteratedString());
forInStmt.setIterated(fact.newExpression("obj.blah"));
}
public void testForEachIn() {
ASForEachInStatement forEachInStmt = meth.newForEachIn("var i", "obj.arry");
forEachInStmt.addStmt("trace(i)");
assertEquals("var i", forEachInStmt.getVarString());
assertEquals("obj.arry", forEachInStmt.getIteratedString());
ExtraAssertions.assertInstanceof(forEachInStmt.getIterated(), ASFieldAccessExpression.class);
forEachInStmt.setVar("j");
forEachInStmt.setIterated("obj");
assertEquals("j", forEachInStmt.getVarString());
assertEquals("obj", forEachInStmt.getIteratedString());
forEachInStmt.setIterated(fact.newExpression("obj.blah"));
}
public void testWhile() {
ASWhileStatement whileStmt = meth.newWhile("test()");
whileStmt.addStmt("trace(result())");
assertEquals("test()", whileStmt.getConditionString());
whileStmt.setCondition("a == b");
assertEquals("a == b", whileStmt.getConditionString());
ExtraAssertions.assertInstanceof(whileStmt.getCondition(), ASBinaryExpression.class);
ExtraAssertions.assertInstanceof(whileStmt.getBody(), ASBlock.class);
}
public void testWhileCondition() {
Expression left = fact.newExpression("a");
Expression right = fact.newExpression("b");
ASWhileStatement whileStmt = meth.newWhile(fact.newAndExpression(left, right));
whileStmt.addStmt("trace(result())");
assertEquals("a && b", whileStmt.getConditionString());
whileStmt.setCondition(fact.newBooleanLiteral(true));
ExtraAssertions.assertInstanceof(whileStmt.getCondition(), ASBooleanLiteral.class);
}
public void testDoWhile() {
ASDoWhileStatement doWhileStmt = meth.newDoWhile("test()");
doWhileStmt.addStmt("trace(result())");
assertEquals("test()", doWhileStmt.getConditionString());
doWhileStmt.setCondition("a == b");
assertEquals("a == b", doWhileStmt.getConditionString());
ExtraAssertions.assertInstanceof(doWhileStmt.getCondition(), ASBinaryExpression.class);
doWhileStmt.setCondition(fact.newBooleanLiteral(true));
}
public void testSwitch() {
ASSwitchStatement swtch = meth.newSwitch("foo");
ASSwitchCase cas = swtch.newCase("1");
assertFalse("Empty case statement claims to contain code", cas.containsCode());
cas.addStmt("trace(1)");
assertEquals("1", cas.getLabelValueString());
ExtraAssertions.assertInstanceof(cas.getLabelValue(), ASIntegerLiteral.class);
cas.setLabelValue("2");
assertEquals("2", cas.getLabelValueString());
ASSwitchDefault def= swtch.newDefault();
def.addStmt("trace('default')");
List labels = swtch.getLabels();
ExtraAssertions.assertSize(2, labels);
ExtraAssertions.assertInstanceof(labels.get(0), ASSwitchCase.class);
ExtraAssertions.assertInstanceof(labels.get(1), ASSwitchDefault.class);
// condition tests,
assertNotNull(swtch.getCondition());
swtch.setCondition(fact.newIntegerLiteral(333));
assertTrue(swtch.getCondition() instanceof ASIntegerLiteral);
assertEquals(333, ((ASIntegerLiteral)swtch.getCondition()).getValue());
}
public void testWith() {
ASWithStatement with = meth.newWith("foo");
with.addStmt("trace(test)");
assertEquals("foo", with.getScopeString());
with.setScope("foo.bar");
assertEquals("foo.bar", with.getScopeString());
ExtraAssertions.assertInstanceof(with.getScope(), ASFieldAccessExpression.class);
with.setScope(fact.newExpression("bar.foo"));
ExtraAssertions.assertInstanceof(with.getScope(), ASFieldAccessExpression.class);
ExtraAssertions.assertInstanceof(with.getBody(), ASBlock.class);
}
public void testDeclaration() {
ASDeclarationStatement decl = meth.newDeclaration("a=1");
assertFalse(decl.isConstant());
decl.setConstant(false); // should not change the result
assertFalse(decl.isConstant());
assertEquals("a", decl.getFirstVarName());
assertNull(decl.getFirstVarTypeName());
ExtraAssertions.assertInstanceof(decl.getFirstVarInitializer(), ASIntegerLiteral.class);
decl.setConstant(true);
assertTrue(decl.isConstant());
List vars = decl.getVars();
ExtraAssertions.assertSize(1, vars);
ASVarDeclarationFragment var = (ASVarDeclarationFragment)vars.get(0);
assertEquals("a", var.getName());
assertNull(var.getTypeName());
ExtraAssertions.assertInstanceof(var.getInitializer(), ASIntegerLiteral.class);
}
public void testParseDeclaration() {
ASDeclarationStatement decl = (ASDeclarationStatement)meth.addStmt("var a=1, b:String='2'");
List vars = decl.getVars();
ExtraAssertions.assertSize(2, vars);
ASVarDeclarationFragment a = (ASVarDeclarationFragment)vars.get(0);
assertEquals("a", a.getName());
assertNull(a.getTypeName());
ExtraAssertions.assertInstanceof(a.getInitializer(), ASIntegerLiteral.class);
ASVarDeclarationFragment b = (ASVarDeclarationFragment)vars.get(1);
assertEquals("b", b.getName());
assertEquals("String", b.getTypeName());
ExtraAssertions.assertInstanceof(b.getInitializer(), ASStringLiteral.class);
}
public void testReturn() throws IOException {
ASReturnStatement returnStmt = meth.newReturn();
assertNull(returnStmt.getExpressionString());
returnStmt.setExpression("false");
assertEquals("false", returnStmt.getExpressionString());
ExtraAssertions.assertInstanceof(returnStmt.getExpression(), ASBooleanLiteral.class);
returnStmt.setExpression(fact.newIntegerLiteral(2));
ExtraAssertions.assertInstanceof(returnStmt.getExpression(), ASIntegerLiteral.class);
assertFirstReflectedStatementIsA(ASReturnStatement.class);
}
public void testReturnRemoveExpr() {
ASReturnStatement returnStmt = meth.newReturn("true");
assertEquals("true", returnStmt.getExpressionString());
returnStmt.setExpression((String)null);
assertNull(returnStmt.getExpressionString());
assertNull(returnStmt.getExpression());
// test removal when there's already nothing to remove,
returnStmt.setExpression((String)null);
}
public void testBlockEmpty() {
assertFalse(meth.containsCode());
meth.addComment(" a comment");
assertFalse(meth.containsCode());
meth.addStmt("return foo");
assertTrue(meth.containsCode());
}
public void testIfBlockReplace() {
ASIfStatement ifStmt = meth.newIf("foo");
ASBlock block = new ActionScriptFactory().newBlock();
ifStmt.setThen(block);
// TODO: find something to assert
}
public void testSuperStatementNoArg() {
ASSuperStatement stmt = meth.newSuper(Collections.EMPTY_LIST);
assertEquals(0, stmt.getArguments().size());
}
public void testSuperStatement() {
List args = Collections.singletonList(fact.newIntegerLiteral(1));
ASSuperStatement stmt = meth.newSuper(args);
assertEquals(1, stmt.getArguments().size());
Expression arg = (Expression)stmt.getArguments().get(0);
assertEquals(1, ((ASIntegerLiteral)arg).getValue());
}
public void testSuperStatementReplaceArgs() {
List args = Collections.singletonList(fact.newIntegerLiteral(1));
ASSuperStatement stmt = meth.newSuper(args);
args = new ArrayList();
args.add(fact.newIntegerLiteral(2));
args.add(fact.newStringLiteral("foo"));
stmt.setArguments(args);
assertEquals(2, stmt.getArguments().size());
}
public void testParseSuper() {
ASSuperStatement stmt = (ASSuperStatement)meth.addStmt("super()");
assertEquals(0, stmt.getArguments().size());
}
public void testParseBlock() {
ASBlock stmt = (ASBlock)meth.addStmt("{ }");
}
public void testBreak() {
Statement brk = meth.addStmt("break");
ExtraAssertions.assertInstanceof(brk, ASBreakStatement.class);
meth.newBreak();
}
public void testTryCatch() {
ASTryStatement tryStmt = meth.newTryCatch("e", "Exception");
tryStmt.addStmt("trace('trying')");
List catches = tryStmt.getCatchClauses();
ExtraAssertions.assertSize(1, catches);
assertEquals(1, catches.size());
ASCatchClause eCatch = (ASCatchClause)catches.get(0);
eCatch.addStmt("trace('catching e')");
assertEquals("e", eCatch.getParamName());
assertEquals("Exception", eCatch.getTypeName());
assertNull(tryStmt.getFinallyClause());
ASCatchClause fCatch = tryStmt.newCatchClause("f", "Error");
fCatch.addStmt("trace('catching f')");
}
public void testTryFinally() {
ASTryStatement tryStmt = meth.newTryFinally();
ASFinallyClause finallyClause = tryStmt.getFinallyClause();
assertNotNull(finallyClause);
assertFalse(finallyClause.containsCode());
finallyClause.addStmt("trace('hello')");
assertTrue(finallyClause.containsCode());
try {
finallyClause = tryStmt.newFinallyClause();
fail("shouldn't be able to add another finally-clause");
} catch (SyntaxException e) {
// expected
}
}
public void testParseTrayCatchFinally() {
ASTryStatement tryStmt = (ASTryStatement)meth.addStmt("try {" +
"} catch (e) {" +
"} catch (f:Exception) {" +
"} finally {" +
"}");
List catches = tryStmt.getCatchClauses();
ExtraAssertions.assertSize(2, catches);
ASCatchClause catch0 = (ASCatchClause)catches.get(0);
assertEquals("e", catch0.getParamName());
assertNull(catch0.getTypeName());
ASCatchClause catch1 = (ASCatchClause)catches.get(1);
assertEquals("f", catch1.getParamName());
assertEquals("Exception", catch1.getTypeName());
assertNotNull(tryStmt.getFinallyClause());
}
public void testContinue() {
ASContinueStatement continueStmt = meth.newContinue();
assertNotNull(continueStmt);
ExtraAssertions.assertInstanceof(meth.addStmt("continue"), ASContinueStatement.class);
}
public void testThrow() {
Expression t = fact.newExpression("new Error()");
ASThrowStatement throwStmt = meth.newThrow(t);
ExtraAssertions.assertInstanceof(throwStmt.getExpression(), ASNewExpression.class);
}
public void testParseThrow() {
ASThrowStatement throwStmt = (ASThrowStatement)meth.addStmt("throw \"oops\"");
ExtraAssertions.assertInstanceof(throwStmt.getExpression(), ASStringLiteral.class);
}
}