bool Generator::outputHeader()

in src/SchemaGenerator.cpp [106:478]


bool Generator::outputHeader() const noexcept
{
	std::ofstream headerFile(_headerPath, std::ios_base::trunc);
	IncludeGuardScope includeGuard { headerFile,
		std::filesystem::path(_headerPath).filename().string() };

	headerFile << R"cpp(#include "graphqlservice/internal/Schema.h"

// Check if the library version is compatible with schemagen )cpp"
			   << graphql::internal::MajorVersion << R"cpp(.)cpp" << graphql::internal::MinorVersion
			   << R"cpp(.0
static_assert(graphql::internal::MajorVersion == )cpp"
			   << graphql::internal::MajorVersion
			   << R"cpp(, "regenerate with schemagen: major version mismatch");
static_assert(graphql::internal::MinorVersion == )cpp"
			   << graphql::internal::MinorVersion
			   << R"cpp(, "regenerate with schemagen: minor version mismatch");

#include <memory>
#include <string>
#include <vector>

)cpp";

	NamespaceScope graphqlNamespace { headerFile, "graphql" };
	NamespaceScope schemaNamespace { headerFile, _loader.getSchemaNamespace() };
	NamespaceScope objectNamespace { headerFile, "object", true };
	PendingBlankLine pendingSeparator { headerFile };

	std::string_view queryType;

	if (!_loader.isIntrospection())
	{
		for (const auto& operation : _loader.getOperationTypes())
		{
			if (operation.operation == service::strQuery)
			{
				queryType = operation.type;
				break;
			}
		}
	}

	if (!_loader.getEnumTypes().empty())
	{
		pendingSeparator.reset();

		for (const auto& enumType : _loader.getEnumTypes())
		{
			headerFile << R"cpp(enum class )cpp" << enumType.cppType << R"cpp(
{
)cpp";

			bool firstValue = true;

			for (const auto& value : enumType.values)
			{
				if (!firstValue)
				{
					headerFile << R"cpp(,
)cpp";
				}

				firstValue = false;
				headerFile << R"cpp(	)cpp" << value.value;
			}
			headerFile << R"cpp(
};

)cpp";
		}
	}

	if (!_loader.getInputTypes().empty())
	{
		pendingSeparator.reset();

		// Output the full declarations
		for (const auto& inputType : _loader.getInputTypes())
		{
			headerFile << R"cpp(struct )cpp" << inputType.cppType << R"cpp(
{
)cpp";
			for (const auto& inputField : inputType.fields)
			{
				headerFile << getFieldDeclaration(inputField) << R"cpp( {};
)cpp";
			}
			headerFile << R"cpp(};

)cpp";
		}
	}

	if (!_loader.getInterfaceTypes().empty())
	{
		objectNamespace.enter();
		headerFile << std::endl;

		// Forward declare all of the interface types
		for (const auto& interfaceType : _loader.getInterfaceTypes())
		{
			headerFile << R"cpp(class )cpp" << interfaceType.cppType << R"cpp(;
)cpp";
		}

		headerFile << std::endl;
	}

	if (!_loader.getUnionTypes().empty())
	{
		if (objectNamespace.enter())
		{
			headerFile << std::endl;
		}

		// Forward declare all of the union types
		for (const auto& unionType : _loader.getUnionTypes())
		{
			headerFile << R"cpp(class )cpp" << unionType.cppType << R"cpp(;
)cpp";
		}

		headerFile << std::endl;
	}

	if (!_loader.getObjectTypes().empty())
	{
		if (_loader.isIntrospection())
		{
			if (objectNamespace.exit())
			{
				headerFile << std::endl;
			}

			// Forward declare all of the concrete types for the Introspection schema
			for (const auto& objectType : _loader.getObjectTypes())
			{
				headerFile << R"cpp(class )cpp" << objectType.cppType << R"cpp(;
)cpp";
			}

			headerFile << std::endl;
		}

		if (objectNamespace.enter())
		{
			headerFile << std::endl;
		}

		// Forward declare all of the object types
		for (const auto& objectType : _loader.getObjectTypes())
		{
			headerFile << R"cpp(class )cpp" << objectType.cppType << R"cpp(;
)cpp";
		}

		headerFile << std::endl;
	}

	if (objectNamespace.exit())
	{
		headerFile << std::endl;
	}

	if (!_loader.isIntrospection())
	{
		bool firstOperation = true;

		headerFile << R"cpp(class Operations final
	: public service::Request
{
public:
	explicit Operations()cpp";

		for (const auto& operation : _loader.getOperationTypes())
		{
			if (!firstOperation)
			{
				headerFile << R"cpp(, )cpp";
			}

			firstOperation = false;
			headerFile << R"cpp(std::shared_ptr<object::)cpp" << operation.cppType << R"cpp(> )cpp"
					   << operation.operation;
		}

		headerFile << R"cpp();
)cpp";

		if (!_loader.getOperationTypes().empty())
		{
			firstOperation = true;

			headerFile << R"cpp(
	template <)cpp";
			for (const auto& operation : _loader.getOperationTypes())
			{
				if (!firstOperation)
				{
					headerFile << R"cpp(, )cpp";
				}

				firstOperation = false;
				headerFile << R"cpp(class T)cpp" << operation.cppType;
			}

			headerFile << R"cpp(>
	explicit Operations()cpp";

			firstOperation = true;

			for (const auto& operation : _loader.getOperationTypes())
			{
				if (!firstOperation)
				{
					headerFile << R"cpp(, )cpp";
				}

				firstOperation = false;
				headerFile << R"cpp(std::shared_ptr<T)cpp" << operation.cppType << R"cpp(> )cpp"
						   << operation.operation;
			}

			headerFile << R"cpp()
		: Operations {)cpp";

			firstOperation = true;

			for (const auto& operation : _loader.getOperationTypes())
			{
				if (!firstOperation)
				{
					headerFile << R"cpp(,)cpp";
				}

				firstOperation = false;
				headerFile << R"cpp( std::make_shared<object::)cpp" << operation.cppType
						   << R"cpp(>(std::move()cpp" << operation.operation << R"cpp()))cpp";
			}

			headerFile << R"cpp( }
	{
	}
)cpp";
		}

		headerFile << R"cpp(
