Skip to content

Commit

Permalink
fix: #338
Browse files Browse the repository at this point in the history
  • Loading branch information
wravery committed Dec 9, 2024
1 parent 10d1124 commit 8e0aa14
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 38 deletions.
33 changes: 33 additions & 0 deletions samples/client/query/QueryClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const std::string& GetRequestText() noexcept
subject
when
isNow
array
}
}
Expand Down Expand Up @@ -431,6 +432,11 @@ graphql::query::client::query::Query::Response::anyType_UnionType Response<graph
result.isNow = ModifiedResponse<bool>::parse(std::move(member.second));
continue;
}
if (member.first == R"js(array)js"sv)
{
result.array = ModifiedResponse<response::IdType>::parse<TypeModifier::List>(std::move(member.second));
continue;
}
}
}

Expand Down Expand Up @@ -492,6 +498,9 @@ struct ResponseVisitor::impl
Member_anyType_0_subject,
Member_anyType_0_when,
Member_anyType_0_isNow,
Member_anyType_0_array,
Member_anyType_0_array_0,
Member_anyType_0_array_0_,
Member_default_,
Complete,
};
Expand Down Expand Up @@ -666,6 +675,10 @@ void ResponseVisitor::add_value([[maybe_unused]] std::shared_ptr<const response:
_pimpl->response.anyType.back()->isNow = ModifiedResponse<bool>::parse(response::Value { *value });
break;

case impl::VisitorState::Member_anyType_0_array_0:
_pimpl->response.anyType.back()->array.push_back(ModifiedResponse<response::IdType>::parse(response::Value { *value }));
break;

case impl::VisitorState::Member_default_:
_pimpl->state = impl::VisitorState::Start;
_pimpl->response.default_ = ModifiedResponse<std::string>::parse<TypeModifier::Nullable>(response::Value { *value });
Expand Down Expand Up @@ -699,6 +712,10 @@ void ResponseVisitor::reserve([[maybe_unused]] std::size_t count)
_pimpl->response.anyType.reserve(count);
break;

case impl::VisitorState::Member_anyType_0_array_0:
_pimpl->response.anyType.back()->array.reserve(count);
break;

case impl::VisitorState::Complete:
break;

Expand Down Expand Up @@ -914,6 +931,10 @@ void ResponseVisitor::add_member([[maybe_unused]] std::string&& key)
{
_pimpl->state = impl::VisitorState::Member_anyType_0_isNow;
}
else if (key == "array"sv)
{
_pimpl->state = impl::VisitorState::Member_anyType_0_array;
}
break;

case impl::VisitorState::Complete:
Expand Down Expand Up @@ -999,6 +1020,10 @@ void ResponseVisitor::start_array()
_pimpl->state = impl::VisitorState::Member_anyType_0;
break;

case impl::VisitorState::Member_anyType_0_array:
_pimpl->state = impl::VisitorState::Member_anyType_0_array_0;
break;

case impl::VisitorState::Complete:
break;

Expand Down Expand Up @@ -1027,6 +1052,10 @@ void ResponseVisitor::end_array()
_pimpl->state = impl::VisitorState::Start;
break;

case impl::VisitorState::Member_anyType_0_array_0:
_pimpl->state = impl::VisitorState::Member_anyType_0_;
break;

case impl::VisitorState::Complete:
break;

Expand Down Expand Up @@ -1226,6 +1255,10 @@ void ResponseVisitor::add_id([[maybe_unused]] response::IdType&& value)
_pimpl->response.anyType.back()->id = std::move(value);
break;

case impl::VisitorState::Member_anyType_0_array_0:
_pimpl->response.anyType.back()->array.push_back(std::move(value));
break;

case impl::VisitorState::Complete:
break;

Expand Down
2 changes: 2 additions & 0 deletions samples/client/query/QueryClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ namespace graphql::query {
/// subject
/// when
/// isNow
/// array
/// }
/// }
///
Expand Down Expand Up @@ -184,6 +185,7 @@ struct [[nodiscard("unnecessary construction")]] Response
std::optional<std::string> subject {};
std::optional<response::Value> when {};
bool isNow {};
std::vector<response::IdType> array {};
};

appointments_AppointmentConnection appointments {};
Expand Down
1 change: 1 addition & 0 deletions samples/client/query/query.today.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ query {
subject
when
isNow
array
}
}

