• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include <string>
17 #include <algorithm>
18 #include <list>
19 
20 #include "tensorflow/java/src/gen/cc/source_writer.h"
21 
22 namespace tensorflow {
23 namespace java {
24 
SourceWriter()25 SourceWriter::SourceWriter() {
26   // Push an empty generic namespace at start, for simplification.
27   generic_namespaces_.push(new GenericNamespace());
28 }
29 
~SourceWriter()30 SourceWriter::~SourceWriter() {
31   // Remove empty generic namespace added at start as well as any other
32   // namespace objects that haven't been removed.
33   while (!generic_namespaces_.empty()) {
34     GenericNamespace* generic_namespace = generic_namespaces_.top();
35     generic_namespaces_.pop();
36     delete generic_namespace;
37   }
38 }
39 
Indent(int tab)40 SourceWriter& SourceWriter::Indent(int tab) {
41   left_margin_.resize(
42       std::max(static_cast<int>(left_margin_.size() + tab), 0), ' ');
43   return *this;
44 }
45 
Prefix(const char * line_prefix)46 SourceWriter& SourceWriter::Prefix(const char* line_prefix) {
47   line_prefix_ = line_prefix;
48   return *this;
49 }
50 
Write(const StringPiece & str)51 SourceWriter& SourceWriter::Write(const StringPiece& str) {
52   size_t line_pos = 0;
53   do {
54     size_t start_pos = line_pos;
55     line_pos = str.find('\n', start_pos);
56     if (line_pos != string::npos) {
57       ++line_pos;
58       Append(str.substr(start_pos, line_pos - start_pos));
59       newline_ = true;
60     } else {
61       Append(str.substr(start_pos, str.size() - start_pos));
62     }
63   } while (line_pos != string::npos && line_pos < str.size());
64 
65   return *this;
66 }
67 
WriteFromFile(const string & fname,Env * env)68 SourceWriter& SourceWriter::WriteFromFile(const string& fname, Env* env) {
69   string data_;
70   TF_CHECK_OK(ReadFileToString(env, fname, &data_));
71   return Write(data_);
72 }
73 
Append(const StringPiece & str)74 SourceWriter& SourceWriter::Append(const StringPiece& str) {
75   if (!str.empty()) {
76     if (newline_) {
77       DoAppend(left_margin_ + line_prefix_);
78       newline_ = false;
79     }
80     DoAppend(str);
81   }
82   return *this;
83 }
84 
AppendType(const Type & type)85 SourceWriter& SourceWriter::AppendType(const Type& type) {
86   if (type.wildcard()) {
87     Append("?");
88   } else {
89     Append(type.name());
90     if (!type.parameters().empty()) {
91       Append("<");
92       bool first = true;
93       for (const Type& t : type.parameters()) {
94         if (!first) {
95           Append(", ");
96         }
97         AppendType(t);
98         first = false;
99       }
100       Append(">");
101     }
102   }
103   return *this;
104 }
105 
EndLine()106 SourceWriter& SourceWriter::EndLine() {
107   Append("\n");
108   newline_ = true;
109   return *this;
110 }
111 
BeginBlock(const string & expression)112 SourceWriter& SourceWriter::BeginBlock(const string& expression) {
113   if (!expression.empty()) {
114     Append(expression + " {");
115   } else {
116     Append(newline_ ? "{" : " {");
117   }
118   return EndLine().Indent(2);
119 }
120 
EndBlock()121 SourceWriter& SourceWriter::EndBlock() {
122   return Indent(-2).Append("}").EndLine();
123 }
124 
BeginMethod(const Method & method,int modifiers,const Javadoc * javadoc)125 SourceWriter& SourceWriter::BeginMethod(const Method& method, int modifiers,
126                                         const Javadoc* javadoc) {
127   GenericNamespace* generic_namespace = PushGenericNamespace(modifiers);
128   if (!method.constructor()) {
129     generic_namespace->Visit(method.return_type());
130   }
131   for (const Variable& v : method.arguments()) {
132     generic_namespace->Visit(v.type());
133   }
134   EndLine();
135   if (javadoc != nullptr) {
136     WriteJavadoc(*javadoc);
137   }
138   if (!method.annotations().empty()) {
139     WriteAnnotations(method.annotations());
140   }
141   WriteModifiers(modifiers);
142   if (!generic_namespace->declared_types().empty()) {
143     WriteGenerics(generic_namespace->declared_types());
144     Append(" ");
145   }
146   if (!method.constructor()) {
147     AppendType(method.return_type()).Append(" ");
148   }
149   Append(method.name()).Append("(");
150   bool first = true;
151   for (const Variable& v : method.arguments()) {
152     if (!first) {
153       Append(", ");
154     }
155     AppendType(v.type()).Append(v.variadic() ? "... " : " ").Append(v.name());
156     first = false;
157   }
158   return Append(")").BeginBlock();
159 }
160 
EndMethod()161 SourceWriter& SourceWriter::EndMethod() {
162   EndBlock();
163   PopGenericNamespace();
164   return *this;
165 }
166 
BeginType(const Type & type,int modifiers,const std::list<Type> * extra_dependencies,const Javadoc * javadoc)167 SourceWriter& SourceWriter::BeginType(const Type& type, int modifiers,
168                                       const std::list<Type>* extra_dependencies,
169                                       const Javadoc* javadoc) {
170   if (!type.package().empty()) {
171     Append("package ").Append(type.package()).Append(";").EndLine();
172   }
173   TypeImporter type_importer(type.package());
174   type_importer.Visit(type);
175   if (extra_dependencies != nullptr) {
176     for (const Type& t : *extra_dependencies) {
177       type_importer.Visit(t);
178     }
179   }
180   if (!type_importer.imports().empty()) {
181     EndLine();
182     for (const string& s : type_importer.imports()) {
183       Append("import ").Append(s).Append(";").EndLine();
184     }
185   }
186   return BeginInnerType(type, modifiers, javadoc);
187 }
188 
BeginInnerType(const Type & type,int modifiers,const Javadoc * javadoc)189 SourceWriter& SourceWriter::BeginInnerType(const Type& type, int modifiers,
190                                            const Javadoc* javadoc) {
191   GenericNamespace* generic_namespace = PushGenericNamespace(modifiers);
192   generic_namespace->Visit(type);
193   EndLine();
194   if (javadoc != nullptr) {
195     WriteJavadoc(*javadoc);
196   }
197   if (!type.annotations().empty()) {
198     WriteAnnotations(type.annotations());
199   }
200   WriteModifiers(modifiers);
201   CHECK_EQ(Type::Kind::CLASS, type.kind()) << ": Not supported yet";
202   Append("class ").Append(type.name());
203   if (!generic_namespace->declared_types().empty()) {
204     WriteGenerics(generic_namespace->declared_types());
205   }
206   if (!type.supertypes().empty()) {
207     bool first_interface = true;
208     for (const Type& t : type.supertypes()) {
209       if (t.kind() == Type::CLASS) {  // superclass is always first in list
210         Append(" extends ");
211       } else if (first_interface) {
212         Append(" implements ");
213         first_interface = false;
214       } else {
215         Append(", ");
216       }
217       AppendType(t);
218     }
219   }
220   return BeginBlock();
221 }
222 
EndType()223 SourceWriter& SourceWriter::EndType() {
224   EndBlock();
225   PopGenericNamespace();
226   return *this;
227 }
228 
WriteField(const Variable & field,int modifiers,const Javadoc * javadoc)229 SourceWriter& SourceWriter::WriteField(const Variable& field, int modifiers,
230                                        const Javadoc* javadoc) {
231   // If present, write field javadoc only as one brief line
232   if (javadoc != nullptr && !javadoc->brief().empty()) {
233     Append("/** ").Append(javadoc->brief()).Append(" */").EndLine();
234   }
235   WriteModifiers(modifiers);
236   AppendType(field.type()).Append(" ").Append(field.name()).Append(";");
237   EndLine();
238   return *this;
239 }
240 
WriteModifiers(int modifiers)241 SourceWriter& SourceWriter::WriteModifiers(int modifiers) {
242   if (modifiers & PUBLIC) {
243     Append("public ");
244   } else if (modifiers & PROTECTED) {
245     Append("protected ");
246   } else if (modifiers & PRIVATE) {
247     Append("private ");
248   }
249   if (modifiers & STATIC) {
250     Append("static ");
251   }
252   if (modifiers & FINAL) {
253     Append("final ");
254   }
255   return *this;
256 }
257 
WriteJavadoc(const Javadoc & javadoc)258 SourceWriter& SourceWriter::WriteJavadoc(const Javadoc& javadoc) {
259   Append("/**").Prefix(" * ").EndLine();
260   bool do_line_break = false;
261   if (!javadoc.brief().empty()) {
262     Write(javadoc.brief()).EndLine();
263     do_line_break = true;
264   }
265   if (!javadoc.details().empty()) {
266     if (do_line_break) {
267       Append("<p>").EndLine();
268     }
269     Write(javadoc.details()).EndLine();
270     do_line_break = true;
271   }
272   if (!javadoc.tags().empty()) {
273     if (do_line_break) {
274       EndLine();
275     }
276     for (const auto& p : javadoc.tags()) {
277       Append("@" + p.first);
278       if (!p.second.empty()) {
279         Append(" ").Write(p.second);
280       }
281       EndLine();
282     }
283   }
284   return Prefix("").Append(" */").EndLine();
285 }
286 
WriteAnnotations(const std::list<Annotation> & annotations)287 SourceWriter& SourceWriter::WriteAnnotations(
288     const std::list<Annotation>& annotations) {
289   for (const Annotation& a : annotations) {
290     Append("@" + a.name());
291     if (!a.attributes().empty()) {
292       Append("(").Append(a.attributes()).Append(")");
293     }
294     EndLine();
295   }
296   return *this;
297 }
298 
WriteGenerics(const std::list<const Type * > & generics)299 SourceWriter& SourceWriter::WriteGenerics(
300     const std::list<const Type*>& generics) {
301   Append("<");
302   bool first = true;
303   for (const Type* pt : generics) {
304     if (!first) {
305       Append(", ");
306     }
307     Append(pt->name());
308     if (!pt->supertypes().empty()) {
309       Append(" extends ").AppendType(pt->supertypes().front());
310     }
311     first = false;
312   }
313   return Append(">");
314 }
315 
PushGenericNamespace(int modifiers)316 SourceWriter::GenericNamespace* SourceWriter::PushGenericNamespace(
317     int modifiers) {
318   GenericNamespace* generic_namespace;
319   if (modifiers & STATIC) {
320     generic_namespace = new GenericNamespace();
321   } else {
322     generic_namespace = new GenericNamespace(generic_namespaces_.top());
323   }
324   generic_namespaces_.push(generic_namespace);
325   return generic_namespace;
326 }
327 
PopGenericNamespace()328 void SourceWriter::PopGenericNamespace() {
329   GenericNamespace* generic_namespace = generic_namespaces_.top();
330   generic_namespaces_.pop();
331   delete generic_namespace;
332 }
333 
Visit(const Type & type)334 void SourceWriter::TypeVisitor::Visit(const Type& type) {
335   DoVisit(type);
336   for (const Type& t : type.parameters()) {
337     Visit(t);
338   }
339   for (const Annotation& t : type.annotations()) {
340     DoVisit(t);
341   }
342   for (const Type& t : type.supertypes()) {
343     Visit(t);
344   }
345 }
346 
DoVisit(const Type & type)347 void SourceWriter::GenericNamespace::DoVisit(const Type& type) {
348   // ignore non-generic parameters, wildcards and generics already declared
349   if (type.kind() == Type::GENERIC && !type.wildcard() &&
350       generic_names_.find(type.name()) == generic_names_.end()) {
351     declared_types_.push_back(&type);
352     generic_names_.insert(type.name());
353   }
354 }
355 
DoVisit(const Type & type)356 void SourceWriter::TypeImporter::DoVisit(const Type& type) {
357   if (!type.package().empty() && type.package() != current_package_) {
358     imports_.insert(type.canonical_name());
359   }
360 }
361 
362 }  // namespace java
363 }  // namespace tensorflow
364