private:
)cpp";

		for (const auto& operation : _loader.getOperationTypes())
		{
			headerFile << R"cpp(	std::shared_ptr<object::)cpp" << operation.cppType
					   << R"cpp(> _)cpp" << operation.operation << R"cpp(;
)cpp";
		}

		headerFile << R"cpp(};

)cpp";
	}

	if (!_loader.getInterfaceTypes().empty())
	{
		for (const auto& interfaceType : _loader.getInterfaceTypes())
		{
			headerFile << R"cpp(void Add)cpp" << interfaceType.cppType
					   << R"cpp(Details(const std::shared_ptr<schema::InterfaceType>& type)cpp"
					   << interfaceType.cppType
					   << R"cpp(, const std::shared_ptr<schema::Schema>& schema);
)cpp";
		}

		headerFile << std::endl;
	}

	if (!_loader.getUnionTypes().empty())
	{
		for (const auto& unionType : _loader.getUnionTypes())
		{
			headerFile << R"cpp(void Add)cpp" << unionType.cppType
					   << R"cpp(Details(const std::shared_ptr<schema::UnionType>& type)cpp"
					   << unionType.cppType
					   << R"cpp(, const std::shared_ptr<schema::Schema>& schema);
)cpp";
		}

		headerFile << std::endl;
	}

	if (!_loader.getObjectTypes().empty())
	{
		for (const auto& objectType : _loader.getObjectTypes())
		{
			headerFile << R"cpp(void Add)cpp" << objectType.cppType
					   << R"cpp(Details(const std::shared_ptr<schema::ObjectType>& type)cpp"
					   << objectType.cppType
					   << R"cpp(, const std::shared_ptr<schema::Schema>& schema);
)cpp";
		}

		headerFile << std::endl;
	}

	if (_loader.isIntrospection())
	{
		headerFile
			<< R"cpp(GRAPHQLSERVICE_EXPORT void AddTypesToSchema(const std::shared_ptr<schema::Schema>& schema);

)cpp";

		if (!_loader.getEnumTypes().empty() || !_loader.getInputTypes().empty())
		{
			if (schemaNamespace.exit())
			{
				headerFile << std::endl;
			}

			NamespaceScope serviceNamespace { headerFile, "service" };

			headerFile << R"cpp(
#ifdef GRAPHQL_DLLEXPORTS
// Export all of the built-in converters
)cpp";

			for (const auto& enumType : _loader.getEnumTypes())
			{
				headerFile << R"cpp(template <>
GRAPHQLSERVICE_EXPORT )cpp" << _loader.getSchemaNamespace()
						   << R"cpp(::)cpp" << enumType.cppType << R"cpp( ModifiedArgument<)cpp"
						   << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType
						   << R"cpp(>::convert(
	const response::Value& value);
template <>
GRAPHQLSERVICE_EXPORT AwaitableResolver ModifiedResult<)cpp"
						   << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType
						   << R"cpp(>::convert(
	AwaitableScalar<)cpp" << _loader.getSchemaNamespace()
						   << R"cpp(::)cpp" << enumType.cppType
						   << R"cpp(> result, ResolverParams params);
template <>
GRAPHQLSERVICE_EXPORT void ModifiedResult<)cpp"
						   << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType
						   << R"cpp(>::validateScalar(
	const response::Value& value);
)cpp";
			}

			for (const auto& inputType : _loader.getInputTypes())
			{
				headerFile << R"cpp(template <>
GRAPHQLSERVICE_EXPORT )cpp" << _loader.getSchemaNamespace()
						   << R"cpp(::)cpp" << inputType.cppType << R"cpp( ModifiedArgument<)cpp"
						   << inputType.cppType << R"cpp(>::convert(
	const response::Value& value);
)cpp";
			}

			headerFile << R"cpp(#endif // GRAPHQL_DLLEXPORTS

)cpp";
		}
	}
	else
	{
		headerFile << R"cpp(std::shared_ptr<schema::Schema> GetSchema();

)cpp";
	}

	return true;
}