Skip to content

Commit 391b8a2

Browse files
committed
add/improve tests
1 parent 428d65a commit 391b8a2

File tree

3 files changed

+132
-61
lines changed

3 files changed

+132
-61
lines changed

src/InheritDoc/InheritDocTask.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,38 @@ public class InheritDocTask : Task
2323
public string? NoWarn { get; set; }
2424
public string? TrimLevel { get; set; }
2525

26+
internal ILogger? Logger { get; set; }
27+
2628
public override bool Execute()
2729
{
2830
try
2931
{
30-
var refPaths = RefAssemblyPaths?.Split(';') ?? Array.Empty<string>();
31-
var addPaths = AdditionalDocPaths?.Split(';') ?? Array.Empty<string>();
32-
var logger = new TaskLogger(Log, NoWarn?.Split(';') ?? Array.Empty<string>()) as ILogger;
32+
var refPaths = RefAssemblyPaths?.Split(';') ?? [ ];
33+
var addPaths = AdditionalDocPaths?.Split(';') ?? [ ];
3334
var trim = (ApiLevel)Math.Min((int)(Enum.TryParse<ApiLevel>(TrimLevel, true, out var t) ? t : ApiLevel.Internal), (int)ApiLevel.Internal);
3435

35-
Log.LogCommandLine(MessageImportance.Normal,
36-
typeof(InheritDocTask).Assembly.GetName().FullName +
36+
string cmdargs = typeof(InheritDocTask).Assembly.GetName().FullName +
3737
Environment.NewLine + nameof(AssemblyPath) + ": " + AssemblyPath +
3838
Environment.NewLine + nameof(InDocPath) + ": " + InDocPath +
3939
Environment.NewLine + nameof(OutDocPath) + ": " + OutDocPath +
4040
Environment.NewLine + nameof(RefAssemblyPaths) + ": " + RefAssemblyPaths +
4141
Environment.NewLine + nameof(AdditionalDocPaths) + ": " + AdditionalDocPaths +
42-
Environment.NewLine + nameof(TrimLevel) + ": " + trim
43-
);
42+
Environment.NewLine + nameof(TrimLevel) + ": " + trim;
43+
44+
Logger ??= new TaskLogger(Log, NoWarn?.Split(';') ?? [ ]);
45+
if (BuildEngine is not null)
46+
Log.LogCommandLine(MessageImportance.Normal, cmdargs);
4447

45-
var (replaced, total, trimmed) = InheritDocProcessor.InheritDocs(AssemblyPath, InDocPath, OutDocPath, refPaths, addPaths, trim, logger);
48+
var (replaced, total, trimmed) = InheritDocProcessor.InheritDocs(AssemblyPath, InDocPath, OutDocPath, refPaths, addPaths, trim, Logger);
4649

47-
logger.Write(ILogger.Severity.Message, $"{nameof(InheritDocTask)} replaced {replaced} of {total} inheritdoc tags {(trim > ApiLevel.None ? $"and removed {trimmed} {(trim == ApiLevel.Private ? "private" : "non-public")} member docs " : null)}in {Path.GetFullPath(OutDocPath)}");
50+
Logger.Write(ILogger.Severity.Message, $"{nameof(InheritDocTask)} replaced {replaced} of {total} inheritdoc tags {(trim > ApiLevel.None ? $"and removed {trimmed} {(trim == ApiLevel.Private ? "private" : "non-public")} member docs " : null)}in {Path.GetFullPath(OutDocPath)}");
4851
return true;
4952
}
5053
catch (Exception ex)
5154
{
52-
Log.LogErrorFromException(ex, true);
55+
if (BuildEngine is not null)
56+
Log.LogErrorFromException(ex, true);
57+
5358
return false;
5459
}
5560
}

tests/InheritDoc.Test/DocTests.cs

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// <auto-generated /> (not really, but this disables analyzer warnings)
44

55
using System;
6+
using System.CodeDom.Compiler;
67
using System.Collections;
78
using System.Collections.Generic;
89
using System.Runtime.CompilerServices;
@@ -34,7 +35,7 @@ public interface IZ
3435
event EventHandler E;
3536
}
3637

37-
/// <summary>Interface IG</summary>
38+
/// <summary>Interface IG <typeparamref name="TG"/></summary>
3839
/// <typeparam name="TG">TypeParam TG</typeparam>
3940
public interface IG<TG>
4041
{
@@ -45,15 +46,16 @@ public interface IG<TG>
4546
unsafe U[] M<U>(U* p) where U : unmanaged;
4647

4748
/// <summary>Nested Interface IG&lt;TG&gt;.IN</summary>
49+
/// <typeparam name="TM">TypeParam TM</typeparam>
4850
public interface IN<TM>
4951
{
50-
/// <summary>Method M</summary>
52+
/// <summary>Method M <typeparamref name="TM" /></summary>
5153
/// <param name="p">Param p</param>
5254
public void M(IN<TM> p);
5355
}
5456
}
5557

