8000 [ApiDiff] Implementation of the new ApiDiff that reuses GenAPI features by carlossanlop · Pull Request #46425 · dotnet/sdk · GitHub
[go: up one dir, main page]

Skip to content

[ApiDiff] Implementation of the new ApiDiff that reuses GenAPI features #46425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 71 commits into from
Apr 28, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
2d1dc61
ApiDiff implementation
carlossanlop Feb 1, 2025
36fd38d
Resources
carlossanlop Feb 1, 2025
1cc4d22
Tests
carlossanlop Feb 1, 2025
80b53ef
Some infra files
carlossanlop Feb 1, 2025
7ac8c16
Address some of the feedback
carlossanlop Feb 3, 2025
bd88b38
Move the IO code to the business layer. Add a test that verifies the …
carlossanlop Feb 4, 2025
e0f9553
Address most of the feedback
carlossanlop Feb 6, 2025
9590165
Exclude diffplex DLLs from signing
carlossanlop Feb 6, 2025
c2d59aa
Fix markdown file title handling.
carlossanlop Feb 7, 2025
3e3bd44
Exclude from source build.
carlossanlop Feb 7, 2025
0027749
Allow overriding attribute list, add tests.
carlossanlop Feb 7, 2025
2c41297
improve attribute comment
carlossanlop Feb 7, 2025
6bbeb12
Add tests for implicit and explicit operators.
carlossanlop Feb 7, 2025
480696f
Implement API exclusion. Add tests.
carlossanlop Feb 7, 2025
33d3585
Remove Microsoft.CodeAnalysis.Worskpaces.Common PackageVersion from t…
carlossanlop Feb 13, 2025
9722f23
Unskip the checked tests.
carlossanlop Feb 13, 2025
edc45a9
Add exception resource strings, make some methods static, ignore newl…
carlossanlop Feb 18, 2025
91f2228
fix the resources error
carlossanlop Feb 19, 2025
a347588
Make some code async. Add option to exclude assemblies. Add tests.
carlossanlop Feb 21, 2025
223195b
Suppress additional diagnostics by default
carlossanlop Feb 27, 2025
5cad5e5
New resource
carlossanlop Feb 27, 2025
2bc7e7c
Fix bugs in attributes and events, add tests
carlossanlop Feb 27, 2025
b50eca1
remove static
carlossanlop Feb 27, 2025
6e12987
Add event tests
carlossanlop Feb 27, 2025
7422840
Support attributes that take arguments, add tests.
carlossanlop Feb 27, 2025
ebd0248
Truly async
carlossanlop Feb 27, 2025
8576cc7
Fix bug with abstract events where the field event declaration needs …
carlossanlop Feb 27, 2025
06d74b3
Add test that confirms that no files are getting overwritten when mul…
carlossanlop Feb 27, 2025
80232b7
Add arguments for before and after friendly name, separate that from …
carlossanlop Feb 28, 2025
befe4c6
Remove the body from methods and properties as requested in API diff PR.
carlossanlop Mar 4, 2025
7923d93
Add unchanged assembly and unchanged namespace tests.
carlossanlop Mar 5, 2025
364ec5c
Add destructor tests.
carlossanlop Mar 5, 2025
a4fbd5f
Add field list tests.
carlossanlop Mar 5, 2025
005d45e
Add an Options class for CSharpAssemblyDocumentGenerator to avoid gro…
carlossanlop Mar 5, 2025
265d10f
Moved some code from the generator to rewriters. Much faster.
carlossanlop Mar 6, 2025
b8829d4
Split test files into smaller ones
carlossanlop Mar 7, 2025
a9da515
Fix bug in TypeDeclarationCSharpSyntaxRewriter causing an extra space…
carlossanlop Mar 7, 2025
969358b
cons string t in AttributeNameSuffixRemover
carlossanlop Mar 7, 2025
09d06de
Fix bug in GlobalPrefixRemover preventing the removal of just global …
carlossanlop Mar 7, 2025
d4ef227
Fix bug in primitive conversion rewriter preventing the correct visit…
carlossanlop Mar 7, 2025
704507c
Fix bugs in body removal rewriter in accesors, operators and records
carlossanlop Mar 7, 2025
dc2d806
Add code specific for records in memory generator. Move the most debu…
carlossanlop Mar 7, 2025
e5eb224
Revert the TypeDeclarationCSharpSyntaxRewriter changes, they were wro…
carlossanlop Mar 7, 2025
21a1ecd
Don't truncate the attribute name, leave the type name full.
carlossanlop Mar 7, 2025
c6fdf8f
missing comments
carlossanlop Mar 14, 2025
ea4cbde
Missing docs
carlossanlop Mar 14, 2025
3ddb52c
Missing docs
carlossanlop Mar 14, 2025
9b5d333
Move private member under public ones
carlossanlop Mar 14, 2025
49dffe0
Replace the WaitAll with actual async method calls.
carlossanlop Mar 14, 2025
6c7cb26
Better split of code
carlossanlop Mar 14, 2025
62078f7
Fix sdk.sln merge conflict
carlossanlop Mar 25, 2025
5b4ef0a
Add enum support. Fix minor bug with records with members.
carlossanlop Mar 27, 2025
eb98ae9
Fix bug preventing attributes with arguments from getting either supp…
carlossanlop Mar 28, 2025
7810d71
Shorter test names. 8000
carlossanlop Mar 28, 2025
d1e46e5
Yet one more attribute bug fix and test.
carlossanlop Mar 28, 2025
942de97
Use ExternalCertificateId to sign DiffPlex dependencies.
carlossanlop Apr 7, 2025
92f306c
Address UI feedback.
carlossanlop Apr 7, 2025
8eaa8c9
Take lists of files with elements to exclude, instead of directly pas…
carlossanlop Apr 8, 2025
7446164
Add missing case for including interface members.
carlossanlop Apr 8, 2025
2241b38
Merge remote-tracking branch 'dotnet/main' into ApiDiff
carlossanlop Apr 24, 2025
b4d4d47
Solve merge confict in sdk.sln
carlossanlop Apr 24, 2025
c27086d
System.CommandLine override no longer needed.
carlossanlop Apr 24, 2025
3d7e841
Delete launchSettings.json
carlossanlop Apr 25, 2025
a5fe497
Update System.CommandLine usage to match latest version's API surface.
carlossanlop Apr 25, 2025
970ca19
test typo
carlossanlop Apr 25, 2025
27ca575
No resources needed yet
carlossanlop Apr 25, 2025
373eb30
Remove Required from optioNTableOfContentsTitle
carlossanlop Apr 25, 2025
37203a0
Set IsShippingPackage to false
carlossanlop Apr 25, 2025
2f050e3
The default attributes to exclude list should only apply to the ApiDi…
carlossanlop Apr 25, 2025
0c8b15a
Delete xlfs
carlossanlop Apr 25, 2025
dc02b78
Merge branch 'main' into ApiDiff
carlossanlop Apr 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add exception resource strings, make some methods static, ignore newl…
…ine diffs in tests
  • Loading branch information
