Skip to content

BRO1601: Overrides and implementations should inherit their documentation

An override or interface implementation without documentation gets /// <inheritdoc/>, which takes the documentation from the member it overrides or implements. Replaces StyleCop SA1600 for these members.

Example

Before

using System;

/// <summary>Something that has a size.</summary>
public interface ISized
{
    /// <summary>Gets the size in bytes.</summary>
    long Size { get; }
}

/// <summary>A file on disk.</summary>
public class DiskFile : ISized, IDisposable
{
    public long Size => 0;

    public void Dispose()
    {
    }

    public override string ToString() => "file";
}

After

using System;

/// <summary>Something that has a size.</summary>
public interface ISized
{
    /// <summary>Gets the size in bytes.</summary>
    long Size { get; }
}

/// <summary>A file on disk.</summary>
public class DiskFile : ISized, IDisposable
{
    /// <inheritdoc/>
    public long Size => 0;

    /// <inheritdoc/>
    public void Dispose()
    {
    }

    /// <inheritdoc/>
    public override string ToString() => "file";
}

Why

The documentation of an override or implementation is usually the same as its base's. <inheritdoc/> says so explicitly, and IntelliSense and documentation generators show the inherited text.

Other missing documentation isn't reported. StyleCop's SA1600 reports every undocumented element, but the only automatic fix for a method or class without documentation is placeholder text, which satisfies the rule without documenting anything. StyleBro only reports what it can fix meaningfully.

How the fix works

/// <inheritdoc/> is inserted on its own line right before the member, above its attributes, at the member's indentation. A plain // comment above the member stays above it; blank lines between that comment and the member go too when BRO1506 is on (it would remove them, but can't see them once the /// is in between). When code sits on the line above, a blank line goes in between (BRO1513); when a property sits right below a documented property, a blank line goes there too (BRO1505 lets undocumented single-line properties sit together, documented ones not).

Checked: methods, properties, indexers and events that override a member or implicitly implement an interface member. Explicit interface implementations (void IDisposable.Dispose()) aren't: they're only reachable through the interface, whose documentation tools show (like StyleCop's unreleased master).

Not reported

  • Projects that don't generate documentation (no <GenerateDocumentationFile>true</GenerateDocumentationFile>), like StyleCop's documentation rules, which say so with SA0001 and stay quiet. The package's build targets pass the property to the analyzer, so a build and dotnet format agree (dotnet format parses documentation comments even where the build doesn't). Without the package's targets (the analyzer referenced directly), the compiler's documentation mode decides.
  • A member with #if, #elif, #else or #endif above it or between its attributes. In a multi-targeted project the member can start with a different token in each target framework ([Obsolete] only under #if NET5_0_OR_GREATER), each copy wanted <inheritdoc/> in another place, and BRO1602 turned the other copy's into //: dotnet format never converged. Other directives (#region, #pragma) are fine.
  • Explicit interface implementations (see How the fix works).

Configuration

Which members need documentation, like StyleCop's documentationRules in stylecop.json. A member counts by its effective accessibility: a public member of an internal class is internal, of a private class private; protected members are exposed.

[*.cs]
# Visible outside the assembly (default true)
stylebro_document_exposed_elements = true
# Visible only inside the assembly (default true)
stylebro_document_internal_elements = true
# Private, or in a private type (default false)
stylebro_document_private_elements = false

How the inserted tag is written (existing tags are never rewritten):

[*.cs]
# compact (default): /// <inheritdoc/>
# spaced:            /// <inheritdoc />
stylebro_inheritdoc_style = compact

With spaced:

/// <inheritdoc />
public override string ToString() => "file";

Compared with StyleCop

Same positions as StyleCop 1.2.0-beta.556 for overrides and implicit implementations. Explicit interface implementations (void IDisposable.Dispose()) aren't reported, like in StyleCop's master (unreleased, 2959cac8; the owner's decision, see decisions); beta.556 reports them. A member with a conditional directive above it or between its attributes isn't reported (StyleCop reports it). StyleCop's own SA1600 fix has no Fix All, so dotnet format doesn't apply it.