56-
/// <summary>Class G</summary>
58+
/// <summary>Class G <typeparamref name="T"/></summary>
5759
/// <typeparam name="T">TypeParam T</typeparam>
5860
public abstract class G<T> where T : class
5961
{
@@ -157,66 +159,51 @@ public struct D : IEquatable<D>
157159
}
158160

159161
/// <inheritdoc />
160-
public class GGI : GG<string>
162+
public class GGI : GG<string[]>
161163
{
162164
new internal const string T_ID = nameof(GGI);
163-
internal const string M_ID = T_ID + "." + nameof(M) + "(" + nameof(System) + "." + nameof(String) + "@)";
165+
internal const string M_ID = T_ID + "." + nameof(M) + "(" + nameof(System) + "." + nameof(String) + "[]@)";
166+
internal const string P_ID = T_ID + ".Item(" + nameof(System) + "." + nameof(Int32) + ")";
164167

165168
/// <inheritdoc />
166169
public GGI() { }
167170

168171
/// <inheritdoc />
169-
public override string M(in string x) => default;
170-
}
171-
172-
/// <inheritdoc />
173-
public class GG<U> : G<U> where U : class
174-
{
175-
internal const string T_ID = nameof(GG<U>) + "`1";
176-
internal const string P_ID_this = T_ID + ".Item(" + nameof(System) + "." + nameof(Int32) + ")";
177-
178-
/// <summary>Constructor GG</summary>
179-
public GG() { }
172+
public override string[] M(in string[] x) => default;
180173

181174
/// <inheritdoc />
182-
public override U this[int i] => default;
175+
public override string[] this[int i] => default;
183176
}
184177

185178
/// <inheritdoc />
186-
public class GI : G<string>
179+
/// <typeparam name="V"><inheritdoc cref="IComparable{T}" path="/typeparam[@name='T']/node()" /></typeparam>
180+
#pragma warning disable 1712
181+
public class GX<V, U> : Lazy<U>, IEquatable<Lazy<U>>, IComparable<V>
182+
#pragma warning restore 1712
187183
{
188-
internal const string T_ID = nameof(GI);
189-
internal const string M_ID = T_ID + "." + nameof(M) + "(" + nameof(System) + "." + nameof(String) + "@)";
190-
191-
/// <inheritdoc />
192-
public override string M(in string s) => default;
193-
194-
/// <inheritdoc />
195-
public override string this[int i] => default;
196-
}
197-
198-
/// <inheritdoc />
199-
public class GX<U> : Lazy<U>, IEquatable<Lazy<U>>
200-
{
201-
internal const string T_ID = nameof(GX<U>) + "`1";
202-
internal const string M_ID_GetHashCode = T_ID + "." + nameof(GetHashCode);
203-
internal const string M_ID_Equals = T_ID + "." + nameof(Equals) + "(" + nameof(System) + "." + nameof(Lazy<U>) + "{`0})";
204-
205184
/// <inheritdoc />
206185
public override int GetHashCode() => default;
207186

208187
/// <inheritdoc />
209188
public bool Equals(Lazy<U> other) => default;
189+
190+
/// <inheritdoc />
191+
/// <param name="other"><typeparamref name="V"/></param>
192+
public int CompareTo(V other) => default;
210193
}
211194

212195
/// <inheritdoc />
213-
public class GXI : Lazy<string>, IEquatable<string>
196+
/// <typeparam name="T">TypeParam T</typeparam>
197+
public class GXI<T> : Lazy<string[]>, IEquatable<string>
214198
{
215-
internal const string T_ID = nameof(GXI);
216-
internal const string M_ID_Equals = T_ID + "." + nameof(Equals) + "(" + nameof(System) + "." + nameof(String) + ")";
199+
internal const string T_ID = nameof(GXI<T>) + "`1";
200+
internal const string M_ID_OpImplicit = T_ID + ".op_Implicit(" + nameof(GXI<T>) + "{`0})~" + nameof(System) + "." + nameof(String);
217201

218202
/// <inheritdoc />
219-
public bool Equals(string other) => default;
203+
public bool Equals(string o) => default;
204+
205+
/// <inheritdoc cref="Equals(string)" />
206+
public static implicit operator string(GXI<T> o) => default;
220207
}
221208

222209
/// <inheritdoc />
@@ -246,11 +233,26 @@ public class GIS<TT> : GG<TT>, IG<TT> where TT : class
246233
unsafe public virtual MT[] M<MT>(MT* mtp) where MT : unmanaged => default;
247234
}
248235

