-
Notifications
You must be signed in to change notification settings - Fork 161
/
JsonVisitor.h
121 lines (100 loc) · 3.4 KB
/
JsonVisitor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include "AstNode.h"
#include "AstVisitor.h"
#include <sstream>
#include <vector>
namespace facebook {
namespace graphql {
namespace ast {
namespace visitor {
/**
* Produces a JSON string describing the visited AST, in a format that
* would be a valid graphql-js AST when parsed.
*/
class JsonVisitor : public AstVisitor {
private:
using ChildrenList = std::vector<std::string>;
// Stack of lists of printed children.
// Postvisit method precondition: printed.back() contains strings
// for this node's children.
// Postvisit method postcondition: *(printed.rbegin() - 1) has had this
std::vector<ChildrenList> printed_;
// Interface to print fields for each kind of node.
// Note that, because of the post-order traversal for printing,
// field values need not be passed explicitly; they are grabbed from
// the passed-in visitor!
class NodeFieldPrinter {
private:
JsonVisitor &visitor_;
ChildrenList::const_iterator nextChild_;
std::ostringstream out_;
void printFieldSeparator();
// Prints a non-null array of n children from the given
// iterator. Does not update the iterator.
void printChildList(
std::ostringstream &out,
const std::vector<std::string>::const_iterator &childIterator,
size_t numChildren);
void printLocation(std::ostringstream &out, const yy::location &location);
public:
// Begin printing the fields for a node of the given kind at the
// given location.
NodeFieldPrinter(
JsonVisitor &visitor,
const char *nodeKind,
const Node &node);
std::string finishPrinting();
void printSingularPrimitiveField(const char *fieldName, const char *value);
void printSingularBooleanField(const char *fieldName, bool value);
void printSingularObjectField(const char *fieldName);
void printNullableSingularObjectField(const char *fieldName, const void *value);
template <typename T>
void printPluralField(
const char *fieldName,
const std::vector<std::unique_ptr<T>> &value) {
printFieldSeparator();
out_ << '"' << fieldName << "\":";
printChildList(out_, nextChild_, value.size());
nextChild_ += value.size();
}
template <typename T>
void printNullablePluralField(
const char *fieldName,
const std::vector<std::unique_ptr<T>> *value) {
printFieldSeparator();
out_ << '"' << fieldName << "\":";
if (value == nullptr) {
out_ << "null";
} else {
printChildList(out_, nextChild_, value->size());
nextChild_ += value->size();
}
}
};
// Must be called at the start of all visit methods for node types
// that have children. Maintains printed_.
void visitNode();
// Must be called at the end of all visit methods for node types
// that have children, passing the text for this node. Maintains
// printed_.
void endVisitNode(std::string &&str);
// Prints one of the many FooValue types that is prepresented with a
// single string.
template <typename ValueNode>
void endVisitValueRepresentedAsString(const char *valueKind, const ValueNode &value);
public:
JsonVisitor();
~JsonVisitor() {}
std::string getResult() const;
#include "JsonVisitor.h.inc"
};
}
}
}
}