Skip to content

Commit 8db6a94

Browse files
committed
Bind the input and parse tree lifetimes so string pointers always work
1 parent 357477a commit 8db6a94

File tree

5 files changed

+50
-25
lines changed

5 files changed

+50
-25
lines changed

GraphQLTree.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -558,21 +558,38 @@ struct ast_selector<document>
558558
{
559559
};
560560

561-
std::unique_ptr<ast_node> parseString(const char* text)
561+
std::unique_ptr<ast<std::string>> parseString(std::string&& input)
562562
{
563-
return parse_tree::parse<document, ast_node, ast_selector>(memory_input<>(text, "GraphQL"));
563+
std::unique_ptr<ast<std::string>> result(new ast<std::string> { std::move(input), nullptr });
564+
memory_input<> in(result->input.c_str(), result->input.size(), "GraphQL");
565+
566+
result->root = parse_tree::parse<document, ast_node, ast_selector>(std::move(in));
567+
568+
return result;
564569
}
565570

566-
std::unique_ptr<ast_node> parseFile(file_input<>&& in)
571+
std::unique_ptr<ast<std::unique_ptr<file_input<>>>> parseFile(const char* filename)
567572
{
568-
return parse_tree::parse<document, ast_node, ast_selector>(std::move(in));
573+
std::unique_ptr<ast<std::unique_ptr<file_input<>>>> result(new ast<std::unique_ptr<file_input<>>> {
574+
std::unique_ptr<file_input<>>(new file_input<>(std::string(filename))),
575+
nullptr
576+
});
577+
578+
result->root = parse_tree::parse<document, ast_node, ast_selector>(std::move(*result->input));
579+
580+
return result;
569581
}
570582

571583
} /* namespace peg */
572584

573-
std::unique_ptr<peg::ast_node> operator "" _graphql(const char* text, size_t size)
585+
std::unique_ptr<peg::ast<const char*>> operator "" _graphql(const char* text, size_t size)
574586
{
575-
return tao::graphqlpeg::parse_tree::parse<peg::document, peg::ast_node, peg::ast_selector>(tao::graphqlpeg::memory_input<>(text, size, "GraphQL"));
587+
std::unique_ptr<peg::ast<const char*>> result(new peg::ast<const char*> { text, nullptr });
588+
peg::memory_input<> in(text, size, "GraphQL");
589+
590+
result->root = peg::parse_tree::parse<peg::document, peg::ast_node, peg::ast_selector>(std::move(in));
591+
592+
return result;
576593
}
577594

578595
} /* namespace graphql */

GraphQLTree.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@ struct ast_node
2323
std::string unescaped;
2424
};
2525

26-
std::unique_ptr<ast_node> parseString(const char* text);
27-
std::unique_ptr<ast_node> parseFile(file_input<>&& in);
26+
template <typename _Input>
27+
struct ast
28+
{
29+
_Input input;
30+
std::unique_ptr<ast_node> root;
31+
};
32+
33+
std::unique_ptr<ast<std::string>> parseString(std::string&& input);
34+
std::unique_ptr<ast<std::unique_ptr<file_input<>>>> parseFile(const char* filename);
2835

2936
} /* namespace peg */
3037

31-
std::unique_ptr<peg::ast_node> operator "" _graphql(const char* text, size_t size);
38+
std::unique_ptr<peg::ast<const char*>> operator "" _graphql(const char* text, size_t size);
3239

3340
} /* namespace graphql */
3441
} /* namespace facebook */

SchemaGenerator.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ Generator::Generator()
144144
throw std::logic_error("Unable to parse the introspection schema, but there was no error message from the parser!");
145145
}
146146

