Skip to content

Commit d160752

Browse files
authored
Refactor domain out of Elastic.Markdown part II (#1196)
1 parent f04de82 commit d160752

File tree

66 files changed

+499
-511
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+499
-511
lines changed

Elastic.Documentation/Diagnostics/DiagnosticsChannel.cs

Lines changed: 0 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5-
using System.Collections.Concurrent;
65
using System.Threading.Channels;
7-
using Microsoft.Extensions.Hosting;
86

97
namespace Elastic.Documentation.Diagnostics;
108

@@ -51,115 +49,3 @@ public interface IDiagnosticsOutput
5149
{
5250
void Write(Diagnostic diagnostic);
5351
}
54-
55-
public class DiagnosticsCollector(IReadOnlyCollection<IDiagnosticsOutput> outputs) : IHostedService, IAsyncDisposable
56-
{
57-
public DiagnosticsChannel Channel { get; } = new();
58-
59-
private int _errors;
60-
private int _warnings;
61-
private int _hints;
62-
public int Warnings => _warnings;
63-
public int Errors => _errors;
64-
public int Hints => _hints;
65-
66-
private Task? _started;
67-
68-
public HashSet<string> OffendingFiles { get; } = [];
69-
70-
public ConcurrentDictionary<string, bool> InUseSubstitutionKeys { get; } = [];
71-
72-
public ConcurrentBag<string> CrossLinks { get; } = [];
73-
74-
public bool NoHints { get; init; }
75-
76-
public Task StartAsync(Cancel cancellationToken)
77-
{
78-
if (_started is not null)
79-
return _started;
80-
_started = Task.Run(async () =>
81-
{
82-
_ = await Channel.WaitToWrite(cancellationToken);
83-
while (!Channel.CancellationToken.IsCancellationRequested)
84-
{
85-
try
86-
{
87-
while (await Channel.Reader.WaitToReadAsync(Channel.CancellationToken))
88-
Drain();
89-
}
90-
catch
91-
{
92-
//ignore
93-
}
94-
}
95-
96-
Drain();
97-
}, cancellationToken);
98-
return _started;
99-
100-
void Drain()
101-
{
102-
while (Channel.Reader.TryRead(out var item))
103-
{
104-
if (item.Severity == Severity.Hint && NoHints)
105-
continue;
106-
IncrementSeverityCount(item);
107-
HandleItem(item);
108-
_ = OffendingFiles.Add(item.File);
109-
foreach (var output in outputs)
110-
output.Write(item);
111-
}
112-
}
113-
}
114-
115-
private void IncrementSeverityCount(Diagnostic item)
116-
{
117-
if (item.Severity == Severity.Error)
118-
_ = Interlocked.Increment(ref _errors);
119-
else if (item.Severity == Severity.Warning)
120-
_ = Interlocked.Increment(ref _warnings);
121-
else if (item.Severity == Severity.Hint && !NoHints)
122-
_ = Interlocked.Increment(ref _hints);
123-
}
124-
125-
protected virtual void HandleItem(Diagnostic diagnostic) { }
126-
127-
public virtual async Task StopAsync(Cancel cancellationToken)
128-
{
129-
if (_started is not null)
130-
await _started;
131-
await Channel.Reader.Completion;
132-
}
133-
134-
public void EmitCrossLink(string link) => CrossLinks.Add(link);
135-
136-
private void Emit(Severity severity, string file, string message) =>
137-
Channel.Write(new Diagnostic
138-
{
139-
Severity = severity,
140-
File = file,
141-
Message = message
142-
});
143-
144-
public void EmitError(string file, string message, Exception? e = null)
145-
{
146-
message = message
147-
+ (e != null ? Environment.NewLine + e : string.Empty)
148-
+ (e?.InnerException != null ? Environment.NewLine + e.InnerException : string.Empty);
149-
Emit(Severity.Error, file, message);
150-
}
151-
152-
public void EmitWarning(string file, string message) => Emit(Severity.Warning, file, message);
153-
154-
public void EmitHint(string file, string message) => Emit(Severity.Hint, file, message);
155-
156-
public async ValueTask DisposeAsync()
157-
{
158-
Channel.TryComplete();
159-
await StopAsync(CancellationToken.None);
160-
GC.SuppressFinalize(this);
161-
}
162-
163-
public void CollectUsedSubstitutionKey(ReadOnlySpan<char> key) =>
164-
_ = InUseSubstitutionKeys.TryAdd(key.ToString(), true);
165-
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.Collections.Concurrent;
6+
using System.IO.Abstractions;
7+
using Microsoft.Extensions.Hosting;
8+
9+
namespace Elastic.Documentation.Diagnostics;
10+
11+
public class DiagnosticsCollector(IReadOnlyCollection<IDiagnosticsOutput> outputs) : IHostedService, IAsyncDisposable
12+
{
13+
public DiagnosticsChannel Channel { get; } = new();
14+
15+
private int _errors;
16+
private int _warnings;
17+
private int _hints;
18+
public int Warnings => _warnings;
19+
public int Errors => _errors;
20+
public int Hints => _hints;
21+
22+
private Task? _started;
23+
24+
public HashSet<string> OffendingFiles { get; } = [];
25+
26+
public ConcurrentDictionary<string, bool> InUseSubstitutionKeys { get; } = [];
27+
28+
public ConcurrentBag<string> CrossLinks { get; } = [];
29+
30+
public bool NoHints { get; init; }
31+
32+
public Task StartAsync(Cancel cancellationToken)
33+
{
34+
if (_started is not null)
35+
return _started;
36+
_started = Task.Run(async () =>
37+
{
38+
_ = await Channel.WaitToWrite(cancellationToken);
39+
while (!Channel.CancellationToken.IsCancellationRequested)
40+
{
41+
try
42+
{
43+
while (await Channel.Reader.WaitToReadAsync(Channel.CancellationToken))
44+
Drain();
45+
}
46+
catch
47+
{
48+
//ignore
49+
}
50+
}
51+
52+
Drain();
53+
}, cancellationToken);
54+
return _started;
55+
56+
void Drain()
57+
{
58+
while (Channel.Reader.TryRead(out var item))
59+
{
60+
if (item.Severity == Severity.Hint && NoHints)
61+
continue;
62+
IncrementSeverityCount(item);
63+
HandleItem(item);
64+
_ = OffendingFiles.Add(item.File);
65+
foreach (var output in outputs)
66+
output.Write(item);
67+
}
68+
}
69+
}
70+
71+
private void IncrementSeverityCount(Diagnostic item)
72+
{
73+
if (item.Severity == Severity.Error)
74+
_ = Interlocked.Increment(ref _errors);
75+
else if (item.Severity == Severity.Warning)
76+
_ = Interlocked.Increment(ref _warnings);
77+
else if (item.Severity == Severity.Hint && !NoHints)
78+
_ = Interlocked.Increment(ref _hints);
79+
}
80+
81+
protected virtual void HandleItem(Diagnostic diagnostic) { }
82+
83+
public virtual async Task StopAsync(Cancel cancellationToken)
84+
{
85+
if (_started is not null)
86+
await _started;
87+
await Channel.Reader.Completion;
88+
}
89+
90+
public void EmitCrossLink(string link) => CrossLinks.Add(link);
91+
92+
private void Emit(Severity severity, string file, string message) =>
93+
Channel.Write(new Diagnostic
94+
{
95+
Severity = severity,
96+
File = file,
97+
Message = message
98+
});
99+
100+
public void EmitError(string file, string message, Exception? e = null)
101+
{
102+
message = message
103+
+ (e != null ? Environment.NewLine + e : string.Empty)
104+
+ (e?.InnerException != null ? Environment.NewLine + e.InnerException : string.Empty);
105+
Emit(Severity.Error, file, message);
106+
}
107+
108+
public void EmitWarning(string file, string message) => Emit(Severity.Warning, file, message);
109+
110+
public void EmitHint(string file, string message) => Emit(Severity.Hint, file, message);
111+
112+
public void EmitError(IFileInfo file, string message, Exception? e = null) => EmitError(file.FullName, message, e);
113+
114+
public void EmitWarning(IFileInfo file, string message) => Emit(Severity.Warning, file.FullName, message);
115+
116+
public void EmitHint(IFileInfo file, string message) => Emit(Severity.Hint, file.FullName, message);
117+
118+
public async ValueTask DisposeAsync()
119+
{
120+
Channel.TryComplete();
121+
await StopAsync(CancellationToken.None);
122+
GC.SuppressFinalize(this);
123+
}
124+
125+
public void CollectUsedSubstitutionKey(ReadOnlySpan<char> key) =>
126+
_ = InUseSubstitutionKeys.TryAdd(key.ToString(), true);
127+
}

Elastic.Documentation/Elastic.Documentation.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11+
<PackageReference Include="DotNet.Glob" />
1112
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
1213
<PackageReference Include="Microsoft.Extensions.Logging"/>
1314
<PackageReference Include="NetEscapades.EnumGenerators"/>
14-
<PackageReference Include="Vecc.YamlDotNet.Analyzers.StaticGenerator"/>
15-
<PackageReference Include="YamlDotNet"/>
1615
<PackageReference Include="SoftCircuits.IniFileParser" />
1716
<PackageReference Include="System.IO.Abstractions" />
1817
</ItemGroup>
18+
1919
</Project>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.IO.Abstractions;
6+
using Elastic.Documentation.Diagnostics;
7+
8+
namespace Elastic.Documentation;
9+
10+
public interface IDocumentationContext
11+
{
12+
DiagnosticsCollector Collector { get; }
13+
IDirectoryInfo DocumentationSourceDirectory { get; }
14+
GitCheckoutInformation Git { get; }
15+
IFileSystem ReadFileSystem { get; }
16+
IFileSystem WriteFileSystem { get; }
17+
IFileInfo ConfigurationPath { get; }
18+
}
19+
20+
public static class DocumentationContextExtensions
21+
{
22+
public static void EmitError(this IDocumentationContext context, IFileInfo file, string message, Exception? e = null) =>
23+
context.Collector.EmitError(file, message, e);
24+
25+
public static void EmitWarning(this IDocumentationContext context, IFileInfo file, string message) =>
26+
context.Collector.EmitWarning(file, message);
27+
28+
}

src/Elastic.Markdown/IO/HistoryMapping/HistoryMapper.cs renamed to Elastic.Documentation/Legacy/ILegacyUrlMapper.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5-
namespace Elastic.Markdown.IO.HistoryMapping;
5+
namespace Elastic.Documentation.Legacy;
66

77
public record LegacyPageMapping(string Url, string Version);
88

9-
public interface IHistoryMapper
9+
public interface ILegacyUrlMapper
1010
{
1111
LegacyPageMapping? MapLegacyUrl(IReadOnlyCollection<string>? mappedPages);
1212
}
1313

14-
public record BypassHistoryMapper : IHistoryMapper
14+
public record NoopLegacyUrlMapper : ILegacyUrlMapper
1515
{
1616
public LegacyPageMapping? MapLegacyUrl(IReadOnlyCollection<string>? mappedPages) => null;
1717
}

Elastic.Documentation/LinkReference.cs renamed to Elastic.Documentation/Links/LinkReference.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using System.Text.Json.Serialization;
77
using Elastic.Documentation.Serialization;
88

9-
namespace Elastic.Documentation;
9+
namespace Elastic.Documentation.Links;
1010

1111
public record LinkMetadata
1212
{

Elastic.Documentation/Links/LinkIndex.cs renamed to Elastic.Documentation/Links/LinkReferenceRegistry.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,23 @@
88

99
namespace Elastic.Documentation.Links;
1010

11-
public record LinkIndex
11+
public record LinkReferenceRegistry
1212
{
13-
[JsonPropertyName("repositories")] public required Dictionary<string, Dictionary<string, LinkIndexEntry>> Repositories { get; init; }
13+
/// Map of branch to <see cref="LinkRegistryEntry"/>
14+
[JsonPropertyName("repositories")]
15+
public required Dictionary<string, Dictionary<string, LinkRegistryEntry>> Repositories { get; init; }
1416

15-
public static LinkIndex Deserialize(Stream json) =>
16-
JsonSerializer.Deserialize(json, SourceGenerationContext.Default.LinkIndex)!;
17+
public static LinkReferenceRegistry Deserialize(Stream json) =>
18+
JsonSerializer.Deserialize(json, SourceGenerationContext.Default.LinkReferenceRegistry)!;
1719

18-
public static LinkIndex Deserialize(string json) =>
19-
JsonSerializer.Deserialize(json, SourceGenerationContext.Default.LinkIndex)!;
20+
public static LinkReferenceRegistry Deserialize(string json) =>
21+
JsonSerializer.Deserialize(json, SourceGenerationContext.Default.LinkReferenceRegistry)!;
2022

21-
public static string Serialize(LinkIndex index) =>
22-
JsonSerializer.Serialize(index, SourceGenerationContext.Default.LinkIndex);
23+
public static string Serialize(LinkReferenceRegistry referenceRegistry) =>
24+
JsonSerializer.Serialize(referenceRegistry, SourceGenerationContext.Default.LinkReferenceRegistry);
2325
}
2426

25-
public record LinkIndexEntry
27+
public record LinkRegistryEntry
2628
{
2729
[JsonPropertyName("repository")]
2830
public required string Repository { get; init; }

Elastic.Documentation/Serialization/SourceGenerationContext.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ namespace Elastic.Documentation.Serialization;
1414
[JsonSerializable(typeof(GenerationState))]
1515
[JsonSerializable(typeof(LinkReference))]
1616
[JsonSerializable(typeof(GitCheckoutInformation))]
17-
[JsonSerializable(typeof(LinkIndex))]
18-
[JsonSerializable(typeof(LinkIndexEntry))]
17+
[JsonSerializable(typeof(LinkReferenceRegistry))]
18+
[JsonSerializable(typeof(LinkRegistryEntry))]
1919
public sealed partial class SourceGenerationContext : JsonSerializerContext;

docs-builder.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "validate-path-prefixes-loca
8080
EndProject
8181
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Documentation", "Elastic.Documentation\Elastic.Documentation.csproj", "{09CE30F6-013A-49ED-B3D6-60AFA84682AC}"
8282
EndProject
83+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Documentation.Configuration", "src\Elastic.Documentation.Configuration\Elastic.Documentation.Configuration.csproj", "{CD94F9E4-7FCD-4152-81F1-4288C6B75367}"
84+
EndProject
8385
Global
8486
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8587
Debug|Any CPU = Debug|Any CPU
@@ -137,6 +139,10 @@ Global
137139
{09CE30F6-013A-49ED-B3D6-60AFA84682AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
138140
{09CE30F6-013A-49ED-B3D6-60AFA84682AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
139141
{09CE30F6-013A-49ED-B3D6-60AFA84682AC}.Release|Any CPU.Build.0 = Release|Any CPU
142+
{CD94F9E4-7FCD-4152-81F1-4288C6B75367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
143+
{CD94F9E4-7FCD-4152-81F1-4288C6B75367}.Debug|Any CPU.Build.0 = Debug|Any CPU
144+
{CD94F9E4-7FCD-4152-81F1-4288C6B75367}.Release|Any CPU.ActiveCfg = Release|Any CPU
145+
{CD94F9E4-7FCD-4152-81F1-4288C6B75367}.Release|Any CPU.Build.0 = Release|Any CPU
140146
EndGlobalSection
141147
GlobalSection(NestedProjects) = preSolution
142148
{4D198E25-C211-41DC-9E84-B15E89BD7048} = {BE6011CC-1200-4957-B01F-FCCA10C5CF5A}
@@ -156,5 +162,6 @@ Global
156162
{C559D52D-100B-4B2B-BE87-2344D835761D} = {4894063D-0DEF-4B7E-97D0-0D0A5B85C608}
157163
{BB789671-B262-43DD-91DB-39F9186B8257} = {245023D2-D3CA-47B9-831D-DAB91A2FFDC7}
158164
{09CE30F6-013A-49ED-B3D6-60AFA84682AC} = {BE6011CC-1200-4957-B01F-FCCA10C5CF5A}
165+
{CD94F9E4-7FCD-4152-81F1-4288C6B75367} = {BE6011CC-1200-4957-B01F-FCCA10C5CF5A}
159166
EndGlobalSection
160167
EndGlobal

0 commit comments

Comments
 (0)