Skip to content

Commit 1dd8c27

Browse files
authored
Fix API Diff args + async (#49164)
1 parent 2310f2b commit 1dd8c27

File tree

6 files changed

+41
-31
lines changed

6 files changed

+41
-31
lines changed

src/Compatibility/ApiDiff/Microsoft.DotNet.ApiDiff.Tool/Program.cs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,96 +18,96 @@ public static class Program
1818

1919
public static async Task Main(string[] args)
2020
{
21-
RootCommand rootCommand = new("genapidiff");
21+
RootCommand rootCommand = new("ApiDiff - Tool for generating a markdown diff of two different versions of the same assembly.");
2222

23-
Option<string> optionBeforeAssembliesFolderPath = new(name: "", aliases: ["--before", "-b"])
23+
Option<string> optionBeforeAssembliesFolderPath = new("--before", "-b")
2424
{
2525
Description = "The path to the folder containing the old (before) assemblies to be included in the diff.",
2626
Arity = ArgumentArity.ExactlyOne,
2727
Required = true
2828
};
2929

30-
Option<string> optionBeforeRefAssembliesFolderPath = new(name: "", aliases: ["--refbefore", "-rb"])
30+
Option<string> optionBeforeRefAssembliesFolderPath = new("--refbefore", "-rb")
3131
{
3232
Description = "The path to the folder containing the references required by old (before) assemblies, not to be included in the diff.",
3333
Arity = ArgumentArity.ExactlyOne,
3434
Required = false
3535
};
3636

37-
Option<string> optionAfterAssembliesFolderPath = new(name: "", aliases: ["--after", "-a"])
37+
Option<string> optionAfterAssembliesFolderPath = new("--after", "-a")
3838
{
3939
Description = "The path to the folder containing the new (after) assemblies to be included in the diff.",
4040
Arity = ArgumentArity.ExactlyOne,
4141
Required = true
4242
};
4343

44-
Option<string> optionAfterRefAssembliesFolderPath = new(name: "", aliases: ["--refafter", "-ra"])
44+
Option<string> optionAfterRefAssembliesFolderPath = new("--refafter", "-ra")
4545
{
4646
Description = "The path to the folder containing references required by the new (after) reference assemblies, not to be included in the diff.",
4747
Arity = ArgumentArity.ExactlyOne,
4848
Required = false
4949
};
5050

51-
Option<string> optionOutputFolderPath = new(name: "", aliases: ["--output", "-o"])
51+
Option<string> optionOutputFolderPath = new("--output", "-o")
5252
{
5353
Description = "The path to the output folder.",
5454
Arity = ArgumentArity.ExactlyOne,
5555
Required = true
5656
};
5757

58-
Option<string> optionBeforeFriendlyName = new(name: "", aliases: ["--beforeFriendlyName", "-bfn"])
58+
Option<string> optionBeforeFriendlyName = new("--beforeFriendlyName", "-bfn")
5959
{
6060
Description = "The friendly name to describe the 'before' assembly.",
6161
Arity = ArgumentArity.ExactlyOne,
6262
Required = true
6363
};
6464

65-
Option<string> optionAfterFriendlyName = new(name: "", aliases: ["--afterFriendlyName", "-afn"])
65+
Option<string> optionAfterFriendlyName = new("--afterFriendlyName", "-afn")
6666
{
6767
Description = "The friendly name to describe the 'after' assembly.",
6868
Arity = ArgumentArity.ExactlyOne,
6969
Required = true
7070
};
7171

72-
Option<string> optionTableOfContentsTitle = new(name: "", aliases: ["--tableOfContentsTitle", "-tc"])
72+
Option<string> optionTableOfContentsTitle = new("--tableOfContentsTitle", "-tc")
7373
{
7474
Description = $"The optional title of the markdown table of contents file that is placed in the output folder.",
75-
Arity = ArgumentArity.ZeroOrMore,
75+
Arity = ArgumentArity.ExactlyOne,
7676
Required = false,
7777
DefaultValueFactory = _ => "api_diff"
7878
};
7979

80-
Option<FileInfo[]?> optionFilesWithAssembliesToExclude = new(name: "", aliases: ["--assembliesToExclude", "-eas"])
80+
Option<FileInfo[]?> optionFilesWithAssembliesToExclude = new("--assembliesToExclude", "-eas")
8181
{
8282
Description = "An optional array of filepaths, each containing a list of assemblies that should be excluded from the diff. Each file should contain one assembly name per line, with no extensions.",
8383
Arity = ArgumentArity.ZeroOrMore,
8484
Required = false,
8585
DefaultValueFactory = _ => null
8686
};
8787

88-
Option<FileInfo[]?> optionFilesWithAttributesToExclude = new(name: "", aliases: ["--attributesToExclude", "-eattrs"])
88+
Option<FileInfo[]?> optionFilesWithAttributesToExclude = new("--attributesToExclude", "-eattrs")
8989
{
9090
Description = $"An optional array of filepaths, each containing a list of attributes to exclude from the diff. Each file should contain one API full name per line. You can either modify the default file '{AttributesToExcludeDefaultFileName}' to add your own attributes, or include additional files using this command line option.",
9191
Arity = ArgumentArity.ZeroOrMore,
9292
Required = false,
9393
DefaultValueFactory = _ => [new FileInfo(AttributesToExcludeDefaultFileName)]
9494
};
9595

96-
Option<FileInfo[]?> optionFilesWithApisToExclude = new(name: "", aliases: ["--apisToExclude", "-eapis"])
96+
Option<FileInfo[]?> optionFilesWithApisToExclude = new("--apisToExclude", "-eapis")
9797
{
9898
Description = "An optional array of filepaths, each containing a list of APIs to exclude from the diff. Each file should contain one API full name per line.",
9999
Arity = ArgumentArity.ZeroOrMore,
100100
Required = false,
101101
DefaultValueFactory = _ => null
102102
};
103103

104-
Option<bool> optionAddPartialModifier = new(name: "", aliases: ["--addPartialModifier", "-apm"])
104+
Option<bool> optionAddPartialModifier = new("--addPartialModifier", "-apm")
105105
{
106106
Description = "Add the 'partial' modifier to types.",
107107
DefaultValueFactory = _ => false
108108
};
109109

110-
Option<bool> optionAttachDebugger = new(name: "", aliases: ["--attachDebugger", "-d"])
110+
Option<bool> optionAttachDebugger = new("--attachDebugger", "-d")
111111
{
112112
Description = "Stops the tool at startup, prints the process ID and waits for a debugger to attach.",
113113
DefaultValueFactory = _ => false
@@ -128,9 +128,9 @@ public static async Task Main(string[] args)
128128
rootCommand.Options.Add(optionAddPartialModifier);
129129
rootCommand.Options.Add(optionAttachDebugger);
130130

131-
rootCommand.SetAction(async (ParseResult result) =>
131+
rootCommand.SetAction(async (ParseResult result, CancellationToken cancellationToken) =>
132132
{
133-
DiffConfiguration c = new(
133+
DiffConfiguration diffConfig = new(
134134
BeforeAssembliesFolderPath: result.GetValue(optionBeforeAssembliesFolderPath) ?? throw new NullReferenceException("Null before assemblies directory"),
135135
BeforeAssemblyReferencesFolderPath: result.GetValue(optionBeforeRefAssembliesFolderPath),
136136
AfterAssembliesFolderPath: result.GetValue(optionAfterAssembliesFolderPath) ?? throw new NullReferenceException("Null after assemblies directory"),
@@ -145,13 +145,15 @@ public static async Task Main(string[] args)
145145
AddPartialModifier: result.GetValue(optionAddPartialModifier),
146146
AttachDebugger: result.GetValue(optionAttachDebugger)
147147
);
148-
await HandleCommandAsync(c).ConfigureAwait(false);
148+
await HandleCommandAsync(diffConfig, cancellationToken).ConfigureAwait(false);
149149
});
150150
await rootCommand.Parse(args).InvokeAsync();
151151
}
152152

153-
private static Task HandleCommandAsync(DiffConfiguration diffConfig)
153+
private static Task HandleCommandAsync(DiffConfiguration diffConfig, CancellationToken cancellationToken = default)
154154
{
155+
cancellationToken.ThrowIfCancellationRequested();
156+
155157
var log = new ConsoleLog(MessageImportance.Normal);
156158

157159
string assembliesToExclude = string.Join(", ", diffConfig.FilesWithAssembliesToExclude?.Select(a => a.FullName) ?? []);
@@ -197,7 +199,7 @@ private static Task HandleCommandAsync(DiffConfiguration diffConfig)
197199
diagnosticOptions: null // TODO: If needed, add CLI option to pass specific diagnostic options
198200
);
199201

200-
return diffGenerator.RunAsync();
202+
return diffGenerator.RunAsync(cancellationToken);
201203
}
202204

203205
private static void WaitForDebugger()

src/Compatibility/ApiDiff/Microsoft.DotNet.ApiDiff/FileOutputDiffGenerator.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,13 @@ internal FileOutputDiffGenerator(ILog log,
8787
public IReadOnlyDictionary<string, string> Results => _results.AsReadOnly();
8888

8989
/// <inheritdoc/>
90-
public async Task RunAsync()
90+
public async Task RunAsync(CancellationToken cancellationToken)
9191
{
9292
Debug.Assert(_beforeAssembliesFolderPaths.Length == 1);
9393
Debug.Assert(_afterAssembliesFolderPaths.Length == 1);
9494

95+
cancellationToken.ThrowIfCancellationRequested();
96+
9597
(IAssemblySymbolLoader beforeLoader, Dictionary<string, IAssemblySymbol> beforeAssemblySymbols) =
9698
AssemblySymbolLoader.CreateFromFiles(
9799
_log,
@@ -118,7 +120,7 @@ public async Task RunAsync()
118120
_addPartialModifier,
119121
_diagnosticOptions);
120122

121-
await generator.RunAsync().ConfigureAwait(false);
123+
await generator.RunAsync(cancellationToken).ConfigureAwait(false);
122124

123125
// If true, output is disk. Otherwise, it's the Results dictionary.
124126
if (_writeToDisk)
@@ -135,6 +137,8 @@ public async Task RunAsync()
135137

136138
foreach ((string assemblyName, string text) in generator.Results.OrderBy(r => r.Key))
137139
{
140+
cancellationToken.ThrowIfCancellationRequested();
141+
138142
string fileName = $"{_tableOfContentsTitle}_{assemblyName}.md";
139143
tableOfContents.AppendLine($"* [{assemblyName}]({fileName})");
140144

src/Compatibility/ApiDiff/Microsoft.DotNet.ApiDiff/IDiffGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ public interface IDiffGenerator
1313
/// <summary>
1414
/// Asynchronously runs the diff generator and may populate the <see cref="Results"/> dictionary depending on the use case.
1515
/// </summary>
16-
Task RunAsync();
16+
Task RunAsync(CancellationToken cancellationToken);
1717
}

src/Compatibility/ApiDiff/Microsoft.DotNet.ApiDiff/MemoryOutputDiffGenerator.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,23 @@ internal MemoryOutputDiffGenerator(
8585
public IReadOnlyDictionary<string, string> Results => _results.AsReadOnly();
8686

8787
/// <inheritdoc/>
88-
public async Task RunAsync()
88+
public async Task RunAsync(CancellationToken cancellationToken)
8989
{
9090
Stopwatch swRun = Stopwatch.StartNew();
9191

9292
foreach ((string beforeAssemblyName, IAssemblySymbol beforeAssemblySymbol) in _beforeAssemblySymbols)
9393
{
94+
cancellationToken.ThrowIfCancellationRequested();
95+
9496
// Needs to block so the _afterAssemblySymbols dictionary gets updated.
9597
await ProcessBeforeAndAfterAssemblyAsync(beforeAssemblyName, beforeAssemblySymbol).ConfigureAwait(false);
9698
}
9799

98100
// Needs to happen after processing the before and after assemblies and filtering out the existing ones.
99101
foreach ((string afterAssemblyName, IAssemblySymbol afterAssemblySymbol) in _afterAssemblySymbols)
100102
{
103+
cancellationToken.ThrowIfCancellationRequested();
104+
101105
await ProcessNewAssemblyAsync(afterAssemblyName, afterAssemblySymbol).ConfigureAwait(false);
102106
}
103107

test/Microsoft.DotNet.ApiDiff.Tests/Diff.Base.Tests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ protected async Task RunTestAsync(
6161
addPartialModifier,
6262
DiffGeneratorFactory.DefaultDiagnosticOptions);
6363

64-
await generator.RunAsync();
64+
await generator.RunAsync(CancellationToken.None);
6565

6666
foreach ((string expectedAssemblyName, string expectedCode) in expected)
6767
{

test/Microsoft.DotNet.ApiDiff.Tests/Diff.Disk.Tests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public async Task DiskRead_DiskWrite()
9696
outputFolderPath.DirPath,
9797
writeToDisk: true);
9898

99-
await generator.RunAsync();
99+
await generator.RunAsync(CancellationToken.None);
100100

101101
VerifyDiskWrite(outputFolderPath.DirPath, DefaultTableOfContentsTitle, ExpectedTableOfContents, DefaultExpectedAssemblyMarkdowns);
102102
}
@@ -255,7 +255,7 @@ Lines preceded by a '+' are additions and a '-' indicates removal.
255255
outputFolderPath.DirPath,
256256
writeToDisk: true);
257257

258-
await generator.RunAsync();
258+
await generator.RunAsync(CancellationToken.None);
259259

260260
VerifyDiskWrite(outputFolderPath.DirPath, DefaultTableOfContentsTitle, expectedTableOfContents, expectedAssemblyMarkdowns);
261261
}
@@ -286,7 +286,7 @@ public async Task DiskRead_DiskWrite_ExcludeAssembly()
286286
writeToDisk: true,
287287
filesWithAssembliesToExclude: await GetFileWithListsAsync(root, [DefaultAssemblyName]));
288288

289-
await generator.RunAsync();
289+
await generator.RunAsync(CancellationToken.None);
290290

291291
VerifyDiskWrite(outputFolderPath.FullName, DefaultTableOfContentsTitle, ExpectedEmptyTableOfContents, []);
292292
}
@@ -376,7 +376,7 @@ public class MySubClass
376376
outputFolderPath.DirPath,
377377
writeToDisk: true);
378378

379-
await generator.RunAsync();
379+
await generator.RunAsync(CancellationToken.None);
380380

381381
VerifyDiskWrite(outputFolderPath.DirPath, DefaultTableOfContentsTitle, ExpectedTableOfContents, expectedAssemblyMarkdowns);
382382
}
@@ -401,7 +401,7 @@ public async Task DiskRead_MemoryWrite()
401401
outputFolderPath.DirPath,
402402
writeToDisk: false);
403403

404-
await generator.RunAsync();
404+
await generator.RunAsync(CancellationToken.None);
405405

406406
string tableOfContentsMarkdownFilePath = Path.Join(outputFolderPath.DirPath, $"{DefaultTableOfContentsTitle}.md");
407407
Assert.Contains(tableOfContentsMarkdownFilePath, generator.Results.Keys);
@@ -440,7 +440,7 @@ public async Task DiskRead_MemoryWrite_ExcludeAssembly()
440440
writeToDisk: false,
441441
filesWithAssembliesToExclude: await GetFileWithListsAsync(root, [DefaultAssemblyName]));
442442

443-
await generator.RunAsync();
443+
await generator.RunAsync(CancellationToken.None);
444444

445445
string tableOfContentsMarkdownFilePath = Path.Join(outputFolderPath.FullName, $"{DefaultTableOfContentsTitle}.md");
446446
Assert.Contains(tableOfContentsMarkdownFilePath, generator.Results.Keys);

0 commit comments

Comments
 (0)