Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow flag enums to have a custom prefix by making the naming function virtual #7463

Closed
wants to merge 1 commit into from

Conversation

Cyberboss
Copy link
Contributor

Currently in order to do this, the entire file needs to be copied to modify this one static function. Simple making it virtual allows a child class to override it instead.

…n virtual

Currently in order to do this, the entire file needs to be copied to modify this one static function. Simple making it virtual allows a child class to override it instead.
@Cyberboss
Copy link
Contributor Author

Also, I'm just now realizing that the implementation uses internal classes like TypeInitializer so having custom names is not possible currently.

@michaelstaib
Copy link
Member

The class itself should be internal sealed.

@michaelstaib
Copy link
Member

I am closing this PR

@michaelstaib
Copy link
Member

are you just trying to change the name? if so you can chain another interceptor in that will rename it ...

@michaelstaib
Copy link
Member

If your on slack.chillicream.com ... put a question on general on how to prefix flags arrays and I will post some code.

@Cyberboss Cyberboss deleted the patch-1 branch September 21, 2024 17:11
@Cyberboss
Copy link
Contributor Author

Was able to achieve it with a type interceptor:

using System;
using System.Collections.Generic;

using HotChocolate.Configuration;
using HotChocolate.Types.Descriptors.Definitions;

using Tgstation.Server.Api.Rights;

namespace Tgstation.Server.Host.GraphQL.Types.Interceptors
{
	/// <summary>
	/// Fixes the names used for the default flags types in API rights.
	/// </summary>
	sealed class RightsTypeInterceptor : TypeInterceptor
	{
		/// <summary>
		/// Names of rights GraphQL object types.
		/// </summary>
		private readonly HashSet<string> objectNames;

		/// <summary>
		/// Names of rights GraphQL input types.
		/// </summary>
		private readonly HashSet<string> inputNames;

		/// <summary>
		/// Initializes a new instance of the <see cref="RightsTypeInterceptor"/> class.
		/// </summary>
		public RightsTypeInterceptor()
		{
			objectNames = new HashSet<string>();
			inputNames = new HashSet<string>();

			foreach (var rightType in Enum.GetValues<RightsType>())
			{
				var flagName = $"{rightType}RightsFlags";

				objectNames.Add(flagName);
				inputNames.Add($"{flagName}Input");
			}
		}

		/// <summary>
		/// Fix the "is" prefix on a given set of <paramref name="fields"/>.
		/// </summary>
		/// <typeparam name="TField">The <see cref="Type"/> of <see cref="FieldDefinitionBase"/> to correct.</typeparam>
		/// <param name="fields">The <see cref="IBindableList{T}"/> of <typeparamref name="TField"/>s to operate on.</param>
		static void FixFields<TField>(IBindableList<TField> fields)
			where TField : FieldDefinitionBase
		{
			TField? noneField = null;

			const string NoneFieldName = "isNone";
			foreach (var field in fields)
			{
				var fieldName = field.Name;
				if (fieldName == NoneFieldName)
				{
					noneField = field;
					continue;
				}

				const string IsPrefix = "is";
				if (!fieldName.StartsWith(IsPrefix))
					throw new InvalidOperationException("Expected flags enum type field to start with \"is\"!");

				field.Name = $"can{fieldName.Substring(IsPrefix.Length)}";
			}

			if (noneField == null)
				throw new InvalidOperationException($"Expected flags enum type field to contain \"{NoneFieldName}\"!");

			fields.Remove(noneField);
		}

		/// <inheritdoc />
		public override void OnBeforeRegisterDependencies(ITypeDiscoveryContext discoveryContext, DefinitionBase definition)
		{
			ArgumentNullException.ThrowIfNull(definition);

			if (definition is ObjectTypeDefinition objectTypeDef)
			{
				if (objectNames.Contains(objectTypeDef.Name))
					FixFields(objectTypeDef.Fields);
			}
			else if (definition is InputObjectTypeDefinition inputTypeDef)
				if (inputNames.Contains(inputTypeDef.Name))
					FixFields(inputTypeDef.Fields);
		}
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants