Skip to content

Commit 9069f08

Browse files
committed
Port reorderInputTypeDependencies to RequestLoader
1 parent 323e5ac commit 9069f08

File tree

3 files changed

+105
-25
lines changed

3 files changed

+105
-25
lines changed

include/RequestLoader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class RequestLoader
9797
void collectFragments() noexcept;
9898
void collectVariables() noexcept;
9999
void collectInputTypes(const RequestSchemaType& variableType) noexcept;
100+
void reorderInputTypeDependencies() noexcept;
100101
void collectEnums(const RequestSchemaType& variableType) noexcept;
101102
void collectEnums(const ResponseField& responseField) noexcept;
102103

src/RequestLoader.cpp

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ RequestLoader::RequestLoader(RequestOptions&& requestOptions, const SchemaLoader
6868
collectEnums(variable.type);
6969
}
7070

71+
// Handle nested input types by fully declaring the dependencies first.
72+
reorderInputTypeDependencies();
73+
7174
for (const auto& responseField : _responseType.fields)
7275
{
7376
collectEnums(responseField);
@@ -774,6 +777,86 @@ void RequestLoader::collectInputTypes(const RequestSchemaType& variableType) noe
774777
}
775778
}
776779

780+
void RequestLoader::reorderInputTypeDependencies() noexcept
781+
{
782+
if (_referencedInputTypes.empty())
783+
{
784+
return;
785+
}
786+
787+
// Build the dependency list for each input type.
788+
struct InputTypeDependencies
789+
{
790+
RequestSchemaType type;
791+
std::string_view name;
792+
std::unordered_set<std::string_view> dependencies;
793+
};
794+
795+
std::vector<InputTypeDependencies> inputTypes(_referencedInputTypes.size());
796+
797+
std::transform(_referencedInputTypes.cbegin(),
798+
_referencedInputTypes.cend(),
799+
inputTypes.begin(),
800+
[](const RequestSchemaType& type) noexcept {
801+
InputTypeDependencies result { type, type->name() };
802+
const auto& fields = type->inputFields();
803+
804+
std::for_each(fields.begin(),
805+
fields.end(),
806+
[&result](const std::shared_ptr<const schema::InputValue>& field) noexcept {
807+
const auto fieldType = field->type().lock();
808+
809+
if (fieldType->kind() == introspection::TypeKind::INPUT_OBJECT)
810+
{
811+
result.dependencies.insert(fieldType->name());
812+
}
813+
});
814+
815+
return result;
816+
});
817+
818+
std::unordered_set<std::string_view> handled;
819+
auto itr = inputTypes.begin();
820+
821+
while (itr != inputTypes.end())
822+
{
823+
// Put all of the input types without unhandled dependencies at the front.
824+
const auto itrDependent = std::stable_partition(itr,
825+
inputTypes.end(),
826+
[&handled](const InputTypeDependencies& entry) noexcept {
827+
return std::find_if(entry.dependencies.cbegin(),
828+
entry.dependencies.cend(),
829+
[&handled](std::string_view dependency) noexcept {
830+
return handled.find(dependency) == handled.cend();
831+
})
832+
== entry.dependencies.cend();
833+
});
834+
835+
if (itrDependent != inputTypes.end())
836+
{
837+
std::for_each(itr,
838+
itrDependent,
839+
[&handled](const InputTypeDependencies& entry) noexcept {
840+
handled.insert(entry.name);
841+
});
842+
}
843+
844+
itr = itrDependent;
845+
}
846+
847+
if (!handled.empty())
848+
{
849+
std::transform(inputTypes.begin(),
850+
inputTypes.end(),
851+
_referencedInputTypes.begin(),
852+
[](InputTypeDependencies& entry) noexcept {
853+
auto result = std::move(entry.type);
854+
855+
return result;
856+
});
857+
}
858+
}
859+
777860
void RequestLoader::collectEnums(const RequestSchemaType& variableType) noexcept
778861
{
779862
// Enums may be referenced in any variable input type or in the response itself.
@@ -816,7 +899,8 @@ void RequestLoader::collectEnums(const ResponseField& responseField) noexcept
816899
{
817900
if (responseField.children)
818901
{
819-
for (const auto& responseType : std::get<ResponseUnionOptions>(*responseField.children))
902+
for (const auto& responseType :
903+
std::get<ResponseUnionOptions>(*responseField.children))
820904
{
821905
for (const auto& field : responseType.fields)
822906
{

src/SchemaLoader.cpp

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -500,18 +500,16 @@ void SchemaLoader::fixupInputFieldList(InputFieldList& fields)
500500
void SchemaLoader::reorderInputTypeDependencies()
501501
{
502502
// Build the dependency list for each input type.
503-
for (auto& entry : _inputTypes)
504-
{
505-
fixupInputFieldList(entry.fields);
506-
507-
for (auto& field : entry.fields)
508-
{
509-
if (field.fieldType == InputFieldType::Input)
510-
{
511-
entry.dependencies.insert(field.type);
512-
}
513-
}
514-
}
503+
std::for_each(_inputTypes.begin(), _inputTypes.end(), [](InputType& entry) noexcept {
504+
std::for_each(entry.fields.cbegin(),
505+
entry.fields.cend(),
506+
[&entry](const InputField& field) noexcept {
507+
if (field.fieldType == InputFieldType::Input)
508+
{
509+
entry.dependencies.insert(field.type);
510+
}
511+
});
512+
});
515513

516514
std::unordered_set<std::string_view> handled;
517515
auto itr = _inputTypes.begin();
@@ -521,16 +519,14 @@ void SchemaLoader::reorderInputTypeDependencies()
521519
// Put all of the input types without unhandled dependencies at the front.
522520
const auto itrDependent = std::stable_partition(itr,
523521
_inputTypes.end(),
524-
[&handled](const InputType& entry) noexcept
525-
{
526-
return std::find_if(entry.dependencies.cbegin(),
527-
entry.dependencies.cend(),
528-
[&handled](std::string_view dependency) noexcept
529-
{
530-
return handled.find(dependency) == handled.cend();
531-
})
532-
== entry.dependencies.cend();
533-
});
522+
[&handled](const InputType& entry) noexcept {
523+
return std::find_if(entry.dependencies.cbegin(),
524+
entry.dependencies.cend(),
525+
[&handled](std::string_view dependency) noexcept {
526+
return handled.find(dependency) == handled.cend();
527+
})
528+
== entry.dependencies.cend();
529+
});
534530

535531
// Check to make sure we made progress.
536532
if (itrDependent == itr)
@@ -544,8 +540,7 @@ void SchemaLoader::reorderInputTypeDependencies()
544540

545541
if (itrDependent != _inputTypes.end())
546542
{
547-
std::for_each(itr, itrDependent, [&handled](const InputType& entry) noexcept
548-
{
543+
std::for_each(itr, itrDependent, [&handled](const InputType& entry) noexcept {
549544
handled.insert(entry.type);
550545
});
551546
}

0 commit comments

Comments
 (0)