uniqueEnumValueNamesRule function
Visitor
uniqueEnumValueNamesRule(
- SDLValidationCtx context
Unique enum value names
A GraphQL enum type is only valid if all its values are uniquely named.
Implementation
Visitor uniqueEnumValueNamesRule(
SDLValidationCtx context,
) {
final schema = context.schema;
final Map<String, GraphQLType> existingTypeMap =
schema != null ? schema.typeMap : {};
final knownValueNames = <String, Map<String, NameNode>>{};
VisitBehavior? checkValueUniqueness(
NameNode name,
List<EnumValueDefinitionNode> valueNodes,
) {
final typeName = name.value;
final valueNames = knownValueNames.putIfAbsent(typeName, () => {});
for (final valueDef in valueNodes) {
final valueName = valueDef.name.value;
final existingType = existingTypeMap[typeName];
if (existingType is GraphQLEnumType &&
existingType.getValue(valueName) != null) {
context.reportError(
GraphQLError(
'Enum value "$typeName.$valueName" already exists in the schema.'
' It cannot also be defined in this type extension.',
locations: [
GraphQLErrorLocation.fromSourceLocation(valueDef.name.span!.start)
],
extensions: _uniqueEnumValueNamesSpec.extensions(),
),
);
} else if (valueNames[valueName] != null) {
context.reportError(
GraphQLError(
'Enum value "$typeName.$valueName" can only be defined once.',
locations: [
GraphQLErrorLocation.fromSourceLocation(
valueNames[valueName]!.span!.start,
),
GraphQLErrorLocation.fromSourceLocation(
valueDef.name.span!.start,
)
],
extensions: _uniqueEnumValueNamesSpec.extensions(),
),
);
} else {
valueNames[valueName] = valueDef.name;
}
}
return VisitBehavior.skipTree;
}
final visitor = TypedVisitor();
visitor.add<EnumTypeDefinitionNode>(
(node) => checkValueUniqueness(node.name, node.values));
visitor.add<EnumTypeExtensionNode>(
(node) => checkValueUniqueness(node.name, node.values));
return visitor;
}