Files
HelperLib/WHY_RIDER_SHOWS_ATTRIBUTES.md
T
2026-02-11 23:33:32 +00:00

4.8 KiB

Why Rider Shows Documentation Attribute Instead of XML Documentation

The Problem

When working in the HelperLib repository, hovering over methods in Rider shows:

[Documentation("TryGetValue", "Tries to get the value...", null, "")]
public bool TryGetValue(TKey key, out TValue value)

Instead of rich IntelliSense documentation.

Root Cause: Source Code Takes Priority

How IDEs Resolve Documentation

IDEs like Rider, Visual Studio, and VS Code follow this priority order:

  1. Triple-slash comments (///) in source code ← HIGHEST PRIORITY
  2. XML documentation files (.xml)
  3. Decompiled/reflected information
  4. Raw signature

What's Happening in HelperLib

Current state:

[Documentation("TryGetValue", "Tries to get the value...")]
public bool TryGetValue(TKey key, out TValue value)
{
    // No /// comments here!
}

The test project uses <ProjectReference>:

  • Rider can access the source code directly
  • No /// comments exist in source
  • Rider shows the raw source code (including the attribute)
  • XML file is ignored because source is available

The Solution: Add Triple-Slash Comments

Add simple /// <summary> that references the documentation:

[Documentation("TryGetValue", "Tries to get the value from the NeoDictionary for the given key.")]
/// <summary>
/// Tries to get the value from the NeoDictionary for the given key.
/// </summary>
public bool TryGetValue(TKey key, out TValue value)

Benefits:

  • ✅ Rider shows documentation immediately
  • ✅ Works for developers with source access
  • ✅ XML generator can still augment with additional info
  • ✅ Standard .NET practice

Option 2: Generated Comments (Advanced)

Create a Source Generator that reads DocumentationAttribute and generates /// <summary> comments automatically.

Benefits:

  • ✅ Single source of truth (the attribute)
  • ✅ No duplication

Drawbacks:

  • ❌ More complex
  • ❌ Requires Source Generator infrastructure
  • ❌ Comments generated at compile-time (not visible in source)

Option 3: Accept Current Behavior

Keep as-is and document that developers see attributes, consumers see XML.

Benefits:

  • ✅ No code changes needed
  • ✅ XML documentation works perfectly for NuGet consumers

Drawbacks:

  • ❌ Poor developer experience in IDE
  • ❌ Makes development harder

Why This Matters

For Library Developers (Us)

Working on HelperLib with ProjectReference:

  • ❌ Without ///: See raw attributes, no IntelliSense
  • ✅ With ///: See rich documentation in IDE

For Library Consumers

Installing HelperLib NuGet package:

  • ✅ Only have DLL + XML
  • ✅ Always see rich documentation
  • ✅ Not affected by source code

Recommendation

Add /// <summary> comments to all public APIs.

This is standard practice in .NET libraries:

  • Microsoft does this (see .NET source code)
  • Popular libraries do this (Newtonsoft.Json, etc.)
  • Provides best developer experience

The DocumentationAttribute can still provide additional metadata:

  • Code examples
  • Extended remarks
  • Structured argument descriptions

The XmlDocGenerator augments the XML with this additional content.

Implementation Plan

  1. Add /// <summary> to all public types and members
  2. Keep DocumentationAttribute for extended metadata
  3. XmlDocGenerator augments XML with attribute data
  4. Best of both worlds:
    • Developers see documentation in IDE
    • XML files have rich content from attributes
    • Consumers get full documentation

Example

Before:

[Documentation("BenchmarkUtility", "Utility class for benchmarking code execution time.")]
public class BenchmarkUtility
{
    [Documentation("Start", "Starts or restarts the stopwatch for the given key.")]
    public static void Start(string key)

After:

[Documentation("BenchmarkUtility", "Utility class for benchmarking code execution time.", null, @"```csharp
BenchmarkUtility.Start(""MyBenchmark"");
// Code to benchmark
BenchmarkUtility.Stop(""MyBenchmark"");
```")]
/// <summary>
/// Utility class for benchmarking code execution time.
/// </summary>
public class BenchmarkUtility
{
    [Documentation("Start", "Starts or restarts the stopwatch for the given key.")]
    /// <summary>
    /// Starts or restarts the stopwatch for the given key.
    /// </summary>
    /// <param name="key">The benchmark identifier</param>
    public static void Start(string key)

Result:

  • ✅ Rider shows documentation immediately
  • ✅ XML file has base documentation
  • ✅ XmlDocGenerator adds code examples from attribute
  • ✅ Perfect IDE experience for everyone

Automated Solution

Could create a tool or analyzer that:

  1. Reads DocumentationAttribute
  2. Warns if no /// <summary> exists
  3. Suggests adding the summary from the attribute

This enforces the pattern and maintains single source of truth.