use of com.google.devtools.j2objc.ast.Statement in project j2objc by google.
the class StatementGenerator method printStatements.
private void printStatements(List<?> statements) {
for (Iterator<?> it = statements.iterator(); it.hasNext(); ) {
Statement s = (Statement) it.next();
s.accept(this);
}
}
use of com.google.devtools.j2objc.ast.Statement in project j2objc by google.
the class AnnotationRewriter method addConstructor.
private void addConstructor(AnnotationTypeDeclaration node, Map<ExecutableElement, VariableElement> fieldElements) {
TypeElement type = node.getTypeElement();
String typeName = nameTable.getFullName(type);
FunctionDeclaration constructorDecl = new FunctionDeclaration("create_" + typeName, type.asType());
Block constructorBody = new Block();
constructorDecl.setBody(constructorBody);
List<Statement> stmts = constructorBody.getStatements();
stmts.add(new NativeStatement(UnicodeUtils.format("%s *self = AUTORELEASE([[%s alloc] init]);", typeName, typeName)));
for (ExecutableElement memberElement : ElementUtil.getSortedAnnotationMembers(type)) {
TypeMirror memberType = memberElement.getReturnType();
String propName = NameTable.getAnnotationPropertyName(memberElement);
String fieldName = nameTable.getVariableShortName(fieldElements.get(memberElement));
VariableElement param = GeneratedVariableElement.newParameter(propName, memberType, null);
constructorDecl.addParameter(new SingleVariableDeclaration(param));
String paramName = nameTable.getVariableShortName(param);
String rhs = TypeUtil.isReferenceType(memberType) ? "RETAIN_(" + paramName + ")" : paramName;
stmts.add(new NativeStatement("self->" + fieldName + " = " + rhs + ";"));
}
stmts.add(new NativeStatement("return self;"));
node.addBodyDeclaration(constructorDecl);
}
use of com.google.devtools.j2objc.ast.Statement in project j2objc by google.
the class Rewriter method visit.
@Override
public boolean visit(TryStatement node) {
// This visit rewrites try-with-resources constructs into regular try statements according to
// JLS 14.20.3. The rewriting is done in a visit instead of endVisit because the mutations may
// result in more try-with-resources constructs that need to be rewritten recursively.
List<TreeNode> resources = node.getResources();
if (resources.isEmpty()) {
return true;
}
if (!node.getCatchClauses().isEmpty() || node.getFinally() != null) {
// Extended try-with-resources. (JLS 14.20.3.2)
// The new innerTry statement will be a "Basic try-with-resources" and will be rewritten by
// the code below when it is visited.
TryStatement innerTry = new TryStatement().setBody(TreeUtil.remove(node.getBody()));
;
TreeUtil.moveList(resources, innerTry.getResources());
node.setBody(new Block().addStatement(innerTry));
return true;
}
// Basic try-with-resources. (JLS 14.20.3.1)
DeclaredType throwableType = (DeclaredType) typeUtil.getJavaThrowable().asType();
VariableElement primaryException = GeneratedVariableElement.newLocalVar("__primaryException" + resources.size(), throwableType, null);
TreeNode resource = resources.remove(0);
VariableElement resourceVar = null;
VariableDeclarationFragment resourceFrag = null;
if (resource.getKind() == Kind.VARIABLE_DECLARATION_EXPRESSION) {
List<VariableDeclarationFragment> resourceFrags = ((VariableDeclarationExpression) resource).getFragments();
assert resourceFrags.size() == 1;
resourceFrag = resourceFrags.get(0);
resourceVar = resourceFrag.getVariableElement();
} else {
resourceVar = TreeUtil.getVariableElement((Expression) resource);
}
assert resourceVar != null;
DeclaredType closeableType = typeUtil.findSupertype(resourceVar.asType(), "java.lang.AutoCloseable");
ExecutablePair closeMethod = typeUtil.findMethod(closeableType, "close");
ExecutablePair addSuppressedMethod = typeUtil.findMethod(throwableType, "addSuppressed", "java.lang.Throwable");
Block block = new Block();
if (resourceFrag != null) {
block.addStatement(new VariableDeclarationStatement(resourceVar, TreeUtil.remove(resourceFrag.getInitializer())));
}
block.addStatement(new VariableDeclarationStatement(primaryException, new NullLiteral(typeUtil.getNull())));
// If the current try node is the only statement in its parent block then replace the parent
// block instead of the try node to avoid extra nesting of braces.
TreeNode parent = node.getParent();
if (parent instanceof Block && ((Block) parent).getStatements().size() == 1) {
parent.replaceWith(block);
} else {
node.replaceWith(block);
}
block.addStatement(TreeUtil.remove(node));
VariableElement caughtException = GeneratedVariableElement.newLocalVar("e", throwableType, null);
Block catchBlock = new Block().addStatement(new ExpressionStatement(new Assignment(new SimpleName(primaryException), new SimpleName(caughtException)))).addStatement(new ThrowStatement(new SimpleName(caughtException)));
node.addCatchClause(new CatchClause().setException(new SingleVariableDeclaration(caughtException)).setBody(catchBlock));
Statement closeResource = new ExpressionStatement(new MethodInvocation(closeMethod, typeUtil.getVoid(), new SimpleName(resourceVar)));
VariableElement suppressedException = GeneratedVariableElement.newLocalVar("e", throwableType, null);
node.setFinally(new Block().addStatement(new IfStatement().setExpression(new InfixExpression(typeUtil.getBoolean(), InfixExpression.Operator.NOT_EQUALS, new SimpleName(resourceVar), new NullLiteral(typeUtil.getNull()))).setThenStatement(new Block().addStatement(new IfStatement().setExpression(new InfixExpression(typeUtil.getBoolean(), InfixExpression.Operator.NOT_EQUALS, new SimpleName(primaryException), new NullLiteral(typeUtil.getNull()))).setThenStatement(new Block().addStatement(new TryStatement().setBody(new Block().addStatement(closeResource)).addCatchClause(new CatchClause().setException(new SingleVariableDeclaration(suppressedException)).setBody(new Block().addStatement(new ExpressionStatement(new MethodInvocation(addSuppressedMethod, typeUtil.getVoid(), new SimpleName(primaryException)).addArgument(new SimpleName(suppressedException)))))))).setElseStatement(new Block().addStatement(closeResource.copy()))))));
// Visit the new block instead of the current node because some of content of the node (eg. the
// resource initializer) has been moved outside of the try node.
block.accept(this);
return false;
}
use of com.google.devtools.j2objc.ast.Statement in project j2objc by google.
the class Functionizer method setFunctionCaller.
/**
* Replace method block statements with single statement that invokes function.
*/
private void setFunctionCaller(MethodDeclaration method, ExecutableElement methodElement) {
TypeMirror returnType = methodElement.getReturnType();
TypeElement declaringClass = ElementUtil.getDeclaringClass(methodElement);
Block body = new Block();
method.setBody(body);
method.removeModifiers(Modifier.NATIVE);
List<Statement> stmts = body.getStatements();
FunctionInvocation invocation = new FunctionInvocation(newFunctionElement(methodElement), returnType);
List<Expression> args = invocation.getArguments();
if (!ElementUtil.isStatic(methodElement)) {
args.add(new ThisExpression(declaringClass.asType()));
}
for (SingleVariableDeclaration param : method.getParameters()) {
args.add(new SimpleName(param.getVariableElement()));
}
if (TypeUtil.isVoid(returnType)) {
stmts.add(new ExpressionStatement(invocation));
if (ElementUtil.isConstructor(methodElement)) {
stmts.add(new ReturnStatement(new ThisExpression(declaringClass.asType())));
}
} else {
stmts.add(new ReturnStatement(invocation));
}
}
use of com.google.devtools.j2objc.ast.Statement in project j2objc by google.
the class InitializationNormalizer method isDesignatedConstructor.
/**
* Returns true if this is a constructor that doesn't call "this(...)". This constructors are
* skipped so initializers aren't run more than once per instance creation.
*/
public static boolean isDesignatedConstructor(MethodDeclaration node) {
if (!node.isConstructor()) {
return false;
}
Block body = node.getBody();
if (body == null) {
return false;
}
List<Statement> stmts = body.getStatements();
return (stmts.isEmpty() || !(stmts.get(0) instanceof ConstructorInvocation));
}
Aggregations