carlossanlop committed Apr 7, 2025
commit edc45a9763190be9cdcb30f806e214e9be0e86cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ internal GenAPIDiffConfigurationBinder(Option<string> optionBeforeAssembliesFold

protected override DiffConfiguration GetBoundValue(BindingContext bindingContext) =>
new DiffConfiguration(
BeforeAssembliesFolderPath: bindingContext.ParseResult.GetValueForOption(_optionBeforeAssembliesFolderPath) ?? throw new NullReferenceException("Null before assemblies directory."),
BeforeAssembliesFolderPath: bindingContext.ParseResult.GetValueForOption(_optionBeforeAssembliesFolderPath) ?? throw new NullReferenceException(Resources.NullBeforeAssembliesDirectory),
BeforeAssemblyReferencesFolderPath: bindingContext.ParseResult.GetValueForOption(_optionBeforeAssemblyReferencesFolderPath),
AfterAssembliesFolderPath: bindingContext.ParseResult.GetValueForOption(_optionAfterAssembliesFolderPath) ?? throw new NullReferenceException("Null after assemblies directory."),
AfterAssembliesFolderPath: bindingContext.ParseResult.GetValueForOption(_optionAfterAssembliesFolderPath) ?? throw new NullReferenceException(Resources.NullAfterAssembliesDirectory),
AfterAssemblyReferencesFolderPath: bindingContext.ParseResult.GetValueForOption(_optionAfterAssemblyReferencesFolderPath),
OutputFolderPath: bindingContext.ParseResult.GetValueForOption(_optionOutputFolderPath) ?? throw new NullReferenceException("Null output directory."),
TableOfContentsTitle: bindingContext.ParseResult.GetValueForOption(_optionTableOfContentsTitle) ?? throw new NullReferenceException("Null table of contents title."),
OutputFolderPath: bindingContext.ParseResult.GetValueForOption(_optionOutputFolderPath) ?? throw new NullReferenceException(Resources.NullOutputDirectory),
TableOfContentsTitle: bindingContext.ParseResult.GetValueForOption(_optionTableOfContentsTitle) ?? throw new NullReferenceException(Resources.NullTableOfContentsTitle),
AttributesToExclude: bindingContext.ParseResult.GetValueForOption(_optionAttributesToExclude),
ApisToExclude: bindingContext.ParseResult.GetValueForOption(_optionApisToExclude),
AddPartialModifier: bindingContext.ParseResult.GetValueForOption(_optionAddPartialModifier),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public void Run()
}
}

