blob: aac691e45bc144c3693cf79e6cedb9a5247b315f [file] [log] [blame]
/*
* Copyright (C) 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ast_java.h"
#include "code_writer.h"
#include "type_java.h"
namespace android {
namespace aidl {
namespace java {
void
WriteModifiers(CodeWriter* to, int mod, int mask)
{
int m = mod & mask;
if (m & OVERRIDE) {
to->Write("@Override ");
}
if ((m & SCOPE_MASK) == PUBLIC) {
to->Write("public ");
}
else if ((m & SCOPE_MASK) == PRIVATE) {
to->Write("private ");
}
else if ((m & SCOPE_MASK) == PROTECTED) {
to->Write("protected ");
}
if (m & STATIC) {
to->Write("static ");
}
if (m & FINAL) {
to->Write("final ");
}
if (m & ABSTRACT) {
to->Write("abstract ");
}
}
void
WriteArgumentList(CodeWriter* to, const vector<Expression*>& arguments)
{
size_t N = arguments.size();
for (size_t i=0; i<N; i++) {
arguments[i]->Write(to);
if (i != N-1) {
to->Write(", ");
}
}
}
Field::Field(int m, Variable* v)
:ClassElement(),
modifiers(m),
variable(v)
{
}
void
Field::GatherTypes(set<const Type*>* types) const
{
types->insert(this->variable->type);
}
void
Field::Write(CodeWriter* to) const
{
if (this->comment.length() != 0) {
to->Write("%s\n", this->comment.c_str());
}
WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | FINAL | OVERRIDE);
to->Write("%s %s", this->variable->type->QualifiedName().c_str(),
this->variable->name.c_str());
if (this->value.length() != 0) {
to->Write(" = %s", this->value.c_str());
}
to->Write(";\n");
}
LiteralExpression::LiteralExpression(const string& v)
:value(v)
{
}
void
LiteralExpression::Write(CodeWriter* to) const
{
to->Write("%s", this->value.c_str());
}
StringLiteralExpression::StringLiteralExpression(const string& v)
:value(v)
{
}
void
StringLiteralExpression::Write(CodeWriter* to) const
{
to->Write("\"%s\"", this->value.c_str());
}
Variable::Variable(const Type* t, const string& n)
:type(t),
name(n),
dimension(0)
{
}
Variable::Variable(const Type* t, const string& n, int d)
:type(t),
name(n),
dimension(d)
{
}
void
Variable::GatherTypes(set<const Type*>* types) const
{
types->insert(this->type);
}
void
Variable::WriteDeclaration(CodeWriter* to) const
{
string dim;
for (int i=0; i<this->dimension; i++) {
dim += "[]";
}
to->Write("%s%s %s", this->type->QualifiedName().c_str(), dim.c_str(),
this->name.c_str());
}
void
Variable::Write(CodeWriter* to) const
{
to->Write("%s", name.c_str());
}
FieldVariable::FieldVariable(Expression* o, const string& n)
:object(o),
clazz(NULL),
name(n)
{
}
FieldVariable::FieldVariable(const Type* c, const string& n)
:object(NULL),
clazz(c),
name(n)
{
}
void
FieldVariable::Write(CodeWriter* to) const
{
if (this->object != NULL) {
this->object->Write(to);
}
else if (this->clazz != NULL) {
to->Write("%s", this->clazz->QualifiedName().c_str());
}
to->Write(".%s", name.c_str());
}
void
StatementBlock::Write(CodeWriter* to) const
{
to->Write("{\n");
int N = this->statements.size();
for (int i=0; i<N; i++) {
this->statements[i]->Write(to);
}
to->Write("}\n");
}
void
StatementBlock::Add(Statement* statement)
{
this->statements.push_back(statement);
}
void
StatementBlock::Add(Expression* expression)
{
this->statements.push_back(new ExpressionStatement(expression));
}
ExpressionStatement::ExpressionStatement(Expression* e)
:expression(e)
{
}
void
ExpressionStatement::Write(CodeWriter* to) const
{
this->expression->Write(to);
to->Write(";\n");
}
Assignment::Assignment(Variable* l, Expression* r)
:lvalue(l),
rvalue(r),
cast(NULL)
{
}
Assignment::Assignment(Variable* l, Expression* r, const Type* c)
:lvalue(l),
rvalue(r),
cast(c)
{
}
void
Assignment::Write(CodeWriter* to) const
{
this->lvalue->Write(to);
to->Write(" = ");
if (this->cast != NULL) {
to->Write("(%s)", this->cast->QualifiedName().c_str());
}
this->rvalue->Write(to);
}
MethodCall::MethodCall(const string& n)
: name(n)
{
}
MethodCall::MethodCall(const string& n, int argc = 0, ...)
:name(n)
{
va_list args;
va_start(args, argc);
init(argc, args);
va_end(args);
}
MethodCall::MethodCall(Expression* o, const string& n)
:obj(o),
name(n)
{
}
MethodCall::MethodCall(const Type* t, const string& n)
:clazz(t),
name(n)
{
}
MethodCall::MethodCall(Expression* o, const string& n, int argc = 0, ...)
:obj(o),
name(n)
{
va_list args;
va_start(args, argc);
init(argc, args);
va_end(args);
}
MethodCall::MethodCall(const Type* t, const string& n, int argc = 0, ...)
:clazz(t),
name(n)
{
va_list args;
va_start(args, argc);
init(argc, args);
va_end(args);
}
void
MethodCall::init(int n, va_list args)
{
for (int i=0; i<n; i++) {
Expression* expression = (Expression*)va_arg(args, void*);
this->arguments.push_back(expression);
}
}
void
MethodCall::Write(CodeWriter* to) const
{
if (this->obj != NULL) {
this->obj->Write(to);
to->Write(".");
}
else if (this->clazz != NULL) {
to->Write("%s.", this->clazz->QualifiedName().c_str());
}
to->Write("%s(", this->name.c_str());
WriteArgumentList(to, this->arguments);
to->Write(")");
}
Comparison::Comparison(Expression* l, const string& o, Expression* r)
:lvalue(l),
op(o),
rvalue(r)
{
}
void
Comparison::Write(CodeWriter* to) const
{
to->Write("(");
this->lvalue->Write(to);
to->Write("%s", this->op.c_str());
this->rvalue->Write(to);
to->Write(")");
}
NewExpression::NewExpression(const Type* t)
:type(t)
{
}
NewExpression::NewExpression(const Type* t, int argc = 0, ...)
:type(t)
{
va_list args;
va_start(args, argc);
init(argc, args);
va_end(args);
}
void
NewExpression::init(int n, va_list args)
{
for (int i=0; i<n; i++) {
Expression* expression = (Expression*)va_arg(args, void*);
this->arguments.push_back(expression);
}
}
void
NewExpression::Write(CodeWriter* to) const
{
to->Write("new %s(", this->type->InstantiableName().c_str());
WriteArgumentList(to, this->arguments);
to->Write(")");
}
NewArrayExpression::NewArrayExpression(const Type* t, Expression* s)
:type(t),
size(s)
{
}
void
NewArrayExpression::Write(CodeWriter* to) const
{
to->Write("new %s[", this->type->QualifiedName().c_str());
size->Write(to);
to->Write("]");
}
Ternary::Ternary(Expression* a, Expression* b, Expression* c)
:condition(a),
ifpart(b),
elsepart(c)
{
}
void
Ternary::Write(CodeWriter* to) const
{
to->Write("((");
this->condition->Write(to);
to->Write(")?(");
this->ifpart->Write(to);
to->Write("):(");
this->elsepart->Write(to);
to->Write("))");
}
Cast::Cast(const Type* t, Expression* e)
:type(t),
expression(e)
{
}
void
Cast::Write(CodeWriter* to) const
{
to->Write("((%s)", this->type->QualifiedName().c_str());
expression->Write(to);
to->Write(")");
}
VariableDeclaration::VariableDeclaration(Variable* l, Expression* r, const Type* c)
:lvalue(l),
cast(c),
rvalue(r)
{
}
VariableDeclaration::VariableDeclaration(Variable* l)
:lvalue(l)
{
}
void
VariableDeclaration::Write(CodeWriter* to) const
{
this->lvalue->WriteDeclaration(to);
if (this->rvalue != NULL) {
to->Write(" = ");
if (this->cast != NULL) {
to->Write("(%s)", this->cast->QualifiedName().c_str());
}
this->rvalue->Write(to);
}
to->Write(";\n");
}
void
IfStatement::Write(CodeWriter* to) const
{
if (this->expression != NULL) {
to->Write("if (");
this->expression->Write(to);
to->Write(") ");
}
this->statements->Write(to);
if (this->elseif != NULL) {
to->Write("else ");
this->elseif->Write(to);
}
}
ReturnStatement::ReturnStatement(Expression* e)
:expression(e)
{
}
void
ReturnStatement::Write(CodeWriter* to) const
{
to->Write("return ");
this->expression->Write(to);
to->Write(";\n");
}
void
TryStatement::Write(CodeWriter* to) const
{
to->Write("try ");
this->statements->Write(to);
}
CatchStatement::CatchStatement(Variable* e)
:statements(new StatementBlock),
exception(e)
{
}
void
CatchStatement::Write(CodeWriter* to) const
{
to->Write("catch ");
if (this->exception != NULL) {
to->Write("(");
this->exception->WriteDeclaration(to);
to->Write(") ");
}
this->statements->Write(to);
}
void
FinallyStatement::Write(CodeWriter* to) const
{
to->Write("finally ");
this->statements->Write(to);
}
Case::Case(const string& c)
{
cases.push_back(c);
}
void
Case::Write(CodeWriter* to) const
{
int N = this->cases.size();
if (N > 0) {
for (int i=0; i<N; i++) {
string s = this->cases[i];
if (s.length() != 0) {
to->Write("case %s:\n", s.c_str());
} else {
to->Write("default:\n");
}
}
} else {
to->Write("default:\n");
}
statements->Write(to);
}
SwitchStatement::SwitchStatement(Expression* e)
:expression(e)
{
}
void
SwitchStatement::Write(CodeWriter* to) const
{
to->Write("switch (");
this->expression->Write(to);
to->Write(")\n{\n");
int N = this->cases.size();
for (int i=0; i<N; i++) {
this->cases[i]->Write(to);
}
to->Write("}\n");
}
void
Break::Write(CodeWriter* to) const
{
to->Write("break;\n");
}
void
Method::GatherTypes(set<const Type*>* types) const
{
size_t N, i;
if (this->returnType) {
types->insert(this->returnType);
}
N = this->parameters.size();
for (i=0; i<N; i++) {
this->parameters[i]->GatherTypes(types);
}
N = this->exceptions.size();
for (i=0; i<N; i++) {
types->insert(this->exceptions[i]);
}
}
void
Method::Write(CodeWriter* to) const
{
size_t N, i;
if (this->comment.length() != 0) {
to->Write("%s\n", this->comment.c_str());
}
WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | ABSTRACT | FINAL | OVERRIDE);
if (this->returnType != NULL) {
string dim;
for (i=0; i<this->returnTypeDimension; i++) {
dim += "[]";
}
to->Write("%s%s ", this->returnType->QualifiedName().c_str(),
dim.c_str());
}
to->Write("%s(", this->name.c_str());
N = this->parameters.size();
for (i=0; i<N; i++) {
this->parameters[i]->WriteDeclaration(to);
if (i != N-1) {
to->Write(", ");
}
}
to->Write(")");
N = this->exceptions.size();
for (i=0; i<N; i++) {
if (i == 0) {
to->Write(" throws ");
} else {
to->Write(", ");
}
to->Write("%s", this->exceptions[i]->QualifiedName().c_str());
}
if (this->statements == NULL) {
to->Write(";\n");
} else {
to->Write("\n");
this->statements->Write(to);
}
}
void
Class::GatherTypes(set<const Type*>* types) const
{
int N, i;
types->insert(this->type);
if (this->extends != NULL) {
types->insert(this->extends);
}
N = this->interfaces.size();
for (i=0; i<N; i++) {
types->insert(this->interfaces[i]);
}
N = this->elements.size();
for (i=0; i<N; i++) {
this->elements[i]->GatherTypes(types);
}
}
void
Class::Write(CodeWriter* to) const
{
size_t N, i;
if (this->comment.length() != 0) {
to->Write("%s\n", this->comment.c_str());
}
WriteModifiers(to, this->modifiers, ALL_MODIFIERS);
if (this->what == Class::CLASS) {
to->Write("class ");
} else {
to->Write("interface ");
}
string name = this->type->Name();
size_t pos = name.rfind('.');
if (pos != string::npos) {
name = name.c_str() + pos + 1;
}
to->Write("%s", name.c_str());
if (this->extends != NULL) {
to->Write(" extends %s", this->extends->QualifiedName().c_str());
}
N = this->interfaces.size();
if (N != 0) {
if (this->what == Class::CLASS) {
to->Write(" implements");
} else {
to->Write(" extends");
}
for (i=0; i<N; i++) {
to->Write(" %s", this->interfaces[i]->QualifiedName().c_str());
}
}
to->Write("\n");
to->Write("{\n");
N = this->elements.size();
for (i=0; i<N; i++) {
this->elements[i]->Write(to);
}
to->Write("}\n");
}
static string
escape_backslashes(const string& str)
{
string result;
const size_t I=str.length();
for (size_t i=0; i<I; i++) {
char c = str[i];
if (c == '\\') {
result += "\\\\";
} else {
result += c;
}
}
return result;
}
void
Document::Write(CodeWriter* to) const
{
size_t N, i;
if (this->comment.length() != 0) {
to->Write("%s\n", this->comment.c_str());
}
to->Write("/*\n"
" * This file is auto-generated. DO NOT MODIFY.\n"
" * Original file: %s\n"
" */\n", escape_backslashes(this->originalSrc).c_str());
if (this->package.length() != 0) {
to->Write("package %s;\n", this->package.c_str());
}
N = this->classes.size();
for (i=0; i<N; i++) {
Class* c = this->classes[i];
c->Write(to);
}
}
} // namespace java
} // namespace aidl
} // namespace android