Skip to content

Commit b5a6121

Browse files
committed
Add extensions to Roslyn primitive analyser config options & dir helper
1 parent d571102 commit b5a6121

2 files changed

Lines changed: 125 additions & 0 deletions

File tree

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System;
2+
using System.Linq;
3+
4+
namespace Riverside.CompilerPlatform.Extensions;
5+
6+
/// <summary>
7+
/// Provides extension methods for reading typed values from <see cref="AnalyzerConfigOptions"/>.
8+
/// </summary>
9+
public static class AnalyzerConfigOptionsExtensions
10+
{
11+
/// <summary>
12+
/// Returns the string value for <paramref name="key"/>, or <see langword="null"/> if the key is absent or whitespace.
13+
/// </summary>
14+
/// <param name="options">The analyser config options to read from.</param>
15+
/// <param name="key">The property key, typically prefixed with <c>build_property.</c>.</param>
16+
/// <returns>The trimmed string value, or <see langword="null"/>.</returns>
17+
public static string? GetString(this AnalyzerConfigOptions options, string key)
18+
{
19+
options.TryGetValue(key, out var value);
20+
return string.IsNullOrWhiteSpace(value) ? null : value;
21+
}
22+
23+
/// <summary>
24+
/// Returns a nullable <see cref="bool"/> for <paramref name="key"/>.
25+
/// Returns <see langword="null"/> when the key is absent, empty, or not a valid boolean string.
26+
/// </summary>
27+
/// <param name="options">The analyzer config options to read from.</param>
28+
/// <param name="key">The property key.</param>
29+
/// <returns>The parsed boolean, or <see langword="null"/>.</returns>
30+
public static bool? GetNullableBool(this AnalyzerConfigOptions options, string key)
31+
{
32+
var value = options.GetString(key);
33+
return value is not null && bool.TryParse(value, out var result) ? result : null;
34+
}
35+
36+
/// <summary>
37+
/// Returns a nullable <typeparamref name="TEnum"/> for <paramref name="key"/>, parsed case-insensitively.
38+
/// Returns <see langword="null"/> when the key is absent, empty, or does not map to a valid enum member.
39+
/// </summary>
40+
/// <typeparam name="TEnum">The enum type to parse into.</typeparam>
41+
/// <param name="options">The analyser config options to read from.</param>
42+
/// <param name="key">The property key.</param>
43+
/// <returns>The parsed enum value, or <see langword="null"/>.</returns>
44+
public static TEnum? GetNullableEnum<TEnum>(this AnalyzerConfigOptions options, string key)
45+
where TEnum : struct, Enum
46+
{
47+
var value = options.GetString(key);
48+
return value is not null && Enum.TryParse<TEnum>(value, ignoreCase: true, out var result) ? result : null;
49+
}
50+
51+
/// <summary>
52+
/// Returns a <see cref="string"/>[] by splitting <paramref name="key"/>'s value on the <c>|</c> character.
53+
/// Empty or whitespace-only segments are discarded.
54+
/// Returns <see langword="null"/> when the key is absent, empty, or yields no usable segments.
55+
/// </summary>
56+
/// <param name="options">The analyser config options to read from.</param>
57+
/// <param name="key">The property key.</param>
58+
/// <returns>A non-empty trimmed array of segments, or <see langword="null"/>.</returns>
59+
public static string[]? GetPipeSeparatedArray(this AnalyzerConfigOptions options, string key)
60+
{
61+
var value = options.GetString(key);
62+
if (value is null)
63+
return null;
64+
var parts = value.Split('|')
65+
.Select(p => p.Trim())
66+
.Where(p => p.Length > 0)
67+
.ToArray();
68+
return parts.Length > 0 ? parts : null;
69+
}
70+
71+
/// <summary>
72+
/// Returns a <typeparamref name="TEnum"/>[] by splitting <paramref name="key"/>'s value on <c>|</c> and parsing each segment case-insensitively.
73+
/// Segments that do not match a valid enum member are silently skipped.
74+
/// </summary>
75+
/// <typeparam name="TEnum">The enum type to parse each segment into.</typeparam>
76+
/// <param name="options">The analyser config options to read from.</param>
77+
/// <param name="key">The property key.</param>
78+
/// <returns>A non-empty array of parsed enum values, or <see langword="null"/> when the <paramref name="key"/> is absent, empty, or yields no valid members.</returns>
79+
public static TEnum[]? GetPipeSeparatedEnumArray<TEnum>(this AnalyzerConfigOptions options, string key)
80+
where TEnum : struct, Enum
81+
{
82+
var raw = options.GetPipeSeparatedArray(key);
83+
if (raw is null)
84+
return null;
85+
var parsed = raw
86+
.Select(s => (ok: Enum.TryParse<TEnum>(s, ignoreCase: true, out var v), val: v))
87+
.Where(t => t.ok)
88+
.Select(t => t.val)
89+
.ToArray();
90+
return parsed.Length > 0 ? parsed : null;
91+
}
92+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using System.IO;
3+
4+
namespace Riverside.CompilerPlatform.Helpers;
5+
6+
/// <summary>
7+
/// Provides utility methods for common directory operations.
8+
/// </summary>
9+
public static class DirectoryHelpers
10+
{
11+
/// <summary>
12+
/// Deletes <paramref name="path"/> and all of its contents recursively, suppressing any exception that occurs.
13+
/// </summary>
14+
/// <param name="path">The directory to delete.</param>
15+
public static void TryDelete(string path)
16+
{
17+
try { if (Directory.Exists(path)) Directory.Delete(path, recursive: true); }
18+
catch { }
19+
}
20+
21+
/// <summary>
22+
/// Creates a uniquely named subdirectory under <paramref name="basePath"/> and returns its full path.
23+
/// The subdirectory name is a compact <see cref="Guid"/> with no formatting characters.
24+
/// </summary>
25+
/// <param name="basePath">The parent directory. Created if it does not already exist.</param>
26+
/// <returns>The full path of the newly created temporary directory.</returns>
27+
public static string CreateTemporary(string basePath)
28+
{
29+
var path = Path.Combine(basePath, Guid.NewGuid().ToString("N"));
30+
Directory.CreateDirectory(path);
31+
return path;
32+
}
33+
}

0 commit comments

Comments
 (0)