Expand Down
5 changes: 0 additions & 5 deletions samples/proxy/query/ProxyClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,6 @@ void ResponseVisitor::start_object()
{
switch (_pimpl->state)
{
case impl::VisitorState::Member_relay_errors_0:
_pimpl->state = impl::VisitorState::Member_relay_errors_0_;
_pimpl->response.relay.errors->push_back(std::make_optional<std::string>({}));
break;

case impl::VisitorState::Complete:
break;

Expand Down
15 changes: 14 additions & 1 deletion samples/today/nointrospection/AppointmentObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ service::ResolverMap Appointment::getResolvers() const noexcept
return {
{ R"gql(id)gql"sv, [this](service::ResolverParams&& params) { return resolveId(std::move(params)); } },
{ R"gql(when)gql"sv, [this](service::ResolverParams&& params) { return resolveWhen(std::move(params)); } },
{ R"gql(array)gql"sv, [this](service::ResolverParams&& params) { return resolveArray(std::move(params)); } },
{ R"gql(isNow)gql"sv, [this](service::ResolverParams&& params) { return resolveIsNow(std::move(params)); } },
{ R"gql(subject)gql"sv, [this](service::ResolverParams&& params) { return resolveSubject(std::move(params)); } },
{ R"gql(__typename)gql"sv, [this](service::ResolverParams&& params) { return resolve_typename(std::move(params)); } },
Expand Down Expand Up @@ -111,6 +112,17 @@ service::AwaitableResolver Appointment::resolveForceError(service::ResolverParam
return service::ModifiedResult<std::string>::convert<service::TypeModifier::Nullable>(std::move(result), std::move(params));
}

service::AwaitableResolver Appointment::resolveArray(service::ResolverParams&& params) const
{
std::unique_lock resolverLock(_resolverMutex);
service::SelectionSetParams selectionSetParams { static_cast<const service::SelectionSetParams&>(params) };
auto directives = std::move(params.fieldDirectives);
auto result = _pimpl->getArray(service::FieldParams { std::move(selectionSetParams), std::move(directives) });
resolverLock.unlock();

return service::ModifiedResult<response::IdType>::convert<service::TypeModifier::List>(std::move(result), std::move(params));
}

service::AwaitableResolver Appointment::resolve_typename(service::ResolverParams&& params) const
{
return service::Result<std::string>::convert(std::string{ R"gql(Appointment)gql" }, std::move(params));
Expand All @@ -128,7 +140,8 @@ void AddAppointmentDetails(const std::shared_ptr<schema::ObjectType>& typeAppoin
schema::Field::Make(R"gql(when)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(DateTime)gql"sv)),
schema::Field::Make(R"gql(subject)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(String)gql"sv)),
schema::Field::Make(R"gql(isNow)gql"sv, R"md()md"sv, std::nullopt, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(Boolean)gql"sv))),
schema::Field::Make(R"gql(forceError)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(String)gql"sv))
schema::Field::Make(R"gql(forceError)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(String)gql"sv)),
schema::Field::Make(R"gql(array)gql"sv, R"md()md"sv, std::nullopt, schema->WrapType(introspection::TypeKind::NON_NULL, schema->WrapType(introspection::TypeKind::LIST, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(ID)gql"sv)))))
});
}

Expand Down
30 changes: 30 additions & 0 deletions samples/today/nointrospection/TodayAppointmentObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ concept getForceError = requires (TImpl impl)
{ service::AwaitableScalar<std::optional<std::string>> { impl.getForceError() } };
};

template <class TImpl>
concept getArrayWithParams = requires (TImpl impl, service::FieldParams params)
{
{ service::AwaitableScalar<std::vector<response::IdType>> { impl.getArray(std::move(params)) } };
};

template <class TImpl>
concept getArray = requires (TImpl impl)
{
{ service::AwaitableScalar<std::vector<response::IdType>> { impl.getArray() } };
};

template <class TImpl>
concept beginSelectionSet = requires (TImpl impl, const service::SelectionSetParams params)
{
Expand All @@ -103,6 +115,7 @@ class [[nodiscard("unnecessary construction")]] Appointment final
[[nodiscard("unnecessary call")]] service::AwaitableResolver resolveSubject(service::ResolverParams&& params) const;
[[nodiscard("unnecessary call")]] service::AwaitableResolver resolveIsNow(service::ResolverParams&& params) const;
[[nodiscard("unnecessary call")]] service::AwaitableResolver resolveForceError(service::ResolverParams&& params) const;
[[nodiscard("unnecessary call")]] service::AwaitableResolver resolveArray(service::ResolverParams&& params) const;

[[nodiscard("unnecessary call")]] service::AwaitableResolver resolve_typename(service::ResolverParams&& params) const;

Expand All @@ -118,6 +131,7 @@ class [[nodiscard("unnecessary construction")]] Appointment final
[[nodiscard("unnecessary call")]] virtual service::AwaitableScalar<std::optional<std::string>> getSubject(service::FieldParams&& params) const = 0;
[[nodiscard("unnecessary call")]] virtual service::AwaitableScalar<bool> getIsNow(service::FieldParams&& params) const = 0;
[[nodiscard("unnecessary call")]] virtual service::AwaitableScalar<std::optional<std::string>> getForceError(service::FieldParams&& params) const = 0;
[[nodiscard("unnecessary call")]] virtual service::AwaitableScalar<std::vector<response::IdType>> getArray(service::FieldParams&& params) const = 0;
};

template <class T>
Expand Down Expand Up @@ -209,6 +223,22 @@ class [[nodiscard("unnecessary construction")]] Appointment final
}
}

