1/*
2 * Copyright (C) 2015, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "ast_java.h"
18
19#include "code_writer.h"
20#include "type_java.h"
21
22using std::vector;
23using std::string;
24
25namespace android {
26namespace aidl {
27namespace java {
28
29void WriteModifiers(CodeWriter* to, int mod, int mask) {
30  int m = mod & mask;
31
32  if (m & OVERRIDE) {
33    to->Write("@Override ");
34  }
35
36  if ((m & SCOPE_MASK) == PUBLIC) {
37    to->Write("public ");
38  } else if ((m & SCOPE_MASK) == PRIVATE) {
39    to->Write("private ");
40  } else if ((m & SCOPE_MASK) == PROTECTED) {
41    to->Write("protected ");
42  }
43
44  if (m & STATIC) {
45    to->Write("static ");
46  }
47
48  if (m & FINAL) {
49    to->Write("final ");
50  }
51
52  if (m & ABSTRACT) {
53    to->Write("abstract ");
54  }
55}
56
57void WriteArgumentList(CodeWriter* to, const vector<Expression*>& arguments) {
58  size_t N = arguments.size();
59  for (size_t i = 0; i < N; i++) {
60    arguments[i]->Write(to);
61    if (i != N - 1) {
62      to->Write(", ");
63    }
64  }
65}
66
67Field::Field(int m, Variable* v) : ClassElement(), modifiers(m), variable(v) {}
68
69void Field::Write(CodeWriter* to) const {
70  if (this->comment.length() != 0) {
71    to->Write("%s\n", this->comment.c_str());
72  }
73  WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | FINAL | OVERRIDE);
74  to->Write("%s %s", this->variable->type->JavaType().c_str(),
75            this->variable->name.c_str());
76  if (this->value.length() != 0) {
77    to->Write(" = %s", this->value.c_str());
78  }
79  to->Write(";\n");
80}
81
82LiteralExpression::LiteralExpression(const string& v) : value(v) {}
83
84void LiteralExpression::Write(CodeWriter* to) const {
85  to->Write("%s", this->value.c_str());
86}
87
88StringLiteralExpression::StringLiteralExpression(const string& v) : value(v) {}
89
90void StringLiteralExpression::Write(CodeWriter* to) const {
91  to->Write("\"%s\"", this->value.c_str());
92}
93
94Variable::Variable(const Type* t, const string& n)
95    : type(t), name(n), dimension(0) {}
96
97Variable::Variable(const Type* t, const string& n, int d)
98    : type(t), name(n), dimension(d) {}
99
100void Variable::WriteDeclaration(CodeWriter* to) const {
101  string dim;
102  for (int i = 0; i < this->dimension; i++) {
103    dim += "[]";
104  }
105  to->Write("%s%s %s", this->type->JavaType().c_str(), dim.c_str(),
106            this->name.c_str());
107}
108
109void Variable::Write(CodeWriter* to) const { to->Write("%s", name.c_str()); }
110
111FieldVariable::FieldVariable(Expression* o, const string& n)
112    : object(o), clazz(NULL), name(n) {}
113
114FieldVariable::FieldVariable(const Type* c, const string& n)
115    : object(NULL), clazz(c), name(n) {}
116
117void FieldVariable::Write(CodeWriter* to) const {
118  if (this->object != NULL) {
119    this->object->Write(to);
120  } else if (this->clazz != NULL) {
121    to->Write("%s", this->clazz->JavaType().c_str());
122  }
123  to->Write(".%s", name.c_str());
124}
125
126void StatementBlock::Write(CodeWriter* to) const {
127  to->Write("{\n");
128  int N = this->statements.size();
129  for (int i = 0; i < N; i++) {
130    this->statements[i]->Write(to);
131  }
132  to->Write("}\n");
133}
134
135void StatementBlock::Add(Statement* statement) {
136  this->statements.push_back(statement);
137}
138
139void StatementBlock::Add(Expression* expression) {
140  this->statements.push_back(new ExpressionStatement(expression));
141}
142
143ExpressionStatement::ExpressionStatement(Expression* e) : expression(e) {}
144
145void ExpressionStatement::Write(CodeWriter* to) const {
146  this->expression->Write(to);
147  to->Write(";\n");
148}
149
150Assignment::Assignment(Variable* l, Expression* r)
151    : lvalue(l), rvalue(r), cast(NULL) {}
152
153Assignment::Assignment(Variable* l, Expression* r, const Type* c)
154    : lvalue(l), rvalue(r), cast(c) {}
155
156void Assignment::Write(CodeWriter* to) const {
157  this->lvalue->Write(to);
158  to->Write(" = ");
159  if (this->cast != NULL) {
160    to->Write("(%s)", this->cast->JavaType().c_str());
161  }
162  this->rvalue->Write(to);
163}
164
165MethodCall::MethodCall(const string& n) : name(n) {}
166
167MethodCall::MethodCall(const string& n, int argc = 0, ...) : name(n) {
168  va_list args;
169  va_start(args, argc);
170  init(argc, args);
171  va_end(args);
172}
173
174MethodCall::MethodCall(Expression* o, const string& n) : obj(o), name(n) {}
175
176MethodCall::MethodCall(const Type* t, const string& n) : clazz(t), name(n) {}
177
178MethodCall::MethodCall(Expression* o, const string& n, int argc = 0, ...)
179    : obj(o), name(n) {
180  va_list args;
181  va_start(args, argc);
182  init(argc, args);
183  va_end(args);
184}
185
186MethodCall::MethodCall(const Type* t, const string& n, int argc = 0, ...)
187    : clazz(t), name(n) {
188  va_list args;
189  va_start(args, argc);
190  init(argc, args);
191  va_end(args);
192}
193
194void MethodCall::init(int n, va_list args) {
195  for (int i = 0; i < n; i++) {
196    Expression* expression = (Expression*)va_arg(args, void*);
197    this->arguments.push_back(expression);
198  }
199}
200
201void MethodCall::Write(CodeWriter* to) const {
202  if (this->obj != NULL) {
203    this->obj->Write(to);
204    to->Write(".");
205  } else if (this->clazz != NULL) {
206    to->Write("%s.", this->clazz->JavaType().c_str());
207  }
208  to->Write("%s(", this->name.c_str());
209  WriteArgumentList(to, this->arguments);
210  to->Write(")");
211}
212
213Comparison::Comparison(Expression* l, const string& o, Expression* r)
214    : lvalue(l), op(o), rvalue(r) {}
215
216void Comparison::Write(CodeWriter* to) const {
217  to->Write("(");
218  this->lvalue->Write(to);
219  to->Write("%s", this->op.c_str());
220  this->rvalue->Write(to);
221  to->Write(")");
222}
223
224NewExpression::NewExpression(const Type* t) : type(t) {}
225
226NewExpression::NewExpression(const Type* t, int argc = 0, ...) : type(t) {
227  va_list args;
228  va_start(args, argc);
229  init(argc, args);
230  va_end(args);
231}
232
233void NewExpression::init(int n, va_list args) {
234  for (int i = 0; i < n; i++) {
235    Expression* expression = (Expression*)va_arg(args, void*);
236    this->arguments.push_back(expression);
237  }
238}
239
240void NewExpression::Write(CodeWriter* to) const {
241  to->Write("new %s(", this->type->InstantiableName().c_str());
242  WriteArgumentList(to, this->arguments);
243  to->Write(")");
244}
245
246NewArrayExpression::NewArrayExpression(const Type* t, Expression* s)
247    : type(t), size(s) {}
248
249void NewArrayExpression::Write(CodeWriter* to) const {
250  to->Write("new %s[", this->type->JavaType().c_str());
251  size->Write(to);
252  to->Write("]");
253}
254
255Ternary::Ternary(Expression* a, Expression* b, Expression* c)
256    : condition(a), ifpart(b), elsepart(c) {}
257
258void Ternary::Write(CodeWriter* to) const {
259  to->Write("((");
260  this->condition->Write(to);
261  to->Write(")?(");
262  this->ifpart->Write(to);
263  to->Write("):(");
264  this->elsepart->Write(to);
265  to->Write("))");
266}
267
268Cast::Cast(const Type* t, Expression* e) : type(t), expression(e) {}
269
270void Cast::Write(CodeWriter* to) const {
271  to->Write("((%s)", this->type->JavaType().c_str());
272  expression->Write(to);
273  to->Write(")");
274}
275
276VariableDeclaration::VariableDeclaration(Variable* l, Expression* r,
277                                         const Type* c)
278    : lvalue(l), cast(c), rvalue(r) {}
279
280VariableDeclaration::VariableDeclaration(Variable* l) : lvalue(l) {}
281
282void VariableDeclaration::Write(CodeWriter* to) const {
283  this->lvalue->WriteDeclaration(to);
284  if (this->rvalue != NULL) {
285    to->Write(" = ");
286    if (this->cast != NULL) {
287      to->Write("(%s)", this->cast->JavaType().c_str());
288    }
289    this->rvalue->Write(to);
290  }
291  to->Write(";\n");
292}
293
294void IfStatement::Write(CodeWriter* to) const {
295  if (this->expression != NULL) {
296    to->Write("if (");
297    this->expression->Write(to);
298    to->Write(") ");
299  }
300  this->statements->Write(to);
301  if (this->elseif != NULL) {
302    to->Write("else ");
303    this->elseif->Write(to);
304  }
305}
306
307ReturnStatement::ReturnStatement(Expression* e) : expression(e) {}
308
309void ReturnStatement::Write(CodeWriter* to) const {
310  to->Write("return ");
311  this->expression->Write(to);
312  to->Write(";\n");
313}
314
315void TryStatement::Write(CodeWriter* to) const {
316  to->Write("try ");
317  this->statements->Write(to);
318}
319
320CatchStatement::CatchStatement(Variable* e)
321    : statements(new StatementBlock), exception(e) {}
322
323void CatchStatement::Write(CodeWriter* to) const {
324  to->Write("catch ");
325  if (this->exception != NULL) {
326    to->Write("(");
327    this->exception->WriteDeclaration(to);
328    to->Write(") ");
329  }
330  this->statements->Write(to);
331}
332
333void FinallyStatement::Write(CodeWriter* to) const {
334  to->Write("finally ");
335  this->statements->Write(to);
336}
337
338Case::Case(const string& c) { cases.push_back(c); }
339
340void Case::Write(CodeWriter* to) const {
341  int N = this->cases.size();
342  if (N > 0) {
343    for (int i = 0; i < N; i++) {
344      string s = this->cases[i];
345      if (s.length() != 0) {
346        to->Write("case %s:\n", s.c_str());
347      } else {
348        to->Write("default:\n");
349      }
350    }
351  } else {
352    to->Write("default:\n");
353  }
354  statements->Write(to);
355}
356
357SwitchStatement::SwitchStatement(Expression* e) : expression(e) {}
358
359void SwitchStatement::Write(CodeWriter* to) const {
360  to->Write("switch (");
361  this->expression->Write(to);
362  to->Write(")\n{\n");
363  int N = this->cases.size();
364  for (int i = 0; i < N; i++) {
365    this->cases[i]->Write(to);
366  }
367  to->Write("}\n");
368}
369
370void Break::Write(CodeWriter* to) const { to->Write("break;\n"); }
371
372void Method::Write(CodeWriter* to) const {
373  size_t N, i;
374
375  if (this->comment.length() != 0) {
376    to->Write("%s\n", this->comment.c_str());
377  }
378
379  WriteModifiers(to, this->modifiers,
380                 SCOPE_MASK | STATIC | ABSTRACT | FINAL | OVERRIDE);
381
382  if (this->returnType != NULL) {
383    string dim;
384    for (i = 0; i < this->returnTypeDimension; i++) {
385      dim += "[]";
386    }
387    to->Write("%s%s ", this->returnType->JavaType().c_str(), dim.c_str());
388  }
389
390  to->Write("%s(", this->name.c_str());
391
392  N = this->parameters.size();
393  for (i = 0; i < N; i++) {
394    this->parameters[i]->WriteDeclaration(to);
395    if (i != N - 1) {
396      to->Write(", ");
397    }
398  }
399
400  to->Write(")");
401
402  N = this->exceptions.size();
403  for (i = 0; i < N; i++) {
404    if (i == 0) {
405      to->Write(" throws ");
406    } else {
407      to->Write(", ");
408    }
409    to->Write("%s", this->exceptions[i]->JavaType().c_str());
410  }
411
412  if (this->statements == NULL) {
413    to->Write(";\n");
414  } else {
415    to->Write("\n");
416    this->statements->Write(to);
417  }
418}
419
420void IntConstant::Write(CodeWriter* to) const {
421  WriteModifiers(to, STATIC | FINAL | PUBLIC, ALL_MODIFIERS);
422  to->Write("int %s = %d;\n", name.c_str(), value);
423}
424
425void StringConstant::Write(CodeWriter* to) const {
426  WriteModifiers(to, STATIC | FINAL | PUBLIC, ALL_MODIFIERS);
427  to->Write("String %s = %s;\n", name.c_str(), value.c_str());
428}
429
430void Class::Write(CodeWriter* to) const {
431  size_t N, i;
432
433  if (this->comment.length() != 0) {
434    to->Write("%s\n", this->comment.c_str());
435  }
436
437  WriteModifiers(to, this->modifiers, ALL_MODIFIERS);
438
439  if (this->what == Class::CLASS) {
440    to->Write("class ");
441  } else {
442    to->Write("interface ");
443  }
444
445  string name = this->type->JavaType();
446  size_t pos = name.rfind('.');
447  if (pos != string::npos) {
448    name = name.c_str() + pos + 1;
449  }
450
451  to->Write("%s", name.c_str());
452
453  if (this->extends != NULL) {
454    to->Write(" extends %s", this->extends->JavaType().c_str());
455  }
456
457  N = this->interfaces.size();
458  if (N != 0) {
459    if (this->what == Class::CLASS) {
460      to->Write(" implements");
461    } else {
462      to->Write(" extends");
463    }
464    for (i = 0; i < N; i++) {
465      to->Write(" %s", this->interfaces[i]->JavaType().c_str());
466    }
467  }
468
469  to->Write("\n");
470  to->Write("{\n");
471
472  N = this->elements.size();
473  for (i = 0; i < N; i++) {
474    this->elements[i]->Write(to);
475  }
476
477  to->Write("}\n");
478}
479
480static string escape_backslashes(const string& str) {
481  string result;
482  const size_t I = str.length();
483  for (size_t i = 0; i < I; i++) {
484    char c = str[i];
485    if (c == '\\') {
486      result += "\\\\";
487    } else {
488      result += c;
489    }
490  }
491  return result;
492}
493
494Document::Document(const std::string& comment,
495                   const std::string& package,
496                   const std::string& original_src,
497                   std::unique_ptr<Class> clazz)
498    : comment_(comment),
499      package_(package),
500      original_src_(original_src),
501      clazz_(std::move(clazz)) {
502}
503
504void Document::Write(CodeWriter* to) const {
505  if (!comment_.empty()) {
506    to->Write("%s\n", comment_.c_str());
507  }
508  to->Write(
509      "/*\n"
510      " * This file is auto-generated.  DO NOT MODIFY.\n"
511      " * Original file: %s\n"
512      " */\n",
513      escape_backslashes(original_src_).c_str());
514  if (!package_.empty()) {
515    to->Write("package %s;\n", package_.c_str());
516  }
517
518  if (clazz_) {
519    clazz_->Write(to);
520  }
521}
522
523}  // namespace java
524}  // namespace aidl
525}  // namespace android
526