private string GetFinalAssemblyDiff(string assemblyName, string diffText)
private static string GetFinalAssemblyDiff(string assemblyName, string diffText)
{
StringBuilder sbAssembly = new();
sbAssembly.AppendLine($"# {assemblyName}");
Expand Down Expand Up @@ -189,7 +189,7 @@ private string GetFinalAssemblyDiff(string assemblyName, string diffText)
return null;
}

private Dictionary<string, MemberDeclarationSyntax> CollectChildrenNodes(SyntaxNode parentNode, SemanticModel model)
private static Dictionary<string, MemberDeclarationSyntax> CollectChildrenNodes(SyntaxNode parentNode, SemanticModel model)
8000 {
Dictionary<string, MemberDeclarationSyntax> dictionary = new();

Expand Down Expand Up @@ -276,7 +276,7 @@ private Dictionary<string, MemberDeclarationSyntax> CollectChildrenNodes(SyntaxN
}
break;
default:
throw new NotSupportedException($"Unexpected change type for node {nodeName}: {changeType}");
throw new NotSupportedException(string.Format(Resources.UnexpectedChangeTypeForNode, nodeName, changeType));
}

return sb.Length > 0 ? sb.ToString() : null;
Expand All @@ -299,11 +299,11 @@ private Dictionary<string, MemberDeclarationSyntax> CollectChildrenNodes(SyntaxN
return namespaceNode.WithAttributeLists(_emptyAttributeList).WithLeadingTrivia(node.GetLeadingTrivia());
}

throw new InvalidOperationException($"Unsupported node for removing attributes.");
throw new InvalidOperationException(Resources.UnsupportedNodeForRemovingAttributes);
}

