void Generator::outputObjectDeclaration()

in src/SchemaGenerator.cpp [680:983]


void Generator::outputObjectDeclaration(
	std::ostream& headerFile, const ObjectType& objectType, bool isQueryType) const
{
	headerFile << R"cpp(class )cpp" << objectType.cppType << R"cpp( final
	: public service::Object
{
private:
)cpp";

	for (const auto& outputField : objectType.fields)
	{
		headerFile << getResolverDeclaration(outputField);
	}

	headerFile << R"cpp(
	service::AwaitableResolver resolve_typename(service::ResolverParams&& params) const;
)cpp";

	if (!_options.noIntrospection && isQueryType)
	{
		headerFile
			<< R"cpp(	service::AwaitableResolver resolve_schema(service::ResolverParams&& params) const;
	service::AwaitableResolver resolve_type(service::ResolverParams&& params) const;

	std::shared_ptr<schema::Schema> _schema;
)cpp";
	}

	headerFile << R"cpp(
	struct Concept
	{
		virtual ~Concept() = default;

)cpp";

	if (!_loader.isIntrospection())
	{
		headerFile
			<< R"cpp(		virtual void beginSelectionSet(const service::SelectionSetParams& params) const = 0;
		virtual void endSelectionSet(const service::SelectionSetParams& params) const = 0;

)cpp";
	}

	for (const auto& outputField : objectType.fields)
	{
		headerFile << getFieldDeclaration(outputField);
	}

	headerFile << R"cpp(	};

	template <class T>
	struct Model
		: Concept
	{
		Model(std::shared_ptr<T>&& pimpl) noexcept
			: _pimpl { std::move(pimpl) }
		{
		}
)cpp";

	for (const auto& outputField : objectType.fields)
	{
		std::string fieldName(outputField.cppName);

		fieldName[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(fieldName[0])));

		headerFile << R"cpp(
		)cpp" << _loader.getOutputCppType(outputField)
				   << R"cpp( )cpp" << outputField.accessor << fieldName << R"cpp(()cpp";

		bool firstArgument = _loader.isIntrospection();

		if (!firstArgument)
		{
			headerFile << R"cpp(service::FieldParams&& params)cpp";
		}

		for (const auto& argument : outputField.arguments)
		{
			if (!firstArgument)
			{
				headerFile << R"cpp(, )cpp";
			}

			headerFile << _loader.getInputCppType(argument) << R"cpp(&& )cpp" << argument.cppName
					   << R"cpp(Arg)cpp";
			firstArgument = false;
		}

		headerFile << R"cpp() const final
		{
			)cpp";

		std::ostringstream ossPassedArguments;
		firstArgument = true;

		for (const auto& argument : outputField.arguments)
		{
			if (!firstArgument)
			{
				ossPassedArguments << R"cpp(, )cpp";
			}

			ossPassedArguments << R"cpp(std::move()cpp" << argument.cppName << R"cpp(Arg))cpp";
			firstArgument = false;
		}

		const auto passedArguments = ossPassedArguments.str();

		if (_loader.isIntrospection())
		{
			headerFile << R"cpp(return { _pimpl->)cpp" << outputField.accessor << fieldName
					   << R"cpp(()cpp";

			if (!passedArguments.empty())
			{
				headerFile << passedArguments;
			}

			headerFile << R"cpp() };)cpp";
		}
		else
		{
			headerFile << R"cpp(if constexpr (methods::)cpp" << objectType.cppType
					   << R"cpp(Has::)cpp" << outputField.accessor << fieldName
					   << R"cpp(WithParams<T>)
			{
				return { _pimpl->)cpp"
					   << outputField.accessor << fieldName << R"cpp((std::move(params))cpp";

			if (!passedArguments.empty())
			{
				headerFile << R"cpp(, )cpp" << passedArguments;
			}

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

			if (!_options.stubs)
			{
				headerFile << R"cpp(
			{
				static_assert(methods::)cpp"
						   << objectType.cppType << R"cpp(Has::)cpp" << outputField.accessor
						   << fieldName << R"cpp(<T>, R"msg()cpp" << objectType.cppType
						   << R"cpp(::)cpp" << outputField.accessor << fieldName
						   << R"cpp( is not implemented)msg");)cpp";
			}
			else
			{
				headerFile << R"cpp( if constexpr (methods::)cpp" << objectType.cppType
						   << R"cpp(Has::)cpp" << outputField.accessor << fieldName << R"cpp(<T>)
			{)cpp";
			}

			headerFile << R"cpp(
				return { _pimpl->)cpp"
					   << outputField.accessor << fieldName << R"cpp(()cpp";

			if (!passedArguments.empty())
			{
				headerFile << passedArguments;
			}

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

			if (_options.stubs)
			{
				headerFile << R"cpp(
			else
			{
				throw std::runtime_error(R"ex()cpp"
						   << objectType.cppType << R"cpp(::)cpp" << outputField.accessor
						   << fieldName << R"cpp( is not implemented)ex");
			})cpp";
			}
		}

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

	if (!_loader.isIntrospection())
	{
		headerFile << R"cpp(
		void beginSelectionSet(const service::SelectionSetParams& params) const final
		{
			if constexpr (methods::)cpp"
				   << objectType.cppType << R"cpp(Has::beginSelectionSet<T>)
			{
				_pimpl->beginSelectionSet(params);
			}
		}

		void endSelectionSet(const service::SelectionSetParams& params) const final
		{
			if constexpr (methods::)cpp"
				   << objectType.cppType << R"cpp(Has::endSelectionSet<T>)
			{
				_pimpl->endSelectionSet(params);
			}
		}
)cpp";
	}

	headerFile << R"cpp(
	private:
		const std::shared_ptr<T> _pimpl;
	};

)cpp";

	if (_loader.isIntrospection())
	{
		headerFile << R"cpp(	const std::unique_ptr<const Concept> _pimpl;

	service::TypeNames getTypeNames() const noexcept;
	service::ResolverMap getResolvers() const noexcept;

public:
	GRAPHQLSERVICE_EXPORT )cpp"
				   << objectType.cppType << R"cpp((std::shared_ptr<)cpp"
				   << SchemaLoader::getIntrospectionNamespace() << R"cpp(::)cpp"
				   << objectType.cppType << R"cpp(> pimpl) noexcept;
	GRAPHQLSERVICE_EXPORT ~)cpp"
				   << objectType.cppType << R"cpp(();
};
)cpp";
	}
	else
	{
		headerFile << R"cpp(	)cpp" << objectType.cppType
				   << R"cpp((std::unique_ptr<const Concept>&& pimpl) noexcept;

)cpp";

		if (!objectType.interfaces.empty())
		{
			headerFile << R"cpp(	// Interfaces which this type implements
)cpp";

			for (auto interfaceName : objectType.interfaces)
			{
				headerFile << R"cpp(	friend )cpp" << _loader.getSafeCppName(interfaceName)
						   << R"cpp(;
)cpp";
			}

			headerFile << std::endl;
		}

		if (!objectType.unions.empty())
		{
			headerFile << R"cpp(	// Unions which include this type
)cpp";

			for (auto unionName : objectType.unions)
			{
				headerFile << R"cpp(	friend )cpp" << _loader.getSafeCppName(unionName)
						   << R"cpp(;
)cpp";
			}

			headerFile << std::endl;
		}

		if (!objectType.interfaces.empty() || !objectType.unions.empty())
		{

			headerFile << R"cpp(	template <class I>
	static constexpr bool implements() noexcept
	{
		return implements::)cpp"
					   << objectType.cppType << R"cpp(Is<I>;
	}

)cpp";
		}

		headerFile
			<< R"cpp(	service::TypeNames getTypeNames() const noexcept;
	service::ResolverMap getResolvers() const noexcept;

	void beginSelectionSet(const service::SelectionSetParams& params) const final;
	void endSelectionSet(const service::SelectionSetParams& params) const final;

	const std::unique_ptr<const Concept> _pimpl;

public:
	template <class T>
	)cpp" << objectType.cppType
			<< R"cpp((std::shared_ptr<T> pimpl) noexcept
		: )cpp"
			<< objectType.cppType
			<< R"cpp( { std::unique_ptr<const Concept> { std::make_unique<Model<T>>(std::move(pimpl)) } }
	{
	}
};
)cpp";
	}