///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // THIS FILE IS A MODIFIED VERSION // https://github.com/sashi0034/angel-lsp/blob/main/examples/OpenSiv3D/make_predefined.cpp ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "DeerRender/Log.h" #include "DeerStudio/AngelScriptEngine.h" #include "angelscript.h" #include #include #include #include #include #include #include #include #include #include #include "DeerRender/DataStore.h" #include "DeerRender/Tools/Path.h" static std::stringstream stream; static std::string str; void printFuncList(const asIScriptEngine& engine) { for (int i = 0; i < engine.GetFuncdefCount(); ++i) { asITypeInfo* t = engine.GetFuncdefByIndex(i); if (!t) continue; asIScriptFunction* func = t->GetFuncdefSignature(); if (!func || func->GetSubType()) continue; std::string decl = func->GetDeclaration(true, true, true); // Detect class-scoped funcdefs by presence of "::" in the declaration size_t scopePos = decl.find("::"); if (scopePos != std::string::npos) continue; stream << "funcdef " << decl << ";\n"; } } void printEnumList(const asIScriptEngine& engine) { for (int i = 0; i < engine.GetEnumCount(); ++i) { const auto e = engine.GetEnumByIndex(i); if (!e) continue; std::string_view ns = e->GetNamespace(); if (!ns.empty()) stream << "namespace " << ns << " {\n"; stream << "enum " << e->GetName() << " {\n"; for (int j = 0; j < e->GetEnumValueCount(); ++j) { int value; stream << "\t" << e->GetEnumValueByIndex(j, &value) << " = " << value; if (j < e->GetEnumValueCount() - 1) stream << ","; stream << "\n"; } stream << "}\n"; if (!ns.empty()) stream << "}\n\n"; } } void writeParameters(asIScriptFunction* function) { for (int n = 0; n < function->GetParamCount(); n++) { int typeId; asDWORD flags; const char* name; const char* defaultArgument; function->GetParam(n, &typeId, &flags, &name, &defaultArgument); if (typeId == -1) { stream << "?"; } else { asITypeInfo* ti = function->GetEngine()->GetTypeInfoById(typeId); if (ti && (ti->GetFlags() & asOBJ_FUNCDEF)) { stream << ti->GetName(); } else { const char* typeName = function->GetEngine()->GetTypeDeclaration(typeId, false); stream << typeName; } } if (flags & asTM_INREF) stream << " &in "; else if (flags & asTM_OUTREF) stream << " &out "; else if (flags & asTM_INOUTREF) stream << " &inout "; if (name) { stream << " " << name; } if (n != function->GetParamCount() - 1) stream << ", "; } } void printClassTypeList(const asIScriptEngine& engine) { for (int i = 0; i < engine.GetObjectTypeCount(); ++i) { asITypeInfo* t = engine.GetObjectTypeByIndex(i); if (!t) continue; std::string_view ns = t->GetNamespace(); if (!ns.empty()) stream << "namespace " << ns << " {\n"; stream << "class " << t->GetName(); if (std::string("any") == t->GetName()) stream << " "; if (t->GetSubTypeCount() > 0) { stream << "<"; for (int sub = 0; sub < t->GetSubTypeCount(); ++sub) { if (sub > 0) stream << ", "; const auto st = t->GetSubType(sub); stream << st->GetName(); } stream << ">"; } stream << " {\n"; for (int i = 0; i < t->GetChildFuncdefCount(); ++i) { asITypeInfo* ftype = t->GetChildFuncdef(i); asIScriptFunction* func = ftype->GetFuncdefSignature(); std::string decl = func->GetDeclaration(false, false, true); stream << "\tfuncdef " << decl << ";\n"; } for (int j = 0; j < t->GetFactoryCount(); ++j) { asIScriptFunction* f = t->GetFactoryByIndex(j); stream << "\t" << t->GetName() << "("; writeParameters(f); stream << ");\n"; } for (int j = 0; j < t->GetBehaviourCount(); ++j) { asEBehaviours behaviours; const auto f = t->GetBehaviourByIndex(j, &behaviours); if (behaviours == asBEHAVE_CONSTRUCT || behaviours == asBEHAVE_DESTRUCT || behaviours == asBEHAVE_FACTORY) stream << "\t" << f->GetDeclaration(false, false, true) << ";\n"; } for (int j = 0; j < t->GetMethodCount(); ++j) { const auto m = t->GetMethodByIndex(j); stream << "\t"; int methodReturnId = m->GetReturnTypeId(); if (methodReturnId == -1) { stream << "? "; } else { stream << t->GetEngine()->GetTypeDeclaration(methodReturnId) << " "; } stream << m->GetName() << "("; writeParameters(m); stream << ")"; // stream << "\t" << m->GetDeclaration(false, false, true); if (m->IsProperty()) stream << " property"; stream << ";\n"; } for (int j = 0; j < t->GetPropertyCount(); ++j) { stream << "\t" << t->GetPropertyDeclaration(j, false) << ";\n"; } for (int j = 0; j < t->GetChildFuncdefCount(); ++j) { stream << "\tfuncdef " << t->GetChildFuncdef(j)->GetFuncdefSignature()->GetDeclaration( false) << ";\n"; } stream << "}\n"; if (!ns.empty()) stream << "}\n\n"; } } void printGlobalFunctionList(const asIScriptEngine& engine) { for (int i = 0; i < engine.GetGlobalFunctionCount(); ++i) { const auto f = engine.GetGlobalFunctionByIndex(i); if (!f) continue; std::string_view ns = f->GetNamespace(); if (!ns.empty()) stream << "namespace " << ns << " { "; stream << f->GetDeclaration(false, false, true) << ";"; if (!ns.empty()) stream << " }"; stream << "\n"; } } void printGlobalPropertyList(const asIScriptEngine& engine) { for (int i = 0; i < engine.GetGlobalPropertyCount(); ++i) { const char* name; const char* ns0; int type; engine.GetGlobalPropertyByIndex(i, &name, &ns0, &type, nullptr, nullptr, nullptr, nullptr); std::string t = engine.GetTypeDeclaration(type, true); if (t.empty()) continue; std::string_view ns = ns0; if (!ns.empty()) stream << "namespace " << ns << " { "; stream << t << " " << name << ";"; if (!ns.empty()) stream << " }"; stream << "\n"; } } void printGlobalTypedef(const asIScriptEngine& engine) { for (int i = 0; i < engine.GetTypedefCount(); ++i) { const auto type = engine.GetTypedefByIndex(i); if (!type) continue; std::string_view ns = type->GetNamespace(); if (!ns.empty()) stream << "namespace " << ns << " {\n"; stream << "typedef " << engine.GetTypeDeclaration(type->GetTypedefTypeId()) << " " << type->GetName() << ";\n"; if (!ns.empty()) stream << "}\n"; } } void printAngelInfo(const asIScriptEngine& engine) { printFuncList(engine); printEnumList(engine); printClassTypeList(engine); printGlobalFunctionList(engine); printGlobalPropertyList(engine); printGlobalTypedef(engine); } namespace Deer { void AngelScriptEngine::generateAngelscriptPredefined() { stream.clear(); stream << "//This file was generated automatically\n"; printAngelInfo(*Deer::AngelScriptEngine::scriptEngine); str = stream.str(); } void AngelScriptEngine::saveAngelscriptPredefined(const Path& path) { Deer::Path filePath = path / "as.predefined"; std::ofstream file(filePath, std::ios::out | std::ios::binary); file.write(reinterpret_cast(str.c_str()), str.size()); file.close(); } } // namespace Deer