236+
/// <inheritdoc />
237+
public class GG<U> : G<U> where U : class
238+
{
239+
internal const string T_ID = nameof(GG<U>) + "`1";
240+
internal const string P_ID_this = T_ID + ".Item(" + nameof(System) + "." + nameof(Int32) + ")";
241+
242+
/// <summary>Constructor GG</summary>
243+
public GG() { }
244+
245+
/// <inheritdoc />
246+
public override U this[int i] => default;
247+
}
248+
249249
/// <inheritdoc />
250250
public class GII : IG<string>
251251
{
252252
internal const string T_ID = nameof(GII);
253-
internal const string M_ID = T_ID + "." + nameof(M) + "``1(``0*)";
253+
254+
/// <inheritdoc />
255+
private GII() { }
254256

255257
/// <inheritdoc />
256258
unsafe public T[] M<T>(T* tp) where T : unmanaged => default;
@@ -266,11 +268,32 @@ public class W
266268
/// <summary>Internal Field T_ID</summary>
267269
internal const string T_ID = nameof(W);
268270
internal const string F_ID = T_ID + "." + nameof(T_ID);
271+
internal const string M_ID_NotInherited = T_ID + "." + nameof(MNotInherited);
272+
internal const string P_ID_NotInherited = T_ID + "." + nameof(PNotInherited);
273+
274+
/// <inheritdoc />
275+
public void MNotInherited() { }
276+
277+
/// <inheritdoc />
278+
[GeneratedCode("SG", "1")]
279+
public int PNotInherited { get; set; }
280+
281+
/// <summary>M managed</summary>
282+
/// <param name="ptr">fnptr</param>
283+
public unsafe void M(delegate*<void> ptr) { }
269284

270285
/// <inheritdoc />
271-
public void NotInherited() { }
286+
public override string ToString() => default;
272287
}
273288

289+
/// <inheritdoc cref="GIG{TT}" />
290+
/// <typeparam name="U">U</typeparam>
291+
public class GB<U> : B { }
292+
293+
/// <inheritdoc />
294+
[CompilerGenerated]
295+
public interface IG { }
296+
274297
//
275298
// Tricky Generic Case
276299
//
@@ -305,6 +328,7 @@ void ICollection<KeyValuePair<string, string>>.CopyTo(KeyValuePair<string, strin
305328
// Internal Type
306329
//
307330

331+
/// <inheritdoc />
308332
internal class ImplementsICollection : ICollection<string>
309333
{
310334
internal const string T_ID = nameof(ImplementsICollection);

tests/InheritDoc.Test/InheritDocTests.cs

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Xml.Linq;
99
using System.Xml.XPath;
1010
using System.Diagnostics;
11+
using System.Collections.Generic;
1112

1213
using Microsoft.VisualStudio.TestTools.UnitTesting;
1314

@@ -23,6 +24,7 @@ public class InheritDocTests
2324
static readonly string assemblyPath = typeof(InheritDocTests).Assembly.Location;
2425
static readonly string documentPath = Path.Combine(Path.GetDirectoryName(assemblyPath), Path.GetFileNameWithoutExtension(assemblyPath) + ".xml");
2526
static readonly string[] referencePaths = new[] { Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), corlibPath.Replace('\\', Path.DirectorySeparatorChar)), typeof(InheritDocProcessor).Assembly.Location };
27+
static readonly DebugLogger logger = new();
2628

2729
static XElement processedDocs;
2830
static XElement processedDocsPrivateTrim;
@@ -33,15 +35,14 @@ public static void InheritDocProcess(TestContext _)
3335
string outPath = documentPath + ".after";
3436
string outPathPrivateTrim = documentPath + ".privateTrim.after";
3537

36-
var log = new DebugLogger() as ILogger;
37-
var (replaced, total, trimmed) = InheritDocProcessor.InheritDocs(assemblyPath, documentPath, outPath, referencePaths, [ ], ApiLevel.Internal, log);
38-
log.Write(ILogger.Severity.Message, $"replaced {replaced} of {total} and removed {trimmed}");
38+
var (replaced, total, trimmed) = InheritDocProcessor.InheritDocs(assemblyPath, documentPath, outPath, referencePaths, [ ], ApiLevel.Internal, logger);
39+
logger.Write(ILogger.Severity.Message, $"replaced {replaced} of {total} and removed {trimmed}");
3940

4041
using var stmdoc = File.Open(outPath, FileMode.Open);
4142
processedDocs = XDocument.Load(stmdoc, LoadOptions.PreserveWhitespace).Root.Element("members");
4243

