@@ -2022,6 +2022,8 @@ void ValidateExecutableVisitor::visitInlineFragment(const peg::ast_node& inlineF
2022
2022
2023
2023
void ValidateExecutableVisitor::visitDirectives (introspection::DirectiveLocation location, const peg::ast_node& directives)
2024
2024
{
2025
+ std::set<std::string> uniqueDirectives;
2026
+
2025
2027
for (const auto & directive : directives.children )
2026
2028
{
2027
2029
std::string directiveName;
@@ -2032,6 +2034,18 @@ void ValidateExecutableVisitor::visitDirectives(introspection::DirectiveLocation
2032
2034
directiveName = child.string_view ();
2033
2035
});
2034
2036
2037
+ if (!uniqueDirectives.insert (directiveName).second )
2038
+ {
2039
+ // http://spec.graphql.org/June2018/#sec-Directives-Are-Unique-Per-Location
2040
+ auto position = directive->begin ();
2041
+ std::ostringstream message;
2042
+
2043
+ message << " Conflicting directive name: " << directiveName;
2044
+
2045
+ _errors.push_back ({ message.str (), { position.line , position.byte_in_line } });
2046
+ continue ;
2047
+ }
2048
+
2035
2049
auto itrDirective = _directives.find (directiveName);
2036
2050
2037
2051
if (itrDirective == _directives.end ())
@@ -2046,6 +2060,52 @@ void ValidateExecutableVisitor::visitDirectives(introspection::DirectiveLocation
2046
2060
continue ;
2047
2061
}
2048
2062
2063
+ if (itrDirective->second .locations .find (location) == itrDirective->second .locations .end ())
2064
+ {
2065
+ // http://spec.graphql.org/June2018/#sec-Directives-Are-In-Valid-Locations
2066
+ auto position = directive->begin ();
2067
+ std::ostringstream message;
2068
+
2069
+ message << " Unexpected location for directive: " << directiveName;
2070
+
2071
+ switch (location)
2072
+ {
2073
+ case introspection::DirectiveLocation::QUERY:
2074
+ message << " name: QUERY" ;
2075
+ break ;
2076
+
2077
+ case introspection::DirectiveLocation::MUTATION:
2078
+ message << " name: MUTATION" ;
2079
+ break ;
2080
+
2081
+ case introspection::DirectiveLocation::SUBSCRIPTION:
2082
+ message << " name: SUBSCRIPTION" ;
2083
+ break ;
2084
+
2085
+ case introspection::DirectiveLocation::FIELD:
2086
+ message << " name: FIELD" ;
2087
+ break ;
2088
+
2089
+ case introspection::DirectiveLocation::FRAGMENT_DEFINITION:
2090
+ message << " name: FRAGMENT_DEFINITION" ;
2091
+ break ;
2092
+
2093
+ case introspection::DirectiveLocation::FRAGMENT_SPREAD:
2094
+ message << " name: FRAGMENT_SPREAD" ;
2095
+ break ;
2096
+
2097
+ case introspection::DirectiveLocation::INLINE_FRAGMENT:
2098
+ message << " name: INLINE_FRAGMENT" ;
2099
+ break ;
2100
+
2101
+ default :
2102
+ break ;
2103
+ }
2104
+
2105
+ _errors.push_back ({ message.str (), { position.line , position.byte_in_line } });
2106
+ continue ;
2107
+ }
2108
+
2049
2109
peg::on_first_child<peg::arguments>(*directive,
2050
2110
[this , &directive, &directiveName, itrDirective](const peg::ast_node& child)
2051
2111
{
0 commit comments