From 9566fe062793b13e0c53e33622ebbb4c019a1d42 Mon Sep 17 00:00:00 2001 From: carlossanlop Date: Fri, 9 Sep 2022 16:17:24 -0700 Subject: [PATCH] Fix inheritdoc bugs for full or partial inheritance: - Avoid escaping crefs except when printing to log. - Make sure params and typeparams are also ported when inheriting from base type or interface. - Add tests. --- src/PortToDocs/src/libraries/Docs/DocsAPI.cs | 10 +- .../src/libraries/Docs/DocsException.cs | 2 +- .../IntelliSenseXml/IntelliSenseXmlMember.cs | 4 +- src/PortToDocs/src/libraries/ToDocsPorter.cs | 120 ++- .../tests/PortToDocs.Strings.Tests.cs | 889 +++++++++++++----- 5 files changed, 749 insertions(+), 276 deletions(-) diff --git a/src/PortToDocs/src/libraries/Docs/DocsAPI.cs b/src/PortToDocs/src/libraries/Docs/DocsAPI.cs index 2944a6e..bca763d 100644 --- a/src/PortToDocs/src/libraries/Docs/DocsAPI.cs +++ b/src/PortToDocs/src/libraries/Docs/DocsAPI.cs @@ -37,7 +37,7 @@ internal abstract class DocsAPI : IDocsAPI public abstract bool Changed { get; set; } public string FilePath { get; set; } = string.Empty; - public string DocId => _docId ??= GetApiSignatureDocId().AsEscapedDocId(); + public string DocId => _docId ??= GetApiSignatureDocId(); public string DocIdUnprefixed => _docIdUnprefixed ??= DocId[2..]; @@ -148,7 +148,7 @@ public List SeeAlsoCrefs { if (Docs != null) { - _seeAlsoCrefs = Docs.Elements("seealso").Select(x => XmlHelper.GetAttributeValue(x, "cref").AsEscapedDocId()).ToList(); + _seeAlsoCrefs = Docs.Elements("seealso").Select(x => XmlHelper.GetAttributeValue(x, "cref")).ToList(); } else { @@ -167,7 +167,7 @@ public List AltMembers { if (Docs != null) { - _altMemberCrefs = Docs.Elements("altmember").Select(x => XmlHelper.GetAttributeValue(x, "cref").AsEscapedDocId()).ToList(); + _altMemberCrefs = Docs.Elements("altmember").Select(x => XmlHelper.GetAttributeValue(x, "cref")).ToList(); } else { @@ -221,7 +221,7 @@ public string InheritDocCref XAttribute? xInheritDocCref = XInheritDoc.Attribute("cref"); if (xInheritDocCref != null) { - _inheritDocCref = xInheritDocCref.Value.AsEscapedDocId(); + _inheritDocCref = xInheritDocCref.Value; } } } @@ -238,7 +238,7 @@ public string InheritDocCref // Non-null to add else { - _inheritDocCref = value.AsEscapedDocId(); // Can be empty string too + _inheritDocCref = value; // Can be empty string too if (XInheritDoc == null) // Not found in Docs { XInheritDoc = new XElement("inheritdoc"); diff --git a/src/PortToDocs/src/libraries/Docs/DocsException.cs b/src/PortToDocs/src/libraries/Docs/DocsException.cs index 95e9fbc..7b0162b 100644 --- a/src/PortToDocs/src/libraries/Docs/DocsException.cs +++ b/src/PortToDocs/src/libraries/Docs/DocsException.cs @@ -16,7 +16,7 @@ public IDocsAPI ParentAPI get; private set; } - public string Cref => XmlHelper.GetAttributeValue(XEException, "cref").AsEscapedDocId(); + public string Cref => XmlHelper.GetAttributeValue(XEException, "cref"); public string Value { diff --git a/src/PortToDocs/src/libraries/IntelliSenseXml/IntelliSenseXmlMember.cs b/src/PortToDocs/src/libraries/IntelliSenseXml/IntelliSenseXmlMember.cs index 4c545c6..b3194c3 100644 --- a/src/PortToDocs/src/libraries/IntelliSenseXml/IntelliSenseXmlMember.cs +++ b/src/PortToDocs/src/libraries/IntelliSenseXml/IntelliSenseXmlMember.cs @@ -30,7 +30,7 @@ public string InheritDocCref XAttribute? xInheritDocCref = XInheritDoc.Attribute("cref"); if (xInheritDocCref != null) { - _inheritDocCref = xInheritDocCref.Value.AsEscapedDocId(); + _inheritDocCref = xInheritDocCref.Value; } } } @@ -66,7 +66,7 @@ public string Namespace /// /// The API DocId. /// - public string Name => _name ??= XmlHelper.GetAttributeValue(XEMember, "name").AsEscapedDocId(); + public string Name => _name ??= XmlHelper.GetAttributeValue(XEMember, "name"); private List? _params; public List Params diff --git a/src/PortToDocs/src/libraries/ToDocsPorter.cs b/src/PortToDocs/src/libraries/ToDocsPorter.cs index e46451c..c91df7b 100644 --- a/src/PortToDocs/src/libraries/ToDocsPorter.cs +++ b/src/PortToDocs/src/libraries/ToDocsPorter.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.SymbolStore; using System.IO; using System.Linq; using System.Text; @@ -212,6 +213,18 @@ private void PortMissingCommentsForType(DocsType dTypeToUpdate) Remarks = tsActualTypeToPort.Remarks }; + // delegates + foreach (IntelliSenseXmlParam tsParam in tsTypeToPort.Params) + { + mc.Params.Add(tsParam.Name, tsParam.Value); + } + + // type typeparams + foreach (IntelliSenseXmlTypeParam tsTypeParam in tsTypeToPort.TypeParams) + { + mc.TypeParams.Add(tsTypeParam.Name, tsTypeParam.Value); + } + // Rare case where the base type or interface docs should be used if (tsTypeToPort.InheritDoc) { @@ -258,6 +271,16 @@ private void PortMissingCommentsForMember(DocsMember dMemberToUpdate) mc.Property = GetPropertyValue(tsMemberToPort.Value, tsMemberToPort.Returns); } + foreach (IntelliSenseXmlParam tsParam in tsMemberToPort.Params) + { + mc.Params.Add(tsParam.Name, tsParam.Value); + } + + foreach (IntelliSenseXmlTypeParam tsTypeParam in tsMemberToPort.TypeParams) + { + mc.TypeParams.Add(tsTypeParam.Name, tsTypeParam.Value); + } + // Rare case where the base type or interface docs should be used, // but only for elements that aren't explicitly documented in the actual API if (tsMemberToPort.InheritDoc) @@ -313,7 +336,18 @@ private void GetMissingCommentsForTypeFromInheritDoc(MissingComments mc, DocsTyp mc.Summary = tsInheritedMember.Summary; mc.Returns = tsInheritedMember.Returns; mc.Remarks = tsInheritedMember.Remarks; - + + // delegates + foreach (IntelliSenseXmlParam tsParam in tsInheritedMember.Params) + { + mc.Params.Add(tsParam.Name, tsParam.Value); + } + + // type typeparams + foreach (IntelliSenseXmlTypeParam tsTypeParam in tsInheritedMember.TypeParams) + { + mc.TypeParams.Add(tsTypeParam.Name, tsTypeParam.Value); + } } // Look for the base type from which this one inherits else if (DocsComments.Types.TryGetValue($"T:{dTypeToUpdate.BaseTypeName}", out DocsType? dBaseType) && @@ -329,6 +363,18 @@ private void GetMissingCommentsForTypeFromInheritDoc(MissingComments mc, DocsTyp mc.Summary = dBaseType.Summary; mc.Returns = dBaseType.Returns; mc.Remarks = dBaseType.Remarks; + + // delegates + foreach (DocsParam tsParam in dBaseType.Params) + { + mc.Params.Add(tsParam.Name, tsParam.Value); + } + + // type typeparams + foreach (DocsTypeParam tsTypeParam in dBaseType.TypeParams) + { + mc.TypeParams.Add(tsTypeParam.Name, tsTypeParam.Value); + } } } @@ -358,6 +404,22 @@ private void GetMissingCommentsForMemberFromInheritDoc(MissingComments mc, DocsM { mc.Property = GetPropertyValue(tsInheritedMember.Value, tsInheritedMember.Returns); } + + foreach (IntelliSenseXmlParam tsParam in tsInheritedMember.Params) + { + if (!mc.Params.TryAdd(tsParam.Name, tsParam.Value)) + { + mc.Params[tsParam.Name] = tsParam.Value; + } + } + + foreach (IntelliSenseXmlTypeParam tsTypeParam in tsInheritedMember.TypeParams) + { + if (!mc.TypeParams.TryAdd(tsTypeParam.Name, tsTypeParam.Value)) + { + mc.TypeParams[tsTypeParam.Name] = tsTypeParam.Value; + } + } } // Look for the base type and find the member from which this one inherits else if (DocsComments.Types.TryGetValue($"T:{dMemberToUpdate.ParentType.BaseTypeName}", out DocsType? dBaseType) && @@ -397,6 +459,22 @@ private void GetMissingCommentsForMemberFromInheritDoc(MissingComments mc, DocsM { mc.Property = GetPropertyValue(dBaseMember.Value, dBaseMember.Returns); } + + foreach (DocsParam baseParam in dBaseMember.Params) + { + if (!mc.Params.TryAdd(baseParam.Name, baseParam.Value)) + { + mc.Params[baseParam.Name] = baseParam.Value; + } + } + + foreach (DocsTypeParam baseTypeParam in dBaseMember.TypeParams) + { + if (!mc.TypeParams.TryAdd(baseTypeParam.Name, baseTypeParam.Value)) + { + mc.TypeParams[baseTypeParam.Name] = baseTypeParam.Value; + } + } } } } @@ -413,13 +491,29 @@ private MissingComments GetMissingCommentsForMemberFromInterface(MissingComments mc.Property = GetPropertyValue(dInterfacedMember.Value, dInterfacedMember.Returns); } + foreach (DocsParam interfaceParam in dInterfacedMember.Params) + { + if (!mc.Params.TryAdd(interfaceParam.Name, interfaceParam.Value)) + { + mc.Params[interfaceParam.Name] = interfaceParam.Value; + } + } + + foreach (DocsTypeParam interfaceTypeParam in dInterfacedMember.TypeParams) + { + if (!mc.TypeParams.TryAdd(interfaceTypeParam.Name, interfaceTypeParam.Value)) + { + mc.TypeParams[interfaceTypeParam.Name] = interfaceTypeParam.Value; + } + } + if (!dInterfacedMember.Remarks.IsDocsEmpty()) { // Only attempt to port if the member name is the same as the interfaced member docid without prefix - if (dMemberToUpdate.MemberName == dInterfacedMember.DocId[2..]) + if (dMemberToUpdate.MemberName == dInterfacedMember.DocIdUnprefixed) { - string dMemberToUpdateTypeDocIdNoPrefix = dMemberToUpdate.ParentType.DocId[2..]; - string interfacedMemberTypeDocIdNoPrefix = dInterfacedMember.ParentType.DocId[2..]; + string dMemberToUpdateTypeDocIdNoPrefix = dMemberToUpdate.ParentType.DocIdUnprefixed; + string interfacedMemberTypeDocIdNoPrefix = dInterfacedMember.ParentType.DocIdUnprefixed; // Special text for EIIs in Remarks string eiiMessage = $"This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface."; @@ -840,7 +934,7 @@ private void TryPortMissingExceptionsForMember(DocsMember dMemberToUpdate, Intel // First time adding the cref if (dException == null && Config.PortExceptionsNew) { - AddedExceptions.Add($"Exception=[{tsException.Cref}] in Member=[{dMemberToUpdate.DocId}]"); + AddedExceptions.Add($"Exception=[{tsException.Cref.AsEscapedDocId()}] in Member=[{dMemberToUpdate.DocId}]"); string text = XmlHelper.ReplaceExceptionPatterns(XmlHelper.GetNodesInPlainText(tsException.XEException)); dException = dMemberToUpdate.AddException(tsException.Cref, text); created = true; @@ -852,7 +946,7 @@ private void TryPortMissingExceptionsForMember(DocsMember dMemberToUpdate, Intel string value = XmlHelper.ReplaceExceptionPatterns(XmlHelper.GetNodesInPlainText(formattedException)); if (!dException.WordCountCollidesAboveThreshold(value, Config.ExceptionCollisionThreshold)) { - AddedExceptions.Add($"Exception=[{tsException.Cref}] in Member=[{dMemberToUpdate.DocId}]"); + AddedExceptions.Add($"Exception=[{tsException.Cref.AsEscapedDocId()}] in Member=[{dMemberToUpdate.DocId}]"); dException.AppendException(value); created = true; } @@ -886,7 +980,7 @@ private bool TryPromptParam(DocsParam oldDParam, IntelliSenseXmlMember tsMember, int option = -1; while (option == -1) { - Log.Error($"Problem in param '{oldDParam.Name}' in member '{tsMember.Name}' in file '{oldDParam.ParentAPI.FilePath}'"); + Log.Error($"Problem in param '{oldDParam.Name}' in member '{tsMember.Name.AsEscapedDocId()}' in file '{oldDParam.ParentAPI.FilePath}'"); Log.Error($"The param probably exists in code, but the exact name was not found in Docs. What would you like to do?"); Log.Warning(" 0 - Exit program."); Log.Info(" 1 - Select the correct IntelliSense xml param from the existing ones."); @@ -915,7 +1009,7 @@ private bool TryPromptParam(DocsParam oldDParam, IntelliSenseXmlMember tsMember, int paramSelection = -1; while (paramSelection == -1) { - Log.Info($"IntelliSense xml params found in member '{tsMember.Name}':"); + Log.Info($"IntelliSense xml params found in member '{tsMember.Name.AsEscapedDocId()}':"); Log.Warning(" 0 - Exit program."); Log.Info(" 1 - Ignore this param and continue."); int paramCounter = 2; @@ -991,7 +1085,7 @@ private bool TryPromptTypeParam(DocsTypeParam oldDTypeParam, IntelliSenseXmlMemb int option = -1; while (option == -1) { - Log.Error($"Problem in typeparam '{oldDTypeParam.Name}' in member '{tsMember.Name}' in file '{oldDTypeParam.ParentAPI.FilePath}'"); + Log.Error($"Problem in typeparam '{oldDTypeParam.Name}' in member '{tsMember.Name.AsEscapedDocId()}' in file '{oldDTypeParam.ParentAPI.FilePath}'"); Log.Error($"The typeparam probably exists in code, but the exact name was not found in Docs. What would you like to do?"); Log.Warning(" 0 - Exit program."); Log.Info(" 1 - Select the correct IntelliSense xml typeparam from the existing ones."); @@ -1020,7 +1114,7 @@ private bool TryPromptTypeParam(DocsTypeParam oldDTypeParam, IntelliSenseXmlMemb int typeParamSelection = -1; while (typeParamSelection == -1) { - Log.Info($"IntelliSense xml typeparams found in member '{tsMember.Name}':"); + Log.Info($"IntelliSense xml typeparams found in member '{tsMember.Name.AsEscapedDocId()}':"); Log.Warning(" 0 - Exit program."); Log.Info(" 1 - Ignore this typeparam and continue."); int typeParamCounter = 2; @@ -1216,7 +1310,7 @@ void TryPrintMember(ref bool undocMember, string memberDocId) { TryPrintMember(ref undocMember, member.DocId); - Log.Error($" Member Exception: {exception.Cref}: {exception.Value}"); + Log.Error($" Member Exception: {exception.Cref.AsEscapedDocId()}: {exception.Value}"); exceptions++; } } @@ -1240,6 +1334,8 @@ private class MissingComments internal string Returns { get; set; } internal string Remarks { get; set; } internal string Property { get; set; } + internal Dictionary Params { get; } + internal Dictionary TypeParams { get; } internal bool IsEII { get; set; } internal MissingComments() @@ -1248,6 +1344,8 @@ internal MissingComments() Returns = Configuration.ToBeAdded; Remarks = Configuration.ToBeAdded; Property = Configuration.ToBeAdded; + Params = new Dictionary(); + TypeParams = new Dictionary(); } } } diff --git a/src/PortToDocs/tests/PortToDocs.Strings.Tests.cs b/src/PortToDocs/tests/PortToDocs.Strings.Tests.cs index 575ab50..e8fbb6c 100644 --- a/src/PortToDocs/tests/PortToDocs.Strings.Tests.cs +++ b/src/PortToDocs/tests/PortToDocs.Strings.Tests.cs @@ -1020,60 +1020,64 @@ public void XmlRemarks() } [Fact] - public void FullInheritDoc() + public void FullInheritDoc_WithBaseType() { - string intellisenseParentType = @" - - - System - - - - This is the summary of the MyParentType class. - These are the remarks of the MyParentType class. - - - This is the summary of the MyParentType.MyMethod method. - These are the remarks of the MyParentType.MyMethod method. - - -"; + // If a type inherits from a base type (not an interface), and the API member in the intellisense xml contains + // the inheritdoc tag, and the API member is not documented in the intellisense xml, then the inheritdoc tag + // is ported to docs, and none of the items get filled out (they stay as 'To be added.'). This is because + // MS Docs is capable of showing the inherited docs automatically, we don't have to port them. - string intellisenseChildType = @" + string intellisenseFile = @" MyAssembly + + The summary of the MyParentType type. + The remarks of the MyParentType type. + + + The summary of MyParentType.MyMethod. + The remarks of MyParentType.MyMethod. + + + The summary of MyParentType.MyMethod`1. + The MyParentType.MyMethod`1 param description. + The MyParentType.MyMethod`1 typeparam description. + The remarks of MyParentType.Method`1. + - + + + + + + + + "; - string originalBaseType = @" - + string originalBaseType = @" + - System + MyAssembly - - System.MyParentType - - To be added. To be added. - + Method - - System + MyAssembly System.Void @@ -1084,37 +1088,76 @@ public void FullInheritDoc() To be added. + + + Method + + MyAssembly + + + System.Void + + + + + + + + + To be added. + To be added. + To be added. + To be added. + + "; - string expectedBaseType = @" - + string expectedBaseType = @" + - System + MyAssembly - - System.MyParentType - - - This is the summary of the MyParentType class. - These are the remarks of the MyParentType class. + The summary of the MyParentType type. + The remarks of the MyParentType type. - + Method - - System + MyAssembly System.Void - This is the summary of the MyParentType.MyMethod method. - These are the remarks of the MyParentType.MyMethod method. + The summary of MyParentType.MyMethod. + The remarks of MyParentType.MyMethod. + + + + + Method + + MyAssembly + + + System.Void + + + + + + + + + The MyParentType.MyMethod`1 param description. + The MyParentType.MyMethod`1 typeparam description. + The summary of MyParentType.MyMethod`1. + The remarks of MyParentType.Method`1. @@ -1126,7 +1169,7 @@ public void FullInheritDoc() MyAssembly - System.MyParentType + MyNamespace.MyParentType @@ -1137,7 +1180,6 @@ public void FullInheritDoc() Method - MyAssembly @@ -1150,6 +1192,28 @@ public void FullInheritDoc() To be added. + + + Method + + MyAssembly + + + System.Void + + + + + + + + + To be added. + To be added. + To be added. + To be added. + + "; @@ -1159,7 +1223,7 @@ public void FullInheritDoc() MyAssembly - System.MyParentType + MyNamespace.MyParentType @@ -1171,7 +1235,6 @@ public void FullInheritDoc() Method - MyAssembly @@ -1182,18 +1245,35 @@ public void FullInheritDoc() To be added. To be added. - + + + + + + Method + + MyAssembly + + + System.Void + + + + + + + + + To be added. + To be added. + To be added. + To be added. + "; - List intellisenseFiles = new() - { - intellisenseParentType, - intellisenseChildType - }; - List docFiles = new() { new StringTestData(originalBaseType, expectedBaseType), @@ -1203,55 +1283,53 @@ public void FullInheritDoc() Configuration configuration = new(); configuration.PreserveInheritDocTag = true; configuration.IncludedAssemblies.Add("MyAssembly"); - configuration.IncludedAssemblies.Add("System"); - TestWithStrings(intellisenseFiles, docFiles, configuration); + TestWithStrings(intellisenseFile, docFiles, configuration); } [Fact] - public void PartialInheritDoc() + public void FullInheritDoc_WithInterface() { - // The tag can be used to inherit documentation without having to port it. - // The exception to the rule are any items with explicit intellisense, which will always be ported. + // Same as the full inheritdoc base type test, but the logic to retrieve the interface + // info is different than the way we retrieve the base type, so we need a separate test. - string intellisense = @" + string intellisenseFile = @" MyAssembly - The IMyInterface summary. - The IMyInterface remarks. + This is the summary of the IMyInterface type. + These are the remarks of the IMyInterface type. - - The IMyInterface.MyMethod summary. - The IMyInterface.MyMethod remarks. - The IMyInterface.MyMethod myParam1 description. - The IMyInterface.MyMethod myParam2 description. + + This is the summary of the IMyInterface.MyMethod method. + These are the remarks of the IMyInterface.MyMethod method. - - The IMyInterface.MyField summary. - The IMyInterface.MyField remarks. + + The summary of IMyInterface.MyMethod`1. + The IMyInterface.MyMethod`1 param description. + The IMyInterface.MyMethod`1 typeparam description. + The remarks of IMyInterface.Method`1. - - - The MyType.MyMethod myParam2 description. - The MyType.MyMethod summary. - + + - + - The MyType.MyField remarks. - + + + + "; - string interfaceOriginalDocs = @" + string originalInterface = @" MyAssembly @@ -1262,7 +1340,7 @@ public void PartialInheritDoc() - + Method MyAssembly @@ -1270,28 +1348,30 @@ public void PartialInheritDoc() System.Void - - - - + - To be added. - To be added. To be added. To be added. - - - Field + + + Method MyAssembly - System.Int32 + System.Void - 1 + + + + + + + To be added. + To be added. To be added. To be added. @@ -1299,18 +1379,33 @@ public void PartialInheritDoc() "; - string interfaceExpectedDocs = @" + string expectedInterface = @" MyAssembly - The IMyInterface summary. - The IMyInterface remarks. + This is the summary of the IMyInterface type. + These are the remarks of the IMyInterface type. - + + Method + + MyAssembly + + + System.Void + + + + This is the summary of the IMyInterface.MyMethod method. + These are the remarks of the IMyInterface.MyMethod method. + + + + Method MyAssembly @@ -1319,35 +1414,83 @@ public void PartialInheritDoc() System.Void - - + + + + - The IMyInterface.MyMethod myParam1 description. - The IMyInterface.MyMethod myParam2 description. - The IMyInterface.MyMethod summary. - The IMyInterface.MyMethod remarks. + The IMyInterface.MyMethod`1 param description. + The IMyInterface.MyMethod`1 typeparam description. + The summary of IMyInterface.MyMethod`1. + The remarks of IMyInterface.Method`1. - - - Field + +"; + + string originalChildType = @" + + + MyAssembly + + + + MyNamespace.IMyInterface + + + + To be added. + To be added. + + + + + Method + + MyAssembly + + + M:MyNamespace.IMyInterface.MyMethod + + + MyNamespace.Void + + + + To be added. + To be added. + + + + + Method MyAssembly + + M:MyNamespace.IMyInterface.MyMethod`1(System.Memory{System.Byte}) + - System.Int32 + System.Void - 1 + + + + + + - The IMyInterface.MyField summary. - The IMyInterface.MyField remarks. + To be added. + To be added. + To be added. + To be added. "; - string originalDocs = @" + string expectedChildType = @" MyAssembly @@ -1360,71 +1503,247 @@ public void PartialInheritDoc() To be added. To be added. + - + Method + + MyAssembly + - M:MyNamespace.MyInterface.MyMethod(System.String,System.Int32) + M:MyNamespace.IMyInterface.MyMethod + + MyNamespace.Void + + + + To be added. + To be added. + + + + + + Method MyAssembly + + M:MyNamespace.IMyInterface.MyMethod`1(System.Memory{System.Byte}) + System.Void - - + + + + - To be added. - To be added. + To be added. + To be added. To be added. To be added. + - - - Field + +"; + + List docFiles = new() + { + new StringTestData(originalInterface, expectedInterface), + new StringTestData(originalChildType, expectedChildType) + }; + + Configuration configuration = new(); + configuration.PreserveInheritDocTag = true; + configuration.IncludedAssemblies.Add("MyAssembly"); + + TestWithStrings(intellisenseFile, docFiles, configuration); + } + + [Fact] + public void PartialInheritDoc_WithBaseType() + { + // The tag can be used to inherit documentation without having to port it. + // The exception to the rule is when the API is documented in the intellisense xml, in which case + // we port that documentation, since the API author intended to override the inherited documentation. + + string intellisenseFile = @" + + + MyAssembly + + + + The summary of the MyParentType type. + The remarks of the MyParentType type. + + + The summary of MyParentType.MyMethod. + The remarks of MyParentType.MyMethod. + + + The summary of MyParentType.MyMethod`1. + The MyParentType.MyMethod`1 param description. + The MyParentType.MyMethod`1 typeparam description. + The remarks of MyParentType.Method`1. + + + I am overriding the inherited interface summary. + + + + I am overriding the inherited interface remarks. + + + + + I am overriding the inherited interface param. + + I am overriding the inherited interface remarks. + + + +"; + + string originalBaseType = @" + + + MyAssembly + + + To be added. + To be added. + + + + + Method MyAssembly - System.Int32 + System.Void - 1 + To be added. To be added. + + + Method + + MyAssembly + + + System.Void + + + + + + + + + To be added. + To be added. + To be added. + To be added. + + "; - string expectedDocs = @" + string expectedBaseType = @" + + + MyAssembly + + + The summary of the MyParentType type. + The remarks of the MyParentType type. + + + + + Method + + MyAssembly + + + System.Void + + + + The summary of MyParentType.MyMethod. + The remarks of MyParentType.MyMethod. + + + + + Method + + MyAssembly + + + System.Void + + + + + + + + + The MyParentType.MyMethod`1 param description. + The MyParentType.MyMethod`1 typeparam description. + The summary of MyParentType.MyMethod`1. + The remarks of MyParentType.Method`1. + + + +"; + + string originalChildType = @" MyAssembly - - - MyNamespace.IMyInterface - - + + MyNamespace.MyParentType + + To be added. To be added. - - + + Method + + MyAssembly + + + System.Void + + + + To be added. + To be added. + + + + Method - - M:MyNamespace.MyInterface.MyMethod(System.String,System.Int32) - MyAssembly @@ -1432,31 +1751,73 @@ public void PartialInheritDoc() System.Void - - + + + + - To be added. - The MyType.MyMethod myParam2 description. - The MyType.MyMethod summary. + To be added. + To be added. + To be added. To be added. - - - - Field + +"; + + string expectedChildType = @" + + + MyAssembly + + + MyNamespace.MyParentType + + + + I am overriding the inherited interface summary. + To be added. + + + + + + Method MyAssembly - System.Int32 + System.Void - 1 + To be added. - The MyType.MyField remarks. - + I am overriding the inherited interface remarks. + + + + + + Method + + MyAssembly + + + System.Void + + + + + + + + + I am overriding the inherited interface param. + To be added. + To be added. + I am overriding the inherited interface remarks. + @@ -1464,64 +1825,62 @@ public void PartialInheritDoc() List docFiles = new() { - new StringTestData(originalDocs, expectedDocs), - new StringTestData(interfaceOriginalDocs, interfaceExpectedDocs) + new StringTestData(originalBaseType, expectedBaseType), + new StringTestData(originalChildType, expectedChildType) }; Configuration configuration = new(); configuration.PreserveInheritDocTag = true; configuration.IncludedAssemblies.Add("MyAssembly"); - TestWithStrings(intellisense, docFiles, configuration); + TestWithStrings(intellisenseFile, docFiles, configuration); } - // [Fact] - // TODO: Implement functionality for PreserveInheritDocTag=false - //public void IgnoreInheritDoc() - private void IgnoreInheritDoc() + [Fact] + public void PartialInheritDoc_WithInterface() { - // If PreserveInheritDocTag is set to false, then if the inheritdoc tag is found, - // all the documentation strings are copied from the ancestors, and the inheritdoc tag - // is not added to the docs xml. + // Same as the partial inheritdoc with base type test, but the logic used to retrieve the inherited interface + // documentation is different to that from the base type, so we need a separate test. - string intellisense = @" + string intellisenseFile = @" MyAssembly - The IMyInterface summary. - The IMyInterface remarks. + This is the summary of the IMyInterface type. + These are the remarks of the IMyInterface type. - - The IMyInterface.MyMethod summary. - The IMyInterface.MyMethod remarks. - The IMyInterface.MyMethod myParam1 description. - The IMyInterface.MyMethod myParam2 description. + + This is the summary of the IMyInterface.MyMethod method. + These are the remarks of the IMyInterface.MyMethod method. - - The IMyInterface.MyField summary. - The IMyInterface.MyField remarks. + + The summary of IMyInterface.MyMethod`1. + The IMyInterface.MyMethod`1 param description. + The IMyInterface.MyMethod`1 typeparam description. + The remarks of IMyInterface.Method`1. - + I am overriding the BaseType remarks. - - The MyType.MyMethod myParam2 description. - The MyType.MyMethod summary. - + + I am overriding the BaseType summary. + - - - The MyType.MyField remarks. - + + I am overriding the BaseType summary. + + I am overriding the BaseType typeparam. + + "; - string interfaceOriginalDocs = @" + string originalBaseType = @" MyAssembly @@ -1532,7 +1891,7 @@ private void IgnoreInheritDoc() - + Method MyAssembly @@ -1540,28 +1899,30 @@ private void IgnoreInheritDoc() System.Void - - - - + - To be added. - To be added. To be added. To be added. - - - Field + + + Method MyAssembly - System.Int32 + System.Void - 1 + + + + + + + To be added. + To be added. To be added. To be added. @@ -1569,18 +1930,18 @@ private void IgnoreInheritDoc() "; - string interfaceExpectedDocs = @" + string expectedBaseType = @" MyAssembly - The IMyInterface summary. - The IMyInterface remarks. + This is the summary of the IMyInterface type. + These are the remarks of the IMyInterface type. - + Method MyAssembly @@ -1588,36 +1949,38 @@ private void IgnoreInheritDoc() System.Void - - - - + - The IMyInterface.MyMethod myParam1 description. - The IMyInterface.MyMethod myParam2 description. - The IMyInterface.MyMethod summary. - The IMyInterface.MyMethod remarks. + This is the summary of the IMyInterface.MyMethod method. + These are the remarks of the IMyInterface.MyMethod method. - - - Field + + + Method MyAssembly - System.Int32 + System.Void - 1 + + + + + + - The IMyInterface.MyField summary. - The IMyInterface.MyField remarks. + The IMyInterface.MyMethod`1 param description. + The IMyInterface.MyMethod`1 typeparam description. + The summary of IMyInterface.MyMethod`1. + The remarks of IMyInterface.Method`1. "; - string originalDocs = @" + string originalChildType = @" MyAssembly @@ -1633,47 +1996,52 @@ private void IgnoreInheritDoc() - + Method - - M:MyNamespace.MyInterface.MyMethod(System.String,System.Int32) - MyAssembly + + M:MyNamespace.IMyInterface.MyMethod + - System.Void + MyNamespace.Void - - - - + - To be added. - To be added. To be added. To be added. - - - Field + + + Method MyAssembly + + M:MyNamespace.IMyInterface.MyMethod`1(System.Memory{System.Byte}) + - System.Int32 + System.Void - 1 + + + + + + - To be added. - To be added. + To be added. + To be added. + To be added. + To be added. "; - string expectedDocs = @" + string expectedChildType = @" MyAssembly @@ -1684,46 +2052,54 @@ private void IgnoreInheritDoc() - The IMyInterface summary. - The IMyInterface remarks. + To be added. + I am overriding the BaseType remarks. + - + Method - - M:MyNamespace.MyInterface.MyMethod(System.String,System.Int32) - MyAssembly + + M:MyNamespace.IMyInterface.MyMethod + - System.Void + MyNamespace.Void - - - - + - The IMyInterface.MyMethod myParam1 description. - The MyType.MyMethod myParam2 description. - The MyType.MyMethod summary. - The IMyInterface.MyMethod remarks. + I am overriding the BaseType summary. + To be added. + - - - Field + + + Method MyAssembly + + M:MyNamespace.IMyInterface.MyMethod`1(System.Memory{System.Byte}) + - System.Int32 + System.Void - 1 + + + + + + - The IMyInterface.MyField summary. - The MyType.MyField remarks. + To be added. + I am overriding the BaseType typeparam. + I am overriding the BaseType summary. + To be added. + @@ -1731,23 +2107,22 @@ private void IgnoreInheritDoc() List docFiles = new() { - new StringTestData(originalDocs, expectedDocs), - new StringTestData(interfaceOriginalDocs, interfaceExpectedDocs) + new StringTestData(originalBaseType, expectedBaseType), + new StringTestData(originalChildType, expectedChildType) }; Configuration configuration = new(); - configuration.PreserveInheritDocTag = false; + configuration.PreserveInheritDocTag = true; configuration.IncludedAssemblies.Add("MyAssembly"); - TestWithStrings(intellisense, docFiles, configuration); + TestWithStrings(intellisenseFile, docFiles, configuration); } + private static void TestWithStrings(string intellisenseFile, string originalDocsFile, string expectedDocsFile, Configuration configuration) => + TestWithStrings(intellisenseFile, new List() { new StringTestData(originalDocsFile, expectedDocsFile) }, configuration); - private static void TestWithStrings(string originalIntellisense, string originalDocs, string expectedDocs, Configuration configuration) => - TestWithStrings(originalIntellisense, new List() { new StringTestData(originalDocs, expectedDocs) }, configuration); - - private static void TestWithStrings(string originalIntellisense, List docFiles, Configuration configuration) => - TestWithStrings(new List() { originalIntellisense }, docFiles, configuration); + private static void TestWithStrings(string intellisenseFile, List docFiles, Configuration configuration) => + TestWithStrings(new List() { intellisenseFile }, docFiles, configuration); private static void TestWithStrings(List intellisenseFiles, List docFiles, Configuration configuration) {