DebuggerDisplayAttribute analyzer - SergeyTeplyakov/ErrorProne.NET GitHub Wiki
DebuggerDisplayAttribute
is one of the most underutilized attributes ever. This attribute is incredibly useful for debugging purposed because it can show not just default ToString
representation of the object but something more meaningful for person during debugging session.
But because DebuggerDisplayAttribute
takes just a string, it is very easy to mess up with it's content. And as always ErrorProne.NET could be in handy in this case.
ErrorProne.NET now understands this attribute and will warn (maybe it should be an error?) in following cases:
Provided string has invalid format
DebuggerDisplayAttribute
takes a format string that should have following structure: Text: {expression}
, i.e. user may specify any text she wants follows by expression in curly braces. So if the string is invalid, ErrorProne.NET will warn you about it:
[DebuggerDisplay("X: {ToString(), nq")]
// ~~~~~~~~~~~~~~~~~~~~
// Can't find corresponding close brace '}' in the input string
public class CustomType
{}
Unknown format specifier
User may provide additional format specifier to DebuggerDisplayAttribute
inside {}
. The only one that I'm aware of is nq
which stands for 'no quotes': DebuggerDisplay("{ToString(), nq}"
. And of course, if you'll mess with it you'll get a warning:
[DebuggerDisplay("X: {ToString(), dq}")]
// ~~~~~~~~~~~~~~~~~~~~
// Expression 'ToString(), dq' is invalid:
// Unknown expression specifier 'dq'. Known specifier is 'nq'.
public class CustomType
{ }
Expression is invalid
Ok, those two cases were pretty simple, now let's consider more advanced stuff.
DebuggerDisplayAttribute
can reference almost everything. It can any expression that references any static/instance members including fields, methods and properties. More over, you may call any methods and even provide any arguments there! The only rule for methods is that it should be non-void (yep, method can return anything and the result would be translated to string).
But because this attribute just takes a string it is relatively easy to mess with it without noticing.
ErrorProne.NET will show warning if the expression provided to the attribute is invalid:
[DebuggerDisplay("X: {ToDisplayString(42)d}")]
// ~~~~~~~~~~~~~~~~~~~~
// Expression 'ToStrinString(42)d' is invalid: 'Unexpected token 'd''
public class CustomType
{ }
NOTE
Please keep in mind that expressions provided to DebuggerDisplayAttribute
are language specific. So you should avoid them and just provide a function invocation that will do all the required computations.
Expression is valid but member is unknown
String-based expressions are very error-prone (pun intended) and refactoring unfriendly. It means that someone can change the name of the field/property/method or just change method signature and compiler will not notice. Compiler can't help in this case, but ErrorProne.NET can:
[DebuggerDisplay("X: {ToDisplayString(string.Empty)}")]
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Expression 'ToStrinString(string.Emmpty)' is invalid:
// Argument 1: cannot convert from 'string' to 'int'
public class CustomType
{
private string _internalStringRepresentation = "foo";
private int ToDisplayString(int someArguments)
{
return someArguments;
}
}
Or member is invalid:
[DebuggerDisplay("X: {_internalStringRepr}")]
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
// Expression 'ToStrinString(string.Emmpty)' is invalid:
// 'The name '_internalStringRepr' does not exists in current context'
public class CustomType
{
private string _internalStringRepresentation = "foo";
}
Even when method returns void
:
[DebuggerDisplay("X: {ToDisplayString()}")]
// ~~~~~~~~~~~~~~~~~~~~~~~~
// Expression 'ToStrinString(string.Emmpty)' is invalid:
// 'Cannot implicitely convert type 'void' to 'object''
public class CustomType
{
private void ToDisplayString()
{}
}