Urho3D/Source/Tools/BindingGenerator/ASResult.cpp

1155 lines
35 KiB
C++

//
// Copyright (c) 2008-2021 the Urho3D project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include "ASResult.h"
#include "Tuning.h"
#include "Utils.h"
#include <fstream>
#include <cassert>
#include <unordered_map>
#include <memory>
extern string _sourceDir;
namespace ASBindingGenerator
{
ASGeneratedFile_WithRegistrationFunction::ASGeneratedFile_WithRegistrationFunction(const string& outputFilePath, const string& functionName)
{
outputFilePath_ = outputFilePath;
functionName_ = functionName;
}
// ============================================================================
void ASGeneratedFile_Members::Save()
{
ofstream out(outputFilePath_);
out <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"#include \"../Precompiled.h\"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"#include \"../AngelScript/Manual.h\"\n"
"\n"
"namespace Urho3D\n"
"{\n"
"\n"
<< glue_.str() <<
"void " << functionName_ << "(asIScriptEngine* engine)\n"
"{\n"
<< reg_.str() <<
"}\n"
"\n"
"}\n";
}
// ============================================================================
ASGeneratedFile_Templates::ASGeneratedFile_Templates(const string& outputFilePath)
{
outputFilePath_ = outputFilePath;
}
void ASGeneratedFile_Templates::Save()
{
ofstream out(outputFilePath_);
out <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"#pragma once\n"
"\n"
"#include \"../Precompiled.h\"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"\n"
"#include \"../AngelScript/Manual.h\"\n"
"\n"
"namespace Urho3D\n"
"{\n"
"\n"
<< glue_.str()
<< reg_.str() <<
"}\n";
}
bool ProcessedEnum::operator <(const ProcessedEnum& rhs) const
{
if (insideDefine_ != rhs.insideDefine_)
return insideDefine_ < rhs.insideDefine_;
return name_ < rhs.name_;
}
bool ProcessedGlobalFunction::operator <(const ProcessedGlobalFunction& rhs) const
{
if (insideDefine_ != rhs.insideDefine_)
return insideDefine_ < rhs.insideDefine_;
if (name_ != rhs.name_)
return name_ < rhs.name_;
// Overloads with the same name may exist
if (comment_ != rhs.comment_)
return comment_ < rhs.comment_;
// Different specializations of the same template and aliases have the same comment
return registration_ < rhs.registration_;
}
bool ProcessedGlobalVariable::operator <(const ProcessedGlobalVariable& rhs) const
{
if (insideDefine_ != rhs.insideDefine_)
return insideDefine_ < rhs.insideDefine_;
return name_ < rhs.name_;
}
bool ProcessedClass::operator <(const ProcessedClass& rhs) const
{
if (inherianceDeep_ != rhs.inherianceDeep_)
return inherianceDeep_ < rhs.inherianceDeep_;
if (insideDefine_ != rhs.insideDefine_)
return insideDefine_ < rhs.insideDefine_;
return name_ < rhs.name_;
}
bool MemberRegistrationError::operator <(const MemberRegistrationError& rhs) const
{
if (name_ != rhs.name_)
return name_ < rhs.name_;
return comment_ < rhs.comment_;
}
namespace Result
{
vector<ProcessedEnum> enums_;
// Write result to Generated_Enums.cpp
static void SaveEnums()
{
sort(enums_.begin(), enums_.end());
ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Enums.cpp");
ofs <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"// We need register all enums before registration of any functions because functions can use any enums\n"
"\n"
"#include \"../Precompiled.h\"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"\n"
"namespace Urho3D\n"
"{\n"
"\n";
for (const ProcessedEnum& processedEnum : enums_)
{
if (!processedEnum.glue_.size())
continue;
if (!processedEnum.insideDefine_.empty())
ofs << "#ifdef " << processedEnum.insideDefine_ << "\n";
ofs << "// " << processedEnum.comment_ << "\n";
for (const string& glue : processedEnum.glue_)
ofs << glue << "\n";
if (!processedEnum.insideDefine_.empty())
ofs << "#endif\n";
ofs << "\n";
}
ofs <<
"void ASRegisterGeneratedEnums(asIScriptEngine* engine)\n"
"{\n";
bool isFirst = true;
string openedDefine;
for (const ProcessedEnum& processedEnum : enums_)
{
if (processedEnum.insideDefine_ != openedDefine && !openedDefine.empty())
{
ofs << "#endif\n";
openedDefine.clear();
}
if (!isFirst)
ofs << "\n";
if (processedEnum.insideDefine_ != openedDefine && !processedEnum.insideDefine_.empty())
{
ofs << "#ifdef " << processedEnum.insideDefine_ << "\n";
openedDefine = processedEnum.insideDefine_;
}
ofs << " // " << processedEnum.comment_ << "\n";
for (const string& registration : processedEnum.registration_)
ofs << " " << registration << "\n";
isFirst = false;
}
if (!openedDefine.empty())
ofs << "#endif\n";
ofs <<
"}\n"
"\n"
"}\n";
}
// ============================================================================
vector<ProcessedGlobalFunction> globalFunctions_;
// Write result to Generated_GlobalFunctions.cpp
static void SaveGlobalFunctions()
{
sort(globalFunctions_.begin(), globalFunctions_.end());
ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_GlobalFunctions.cpp");
ofs <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"#include \"../Precompiled.h\"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"\n"
"namespace Urho3D\n"
"{\n"
"\n";
for (const ProcessedGlobalFunction& globalFunction : globalFunctions_)
{
if (globalFunction.glue_.empty())
continue;
if (!globalFunction.insideDefine_.empty())
ofs << "#ifdef " << globalFunction.insideDefine_ << "\n";
ofs << "// " << globalFunction.comment_ << "\n";
ofs << globalFunction.glue_ << "\n";
if (!globalFunction.insideDefine_.empty())
ofs << "#endif\n";
ofs << "\n";
}
ofs <<
"void ASRegisterGeneratedGlobalFunctions(asIScriptEngine* engine)\n"
"{\n";
bool isFirst = true;
string openedDefine;
string lastComment;
for (const ProcessedGlobalFunction& globalFunction : globalFunctions_)
{
if (globalFunction.insideDefine_ != openedDefine && !openedDefine.empty())
{
ofs << "#endif\n";
openedDefine.clear();
}
if (!isFirst && lastComment != globalFunction.comment_)
ofs << "\n";
if (globalFunction.insideDefine_ != openedDefine && !globalFunction.insideDefine_.empty())
{
ofs << "#ifdef " << globalFunction.insideDefine_ << "\n";
openedDefine = globalFunction.insideDefine_;
}
if (lastComment != globalFunction.comment_)
ofs << " // " << globalFunction.comment_ << "\n";
ofs << " " << globalFunction.registration_ << "\n";
isFirst = false;
lastComment = globalFunction.comment_;
}
if (!openedDefine.empty())
ofs << "#endif\n";
ofs <<
"}\n"
"\n"
"}\n";
}
// ============================================================================
vector<ProcessedGlobalVariable> globalVariables_;
// Write result to Generated_GlobalVariables.cpp
static void SaveGlobalVariables()
{
sort(globalVariables_.begin(), globalVariables_.end());
ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_GlobalVariables.cpp");
ofs <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"#include \"../Precompiled.h\"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"\n"
"// Some headers could re-define M_PI, ensure that it's undefined\n"
"#undef M_PI\n"
"\n"
"namespace Urho3D\n"
"{\n"
"\n"
"void ASRegisterGeneratedGlobalVariables(asIScriptEngine* engine)\n"
"{\n";
bool isFirst = true;
string openedDefine;
string lastComment;
for (const ProcessedGlobalVariable& globalVariable : globalVariables_)
{
if (globalVariable.insideDefine_ != openedDefine && !openedDefine.empty())
{
ofs << "#endif\n";
openedDefine.clear();
}
if (!isFirst && lastComment != globalVariable.comment_)
ofs << "\n";
if (globalVariable.insideDefine_ != openedDefine && !globalVariable.insideDefine_.empty())
{
ofs << "#ifdef " << globalVariable.insideDefine_ << "\n";
openedDefine = globalVariable.insideDefine_;
}
if (lastComment != globalVariable.comment_)
ofs << " // " << globalVariable.comment_ << "\n";
ofs << " " << globalVariable.registration_ << "\n";
isFirst = false;
lastComment = globalVariable.comment_;
}
if (!openedDefine.empty())
ofs << "#endif\n";
ofs <<
"}\n"
"\n"
"}\n";
}
// ============================================================================
vector<ProcessedClass> classes_;
// Write result to Generated_ObjectTypes.cpp
static void SaveObjectTypes()
{
ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_ObjectTypes.cpp");
ofs <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"// We need register all types before registration of any functions because functions can use any types\n"
"\n"
"#include \"../Precompiled.h\"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"\n"
"namespace Urho3D\n"
"{\n"
"\n"
"void ASRegisterGeneratedObjectTypes(asIScriptEngine* engine)\n"
"{\n";
string openedDefine;
bool isFirst = true;
for (const ProcessedClass& processedClass : classes_)
{
if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
{
ofs << "#endif\n";
openedDefine.clear();
}
if (!isFirst)
ofs << "\n";
if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
{
ofs << "#ifdef " << processedClass.insideDefine_ << "\n";
openedDefine = processedClass.insideDefine_;
}
ofs
<< " // " << processedClass.comment_ << "\n"
<< " " << processedClass.objectTypeRegistration_ << "\n";
isFirst = false;
}
if (!openedDefine.empty())
ofs << "#endif\n";
ofs <<
"}\n"
"\n"
"}\n";
}
// Write result to Generated_DefaultConstructors.cpp
static void SaveDefaultConstructors()
{
ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_DefaultConstructors.cpp");
ofs <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"// We need register default constructors before any members to allow using in Array<type>\n"
"\n"
"#include \"../Precompiled.h\"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"\n"
"namespace Urho3D\n"
"{\n";
string openedDefine;
for (const ProcessedClass& processedClass : classes_)
{
if (!processedClass.defaultConstructor_)
continue;
if (processedClass.defaultConstructor_->glue_.empty())
continue;
if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
{
ofs << "\n#endif\n";
openedDefine.clear();
}
ofs << "\n";
if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
{
ofs << "#ifdef " << processedClass.insideDefine_ << "\n\n";
openedDefine = processedClass.insideDefine_;
}
ofs <<
"// " << processedClass.defaultConstructor_->comment_ << "\n" <<
processedClass.defaultConstructor_->glue_;
}
if (!openedDefine.empty())
{
ofs << "\n#endif\n";
openedDefine.clear();
}
ofs <<
"\n"
"void ASRegisterGeneratedDefaultConstructors(asIScriptEngine* engine)\n"
"{\n";
bool isFirst = true;
for (const ProcessedClass& processedClass : classes_)
{
if (!processedClass.defaultConstructor_)
continue;
if (processedClass.noBind_)
continue;
if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
{
ofs << "#endif\n";
openedDefine.clear();
}
if (!isFirst)
ofs << "\n";
if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
{
ofs << "#ifdef " << processedClass.insideDefine_ << "\n";
openedDefine = processedClass.insideDefine_;
}
ofs <<
" // " << processedClass.defaultConstructor_->comment_ << "\n" <<
" " << processedClass.defaultConstructor_->registration_ << "\n";
isFirst = false;
}
if (!openedDefine.empty())
ofs << "#endif\n";
ofs <<
"}\n"
"\n"
"}\n";
}
// Write result to Generated_Classes.cpp
static void SaveGeneratedClasses()
{
ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Classes.cpp");
ofs <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"#include \"../Precompiled.h\"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"#include \"../AngelScript/Generated_Members.h\"\n"
"#include \"../AngelScript/Manual.h\"\n"
"\n"
"namespace Urho3D\n"
"{\n";
string openedDefine;
for (ProcessedClass& processedClass : classes_)
{
if (processedClass.noBind_)
continue;
if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
{
ofs << "\n#endif // def " << openedDefine << "\n";
openedDefine.clear();
}
ofs << "\n";
if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
{
ofs << "#ifdef " << processedClass.insideDefine_ << "\n\n";
openedDefine = processedClass.insideDefine_;
}
if (processedClass.destructor_ && !processedClass.destructor_->glue_.empty())
{
ofs <<
"// " << processedClass.destructor_->comment_ << "\n"
<< processedClass.destructor_->glue_ <<
"\n";
}
for (const SpecialMethodRegistration& nonDefaultConstructor : processedClass.nonDefaultConstructors_)
{
ofs <<
"// " << nonDefaultConstructor.comment_ << "\n"
<< nonDefaultConstructor.glue_ <<
"\n";
}
for (const Registration& personalMethod : processedClass.personalMethods_)
{
if (personalMethod.glue_.size())
{
ofs <<
"// " << personalMethod.comment_ << "\n"
<< personalMethod.glue_ <<
"\n";
}
}
for (const Registration& personalStaticMethod : processedClass.personalStaticMethods_)
{
if (personalStaticMethod.glue_.size())
{
ofs <<
"// " << personalStaticMethod.comment_ << "\n"
<< personalStaticMethod.glue_ <<
"\n";
}
}
ofs <<
"// " << processedClass.comment_ << "\n"
"static void Register_" << processedClass.name_ << "(asIScriptEngine* engine)\n"
"{\n";
bool needGap = false;
sort(processedClass.unregisteredSpecialMethods_.begin(), processedClass.unregisteredSpecialMethods_.end());
for (const MemberRegistrationError& regError : processedClass.unregisteredSpecialMethods_)
{
ofs <<
" // " << regError.comment_ << "\n"
" // " << regError.message_ << "\n";
needGap = true;
}
if (needGap && processedClass.nonDefaultConstructors_.size())
ofs << '\n';
for (const SpecialMethodRegistration& nonDefaultConstructor : processedClass.nonDefaultConstructors_)
{
ofs <<
" // " << nonDefaultConstructor.comment_ << "\n"
" " << nonDefaultConstructor.registration_ << "\n";
needGap = true;
}
if (processedClass.destructor_)
{
if (needGap)
ofs << '\n';
ofs <<
" // " << processedClass.destructor_->comment_ << "\n"
" " << processedClass.destructor_->registration_ << "\n";
needGap = true;
}
if (needGap && processedClass.subclassRegistrations_.size())
ofs << '\n';
for (const string& subclassRegistration : processedClass.subclassRegistrations_)
{
ofs << " " << subclassRegistration << '\n';
needGap = true;
}
if (needGap)
ofs << '\n';
ofs <<
" RegisterMembers_" << processedClass.name_ << "<" << processedClass.name_ << ">(engine, \"" << processedClass.name_ << "\");\n"
"\n"
" #ifdef REGISTER_CLASS_MANUAL_PART_" << processedClass.name_ << "\n"
" REGISTER_CLASS_MANUAL_PART_" << processedClass.name_ << "();\n"
" #endif\n";
for (const MemberRegistrationError& unregisteredPersonalMethod : processedClass.unregisteredPersonalMethods_)
{
ofs <<
"\n"
" // " << unregisteredPersonalMethod.comment_ << "\n"
" // " << unregisteredPersonalMethod.message_ << "\n";
needGap = true;
}
for (const Registration& perosnalMethod : processedClass.personalMethods_)
{
ofs <<
"\n"
" // " << perosnalMethod.comment_ << "\n";
for (const string& reg : perosnalMethod.registration_)
ofs << " " << reg << '\n';
}
for (const MemberRegistrationError& unregisteredPersonalStaticMethod : processedClass.unregisteredPersonalStaticMethods_)
{
ofs <<
"\n"
" // " << unregisteredPersonalStaticMethod.comment_ << "\n"
" // " << unregisteredPersonalStaticMethod.message_ << "\n";
needGap = true;
}
for (const Registration& perosnalStaticMethod : processedClass.personalStaticMethods_)
{
ofs <<
"\n"
" // " << perosnalStaticMethod.comment_ << "\n";
for (const string& reg : perosnalStaticMethod.registration_)
ofs << " " << reg << '\n';
}
if (processedClass.additionalLines_.size())
ofs << '\n';
for (string str : processedClass.additionalLines_)
ofs << str << '\n';
ofs << "}\n";
}
if (!openedDefine.empty())
{
ofs << "\n#endif // def " << openedDefine << "\n";
openedDefine.clear();
}
ofs <<
"\n"
"void ASRegisterGeneratedClasses(asIScriptEngine* engine)\n"
"{\n";
bool isFirst = true;
for (const ProcessedClass& processedClass : classes_)
{
if (processedClass.noBind_)
continue;
if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
{
ofs << "#endif\n";
openedDefine.clear();
}
if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
{
if (!isFirst)
ofs << "\n";
ofs << "#ifdef " << processedClass.insideDefine_ << "\n";
openedDefine = processedClass.insideDefine_;
}
ofs << " Register_" << processedClass.name_ << "(engine);\n";
isFirst = false;
}
if (!openedDefine.empty())
ofs << "#endif\n";
ofs <<
"}\n"
"\n"
"}\n";
}
struct MemberCppFile
{
ofstream ofs_;
string openedDefine_;
bool needGap_ = false;
MemberCppFile(const string& dirName)
{
string fileName = _sourceDir + "/Source/Urho3D/AngelScript/Generated_Members_" + dirName + ".cpp";
ofs_ = ofstream(fileName);
ofs_ <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"#include \"../Precompiled.h\"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"#include \"../AngelScript/Generated_ClassMembers.h\"\n"
"#include \"../AngelScript/Manual.h\"\n"
"\n"
"namespace Urho3D\n"
"{\n";
}
};
unordered_map<string, shared_ptr<MemberCppFile>> memberCppFiles_;
shared_ptr<MemberCppFile> GetMemberCppFile(const string& dirName)
{
auto it = memberCppFiles_.find(dirName);
if (it == memberCppFiles_.end())
{
auto newElement = memberCppFiles_.emplace(dirName, make_shared<MemberCppFile>(dirName));
it = newElement.first;
}
return (*it).second;
}
// Write result to GeneratedClassMembers.cpp and GeneratedClassMembers.h // TODO change comment
static void SaveClassMembers()
{
ofstream ofsH = ofstream(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Members.h");
ofsH <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"#pragma once\n"
"\n"
"#include \"../AngelScript/APITemplates.h\"\n"
"\n"
"#include \"../AngelScript/Generated_Includes.h\"\n"
"#include \"../AngelScript/Manual.h\"\n"
"\n"
"namespace Urho3D\n"
"{\n";
string openedDefine;
for (const ProcessedClass& processedClass : classes_)
{
if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
{
ofsH <<
"\n"
"#endif // def " << openedDefine << "\n";
openedDefine.clear();
}
if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
{
ofsH <<
"\n"
"#ifdef " << processedClass.insideDefine_ << "\n";
openedDefine = processedClass.insideDefine_;
}
for (const Registration& method : processedClass.templateMethods_)
{
if (method.glue_.size())
{
ofsH <<
"\n"
"// " << method.comment_ << "\n"
<< method.glue_;
}
}
for (const Registration& staticMethod : processedClass.templateStaticMethods_)
{
if (staticMethod.glue_.size())
{
ofsH <<
"\n"
"// " << staticMethod.comment_ << "\n"
<< staticMethod.glue_;
}
}
ofsH <<
"\n"
"// " << processedClass.comment_ << "\n"
"template <class T> void RegisterMembers_" << processedClass.name_ << "(asIScriptEngine* engine, const char* className)\n"
"{\n";
bool needGap = false;
if (processedClass.baseClassNames_.size())
{
for (const string& baseClassName : processedClass.baseClassNames_)
ofsH << " RegisterMembers_" << baseClassName << "<T>(engine, className);\n";
needGap = true;
}
if (needGap && processedClass.unregisteredTemplateMethods_.size())
ofsH << '\n';
for (const MemberRegistrationError& unregisteredTemplateMethod : processedClass.unregisteredTemplateMethods_)
{
ofsH <<
" // " << unregisteredTemplateMethod.comment_ << "\n"
" // " << unregisteredTemplateMethod.message_ << "\n";
needGap = true;
}
for (const Registration& method : processedClass.templateMethods_)
{
if (needGap)
ofsH << '\n';
ofsH << " // " << method.comment_ << '\n';
for (const string& registration : method.registration_)
ofsH << " " << registration << '\n';
needGap = true;
}
if (needGap && processedClass.unregisteredTemplateStaticMethods_.size())
ofsH << '\n';
for (const MemberRegistrationError& unregisteredTemplateStaticMethod : processedClass.unregisteredTemplateStaticMethods_)
{
ofsH <<
" // " << unregisteredTemplateStaticMethod.comment_ << "\n"
" // " << unregisteredTemplateStaticMethod.message_ << "\n";
needGap = true;
}
for (const Registration& staticMethod : processedClass.templateStaticMethods_)
{
if (needGap)
ofsH << '\n';
ofsH << " // " << staticMethod.comment_ << '\n';
for (const string& registration : staticMethod.registration_)
ofsH << " " << registration << '\n';
needGap = true;
}
if (needGap && processedClass.unregisteredTemplateFields_.size())
ofsH << '\n';
for (const MemberRegistrationError& unregisteredTemplateField : processedClass.unregisteredTemplateFields_)
{
ofsH <<
" // " << unregisteredTemplateField.comment_ << "\n"
" // " << unregisteredTemplateField.message_ << "\n";
needGap = true;
}
for (const Registration& field : processedClass.templateFields_)
{
if (needGap)
ofsH << '\n';
ofsH << " // " << field.comment_ << '\n';
for (const string& registration : field.registration_)
ofsH << " " << registration << '\n';
needGap = true;
}
if (needGap && processedClass.unregisteredTemplateStaticFields_.size())
ofsH << '\n';
for (const MemberRegistrationError& unregisteredTemplateStaticField : processedClass.unregisteredTemplateStaticFields_)
{
ofsH <<
" // " << unregisteredTemplateStaticField.comment_ << "\n"
" // " << unregisteredTemplateStaticField.message_ << "\n";
needGap = true;
}
for (const Registration& field : processedClass.templateStaticFields_)
{
if (needGap)
ofsH << '\n';
ofsH << " // " << field.comment_ << '\n';
for (const string& registration : field.registration_)
ofsH << " " << registration << '\n';
needGap = true;
}
if (needGap)
ofsH << '\n';
ofsH <<
" #ifdef REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "\n"
" REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "();\n"
" #endif\n";
ofsH << "}\n";
}
if (!openedDefine.empty())
{
ofsH <<
"\n"
"#endif // def " << openedDefine << "\n";
openedDefine.clear();
}
ofsH <<
"\n"
"} // namespace Urho3D\n";
}
static void SaveClasses()
{
sort(classes_.begin(), classes_.end());
SaveObjectTypes();
SaveDefaultConstructors();
SaveGeneratedClasses();
SaveClassMembers();
}
// ============================================================================
// List of all required header files
static vector<string> headers_;
// Discarded header files for statistic
static vector<string> ignoredHeaders_;
// Add header to lists if not added yet
void AddHeader(const string& headerFile)
{
if (IsIgnoredHeader(headerFile))
{
if (!CONTAINS(ignoredHeaders_, headerFile))
ignoredHeaders_.push_back(headerFile);
}
else
{
if (!CONTAINS(headers_, headerFile))
headers_.push_back(headerFile);
}
}
// Write result to Generated_Includes.h
static void SaveIncludes()
{
sort(headers_.begin(), headers_.end());
sort(ignoredHeaders_.begin(), ignoredHeaders_.end());
ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Includes.h");
ofs <<
"// DO NOT EDIT. This file is generated\n"
"\n"
"#pragma once\n"
"\n";
string openedDefine;
bool isFirst = true;
for (const string& header : headers_)
{
string insideDefine = InsideDefine(header);
if (insideDefine != openedDefine)
{
if (!openedDefine.empty())
{
ofs << "#endif\n";
openedDefine.clear();
}
if (!isFirst) // First include can be guarded. Avoid print \n before it
ofs << "\n";
if (!insideDefine.empty())
{
ofs << "#ifdef " << insideDefine << "\n";
openedDefine = insideDefine;
}
}
ofs << "#include \"" << header << "\"\n";
isFirst = false;
}
if (!openedDefine.empty())
{
ofs << "#endif\n";
openedDefine.clear();
}
if (headers_.size() > 0)
ofs << "\n";
if (ignoredHeaders_.size() > 0)
ofs << "// Ignored headers\n\n";
isFirst = true;
for (const string& header : ignoredHeaders_)
{
string insideDefine = InsideDefine(header);
if (insideDefine != openedDefine)
{
if (!openedDefine.empty())
{
ofs << "//#endif\n";
openedDefine.clear();
}
if (!isFirst) // First include can be guarded. Avoid print \n before it
ofs << "\n";
if (!insideDefine.empty())
{
ofs << "//#ifdef " << insideDefine << "\n";
openedDefine = insideDefine;
}
}
ofs << "//#include \"" << header << "\"\n";
isFirst = false;
}
if (!openedDefine.empty())
ofs << "//#endif\n";
}
}
void SaveResult()
{
Result::SaveEnums();
Result::SaveGlobalFunctions();
Result::SaveGlobalVariables();
Result::SaveClasses();
Result::SaveIncludes();
}
}