Skip to content

Commit c780b3c

Browse files
[build] Rework examples
1 parent 3f890fd commit c780b3c

File tree

4 files changed

+229
-131
lines changed

4 files changed

+229
-131
lines changed

build/BenchmarkDotNet.Build/CommandLineParser.cs

Lines changed: 80 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -108,78 +108,73 @@ private void PrintHelp()
108108

109109
WriteLine();
110110

111-
WriteHeader("Examples:");
111+
PrintExamples(GetTasks().SelectMany(task => task.HelpInfo.Examples));
112112

113-
WritePrefix();
114-
Write(CallScriptName + " ");
115-
WriteTask("restore");
116-
WriteLine();
113+
PrintOptions(baseOptions);
117114

118-
WritePrefix();
119-
Write(CallScriptName + " ");
120-
WriteTask("build ");
121-
WriteOption("/p:");
122-
WriteArg("Configuration");
123-
WriteOption("=");
124-
WriteArg("Debug");
125-
WriteLine();
115+
WriteHeader("Tasks:");
116+
var taskWidth = GetTaskNames().Max(name => name.Length) + 3;
117+
foreach (var (taskName, taskDescription, _) in GetTasks())
118+
{
119+
if (taskName.Equals("Default", StringComparison.OrdinalIgnoreCase))
120+
continue;
126121

127-
WritePrefix();
128-
Write(CallScriptName + " ");
129-
WriteTask("pack ");
130-
WriteOption("/p:");
131-
WriteArg("VersionPrefix");
132-
WriteOption("=");
133-
WriteArg("0.1.1729");
134-
WriteOption(" /p:");
135-
WriteArg("VersionSuffix");
136-
WriteOption("=");
137-
WriteArg("preview");
138-
WriteLine();
122+
WriteTask(" " + taskName.PadRight(taskWidth));
123+
Write(taskDescription);
139124

140-
WritePrefix();
141-
Write(CallScriptName + " ");
142-
WriteTask("unit-tests ");
143-
WriteOption("--exclusive --verbosity ");
144-
WriteArg("Diagnostic");
145-
WriteLine();
125+
WriteLine();
126+
}
127+
}
128+
129+
private void PrintTaskHelp(string taskName)
130+
{
131+
var taskType = typeof(BuildContext).Assembly
132+
.GetTypes()
133+
.Where(type => type.IsSubclassOf(typeof(FrostingTask<BuildContext>)) && !type.IsAbstract)
134+
.First(type => Is(type.GetCustomAttribute<TaskNameAttribute>()?.Name, taskName));
135+
taskName = taskType.GetCustomAttribute<TaskNameAttribute>()!.Name;
136+
var taskDescription = taskType.GetCustomAttribute<TaskDescriptionAttribute>()?.Description ?? "";
137+
var helpInfo = GetHelpInfo(taskType);
138+
139+
WriteHeader("Description:");
146140

147141
WritePrefix();
148-
Write(CallScriptName + " ");
149-
WriteTask("docs-update ");
150-
WriteOption("--depth ");
151-
WriteArg("3");
142+
WriteLine(!string.IsNullOrWhiteSpace(taskDescription)
143+
? $"Task '{taskName}': {taskDescription}"
144+
: $"Task '{taskName}'");
145+
146+
if (string.IsNullOrWhiteSpace(helpInfo.Description))
147+
foreach (var line in helpInfo.Description.Split('\n', StringSplitOptions.RemoveEmptyEntries))
148+
{
149+
WritePrefix();
150+
WriteLine(line.Trim());
151+
}
152+
152153
WriteLine();
153154

155+
WriteHeader("Usage:");
156+
154157
WritePrefix();
155158
Write(CallScriptName + " ");
156-
WriteTask("docs-build ");
157-
WriteOption("--preview ");
159+
WriteTask(taskName + " ");
160+
WriteOption("[OPTIONS]");
158161
WriteLine();
159162

160163
WriteLine();
161164

162-
PrintOptions(baseOptions);
165+
PrintExamples(helpInfo.Examples);
163166

164-
WriteHeader("Tasks:");
165-
var taskWidth = GetTaskNames().Max(name => name.Length) + 3;
166-
foreach (var (taskName, taskDescription) in GetTasks())
167-
{
168-
if (taskName.Equals("Default", StringComparison.OrdinalIgnoreCase))
169-
continue;
167+
PrintOptions(helpInfo.Options.Concat(baseOptions).ToArray());
170168

171-
if (taskDescription.StartsWith("OBSOLETE", StringComparison.OrdinalIgnoreCase))
172-
{
173-
WriteObsolete(" " + taskName.PadRight(taskWidth));
174-
WriteObsolete(taskDescription);
175-
}
176-
else
169+
if (helpInfo.EnvironmentVariables.Any())
170+
{
171+
WriteHeader("Environment variables:");
172+
foreach (var variable in helpInfo.EnvironmentVariables)
177173
{
178-
WriteTask(" " + taskName.PadRight(taskWidth));
179-
Write(taskDescription);
174+
WritePrefix();
175+
WriteOption(variable);
176+
WriteLine();
180177
}
181-
182-
WriteLine();
183178
}
184179
}
185180

@@ -242,88 +237,64 @@ int GetWidth(IOption option)
242237
WriteLine();
243238
}
244239

