in src/Elastic.Documentation.Configuration/YamlStreamReader.cs [19:204]
public class YamlStreamReader(IFileInfo source, IDiagnosticsCollector collector)
{
private IFileInfo Source { get; init; } = source;
private IDiagnosticsCollector Collector { get; init; } = collector;
public IEnumerable<YamlToplevelKey> Read()
{
// Load the stream
var yaml = new YamlStream();
var textReader = Source.FileSystem.File.OpenText(Source.FullName);
yaml.Load(textReader);
if (yaml.Documents.Count == 0)
{
Collector.EmitWarning(Source, "empty redirect file");
yield break;
}
// Examine the stream
var mapping = (YamlMappingNode)yaml.Documents[0].RootNode;
foreach (var entry in mapping.Children)
{
var key = (entry.Key as YamlScalarNode)?.Value;
if (key is null)
continue;
yield return new YamlToplevelKey { Key = key, Entry = entry };
}
}
public string? ReadString(KeyValuePair<YamlNode, YamlNode> entry)
{
if (entry.Value is YamlScalarNode scalar)
return scalar.Value;
if (entry.Key is YamlScalarNode scalarKey)
{
var key = scalarKey.Value;
EmitError($"'{key}' is not a string", entry.Key);
return null;
}
EmitError($"'{entry.Key}' is not a string", entry.Key);
return null;
}
public static string[] ReadStringArray(KeyValuePair<YamlNode, YamlNode> entry)
{
var values = new List<string>();
if (entry.Value is not YamlSequenceNode sequence)
return [.. values];
foreach (var entryValue in sequence.Children.OfType<YamlScalarNode>())
{
if (entryValue.Value is not null)
values.Add(entryValue.Value);
}
return [.. values];
}
public bool ReadObjectDictionary(KeyValuePair<YamlNode, YamlNode> entry, [NotNullWhen(true)] out YamlMappingNode? mapping)
{
mapping = null;
if (entry.Value is not YamlMappingNode m)
{
if (entry.Key is YamlScalarNode scalarKey)
{
var key = scalarKey.Value;
EmitWarning($"'{key}' is not a dictionary");
}
else
EmitWarning($"'{entry.Key}' is not a dictionary");
return false;
}
mapping = m;
return true;
}
public Dictionary<string, string?> ReadDictionaryNullValue(KeyValuePair<YamlNode, YamlNode> entry)
{
var dictionary = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
if (entry.Value is YamlScalarNode shortSyntax && shortSyntax.Value is not null)
{
if (shortSyntax.Value is "!")
return new Dictionary<string, string?> { { "!", "!" } };
EmitError($"'{shortSyntax.Value}' is not a valid redirect anchor value", entry.Key);
return [];
}
if (entry.Value is not YamlMappingNode mapping)
{
if (entry.Key is YamlScalarNode scalarKey)
{
var key = scalarKey.Value;
EmitWarning($"'{key}' is not a dictionary");
}
else
EmitWarning($"'{entry.Key}' is not a dictionary");
return dictionary;
}
foreach (var entryValue in mapping.Children)
{
if (entryValue.Key is not YamlScalarNode scalar || scalar.Value is null)
continue;
var key = scalar.Value;
var value = ReadString(entryValue);
if (value is "null" or "")
dictionary.Add(key, null);
else if (value is not null)
dictionary.Add(key, value);
}
return dictionary;
}
public Dictionary<string, string> ReadDictionary(KeyValuePair<YamlNode, YamlNode> entry)
{
var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
if (entry.Value is not YamlMappingNode mapping)
{
if (entry.Key is YamlScalarNode scalarKey)
{
var key = scalarKey.Value;
EmitWarning($"'{key}' is not a dictionary");
}
else
EmitWarning($"'{entry.Key}' is not a dictionary");
return dictionary;
}
foreach (var entryValue in mapping.Children)
{
if (entryValue.Key is not YamlScalarNode scalar || scalar.Value is null)
continue;
var key = scalar.Value;
var value = ReadString(entryValue);
if (value is not null)
dictionary.Add(key, value);
}
return dictionary;
}
public void EmitError(string message, YamlNode? node) =>
EmitError(message, node?.Start, node?.End, (node as YamlScalarNode)?.Value?.Length);
public void EmitWarning(string message, YamlNode? node) =>
EmitWarning(message, node?.Start, node?.End, (node as YamlScalarNode)?.Value?.Length);
public void EmitError(string message, Exception e) =>
Collector.EmitError(Source.FullName, message, e);
private void EmitError(string message, Mark? start = null, Mark? end = null, int? length = null)
{
length ??= start.HasValue && end.HasValue ? (int)start.Value.Column - (int)end.Value.Column : null;
var d = new Diagnostic
{
Severity = Severity.Error,
File = Source.FullName,
Message = message,
Line = start.HasValue ? (int)start.Value.Line : null,
Column = start.HasValue ? (int)start.Value.Column : null,
Length = length
};
Collector.Write(d);
}
public void EmitWarning(string message, Mark? start = null, Mark? end = null, int? length = null)
{
length ??= start.HasValue && end.HasValue ? (int)start.Value.Column - (int)end.Value.Column : null;
var d = new Diagnostic
{
Severity = Severity.Warning,
File = Source.FullName,
Message = message,
Line = start.HasValue ? (int)start.Value.Line : null,
Column = start.HasValue ? (int)start.Value.Column : null,
Length = length
};
Collector.Write(d);
}
}