Skip to content

Commit 1a45367

Browse files
committed
Add some DebuggerDisplay love
I followed implementation best practices as described at http://blogs.msdn.com/b/jaredpar/archive/2011/03/18/debuggerdisplay-attribute-best-practices.aspx Also added a Meta test to make sure the same implementation is used everywhere when using `[DebuggerDisplay]`.
1 parent 247ca1a commit 1a45367

20 files changed

+224
-4
lines changed

LibGit2Sharp.Tests/MetaFixture.cs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Text;
1+
using System.Diagnostics;
2+
using System.Text;
23
using Xunit;
34
using System.Reflection;
45
using System;
@@ -11,13 +12,54 @@ public class MetaFixture
1112
{
1213
private static readonly Type[] excludedTypes = new[] { typeof(Repository) };
1314

15+
// Related to https://github.com/libgit2/libgit2sharp/pull/251
16+
[Fact]
17+
public void TypesInLibGit2DecoratedWithDebuggerDisplayMustFollowTheStandardImplPattern()
18+
{
19+
var typesWithDebuggerDisplayAndInvalidImplPattern = new List<Type>();
20+
21+
IEnumerable<Type> libGit2SharpTypes = Assembly.GetAssembly(typeof(Repository)).GetExportedTypes()
22+
.Where(t => t.GetCustomAttributes(typeof(DebuggerDisplayAttribute), false).Any());
23+
24+
foreach (Type type in libGit2SharpTypes)
25+
{
26+
var debuggerDisplayAttribute = (DebuggerDisplayAttribute)type.GetCustomAttributes(typeof(DebuggerDisplayAttribute), false).Single();
27+
28+
if (debuggerDisplayAttribute.Value != "{DebuggerDisplay,nq}")
29+
{
30+
typesWithDebuggerDisplayAndInvalidImplPattern.Add(type);
31+
continue;
32+
}
33+
34+
PropertyInfo debuggerDisplayProperty = type.GetProperty("DebuggerDisplay",
35+
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
36+
37+
if (debuggerDisplayProperty == null)
38+
{
39+
typesWithDebuggerDisplayAndInvalidImplPattern.Add(type);
40+
continue;
41+
}
42+
43+
if (debuggerDisplayProperty.PropertyType != typeof(string))
44+
{
45+
typesWithDebuggerDisplayAndInvalidImplPattern.Add(type);
46+
}
47+
}
48+
49+
if (typesWithDebuggerDisplayAndInvalidImplPattern.Any())
50+
{
51+
Assert.True(false, Environment.NewLine + BuildMissingDebuggerDisplayPropertyMessage(typesWithDebuggerDisplayAndInvalidImplPattern));
52+
}
53+
}
54+
1455
// Related to https://github.com/libgit2/libgit2sharp/pull/185
1556
[Fact]
1657
public void TypesInLibGit2SharpMustBeExtensibleInATestingContext()
1758
{
1859
var nonTestableTypes = new Dictionary<Type, IEnumerable<string>>();
1960

20-
IEnumerable<Type> libGit2SharpTypes = Assembly.GetAssembly(typeof(Repository)).GetExportedTypes().Where(t => !excludedTypes.Contains(t) && t.Namespace == typeof(Repository).Namespace);
61+
IEnumerable<Type> libGit2SharpTypes = Assembly.GetAssembly(typeof(Repository)).GetExportedTypes()
62+
.Where(t => !excludedTypes.Contains(t) && t.Namespace == typeof(Repository).Namespace);
2163

2264
foreach (Type type in libGit2SharpTypes)
2365
{
@@ -49,6 +91,21 @@ public void TypesInLibGit2SharpMustBeExtensibleInATestingContext()
4991
}
5092
}
5193

94+
private string BuildMissingDebuggerDisplayPropertyMessage(IEnumerable<Type> typesWithDebuggerDisplayAndInvalidImplPattern)
95+
{
96+
var sb = new StringBuilder();
97+
98+
foreach (Type type in typesWithDebuggerDisplayAndInvalidImplPattern)
99+
{
100+
sb.AppendFormat("'{0}' is decorated with the DebuggerDisplayAttribute, but does not follow LibGit2Sharp implementation pattern.{1}" +
101+
" Please make sure that the type is decorated with `[DebuggerDisplay(\"{{DebuggerDisplay,nq}}\")]`,{1}" +
102+
" and that the type implements a private property named `DebuggerDisplay`, returning a string.{1}",
103+
type.Name, Environment.NewLine);
104+
}
105+
106+
return sb.ToString();
107+
}
108+
52109
private static string BuildNonTestableTypesMessage(Dictionary<Type, IEnumerable<string>> nonTestableTypes)
53110
{
54111
var sb = new StringBuilder();

LibGit2Sharp/BranchCollection.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Diagnostics;
45
using System.Globalization;
56
using System.Linq;
67
using LibGit2Sharp.Core;
@@ -11,6 +12,7 @@ namespace LibGit2Sharp
1112
/// <summary>
1213
/// The collection of Branches in a <see cref = "Repository" />
1314
/// </summary>
15+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1416
public class BranchCollection : IEnumerable<Branch>
1517
{
1618
internal readonly Repository repo;
@@ -192,5 +194,10 @@ private static bool LooksLikeABranchName(string referenceName)
192194
referenceName.StartsWith("refs/heads/", StringComparison.Ordinal) ||
193195
referenceName.StartsWith("refs/remotes/", StringComparison.Ordinal);
194196
}
197+
198+
private string DebuggerDisplay
199+
{
200+
get { return string.Format("Count = {0}", this.Count()); }
201+
}
195202
}
196203
}

LibGit2Sharp/Changes.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
using System.Diagnostics;
12
using System.Text;
23

34
namespace LibGit2Sharp
45
{
56
/// <summary>
67
/// Base class for changes.
78
/// </summary>
9+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
810
public abstract class Changes
911
{
1012
private readonly StringBuilder patchBuilder = new StringBuilder();
@@ -36,5 +38,10 @@ public virtual string Patch
3638
/// Determines if at least one side of the comparison holds binary content.
3739
/// </summary>
3840
public virtual bool IsBinaryComparison { get; protected set; }
41+
42+
private string DebuggerDisplay
43+
{
44+
get { return string.Format(@"{{+{0}, -{1}}}", LinesAdded, LinesDeleted); }
45+
}
3946
}
4047
}

LibGit2Sharp/ConfigurationEntry.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
namespace LibGit2Sharp
1+
using System.Diagnostics;
2+
3+
namespace LibGit2Sharp
24
{
35
/// <summary>
46
/// An enumerated configuration entry.
57
/// </summary>
8+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
69
public class ConfigurationEntry
710
{
811
/// <summary>
@@ -33,5 +36,10 @@ public ConfigurationEntry(string key, string value, ConfigurationLevel level)
3336
Value = value;
3437
Level = level;
3538
}
39+
40+
private string DebuggerDisplay
41+
{
42+
get { return string.Format("{0} = \"{1}\"", Key, Value); }
43+
}
3644
}
3745
}

