52 #define TEMPLATE_FILTER_STD    54 #define TEMPLATED_CLASS_PRINT_THRESHOLD 10    55 #define TEMPLATED_FUNCTION_PRINT_THRESHOLD 100    83                                                   {
"^(?:std::|eastl::)?(?:vector_)?(?:multi)?map", 
"Object.{$1, $2}"},
    85                                                   {
"^(?:const)?\\s*(?:unsigned)?\\s*(?:char|short|int|long|long long|float|double|long double)\\s*(?:const)?\\s*[*]?\\s*[&]?$", 
"Number"},
    86                                                   {
"^(?:const)?\\s*_?[Bb]ool\\s*(?:const)?\\s*[*]?\\s*[&]?$", 
"Boolean"},
    87                                                   {
"^(?:const)?\\s*(?:char\\s*[*]|(?:std::)?string)\\s*(?:const)?\\s*\\s*[&]?$", 
"String"},
    88                                                   {
"^void$", 
"Undefined"},
    89                                                   {
"^(?:std::)?unique_ptr", 
"$1"},
    90                                                   {
"^(?:std::)?basic_string", 
"String"},
    91                                                   {
"^\\s*nullptr\\s*$", 
"null"}
   117 function println(s){}
   129 function printobj(o){}
   135 function printobjall(o){}
   142 function require(module_name){}
   153 #include <fmt/ostream.h>   200 void print_vector(
