Skip to content

Commit 89fc567

Browse files
authored
Merge pull request #241 from wravery/multi-request
Output all operations from `clientgen` if the `--operation` flag is not specified
2 parents a74155a + 6570214 commit 89fc567

24 files changed

+2139
-683
lines changed

cmake/cppgraphqlgen-update-client-files.cmake

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ cmake_policy(SET CMP0057 NEW)
4848
file(GLOB OLD_FILES ${CLIENT_SOURCE_DIR}/*.h ${CLIENT_SOURCE_DIR}/*.cpp)
4949
foreach(OLD_FILE ${OLD_FILES})
5050
get_filename_component(OLD_FILE ${OLD_FILE} NAME)
51-
if(NOT OLD_FILE IN_LIST FILE_NAMES AND
52-
NOT OLD_FILE STREQUAL "${CLIENT_PREFIX}Client.h" AND
53-
NOT OLD_FILE STREQUAL "${CLIENT_PREFIX}Client.cpp")
54-
message(WARNING "Unexpected file in ${CLIENT_TARGET} client sources: ${OLD_FILE}")
51+
if(NOT OLD_FILE IN_LIST FILE_NAMES)
52+
if(OLD_FILE MATCHES "Client\\.h$" OR OLD_FILE MATCHES "Client\\.cpp$")
53+
file(REMOVE "${CLIENT_SOURCE_DIR}/${OLD_FILE}")
54+
else()
55+
message(WARNING "Unexpected file in ${CLIENT_TARGET} client sources: ${OLD_FILE}")
56+
endif()
5557
endif()
5658
endforeach()
5759

include/ClientGenerator.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,22 @@ class [[nodiscard]] Generator
3939
[[nodiscard]] std::string getHeaderPath() const noexcept;
4040
[[nodiscard]] std::string getSourcePath() const noexcept;
4141
[[nodiscard]] const std::string& getClientNamespace() const noexcept;
42-
[[nodiscard]] const std::string& getRequestNamespace() const noexcept;
43-
[[nodiscard]] const std::string& getFullNamespace() const noexcept;
42+
[[nodiscard]] const std::string& getOperationNamespace(
43+
const Operation& operation) const noexcept;
4444
[[nodiscard]] std::string getResponseFieldCppType(
4545
const ResponseField& responseField, std::string_view currentScope = {}) const noexcept;
4646

4747
[[nodiscard]] bool outputHeader() const noexcept;
4848
void outputRequestComment(std::ostream& headerFile) const noexcept;
4949
void outputGetRequestDeclaration(std::ostream& headerFile) const noexcept;
50+
void outputGetOperationNameDeclaration(std::ostream& headerFile) const noexcept;
5051
[[nodiscard]] bool outputResponseFieldType(std::ostream& headerFile,
5152
const ResponseField& responseField, size_t indent = 0) const noexcept;
5253

5354
[[nodiscard]] bool outputSource() const noexcept;
5455
void outputGetRequestImplementation(std::ostream& sourceFile) const noexcept;
56+
void outputGetOperationNameImplementation(
57+
std::ostream& sourceFile, const Operation& operation) const noexcept;
5558
bool outputModifiedResponseImplementation(std::ostream& sourceFile,
5659
const std::string& outerScope, const ResponseField& responseField) const noexcept;
5760
[[nodiscard]] static std::string getTypeModifierList(

include/GeneratorUtil.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class [[nodiscard]] NamespaceScope
3939
private:
4040
bool _inside = false;
4141
std::ostream& _outputFile;
42-
std::string_view _cppNamespace;
42+
std::string _cppNamespace;
4343
};
4444

4545
// Keep track of whether we want to add a blank separator line once some additional content is about

include/RequestLoader.h

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,25 @@ struct [[nodiscard]] RequestVariable
6464

6565
using RequestVariableList = std::vector<RequestVariable>;
6666

67+
struct [[nodiscard]] Operation
68+
{
69+
const peg::ast_node* operation;
70+
std::string_view name;
71+
std::string_view type;
72+
ResponseType responseType {};
73+
RequestVariableList variables {};
74+
internal::string_view_set inputTypeNames {};
75+
RequestInputTypeList referencedInputTypes {};
76+
internal::string_view_set enumNames {};
77+
RequestSchemaTypeList referencedEnums {};
78+
};
79+
80+
using OperationList = std::vector<Operation>;
81+
6782
struct [[nodiscard]] RequestOptions
6883
{
6984
const std::string requestFilename;
70-
const std::string operationName;
85+
const std::optional<std::string> operationName;
7186
const bool noIntrospection = false;
7287
};
7388

@@ -79,16 +94,21 @@ class [[nodiscard]] RequestLoader
7994
explicit RequestLoader(RequestOptions&& requestOptions, const SchemaLoader& schemaLoader);
8095

8196
[[nodiscard]] std::string_view getRequestFilename() const noexcept;
82-
[[nodiscard]] std::string_view getOperationDisplayName() const noexcept;
83-
[[nodiscard]] std::string getOperationNamespace() const noexcept;
84-
[[nodiscard]] std::string_view getOperationType() const noexcept;
97+
[[nodiscard]] const OperationList& getOperations() const noexcept;
98+
[[nodiscard]] std::string_view getOperationDisplayName(
99+
const Operation& operation) const noexcept;
100+
[[nodiscard]] std::string getOperationNamespace(const Operation& operation) const noexcept;
101+
[[nodiscard]] std::string_view getOperationType(const Operation& operation) const noexcept;
85102
[[nodiscard]] std::string_view getRequestText() const noexcept;
86103

87-
[[nodiscard]] const ResponseType& getResponseType() const noexcept;
88-
[[nodiscard]] const RequestVariableList& getVariables() const noexcept;
104+
[[nodiscard]] const ResponseType& getResponseType(const Operation& operation) const noexcept;
105+
[[nodiscard]] const RequestVariableList& getVariables(
106+
const Operation& operation) const noexcept;
89107

90-
[[nodiscard]] const RequestInputTypeList& getReferencedInputTypes() const noexcept;
91-
[[nodiscard]] const RequestSchemaTypeList& getReferencedEnums() const noexcept;
108+
[[nodiscard]] const RequestInputTypeList& getReferencedInputTypes(
109+
const Operation& operation) const noexcept;
110+
[[nodiscard]] const RequestSchemaTypeList& getReferencedEnums(
111+
const Operation& operation) const noexcept;
92112

93113
[[nodiscard]] std::string getInputCppType(
94114
const RequestSchemaType& wrappedInputType) const noexcept;
@@ -111,11 +131,11 @@ class [[nodiscard]] RequestLoader
111131

112132
void findOperation();
113133
void collectFragments() noexcept;
114-
void collectVariables() noexcept;
115-
void collectInputTypes(const RequestSchemaType& variableType) noexcept;
116-
void reorderInputTypeDependencies();
117-
void collectEnums(const RequestSchemaType& variableType) noexcept;
118-
void collectEnums(const ResponseField& responseField) noexcept;
134+
void collectVariables(Operation& operation) noexcept;
135+
void collectInputTypes(Operation& operation, const RequestSchemaType& variableType) noexcept;
136+
void reorderInputTypeDependencies(Operation& operation);
137+
void collectEnums(Operation& operation, const RequestSchemaType& variableType) noexcept;
138+
void collectEnums(Operation& operation, const ResponseField& responseField) noexcept;
119139

120140
using FragmentDefinitionMap = std::map<std::string_view, const peg::ast_node*>;
121141

@@ -153,16 +173,8 @@ class [[nodiscard]] RequestLoader
153173
peg::ast _ast;
154174

155175
std::string _requestText;
156-
const peg::ast_node* _operation = nullptr;
157-
std::string_view _operationName;
158-
std::string_view _operationType;
176+
OperationList _operations;
159177
FragmentDefinitionMap _fragments;
160-
ResponseType _responseType;
161-
RequestVariableList _variables;
162-
internal::string_view_set _inputTypeNames;
163-
RequestInputTypeList _referencedInputTypes;
164-
internal::string_view_set _enumNames;
165-
RequestSchemaTypeList _referencedEnums;
166178
};
167179

168180
} // namespace graphql::generator

samples/client/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ add_subdirectory(query)
77
add_subdirectory(mutate)
88
add_subdirectory(subscribe)
99
add_subdirectory(nestedinput)
10+
add_subdirectory(multiple)
1011

1112
add_subdirectory(benchmark)
1213

samples/client/benchmark.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,15 @@ int main(int argc, char** argv)
8686

8787
try
8888
{
89-
for (size_t i = 0; i < iterations; ++i)
90-
{
91-
using namespace client::query::Query;
89+
using namespace client::query::Query;
9290

93-
auto query = GetRequestObject();
91+
auto query = GetRequestObject();
92+
const auto& name = GetOperationName();
9493

94+
for (size_t i = 0; i < iterations; ++i)
95+
{
9596
const auto startResolve = std::chrono::steady_clock::now();
96-
auto response = service->resolve({ query }).get();
97+
auto response = service->resolve({ query, name }).get();
9798
const auto startParseServiceResponse = std::chrono::steady_clock::now();
9899
auto serviceResponse = client::parseServiceResponse(std::move(response));
99100
const auto startParseResponse = std::chrono::steady_clock::now();

samples/client/benchmark/BenchmarkClient.cpp

Lines changed: 59 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,56 @@
1414
using namespace std::literals;
1515

1616
namespace graphql::client {
17+
namespace benchmark {
1718

18-
using namespace query::Query;
19+
const std::string& GetRequestText() noexcept
20+
{
21+
static const auto s_request = R"gql(
22+
# Copyright (c) Microsoft Corporation. All rights reserved.
23+
# Licensed under the MIT License.
24+
25+
query {
26+
appointments {
27+
pageInfo {
28+
hasNextPage
29+
}
30+
edges {
31+
node {
32+
id
33+
when
34+
subject
35+
isNow
36+
}
37+
}
38+
}
39+
}
40+
)gql"s;
41+
42+
return s_request;
43+
}
44+
45+
const peg::ast& GetRequestObject() noexcept
46+
{
47+
static const auto s_request = []() noexcept {
48+
auto ast = peg::parseString(GetRequestText());
49+
50+
// This has already been validated against the schema by clientgen.
51+
ast.validated = true;
52+
53+
return ast;
54+
}();
55+
56+
return s_request;
57+
}
58+
59+
} // namespace benchmark
60+
61+
using namespace benchmark;
1962

2063
template <>
21-
Response::appointments_AppointmentConnection::pageInfo_PageInfo ModifiedResponse<Response::appointments_AppointmentConnection::pageInfo_PageInfo>::parse(response::Value&& response)
64+
query::Query::Response::appointments_AppointmentConnection::pageInfo_PageInfo ModifiedResponse<query::Query::Response::appointments_AppointmentConnection::pageInfo_PageInfo>::parse(response::Value&& response)
2265
{
23-
Response::appointments_AppointmentConnection::pageInfo_PageInfo result;
66+
query::Query::Response::appointments_AppointmentConnection::pageInfo_PageInfo result;
2467

2568
if (response.type() == response::Type::Map)
2669
{
@@ -40,9 +83,9 @@ Response::appointments_AppointmentConnection::pageInfo_PageInfo ModifiedResponse
4083
}
4184

4285
template <>
43-
Response::appointments_AppointmentConnection::edges_AppointmentEdge::node_Appointment ModifiedResponse<Response::appointments_AppointmentConnection::edges_AppointmentEdge::node_Appointment>::parse(response::Value&& response)
86+
query::Query::Response::appointments_AppointmentConnection::edges_AppointmentEdge::node_Appointment ModifiedResponse<query::Query::Response::appointments_AppointmentConnection::edges_AppointmentEdge::node_Appointment>::parse(response::Value&& response)
4487
{
45-
Response::appointments_AppointmentConnection::edges_AppointmentEdge::node_Appointment result;
88+
query::Query::Response::appointments_AppointmentConnection::edges_AppointmentEdge::node_Appointment result;
4689

4790
if (response.type() == response::Type::Map)
4891
{
@@ -77,9 +120,9 @@ Response::appointments_AppointmentConnection::edges_AppointmentEdge::node_Appoin
77120
}
78121

79122
template <>
80-
Response::appointments_AppointmentConnection::edges_AppointmentEdge ModifiedResponse<Response::appointments_AppointmentConnection::edges_AppointmentEdge>::parse(response::Value&& response)
123+
query::Query::Response::appointments_AppointmentConnection::edges_AppointmentEdge ModifiedResponse<query::Query::Response::appointments_AppointmentConnection::edges_AppointmentEdge>::parse(response::Value&& response)
81124
{
82-
Response::appointments_AppointmentConnection::edges_AppointmentEdge result;
125+
query::Query::Response::appointments_AppointmentConnection::edges_AppointmentEdge result;
83126

84127
if (response.type() == response::Type::Map)
85128
{
@@ -89,7 +132,7 @@ Response::appointments_AppointmentConnection::edges_AppointmentEdge ModifiedResp
89132
{
90133
if (member.first == R"js(node)js"sv)
91134
{
92-
result.node = ModifiedResponse<Response::appointments_AppointmentConnection::edges_AppointmentEdge::node_Appointment>::parse<TypeModifier::Nullable>(std::move(member.second));
135+
result.node = ModifiedResponse<query::Query::Response::appointments_AppointmentConnection::edges_AppointmentEdge::node_Appointment>::parse<TypeModifier::Nullable>(std::move(member.second));
93136
continue;
94137
}
95138
}
@@ -99,9 +142,9 @@ Response::appointments_AppointmentConnection::edges_AppointmentEdge ModifiedResp
99142
}
100143

101144
template <>
102-
Response::appointments_AppointmentConnection ModifiedResponse<Response::appointments_AppointmentConnection>::parse(response::Value&& response)
145+
query::Query::Response::appointments_AppointmentConnection ModifiedResponse<query::Query::Response::appointments_AppointmentConnection>::parse(response::Value&& response)
103146
{
104-
Response::appointments_AppointmentConnection result;
147+
query::Query::Response::appointments_AppointmentConnection result;
105148

106149
if (response.type() == response::Type::Map)
107150
{
@@ -111,12 +154,12 @@ Response::appointments_AppointmentConnection ModifiedResponse<Response::appointm
111154
{
112155
if (member.first == R"js(pageInfo)js"sv)
113156
{
114-
result.pageInfo = ModifiedResponse<Response::appointments_AppointmentConnection::pageInfo_PageInfo>::parse(std::move(member.second));
157+
result.pageInfo = ModifiedResponse<query::Query::Response::appointments_AppointmentConnection::pageInfo_PageInfo>::parse(std::move(member.second));
115158
continue;
116159
}
117160
if (member.first == R"js(edges)js"sv)
118161
{
119-
result.edges = ModifiedResponse<Response::appointments_AppointmentConnection::edges_AppointmentEdge>::parse<TypeModifier::Nullable, TypeModifier::List, TypeModifier::Nullable>(std::move(member.second));
162+
result.edges = ModifiedResponse<query::Query::Response::appointments_AppointmentConnection::edges_AppointmentEdge>::parse<TypeModifier::Nullable, TypeModifier::List, TypeModifier::Nullable>(std::move(member.second));
120163
continue;
121164
}
122165
}
@@ -127,44 +170,11 @@ Response::appointments_AppointmentConnection ModifiedResponse<Response::appointm
127170

128171
namespace query::Query {
129172

130-
const std::string& GetRequestText() noexcept
131-
{
132-
static const auto s_request = R"gql(
133-
# Copyright (c) Microsoft Corporation. All rights reserved.
134-
# Licensed under the MIT License.
135-
136-
query {
137-
appointments {
138-
pageInfo {
139-
hasNextPage
140-
}
141-
edges {
142-
node {
143-
id
144-
when
145-
subject
146-
isNow
147-
}
148-
}
149-
}
150-
}
151-
)gql"s;
152-
153-
return s_request;
154-
}
155-
156-
const peg::ast& GetRequestObject() noexcept
173+
const std::string& GetOperationName() noexcept
157174
{
158-
static const auto s_request = []() noexcept {
159-
auto ast = peg::parseString(GetRequestText());
160-
161-
// This has already been validated against the schema by clientgen.
162-
ast.validated = true;
175+
static const auto s_name = R"gql()gql"s;
163176

164-
return ast;
165-
}();
166-
167-
return s_request;
177+
return s_name;
168178
}
169179

170180
Response parseResponse(response::Value&& response)
@@ -179,7 +189,7 @@ Response parseResponse(response::Value&& response)
179189
{
180190
if (member.first == R"js(appointments)js"sv)
181191
{
182-
result.appointments = ModifiedResponse<Response::appointments_AppointmentConnection>::parse(std::move(member.second));
192+
result.appointments = ModifiedResponse<query::Query::Response::appointments_AppointmentConnection>::parse(std::move(member.second));
183193
continue;
184194
}
185195
}

samples/client/benchmark/BenchmarkClient.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ static_assert(graphql::internal::MinorVersion == 2, "regenerate with clientgen:
2222
#include <string>
2323
#include <vector>
2424

25+
namespace graphql::client {
26+
2527
/// <summary>
2628
/// Operation: query (unnamed)
2729
/// </summary>
@@ -45,14 +47,24 @@ static_assert(graphql::internal::MinorVersion == 2, "regenerate with clientgen:
4547
/// }
4648
/// }
4749
/// </code>
48-
namespace graphql::client::query::Query {
50+
namespace benchmark {
4951

5052
// Return the original text of the request document.
5153
const std::string& GetRequestText() noexcept;
5254

5355
// Return a pre-parsed, pre-validated request object.
5456
const peg::ast& GetRequestObject() noexcept;
5557

58+
} // namespace benchmark
59+
60+
namespace query::Query {
61+
62+
using benchmark::GetRequestText;
63+
using benchmark::GetRequestObject;
64+
65+
// Return the name of this operation in the shared request document.
66+
const std::string& GetOperationName() noexcept;
67+
5668
struct Response
5769
{
5870
struct appointments_AppointmentConnection
@@ -84,6 +96,7 @@ struct Response
8496

8597
Response parseResponse(response::Value&& response);
8698

87-
} // namespace graphql::client::query::Query
99+
} // namespace query::Query
100+
} // namespace graphql::client
88101

89102
#endif // BENCHMARKCLIENT_H

0 commit comments

Comments
 (0)