LibGit2Sharp/GitObject.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Globalization;
34
using LibGit2Sharp.Core;
45

@@ -7,6 +8,7 @@ namespace LibGit2Sharp
78
/// <summary>
89
/// A GitObject
910
/// </summary>
11+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1012
public abstract class GitObject : IEquatable<GitObject>
1113
{
1214
internal static GitObjectTypeMap TypeToTypeMap =
@@ -124,5 +126,10 @@ public override int GetHashCode()
124126
{
125127
return !Equals(left, right);
126128
}
129+
130+
private string DebuggerDisplay
131+
{
132+
get { return Id.ToString(7); }
133+
}
127134
}
128135
}

LibGit2Sharp/Index.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Diagnostics;
45
using System.Globalization;
56
using System.IO;
67
using System.Runtime.InteropServices;
@@ -14,6 +15,7 @@ namespace LibGit2Sharp
1415
/// The Index is a staging area between the Working directory and the Repository.
1516
/// It's used to prepare and aggregate the changes that will be part of the next commit.
1617
/// </summary>
18+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1719
public class Index : IEnumerable<IndexEntry>
1820
{
1921
private readonly IndexSafeHandle handle;
@@ -499,5 +501,10 @@ private void ReplaceIndexEntryWith(TreeEntryChanges treeEntryChanges)
499501
Proxy.git_index_add(handle, indexEntry);
500502
Marshal.FreeHGlobal(indexEntry.Path);
501503
}
504+
505+
private string DebuggerDisplay
506+
{
507+
get { return string.Format("Count = {0}", Count); }
508+
}
502509
}
503510
}

LibGit2Sharp/IndexEntry.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using LibGit2Sharp.Core;
34
using LibGit2Sharp.Core.Handles;
45

@@ -7,6 +8,7 @@ namespace LibGit2Sharp
78
/// <summary>
89
/// A reference to a <see cref = "Blob" /> known by the <see cref = "Index" />.
910
/// </summary>
11+
[DebuggerDisplayAttribute("{DebuggerDisplay,nq}")]
1012
public class IndexEntry : IEquatable<IndexEntry>
1113
{
1214
private static readonly LambdaEqualityHelper<IndexEntry> equalityHelper =
@@ -108,5 +110,10 @@ public override int GetHashCode()
108110
{
109111
return !Equals(left, right);
110112
}
113+
114+
private string DebuggerDisplay
115+
{
116+
get { return string.Format("{0} => \"{1}\"", Path, Id.ToString(7)); }
117+
}
111118
}
112119
}

LibGit2Sharp/Note.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using LibGit2Sharp.Core;
34
using LibGit2Sharp.Core.Handles;
45