43-
(replaced, total, trimmed) = InheritDocProcessor.InheritDocs(assemblyPath, documentPath, outPathPrivateTrim, referencePaths, [ ], ApiLevel.Private, log);
44-
log.Write(ILogger.Severity.Message, $"replaced {replaced} of {total} and removed {trimmed}");
44+
var task = new InheritDocTask { AssemblyPath = assemblyPath, InDocPath = documentPath, OutDocPath = outPathPrivateTrim, RefAssemblyPaths = string.Join(";", referencePaths), TrimLevel = ApiLevel.Private.ToString(), Logger = logger };
45+
task.Execute();
4546

4647
using var stmdocPrivateTrim = File.Open(outPathPrivateTrim, FileMode.Open);
4748
processedDocsPrivateTrim = XDocument.Load(stmdocPrivateTrim, LoadOptions.PreserveWhitespace).Root.Element("members");
@@ -100,7 +101,7 @@ public void ConstructorInherits()
100101
public void NestedGenericParamsAssigned()
101102
{
102103
var ele = getDocElement("M:" + GIG<string>.M_ID_MImplicit, "summary");
103-
Assert.AreEqual("Method M", ele?.Value);
104+
Assert.AreEqual("Method M ", ele?.Value);
104105
}
105106

106107
[TestMethod]
@@ -125,12 +126,33 @@ public void CrefOverridesDefaultBase()
125126
}
126127

127128
[TestMethod]
128-
public void TypeParamRefRemapped()
129+
public void MethodTypeParamRefRemapped()
129130
{
130131
var ele = getDocElement("M:" + GIG<string>.M_ID_MExplicit, "returns/typeparamref[@name='MT']");
131132
Assert.IsNotNull(ele);
132133
}
133134

135+
[TestMethod]
136+
public void MethodTypeParamRefRemappedFromClass()
137+
{
138+
var ele = getDocElement("M:" + GIG<string>.M_ID_MImplicit, "summary/typeparamref[@name='TT']");
139+
Assert.IsNotNull(ele);
140+
}
141+
142+
[TestMethod]
143+
public void ClosedTypeParamRefReplaced()
144+
{
145+
var ele = getDocElement("P:" + GGI.P_ID, "value/see[@cref='T:System.String[]']");
146+
Assert.IsNotNull(ele);
147+
}
148+
149+
[TestMethod]
150+
public void UnusedTypeParamsTrimmed()
151+
{
152+
var ele = getDocElement("T:" + D.T_ID, ".");
153+
Assert.AreEqual(0, ele?.Elements("typeparam").Count() ?? 0);
154+
}
155+
134156
[TestMethod]
135157
public void UnusedParamsTrimmed()
136158
{
@@ -183,7 +205,7 @@ public void StructInheritsFromRefDocs()
183205
[TestMethod]
184206
public void ClassInheritsFromRefDocs()
185207
{
186-
var ele = getDocElement("T:" + GXI.T_ID, "summary");
208+
var ele = getDocElement("T:" + GXI<string>.T_ID, "summary");
187209
Assert.AreEqual("Provides support for lazy initialization.", ele?.Value);
188210
}
189211

@@ -297,6 +319,20 @@ public void InternalClassImplementsInterfaceImplicitPrivateTrim()
297319
Assert.IsNotNull(ele);
298320
}
299321

322+
[TestMethod]
323+
public void NoBaseWarning()
324+
{
325+
bool warn = logger.Warnings.Any(w => w.code == ErrorCodes.NoBase && w.msg.Contains("M:" + W.M_ID_NotInherited));
326+
Assert.IsTrue(warn);
327+
}
328+
329+
[TestMethod]
330+
public void NoBaseWarningIgnoredForGenerated()
331+
{
332+
bool warn = logger.Warnings.Any(w => w.code == ErrorCodes.NoBase && w.msg.Contains("P:" + W.P_ID_NotInherited));
333+
Assert.IsFalse(warn);
334+
}
335+
300336
private static XElement? getDocElement(string docID, string xpath) =>
301337
processedDocs.Elements("member").FirstOrDefault(m => (string)m.Attribute("name") == docID)?.XPathSelectElement(xpath);
302338

@@ -305,12 +341,18 @@ public void InternalClassImplementsInterfaceImplicitPrivateTrim()
305341

306342
private class DebugLogger : ILogger
307343
{
308-
void ILogger.Write(ILogger.Severity severity, string msg)
344+
public readonly List<(string code, string msg)> Warnings = [ ];
345+
346+
public void Write(ILogger.Severity severity, string msg)
309347
{
310348
if (severity >= ILogger.Severity.Info)
311349
Debug.WriteLine(msg);
312350
}
313351

314-
void ILogger.Warn(string code, string file, int line, int column, string msg) => Debug.WriteLine(code + ": " + msg);
352+
public void Warn(string code, string file, int line, int column, string msg)
353+
{
354+
Warnings.Add((code, msg));
355+
Debug.WriteLine(code + ": " + msg);
356+
}
315357
}
316358
}

0 commit comments

Comments
 (0)