Packages

An elixir interface for libgraphqlparser implemented as a NIF for parsing GraphQL.

Current section

Files

Jump to
graphql_parser libgraphqlparser JsonVisitor.cpp
Raw

libgraphqlparser/JsonVisitor.cpp

/**
* Copyright (c) 2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#include "position.hh"
#include "JsonVisitor.h"
#include <assert.h>
#include <iterator>
namespace facebook {
namespace graphql {
namespace ast {
namespace visitor {
// Method invariant: printed_ contains strings for this node's children.
void JsonVisitor::printLocation(const yy::location &location)
{
out_ << "{\"start\":" << location.begin.column
<< ",\"end\":" << location.end.column << '}';
}
void JsonVisitor::startPrintingNode(const char *kind, const yy::location &location) {
out_.str("");
out_ << "{\"kind\":\"" << kind << "\",\"loc\":";
printLocation(location);
out_ << ',';
return;
}
void JsonVisitor::printChildArray(
const std::vector<std::string>::const_iterator &childIterator,
size_t numChildren) {
out_ << '[';
for (int ii = 0; ii < numChildren; ++ii) {
if (ii != 0) {
out_ << ',';
}
out_ << *(childIterator + ii);
}
out_ << ']';
}
void JsonVisitor::visitNode() {
printed_.emplace_back();
}
void JsonVisitor::endVisitNode() {
printed_.pop_back();
printed_.back().emplace_back(out_.str());
}
bool JsonVisitor::visitDocument(const Document &document) {
visitNode();
return true;
}
void JsonVisitor::endVisitDocument(const Document &document) {
startPrintingNode("Document", document.getLocation());
out_ << "\"definitions\":";
const auto &children = printed_.back();
printChildArray(children.begin(), children.size());
out_ << '}';
printed_.pop_back();
assert(printed_.empty());
}
bool JsonVisitor::visitOperationDefinition(const OperationDefinition &operationDefinition) {
visitNode();
return true;
}
void JsonVisitor::endVisitOperationDefinition(const OperationDefinition &operationDefinition) {
startPrintingNode("OperationDefinition", operationDefinition.getLocation());
out_ << "\"operation\":\"" << operationDefinition.getOperation()
<< '\"';
const auto &children = printed_.back();
auto nextChild = children.begin();
out_ << ",\"name\": "
<< (operationDefinition.getName() ? *nextChild++ : "null");
out_ << ",\"variableDefinitions\":";
const auto *variableDefinitions = operationDefinition.getVariableDefinitions();
if (variableDefinitions != nullptr) {
printChildArray(nextChild, variableDefinitions->size());
nextChild += variableDefinitions->size();
} else {
out_ << "null";
}
out_ << ",\"directives\":";
const auto *directives = operationDefinition.getDirectives();
if (directives != nullptr) {
printChildArray(nextChild, directives->size());
nextChild += directives->size();
} else {
out_ << "null";
}
out_ << ",\"selectionSet\":" << *nextChild++;
assert(nextChild == children.end());
out_ << "}";
endVisitNode();
}
bool JsonVisitor::visitVariableDefinition(const VariableDefinition &variableDefinition) {
visitNode();
return true;
}
void JsonVisitor::endVisitVariableDefinition(const VariableDefinition &variableDefinition) {
startPrintingNode("VariableDefinition", variableDefinition.getLocation());
const auto &children = printed_.back();
out_ << "\"variable\":" << children[0];
out_ << ",\"type\":" << children[1];
out_ << ",\"defaultValue\":";
if (children.size() > 2) {
assert(children.size() == 3);
out_ << children[2];
} else {
assert(children.size() == 2);
out_ << "null";
}
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitSelectionSet(const SelectionSet &selectionSet) {
visitNode();
return true;
}
void JsonVisitor::endVisitSelectionSet(const SelectionSet &selectionSet) {
startPrintingNode("SelectionSet", selectionSet.getLocation());
out_ << "\"selections\":";
const auto &children = printed_.back();
printChildArray(children.begin(), children.size());
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitField(const Field &field) {
visitNode();
return true;
}
void JsonVisitor::endVisitField(const Field &field) {
startPrintingNode("Field", field.getLocation());
const auto &children = printed_.back();
auto nextChild = children.begin();
out_ << "\"alias\":";
if (field.getAlias() != nullptr) {
out_ << *nextChild++;
} else {
out_ << "null";
}
out_ << ",\"name\":" << *nextChild++;
out_ << ",\"arguments\":";
const auto *arguments = field.getArguments();
if (arguments != nullptr) {
printChildArray(nextChild, arguments->size());
nextChild += arguments->size();
} else {
out_ << "null";
}
out_ << ",\"directives\":";
const auto *directives = field.getDirectives();
if (directives != nullptr) {
printChildArray(nextChild, directives->size());
nextChild += directives->size();
} else {
out_ << "null";
}
out_ << ",\"selectionSet\":";
if (field.getSelectionSet() != nullptr) {
out_ << *nextChild++;
} else {
out_ << "null";
}
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitArgument(const Argument &argument) {
visitNode();
return true;
}
void JsonVisitor::endVisitArgument(const Argument &argument) {
startPrintingNode("Argument", argument.getLocation());
const auto &children = printed_.back();
out_ << "\"name\":" << children[0] << ",\"value\":" << children[1];
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitFragmentSpread(const FragmentSpread &fragmentSpread) {
visitNode();
return true;
}
void JsonVisitor::endVisitFragmentSpread(const FragmentSpread &fragmentSpread) {
startPrintingNode("FragmentSpread", fragmentSpread.getLocation());
const auto &children = printed_.back();
out_ << "\"name\":" << children[0];
out_ << ",\"directives\":";
const auto *directives = fragmentSpread.getDirectives();
if (directives != nullptr) {
printChildArray(children.begin() + 1, directives->size());
} else {
out_ << "null";
}
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitInlineFragment(const InlineFragment &inlineFragment) {
visitNode();
return true;
}
void JsonVisitor::endVisitInlineFragment(const InlineFragment &inlineFragment) {
startPrintingNode("InlineFragment", inlineFragment.getLocation());
const auto &children = printed_.back();
out_ << "\"typeCondition\":" << children[0];
out_ << ",\"directives\":";
auto nextChild = children.begin() + 1;
const auto *directives = inlineFragment.getDirectives();
if (directives != nullptr) {
printChildArray(nextChild, directives->size());
nextChild += directives->size();
} else {
out_ << "null";
}
out_ << ",\"selectionSet\":" << *nextChild++;
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitFragmentDefinition(const FragmentDefinition &fragmentDefinition) {
visitNode();
return true;
}
void JsonVisitor::endVisitFragmentDefinition(const FragmentDefinition &fragmentDefinition) {
startPrintingNode("FragmentDefinition", fragmentDefinition.getLocation());
const auto &children = printed_.back();
out_ << "\"name\":" << children[0];
out_ << ",\"typeCondition\":" << children[1];
auto nextChild = children.begin() + 2;
out_ << ",\"directives\":";
const auto *directives = fragmentDefinition.getDirectives();
if (directives != nullptr) {
printChildArray(nextChild, directives->size());
nextChild += directives->size();
} else {
out_ << "null";
}
out_ << ",\"selectionSet\":" << *nextChild++;
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitVariable(const Variable &variable) {
visitNode();
return true;
}
void JsonVisitor::endVisitVariable(const Variable &variable) {
startPrintingNode("Variable", variable.getLocation());
out_ << "\"name\":" << printed_.back()[0] << '}';
endVisitNode();
}
template <typename ValueType>
void JsonVisitor::endVisitValueRepresentedAsString(const char *valueKind, const ValueType &value) {
startPrintingNode(valueKind, value.getLocation());
out_ << "\"value\":\"" << value.getValue() << "\"}";
printed_.back().emplace_back(out_.str());
}
void JsonVisitor::endVisitIntValue(const IntValue &intValue) {
endVisitValueRepresentedAsString("IntValue", intValue);
}
void JsonVisitor::endVisitFloatValue(const FloatValue &floatValue) {
endVisitValueRepresentedAsString("FloatValue", floatValue);
}
void JsonVisitor::endVisitStringValue(const StringValue &stringValue) {
endVisitValueRepresentedAsString("StringValue", stringValue);
}
void JsonVisitor::endVisitEnumValue(const EnumValue &enumValue) {
endVisitValueRepresentedAsString("EnumValue", enumValue);
}
void JsonVisitor::endVisitBooleanValue(const BooleanValue &booleanValue) {
startPrintingNode("BooleanValue", booleanValue.getLocation());
out_ << "\"value\":" << (booleanValue.getValue() ? "true" : "false") << '}';
printed_.back().emplace_back(out_.str());
}
bool JsonVisitor::visitArrayValue(const ArrayValue &arrayValue) {
visitNode();
return true;
}
void JsonVisitor::endVisitArrayValue(const ArrayValue &arrayValue) {
startPrintingNode("ArrayValue", arrayValue.getLocation());
out_ << "\"values\":";
printChildArray(printed_.back().begin(), arrayValue.getValues().size());
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitObjectValue(const ObjectValue &objectValue) {
visitNode();
return true;
}
void JsonVisitor::endVisitObjectValue(const ObjectValue &objectValue) {
startPrintingNode("ObjectValue", objectValue.getLocation());
out_ << "\"fields\":";
printChildArray(printed_.back().begin(), objectValue.getFields().size());
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitObjectField(const ObjectField &objectField) {
visitNode();
return true;
}
void JsonVisitor::endVisitObjectField(const ObjectField &objectField) {
startPrintingNode("ObjectField", objectField.getLocation());
const auto &children = printed_.back();
out_ << "\"name\":" << children[0] << ",\"value\":" << children[1];
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitDirective(const Directive &directive) {
visitNode();
return true;
}
void JsonVisitor::endVisitDirective(const Directive &directive) {
startPrintingNode("Directive", directive.getLocation());
const auto &children = printed_.back();
out_ << "\"name\":" << children[0];
auto nextChild = children.begin() + 1;
out_ << ",\"arguments\":";
const auto *arguments = directive.getArguments();
if (arguments != nullptr) {
printChildArray(nextChild, arguments->size());
} else {
out_ << "null";
}
out_ << '}';
endVisitNode();
}
void JsonVisitor::endVisitName(const Name &name) {
endVisitValueRepresentedAsString("Name", name);
}
bool JsonVisitor::visitNamedType(const NamedType &namedType) {
visitNode();
return true;
}
void JsonVisitor::endVisitNamedType(const NamedType &namedType) {
startPrintingNode("NamedType", namedType.getLocation());
out_ << "\"name\":" << printed_.back()[0];
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitListType(const ListType &listType) {
visitNode();
return true;
}
void JsonVisitor::endVisitListType(const ListType &listType) {
startPrintingNode("ListType", listType.getLocation());
out_ << "\"type\":" << printed_.back()[0];
out_ << '}';
endVisitNode();
}
bool JsonVisitor::visitNonNullType(const NonNullType &nonNullType) {
visitNode();
return true;
}
void JsonVisitor::endVisitNonNullType(const NonNullType &nonNullType) {
startPrintingNode("NonNullType", nonNullType.getLocation());
out_ << "\"type\":" << printed_.back()[0];
out_ << '}';
endVisitNode();
}
}
}
}
}