245-
private void PrintTaskHelp(string taskName)
240+
private void PrintExamples(IEnumerable<Example> examples)
246241
{
247-
var taskType = typeof(BuildContext).Assembly
248-
.GetTypes()
249-
.Where(type => type.IsSubclassOf(typeof(FrostingTask<BuildContext>)) && !type.IsAbstract)
250-
.First(type => Is(type.GetCustomAttribute<TaskNameAttribute>()?.Name, taskName));
251-
taskName = taskType.GetCustomAttribute<TaskNameAttribute>()!.Name;
252-
var taskDescription = taskType.GetCustomAttribute<TaskDescriptionAttribute>()?.Description ?? "";
253-
var taskInstance = Activator.CreateInstance(taskType);
254-
var helpInfo = taskInstance is IHelpProvider helpProvider ? helpProvider.GetHelp() : new HelpInfo();
255-
256-
WriteHeader("Description:");
257-
258-
WritePrefix();
259-
WriteLine($"Task '{taskName}'");
260-
if (!string.IsNullOrWhiteSpace(taskDescription))
261-
{
262-
WritePrefix();
263-
WriteLine(taskDescription);
264-
}
265-
266-
if (string.IsNullOrWhiteSpace(helpInfo.Description))
267-
foreach (var line in helpInfo.Description.Split('\n', StringSplitOptions.RemoveEmptyEntries))
268-
{
269-
WritePrefix();
270-
WriteLine(line.Trim());
271-
}
272-
273-
WriteLine();
274-
275-
WriteHeader("Usage:");
276-
277-
WritePrefix();
278-
Write(CallScriptName + " ");
279-
WriteTask(taskName + " ");
280-
WriteOption("[OPTIONS]");
281-
WriteLine();
282-
283-
WriteLine();
284-
285242
WriteHeader("Examples:");
286243

287-
WritePrefix();
288-
Write(ScriptName + " ");
289-
WriteTask(taskName);
290-
WriteLine();
291-
292-
WriteLine();
293-
294-
PrintOptions(helpInfo.Options.Concat(baseOptions).ToArray());
295-
296-
if (helpInfo.EnvironmentVariables.Any())
244+
foreach (var example in examples)
297245
{
298-
WriteHeader("Environment variables:");
299-
foreach (var variable in helpInfo.EnvironmentVariables)
246+
WritePrefix();
247+
Write(CallScriptName + " ");
248+
WriteTask(example.TaskName + " ");
249+
foreach (var (name, value, isMsBuild) in example.Arguments)
300250
{
301-
WritePrefix();
302-
WriteOption(variable);
251+
if (isMsBuild)
252+
{
253+
WriteOption("/p:");
254+
WriteArg(name);
255+
WriteOption("=");
256+
WriteArg(value + " ");
257+
}
258+
else
259+
{
260+
WriteOption(name + " ");
261+
if (value != null)
262+
WriteArg(value + " ");
263+
}
303264
}
304265

305266
WriteLine();
306267
}
268+
269+
WriteLine();
307270
}
308271

309272
private static HashSet<string> GetTaskNames()
310273
{
311274
return GetTasks().Select(task => task.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
312275
}
313276

314-
private static List<(string Name, string Description)> GetTasks()
277+
private static List<(string Name, string Description, HelpInfo HelpInfo)> GetTasks()
315278
{
316279
return typeof(BuildContext).Assembly
317280
.GetTypes()
318281
.Where(type => type.IsSubclassOf(typeof(FrostingTask<BuildContext>)) && !type.IsAbstract)
319282
.Select(type => (
320283
Name: type.GetCustomAttribute<TaskNameAttribute>()?.Name ?? "",
321-
Description: type.GetCustomAttribute<TaskDescriptionAttribute>()?.Description ?? ""
284+
Description: type.GetCustomAttribute<TaskDescriptionAttribute>()?.Description ?? "",
285+
HelpInfo: GetHelpInfo(type)
322286
))
323287
.Where(task => task.Name != "")
324288
.ToList();
325289
}
326290

291+
private static HelpInfo GetHelpInfo(Type taskType)
292+
{
293+
return Activator.CreateInstance(taskType) is IHelpProvider helpProvider
294+
? helpProvider.GetHelp()
295+
: new HelpInfo();
296+
}
297+
327298
private static bool Is(string? arg, params string[] values) =>
328299
values.Any(value => value.Equals(arg, StringComparison.OrdinalIgnoreCase));
329300

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System.Collections.Generic;
2+
using BenchmarkDotNet.Build.Options;
3+
4+
namespace BenchmarkDotNet.Build;
5+
6+
public class Example
7+
{
8+
private readonly List<Argument> arguments = new();
9+
10+
public string TaskName { get; }
11+
public IReadOnlyCollection<Argument> Arguments => arguments;
12+
13+
public Example(string taskName)
14+
{
15+
TaskName = taskName;
16+
}
17+
18+
public Example WithArgument(string name, string? value = null)
19+
{
20+
arguments.Add(new Argument(name, value, false));
21+
return this;
22+
}
23+
24+
public Example WithMsBuildArgument(string name, string value)
25+
{
26+
arguments.Add(new Argument(name, value, true));
27+
return this;
28+
}
29+
30+
public Example WithArgument(IOption option, string? value = null)
31+
{
32+
arguments.Add(new Argument(option.CommandLineName, value, false));
33+
return this;
34+
}
35+
36+
37+
public record Argument(string Name, string? Value, bool IsMsBuild);
38+
}

build/BenchmarkDotNet.Build/HelpInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ public class HelpInfo
88
public string Description { get; init; } = "";
99
public IOption[] Options { get; init; } = Array.Empty<IOption>();
1010
public string[] EnvironmentVariables { get; init; } = Array.Empty<string>();
11+
public Example[] Examples { get; init; } = Array.Empty<Example>();
1112
}

0 commit comments

Comments
 (0)