const vector<string> & vec, 
const string & header, 
const string & indentation, 
bool ignore_empty) {
   202     if (ignore_empty && vec.empty()) {
   207         cerr << indentation << header << endl;
   209     for (
auto & str : vec) {
   210         cerr << indentation << 
" - " << str << endl;
   213         cerr << indentation << 
" * (EMPTY VECTOR)" << endl;
   222     if (decl == 
nullptr) {
   226     if (!decl->isThisDeclarationADefinition()) {
   230     for (
auto base : decl->bases()) {
   231         if (base.getType().getTypePtrOrNull() == 
nullptr) {
   232             llvm::report_fatal_error(fmt::format(
"base type ptr was null for {}", decl->getNameAsString()).c_str());
   245     auto include_source_location = compiler_instance.getPreprocessor().getSourceManager().getIncludeLoc(file_id);
   248     if (include_source_location.isValid()) {
   249         auto header_file = include_source_location.printToString(compiler_instance.getPreprocessor().getSourceManager());
   259     const char * text = compiler_instance.getPreprocessor().getSourceManager().getCharacterData(include_source_location, &invalid);
   260     const char * text_end = text + 1;
   261     while(*text_end != 
'>' && *text_end != 
'"') {
   265     return string(text, (text_end - text) + 1);
   271     auto full_source_loc = FullSourceLoc(source_location, compiler_instance.getPreprocessor().getSourceManager());
   273     auto file_id = full_source_loc.getFileID();
   278     if (type_decl == 
nullptr) {
   296     std::string text = Lexer::getSourceText(CharSourceRange::getTokenRange(source_range), sm, LangOptions(), 0);
   297     if (!text.empty() && text.at(text.size()-1) == 
',')
   298         return Lexer::getSourceText(CharSourceRange::getCharRange(source_range), sm, LangOptions(), 0);
   303 vector<string> count_top_level_template_parameters(
const std::string & source) {
   304     int open_angle_count = 0;
   305     vector<string> parameter_strings;
   307     for (
char c : source) {
   313             if (open_angle_count > 1) {
   316         } 
else if (c == 
'>') {
   318             if (open_angle_count > 0) {
   322             if (open_angle_count == 1) {
   323                 if (parameter_strings.size() == 0) {
   324                     parameter_strings.push_back(
"");
   325                     current = ¶meter_strings.back();
   328                     parameter_strings.push_back(
"");
   329                     current = ¶meter_strings.back();
   330                     if (open_angle_count > 1) {
   336             } 
else if (open_angle_count > 1) {
   341     if (
print_logging) 
if (
print_logging) cerr << 
"^^^^^^^^^^^^^^^ Counted " << parameter_strings.size() << 
" for " << source << endl;
   342     for (
auto & str : parameter_strings) {
   345     return parameter_strings;
   356     const ClassTemplateDecl * 
decl;
   357     int instantiations = 0;
   360         name = decl->getQualifiedNameAsString();
   369         for(
auto & tmpl : class_templates) {
   370             if (tmpl->decl == decl) {
   374         class_templates.emplace_back(make_unique<ClassTemplate>(decl));
   375         return *class_templates.back();
   387     int instantiations = 0;
   390         name = decl->getQualifiedNameAsString();
   399         for(
auto & tmpl : function_templates) {
   400             if (tmpl->decl == decl) {
   404         function_templates.emplace_back(make_unique<FunctionTemplate>(decl));
   405         return *function_templates.back();
   432     for (
auto & wrapped_class : WrappedClass::wrapped_classes) {
   434         if (wrapped_class->class_name == class_name) {
   446     vector<string> sfinaes;
   447     string forward_declarations = 
"#define V8TOOLKIT_V8CLASSWRAPPER_FORWARD_DECLARATIONS ";
   448     for (
auto & wrapped_class : wrapped_classes) {
   452         if (!wrapped_class->should_be_wrapped()) {
   455         sfinaes.emplace_back(wrapped_class->make_sfinae_to_match_wrapped_class());
   456         forward_declarations += wrapped_class->class_name + 
"; ";
   460     for(
int i = sfinaes.size() - 1; i >= 0; i--) {
   461         if (sfinaes[i] == 
"") {
   462             sfinaes.erase(sfinaes.begin() + i);
   468     if (sfinaes.size() > 40 ) {
   469         cerr << 
join(sfinaes, 
" || ") << endl;
   470         llvm::report_fatal_error(
"more 'sfinae's than arbitrary number used to catch likely errors - can be increased if needed");
   476     if (!sfinaes.empty()) {
   477         sfinae = 
string(
"#define V8TOOLKIT_V8CLASSWRAPPER_FULL_TEMPLATE_SFINAE ") + 
join(sfinaes, 
" || ") + 
"\n";
   480     forward_declarations += 
"\n";
   481     return sfinae + 
"\n" + forward_declarations;
   515 bool is_trivial_std_type(QualType & qual_type, 
std::string & output) {
   517     std::string canonical_name = qual_type.getCanonicalType().getAsString();
   520     if (std::regex_match(name, regex(
"^(const\\s+|volatile\\s+)*(class\\s+|struct\\s+)?std::[^<]*$"))) {
   521         output = handle_std(name);a
   525     else if (has_std(canonical_name) &&
   526              std::regex_match(name, regex(
"^[^<]*$"))) {
   527         output = handle_std(name);
   535 bool is_nontrivial_std_type(QualType & qual_type, 
std::string & output) {
   538     std::string canonical_name = qual_type.getCanonicalType().getAsString();
   539     if (
print_logging) cerr << 
"Checking nontrivial std type on " << name << 
" : " << canonical_name << endl;
   544     if (has_std(canonical_name) &&
   545              std::regex_match(name, matches, regex(
"^([^<]*<).*$"))) {
   546         output = handle_std(matches[1].str());
   560     auto original_qualifiers = qual_type.getLocalFastQualifiers();
   562     while (
auto typedef_type = dyn_cast<TypedefType>(qual_type)) {
   563         qual_type = typedef_type->getDecl()->getUnderlyingType();
   567     qual_type.setLocalFastQualifiers(original_qualifiers);
   569     auto canonical_qual_type = qual_type.getCanonicalType();
   571     static PrintingPolicy pp = PrintingPolicy(LangOptions());
   572     pp.adjustForCPlusPlus();
   573     auto canonical = canonical_qual_type.getAsString(pp);
   574     return regex_replace(canonical, regex(
"std::__1::"), 
"std::");
   579     bool turn_logging_off = 
false;
   587     if (
print_logging) cerr << indentation << 
"Started at " << qual_type.getAsString() << endl;
   588     if (
print_logging) cerr << indentation << 
"  And canonical name: " << qual_type.getCanonicalType().getAsString() << endl;
   589     if (
print_logging) cerr << indentation << 
"  And source " << source << endl;
   592     if (is_trivial_std_type(qual_type, std_result)) {
   593         if (
print_logging) cerr << indentation << 
"Returning trivial std:: type: " << std_result << endl << endl;
   598     bool is_reference = qual_type->isReferenceType();
   599     string reference_suffix = is_reference ? 
"&" : 
"";
   600     qual_type = qual_type.getNonReferenceType();
   602     stringstream pointer_suffix;
   606         if (!qual_type->getPointeeType().isNull()) {
   608             pointer_suffix << 
"*";
   609             qual_type = qual_type->getPointeeType();
   610             if (
print_logging) cerr << indentation << 
"stripped pointer, went to: " << qual_type.getAsString() << endl;
   615         if (dyn_cast<TypedefType>(qual_type) != 
nullptr) {
   617             if (
print_logging) cerr << indentation << 
"stripped typedef, went to: " << qual_type.getAsString() << endl;
   618             qual_type = dyn_cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType();
   623     if (
print_logging) cerr << indentation << 
"CHECKING TO SEE IF " << qual_type.getUnqualifiedType().getAsString() << 
" is a template specialization"<< endl;
   624     auto base_type_record_decl = qual_type.getUnqualifiedType()->getAsCXXRecordDecl();
   625     if (dyn_cast<ClassTemplateSpecializationDecl>(base_type_record_decl)) {
   629         if (
print_logging) cerr << indentation << 
"!!!!! Started with template specialization: " << qual_type.getAsString() << endl;
   634         string qual_type_string = qual_type.getAsString();
   637         bool nontrivial_std_type = 
false;
   638         if (is_nontrivial_std_type(qual_type, std_type_output)) {
   639             if (
print_logging) cerr << indentation << 
"is nontrivial std type and got result: " << std_type_output << endl;
   640             nontrivial_std_type = 
true;
   641             result << std_type_output;
   644         else if (!regex_match(qual_type_string, matches, regex(
"^([^<]+<).*(>[^>]*)$"))) {
   645             if (
print_logging) cerr << indentation << 
"short circuiting on " << original_qual_type.getAsString() << endl;
   647             return original_qual_type.getAsString();
   649             result << matches[1];
   650             if (
print_logging) cerr << indentation << 
"is NOT nontrivial std type" << endl;
   652         auto template_specialization_decl = dyn_cast<ClassTemplateSpecializationDecl>(base_type_record_decl);
   654         auto user_specified_template_parameters = count_top_level_template_parameters(source);
   657         auto & template_arg_list = template_specialization_decl->getTemplateArgs();
   658         if (user_specified_template_parameters.size() > template_arg_list.size()) {
   659     llvm::report_fatal_error(fmt::format(
"ERROR: detected template parameters > actual list size for {}", qual_type_string).c_str());
   662         auto template_types_to_handle = user_specified_template_parameters.size();
   665             template_types_to_handle = template_arg_list.size();
   669         for (decltype(template_arg_list.size()) i = 0; i < template_types_to_handle; i++) {
   673             if (
print_logging) cerr << indentation << 
"Working on template parameter " << i << endl;
   674             auto & arg = template_arg_list[i];
   676             switch(arg.getKind()) {
   677                 case clang::TemplateArgument::Type: {
   678                     if (
print_logging) cerr << indentation << 
"processing as type argument" << endl;
   679                     auto template_arg_qual_type = arg.getAsType();
   682                     if (
print_logging) cerr << indentation << 
"About to append " << template_type_string << 
" template type string onto existing: " << result.str() << endl;
   683                     result << template_type_string;
   685                 case clang::TemplateArgument::Integral: {
   686                     if (
print_logging) cerr << indentation << 
"processing as integral argument" << endl;
   687                     auto integral_value = arg.getAsIntegral();
   688                     if (
print_logging) cerr << indentation << 
"integral value radix10: " << integral_value.toString(10) << endl;
   689                     result << integral_value.toString(10);
   692                     if (
print_logging) cerr << indentation << 
"Oops, unhandled argument type" << endl;
   695         result << 
">" << pointer_suffix.str() << reference_suffix;
   696         if (
print_logging) cerr << indentation << 
"!!!!!Finished stringifying templated type to: " << result.str() << endl << endl;
   723         auto canonical_qual_type = original_qual_type.getCanonicalType();
   727         if (
print_logging) cerr << indentation << 
"returning canonical: " << canonical_qual_type.getAsString() << endl << endl;
   730         return canonical_qual_type.getAsString();
   743                                            const CXXMethodDecl * method,
   744                                            const string & annotation = 
"") {
   745     vector<string> results;
   746     auto parameter_count = method->getNumParams();
   747     for (
unsigned int i = 0; i < parameter_count; i++) {
   748         auto param_decl = method->getParamDecl(i);
   750         if (param_decl->hasDefaultArg()) {
   751             auto default_argument = param_decl->getDefaultArg();
   752             auto source_range = default_argument->getSourceRange();
   754             results.push_back(source);
   756             results.push_back(
"");
   764                                              const CXXMethodDecl * method,
   765                                              string const & annotation) {
   766     vector<QualType> results;
   767     auto parameter_count = method->getNumParams();
   768     for (
unsigned int i = 0; i < parameter_count; i++) {
   769         auto param_decl = method->getParamDecl(i);
   773         if (annotation != 
"" && !annotations.
has(annotation)) {
   774             if (
print_logging) cerr << 
"Skipping method parameter because it didn't have requested annotation: " << annotation << endl;
   777         auto param_qual_type = param_decl->getType();
   778         results.push_back(param_qual_type);
   784     vector<string> results;
   785     for (std::size_t i = 0; i < qual_types.size(); i++) {
   786         if (with_std_move && qual_types[i]->isRValueReferenceType()) {
   787             results.push_back(fmt::format(
"std::move(var{})", i+1));
   789             results.push_back(fmt::format(
"var{}", i+1));
   802     cerr << 
"*****" << endl;
   803     if (decl->isDependentType()) {
   804         cerr << fmt::format(
"{} is a dependent type", name) << endl;
   806     if (
auto spec = dyn_cast<ClassTemplateSpecializationDecl>(decl)) {
   807         fprintf(stderr, 
"decl is a ClassTemplateSpecializationDecl: %p\n", (
void *)decl);
   808         cerr << name << endl;
   810         if (
auto spec_tmpl = spec->getSpecializedTemplate()) {
   811             fprintf(stderr, 
"Specialized template: %p, %s\n", (
void *)spec_tmpl, spec_tmpl->getQualifiedNameAsString().c_str());
   814             cerr << 
"no spec tmpl" << endl;
   818         if (dyn_cast<ClassTemplatePartialSpecializationDecl>(decl)) {
   819             cerr << 
"It is also a partial specialization decl" << endl;
   821             cerr << 
"It is NOT a PARTIAL specialization decl" << endl;
   826         cerr << name << 
" is not a class template specialization decl" << endl;
   828     cerr << 
"*****END" << endl;
 
int matched_classes_returned
 
vector< string > types_to_ignore_regex
 
map< string, int > template_instantiations
 
bool generate_v8classwrapper_sfinae
 
static ClassTemplate & get_or_create(const ClassTemplateDecl *decl)
 
vector< QualType > get_method_param_qual_types(CompilerInstance &compiler_instance, const CXXMethodDecl *method, string const &annotation)
 
ClassTemplate(const ClassTemplateDecl *decl)
 
std::string get_include_for_source_location(CompilerInstance &compiler_instance, const SourceLocation &source_location)
 
std::string get_type_string(QualType qual_type, const std::string &indentation)
 
static vector< WrappedClass * > wrapped_classes
 
static FunctionTemplate & get_or_create(const FunctionDecl *decl)
 
string header_for_every_class_wrapper_file
 
string get_sfinae_matching_wrapped_classes(const vector< unique_ptr< WrappedClass >> &wrapped_classes)
 
std::string get_include_for_type_decl(CompilerInstance &compiler_instance, const TypeDecl *type_decl)
 
bool is_good_record_decl(const CXXRecordDecl *decl)
 
vector< unique_ptr< FunctionTemplate > > function_templates
 
const FunctionDecl * decl
 
vector< string > get_default_argument_values(CompilerInstance &compiler_instance, const CXXMethodDecl *method, const string &annotation="")
 
std::string js_api_header
 
std::vector< std::string > used_constructor_names
 
std::string get_include_string_for_fileid(CompilerInstance &compiler_instance, FileID &file_id)
 
vector< string > includes_for_every_class_wrapper_file
 
void print_specialization_info(const CXXRecordDecl *decl)
 
vector< string > generate_variable_names(vector< QualType > qual_types, bool with_std_move)
 
vector< std::unique_ptr< ClassTemplate > > class_templates
 
const ClassTemplateDecl * decl
 
FunctionTemplate(const FunctionDecl *decl)
 
bool has(const std::string &target) const 
 
std::string get_source_for_source_range(SourceManager &sm, SourceRange source_range)
 
vector< string > never_include_for_any_file
 
std::string get_canonical_name_for_decl(const TypeDecl *decl)
 
vector< string > base_types_to_ignore
 
map< string, string > cpp_to_js_type_conversions
 
std::string join(const T &source, const std::string &between=", ", bool leading_between=false)
 
bool has_wrapped_class(const CXXRecordDecl *decl)
 
map< string, string > static_method_renames
 
void print_vector(const vector< string > &vec, const string &header, const string &indentation, bool ignore_empty)