Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use <inheritdoc cref> to reference the XML summary of another variable?

When I'm writing functions for my project, and more specifically, their XML documentation comments, I find myself repeating the comments for a specific parameter often. This leads to misleading documentation sometimes (as copy pasting usually does...).

This is a simple example I thought of, which represents the real problem.

/// <summary>
/// The number that should be doubled
/// </summary>
private static float myNumber = 10f;

/// <summary>
/// Multiplies a number by 2
/// </summary>
/// <param name="number"><inheritdoc cref="myNumber"/></param>
/// <returns>The number multiplied by 2</returns>
private static float MultiplyByTwo(float number)
{
    return number * 2f;
}

In this line /// <param name="number"><inheritdoc cref="myNumber"/></param>, I would like to have the text "The number that should be doubled", but it's not showing up. Maybe I don't understand the use of inheritdoc completely.

What I mean by showing up is this. Visual Studio should show the documentation of number in that box:

visual studio info box not showing the documentation when hovering over the function

This is what it should look like (without copy pasting the text):

visual studio info box showing the documentation when hovering over the function

So, is there a way to reference a different variable in XML documentation comments?

like image 750
Eldemarkki Avatar asked Aug 06 '20 13:08

Eldemarkki


1 Answers

In Visual Studio 16.8.4 I'm able to use <inheritdoc>'s path attribute to do this.

/// <summary>
/// The number that should be doubled
/// </summary>
private static float myNumber = 10f;
        
/// <summary>
/// Multiplies a number by 2
/// </summary>
/// <param name="number"><inheritdoc cref="myNumber" path="/summary"/></param>
/// <returns></returns>
private static float MultiplyByTwo(float number)
{
    return number * 2f;
}

In the path attribute, / selects the 'root' node and then summary is the node to select within that node.

Result:

enter image description here

The path attribute uses XPath syntax, which you can find more about here.

You can use it to do some great stuff if you're careful; I regularly use it when implementing the Try[...] pattern.

For example:

/// <summary>
/// This throws!
/// </summary>
/// <param name="param1">This is a parameter.</param>
/// <param name="param2">This is another parameter!</param>
/// <exception cref="InvalidOperationException"/>
public string ExampleThatCanThrow(int param1, float param2)
{
    throw new InvalidOperationException();
}

/// <summary>
/// This never throws!
/// </summary>
/// <inheritdoc cref="ExampleThatCanThrow(int, float)" path="/*[not(self::exception)]"/>
public bool TryExample(int param1, float param2, out string? result)
{
    result = "No throwing here!";
    return true;
}

Normally when using <inheritdoc> for the TryExample method in this way, it would show that it could throw InvalidOperationException. Using the path attribute, I've filtered it so only the nodes that don't match the name of exception will be inherited.

/: Matches the root node.

*: Matches any child node.

[ and ]: Matches any node that meets the conditions of the contained predicate.

not(): Matches any node that doesn't meet the conditions of the expression within the parentheses.

self::exception: Matches the current node if it has the name of exception.

This results in the below:

enter image description here enter image description here

In addition, you can use this functionality to more easily show the exceptions that can be thrown by a method without typing them out explicitly:

/// <summary>
/// Validates a file in some way.
/// </summary>
/// <param name="filePath">A full path to the file to be validated.</param>
/// <inheritdoc cref="File.OpenRead(string)" path="/exception"/>
private static void ValidateFile(string filePath)
{
    using FileStream file = File.OpenRead(filePath);
    // Validation code...
}

This above use of <inheritdoc> will cause the tooltip on the method to show that it can throw all of the exceptions that the System.IO.File.OpenRead method can throw. Just be careful that you ensure necessary validation exceptions are actually thrown and accounted for.

like image 199
Unordinal Avatar answered Sep 30 '22 03:09

Unordinal