You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
525 lines
13 KiB
525 lines
13 KiB
/* |
|
* 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" |
|
|
|
using std::vector; |
|
using std::string; |
|
|
|
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::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->JavaType().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::WriteDeclaration(CodeWriter* to) const { |
|
string dim; |
|
for (int i = 0; i < this->dimension; i++) { |
|
dim += "[]"; |
|
} |
|
to->Write("%s%s %s", this->type->JavaType().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->JavaType().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->JavaType().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->JavaType().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->JavaType().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->JavaType().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->JavaType().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::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->JavaType().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]->JavaType().c_str()); |
|
} |
|
|
|
if (this->statements == NULL) { |
|
to->Write(";\n"); |
|
} else { |
|
to->Write("\n"); |
|
this->statements->Write(to); |
|
} |
|
} |
|
|
|
void IntConstant::Write(CodeWriter* to) const { |
|
WriteModifiers(to, STATIC | FINAL | PUBLIC, ALL_MODIFIERS); |
|
to->Write("int %s = %d;\n", name.c_str(), value); |
|
} |
|
|
|
void StringConstant::Write(CodeWriter* to) const { |
|
WriteModifiers(to, STATIC | FINAL | PUBLIC, ALL_MODIFIERS); |
|
to->Write("String %s = %s;\n", name.c_str(), value.c_str()); |
|
} |
|
|
|
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->JavaType(); |
|
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->JavaType().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]->JavaType().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; |
|
} |
|
|
|
Document::Document(const std::string& comment, |
|
const std::string& package, |
|
const std::string& original_src, |
|
std::unique_ptr<Class> clazz) |
|
: comment_(comment), |
|
package_(package), |
|
original_src_(original_src), |
|
clazz_(std::move(clazz)) { |
|
} |
|
|
|
void Document::Write(CodeWriter* to) const { |
|
if (!comment_.empty()) { |
|
to->Write("%s\n", comment_.c_str()); |
|
} |
|
to->Write( |
|
"/*\n" |
|
" * This file is auto-generated. DO NOT MODIFY.\n" |
|
" * Original file: %s\n" |
|
" */\n", |
|
escape_backslashes(original_src_).c_str()); |
|
if (!package_.empty()) { |
|
to->Write("package %s;\n", package_.c_str()); |
|
} |
|
|
|
if (clazz_) { |
|
clazz_->Write(to); |
|
} |
|
} |
|
|
|
} // namespace java |
|
} // namespace aidl |
|
} // namespace android
|
|
|