Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add code fix for CS0037 ([#929](https://github.com/josefpihrt/roslynator/pull/929)).
- [CLI] Generate reference documentation that can be published with Docusaurus ([#918](https://github.com/josefpihrt/roslynator/pull/918)).
- `roslynator generate-doc --host docusaurus`
- [CLI] Generate reference documentation that can be published with Sphinx ([#961](https://github.com/josefpihrt/roslynator/pull/961)).
- `roslynator generate-doc --host sphinx`

### Changed

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup Condition="'$(RoslynatorDotNetCli)' != true AND '$(RoslynatorCommandLine)' != true">
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<PropertyGroup Condition="'$(RoslynatorDotNetCli)' == true AND '$(Configuration)' == 'Release'">
<PropertyGroup Condition="'$(RoslynatorDotNetCli)' == true">
<TargetFrameworks>net5.0;net6.0</TargetFrameworks>
</PropertyGroup>

Expand Down
3 changes: 2 additions & 1 deletion src/CommandLine/AssemblyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEven
Debug.Assert(
(!assemblyName.Name.StartsWith("Microsoft.")
|| assemblyName.Name.StartsWith("Microsoft.VisualStudio.")
|| string.Equals(assemblyName.Name, "Microsoft.DiaSymReader", StringComparison.Ordinal))
|| string.Equals(assemblyName.Name, "Microsoft.DiaSymReader", StringComparison.Ordinal)
|| assemblyName.Name.EndsWith(".Analyzers"))
&& !assemblyName.Name.StartsWith("System."),
assemblyName.ToString());

Expand Down
2 changes: 1 addition & 1 deletion src/CommandLine/CommandLine.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup Condition="'$(RoslynatorDotNetCli)' != true AND '$(RoslynatorCommandLine)' != true">
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<PropertyGroup Condition="'$(RoslynatorDotNetCli)' == true">
Expand Down
86 changes: 82 additions & 4 deletions src/CommandLine/Commands/GenerateDocCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
Expand Down Expand Up @@ -112,7 +113,7 @@ public override async Task<CommandResult> ExecuteAsync(ProjectOrSolution project
ignoredCommonParts: IgnoredCommonParts,
includeContainingNamespaceFilter: IncludeContainingNamespaceFilter,
filesLayout: FilesLayout,
scrollToContent: Options.ScrollToContent);
scrollToContent: (DocumentationHost == DocumentationHost.GitHub) && Options.ScrollToContent);

ImmutableArray<Compilation> compilations = await GetCompilationsAsync(projectOrSolution, cancellationToken);

Expand All @@ -123,7 +124,9 @@ public override async Task<CommandResult> ExecuteAsync(ProjectOrSolution project
if (GroupByCommonNamespace)
{
commonNamespaces = DocumentationUtility.FindCommonNamespaces(
documentationModel.Types.Concat(documentationModel.GetExtendedExternalTypes()));
documentationModel.Types
.Concat(documentationModel.GetExtendedExternalTypes())
.Where(f => !documentationOptions.ShouldBeIgnored(f)));
}

UrlSegmentProvider urlSegmentProvider = new DefaultUrlSegmentProvider(FilesLayout, commonNamespaces);
Expand All @@ -138,6 +141,8 @@ DocumentationUrlProvider GetUrlProvider()
return new GitHubDocumentationUrlProvider(urlSegmentProvider, externalProviders);
case DocumentationHost.Docusaurus:
return new DocusaurusDocumentationUrlProvider(urlSegmentProvider, externalProviders);
case DocumentationHost.Sphinx:
return new SphinxDocumentationUrlProvider(urlSegmentProvider, externalProviders);
default:
throw new InvalidOperationException($"Unknown value '{DocumentationHost}'.");
}
Expand All @@ -148,6 +153,7 @@ MarkdownWriterSettings GetMarkdownWriterSettings()
switch (DocumentationHost)
{
case DocumentationHost.GitHub:
case DocumentationHost.Sphinx:
return MarkdownWriterSettings.Default;
case DocumentationHost.Docusaurus:
return new MarkdownWriterSettings(new MarkdownFormat(angleBracketEscapeStyle: AngleBracketEscapeStyle.EntityRef));
Expand All @@ -165,9 +171,11 @@ DocumentationWriter CreateDocumentationWriter(DocumentationContext context)
switch (DocumentationHost)
{
case DocumentationHost.GitHub:
return new MarkdownDocumentationWriter(context, writer);
return new GitHubDocumentationWriter(context, writer);
case DocumentationHost.Docusaurus:
return new DocusaurusDocumentationWriter(context, writer);
case DocumentationHost.Sphinx:
return new SphinxDocumentationWriter(context, writer);
default:
throw new InvalidOperationException($"Unknown value '{DocumentationHost}'.");
}
Expand Down Expand Up @@ -206,7 +214,16 @@ DocumentationWriter CreateDocumentationWriter(DocumentationContext context)

WriteLine($"Generate documentation to '{Options.Output}'", Verbosity.Minimal);

foreach (DocumentationGeneratorResult documentationFile in generator.Generate(heading: Options.Heading, cancellationToken))
IEnumerable<DocumentationGeneratorResult> results = generator.Generate(heading: Options.Heading, cancellationToken);

if (DocumentationHost == DocumentationHost.Sphinx)
{
List<DocumentationGeneratorResult> resultList = results.ToList();
AddTableOfContents(resultList);
results = resultList;
}

foreach (DocumentationGeneratorResult documentationFile in results)
{
string path = Path.Combine(directoryPath, documentationFile.FilePath);

Expand All @@ -221,5 +238,66 @@ DocumentationWriter CreateDocumentationWriter(DocumentationContext context)

return CommandResults.Success;
}

private void AddTableOfContents(IEnumerable<DocumentationGeneratorResult> results)
{
foreach (DocumentationGeneratorResult result in results)
{
string content = result.Content;
string filePath = result.FilePath;
string directoryPath = Path.GetDirectoryName(filePath);

IEnumerable<DocumentationGeneratorResult> children = results.Where(r =>
{
if (r != result)
{
string path = r.FilePath;

if (path.StartsWith(directoryPath))
{
string relativePath = path.Substring(directoryPath.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);

if (relativePath.Count(f => f == Path.DirectorySeparatorChar || f == Path.AltDirectorySeparatorChar) == 1)
{
return true;
}
}
}

return false;
});

if (children.Any())
{
var sb = new StringBuilder();

sb.AppendLine();
sb.AppendLine("```{toctree}");
sb.AppendLine(":hidden:");
sb.AppendLine(":maxdepth: 1");
sb.AppendLine();

foreach (DocumentationGeneratorResult child in children
.OrderBy(child => child.Label))
{
Debug.Assert(child.Label is not null);

sb.Append(child.Label);
sb.Append(" <");

sb.Append(child.FilePath
.Substring(directoryPath.Length)
.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
.Replace('\\', '/'));

sb.AppendLine(">");
}

sb.AppendLine("```");

result.Content += sb.ToString();
}
}
}
}
}
9 changes: 7 additions & 2 deletions src/CommandLine/Commands/GenerateDocRootCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public override async Task<CommandResult> ExecuteAsync(ProjectOrSolution project
depth: Depth,
ignoredRootParts: IgnoredParts,
includeContainingNamespaceFilter: IncludeContainingNamespaceFilter,
scrollToContent: Options.ScrollToContent);
scrollToContent: (DocumentationHost == DocumentationHost.GitHub) && Options.ScrollToContent);

ImmutableArray<Compilation> compilations = await GetCompilationsAsync(projectOrSolution, cancellationToken);

Expand All @@ -80,6 +80,8 @@ DocumentationUrlProvider GetUrlProvider()
return new GitHubDocumentationUrlProvider(urlSegmentProvider, externalProviders);
case DocumentationHost.Docusaurus:
return new DocusaurusDocumentationUrlProvider(urlSegmentProvider, externalProviders);
case DocumentationHost.Sphinx:
return new SphinxDocumentationUrlProvider(urlSegmentProvider, externalProviders);
default:
throw new InvalidOperationException($"Unknown value '{DocumentationHost}'.");
}
Expand All @@ -90,6 +92,7 @@ MarkdownWriterSettings GetMarkdownWriterSettings()
switch (DocumentationHost)
{
case DocumentationHost.GitHub:
case DocumentationHost.Sphinx:
return MarkdownWriterSettings.Default;
case DocumentationHost.Docusaurus:
return new MarkdownWriterSettings(new MarkdownFormat(angleBracketEscapeStyle: AngleBracketEscapeStyle.EntityRef));
Expand All @@ -107,9 +110,11 @@ DocumentationWriter CreateDocumentationWriter(DocumentationContext context)
switch (DocumentationHost)
{
case DocumentationHost.GitHub:
return new MarkdownDocumentationWriter(context, writer);
return new GitHubDocumentationWriter(context, writer);
case DocumentationHost.Docusaurus:
return new DocusaurusDocumentationWriter(context, writer);
case DocumentationHost.Sphinx:
return new SphinxDocumentationWriter(context, writer);
default:
throw new InvalidOperationException($"Unknown value '{DocumentationHost}'.");
}
Expand Down
3 changes: 2 additions & 1 deletion src/CommandLine/DocumentationHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ namespace Roslynator.CommandLine
{
internal enum DocumentationHost
{
GitHub,
Docusaurus,
GitHub,
Sphinx,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public abstract class AbstractGenerateDocCommandLineOptions : MSBuildCommandLine
[Option(
longName: OptionNames.Host,
Required = true,
HelpText = "Defines a host where the content will be published. Allowed values are github or docusaurus.",
HelpText = "Defines a host where the content will be published. Allowed values are docusaurus, github or sphinx.",
MetaValue = "<HOST>")]
public string Host { get; set; }

Expand All @@ -59,7 +59,7 @@ public abstract class AbstractGenerateDocCommandLineOptions : MSBuildCommandLine

[Option(
longName: "scroll-to-content",
HelpText = "Indicates whether a link should lead to the top of the documentation content.")]
HelpText = "Indicates whether a link should lead to the top of the documentation content. This option is applicable when host is set to 'github'.")]
public bool ScrollToContent { get; set; }

[Option(
Expand Down
12 changes: 12 additions & 0 deletions src/Documentation/DocumentationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;

namespace Roslynator.Documentation
{
public class DocumentationContext
{
private readonly Func<DocumentationContext, DocumentationWriter> _createWriter;
private ImmutableHashSet<(INamespaceSymbol, string)> _commonNamespacesAsText;

public DocumentationContext(
DocumentationModel documentationModel,
Expand Down Expand Up @@ -44,6 +46,16 @@ public DocumentationContext(

public ImmutableHashSet<INamespaceSymbol> CommonNamespaces { get; }

internal ImmutableHashSet<(INamespaceSymbol symbol, string displayString)> CommonNamespacesAsText
{
get
{
return _commonNamespacesAsText ??= CommonNamespaces
.Select(f => (f, f.ToDisplayString(TypeSymbolDisplayFormats.Name_ContainingTypes_Namespaces_GlobalNamespace_OmittedAsContaining)))
.ToImmutableHashSet();
}
}

public DocumentationWriter CreateWriter()
{
return _createWriter(this);
Expand Down
Loading