提交 21bc81c5 编写于 作者: T Tom Meschter

Update the DeclarePublicAPI analyzer to consider return types

The DeclarePublicAPI draws attention to changes to the public API
surface area in order to prevent breaking changes and to encourage
careful design when adding new APIs. It requires that every project with
a public API capture the public types and members in a file called
PublicAPI.txt, and creates errors when this file does not match the
actual symbols in the project. This makes changes very obvious in code
reviews and source control history.

Currently PublicAPI.txt does not capture the return types of members
(field, properties, methods, and events) so these can changes without it
being caught by the tool. This changes updates the analyzer to include
the return type.

A nice feature of the associated code fix is that it sorts PublicAPI.txt
alphabetically, and since type names are fully qualified this naturally
groups together types in the same namespace, members in the same type,
overloads, etc. To preserve this property we put the return type at the
end of the line, after the type and member name.
上级 4f147f5b
......@@ -49,7 +49,7 @@ public class DeclarePublicAPIAnalyzer : DiagnosticAnalyzer
miscellaneousOptions:
SymbolDisplayMiscellaneousOptions.None);
internal static readonly SymbolDisplayFormat PublicApiFormat =
private static readonly SymbolDisplayFormat PublicApiFormat =
new SymbolDisplayFormat(
globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.OmittedAsContaining,
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
......@@ -110,7 +110,7 @@ public override void Initialize(AnalysisContext context)
return;
}
var publicApiName = symbol.ToDisplayString(PublicApiFormat);
string publicApiName = GetPublicApiName(symbol);
lock (lockObj)
{
......@@ -160,6 +160,36 @@ public override void Initialize(AnalysisContext context)
});
}
internal static string GetPublicApiName(ISymbol symbol)
{
var publicApiName = symbol.ToDisplayString(PublicApiFormat);
ITypeSymbol memberType = null;
if (symbol is IMethodSymbol)
{
memberType = ((IMethodSymbol)symbol).ReturnType;
}
else if (symbol is IPropertySymbol)
{
memberType = ((IPropertySymbol)symbol).Type;
}
else if (symbol is IEventSymbol)
{
memberType = ((IEventSymbol)symbol).Type;
}
else if (symbol is IFieldSymbol)
{
memberType = ((IFieldSymbol)symbol).Type;
}
if (memberType != null)
{
publicApiName = publicApiName + " -> " + memberType.ToDisplayString(PublicApiFormat);
}
return publicApiName;
}
private TextSpan? FindString(SourceText sourceText, string symbol)
{
foreach (var line in sourceText.Lines)
......
......@@ -47,7 +47,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (symbol != null)
{
var minimalSymbolName = symbol.ToMinimalDisplayString(semanticModel, location.SourceSpan.Start, DeclarePublicAPIAnalyzer.ShortSymbolNameFormat);
var publicSurfaceAreaSymbolName = symbol.ToDisplayString(DeclarePublicAPIAnalyzer.PublicApiFormat);
var publicSurfaceAreaSymbolName = DeclarePublicAPIAnalyzer.GetPublicApiName(symbol);
context.RegisterCodeFix(
new AdditionalDocumentChangeAction(
......@@ -196,7 +196,7 @@ protected override async Task<Solution> GetChangedSolutionAsync(CancellationToke
if (symbol != null)
{
var publicSurfaceAreaSymbolName = symbol.ToDisplayString(DeclarePublicAPIAnalyzer.PublicApiFormat);
var publicSurfaceAreaSymbolName = DeclarePublicAPIAnalyzer.GetPublicApiName(symbol);
if (symbol != null)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册