15 if (
const CXXRecordDecl * klass = Result.Nodes.getNodeAs<clang::CXXRecordDecl>(
"not std:: class")) {
18 std::cerr << fmt::format(
"Got a class that's not a std:: class {}", class_name) << std::endl;
21 if (klass->isDependentType()) {
22 cerr <<
"Skipping 'class with annotation' dependent type: " << class_name << endl;
27 if (std::regex_match(name, regex(
"^(class\\s+|struct\\s+)?std::.*$"))) {
30 if (std::regex_match(name, regex(
"^(class\\s+|struct\\s+)?__.*$"))) {
34 cerr << endl <<
"Got class definition: " << class_name << endl;
35 fprintf(stderr,
"decl ptr: %p\n", (
void *)klass);
39 cerr <<
"SKIPPING BAD RECORD DECL" << endl;
42 cerr <<
"Storing it for later processing (unless dupe)" << endl;
48 if (
const CXXRecordDecl * klass = Result.Nodes.getNodeAs<clang::CXXRecordDecl>(
"forward declaration with annotation")) {
51 cerr << endl <<
"Got forward declaration with annotation: " << class_name << endl;
54 auto described_tmpl = klass->getDescribedClassTemplate();
55 if (klass->isDependentType() && described_tmpl) {
56 fprintf(stderr,
"described template %p, %s\n", (
void *)described_tmpl, described_tmpl->getQualifiedNameAsString().c_str());
57 printf(
"Merging %d annotations with template %p\n", (
int)
Annotations(klass).
get().size(), (
void*)described_tmpl);
63 if (
const CXXRecordDecl * klass = Result.Nodes.getNodeAs<clang::CXXRecordDecl>(
"class derived from WrappedClassBase")) {
66 cerr <<
"skipping 'bad' record decl" << endl;
69 if (klass->isDependentType()) {
70 cerr <<
"skipping dependent type" << endl;
75 if (std::regex_match(name, regex(
"^(class\\s+|struct\\s+)?std::.*$"))) {
78 if (std::regex_match(name, regex(
"^(class\\s+|struct\\s+)?__.*$"))) {
84 cerr <<
"Skipping class because it's explicitly marked SKIP" << endl;
93 cerr <<
"SKIPPING BAD RECORD DECL" << endl;
96 cerr <<
"Storing it for later processing (unless dupe)" << endl;
102 if (
auto typedef_decl = Result.Nodes.getNodeAs<clang::TypedefNameDecl>(
"named decl")) {
103 auto qual_type = typedef_decl->getUnderlyingType();
104 auto record_decl = qual_type->getAsCXXRecordDecl();
111 if (std::regex_match(name, regex(
"^(class\\s+|struct\\s+)?std::.*$"))) {
114 if (std::regex_match(name, regex(
"^(class\\s+|struct\\s+)?__.*$"))) {
121 string name_alias = typedef_decl->getNameAsString();
122 std::cerr << fmt::format(
"Annotated type name: {} => {}", record_decl->getQualifiedNameAsString(), typedef_decl->getNameAsString()) << std::endl;
127 wrapped_class->name_alias = name_alias;
134 #ifdef TEMPLATE_INFO_ONLY 136 if (
const ClassTemplateSpecializationDecl * klass = Result.Nodes.getNodeAs<clang::ClassTemplateSpecializationDecl>(
"class")) {
141 if (std::regex_search(class_name, std::regex(
"^(class|struct)\\s+v8toolkit"))) {
143 print_logging =
true;
144 cerr << fmt::format(
"Got class {}", class_name) << endl;
148 #ifdef TEMPLATE_FILTER_STD 149 if (std::regex_search(class_name, std::regex(
"^std::"))) {
150 if (print_logging) cerr <<
"Filtering out because in std::" << endl;
157 auto tmpl = klass->getSpecializedTemplate();
159 cerr <<
"got specialized template " << tmpl->getQualifiedNameAsString() << endl;
164 #ifdef TEMPLATE_FILTER_STD 165 if (std::regex_search(tmpl->getQualifiedNameAsString(), std::regex(
"^std::"))) {
176 if (
const CXXMethodDecl * method = Result.Nodes.getNodeAs<clang::CXXMethodDecl>(
"method")) {
177 auto method_name = method->getQualifiedNameAsString();
178 const FunctionDecl * pattern =
nullptr;
180 if (!method->isTemplateInstantiation()) {
183 #ifdef TEMPLATE_FILTER_STD 184 if (std::regex_search(method_name, std::regex(
"^std::"))) {
189 pattern = method->getTemplateInstantiationPattern();
195 llvm::report_fatal_error(
"method is template insantiation but pattern still nullptr");
204 if (std::regex_search(method_name, std::regex(
"function_in_temp"))) {
205 cerr << endl <<
"*******Found function in templated class decl" << endl;
206 fprintf(stderr,
"Method decl ptr: %p\n", (
void*) method);
207 cerr <<
"is dependent context: " << method->isDependentContext() << endl;
208 cerr <<
"has dependent template info: " << (method->getDependentSpecializationInfo() !=
nullptr) << endl;
209 cerr <<
"is template instantiation: " << (method->isTemplateInstantiation()) << endl;
210 cerr <<
"has instantiation pattern: " << (method->getTemplateInstantiationPattern() !=
nullptr) << endl;
211 if (method->getTemplateInstantiationPattern()) {
212 fprintf(stderr,
"template instantiation pattern ptr: %p\n", (
void*) method->getTemplateInstantiationPattern());
214 print_logging =
true;
217 const FunctionTemplateDecl * function_template_decl = method->getDescribedFunctionTemplate();
219 if (function_template_decl ==
nullptr && method->getTemplateSpecializationInfo()) {
220 function_template_decl = method->getTemplateSpecializationInfo()->getTemplate();
223 if (function_template_decl) {
224 cerr << fmt::format(
"'real' templated method {} has instantiation pattern: {}", method_name, method->getTemplateInstantiationPattern() !=
nullptr) << endl;
225 fprintf(stderr,
"method: %p, instantiation pattern: %p\n", (
void *)method, (
void*)method->getTemplateInstantiationPattern());
227 cerr << fmt::format(
"Got method {}", method_name) << endl;
230 if (print_logging) cerr <<
"not interesting method" << endl;
237 #endif // end TEMPLATE_INFO_ONLY 254 auto full_source_loc = FullSourceLoc(wrapped_class.
decl->getLocation(), this->source_manager);
256 auto file_id = full_source_loc.getFileID();
289 if (
print_logging) cerr <<
"About to process base class info" << endl;
298 "Not wrapping constructor for class only wrapped because it's base class of another wrapped type")
301 cerr << fmt::format(
"Not wrapping because class has DO NOT WRAP CONSTRUCTORS annotation") << endl;
302 }
else if (wrapped_class.
decl->isAbstract()) {
303 cerr <<
"Skipping all constructors because class is abstract: " << class_name << endl;
305 cerr << fmt::format(
"'force no constructors' set on {} so skipping making constructors", class_name)
310 "About to process constructors for {} -- passed all checks to skip class constructors.",
318 if (top_level_class->constructors.empty() && top_level_class->
has_static_method) {
322 if (!static_name_annotation.empty()) {
323 static_name = static_name_annotation[0];
325 top_level_class->constructors.insert(
326 fmt::format(
"{} class_wrapper.expose_static_methods(\"{}\", isolate);\n", indentation,
335 cerr <<
"Type " << top_level_class->
class_name <<
" **IS** bidirectional" << endl;
337 auto generated_header_name = fmt::format(
"\"v8toolkit_generated_bidirectional_{}.h\"",
341 auto bidirectional_class_name = fmt::format(
"JS{}", top_level_class->
get_short_name());
345 cerr <<
"Creating new Wrapped class object for " << bidirectional_class_name << endl;
346 js_wrapped_class =
new WrappedClass(bidirectional_class_name,
350 auto &bidirectional = *js_wrapped_class;
351 bidirectional.base_types.insert(top_level_class);
353 cerr << fmt::format(
"Adding derived bidirectional type {} to base type: {}",
354 bidirectional.class_name, wrapped_class.
name_alias) << endl;
359 bidirectional.include_files.insert(generated_header_name);
360 bidirectional.my_include = generated_header_name;
362 BidirectionalBindings bd(this->
ci, *js_wrapped_class, wrapped_class);
363 bd.generate_bindings();
368 cerr <<
"Type " << top_level_class->
class_name <<
" is not bidirectional" << endl;
379 cerr << warning << endl;
385 cerr <<
"Errors detected:" << endl;
387 cerr << error << endl;
389 llvm::report_fatal_error(
"Errors detected in source data");
394 cerr <<
"*************" << endl <<
"ABOUT TO GENERATE OUTPUT FILES" << endl <<
"*****************" << endl;
403 void ClassHandler::handle_method(
WrappedClass & klass, CXXMethodDecl * method) {
406 std::string full_method_name(method->getQualifiedNameAsString());
407 std::string short_method_name(method->getNameAsString());
427 full_method_name.c_str(), export_type);
432 if (method->getAccess() != AS_public) {
439 if (method->isOverloadedOperator()) {
442 if (OO_Call == method->getOverloadedOperator()) {
448 printf(
"**skipping overloaded operator %s\n", full_method_name.c_str());
452 if (dyn_cast<CXXConstructorDecl>(method)) {
456 if (dyn_cast<CXXDestructorDecl>(method)) {
478 if (method->isVirtual() && method->size_overridden_methods()) {
479 if (
PRINT_SKIPPED_EXPORT_REASONS) printf(
"**skipping derived-class override of base class virtual function %s\n", full_method_name.c_str());
483 if (dyn_cast<CXXConversionDecl>(method)) {
495 if (top_level_class->names.count(short_method_name)) {
496 data_error(fmt::format(
"Skipping duplicate name {}/{} :: {}\n",
503 top_level_class->names.insert(short_method_name);
505 auto parsed_method = make_unique<ParsedMethod>(this->
ci, klass, method);
514 std::stringstream result;
516 auto short_field_name = field->getNameAsString();
517 auto full_field_name = field->getQualifiedNameAsString();
520 cerr <<
"Processing data member for: " << containing_class.
name_alias <<
": " << full_field_name << endl;
533 top_level_class->names.insert(short_field_name);
545 std::cerr << fmt::format(
"incrementing declaration count for {} - data member", top_level_class->
name_alias) << std::endl;
static map< const ClassTemplateDecl *, Annotations > annotations_for_class_templates
int matched_classes_returned
static WrappedClass & get_or_insert_wrapped_class(const CXXRecordDecl *decl, CompilerInstance &compiler_instance, FOUND_METHOD found_method)
string name_alias
this is the possibly shortened javascript name of the type - not necessarily valid in generated c++ ...
void data_error(const string &error)
static ClassTemplate & get_or_create(const ClassTemplateDecl *decl)
void update_wrapped_class_for_type(WrappedClass &wrapped_class, QualType qual_type)
std::string get_type_string(QualType qual_type, const std::string &indentation)
static FunctionTemplate & get_or_create(const FunctionDecl *decl)
set< string > include_files
bool is_good_record_decl(const CXXRecordDecl *decl)
#define V8TOOLKIT_NAME_ALIAS_STRING
virtual void onEndOfTranslationUnit() override
#define V8TOOLKIT_BIDIRECTIONAL_CLASS_STRING
bool force_no_constructors
#define PRINT_SKIPPED_EXPORT_REASONS
vector< string > data_errors
std::string get_include_string_for_fileid(CompilerInstance &compiler_instance, FileID &file_id)
FOUND_METHOD found_method
void print_specialization_info(const CXXRecordDecl *decl)
std::vector< string > get_regex(const string ®ex_string) const
#define V8TOOLKIT_EXPOSE_STATIC_METHODS_AS_PREFIX
void generate_bidirectional_classes(CompilerInstance &compiler_instance)
EXPORT_TYPE get_export_type(const NamedDecl *decl, EXPORT_TYPE previous)
virtual void run(const ast_matchers::MatchFinder::MatchResult &Result) override
#define V8TOOLKIT_NONE_STRING
bool has(const std::string &target) const
static WrappedClass * get_if_exists(const CXXRecordDecl *decl)
std::string handle_data_member(WrappedClass &containing_class, FieldDecl *field, const std::string &indentation)
void generate_javascript_stub(std::string const &filename)
set< WrappedClass * > derived_types
static void insert_wrapped_class(WrappedClass *wrapped_class)
vector< string > data_warnings
std::string get_canonical_name_for_decl(const TypeDecl *decl)
CXXRecordDecl const * decl
static map< const CXXRecordDecl *, string > names_for_record_decls
static map< const CXXRecordDecl *, Annotations > annotations_for_record_decls
void handle_class(WrappedClass &wrapped_class, bool top_level=true, const std::string &indentation="")
#define V8TOOLKIT_DO_NOT_WRAP_CONSTRUCTORS_STRING
std::string get_short_name() const