diff --git a/.gitignore b/.gitignore index 021cb1d..54c12dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,2 @@ .vs -bin -obj out -TestResults -BenchmarkDotNet.Artifacts diff --git a/build/Common.props b/build/Common.props index 8ecdfcb..c204186 100644 --- a/build/Common.props +++ b/build/Common.props @@ -4,7 +4,7 @@ SauceControl Clinton Ingram https://github.com/saucecontrol/InheritDoc - Copyright © 2019-$([System.DateTime]::Today.Year) $(Authors) + Copyright © 2019-$([System.DateTime]::Today.Year) $(Authors) and Contributors Automatic Documentation Inheritance Processing Automatically replace <inheritdoc /> tags with inherited documentation at build time. Integrates with MSBuild, so no command line tool or VS add-on is required. @@ -13,7 +13,7 @@ $(MSBuildProjectName) $(MSBuildProjectName) - $(Owners).png + icon.png readme.md MIT $(RepositoryUrl) @@ -57,8 +57,8 @@ - - + + diff --git a/build/SauceControl.png b/build/SauceControl.png deleted file mode 100644 index 8a26d44..0000000 Binary files a/build/SauceControl.png and /dev/null differ diff --git a/build/icon.png b/build/icon.png new file mode 100644 index 0000000..9149f4f Binary files /dev/null and b/build/icon.png differ diff --git a/src/InheritDoc/InheritDocProcessor.cs b/src/InheritDoc/InheritDocProcessor.cs index ec68763..caed8f2 100644 --- a/src/InheritDoc/InheritDocProcessor.cs +++ b/src/InheritDoc/InheritDocProcessor.cs @@ -226,34 +226,30 @@ private static IDictionary> generateDocMap(IList (string)i.Attribute(DocAttributeNames.Cref)).Where(c => !string.IsNullOrWhiteSpace(c)).ToHashSet(); - var bases = (om is not null ? (new[] { om }) : [ ]).Concat(m.GetBaseCandidates()).ToList(); - - // Fix up docs for C# primary constructors, which do not have docs of their own and therefore should not get warnings for missing base. - if (m.IsConstructor && bases.Count == 0 && crefs.Count == 0 && memDocs.Any()) + // Fix up docs for C# primary constructors, which result in type and constructor sharing docs. + if (m.IsConstructor && memDocs.Any()) { var typeDoc = memDocs.First(); var ctorDoc = methDocs.First(); ctorDoc.SetAttributeValue(DocAttributeNames.Name, typeID); - // Type and constructor having identical docs is the surest sign of a primary constructor. - // We'll find a suitable base for the ctor and inject a cref pointing to it. if (nodeComparer.Equals(typeDoc, ctorDoc)) { - string cref = typeID; - if (m.GetBaseConstructor() is MethodDefinition bc && bc.GetDocID().SelectMany(d => findDocsByID(docMembers, d)).FirstOrDefault() is XElement bcd) - cref = (string)bcd.Attribute(DocAttributeNames.Name); + // Find a suitable base for the ctor and inject a cref in order to avoid warning for missing base. + if (ctorDoc.Elements(DocElementNames.InheritDoc).Any()) + { + string cref = typeID; + if (m.GetBaseConstructor() is MethodDefinition bc && bc.GetDocID().SelectMany(d => findDocsByID(docMembers, d)).FirstOrDefault() is XElement bcd) + cref = (string)bcd.Attribute(DocAttributeNames.Name); - crefs.Add(cref); - foreach (var d in methDocs.Descendants(DocElementNames.InheritDoc)) - d.SetElementValue(DocAttributeNames.Cref, cref); + foreach (var d in ctorDoc.Elements(DocElementNames.InheritDoc).Where(i => !i.HasAttribute(DocAttributeNames.Cref))) + d.SetAttributeValue(DocAttributeNames.Cref, cref); + } - // `param` elements meant for the constructor will also appear in the type's docs. - foreach (var param in typeDoc.Descendants(DocElementNames.Param).ToList()) + // Remove `param` elements meant for the constructor, which also appear in the type's docs. + foreach (var param in typeDoc.Elements(DocElementNames.Param).ToList()) { if ((param.PreviousNode?.IsWhiteSpace()).GetValueOrDefault()) param.PreviousNode!.Remove(); @@ -265,23 +261,31 @@ private static IDictionary> generateDocMap(IList(); - foreach (var (bm, cref) in bases.SelectMany(bm => bm.GetDocID().Select(d => (bm, d)))) + if (methDocs.Descendants(DocElementNames.InheritDoc).Any()) { - if (dml.Count == 0 || crefs.Contains(cref)) - dml.Add(new DocMatch(cref, m, bm)); + logger.Write(ILogger.Severity.Diag, "Processing DocID: " + memID); - if (crefs.Count == 0) - break; - } + var bases = (om is not null ? (new[] { om }) : []).Concat(m.GetBaseCandidates()).ToList(); + var crefs = methDocs.Descendants(DocElementNames.InheritDoc).Select(i => (string)i.Attribute(DocAttributeNames.Cref)).Where(c => !string.IsNullOrWhiteSpace(c)).ToHashSet(); + var dml = new List(); - foreach (var cref in crefs.Where(c => !dml.Any(dm => dm.Cref == c))) - dml.Add(new DocMatch(cref, m)); + foreach (var (bm, cref) in bases.SelectMany(bm => bm.GetDocID().Select(d => (bm, d)))) + { + if (dml.Count == 0 || crefs.Contains(cref)) + dml.Add(new DocMatch(cref, m, bm)); - if (dml.Count > 0) - docMap.Add(memID, dml); - else - logger.Write(ILogger.Severity.Info, "No inherit candidate for: " + memID); + if (crefs.Count == 0) + break; + } + + foreach (var cref in crefs.Where(c => !dml.Any(dm => dm.Cref == c))) + dml.Add(new DocMatch(cref, m)); + + if (dml.Count > 0) + docMap.Add(memID, dml); + else + logger.Write(ILogger.Severity.Info, "No inherit candidate for: " + memID); + } } } diff --git a/tests/InheritDoc.Test/InheritDoc.Test.csproj b/tests/InheritDoc.Test/InheritDoc.Test.csproj index 61f0e01..eb78ef5 100644 --- a/tests/InheritDoc.Test/InheritDoc.Test.csproj +++ b/tests/InheritDoc.Test/InheritDoc.Test.csproj @@ -7,7 +7,7 @@ - +