12 name = regex_replace(
name, std::regex(
"^(struct|class) "),
"");
15 static std::regex bool_conversion = std::regex(
"^_Bool$");
16 name = std::regex_replace(this->
name, bool_conversion,
"bool");
20 string ClassFunction::TypeInfo::convert_simple_typename_to_jsdoc(
string simple_type_name) {
24 simple_type_name = regex_replace(simple_type_name, regex(
"std::__(cxx\\d\\d|\\d)::"),
"std::");
27 simple_type_name = regex_replace(simple_type_name, regex(
"^(class|struct)\\s*"),
"");
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;
42 std::cerr << fmt::format(
"returning simple type name unchanged {}", simple_type_name) << std::endl;
43 return simple_type_name;
48 std::cerr << fmt::format(
"converting {}", this->
name) << std::endl;
50 vector<string> template_type_jsdoc_conversions;
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());
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());
69 llvm::report_fatal_error(
"couldn't determine name of template being specialized");
72 llvm::report_fatal_error(
"Template being specialized couldn't be cast to class template spec decl (shouldn't happen)");
75 specialized_template_name = this->convert_simple_typename_to_jsdoc(specialized_template_name);
79 for (
size_t i = 0; i < template_type_jsdoc_conversions.size(); i++) {
81 specialized_template_name = std::regex_replace(specialized_template_name, std::regex(fmt::format(
"\\${}", i+1)),
82 template_type_jsdoc_conversions[i]);
84 std::cerr << fmt::format(
"final jsdoc conversion: {} =? {}", this->
plain_name, specialized_template_name) << std::endl;
85 return specialized_template_name;
100 non_const.removeLocalConst();
107 auto decl = this->
plain_type->getAsCXXRecordDecl();
108 if (decl ==
nullptr) {
111 return dyn_cast<ClassTemplateSpecializationDecl>(decl);
118 if (decl ==
nullptr) {
121 if (dyn_cast<ClassTemplateSpecializationDecl>(decl) !=
nullptr) {
129 if (
auto specialization_decl = dyn_cast<ClassTemplateSpecializationDecl>(this->
plain_type->getAsCXXRecordDecl())) {
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];
138 if (arg.getKind() != clang::TemplateArgument::Type) {
141 auto template_arg_qual_type = arg.getAsType();
142 if (template_arg_qual_type.isNull()) {
146 callback(template_arg_qual_type);
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),
189 result << fmt::format(
" class_wrapper.add_member_readonly<{}, {}, &{}>(\"{}\");\n",
191 this->declared_in.class_name, this->long_name, this->short_name);
194 result << fmt::format(
" class_wrapper.add_member<{}, {}, &{}>(\"{}\");\n",
196 this->declared_in.class_name, this->long_name, this->short_name);
205 if (this->default_value !=
"") {
219 compiler_instance(compiler_instance),
220 parameter_decl(parameter_decl),
222 type(parameter_decl->getType())
227 this->
name = this->parameter_decl->getNameAsString();
229 if (this->
name ==
"") {
231 this->
name = fmt::format(
"unspecified_position_{}", this->position);
233 data_warning(fmt::format(
"class {} method {} parameter index {} has no variable name",
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()) {
248 this->
default_value = std::regex_replace(source, std::regex(
"^\\s*=\\s*"),
"");
250 if (this->default_value ==
"{}") {
271 method_decl(method_decl),
272 name(method_decl->getQualifiedNameAsString()),
273 js_name(method_decl->getNameAsString()),
274 wrapped_class(wrapped_class),
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;
287 std::cerr << fmt::format(
"not overriding method name {}", this->
js_name) << std::endl;
292 std::cerr << fmt::format(
"***** Parsing method {}", this->
name) << std::endl;
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;
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) {
312 this->
compiler_instance.getPreprocessor().getSourceManager(), comment->getSourceRange());
314 cerr <<
"FullComment: " << comment_text << endl;
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()) {
325 child_comment_source_range);
327 cerr <<
"Child comment kind: " << (*i)->getCommentKind() <<
": " << child_comment_text << endl;
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;
335 std::cerr << fmt::format(
"param name aswritten: {}", param_command->getParamNameAsWritten().str()) << std::endl;
338 auto command_param_name = param_command->getParamNameAsWritten().str();
339 std::cerr << fmt::format(
"got command param name {}", command_param_name) << std::endl;
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 = ¶meter;
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) {
360 auto ¶m_info = *matching_parameter_info_ptr;
361 if (param_command->getParagraph() !=
nullptr) {
364 param_command->getParagraph()->getSourceRange());
368 fmt::format(
"method parameter comment name doesn't match any parameter {}",
369 command_param_name));
372 cerr <<
"is not param command comment" << endl;
377 cerr <<
"No comment on " << method_decl->getNameAsString() << endl;
430 bool first_default_argument =
true;
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;
440 if (param.default_value ==
"") {
441 assert(first_default_argument);
444 if (!first_default_argument) {
448 first_default_argument =
false;
451 QualType default_arg_type = param.type.type.getNonReferenceType();
452 default_arg_type.removeLocalConst();
457 values << param.default_value;
460 return fmt::format(
"std::tuple<{}>({})", types.str(), values.str());
466 result << fmt::format(
"{}, {}", this->
return_type.
name, this->wrapped_class.class_name);
489 bool first_result =
true;
494 first_result =
false;
495 result << fmt::format(
"{}", parameter.type.name);
503 bool first_result =
true;
508 first_result =
false;
509 result << fmt::format(
"{}", parameter.name);
604 result << this->
name <<
"(";
612 result << p.type.name;
640 constructor_decl(constructor_decl)
643 cerr <<
"About to get full source for constructor in " << wrapped_class.
name_alias << endl;
644 auto full_source_loc = FullSourceLoc(constructor_decl->getLocation(),
646 fprintf(stderr,
"%s constructor Decl at line %d, file id: %d\n",
648 full_source_loc.getExpansionLineNumber(),
649 full_source_loc.getFileID().getHashValue());
664 fmt::format(
"Error: because duplicate JS constructor function name: {} in class {}",
667 cerr << (fmt::format(
"Already used constructor name: {}",
name)) << endl;
670 cerr << fmt::format(
"for {}, wrapping constructor {}", wrapped_class.
name_alias,
671 this->js_name) << endl;
679 result << fmt::format(
" class_wrapper.add_constructor<{}>(\"{}\", isolate, {});",
687 if (OO_Call ==
method_decl->getOverloadedOperator()) {
688 result << fmt::format(
" class_wrapper.make_callable<{}>(&{});\n",
692 result << fmt::format(
" class_wrapper.add_method<{}>(\"{}\", &{}, {});\n",
701 result << fmt::format(
" /**") << endl;
703 result << parameter.generate_js_stub();
709 result << fmt::format(
" */") << endl;
726 result << fmt::format(
" class_wrapper.add_static_method<{}>(\"{}\", &{}, {});\n",
735 result << fmt::format(
" /**") << endl;
737 result << parameter.generate_js_stub();
742 result << fmt::format(
" */") << endl;
754 result << fmt::format(
" /**") << endl;
756 result << parameter.generate_js_stub();
758 result << fmt::format(
" */") << endl;
WrappedClass & wrapped_class
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++ ...
vector< ParameterInfo > parameters
string name
name of actual type
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
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
StaticFunction(WrappedClass &wrapped_class, CXXMethodDecl const *method_decl)
#define V8TOOLKIT_USE_NAME_PREFIX
std::vector< std::string > used_constructor_names
std::vector< string > get_regex(const string ®ex_string) const
string get_default_argument_tuple_string() const
bool is_templated() const
void data_warning(const string &warning)
string generate_js_bindings()
bool has(const std::string &target) const
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
string generate_js_bindings()
void add_static_name(string const &name)
#define V8TOOLKIT_READONLY_STRING
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()
string generate_js_stub()
MemberFunction(WrappedClass &wrapped_class, CXXMethodDecl const *method_decl)
CXXMethodDecl const * method_decl
map< string, string > cpp_to_js_type_conversions
string plain_name
name of type without reference or pointers
string generate_js_stub()
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)