// Returns a non-null string if any attribute was changed (added, deleted or modified). Returns null if all attributes were the same before and after.
private string? VisitAttributes(MemberDeclarationSyntax? beforeNode, MemberDeclarationSyntax? afterNode)
private static string? VisitAttributes(MemberDeclarationSyntax? beforeNode, MemberDeclarationSyntax? afterNode)
{
Dictionary<string, AttributeSyntax>? beforeAttributeNodes = beforeNode != null ? CollectAttributeNodes(beforeNode) : null;
Dictionary<string, AttributeSyntax>? afterAttributeNodes = afterNode != null ? CollectAttributeNodes(afterNode) : null;
Expand Down Expand Up @@ -351,15 +351,15 @@ private Dictionary<string, MemberDeclarationSyntax> CollectChildrenNodes(SyntaxN
private (SyntaxNode rootNode, SemanticModel model) GetAssemblyRootNodeAndModel(IAssemblySymbolLoader loader, IAssemblySymbol assemblySymbol)
{
CSharpAssemblyDocumentGenerator docGenerator = new(_log,
loader,
_symbolFilter,
_attributeSymbolFilter,
exceptionMessage: null,
includeAssemblyAttributes: false,
loader.MetadataReferences,
diagnosticOptions: _diagnosticOptions,
addPartialModifier: _addPartialModifier,
hideImplicitDefaultConstructors: _hideImplicitDefaultConstructors);
loader,
_symbolFilter,
_attributeSymbolFilter,
exceptionMessage: null,
includeAssemblyAttributes: false,
loader.MetadataReferences,
diagnosticOptions: _diagnosticOptions,
addPartialModifier: _addPartialModifier,
hideImplicitDefaultConstructors: _hideImplicitDefaultConstructors);

// This is a workaround to get the root node and semantic model for a rewritten assembly root node.
Document oldDocument = docGenerator.GetDocumentForAssembly(assemblySymbol);
Expand Down Expand Up @@ -409,7 +409,7 @@ private string GetCodeWrappedByParent(string childrenText, SyntaxNode parentNode
return sb.ToString();
}

private SyntaxNode GetChildlessNode(SyntaxNode node)
private static SyntaxNode GetChildlessNode(SyntaxNode node)
{
SyntaxNode childlessNode = node switch
{
Expand Down Expand Up @@ -472,7 +472,7 @@ private string GetCodeOfNodeClosing(SyntaxNode childlessNode)
.WithLeadingTrivia(nsDecl.CloseBraceToken.LeadingTrivia.AddRange(_twoSpacesTrivia))
.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed),

_ => throw new InvalidOperationException("Unexpected node type.")
_ => throw new InvalidOperationException(Resources.UnexpectedNodeType)
};

StringBuilder sb = new();
Expand Down Expand Up @@ -507,7 +507,7 @@ private static string GetDocId(SyntaxNode node, SemanticModel model)
}
}

throw new NullReferenceException($"Could not get the DocID of the node: {node}");
throw new NullReferenceException(string.Format(Resources.CouldNotGetDocIdForNode, node));
}

private static string? GenerateAddedDiff(SyntaxNode afterNode) =>
Expand Down Expand Up @@ -540,14 +540,8 @@ private static string GetDocId(SyntaxNode node, SemanticModel model)
default:
break;
}
;
}

if (sb.Length == 0)
{
return null;
}

return sb.ToString();
return sb.Length == 0 ? null : sb.ToString();
}
}
80 changes: 52 additions & 28 deletions src/Compatibility/ApiDiff/Microsoft.DotNet.ApiDiff/Resources.resx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema

Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes

The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.

Example:

... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
Expand All @@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple

There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the

Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not

The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can

Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.

mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
Expand Down Expand Up @@ -120,7 +120,31 @@
<data name="AddMemberThrowsException" xml:space="preserve">
<value>Adding member '{0}' to the named type '{1}' failed with exception '{2}'.</value>
</data>
<data name="CouldNotGetDocIdForNode" xml:space="preserve">
<value>Could not get the DocID for node: {0}</value>
</data>
<data name="NullAfterAssembliesDirectory" xml:space="preserve">
<value>Null after assemblies directory.</value>
</data>
<data name="NullBeforeAssembliesDirectory" xml:space="preserve">
<value>Null before assemblies directory.</value>
</data>
<data name="NullOutputDirectory" xml:space="preserve">
<value>Null output directory.</value>
</data>
<data name="NullTableOfContentsTitle" xml:space="preserve">
<value>Null table of contents title.</value>
</data>
<data name="ResolveTypeForwardFailed" xml:space="preserve">
<value>Could not resolve type '{0}' in containing assembly '{1}' via type forward. Make sure that the assembly is provided as a reference and contains the type.</value>
</data>
</root>
<data name="UnexpectedChangeTypeForNode" xml:space="preserve">
<value>Unexpected change type for node {0}: {1}</value>
</data>
<data name="UnsupportedNodeForRemovingAttributes" xml:space="preserve">
<value>Unsupported node for removing attributes.</value>
</data>
<data name="UnexpectedNodeType" xml:space="preserve">
<value>Unexpected node type.</value>
</data>
</root>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
0