diff --git a/source/RobotAPI/libraries/aron/codegeneration/codegenerator/codewriter/cpp/Writer.cpp b/source/RobotAPI/libraries/aron/codegeneration/codegenerator/codewriter/cpp/Writer.cpp index 1a38b4d5a6e39a86860e66b65f62a9ba093320bc..bd0bc005c622ceff32327aeeba02ccd972b3aca5 100644 --- a/source/RobotAPI/libraries/aron/codegeneration/codegenerator/codewriter/cpp/Writer.cpp +++ b/source/RobotAPI/libraries/aron/codegeneration/codegenerator/codewriter/cpp/Writer.cpp @@ -325,7 +325,7 @@ namespace armarx::aron::codegenerator::cpp { if (!s.empty()) { - c->addInclude(s); + c->addInclude(simox::alg::replace_last(s, ".aron.generated.codesuffix", ".aron.generated.h")); } } diff --git a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Data.cpp b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Data.cpp index dae418cdb4fd4de31b2daf86c839b60b988233ca..925582621433aa3f679dccee50af2b7e2dcad6d7 100644 --- a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Data.cpp +++ b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Data.cpp @@ -46,7 +46,7 @@ namespace armarx::aron::typereader::xml { if (!HasAttribute(node, att)) { - throw error::ValueNotValidException(__PRETTY_FUNCTION__, "A <" + node.name() + ">-tag does not have the correct attribute", att); + throw error::ValueNotValidException(__PRETTY_FUNCTION__, "A <" + node.name() + ">-tag does not have the '"+att+"' attribute", simox::alg::to_string(node.get_all_attributes())); } } diff --git a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Data.h b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Data.h index a780a801173760a7adeae69fda0b4cff4a66e0f9..a2b724af0ceb6a029c76db86341e8445c725eebc 100644 --- a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Data.h +++ b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Data.h @@ -42,14 +42,17 @@ namespace armarx::aron::typereader::xml // Definition tags const std::string TYPE_DEFINITION_TAG = "arontypedefinition"; - const std::string CODE_INCLUDES_TAG = "codeincludes"; // Legacy - const std::string ARON_INCLUDES_TAG = "aronincludes"; // Legacy + const std::string CODE_INCLUDES_TAG = "codeincludes"; + const std::string ARON_INCLUDES_TAG = "aronincludes"; const std::string INCLUDES_TAG = "includes"; const std::string SYSTEM_INCLUDE_TAG = "systeminclude"; + const std::string PACKAGE_PATH_TAG = "packagepath"; const std::string INCLUDE_TAG = "include"; const std::string GENERATE_TYPES_TAG = "generatetypes"; // Attribute names + const std::string ARON_ATTRIBUTE_NAME = "aron"; + const std::string CODE_ATTRIBUTE_NAME = "code"; const std::string METHOD_ATTRIBUTE_NAME = "method"; const std::string RETURN_ATTRIBUTE_NAME = "return"; const std::string ARGUMENT_TYPE_ATTRIBUTE_NAME = "argumenttype"; @@ -105,21 +108,21 @@ namespace armarx::aron::typereader::xml // others const std::vector<std::string> WHATEVER_VALUES = {"?"}; - // Replacements ({tagName, {replacementsTag, additionalAronDTOInclude}}) - const std::map<std::string, std::pair<std::string, std::string>> REPLACEMENTS = + // Replacements ({tagName, {replacementsTag, additionalAronDTOXMLIncludePackagePath}}) + const std::map<std::string, std::pair<std::string, std::pair<std::string, std::string>>> REPLACEMENTS = { - {"position", {"<matrix rows='3' cols='1' type='float32' />", ""}}, - {"pose", {"<matrix rows='4' cols='4' type='float32' />", ""}}, - {"orientation", {"<quaternion type='float32' />", ""}}, + {"position", {"<matrix rows='3' cols='1' type='float32' />", {}}}, + {"pose", {"<matrix rows='4' cols='4' type='float32' />", {}}}, + {"orientation", {"<quaternion type='float32' />", {}}}, // You can also add replacements for arondtos here! // structure: {xml-identifier, {replacement, auto-include}} - {"datetime", {"<armarx::arondto::DateTime />", "<RobotAPI/libraries/aron/common/aron/time.xml>"}}, - {"time", {"<armarx::arondto::DateTime />", "<RobotAPI/libraries/aron/common/aron/time.xml>"}}, - {"duration", {"<armarx::arondto::Duration />", "<RobotAPI/libraries/aron/common/aron/time.xml>"}}, - {"framedposition", {"<armarx::arondto::FramedPosition />", "<RobotAPI/libraries/aron/common/aron/framed.xml>"}}, - {"framedorientation", {"<armarx::arondto::FramedOrientation />", "<RobotAPI/libraries/aron/common/aron/framed.xml>"}}, - {"framedpose", {"<armarx::arondto::FramedPose />", "<RobotAPI/libraries/aron/common/aron/framed.xml>"}} + {"datetime", {"<armarx::arondto::DateTime />", {"RobotAPI", "libraries/aron/common/aron/time.xml"}}}, + {"time", {"<armarx::arondto::DateTime />", {"RobotAPI", "libraries/aron/common/aron/time.xml"}}}, + {"duration", {"<armarx::arondto::Duration />", {"RobotAPI", "libraries/aron/common/aron/time.xml"}}}, + {"framedposition", {"<armarx::arondto::FramedPosition />", {"RobotAPI", "libraries/aron/common/aron/framed.xml"}}}, + {"framedorientation", {"<armarx::arondto::FramedOrientation />", {"RobotAPI", "libraries/aron/common/aron/framed.xml"}}}, + {"framedpose", {"<armarx::arondto::FramedPose />", {"RobotAPI", "libraries/aron/common/aron/framed.xml"}}} }; } diff --git a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Factory.cpp b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Factory.cpp index 9f47179577d816c8600b85177f00600f5d7a9712..9b17f8aa6ec6cfb67dbb14ccaae3e97eb9b5c111 100644 --- a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Factory.cpp +++ b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Factory.cpp @@ -179,10 +179,8 @@ namespace armarx::aron::typereader::xml } // ensured we are toplevel! - util::EnforceAttribute(node, constantes::NAME_ATTRIBUTE_NAME); - const std::string extends = util::GetAttributeWithDefault(node, constantes::EXTENDS_ATTRIBUTE_NAME, ""); const std::string name = util::GetAttribute(node, constantes::NAME_ATTRIBUTE_NAME); - + const std::string extends = util::GetAttributeWithDefault(node, constantes::EXTENDS_ATTRIBUTE_NAME, ""); auto templates = simox::alg::split(util::GetAttributeWithDefault(node, constantes::TEMPLATE_ATTRIBUTE_NAME, ""), ","); auto newObjectInfo = typereader::GenerateObjectInfo(); diff --git a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.cpp b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.cpp index 0d2bfcc301e14a9eb21e17760bae468d36cd5ae9..be81be7eab5bf633e63f82ee9b9aa975f1d6fe21 100644 --- a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.cpp +++ b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.cpp @@ -45,7 +45,7 @@ namespace armarx::aron::typereader::xml namespace { - /// Resolve a relative Package path. This may be removed in a newer version of aron + /// Resolve a relative package path std::optional<fs::path> resolveRelativePackagePath(const fs::path& path, const std::vector<fs::path>& includePaths) { // new behavior: using provided include paths @@ -83,6 +83,7 @@ namespace armarx::aron::typereader::xml void Reader::parseFile(const std::string& _filename, const std::vector<std::filesystem::path>& includePaths) { std::string filename = _filename; + // Handle C++ style includes like "<path/to/file>". if (!filename.empty() && filename.front() == '<' && filename.back() == '>') { @@ -94,9 +95,19 @@ namespace armarx::aron::typereader::xml void Reader::parseFile(const std::filesystem::path& _file, const std::vector<std::filesystem::path>& includePaths) { fs::path file = _file; + if (not std::filesystem::exists(file)) + { + // check if file is package path + auto p = resolveRelativePackagePath(file, includePaths); + if (not p) + { + throw error::AronException(__PRETTY_FUNCTION__, "Could not find the file " + file.string() + ". Tried include paths: " + simox::alg::to_string(includePaths)); + } + file = *p; + } RapidXmlReaderPtr reader = RapidXmlReader::FromFile(file.string()); - parse(reader, _file, includePaths); + parse(reader, file, includePaths); } // private method reading nodes @@ -112,48 +123,66 @@ namespace armarx::aron::typereader::xml auto includes = util::GetFirstNodeWithTag(root, constantes::INCLUDES_TAG); auto generate_types = util::GetFirstNodeWithTag(root, constantes::GENERATE_TYPES_TAG); - // 0. Check legacy includes + // 1. Check code includes auto codeincludes = util::GetFirstNodeWithTag(root, constantes::CODE_INCLUDES_TAG); auto aronincludes = util::GetFirstNodeWithTag(root, constantes::ARON_INCLUDES_TAG); if (codeincludes.has_value()) { - deprecated_include(); - for (const auto& include : (*codeincludes).nodes()) { - auto i = readCodeInclude(include, filePath); - if (i) this->systemIncludes.push_back(*i); + auto i = readCodeInclude(include, includePaths); + if (not i.empty()) this->systemIncludes.push_back(i); } } + + // 2. Check aron includes if (aronincludes.has_value()) { - deprecated_include(); - for (const auto& include : (*aronincludes).nodes()) { - auto i = readAronInclude(include, filePath); - if (i) this->aronIncludes.push_back(*i); + auto i = readAronInclude(include, includePaths); + if (not i.empty()) this->aronIncludes.push_back(i); } } - // 1. Check includes + // 3. Check general includes and try to deduce info if (includes.has_value()) { for (const auto& include : (*includes).nodes()) { - if (util::HasTagName(include, constantes::SYSTEM_INCLUDE_TAG)) + if (util::HasTagName(include, constantes::SYSTEM_INCLUDE_TAG)) // if its a system include tag then we know that it must be a code include { - auto i = readCodeInclude(include, filePath); - if (i) this->systemIncludes.push_back(*i); + auto i = readCodeInclude(include, includePaths); + if (not i.empty()) this->systemIncludes.push_back(i); } + else + { + // case that the file can be either an aron or code file. We need to deduce the type based on the given information + std::string what = ""; - // ToDo: add special tag for aron includes + if (util::HasTagName(include, constantes::PACKAGE_PATH_TAG)) // can be both + { + what = util::GetAttribute(include, constantes::PATH_ATTRIBUTE_NAME); + } - // ToDo: system includes also allow to use the <include> tag. Try to estimate aron or system include from attributes - if (util::HasTagName(include, constantes::INCLUDE_TAG)) - { - auto i = readAronInclude(include, filePath); - if (i) this->aronIncludes.push_back(*i); + if (util::HasTagName(include, constantes::INCLUDE_TAG)) // can be both + { + what = util::GetAttribute(include, constantes::INCLUDE_ATTRIBUTE_NAME); + } + + if (not what.empty() && std::filesystem::path(what) != filePath) // did we found something? + { + if (what.ends_with(ARON_FILE_SUFFIX)) + { + auto i = readAronInclude(include, includePaths); + if (not i.empty()) this->aronIncludes.push_back(i); + } + else // we believe that this is a code include since it is not an xml file + { + auto i = readCodeInclude(include, includePaths); + if (not i.empty()) this->systemIncludes.push_back(i); + } + } } } } @@ -165,12 +194,16 @@ namespace armarx::aron::typereader::xml { if (util::HasTagName(generateType, constantes::OBJECT_TAG)) { - for (const auto& x : checkForInclude(generateType, filePath)) + for (const auto& additionalInclude : getAdditionalIncludesFromReplacements(generateType, filePath)) { - auto i = this->readAronInclude(x, filePath, includePaths); - if (i && std::find(this->aronIncludes.begin(), this->aronIncludes.end(), *i) == this->aronIncludes.end()) + RapidXmlReaderPtr reader = RapidXmlReader::FromXmlString("<PackagePath package=\""+additionalInclude.first+"\" path=\""+additionalInclude.second+"\"/>"); + auto node = reader->getRoot(); + + auto i = this->readAronInclude(node, includePaths); + if (not i.empty() && std::find(this->aronIncludes.begin(), this->aronIncludes.end(), i) == this->aronIncludes.end()) { - this->aronIncludes.push_back(*i); + std::cout << "OUT IS: " << i << std::endl; + this->aronIncludes.push_back(i); } } } @@ -204,124 +237,120 @@ namespace armarx::aron::typereader::xml } } - std::string Reader::readCodeInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths) + std::pair<std::string, std::string> Reader::readPackagePathInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths) { - util::EnforceTagNames(node, {constantes::SYSTEM_INCLUDE_TAG, constantes::INCLUDE_TAG}); - std::string specifiedPath = util::GetAttributeWithDefault(node, constantes::INCLUDE_ATTRIBUTE_NAME, ""); - specifiedPath = simox::alg::replace_all(specifiedPath, "<", ""); - specifiedPath = simox::alg::replace_all(specifiedPath, ">", ""); - if (specifiedPath.empty()) + util::EnforceTagName(node, constantes::PACKAGE_PATH_TAG); + std::string package = util::GetAttribute(node, constantes::PACKAGE_ATTRIBUTE_NAME); + std::string path = util::GetAttribute(node, constantes::PATH_ATTRIBUTE_NAME); + util::EnforceChildSize(node, 0); + + package = simox::alg::replace_all(package, "<", ""); + package = simox::alg::replace_all(package, ">", ""); + path = simox::alg::replace_all(path, "<", ""); + path = simox::alg::replace_all(path, ">", ""); + + const std::filesystem::path includepath(package + "/" + path); + if (std::optional<fs::path> resolvedPackagePath = resolveRelativePackagePath(includepath, includePaths); resolvedPackagePath.has_value()) { - // else we require a package path - util::EnforceAttribute(node, constantes::PACKAGE_ATTRIBUTE_NAME); - util::EnforceAttribute(node, constantes::PATH_ATTRIBUTE_NAME); - const std::string package = util::GetAttribute(node, constantes::PACKAGE_ATTRIBUTE_NAME); - const std::string path = util::GetAttribute(node, constantes::PATH_ATTRIBUTE_NAME); - specifiedPath = package + "/" + path; + return {package + "/" + path, "<" + package + "/" + path + ">"}; } - return readCodeInclude("<" + specifiedPath + ">", filePath); // <> for legacy reasons. ToDo: - } - std::optional<std::string> Reader::readCodeInclude(std::string s, const std::filesystem::path&, const std::vector<std::filesystem::path>& includePaths) - { - return s; + throw error::AronException(__PRETTY_FUNCTION__, "Could not find an file `" + includepath.string() + "`. Search paths are: " + simox::alg::to_string(includePaths)); } - std::string Reader::readAronInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths) + std::pair<std::string, std::string> Reader::readInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths) { util::EnforceTagName(node, constantes::INCLUDE_TAG); - std::string specifiedPath = util::GetAttributeWithDefault(node, constantes::INCLUDE_ATTRIBUTE_NAME, ""); - specifiedPath = simox::alg::replace_all(specifiedPath, "<", ""); - specifiedPath = simox::alg::replace_all(specifiedPath, ">", ""); - if (specifiedPath.empty()) - { - const std::string package = util::GetAttribute(node, constantes::PACKAGE_ATTRIBUTE_NAME); - const std::string path = util::GetAttribute(node, constantes::PATH_ATTRIBUTE_NAME); - specifiedPath = package + "/" + path; - } + std::string value = util::GetAttribute(node, constantes::INCLUDE_ATTRIBUTE_NAME); + util::EnforceChildSize(node, 0); - std::optional<std::string> resolved_absolute_path = readAronInclude("<" + specifiedPath + ">", filePath); - if (resolved_absolute_path) // we found something - { - std::string codeinclude = simox::alg::replace_last(specifiedPath, ".xml", ".aron.generated.h"); - auto i = this->readCodeInclude("<" + codeinclude + ">", filePath, includePaths); - if (i) this->systemIncludes.push_back(*i); - } + value = simox::alg::replace_all(value, "<", ""); + value = simox::alg::replace_all(value, ">", ""); - return resolved_absolute_path; + return {value, "\"" + value + "\""}; } - std::optional<std::string> Reader::readAronInclude(std::string specifiedPath, const std::filesystem::path& filePath) + std::pair<std::string, std::string> Reader::readSystemInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths) { - specifiedPath = simox::alg::replace_all(specifiedPath, "<", ""); - specifiedPath = simox::alg::replace_all(specifiedPath, ">", ""); - const std::filesystem::path xmlincludepath(specifiedPath); + util::EnforceTagName(node, constantes::SYSTEM_INCLUDE_TAG); + std::string value = util::GetAttribute(node, constantes::INCLUDE_ATTRIBUTE_NAME); + util::EnforceChildSize(node, 0); - // add logic to allow relative paths: - std::filesystem::path resolved_absolute_path(xmlincludepath); - std::filesystem::path resolved_relative_path(xmlincludepath); + value = simox::alg::replace_all(value, "<", ""); + value = simox::alg::replace_all(value, ">", ""); - if (!xmlincludepath.empty() && xmlincludepath.is_relative()) - { - // ARMARX_INFO << "Checking file " << xmlincludepath; - if (std::optional<fs::path> resolvedPackagePath = resolveRelativePackagePath(xmlincludepath, includePaths); resolvedPackagePath.has_value()) - { - // check if relative path belongs to a package - resolved_absolute_path = resolvedPackagePath.value(); - resolved_relative_path = xmlincludepath; - } - else - { - // perhaps the relative path is relative from file position? - // TODO: FixMe - resolved_absolute_path = filePath.parent_path() / xmlincludepath; - resolved_relative_path = filePath.parent_path() / xmlincludepath; - - if (!fs::is_regular_file(resolved_absolute_path)) - { - std::stringstream ss; - for(const auto& includePath: includePaths) - { - ss << includePath << ", "; - } + return {value, "<" + value + ">"}; + } - throw error::AronException(__PRETTY_FUNCTION__, "Could not find an aron XML file `" + xmlincludepath.string() + "`. Search paths are: " + ss.str()); - } - } + std::string Reader::readCodeInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths) + { + if (util::HasTagName(node, constantes::PACKAGE_PATH_TAG)) + { + return readPackagePathInclude(node, includePaths).second; } - // else path is absolute - - // check if referred file is same as current file. If so, abort. - if (resolved_absolute_path == filePath) + if (util::HasTagName(node, constantes::INCLUDE_TAG)) { - return std::nullopt; + return readInclude(node, includePaths).second; + } + if (util::HasTagName(node, constantes::SYSTEM_INCLUDE_TAG)) + { + return readSystemInclude(node, includePaths).second; } - // parse parent xml file and add objects to alreday known - Reader anotherReader; - anotherReader.parseFile(resolved_absolute_path, includePaths); - for (const auto& previouslyKnown : anotherReader.factory.allPreviouslyKnownPublicTypes) + throw error::ValueNotValidException(__PRETTY_FUNCTION__, "Could not parse a code include. The tag is wrong.", node.name()); + } + + std::string Reader::readAronInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths) + { + std::string include; + std::string orig_include; + if (util::HasTagName(node, constantes::PACKAGE_PATH_TAG)) { - factory.allPreviouslyKnownPublicTypes.push_back(previouslyKnown); + auto p = readPackagePathInclude(node, includePaths); + orig_include = p.first; + include = p.second; } - for (const auto& knownObjectInfo : anotherReader.factory.allGeneratedPublicObjects) + if (util::HasTagName(node, constantes::INCLUDE_TAG)) { - factory.allPreviouslyKnownPublicTypes.push_back(knownObjectInfo.first); + auto p = readInclude(node, includePaths); + orig_include = p.first; + include = p.second; } - for (const auto& knownIntEnumInfo : anotherReader.factory.allGeneratedPublicIntEnums) + + if (not include.empty()) // we found something { - factory.allPreviouslyKnownPublicTypes.push_back(knownIntEnumInfo.first); + // autoinclude the code file (suffix will be replaced by correct language) + std::string codeinclude = simox::alg::replace_last(include, ARON_FILE_SUFFIX, CODE_FILE_SUFFIX); + this->systemIncludes.push_back(codeinclude); + + // parse parent xml file and add objects to alreday known + Reader anotherReader; + anotherReader.parseFile(orig_include, includePaths); + for (const auto& previouslyKnown : anotherReader.factory.allPreviouslyKnownPublicTypes) + { + factory.allPreviouslyKnownPublicTypes.push_back(previouslyKnown); + } + for (const auto& knownObjectInfo : anotherReader.factory.allGeneratedPublicObjects) + { + factory.allPreviouslyKnownPublicTypes.push_back(knownObjectInfo.first); + } + for (const auto& knownIntEnumInfo : anotherReader.factory.allGeneratedPublicIntEnums) + { + factory.allPreviouslyKnownPublicTypes.push_back(knownIntEnumInfo.first); + } + + return include; } - return resolved_absolute_path.string(); + throw error::ValueNotValidException(__PRETTY_FUNCTION__, "Could not parse an aron include. The tag is wrong.", node.name()); } - std::vector<std::string> Reader::checkForInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath) + std::vector<std::pair<std::string, std::string>> Reader::getAdditionalIncludesFromReplacements(const RapidXmlReaderNode& node, const std::filesystem::path& filePath) { - std::vector<std::string> ret; + std::vector<std::pair<std::string, std::string>> ret; for (const auto& repl : constantes::REPLACEMENTS) { - if (!repl.second.second.empty() && util::HasTagName(node, repl.first)) + if (not repl.second.second.first.empty() && not repl.second.second.second.empty() && util::HasTagName(node, repl.first)) { // we found a string that will be replaced so we might need to add a default include ret.push_back(repl.second.second); @@ -336,7 +365,7 @@ namespace armarx::aron::typereader::xml for (const auto& n : node.nodes()) // only valid if ret is empty { - auto v = checkForInclude(n, filePath); + auto v = getAdditionalIncludesFromReplacements(n, filePath); ret = simox::alg::appended(ret, v); } diff --git a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.h b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.h index 71c7d0e53e928bf30ed3b42abe5d7bfc4d81e258..293f4c290ea166fe12fd2d88ba429be40df7f158 100644 --- a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.h +++ b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.h @@ -56,18 +56,25 @@ namespace armarx::aron::typereader::xml private: void parse(const RapidXmlReaderPtr& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths); - std::optional<std::string> readCodeInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths); - std::optional<std::string> readAronInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths); + // replacement management + std::vector<std::pair<std::string, std::string>> getAdditionalIncludesFromReplacements(const RapidXmlReaderNode& node, const std::filesystem::path& filePath); - std::vector<std::string> checkForInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath); - - std::optional<std::string> readCodeInclude(std::string, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths); - std::optional<std::string> readAronInclude(std::string, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths); + // parse includes + std::pair<std::string, std::string> readPackagePathInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths); + std::pair<std::string, std::string> readInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths); + std::pair<std::string, std::string> readSystemInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths); + std::string readCodeInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths); + std::string readAronInclude(const RapidXmlReaderNode& node, const std::vector<std::filesystem::path>& includePaths); + // parse top-level objects type::ObjectPtr readGenerateObject(const RapidXmlReaderNode& node); type::IntEnumPtr readGenerateIntEnum(const RapidXmlReaderNode& node); + public: + static const constexpr char* CODE_FILE_SUFFIX = ".aron.generated.codesuffix"; + static const constexpr char* ARON_FILE_SUFFIX = ".xml"; + private: ReaderFactory factory; };