diff --git a/ChangeLog.md b/ChangeLog.md
index 2e40e1e514..c7e4d3f48a 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [CLI] Generate reference documentation that can be published with Sphinx ([#961](https://github.com/josefpihrt/roslynator/pull/961)).
- `roslynator generate-doc --host sphinx`
- [CLI] Basic support for `` when generating documentation (`generate-doc` command) ([#972](https://github.com/josefpihrt/roslynator/pull/972)).
+- [CLI] Add option `ignored-title-parts` (`generate-doc` command) ([#975](https://github.com/josefpihrt/roslynator/pull/975)).
### Changed
diff --git a/src/CommandLine/Commands/GenerateDocCommand.cs b/src/CommandLine/Commands/GenerateDocCommand.cs
index 327bf87f27..19878d43f2 100644
--- a/src/CommandLine/Commands/GenerateDocCommand.cs
+++ b/src/CommandLine/Commands/GenerateDocCommand.cs
@@ -29,6 +29,7 @@ public GenerateDocCommand(
TypeDocumentationParts ignoredTypeParts,
MemberDocumentationParts ignoredMemberParts,
CommonDocumentationParts ignoredCommonParts,
+ SymbolTitleParts ignoredTitleParts,
OmitMemberParts omitMemberParts,
IncludeContainingNamespaceFilter includeContainingNamespaceFilter,
Visibility visibility,
@@ -46,6 +47,7 @@ public GenerateDocCommand(
IgnoredMemberParts = ignoredMemberParts;
IgnoredCommonParts = ignoredCommonParts;
OmitMemberParts = omitMemberParts;
+ IgnoredTitleParts = ignoredTitleParts;
IncludeContainingNamespaceFilter = includeContainingNamespaceFilter;
Visibility = visibility;
DocumentationHost = documentationHost;
@@ -70,6 +72,8 @@ public GenerateDocCommand(
public OmitMemberParts OmitMemberParts { get; }
+ public SymbolTitleParts IgnoredTitleParts { get; }
+
public IncludeContainingNamespaceFilter IncludeContainingNamespaceFilter { get; }
public Visibility Visibility { get; }
@@ -111,6 +115,7 @@ public override async Task ExecuteAsync(ProjectOrSolution project
ignoredTypeParts: IgnoredTypeParts,
ignoredMemberParts: IgnoredMemberParts,
ignoredCommonParts: IgnoredCommonParts,
+ ignoredTitleParts: IgnoredTitleParts,
includeContainingNamespaceFilter: IncludeContainingNamespaceFilter,
filesLayout: FilesLayout,
scrollToContent: (DocumentationHost == DocumentationHost.GitHub) && Options.ScrollToContent);
diff --git a/src/CommandLine/OptionNames.cs b/src/CommandLine/OptionNames.cs
index 51e381836f..7e6811952d 100644
--- a/src/CommandLine/OptionNames.cs
+++ b/src/CommandLine/OptionNames.cs
@@ -20,6 +20,7 @@ internal static class OptionNames
public const string IgnoredProjects = "ignored-projects";
public const string IgnoredRootParts = "ignored-root-parts";
public const string IgnoredScope = "ignored-scope";
+ public const string IgnoredTitleParts = "ignored-title-parts";
public const string IgnoredTypeParts = "ignored-type-parts";
public const string IncludeContainingNamespace = "include-containing-namespace";
public const string IncludeSystemNamespace = "include-system-namespace";
diff --git a/src/CommandLine/Options/GenerateDocCommandLineOptions.cs b/src/CommandLine/Options/GenerateDocCommandLineOptions.cs
index 1510ec48b2..035835d4a0 100644
--- a/src/CommandLine/Options/GenerateDocCommandLineOptions.cs
+++ b/src/CommandLine/Options/GenerateDocCommandLineOptions.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using CommandLine;
-using Roslynator.Documentation;
using static Roslynator.Documentation.DocumentationOptions;
namespace Roslynator.CommandLine
@@ -45,6 +44,12 @@ public class GenerateDocCommandLineOptions : AbstractGenerateDocCommandLineOptio
MetaValue = "")]
public IEnumerable IgnoredRootParts { get; set; }
+ [Option(
+ longName: OptionNames.IgnoredTitleParts,
+ HelpText = "Defines title parts of a documentation that should be excluded. Allowed value is containing-namespace, containing-type, parameters and explicit-implementation.",
+ MetaValue = "")]
+ public IEnumerable IgnoredTitleParts { get; set; }
+
[Option(
longName: OptionNames.IgnoredTypeParts,
HelpText = "Defines parts of a type documentation that should be excluded. Allowed values are content, containing-namespace, containing-assembly, obsolete-message, summary, declaration, type-parameters, parameters, return-value, inheritance, attributes, derived, implements, examples, remarks, constructors, fields, indexers, properties, methods, operators, events, explicit-interface-implementations, extension-methods, classes, structs, interfaces, enums, delegates and see-also.",
diff --git a/src/CommandLine/Program.cs b/src/CommandLine/Program.cs
index 9a652d4c56..ce990aa316 100644
--- a/src/CommandLine/Program.cs
+++ b/src/CommandLine/Program.cs
@@ -762,6 +762,9 @@ private static async Task GenerateDocAsync(GenerateDocCommandLineOptions op
if (!TryParseOptionValueAsEnumFlags(options.IgnoredCommonParts, OptionNames.IgnoredCommonParts, out CommonDocumentationParts ignoredCommonParts, DocumentationOptions.DefaultValues.IgnoredCommonParts))
return ExitCodes.Error;
+ if (!TryParseOptionValueAsEnumFlags(options.IgnoredTitleParts, OptionNames.IgnoredTitleParts, out SymbolTitleParts ignoredTitleParts, DocumentationOptions.DefaultValues.IgnoredTitleParts))
+ return ExitCodes.Error;
+
if (!TryParseOptionValueAsEnumFlags(options.IncludeContainingNamespace, OptionNames.IncludeContainingNamespace, out IncludeContainingNamespaceFilter includeContainingNamespaceFilter, DocumentationOptions.DefaultValues.IncludeContainingNamespaceFilter))
return ExitCodes.Error;
@@ -784,21 +787,22 @@ private static async Task GenerateDocAsync(GenerateDocCommandLineOptions op
return ExitCodes.Error;
var command = new GenerateDocCommand(
- options,
- depth,
- ignoredRootParts,
- ignoredNamespaceParts,
- ignoredTypeParts,
- ignoredMemberParts,
- ignoredCommonParts,
- omitMemberParts,
- includeContainingNamespaceFilter,
- visibility,
- documentationHost,
- filesLayout,
+ options: options,
+ depth: depth,
+ ignoredRootParts: ignoredRootParts,
+ ignoredNamespaceParts: ignoredNamespaceParts,
+ ignoredTypeParts: ignoredTypeParts,
+ ignoredMemberParts: ignoredMemberParts,
+ ignoredCommonParts: ignoredCommonParts,
+ ignoredTitleParts: ignoredTitleParts,
+ omitMemberParts: omitMemberParts,
+ includeContainingNamespaceFilter: includeContainingNamespaceFilter,
+ visibility: visibility,
+ documentationHost: documentationHost,
+ filesLayout: filesLayout,
groupByCommonNamespace: options.GroupByCommonNamespace,
inheritanceStyle: inheritanceStyle,
- projectFilter);
+ projectFilter: projectFilter);
CommandStatus status = await command.ExecuteAsync(paths, options.MSBuildPath, options.Properties);
diff --git a/src/Documentation/DocumentationGenerator.cs b/src/Documentation/DocumentationGenerator.cs
index 6c7a22eea8..b8f392f34d 100644
--- a/src/Documentation/DocumentationGenerator.cs
+++ b/src/Documentation/DocumentationGenerator.cs
@@ -332,7 +332,14 @@ private DocumentationGeneratorResult GenerateNamespace(INamespaceSymbol namespac
SymbolXmlDocumentation xmlDocumentation = DocumentationModel.GetXmlDocumentation(namespaceSymbol, Options.PreferredCultureName);
- writer.WriteHeading(1, namespaceSymbol, TypeSymbolDisplayFormats.Name_ContainingTypes_Namespaces, addLink: false, linkDestination: (Options.ScrollToContent) ? WellKnownNames.TopFragmentName : null);
+ writer.WriteHeading(
+ 1,
+ namespaceSymbol,
+ ((Options.IgnoredTitleParts & SymbolTitleParts.ContainingNamespace) != 0)
+ ? TypeSymbolDisplayFormats.Name
+ : TypeSymbolDisplayFormats.Name_ContainingTypes_Namespaces,
+ addLink: false,
+ linkDestination: (Options.ScrollToContent) ? WellKnownNames.TopFragmentName : null);
foreach (NamespaceDocumentationParts part in EnabledAndSortedNamespaceParts)
{
@@ -591,7 +598,9 @@ private DocumentationGeneratorResult GenerateType(TypeDocumentationModel typeMod
writer.WriteHeading(
1,
typeSymbol,
- TypeSymbolDisplayFormats.Name_ContainingTypes_TypeParameters,
+ ((Options.IgnoredTitleParts & SymbolTitleParts.ContainingType) != 0)
+ ? TypeSymbolDisplayFormats.Name_TypeParameters
+ : TypeSymbolDisplayFormats.Name_ContainingTypes_TypeParameters,
SymbolDisplayAdditionalMemberOptions.UseItemPropertyName | SymbolDisplayAdditionalMemberOptions.UseOperatorName,
addLink: false,
linkDestination: (Options.ScrollToContent) ? WellKnownNames.TopFragmentName : null);
diff --git a/src/Documentation/DocumentationOptions.cs b/src/Documentation/DocumentationOptions.cs
index 35254acac0..c4c87950b9 100644
--- a/src/Documentation/DocumentationOptions.cs
+++ b/src/Documentation/DocumentationOptions.cs
@@ -39,6 +39,7 @@ public DocumentationOptions(
TypeDocumentationParts ignoredTypeParts = TypeDocumentationParts.None,
MemberDocumentationParts ignoredMemberParts = MemberDocumentationParts.None,
CommonDocumentationParts ignoredCommonParts = CommonDocumentationParts.None,
+ SymbolTitleParts ignoredTitleParts = SymbolTitleParts.None,
IncludeContainingNamespaceFilter includeContainingNamespaceFilter = IncludeContainingNamespaceFilter.None,
FilesLayout filesLayout = FilesLayout.Hierarchical,
bool scrollToContent = DefaultValues.ScrollToContent)
@@ -74,6 +75,7 @@ public DocumentationOptions(
IgnoredTypeParts = ignoredTypeParts;
IgnoredMemberParts = ignoredMemberParts;
IgnoredCommonParts = ignoredCommonParts;
+ IgnoredTitleParts = ignoredTitleParts;
IncludeContainingNamespaceFilter = includeContainingNamespaceFilter;
FilesLayout = filesLayout;
ScrollToContent = scrollToContent;
@@ -141,6 +143,8 @@ public DocumentationOptions(
public CommonDocumentationParts IgnoredCommonParts { get; }
+ public SymbolTitleParts IgnoredTitleParts { get; }
+
public IncludeContainingNamespaceFilter IncludeContainingNamespaceFilter { get; }
public FilesLayout FilesLayout { get; }
@@ -202,6 +206,7 @@ internal static class DefaultValues
public const TypeDocumentationParts IgnoredTypeParts = TypeDocumentationParts.None;
public const MemberDocumentationParts IgnoredMemberParts = MemberDocumentationParts.None;
public const CommonDocumentationParts IgnoredCommonParts = CommonDocumentationParts.None;
+ public const SymbolTitleParts IgnoredTitleParts = SymbolTitleParts.None;
public const IncludeContainingNamespaceFilter IncludeContainingNamespaceFilter = Roslynator.Documentation.IncludeContainingNamespaceFilter.None;
}
}
diff --git a/src/Documentation/DocumentationWriter.cs b/src/Documentation/DocumentationWriter.cs
index 9bc99d9055..d37b58e5c4 100644
--- a/src/Documentation/DocumentationWriter.cs
+++ b/src/Documentation/DocumentationWriter.cs
@@ -18,6 +18,10 @@ public abstract class DocumentationWriter : IDisposable
{
private bool _disposed;
+ private SymbolDisplayFormat _nonOverloadedConstructorDisplayFormat;
+ private SymbolDisplayFormat _nonOverloadedMemberDisplayFormat;
+ private SymbolDisplayFormat _overloadedMemberDisplayFormat;
+
protected DocumentationWriter(DocumentationContext context)
{
Context = context ?? throw new ArgumentNullException(nameof(context));
@@ -350,27 +354,81 @@ internal void WriteMemberTitle(ISymbol symbol, bool isOverloaded)
{
WriteStartHeading(1);
- if (symbol.Kind == SymbolKind.Method
- && ((IMethodSymbol)symbol).MethodKind == MethodKind.Constructor)
+ if ((symbol as IMethodSymbol)?.MethodKind == MethodKind.Constructor)
{
if (isOverloaded)
{
- WriteString(symbol.ContainingType.ToDisplayString(TypeSymbolDisplayFormats.Name_ContainingTypes_TypeParameters));
+ SymbolDisplayFormat format = ((Options.IgnoredTitleParts & SymbolTitleParts.ContainingType) != 0)
+ ? TypeSymbolDisplayFormats.Name_TypeParameters
+ : TypeSymbolDisplayFormats.Name_ContainingTypes_TypeParameters;
+
+ WriteString(symbol.ContainingType.ToDisplayString(format));
WriteSpace();
WriteString(Resources.ConstructorsTitle);
}
else
{
- WriteString(symbol.ToDisplayString(DocumentationDisplayFormats.SimpleDeclaration));
+ _nonOverloadedConstructorDisplayFormat ??= DocumentationDisplayFormats.Default.Update(
+ genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
+ memberOptions: ((Options.IgnoredTitleParts & SymbolTitleParts.Parameters) != 0)
+ ? SymbolDisplayMemberOptions.None
+ : SymbolDisplayMemberOptions.IncludeParameters,
+ parameterOptions: SymbolDisplayParameterOptions.IncludeType);
+
+ if ((Options.IgnoredTitleParts & SymbolTitleParts.ContainingType) == 0)
+ {
+ INamedTypeSymbol containingType = symbol.ContainingType.ContainingType;
+
+ if (containingType is not null)
+ {
+ WriteString(containingType.ToDisplayString(TypeSymbolDisplayFormats.Name_ContainingTypes_TypeParameters));
+ WriteString(".");
+ }
+ }
+
+ WriteString(symbol.ToDisplayString(_nonOverloadedConstructorDisplayFormat));
WriteSpace();
WriteString(Resources.ConstructorTitle);
}
}
else
{
- SymbolDisplayFormat format = (isOverloaded)
- ? DocumentationDisplayFormats.OverloadedMemberTitle
- : DocumentationDisplayFormats.MemberTitle;
+ SymbolDisplayFormat format;
+ if (isOverloaded)
+ {
+ _overloadedMemberDisplayFormat ??= DocumentationDisplayFormats.Default.Update(
+ typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes,
+ genericsOptions: SymbolDisplayGenericsOptions.None,
+ memberOptions: (((Options.IgnoredTitleParts & SymbolTitleParts.ExplicitImplementation) != 0)
+ ? SymbolDisplayMemberOptions.None
+ : SymbolDisplayMemberOptions.IncludeExplicitInterface)
+ | (((Options.IgnoredTitleParts & SymbolTitleParts.ContainingType) != 0)
+ ? SymbolDisplayMemberOptions.None
+ : SymbolDisplayMemberOptions.IncludeContainingType));
+
+ format = _overloadedMemberDisplayFormat;
+ }
+ else
+ {
+ _nonOverloadedMemberDisplayFormat ??= DocumentationDisplayFormats.Default.Update(
+ typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes,
+ genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
+ memberOptions: (((Options.IgnoredTitleParts & SymbolTitleParts.ExplicitImplementation) != 0)
+ ? SymbolDisplayMemberOptions.None
+ : SymbolDisplayMemberOptions.IncludeExplicitInterface)
+ | (((Options.IgnoredTitleParts & SymbolTitleParts.Parameters) != 0)
+ ? SymbolDisplayMemberOptions.None
+ : SymbolDisplayMemberOptions.IncludeParameters)
+ | (((Options.IgnoredTitleParts & SymbolTitleParts.ContainingType) != 0)
+ ? SymbolDisplayMemberOptions.None
+ : SymbolDisplayMemberOptions.IncludeContainingType),
+ delegateStyle: ((Options.IgnoredTitleParts & SymbolTitleParts.Parameters) != 0)
+ ? SymbolDisplayDelegateStyle.NameOnly
+ : SymbolDisplayDelegateStyle.NameAndParameters,
+ parameterOptions: SymbolDisplayParameterOptions.IncludeType);
+
+ format = _nonOverloadedMemberDisplayFormat;
+ }
WriteString(symbol.ToDisplayString(format, SymbolDisplayAdditionalMemberOptions.UseItemPropertyName | SymbolDisplayAdditionalMemberOptions.UseOperatorName));
WriteSpace();
diff --git a/src/Documentation/SymbolTitleParts.cs b/src/Documentation/SymbolTitleParts.cs
new file mode 100644
index 0000000000..685fd98a02
--- /dev/null
+++ b/src/Documentation/SymbolTitleParts.cs
@@ -0,0 +1,16 @@
+// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+
+namespace Roslynator.Documentation
+{
+ [Flags]
+ public enum SymbolTitleParts
+ {
+ None = 0,
+ ContainingNamespace = 1,
+ ContainingType = 1 << 1,
+ Parameters = 1 << 2,
+ ExplicitImplementation = 1 << 3,
+ }
+}