@@ -7,6 +8,7 @@ namespace LibGit2Sharp
78
/// <summary>
89
/// A note, attached to a given <see cref = "GitObject"/>.
910
/// </summary>
11+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1012
public class Note : IEquatable<Note>
1113
{
1214
/// <summary>
@@ -105,5 +107,14 @@ public override int GetHashCode()
105107
{
106108
return !Equals(left, right);
107109
}
110+
111+
private string DebuggerDisplay
112+
{
113+
get
114+
{
115+
return string.Format("Target \"{0}\", Namespace \"{1}\": {2}",
116+
TargetObjectId.ToString(7), Namespace, Message);
117+
}
118+
}
108119
}
109120
}

LibGit2Sharp/NoteCollection.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Diagnostics;
45
using System.Linq;
56
using LibGit2Sharp.Core;
67
using LibGit2Sharp.Core.Compat;
@@ -11,6 +12,7 @@ namespace LibGit2Sharp
1112
/// <summary>
1213
/// A collection of <see cref = "Note"/> exposed in the <see cref = "Repository"/>.
1314
/// </summary>
15+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1416
public class NoteCollection : IEnumerable<Note>
1517
{
1618
private readonly Repository repo;
@@ -226,5 +228,10 @@ public virtual void Delete(ObjectId targetId, Signature author, Signature commit
226228
{
227229
Remove(targetId, author, committer, @namespace);
228230
}
231+
232+
private string DebuggerDisplay
233+
{
234+
get { return string.Format("Count = {0}", this.Count()); }
235+
}
229236
}
230237
}

LibGit2Sharp/Reference.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Globalization;
34
using LibGit2Sharp.Core;
45
using LibGit2Sharp.Core.Compat;
@@ -9,6 +10,7 @@ namespace LibGit2Sharp
910
/// <summary>
1011
/// A Reference to another git object
1112
/// </summary>
13+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1214
public abstract class Reference : IEquatable<Reference>
1315
{
1416
private static readonly LambdaEqualityHelper<Reference> equalityHelper =
@@ -133,5 +135,10 @@ public override string ToString()
133135
{
134136
return CanonicalName;
135137
}
138+
139+
private string DebuggerDisplay
140+
{
141+
get { return string.Format("{0} => \"{1}\"", CanonicalName, TargetIdentifier); }
142+
}
136143
}
137144
}

LibGit2Sharp/ReferenceCollection.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Diagnostics;
45
using System.Linq;
56
using LibGit2Sharp.Core;
67
using LibGit2Sharp.Core.Handles;
@@ -10,6 +11,7 @@ namespace LibGit2Sharp
1011
/// <summary>
1112
/// The Collection of references in a <see cref = "Repository" />
1213
/// </summary>
14+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1315
public class ReferenceCollection : IEnumerable<Reference>
1416
{
1517
internal readonly Repository repo;
@@ -257,5 +259,10 @@ public virtual bool IsValidName(string canonicalName)
257259
{
258260
return Proxy.git_reference_is_valid_name(canonicalName);
259261
}
262+
263+
private string DebuggerDisplay
264+
{
265+
get { return string.Format("Count = {0}", this.Count()); }
266+
}
260267
}
261268
}

LibGit2Sharp/ReferenceWrapper.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using LibGit2Sharp.Core;
34
using LibGit2Sharp.Core.Compat;
45

@@ -8,6 +9,7 @@ namespace LibGit2Sharp
89
/// A base class for things that wrap a <see cref = "Reference" /> (branch, tag, etc).
910
/// </summary>
1011
/// <typeparam name="TObject">The type of the referenced Git object.</typeparam>
12+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1113
public abstract class ReferenceWrapper<TObject> : IEquatable<ReferenceWrapper<TObject>> where TObject : GitObject
1214
{
1315
/// <summary>
@@ -148,5 +150,14 @@ public override int GetHashCode()
148150
{
149151
return !Equals(left, right);
150152
}
153+
154+
private string DebuggerDisplay
155+
{
156+
get
157+
{
158+
return string.Format("{0} => \"{1}\"", CanonicalName,
159+
(TargetObject != null) ? TargetObject.Id.ToString(7) : "?");
160+
}
161+
}
151162
}
152163
}

LibGit2Sharp/Remote.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using LibGit2Sharp.Core;
34
using LibGit2Sharp.Core.Handles;
45
using LibGit2Sharp.Handlers;
@@ -8,6 +9,7 @@ namespace LibGit2Sharp
89
/// <summary>
910
/// A remote repository whose branches are tracked.
1011
/// </summary>
12+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1113
public class Remote : IEquatable<Remote>
1214
{
1315
private static readonly LambdaEqualityHelper<Remote> equalityHelper =
@@ -146,5 +148,10 @@ public override int GetHashCode()
146148
{
147149
return !Equals(left, right);
148150
}
151+
152+
private string DebuggerDisplay
153+
{
154+
get { return string.Format("{0} => {1}", Name, Url); }
155+
}
149156
}
150157
}

0 commit comments

Comments
 (0)