Skip to content

Fix some mismatches in <inheritdoc /> #115653

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

Merged
merged 2 commits into from
May 17, 2025
Merged

Conversation

rhuijben
Copy link
Contributor

Fix some cases identified by a stupid scanner script written after looking at #115651.

@Copilot Copilot AI review requested due to automatic review settings May 16, 2025 14:58
@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label May 16, 2025
@rhuijben
Copy link
Contributor Author

Script used

using System;
using System.IO;
using System.Text.RegularExpressions;

class Program
{
    static void Main(string[] args)
    {
        string directoryPath = args.Length > 0 ? args[0] : Directory.GetCurrentDirectory();
        Console.WriteLine($"Scanning directory: {directoryPath}");

        foreach (string file in Directory.GetFiles(directoryPath, "*.cs", SearchOption.AllDirectories))
        {
            ProcessFile(file);
        }
    }

    static void ProcessFile(string filePath)
    {
        string[] lines = File.ReadAllLines(filePath);
        Regex inheritdocRegex = new Regex(@"^\s*///\s*<inheritdoc\s+cref=""([^""]+)""\s*/?>");
        Regex functionRegex = new Regex(
            @"^\s*(?:public|private|protected|internal|static|readonly|unsafe|async|virtual|override|sealed|abstract|extern|\s)*" + // modifiers
            @"(?:[\w<>,\[\]\s\(\).]+\??\s+)+" + // return type including optional '?'
            @"(?<name>(?:[\w\.<>]+))\s*\("   // method name
        );
        Regex propertyRegex = new Regex(
            @"^\s*(?:public|private|protected|internal|static|readonly|unsafe|abstract|virtual|override|sealed|\s)*" +
            @"[\w<>\[\],\s\(\).]+\s+" + // type
            @"(?<name>[a-zA-Z_][\w\.<>]*)\s*" +
            @"{?|=>"
        );

        string lastInheritedFunction = null;
        int inheritdocLineNumber = -1;

        for (int i = 0; i < lines.Length; i++)
        {
            Match inheritdocMatch = inheritdocRegex.Match(lines[i]);
            if (inheritdocMatch.Success)
            {
                lastInheritedFunction = ExtractFunctionName(inheritdocMatch.Groups[1].Value);
                inheritdocLineNumber = i + 1; // Store line number (1-based index)

                // Search forward for the actual function declaration
                for (int j = i + 1; j < lines.Length; j++)
                {
                    string trimmed = lines[j].Trim();

                    if (string.IsNullOrWhiteSpace(trimmed))
                        continue; // Skip empty lines

                    if (trimmed.StartsWith("///"))
                        continue; // Skip XML comments

                    if (trimmed is "{" or "}" || trimmed.StartsWith("("))
                        break; // Likely inside a body or unrelated block

                    Match functionMatch = functionRegex.Match(lines[j]);
                    Match propertyMatch = propertyRegex.Match(lines[j]);

                    string foundName = null;

                    if (functionMatch.Success)
                        foundName = CleanMemberName(functionMatch.Groups["name"].Value);
                    else if (propertyMatch.Success)
                        foundName = CleanMemberName(propertyMatch.Groups["name"].Value);

                    if (foundName != null)
                    {
                        if (foundName != lastInheritedFunction)
                        {
                            if (foundName == "operator" || lastInheritedFunction.StartsWith("op_")) // Operators
                            { }
                            else if (lastInheritedFunction + "Core" == foundName) // GetEnumeratorCore
                            { }
                            else if (lastInheritedFunction + "Alternate" == foundName) // GetEnumeratorCore
                            { }
                            else
                                Console.WriteLine($"{filePath}:{inheritdocLineNumber}: Expected '{lastInheritedFunction}', found '{foundName}'");
                        }
                        break;
                    }

                    // Optional: give up after N lines to avoid matching unrelated declarations
                    if (j - i > 5)
                        break;
                }
                lastInheritedFunction = null; // Reset after matching
            }
        }
    }

    static string ExtractFunctionName(string crefValue)
    {
        // Remove everything up to the last '.'
        int lastDot = crefValue.LastIndexOf('.');
        string namePart = lastDot != -1 ? crefValue.Substring(lastDot + 1) : crefValue;

        // Strip off parameter list: Method(...) → Method
        int parenIndex = namePart.IndexOf('(');
        if (parenIndex != -1)
            namePart = namePart.Substring(0, parenIndex);

        // Strip off generic arity: TryConvertFromChecked{T} → TryConvertFromChecked
        int genericIndex = namePart.IndexOf('{');
        if (genericIndex != -1)
            namePart = namePart.Substring(0, genericIndex);

        return namePart;
    }


    static string CleanMemberName(string rawName)
    {
        // Remove explicit interface prefix (e.g., INumberBase<Complex>.TryConvert → TryConvert)
        int lastDotIndex = rawName.LastIndexOf('.');
        string name = lastDotIndex != -1 ? rawName.Substring(lastDotIndex + 1) : rawName;

        // Remove generic arity (e.g., TryConvertFromChecked<TOther> → TryConvertFromChecked)
        int genericIndex = name.IndexOf('<');
        if (genericIndex != -1)
            name = name.Substring(0, genericIndex);

        return name;
    }
}

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label May 16, 2025
@rhuijben
Copy link
Contributor Author

@dotnet-policy-service agree

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes mismatches in XML documentation references for various intrinsic and numerical types as identified by a scanner script. The proposed changes update tags so that they correctly reference the intended interface or method.

  • Updated doc comments on SIMD intrinsic types to reference the corresponding SinCos or ElementCount members.
  • Swapped mistaken documentation references for logarithm methods in Vector2/Vector3.
  • Corrected inherited documentation for collection synchronization members in Queue and Stack.

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs Changed XML doc from Count to ElementCount.
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs Updated XML docs to refer to SinCos methods for double and float.
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs Updated XML docs to refer to SinCos methods for double and float.
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs Updated XML docs to refer to SinCos methods for double and float.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs Corrected XML docs for Clamp and SinCosPi.
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs Swapped XML docs for Log and Log2 methods.
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs Swapped XML docs for Log and Log2 methods.
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs Updated XML doc to reference ICollection{T}.IsSynchronized.
src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs Updated XML doc to reference ICollection{T}.IsSynchronized.
Comments suppressed due to low confidence (4)

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs:531

  • The XML documentation now correctly reflects the property 'ElementCount'. Verify that this change aligns with the interface's intended contract.
/// <inheritdoc cref="ISimdVector{TSelf, T}.ElementCount" />

src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs:751

  • The XML reference for the Log method has been updated; ensure this correctly reflects the conversion from Vector3 to Vector4 for logarithm computation.
/// <inheritdoc cref="Vector4.Log(Vector4)" />

src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs:755

  • Changing the XML documentation for the Log2 method clarifies the intended reference. Confirm the switch properly distinguishes it from Log.
/// <inheritdoc cref="Vector4.Log2(Vector4)" />

src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs:722

  • The XML documentation for the Log2 method now properly references Vector4.Log2. Verify that this change aligns with the intended behavior.
/// <inheritdoc cref="Vector4.Log2(Vector4)" />

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@jkotas jkotas merged commit 058b1ef into dotnet:main May 17, 2025
137 of 141 checks passed
@rhuijben rhuijben deleted the fix/inheritdoc branch May 18, 2025 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community-contribution Indicates that the PR has been added by a community member needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants