v8toolkit  0.0.1
Utility library for embedding V8 Javascript engine in a c++ program
parsed_method.cpp
Go to the documentation of this file.
1 #include "parsed_method.h"
2 #include "wrapped_class.h"
3 #include <cstdbool>
4 
5 ClassFunction::TypeInfo::TypeInfo(QualType const & type) :
6  type(type),
7  //name(this->type.getAsString()),
8  name(get_type_string(this->type)),
9  plain_type(get_plain_type(this->type)),
10  plain_name(get_type_string(this->plain_type))
11 {
12  name = regex_replace(name, std::regex("^(struct|class) "), "");
13 
14  // do any required textual type conversions
15  static std::regex bool_conversion = std::regex("^_Bool$");
16  name = std::regex_replace(this->name, bool_conversion, "bool");
17 }
18 
19 
20 string ClassFunction::TypeInfo::convert_simple_typename_to_jsdoc(string simple_type_name) {
21 
22  // picks off the middle namespace of things like:
23  // std::__cxx11::string as well as std::__1::vector so type names are more predictable
24  simple_type_name = regex_replace(simple_type_name, regex("std::__(cxx\\d\\d|\\d)::"), "std::");
25 
26  // clang generates type names with class/struct prefixes, remove them
27  simple_type_name = regex_replace(simple_type_name, regex("^(class|struct)\\s*"), "");
28 
29 
30  std::smatch matches;
31 
32  for(auto & conversion_pattern : cpp_to_js_type_conversions) {
33  for (auto &pair : cpp_to_js_type_conversions) {
34  if (regex_match(simple_type_name, matches, std::regex(pair.first))) {
35  std::cerr << fmt::format("matched {}, converting to {}", pair.first, pair.second) << std::endl;
36  return pair.second;
37  }
38  }
39  }
40 
41  // no match, return unchanged
42  std::cerr << fmt::format("returning simple type name unchanged {}", simple_type_name) << std::endl;
43  return simple_type_name;
44 }
45 
46 
48  std::cerr << fmt::format("converting {}", this->name) << std::endl;
49 
50  vector<string> template_type_jsdoc_conversions;
51  if (this->is_templated()) {
52 
53  // convert each templated type
54  this->for_each_templated_type([&](QualType qualtype) {
55  auto typeinfo = TypeInfo(qualtype);
56  std::cerr << fmt::format("converting templated type {}", typeinfo.plain_name) << std::endl;
57  template_type_jsdoc_conversions.push_back(typeinfo.get_jsdoc_type_name());
58  });
59 
60  // convert the specialized template name
61  string specialized_template_name;
62  if (auto specialization = dyn_cast<ClassTemplateSpecializationDecl>(this->get_plain_type_decl())) {
63  if (auto spec_tmpl = specialization->getSpecializedTemplate()) {
64  specialized_template_name = spec_tmpl->getQualifiedNameAsString();
65  fprintf(stderr, "Specialized template: %p, %s\n", (void *) spec_tmpl,
66  specialized_template_name.c_str());
67  print_vector(Annotations(spec_tmpl).get(), "specialized template annotations", "", false);
68  } else {
69  llvm::report_fatal_error("couldn't determine name of template being specialized");
70  }
71  } else {
72  llvm::report_fatal_error("Template being specialized couldn't be cast to class template spec decl (shouldn't happen)");
73  }
74 
75  specialized_template_name = this->convert_simple_typename_to_jsdoc(specialized_template_name);
76 
77 
78  // go through each capturing match and...
79  for (size_t i = 0; i < template_type_jsdoc_conversions.size(); i++) {
80  // look for $1, $2, etc in replacement and substitute in the matching position
81  specialized_template_name = std::regex_replace(specialized_template_name, std::regex(fmt::format("\\${}", i+1)),
82  template_type_jsdoc_conversions[i]);
83  }
84  std::cerr << fmt::format("final jsdoc conversion: {} =? {}", this->plain_name, specialized_template_name) << std::endl;
85  return specialized_template_name;
86  }
87  // Handle non-templated types
88  else {
89  return this->convert_simple_typename_to_jsdoc(this->plain_without_const().name);
90  }
91 }
92 
94  return this->plain_type.isConstQualified();
95 }
96 
97 
99  QualType non_const = this->plain_type;
100  non_const.removeLocalConst();
101  return TypeInfo(non_const);
102 }
103 
104 
105 
106 CXXRecordDecl const * ClassFunction::TypeInfo::get_plain_type_decl() const {
107  auto decl = this->plain_type->getAsCXXRecordDecl();
108  if (decl == nullptr) {
109  return nullptr;
110  }
111  return dyn_cast<ClassTemplateSpecializationDecl>(decl);
112 }
113 
114 
115 
117  auto decl = this->get_plain_type_decl();
118  if (decl == nullptr) {
119  return false;
120  }
121  if (dyn_cast<ClassTemplateSpecializationDecl>(decl) != nullptr) {
122  return true;
123  } else {
124  return false;
125  }
126 }
127 
128 void ClassFunction::TypeInfo::for_each_templated_type(std::function<void(QualType)> callback) const {
129  if (auto specialization_decl = dyn_cast<ClassTemplateSpecializationDecl>(this->plain_type->getAsCXXRecordDecl())) {
130 
131 
132  // go through the template args
133  auto & template_arg_list = specialization_decl->getTemplateArgs();
134  for (decltype(template_arg_list.size()) i = 0; i < template_arg_list.size(); i++) {
135  auto & arg = template_arg_list[i];
136 
137  // this code only cares about types, so skip non-type template arguments
138  if (arg.getKind() != clang::TemplateArgument::Type) {
139  continue;
140  }
141  auto template_arg_qual_type = arg.getAsType();
142  if (template_arg_qual_type.isNull()) {
143  if (print_logging) cerr << "qual type is null" << endl;
144  continue;
145  }
146  callback(template_arg_qual_type);
147  }
148  } else {
149  if (print_logging) cerr << "Not a template specializaiton type " << this->plain_type.getAsString() << endl;
150  }
151 }
152 
153 
155  WrappedClass & declared_in,
156  FieldDecl * field_decl) :
157  wrapped_class(wrapped_class),
158  declared_in(declared_in),
159  short_name(field_decl->getNameAsString()),
160  long_name(field_decl->getQualifiedNameAsString()),
161  type(field_decl->getType()),
162  field_decl(field_decl),
163  annotations(this->field_decl)
164 {
165  wrapped_class.add_member_name(this->short_name);
166  wrapped_class.declaration_count++;
167 
168  update_wrapped_class_for_type(wrapped_class, this->type.type);
169 
170  // the member will be wrapped as const if the actual data type is const or there's an attribute saying it should be const
172 
173 }
174 
175 
177 
178  stringstream result;
179 
180  result << fmt::format(" * @property {{{}}} {} \n", this->type.get_jsdoc_type_name(), this->short_name);
181 
182  return result.str();
183 }
184 
186  stringstream result;
187 
188  if (this->is_const) {
189  result << fmt::format(" class_wrapper.add_member_readonly<{}, {}, &{}>(\"{}\");\n",
190  this->type.name,
191  this->declared_in.class_name, this->long_name, this->short_name);
192 
193  } else {
194  result << fmt::format(" class_wrapper.add_member<{}, {}, &{}>(\"{}\");\n",
195  this->type.name,
196  this->declared_in.class_name, this->long_name, this->short_name);
197  }
198 
199  return result.str();
200 }
201 
203  stringstream result;
204 
205  if (this->default_value != "") {
206  result << fmt::format(" * @param {{{}}} [{} = {}] {}\n", this->type.get_jsdoc_type_name(),
207  this->name,
208  this->default_value,
209  this->description);
210  } else {
211  result << fmt::format(" * @param {{{}}} {}\n", this->type.get_jsdoc_type_name(), this->name,
212  this->description);
213  }
214  return result.str();
215 }
216 
217 ClassFunction::ParameterInfo::ParameterInfo(ClassFunction & method, int position, ParmVarDecl const * parameter_decl, CompilerInstance & compiler_instance) :
218  method(method),
219  compiler_instance(compiler_instance),
220  parameter_decl(parameter_decl),
221  position(position),
222  type(parameter_decl->getType())
223 {
224  //std::cerr << fmt::format("parameterinfo constructor: parsing parameter {}", name) << std::endl;
225  // set the name, give placeholder name if unnamed
226  //std::cerr << fmt::format("1") << std::endl;
227  this->name = this->parameter_decl->getNameAsString();
228  //std::cerr << fmt::format("2") << std::endl;
229  if (this->name == "") {
230  //std::cerr << fmt::format("3") << std::endl;
231  this->name = fmt::format("unspecified_position_{}", this->position);
232 
233  data_warning(fmt::format("class {} method {} parameter index {} has no variable name",
234  this->method.wrapped_class.name_alias, this->method.name, this->position));
235  }
236 
237  // set default argument or "" if none
238  if (parameter_decl->hasDefaultArg()) {
239  auto default_argument = parameter_decl->getDefaultArg();
240  if (default_argument != nullptr) {
241  auto source_range = default_argument->getSourceRange();
242  if (source_range.isValid()) {
243 
244  auto source = get_source_for_source_range(compiler_instance.getSourceManager(), source_range);
245 
246  // certain default values return the = sign, others don't. specifically "= {}" comes back with the =, so strip it off
247  // is this a clang bug?
248  this->default_value = std::regex_replace(source, std::regex("^\\s*=\\s*"), "");
249 
250  if (this->default_value == "{}") {
251 
252  this->default_value = fmt::format("{}{{}}", this->type.plain_without_const().name);
253  }
254 
255  } else {
256 
257  }
258  } else {
259  }
260  } else {
261  this->default_value = "";
262  }
263 
264 }
265 
266 
268  CXXMethodDecl const * method_decl) :
269  compiler_instance(wrapped_class.compiler_instance),
270  return_type(method_decl->getReturnType()),
271  method_decl(method_decl),
272  name(method_decl->getQualifiedNameAsString()),
273  js_name(method_decl->getNameAsString()),
274  wrapped_class(wrapped_class),
275  is_virtual(method_decl->isVirtual()),
276  annotations(this->method_decl)
277 {
278 
279  // check to see if there's a name annotation on the method giving it a different JavaScript name
280  auto annotated_custom_name = annotations.get_regex(
281  "^" V8TOOLKIT_USE_NAME_PREFIX "(.*)$");
282  if (!annotated_custom_name.empty()) {
283  std::cerr << fmt::format("Overriding method name {} => {}", this->js_name, annotated_custom_name[0]) << std::endl;
284  this->js_name = annotated_custom_name[0];
285  std::cerr << fmt::format("short name is now {}", this->js_name) << std::endl;
286  } else {
287  std::cerr << fmt::format("not overriding method name {}", this->js_name) << std::endl;
288  }
289 
290  this->wrapped_class.declaration_count++;
291 
292  std::cerr << fmt::format("***** Parsing method {}", this->name) << std::endl;
293 
294  update_wrapped_class_for_type(this->wrapped_class, this->return_type.type);
295 
296  auto parameter_count = method_decl->getNumParams();
297  for (int i = 0; i < parameter_count; i++) {
298  std::cerr << fmt::format("ParsedMethod constructor - parsing parameter {}", i) << std::endl;
299  parameters.emplace_back(*this, i, method_decl->getParamDecl(i), this->compiler_instance);
300 
301  // make sure the wrapped class has includes for all the types in the method
302  update_wrapped_class_for_type(this->wrapped_class, this->parameters.back().type.type);
303  }
304 
305 
306  // get the comment associated with the method and if there is one, parse it
307  std::cerr << fmt::format("Parsing doxygen comments") << std::endl;
308  FullComment *comment = this->compiler_instance.getASTContext().getCommentForDecl(this->method_decl, nullptr);
309  if (comment != nullptr) {
310 
311  auto comment_text = get_source_for_source_range(
312  this->compiler_instance.getPreprocessor().getSourceManager(), comment->getSourceRange());
313 
314  cerr << "FullComment: " << comment_text << endl;
315 
316  // go through each portion (child) of the full commetn
317  int j = 0;
318  for (auto i = comment->child_begin(); i != comment->child_end(); i++) {
319  std::cerr << fmt::format("looking at child comment {}", ++j) << std::endl;
320  auto child_comment_source_range = (*i)->getSourceRange();
321  if (child_comment_source_range.isValid()) {
322 
323  auto child_comment_text = get_source_for_source_range(
324  this->compiler_instance.getPreprocessor().getSourceManager(),
325  child_comment_source_range);
326 
327  cerr << "Child comment kind: " << (*i)->getCommentKind() << ": " << child_comment_text << endl;
328 
329  // if the child comment is a param command comment (describes a parameter)
330  if (auto param_command = dyn_cast<ParamCommandComment>(*i)) {
331  cerr << "Is ParamCommandComment" << endl;
332  if (param_command == nullptr) {
333  std::cerr << fmt::format("THIS CANT BE RIGHT") << std::endl;
334  }
335  std::cerr << fmt::format("param name aswritten: {}", param_command->getParamNameAsWritten().str()) << std::endl;
336 
337  // cannot use getParamName() because it crashes if the name doesn't match a parameter
338  auto command_param_name = param_command->getParamNameAsWritten().str();
339  std::cerr << fmt::format("got command param name {}", command_param_name) << std::endl;
340 
341  ParameterInfo * matching_parameter_info_ptr = nullptr;
342  for(auto & parameter : this->parameters) {
343  std::cerr << fmt::format("comparing {} against {}", command_param_name, parameter.name) << std::endl;
344  if (command_param_name == parameter.name) {
345  std::cerr << fmt::format("found match!") << std::endl;
346  matching_parameter_info_ptr = &parameter;
347  break;
348  }
349  }
350 // auto matching_param_iterator =
351 // std::find_if(parameters.begin(), parameters.end(),
352 // [&command_param_name](auto &param) {
353 // return command_param_name == param.name;
354 // });
355 
356  std::cerr << fmt::format("found parameter (not matching .end()) {}", matching_parameter_info_ptr != nullptr) << std::endl;
357  std::cerr << fmt::format("has param name? {}", param_command->hasParamName()) << std::endl;
358  if (param_command->hasParamName() && matching_parameter_info_ptr != nullptr) {
359 
360  auto &param_info = *matching_parameter_info_ptr;
361  if (param_command->getParagraph() != nullptr) {
363  this->compiler_instance.getPreprocessor().getSourceManager(),
364  param_command->getParagraph()->getSourceRange());
365  }
366  } else {
367  data_warning(
368  fmt::format("method parameter comment name doesn't match any parameter {}",
369  command_param_name));
370  }
371  } else {
372  cerr << "is not param command comment" << endl;
373  }
374  }
375  }
376  } else {
377  cerr << "No comment on " << method_decl->getNameAsString() << endl;
378  }
379 
380 }
381 
382 
383 
384 //
385 //std::string ClassFunction::get_js_stub() {
386 //
387 // string indentation = " ";
388 // stringstream result;
389 //
390 // string method_description;
391 //
392 // result << fmt::format("{}/**\n", indentation);
393 //
394 //// std::cerr << fmt::format("looking through {} parameters", this->parameters.size()) << std::endl;
395 // for (auto &param : this->parameters) {
396 // if (param.default_value != "") {
397 // result << fmt::format("{} * @param {{{}}} [{} = {}] {}\n", indentation, param.type.get_jsdoc_type_name(),
398 // param.name,
399 // param.default_value,
400 // param.description);
401 // } else {
402 // result << fmt::format("{} * @param {{{}}} {}\n", indentation, param.type.get_jsdoc_type_name(), param.name,
403 // param.description);
404 // }
405 // }
406 //
407 // result << fmt::format("{} * @return {{{}}} {}\n", indentation, this->return_type.get_jsdoc_type_name(),
408 // this->return_type_comment);
409 // result << fmt::format("{} */\n", indentation);
410 //
411 // result << fmt::format("{}{}{}(", indentation, this->is_static ? "static " : "", this->short_name);
412 //
413 // bool first_parameter = true;
414 // for (auto &param : parameters) {
415 // if (!first_parameter) {
416 // result << ", ";
417 // }
418 // first_parameter = false;
419 // result << fmt::format("{}", param.name);
420 // }
421 // result << fmt::format("){{}}\n\n");
422 //
423 // return result.str();
424 //}
425 
426 
428  stringstream types;
429  stringstream values;
430  bool first_default_argument = true;
431  for (auto & param : this->parameters) {
432 
433 
434  // this should go away once there's proper support
435  if (std::regex_search(param.type.plain_name, std::regex("^(class|struct)?\\s*std::function"))) {
436  std::cerr << fmt::format("Cannot handle std::function default parameters yet -- skipping") << std::endl;
437  continue;
438  }
439 
440  if (param.default_value == "") {
441  assert(first_default_argument); // if it's not true then there's a gap somehow
442  continue;
443  }
444  if (!first_default_argument) {
445  types << ", ";
446  values << ", ";
447  }
448  first_default_argument = false;
449 
450  //types << param.type.name; // still has const and references on it, which doesn't work well for tuples
451  QualType default_arg_type = param.type.type.getNonReferenceType();
452  default_arg_type.removeLocalConst();
453  types << get_type_string(default_arg_type);
454 
455  // this may have a problem with using type names not visible outside where the default argument is specified
456  // may need to substitute the type name instead if it's not a constant and is instead some sort of name
457  values << param.default_value;
458  }
459 
460  return fmt::format("std::tuple<{}>({})", types.str(), values.str());
461 }
462 
464  stringstream result;
465 
466  result << fmt::format("{}, {}", this->return_type.name, this->wrapped_class.class_name);
467  if (!this->parameters.empty()) {
468  result << ", ";
469  result << this->get_parameter_types_string();
470  }
471 
472  return result.str();
473 }
474 
476  stringstream result;
477 
478  result << fmt::format("{}", this->return_type.name);
479  if (!this->parameters.empty()) {
480  result << ", ";
481  result << this->get_parameter_types_string();
482  }
483 
484  return result.str();
485 }
486 
488  stringstream result;
489  bool first_result = true;
490  for (auto & parameter : this->parameters) {
491  if (!first_result) {
492  result << ", ";
493  }
494  first_result = false;
495  result << fmt::format("{}", parameter.type.name);
496  }
497 
498  return result.str();
499 }
500 
502  stringstream result;
503  bool first_result = true;
504  for (auto & parameter : this->parameters) {
505  if (!first_result) {
506  result << ", ";
507  }
508  first_result = false;
509  result << fmt::format("{}", parameter.name);
510  }
511 
512  return result.str();
513 }
514 
515 //
516 //string ParsedMethod::get_bindings() {
517 // stringstream result;
518 //
519 // // for add_method
520 // stringstream return_class_and_parameter_types;
521 //
522 // // for add_static_method
523 // stringstream return_and_parameter_types;
524 //
525 // return_class_and_parameter_types << fmt::format("{}, {}", this->return_type.name, this->wrapped_class.class_name);
526 // return_and_parameter_types << fmt::format("{}", this->return_type.name, this->wrapped_class.class_name);
527 // for (auto & parameter : this->parameters) {
528 // return_class_and_parameter_types << fmt::format(", {}", parameter.type.name);
529 // return_and_parameter_types << fmt::format(", {}", parameter.type.name);
530 // }
531 //
532 //
533 // // overloaded operator type names (like OO_Call) defined here:
534 // // http://llvm.org/reports/coverage/tools/clang/include/clang/Basic/OperatorKinds.def.gcov.html
535 // // name is "OO_" followed by the first field in each line
536 // if (OO_Call == method_decl->getOverloadedOperator()) {
537 // result << fmt::format(" class_wrapper.make_callable<{}>(&{});\n",
538 // return_class_and_parameter_types.str(), this->full_name);
539 // } else if (this->is_static) {
540 //
541 // if (static_method_renames.find(this->short_name) != static_method_renames.end()) {
542 // this->short_name = static_method_renames[this->short_name];
543 // }
544 // this->wrapped_class.has_static_method = true;
545 // result << fmt::format(" class_wrapper.add_static_method<{}>(\"{}\", &{});\n",
546 // return_and_parameter_types.str(), this->short_name, this->full_name);
547 // } else {
548 // result << fmt::format(" class_wrapper.add_method<{}>(\"{}\", &{}, {});\n",
549 // return_class_and_parameter_types.str(), this->short_name, this->full_name,
550 // this->get_default_argument_tuple_string());
551 // }
552 //
553 //
554 // return result.str();
555 //}
556 
557 //
558 //
559 //
560 //std::string ParsedMethod::get_bidirectional() {
561 // llvm::report_fatal_error("Shouldn't be calling this anymore");
562 ////
563 //// if (!this->method_decl->isVirtual()) {
564 //// return "";
565 //// }
566 ////
567 //// // skip pure virtual functions
568 //// if (this->method_decl->isPure()) {
569 //// return "";
570 //// }
571 ////
572 //// auto num_params = this->method_decl->getNumParams();
573 ////// printf("Dealing with %s\n", method->getQualifiedNameAsString().c_str());
574 //// std::stringstream result;
575 ////
576 ////
577 //// result << " JS_ACCESS_" << num_params << (this->method_decl->isConst() ? "_CONST(" : "(");
578 ////
579 //// result << this->return_type.name << ", ";
580 ////
581 ////
582 //// result << this->short_name;
583 ////
584 //// if (num_params > 0) {
585 //// auto types = get_method_param_qual_types(this->compiler_instance, this->method_decl);
586 //// vector<string>type_names;
587 //// for (auto & type : types) {
588 //// type_names.push_back(std::regex_replace(type.getAsString(), std::regex("\\s*,\\s*"), " V8TOOLKIT_COMMA "));
589 //// }
590 ////
591 //// result << join(type_names, ", ", true);
592 //// }
593 ////
594 //// result << ");\n";
595 ////
596 //// return result.str();
597 //
598 //}
599 //
600 
601 
603  stringstream result;
604  result << this->name << "(";
605 
606  bool first = true;
607  for (auto & p : this->parameters) {
608  if (!first) {
609  result << ",";
610  }
611  first = false;
612  result << p.type.name;
613  }
614 
615  result << ")";
616  return result.str();
617 }
618 
620  ClassFunction(wrapped_class, method_decl)
621 {
622  wrapped_class.add_member_name(this->js_name);
623 }
624 
626  ClassFunction(wrapped_class, method_decl)
627 {
628  wrapped_class.add_static_name(this->js_name);
629 
630  if (static_method_renames.find(this->js_name) != static_method_renames.end()) {
631  this->js_name = static_method_renames[this->js_name];
632  }
633 }
634 
635 
636 
637 
638 ConstructorFunction::ConstructorFunction(WrappedClass & wrapped_class, CXXConstructorDecl const * constructor_decl) :
639  ClassFunction(wrapped_class, constructor_decl),
640  constructor_decl(constructor_decl)
641 {
642 
643  cerr << "About to get full source for constructor in " << wrapped_class.name_alias << endl;
644  auto full_source_loc = FullSourceLoc(constructor_decl->getLocation(),
645  this->compiler_instance.getSourceManager());
646  fprintf(stderr,"%s constructor Decl at line %d, file id: %d\n",
647  wrapped_class.name_alias.c_str(),
648  full_source_loc.getExpansionLineNumber(),
649  full_source_loc.getFileID().getHashValue());
650 
651  // this should be moved to ClassFunction
652 // Annotations constructor_annotations(constructor_decl);
653 // auto constructor_name_annotation = constructor_annotations.get_regex(V8TOOLKIT_CONSTRUCTOR_PREFIX "(.*)");
654 // // fprintf(stderr,"Got %d annotations on constructor\n", (int)constructor_annotations.size());
655 // std::string constructor_name = wrapped_class.name_alias;
656 // if (!constructor_name_annotation.empty()) {
657 // constructor_name = constructor_name_annotation[0];
658 // }
659 
660 
661  if (std::find(used_constructor_names.begin(), used_constructor_names.end(), this->js_name) !=
662  used_constructor_names.end()) {
663  data_error(
664  fmt::format("Error: because duplicate JS constructor function name: {} in class {}",
665  this->js_name.c_str(), wrapped_class.name_alias));
666  for (auto &name : used_constructor_names) {
667  cerr << (fmt::format("Already used constructor name: {}", name)) << endl;
668  }
669  } else {
670  cerr << fmt::format("for {}, wrapping constructor {}", wrapped_class.name_alias,
671  this->js_name) << endl;
672  used_constructor_names.push_back(this->js_name);
673  }
674 }
675 
676 
678  stringstream result;
679  result << fmt::format(" class_wrapper.add_constructor<{}>(\"{}\", isolate, {});",
681 
682  return result.str();
683 }
684 
686  stringstream result;
687  if (OO_Call == method_decl->getOverloadedOperator()) {
688  result << fmt::format(" class_wrapper.make_callable<{}>(&{});\n",
690 
691  } else {
692  result << fmt::format(" class_wrapper.add_method<{}>(\"{}\", &{}, {});\n",
695  }
696  return result.str();
697 }
698 
700  stringstream result;
701  result << fmt::format(" /**") << endl;
702  for (auto & parameter : this->parameters) {
703  result << parameter.generate_js_stub();
704  }
705  if (!this->return_type.is_void()) {
706  result << fmt::format(" * @return {{{}}}", this->return_type.get_jsdoc_type_name()) << endl;
707  }
708 
709  result << fmt::format(" */") << endl;
710  result << fmt::format(" {}({}){{}}", this->js_name, this->get_js_input_parameter_string()) << endl;
711  result << endl;
712 
713  return result.str();
714 }
715 
717  stringstream result;
718 
719  return result.str();
720 
721 }
722 
723 
725  stringstream result;
726  result << fmt::format(" class_wrapper.add_static_method<{}>(\"{}\", &{}, {});\n",
727  this->get_return_and_parameter_types_string(), this->js_name, this->name,
729  return result.str();
730 
731 }
732 
734  stringstream result;
735  result << fmt::format(" /**") << endl;
736  for (auto & parameter : this->parameters) {
737  result << parameter.generate_js_stub();
738  }
739  if (!this->return_type.is_void()) {
740  result << fmt::format(" * @return {{{}}}", this->return_type.get_jsdoc_type_name()) << endl;
741  }
742  result << fmt::format(" */") << endl;
743 
744  result << fmt::format(" static {}({}){{}}", this->js_name, this->get_js_input_parameter_string()) << endl;
745  result << endl;
746 
747  return result.str();
748 
749 }
750 
752  stringstream result;
753 
754  result << fmt::format(" /**") << endl;
755  for (auto & parameter : this->parameters) {
756  result << parameter.generate_js_stub();
757  }
758  result << fmt::format(" */") << endl;
759 
760  result << fmt::format(" constructor({}){{}}", this->get_js_input_parameter_string()) << endl;
761  result << endl;
762 
763  return result.str();
764 
765 }
766 
767 
TypeInfo return_type
Definition: parsed_method.h:87
WrappedClass & wrapped_class
Definition: parsed_method.h:16
string generate_js_stub()
void add_member_name(string const &name)
string name_alias
this is the possibly shortened javascript name of the type - not necessarily valid in generated c++ ...
Definition: wrapped_class.h:46
vector< ParameterInfo > parameters
Definition: parsed_method.h:89
int print_logging
string name
name of actual type
Definition: parsed_method.h:39
string get_parameter_types_string() const
void data_error(const string &error)
string generate_js_bindings()
QualType get_plain_type(QualType qual_type)
ClassFunction::TypeInfo type
string get_return_and_parameter_types_string() const
void update_wrapped_class_for_type(WrappedClass &wrapped_class, QualType qual_type)
CXXRecordDecl const * get_plain_type_decl() const
TypeInfo plain_without_const() const
std::string get_type_string(QualType qual_type, const std::string &indentation)
string get_signature_string()
CompilerInstance & compiler_instance
Definition: parsed_method.h:68
int declaration_count
Definition: wrapped_class.h:52
ClassFunction(WrappedClass &wrapped_class, CXXMethodDecl const *method_decl)
ConstructorFunction(WrappedClass &wrapped_class, CXXConstructorDecl const *constructor_decl)
ParameterInfo(ClassFunction &method, int position, ParmVarDecl const *parameter_decl, CompilerInstance &compiler_instance)
string get_js_input_parameter_string() const
Annotations annotations
StaticFunction(WrappedClass &wrapped_class, CXXMethodDecl const *method_decl)
#define V8TOOLKIT_USE_NAME_PREFIX
Definition: class_parser.h:64
std::vector< std::string > used_constructor_names
std::vector< string > get_regex(const string &regex_string) const
Definition: annotations.h:51
string get_default_argument_tuple_string() const
void data_warning(const string &warning)
string get_js_stub()
bool has(const std::string &target) const
Definition: annotations.h:67
DataMember(WrappedClass &wrapped_class, WrappedClass &declared_in, FieldDecl *field_decl)
std::string get_source_for_source_range(SourceManager &sm, SourceRange source_range)
string get_return_and_class_and_parameter_types_string() const
CompilerInstance & compiler_instance
Definition: parsed_method.h:97
string generate_js_bindings()
void add_static_name(string const &name)
#define V8TOOLKIT_READONLY_STRING
Definition: class_parser.h:19
string get_jsdoc_type_name() const
corresponding javascript type
string generate_js_stub()
void for_each_templated_type(std::function< void(QualType)>) const
string generate_bidirectional()
MemberFunction(WrappedClass &wrapped_class, CXXMethodDecl const *method_decl)
string short_name
CXXMethodDecl const * method_decl
Definition: parsed_method.h:90
map< string, string > cpp_to_js_type_conversions
string get_bindings()
Annotations annotations
Definition: parsed_method.h:98
string plain_name
name of type without reference or pointers
Definition: parsed_method.h:42
TypeInfo(QualType const &type)
map< string, string > static_method_renames
void print_vector(const vector< string > &vec, const string &header, const string &indentation, bool ignore_empty)