Skip to content

Commit dc2d806

Browse files
committed
Add code specific for records in memory generator. Move the most debugged method to the top for easier finding.
1 parent 704507c commit dc2d806

File tree

1 file changed

+41
-31
lines changed

1 file changed

+41
-31
lines changed

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

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,35 @@ internal MemoryOutputDiffGenerator(
8282
_endOfLineTrivia = Environment.NewLine == "\r\n" ? SyntaxFactory.CarriageReturnLineFeed : SyntaxFactory.LineFeed;
8383
}
8484

85+
private async Task<(SyntaxNode rootNode, SemanticModel model)> GetAssemblyRootNodeAndModelAsync(IAssemblySymbolLoader loader, IAssemblySymbol assemblySymbol)
86+
{
87+
CSharpAssemblyDocumentGeneratorOptions options = new(loader, _symbolFilter, _attributeSymbolFilter)
88+
{
89+
HideImplicitDefaultConstructors = _hideImplicitDefaultConstructors,
90+
ShouldFormat = true,
91+
ShouldReduce = false,
92+
MetadataReferences = loader.MetadataReferences,
93+
DiagnosticOptions = _diagnosticOptions,
94+
SyntaxRewriters = [
95+
new TypeDeclarationCSharpSyntaxRewriter(_addPartialModifier), // This must be visited BEFORE GlobalPrefixRemover as it depends on the 'global::' prefix to be found
96+
GlobalPrefixRemover.Singleton, // And then call this ASAP afterwards so there are fewer identifiers to visit
97+
PrimitiveSimplificationRewriter.Singleton,
98+
RemoveBodyCSharpSyntaxRewriter.Singleton,
99+
AttributeNameSuffixRemover.Singleton,
100+
SingleLineStatementCSharpSyntaxRewriter.Singleton,
101+
],
102+
AdditionalAnnotations = [Formatter.Annotation] // Formatter is needed to fix some spacing
103+
};
104+
105+
CSharpAssemblyDocumentGenerator docGenerator = new(_log, options);
106+
107+
Document document = await docGenerator.GetDocumentForAssemblyAsync(assemblySymbol).ConfigureAwait(false); // Super hot and resource-intensive path
108+
SyntaxNode root = await document.GetSyntaxRootAsync().ConfigureAwait(false) ?? throw new InvalidOperationException(string.Format(Resources.RootNodeNotFound, assemblySymbol.Name));
109+
SemanticModel model = await document.GetSemanticModelAsync().ConfigureAwait(false) ?? throw new InvalidOperationException(string.Format(Resources.SemanticModelNotFound, assemblySymbol.Name));
110+
111+
return (root, model);
112+
}
113+
85114
/// <inheritdoc/>
86115
public IReadOnlyDictionary<string, string> Results => _results.AsReadOnly();
87116

@@ -174,35 +203,6 @@ public async Task RunAsync()
174203
swRun.Stop();
175204
}
176205

