Skip to content

Commit

Permalink
Merge pull request #3916 from mavasani/PublicAPI_Enable
Browse files Browse the repository at this point in the history
[PublicApiAnalyzer] Add support for creating shipped and unshiped tex…
  • Loading branch information
mavasani authored Jul 31, 2020
2 parents 6dd2937 + b88f92e commit 30c2edf
Show file tree
Hide file tree
Showing 23 changed files with 311 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ Rule ID | Category | Severity | Notes
--------|----------|----------|-------
RS0036 | ApiDesign | Warning | DeclarePublicApiAnalyzer, [Documentation](https://github.com/dotnet/roslyn-analyzers/blob/master/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
RS0037 | ApiDesign | Warning | DeclarePublicApiAnalyzer, [Documentation](https://github.com/dotnet/roslyn-analyzers/blob/master/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
RS0041 | ApiDesign | Warning | DeclarePublicApiAnalyzer, [Documentation](https://github.com/dotnet/roslyn-analyzers/blob/master/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
RS0041 | ApiDesign | Warning | DeclarePublicApiAnalyzer, [Documentation](https://github.com/dotnet/roslyn-analyzers/blob/master/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
RS0048 | ApiDesign | Warning | DeclarePublicApiAnalyzer, [Documentation](https://github.com/dotnet/roslyn-analyzers/blob/master/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public ApiName(string name, string nameWithNullability)
private readonly struct ApiData
#pragma warning restore CA1815 // Override equals and operator equals on value types
{
public static readonly ApiData Empty = new ApiData(ImmutableArray<ApiLine>.Empty, ImmutableArray<RemovedApiLine>.Empty, nullableRank: -1);

public ImmutableArray<ApiLine> ApiList { get; }
public ImmutableArray<RemovedApiLine> RemovedApiList { get; }
// Number for the max line where #nullable enable was found (-1 otherwise)
Expand Down
39 changes: 29 additions & 10 deletions src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading;
Expand Down Expand Up @@ -93,6 +94,16 @@ public sealed partial class DeclarePublicApiAnalyzer : DiagnosticAnalyzer
helpLinkUri: "https://github.com/dotnet/roslyn-analyzers/blob/master/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md",
customTags: WellKnownDiagnosticTags.Telemetry);

internal static readonly DiagnosticDescriptor PublicApiFileMissing = new DiagnosticDescriptor(
id: DiagnosticIds.PublicApiFileMissing,
title: PublicApiAnalyzerResources.PublicApiFileMissingTitle,
messageFormat: PublicApiAnalyzerResources.PublicApiFileMissingMessage,
category: "ApiDesign",
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: "https://github.com/dotnet/roslyn-analyzers/blob/master/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md",
customTags: WellKnownDiagnosticTags.Telemetry);

internal static readonly DiagnosticDescriptor DuplicateSymbolInApiFiles = new DiagnosticDescriptor(
id: DiagnosticIds.DuplicatedSymbolInPublicApiFiles,
title: PublicApiAnalyzerResources.DuplicateSymbolsInPublicApiFilesTitle,
Expand Down Expand Up @@ -179,7 +190,7 @@ public sealed partial class DeclarePublicApiAnalyzer : DiagnosticAnalyzer

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
ImmutableArray.Create(DeclareNewApiRule, AnnotateApiRule, ObliviousApiRule, RemoveDeletedApiRule, ExposedNoninstantiableType,
PublicApiFilesInvalid, DuplicateSymbolInApiFiles, AvoidMultipleOverloadsWithOptionalParameters,
PublicApiFilesInvalid, PublicApiFileMissing, DuplicateSymbolInApiFiles, AvoidMultipleOverloadsWithOptionalParameters,
OverloadWithOptionalParametersShouldHaveMostParameters, ShouldAnnotateApiFilesRule);

public override void Initialize(AnalysisContext context)
Expand All @@ -195,13 +206,11 @@ public override void Initialize(AnalysisContext context)
private void OnCompilationStart(CompilationStartAnalysisContext compilationContext)
{
var additionalFiles = compilationContext.Options.AdditionalFiles;
var errors = new List<Diagnostic>();

if (!TryGetApiData(additionalFiles, compilationContext.CancellationToken, out ApiData shippedData, out ApiData unshippedData))
{
return;
}

if (!ValidateApiFiles(shippedData, unshippedData, out List<Diagnostic> errors))
// Switch to "RegisterAdditionalFileAction" available in Microsoft.CodeAnalysis "3.8.x" to report additional file diagnostics: https://github.com/dotnet/roslyn-analyzers/issues/3918
if (!TryGetApiData(additionalFiles, errors, compilationContext.CancellationToken, out ApiData shippedData, out ApiData unshippedData) ||
!ValidateApiFiles(shippedData, unshippedData, errors))
{
compilationContext.RegisterCompilationEndAction(context =>
{
Expand All @@ -214,6 +223,8 @@ private void OnCompilationStart(CompilationStartAnalysisContext compilationConte
return;
}

Debug.Assert(errors.Count == 0);

var impl = new Impl(compilationContext.Compilation, shippedData, unshippedData);
compilationContext.RegisterSymbolAction(
impl.OnSymbolAction,
Expand Down Expand Up @@ -265,10 +276,19 @@ private static ApiData ReadApiData(string path, SourceText sourceText, bool isSh
return new ApiData(apiBuilder.ToImmutable(), removedBuilder.ToImmutable(), maxNullableRank);
}

private static bool TryGetApiData(ImmutableArray<AdditionalText> additionalTexts, CancellationToken cancellationToken, out ApiData shippedData, out ApiData unshippedData)
private static bool TryGetApiData(ImmutableArray<AdditionalText> additionalTexts, List<Diagnostic> errors, CancellationToken cancellationToken, out ApiData shippedData, out ApiData unshippedData)
{
if (!TryGetApiText(additionalTexts, cancellationToken, out var shippedText, out var unshippedText))
{
if (shippedText == null && unshippedText == null)
{
// Bootstrapping public API files.
(shippedData, unshippedData) = (ApiData.Empty, ApiData.Empty);
return true;
}

var missingFileName = shippedText == null ? ShippedFileName : UnshippedFileName;
errors.Add(Diagnostic.Create(PublicApiFileMissing, Location.None, missingFileName));
shippedData = default;
unshippedData = default;
return false;
Expand Down Expand Up @@ -310,9 +330,8 @@ private static bool TryGetApiText(
return shippedText != null && unshippedText != null;
}

private static bool ValidateApiFiles(ApiData shippedData, ApiData unshippedData, out List<Diagnostic> errors)
private static bool ValidateApiFiles(ApiData shippedData, ApiData unshippedData, List<Diagnostic> errors)
{
errors = new List<Diagnostic>();
if (!shippedData.RemovedApiList.IsEmpty)
{
errors.Add(Diagnostic.Create(PublicApiFilesInvalid, Location.None, InvalidReasonShippedCantHaveRemoved));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@
<data name="PublicApiFilesInvalidMessage" xml:space="preserve">
<value>The contents of the public API files are invalid: {0}</value>
</data>
<data name="PublicApiFileMissingTitle" xml:space="preserve">
<value>Missing shipped or unshipped public API file</value>
</data>
<data name="PublicApiFileMissingMessage" xml:space="preserve">
<value>Public API file '{0}' is missing or not marked as an additional analyzer file</value>
</data>
<data name="DuplicateSymbolsInPublicApiFilesTitle" xml:space="preserve">
<value>Do not duplicate symbols in public API files</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">Veřejné rozhraní API s nepovinnými parametry by mělo mít ze všech veřejných přetížení nejvíce parametrů</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">Obsah souborů veřejných rozhraní API není platný: {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">Öffentliche API mit optionalen Parametern muss die meisten Parameter bei den öffentlichen Überladungen aufweisen.</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">Die Inhalte der öffentlichen API-Dateien sind ungültig: {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">La API pública con parámetros opcionales debe tener la mayoría de los parámetros entre sus sobrecargas públicas</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">El contenido de los archivos de la API pública no es válido: {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">L'API publique avec un ou plusieurs paramètres optionnels doit avoir le plus de paramètres possibles parmi ses surcharges publiques.</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">Le contenu des fichiers de l'API publique est non valide : {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">L'API pubblica con parametri facoltativi deve includere la maggior parte dei parametri tra i relativi overload public.</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">Il contenuto dei file dell'API pubblica non è valido: {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">省略可能なパラメーターを持つパブリック API は、そのパブリック オーバーロード内のほとんどのパラメーターを持つ必要があります。</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">パブリック API ファイルのコンテンツが無効です: {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">선택적 매개 변수가 있는 공용 API에는 공용 오버로드 중 대부분의 매개 변수가 포함되어야 합니다.</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">공용 API 파일의 콘텐츠가 유효하지 않습니다. {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">Publiczny interfejs API z opcjonalnymi parametrami powinien mieć najwięcej parametrów spośród przeciążeń publicznych.</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">Zawartość plików publicznego interfejsu API jest nieprawidłowa: {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">A API pública com parâmetros opcionais deve ter a maioria dos parâmetros entre suas sobrecargas públicas.</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">O conteúdo dos arquivos da API pública é inválido: {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">Открытый API с необязательными параметрами должен иметь основную часть параметров среди своих открытых перегрузок.</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">Недопустимое содержимое файлов открытого API: {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">İsteğe bağlı parametreleri olan genel API'nin, genel aşırı yüklemeleri arasında en çok parametreye sahip olması gerekir.</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">Genel API dosyalarının içerikleri geçersiz: {0}</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@
<target state="translated">具有可选参数的公共 API 应在其公共重载中具有最多参数。</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingMessage">
<source>Public API file '{0}' is missing or not marked as an additional analyzer file</source>
<target state="new">Public API file '{0}' is missing or not marked as an additional analyzer file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFileMissingTitle">
<source>Missing shipped or unshipped public API file</source>
<target state="new">Missing shipped or unshipped public API file</target>
<note />
</trans-unit>
<trans-unit id="PublicApiFilesInvalidMessage">
<source>The contents of the public API files are invalid: {0}</source>
<target state="translated">公共 API 文件的内容无效: {0}</target>
Expand Down
Loading

0 comments on commit 30c2edf

Please sign in to comment.