Skip to content

Commit b27d5d3

Browse files
committed
Unwrap referenced enum and input types
1 parent 9069f08 commit b27d5d3

File tree

2 files changed

+94
-44
lines changed

2 files changed

+94
-44
lines changed

include/RequestLoader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ class RequestLoader
9191
std::string_view type, const TypeModifierStack& modifiers) const noexcept;
9292
void validateRequest() const;
9393

94+
static std::pair<RequestSchemaType, TypeModifierStack> unwrapSchemaType(
95+
RequestSchemaType&& type) noexcept;
9496
static std::string_view trimWhitespace(std::string_view content) noexcept;
9597

9698
void findOperation();

src/RequestLoader.cpp

Lines changed: 92 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ RequestLoader::RequestLoader(RequestOptions&& requestOptions, const SchemaLoader
6262

6363
collectVariables();
6464

65+
// Variables can reference both input types and enums.
6566
for (const auto& variable : _variables)
6667
{
6768
collectInputTypes(variable.type);
@@ -71,6 +72,7 @@ RequestLoader::RequestLoader(RequestOptions&& requestOptions, const SchemaLoader
7172
// Handle nested input types by fully declaring the dependencies first.
7273
reorderInputTypeDependencies();
7374

75+
// The response can also reference enums.
7476
for (const auto& responseField : _responseType.fields)
7577
{
7678
collectEnums(responseField);
@@ -604,6 +606,48 @@ void RequestLoader::validateRequest() const
604606
}
605607
}
606608

609+
std::pair<RequestSchemaType, TypeModifierStack> RequestLoader::unwrapSchemaType(
610+
RequestSchemaType&& type) noexcept
611+
{
612+
std::pair<RequestSchemaType, TypeModifierStack> result { std::move(type), {} };
613+
bool wrapped = true;
614+
bool nonNull = false;
615+
616+
while (wrapped)
617+
{
618+
switch (result.first->kind())
619+
{
620+
case introspection::TypeKind::NON_NULL:
621+
nonNull = true;
622+
result.first = result.first->ofType().lock();
623+
break;
624+
625+
case introspection::TypeKind::LIST:
626+
if (!nonNull)
627+
{
628+
result.second.push_back(service::TypeModifier::Nullable);
629+
}
630+
631+
nonNull = false;
632+
result.second.push_back(service::TypeModifier::List);
633+
result.first = result.first->ofType().lock();
634+
break;
635+
636+
default:
637+
if (!nonNull)
638+
{
639+
result.second.push_back(service::TypeModifier::Nullable);
640+
}
641+
642+
nonNull = false;
643+
wrapped = false;
644+
break;
645+
}
646+
}
647+
648+
return result;
649+
}
650+
607651
std::string_view RequestLoader::trimWhitespace(std::string_view content) noexcept
608652
{
609653
const auto isSpacePredicate = [](char ch) noexcept {
@@ -764,16 +808,36 @@ void RequestLoader::collectVariables() noexcept
764808

765809
void RequestLoader::collectInputTypes(const RequestSchemaType& variableType) noexcept
766810
{
767-
// Input types may be referenced in any variable or field of a variable input type.
768-
if (variableType->kind() == introspection::TypeKind::INPUT_OBJECT
769-
&& _inputTypeNames.emplace(variableType->name()).second)
811+
switch (variableType->kind())
770812
{
771-
_referencedInputTypes.push_back(variableType);
813+
case introspection::TypeKind::INPUT_OBJECT:
814+
{
815+
if (_inputTypeNames.emplace(variableType->name()).second)
816+
{
817+
_referencedInputTypes.push_back(variableType);
818+
819+
// Input types can reference other input types and enums.
820+
for (const auto& inputField : variableType->inputFields())
821+
{
822+
const auto fieldType = inputField->type().lock();
823+
824+
collectInputTypes(fieldType);
825+
collectEnums(fieldType);
826+
}
827+
}
772828

773-
for (const auto& inputField : variableType->inputFields())
829+
break;
830+
}
831+
832+
case introspection::TypeKind::LIST:
833+
case introspection::TypeKind::NON_NULL:
774834
{
775-
collectInputTypes(inputField->type().lock());
835+
collectInputTypes(variableType->ofType().lock());
836+
break;
776837
}
838+
839+
default:
840+
break;
777841
}
778842
}
779843

@@ -859,11 +923,27 @@ void RequestLoader::reorderInputTypeDependencies() noexcept
859923

860924
void RequestLoader::collectEnums(const RequestSchemaType& variableType) noexcept
861925
{
862-
// Enums may be referenced in any variable input type or in the response itself.
863-
if (variableType->kind() == introspection::TypeKind::ENUM
864-
&& _enumNames.emplace(variableType->name()).second)
926+
switch (variableType->kind())
865927
{
866-
_referencedEnums.push_back(variableType);
928+
case introspection::TypeKind::ENUM:
929+
{
930+
if (_enumNames.emplace(variableType->name()).second)
931+
{
932+
_referencedEnums.push_back(variableType);
933+
}
934+
935+
break;
936+
}
937+
938+
case introspection::TypeKind::LIST:
939+
case introspection::TypeKind::NON_NULL:
940+
{
941+
collectEnums(variableType->ofType().lock());
942+
break;
943+
}
944+
945+
default:
946+
break;
867947
}
868948
}
869949

@@ -1023,40 +1103,8 @@ void RequestLoader::SelectionVisitor::visitField(const peg::ast_node& field)
10231103
responseField.type = (*itr)->type().lock();
10241104
}
10251105

1026-
bool wrapped = true;
1027-
bool nonNull = false;
1028-
1029-
while (wrapped)
1030-
{
1031-
switch (responseField.type->kind())
1032-
{
1033-
case introspection::TypeKind::NON_NULL:
1034-
nonNull = true;
1035-
responseField.type = responseField.type->ofType().lock();
1036-
break;
1037-
1038-
case introspection::TypeKind::LIST:
1039-
if (!nonNull)
1040-
{
1041-
responseField.modifiers.push_back(service::TypeModifier::Nullable);
1042-
}
1043-
1044-
nonNull = false;
1045-
responseField.modifiers.push_back(service::TypeModifier::List);
1046-
responseField.type = responseField.type->ofType().lock();
1047-
break;
1048-
1049-
default:
1050-
if (!nonNull)
1051-
{
1052-
responseField.modifiers.push_back(service::TypeModifier::Nullable);
1053-
}
1054-
1055-
nonNull = false;
1056-
wrapped = false;
1057-
break;
1058-
}
1059-
}
1106+
std::tie(responseField.type, responseField.modifiers) =
1107+
unwrapSchemaType(std::move(responseField.type));
10601108

10611109
const peg::ast_node* selection = nullptr;
10621110

0 commit comments

Comments
 (0)