177-
private async Task<(SyntaxNode rootNode, SemanticModel model)> GetAssemblyRootNodeAndModelAsync(IAssemblySymbolLoader loader, IAssemblySymbol assemblySymbol)
178-
{
179-
CSharpAssemblyDocumentGeneratorOptions options = new(loader, _symbolFilter, _attributeSymbolFilter)
180-
{
181-
HideImplicitDefaultConstructors = _hideImplicitDefaultConstructors,
182-
ShouldFormat = false,
183-
ShouldReduce = false,
184-
MetadataReferences = loader.MetadataReferences,
185-
DiagnosticOptions = _diagnosticOptions,
186-
SyntaxRewriters = [
187-
new TypeDeclarationCSharpSyntaxRewriter(_addPartialModifier), // This must be visited BEFORE GlobalPrefixRemover as it depends on the 'global::' prefix to be found
188-
GlobalPrefixRemover.Singleton, // And then call this ASAP afterwards so there are fewer identifiers to visit
189-
PrimitiveSimplificationRewriter.Singleton,
190-
RemoveBodyCSharpSyntaxRewriter.Singleton,
191-
AttributeNameSuffixRemover.Singleton,
192-
SingleLineStatementCSharpSyntaxRewriter.Singleton,
193-
],
194-
AdditionalAnnotations = [Formatter.Annotation] // Formatter is needed to fix some spacing
195-
};
196-
197-
CSharpAssemblyDocumentGenerator docGenerator = new(_log, options);
198-
199-
Document document = await docGenerator.GetDocumentForAssemblyAsync(assemblySymbol).ConfigureAwait(false); // Super hot and resource-intensive path
200-
SyntaxNode root = await document.GetSyntaxRootAsync().ConfigureAwait(false) ?? throw new InvalidOperationException(string.Format(Resources.RootNodeNotFound, assemblySymbol.Name));
201-
SemanticModel model = await document.GetSemanticModelAsync().ConfigureAwait(false) ?? throw new InvalidOperationException(string.Format(Resources.SemanticModelNotFound, assemblySymbol.Name));
202-
203-
return (root, model);
204-
}
205-
206206
private static string GetFinalAssemblyDiff(string assemblyName, string diffText)
207207
{
208208
StringBuilder sbAssembly = new();
@@ -319,7 +319,15 @@ private static ConcurrentDictionary<string, MemberDeclarationSyntax> CollectChil
319319

320320
ConcurrentDictionary<string, MemberDeclarationSyntax> dictionary = [];
321321

322-
if (parentNode is BaseNamespaceDeclarationSyntax)
322+
if (parentNode is RecordDeclarationSyntax record && record.Members.Any())
323+
{
324+
foreach (MemberDeclarationSyntax memberNode in record.ChildNodes().Where(n => n is MemberDeclarationSyntax m && IsPublicOrProtectedOrDestructor(m)).Cast<MemberDeclarationSyntax>())
325+
{
326+
// Note that these could also be nested types
327+
dictionary.TryAdd(GetDocId(memberNode, model), memberNode);
328+
}
329+
}
330+
else if (parentNode is BaseNamespaceDeclarationSyntax)
323331
{
324332
foreach (BaseTypeDeclarationSyntax typeNode in parentNode.ChildNodes().Where(n => n is BaseTypeDeclarationSyntax t && IsPublicOrProtectedOrDestructor(t)).Cast<BaseTypeDeclarationSyntax>())
325333
{
@@ -555,7 +563,7 @@ private string GetCodeWrappedByParent(string diffedChildrenCode, SyntaxNode pare
555563
private static SyntaxNode GetChildlessNode(MemberDeclarationSyntax node)
556564
{
557565
SyntaxNode childlessNode = node.RemoveNodes(node.ChildNodes().Where(
558-
c => c is MemberDeclarationSyntax or BaseTypeDeclarationSyntax or DelegateDeclarationSyntax), SyntaxRemoveOptions.KeepNoTrivia)!;
566+
c => c is MemberDeclarationSyntax or BaseTypeDeclarationSyntax or DelegateDeclarationSyntax), SyntaxRemoveOptions.KeepNoTrivia)!;
559567

560568
return childlessNode.WithLeadingTrivia(node.GetLeadingTrivia());
561569
}
@@ -568,6 +576,7 @@ private string GetDeclarationAndOpeningBraceCode(SyntaxNode childlessNode, Synta
568576

569577
SyntaxNode unclosedNode = childlessNode switch
570578
{
579+
RecordDeclarationSyntax recordDecl => recordDecl.OpenBraceToken.IsMissing ? recordDecl : recordDecl.WithCloseBraceToken(_missingCloseBrace),
571580
BaseTypeDeclarationSyntax typeDecl => typeDecl.WithOpenBraceToken(openBrace)
572581
.WithCloseBraceToken(_missingCloseBrace),
573582

@@ -584,6 +593,7 @@ private string GetClosingBraceCode(SyntaxNode childlessNode, SyntaxTriviaList le
584593
{
585594
SyntaxToken closeBrace = childlessNode switch
586595
{
596+
RecordDeclarationSyntax recordDecl => recordDecl.CloseBraceToken.IsMissing ? _missingCloseBrace : recordDecl.CloseBraceToken,
587597
BaseTypeDeclarationSyntax typeDecl => typeDecl.CloseBraceToken,
588598
NamespaceDeclarationSyntax nsDecl => nsDecl.CloseBraceToken,
589599
_ => throw new InvalidOperationException(string.Format(Resources.UnexpectedNodeType, childlessNode.Kind()))

0 commit comments

Comments
 (0)