[[nodiscard("unnecessary call")]] service::AwaitableScalar<std::vector<response::IdType>> getArray(service::FieldParams&& params) const override
{
if constexpr (methods::AppointmentHas::getArrayWithParams<T>)
{
return { _pimpl->getArray(std::move(params)) };
}
else if constexpr (methods::AppointmentHas::getArray<T>)
{
return { _pimpl->getArray() };
}
else
{
throw service::unimplemented_method(R"ex(Appointment::getArray)ex");
}
}

void beginSelectionSet(const service::SelectionSetParams& params) const override
{
if constexpr (methods::AppointmentHas::beginSelectionSet<T>)
Expand Down
1 change: 1 addition & 0 deletions samples/today/schema.today.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ type Appointment implements Node {
subject: String
isNow: Boolean!
forceError: String
array: [ID!]!
}

type Task implements Node {
Expand Down
15 changes: 14 additions & 1 deletion samples/today/schema/AppointmentObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ service::ResolverMap Appointment::getResolvers() const noexcept
return {
{ R"gql(id)gql"sv, [this](service::ResolverParams&& params) { return resolveId(std::move(params)); } },
{ R"gql(when)gql"sv, [this](service::ResolverParams&& params) { return resolveWhen(std::move(params)); } },
{ R"gql(array)gql"sv, [this](service::ResolverParams&& params) { return resolveArray(std::move(params)); } },
{ R"gql(isNow)gql"sv, [this](service::ResolverParams&& params) { return resolveIsNow(std::move(params)); } },
{ R"gql(subject)gql"sv, [this](service::ResolverParams&& params) { return resolveSubject(std::move(params)); } },
{ R"gql(__typename)gql"sv, [this](service::ResolverParams&& params) { return resolve_typename(std::move(params)); } },
Expand Down Expand Up @@ -111,6 +112,17 @@ service::AwaitableResolver Appointment::resolveForceError(service::ResolverParam
return service::ModifiedResult<std::string>::convert<service::TypeModifier::Nullable>(std::move(result), std::move(params));
}

service::AwaitableResolver Appointment::resolveArray(service::ResolverParams&& params) const
{
std::unique_lock resolverLock(_resolverMutex);
service::SelectionSetParams selectionSetParams { static_cast<const service::SelectionSetParams&>(params) };
auto directives = std::move(params.fieldDirectives);
auto result = _pimpl->getArray(service::FieldParams { std::move(selectionSetParams), std::move(directives) });
resolverLock.unlock();

return service::ModifiedResult<response::IdType>::convert<service::TypeModifier::List>(std::move(result), std::move(params));
}

service::AwaitableResolver Appointment::resolve_typename(service::ResolverParams&& params) const
{
return service::Result<std::string>::convert(std::string{ R"gql(Appointment)gql" }, std::move(params));
Expand All @@ -128,7 +140,8 @@ void AddAppointmentDetails(const std::shared_ptr<schema::ObjectType>& typeAppoin
schema::Field::Make(R"gql(when)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(DateTime)gql"sv)),
schema::Field::Make(R"gql(subject)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(String)gql"sv)),
schema::Field::Make(R"gql(isNow)gql"sv, R"md()md"sv, std::nullopt, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(Boolean)gql"sv))),
schema::Field::Make(R"gql(forceError)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(String)gql"sv))
schema::Field::Make(R"gql(forceError)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(String)gql"sv)),
schema::Field::Make(R"gql(array)gql"sv, R"md()md"sv, std::nullopt, schema->WrapType(introspection::TypeKind::NON_NULL, schema->WrapType(introspection::TypeKind::LIST, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(ID)gql"sv)))))
});
}

Expand Down
30 changes: 30 additions & 0 deletions samples/today/schema/TodayAppointmentObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ concept getForceError = requires (TImpl impl)
{ service::AwaitableScalar<std::optional<std::string>> { impl.getForceError() } };
};

template <class TImpl>
concept getArrayWithParams = requires (TImpl impl, service::FieldParams params)
{
{ service::AwaitableScalar<std::vector<response::IdType>> { impl.getArray(std::move(params)) } };
};

template <class TImpl>
concept getArray = requires (TImpl impl)
{
{ service::AwaitableScalar<std::vector<response::IdType>> { impl.getArray() } };
};

template <class TImpl>
concept beginSelectionSet = requires (TImpl impl, const service::SelectionSetParams params)
{
Expand All @@ -103,6 +115,7 @@ class [[nodiscard("unnecessary construction")]] Appointment final
[[nodiscard("unnecessary call")]] service::AwaitableResolver resolveSubject(service::ResolverParams&& params) const;
[[nodiscard("unnecessary call")]] service::AwaitableResolver resolveIsNow(service::ResolverParams&& params) const;
[[nodiscard("unnecessary call")]] service::AwaitableResolver resolveForceError(service::ResolverParams&& params) const;
[[nodiscard("unnecessary call")]] service::AwaitableResolver resolveArray(service::ResolverParams&& params) const;

[[nodiscard("unnecessary call")]] service::AwaitableResolver resolve_typename(service::ResolverParams&& params) const;

Expand All @@ -118,6 +131,7 @@ class [[nodiscard("unnecessary construction")]] Appointment final
[[nodiscard("unnecessary call")]] virtual service::AwaitableScalar<std::optional<std::string>> getSubject(service::FieldParams&& params) const = 0;
[[nodiscard("unnecessary call")]] virtual service::AwaitableScalar<bool> getIsNow(service::FieldParams&& params) const = 0;
[[nodiscard("unnecessary call")]] virtual service::AwaitableScalar<std::optional<std::string>> getForceError(service::FieldParams&& params) const = 0;
[[nodiscard("unnecessary call")]] virtual service::AwaitableScalar<std::vector<response::IdType>> getArray(service::FieldParams&& params) const = 0;
};

template <class T>
Expand Down Expand Up @@ -209,6 +223,22 @@ class [[nodiscard("unnecessary construction")]] Appointment final
}
}

