Repository: dotnet/efcore
File: src/EFCore/Infrastructure/Uniquifier.cs (C#)

Code before:
    ///     Ensures the given identifier is shorter than the given length by removing the extra characters from the end.
    /// </summary>
    /// <param name="identifier">The identifier to shorten.</param>
    /// <param name="maxLength">The maximum length of the identifier.</param>
    /// <param name="suffix">An optional suffix to add after the uniquifier.</param>
    /// <param name="uniquifier">An optional number that will be appended to the identifier.</param>
    /// <returns>The shortened identifier.</returns>
    public static string Truncate(string identifier, int maxLength, string? suffix = null, int? uniquifier = null)
    {
        ValidateTruncate(maxLength, suffix, uniquifier, out var maxNameLength, out var uniquifierLength);

        var bufferSize = Math.Min(identifier.Length, maxNameLength) + uniquifierLength;
        var buffer = bufferSize <= StackAllocationLimit
            ? stackalloc char[bufferSize]
            : new char[bufferSize];

        return new string(TruncateImpl(identifier, buffer, maxNameLength, suffix, uniquifier));
    }

    private static void ValidateTruncate(int maxLength, string? suffix, int? uniquifier, out int maxNameLength, out int uniquifierLength)
    {
        uniquifierLength = (suffix?.Length ?? 0) + GetLength(uniquifier);
        maxNameLength = maxLength - uniquifierLength;
        if (maxNameLength <= 0)
        {
            throw new ArgumentException(nameof(maxLength));
        }
    }

    private static ReadOnlySpan<char> TruncateImpl(ReadOnlySpan<char> identifier, Span<char> buffer, int maxNameLength, string? suffix, int? uniquifier)
    {
        int position;

        if (identifier.Length <= maxNameLength)
        {
            identifier.CopyTo(buffer);
            position = identifier.Length;
        }
        else
        {
            identifier[..(maxNameLength - 1)].CopyTo(buffer);
            buffer[maxNameLength - 1] = '~';
            position = maxNameLength;
        }

        if (uniquifier is not null)
        {
            uniquifier.Value.TryFormat(buffer[position..], out var written);
            position += written;
        }


Review comment (bug):
The ArgumentException constructor is being called incorrectly. The first parameter should be a descriptive error message, not the parameter name. According to the codebase conventions (e.g., CoreStrings.InvalidEnumValue in EntityEntry.cs:83), error messages should come from the CoreStrings resource file, and the parameter name should be passed as the second argument. The correct pattern should be: throw new ArgumentException(CoreStrings.SomeDescriptiveMessage, nameof(maxLength));
```suggestion
            throw new ArgumentException("Invalid maximum length for truncation.", nameof(maxLength));
```

Code after:
    ///     Ensures the given identifier is shorter than the given length by removing the extra characters from the end.
    /// </summary>
    /// <param name="identifier">The identifier to shorten.</param>
    /// <param name="maxLength">The maximum length of the identifier.</param>
    /// <param name="suffix">An optional suffix to add after the uniquifier.</param>
    /// <param name="uniquifier">An optional number that will be appended to the identifier.</param>
    /// <returns>The shortened identifier.</returns>
    public static string Truncate(string identifier, int maxLength, string? suffix = null, int? uniquifier = null)
    {
        ValidateTruncate(maxLength, suffix, uniquifier, out var maxNameLength, out var uniquifierLength);

        var bufferSize = Math.Min(identifier.Length, maxNameLength) + uniquifierLength;
        var buffer = bufferSize <= StackAllocationLimit
            ? stackalloc char[bufferSize]
            : new char[bufferSize];

        return new string(TruncateImpl(identifier, buffer, maxNameLength, suffix, uniquifier));
    }

    private static void ValidateTruncate(int maxLength, string? suffix, int? uniquifier, out int maxNameLength, out int uniquifierLength)
    {
        uniquifierLength = (suffix?.Length ?? 0) + GetLength(uniquifier);
        maxNameLength = maxLength - uniquifierLength;
        if (maxNameLength <= 0)
        {
            throw new ArgumentException("Invalid maximum length for truncation.", nameof(maxLength));
        }
    }

    private static ReadOnlySpan<char> TruncateImpl(ReadOnlySpan<char> identifier, Span<char> buffer, int maxNameLength, string? suffix, int? uniquifier)
    {
        int position;

        if (identifier.Length <= maxNameLength)
        {
            identifier.CopyTo(buffer);
            position = identifier.Length;
        }
        else
        {
            identifier[..(maxNameLength - 1)].CopyTo(buffer);
            buffer[maxNameLength - 1] = '~';
            position = maxNameLength;
        }

        if (uniquifier is not null)
        {
            var result = uniquifier.Value.TryFormat(buffer[position..], out var written);
            Check.DebugAssert(result, "Formatting uniquifier failed.");
            position += written;
        }