147-
for (const auto& child : ast->children.front()->children)
147+
for (const auto& child : ast->root->children.front()->children)
148148
{
149149
visitDefinition(*child);
150150
}
@@ -160,15 +160,14 @@ Generator::Generator(std::string schemaFileName, std::string filenamePrefix, std
160160
, _filenamePrefix(std::move(filenamePrefix))
161161
, _schemaNamespace(std::move(schemaNamespace))
162162
{
163-
tao::graphqlpeg::file_input<> in(schemaFileName.c_str());
164-
auto ast = peg::parseFile(std::move(in));
163+
auto ast = peg::parseFile(schemaFileName.c_str());
165164

166165
if (!ast)
167166
{
168167
throw std::logic_error("Unable to parse the service schema, but there was no error message from the parser!");
169168
}
170169

171-
for (const auto& child : ast->children.front()->children)
170+
for (const auto& child : ast->root->children.front()->children)
172171
{
173172
visitDefinition(*child);
174173
}

test_today.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,25 +60,27 @@ int main(int argc, char** argv)
6060

6161
try
6262
{
63-
std::string input;
64-
std::unique_ptr<tao::graphqlpeg::file_input<>> file;
65-
std::unique_ptr<peg::ast_node> ast;
63+
const peg::ast_node* ast = nullptr;
64+
std::unique_ptr<peg::ast<std::string>> ast_input;
65+
std::unique_ptr<peg::ast<std::unique_ptr<peg::file_input<>>>> ast_file;
6666

6767
if (argc > 1)
6868
{
69-
file.reset(new tao::graphqlpeg::file_input<>(argv[1]));
70-
ast = peg::parseFile(std::move(*file));
69+
ast_file = peg::parseFile(argv[1]);
70+
ast = ast_file->root.get();
7171
}
7272
else
7373
{
74+
std::string input;
7475
std::string line;
7576

7677
while (std::getline(std::cin, line))
7778
{
7879
input.append(line);
7980
}
8081

81-
ast = peg::parseString(input.c_str());
82+
ast_input = peg::parseString(std::move(input));
83+
ast = ast_input->root.get();
8284
}
8385

8486
if (!ast)

tests.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ TEST_F(TodayServiceCase, QueryEverything)
123123
}
124124
})"_graphql;
125125
const rapidjson::Document variables(rapidjson::Type::kObjectType);
126-
const auto result = _service->resolve(*ast, "Everything", variables.GetObject());
126+
const auto result = _service->resolve(*ast->root, "Everything", variables.GetObject());
127127
EXPECT_EQ(size_t(1), _getAppointmentsCount) << "today service lazy loads the appointments and caches the result";
128128
EXPECT_EQ(size_t(1), _getTasksCount) << "today service lazy loads the tasks and caches the result";
129129
EXPECT_EQ(size_t(1), _getUnreadCountsCount) << "today service lazy loads the unreadCounts and caches the result";
@@ -197,7 +197,7 @@ TEST_F(TodayServiceCase, QueryAppointments)
197197
}
198198
})"_graphql;
199199
const rapidjson::Document variables(rapidjson::Type::kObjectType);
200-
const auto result = _service->resolve(*ast, "", variables.GetObject());
200+
const auto result = _service->resolve(*ast->root, "", variables.GetObject());
201201
EXPECT_EQ(size_t(1), _getAppointmentsCount) << "today service lazy loads the appointments and caches the result";
202202
EXPECT_GE(size_t(1), _getTasksCount) << "today service lazy loads the tasks and caches the result";
203203
EXPECT_GE(size_t(1), _getUnreadCountsCount) << "today service lazy loads the unreadCounts and caches the result";
@@ -252,7 +252,7 @@ TEST_F(TodayServiceCase, QueryTasks)
252252
}
253253
})gql"_graphql;
254254
const rapidjson::Document variables(rapidjson::Type::kObjectType);
255-
const auto result = _service->resolve(*ast, "", variables.GetObject());
255+
const auto result = _service->resolve(*ast->root, "", variables.GetObject());
256256
EXPECT_GE(size_t(1), _getAppointmentsCount) << "today service lazy loads the appointments and caches the result";
257257
EXPECT_EQ(size_t(1), _getTasksCount) << "today service lazy loads the tasks and caches the result";
258258
EXPECT_GE(size_t(1), _getUnreadCountsCount) << "today service lazy loads the unreadCounts and caches the result";
@@ -306,7 +306,7 @@ TEST_F(TodayServiceCase, QueryUnreadCounts)
306306
}
307307
})"_graphql;
308308
const rapidjson::Document variables(rapidjson::Type::kObjectType);
309-
const auto result = _service->resolve(*ast, "", variables.GetObject());
309+
const auto result = _service->resolve(*ast->root, "", variables.GetObject());
310310
EXPECT_GE(size_t(1), _getAppointmentsCount) << "today service lazy loads the appointments and caches the result";
311311
EXPECT_GE(size_t(1), _getTasksCount) << "today service lazy loads the tasks and caches the result";
312312
EXPECT_EQ(size_t(1), _getUnreadCountsCount) << "today service lazy loads the unreadCounts and caches the result";
@@ -359,7 +359,7 @@ TEST_F(TodayServiceCase, MutateCompleteTask)
359359
}
360360
})"_graphql;
361361
const rapidjson::Document variables(rapidjson::Type::kObjectType);
362-
const auto result = _service->resolve(*ast, "", variables.GetObject());
362+
const auto result = _service->resolve(*ast->root, "", variables.GetObject());
363363

364364
try
365365
{
@@ -434,7 +434,7 @@ TEST_F(TodayServiceCase, Introspection)
434434
}
435435
})"_graphql;
436436
const rapidjson::Document variables(rapidjson::Type::kObjectType);
437-
const auto result = _service->resolve(*ast, "", variables.GetObject());
437+
const auto result = _service->resolve(*ast->root, "", variables.GetObject());
438438

439439
try
440440
{

0 commit comments

Comments
 (0)