[[nodiscard("unnecessary call")]] service::AwaitableScalar<std::vector<response::IdType>> getArray(service::FieldParams&& params) const override
{
if constexpr (methods::AppointmentHas::getArrayWithParams<T>)
{
return { _pimpl->getArray(std::move(params)) };
}
else if constexpr (methods::AppointmentHas::getArray<T>)
{
return { _pimpl->getArray() };
}
else
{
throw service::unimplemented_method(R"ex(Appointment::getArray)ex");
}
}

void beginSelectionSet(const service::SelectionSetParams& params) const override
{
if constexpr (methods::AppointmentHas::beginSelectionSet<T>)
Expand Down
42 changes: 11 additions & 31 deletions src/ClientGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2203,6 +2203,11 @@ void Generator::outputResponseFieldVisitorReserve(std::ostream& sourceFile,
}
}

if (dereference)
{
accessor.append(R"cpp(.)cpp");
}

std::unordered_set<std::string_view> fieldNames;

switch (responseField.type->kind())
Expand All @@ -2211,37 +2216,6 @@ void Generator::outputResponseFieldVisitorReserve(std::ostream& sourceFile,
case introspection::TypeKind::INTERFACE:
case introspection::TypeKind::UNION:
{
dereference = true;

for (auto modifier : responseField.modifiers)
{
switch (modifier)
{
case service::TypeModifier::None:
break;

case service::TypeModifier::Nullable:
accessor.append(R"cpp(->)cpp");
dereference = false;
break;

case service::TypeModifier::List:
if (dereference)
{
accessor.append(R"cpp(.)cpp");
}

accessor.append(R"cpp(back())cpp");
dereference = true;
break;
}
}

if (dereference)
{
accessor.append(R"cpp(.)cpp");
}

for (const auto& field : responseField.children)
{
if (fieldNames.emplace(field.name).second)
Expand All @@ -2263,6 +2237,12 @@ void Generator::outputResponseFieldVisitorStartObject(std::ostream& sourceFile,
std::string_view parentAccessor /* = {} */,
std::string_view parentCppType /* = {} */) const noexcept
{
if (responseField.type->kind() == introspection::TypeKind::SCALAR
&& SchemaLoader::getBuiltinTypes().contains(responseField.type->name()))
{
return;
}

auto state = std::format("{}_{}",
parentState.empty() ? R"cpp(Member)cpp"sv : parentState,
responseField.cppName);
Expand Down

0 comments on commit 8e0aa14

Please sign in to comment.