Remove Internal.AspNetCore.Analyzers (#24693)

* Remove Internal.AspNetCore.Analyzers

This resolves build flakiness caused by referencing the analyzer:

```
2020-08-07T21:22:39.1149296Z ##[error].dotnet\sdk\5.0.100-rc.1.20379.10\Microsoft.Common.CurrentVersion.targets(4188,5): error MSB3026: (NETCORE_ENGINEERING_TELEMETRY=Build)
Could not copy "F:\workspace\_work\1\s\artifacts\obj\Internal.AspNetCore.Analyzers\Release\netstandard1.3\Internal.AspNetCore.Analyzers.dll"
to "F:\workspace\_work\1\s\artifacts\bin\Internal.AspNetCore.Analyzers\Release\netstandard1.3\Internal.AspNetCore.Analyzers.dll". Beginning retry 1 in 1000ms.
The process cannot access the file 'F:\workspace\_work\1\s\artifacts\bin\Internal.AspNetCore.Analyzers\Release\netstandard1.3\Internal.AspNetCore.Analyzers.dll' because it is being used by another process.
```

The analyzer checks if pubternal types are being exposed in public APIs. We no longer author pubternal types, so this is no longer a concern.

* Remove DisablePubternalApiCheck
This commit is contained in:
Pranav K 2020-08-10 20:08:55 -07:00 committed by GitHub
parent 5fbd1eb007
commit 059e2fdc49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 0 additions and 628 deletions

View File

@ -140,20 +140,6 @@
<InternalInstallerBaseName>$(RuntimeInstallerBaseName)-internal</InternalInstallerBaseName>
</PropertyGroup>
<ItemGroup
Condition="'$(DisablePubternalApiCheck)' != 'true'
AND '$(IsTestProject)' != 'true'
AND '$(IsBenchmarkProject)' != 'true'
AND '$(IsTestAssetProject)' != 'true'
AND '$(MSBuildProjectName)' != 'Internal.AspNetCore.Analyzers'
AND '$(MSBuildProjectExtension)' == '.csproj'">
<ProjectReference
Include="$(RepoRoot)src\Analyzers\Internal.AspNetCore.Analyzers\src\Internal.AspNetCore.Analyzers.csproj"
ReferenceOutputAssembly="false"
OutputItemType="Analyzer"
PrivateAssets="All" />
</ItemGroup>
<!-- Compilation options which apply to all languages. Language-specific options should be set in eng/targets/$(lang).Common.props -->
<PropertyGroup>
<BuildArchitecture>$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant())</BuildArchitecture>

View File

@ -1,26 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core internal use analyzers.</Description>
<TargetFramework>netstandard1.3</TargetFramework>
<PackageTags>$(PackageTags);analyzers</PackageTags>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<BuildOutputTargetFolder>analyzers/dotnet/cs/</BuildOutputTargetFolder>
<!--
Except for analyzer unit tests, analyzers should not be referenced by other projects in this repo. Analyzers cannot be used as
a project reference unless referenced with OutputItemType="Analyzer". The SDK currently only supports using analyzers as a PackageReference. This flag prevents this project from
being used as a `<Reference>`, which indicates that a reference is interchangeable between ProjectRef and PackageRef.
-->
<IsProjectReferenceProvider>false</IsProjectReferenceProvider>
<UseLatestPackageReferences>true</UseLatestPackageReferences>
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
<IsShippingPackage>false</IsShippingPackage>
<!-- This project needs an older version of M.CA.CSharp.Workspaces since it targets netstandard1.3 -->
<DisablePackageReferenceRestrictions>true</DisablePackageReferenceRestrictions>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="2.8.0" PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@ -1,279 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Internal.AspNetCore.Analyzers
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class PubternalityAnalyzer : DiagnosticAnalyzer
{
public PubternalityAnalyzer()
{
SupportedDiagnostics = ImmutableArray.Create(new[]
{
PubturnalityDescriptors.PUB0001,
PubturnalityDescriptors.PUB0002
});
}
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.RegisterCompilationStartAction(analysisContext =>
{
analysisContext.RegisterSymbolAction(symbolAnalysisContext => AnalyzeTypeUsage(symbolAnalysisContext), SymbolKind.Namespace);
analysisContext.RegisterSyntaxNodeAction(syntaxContext => AnalyzeTypeUsage(syntaxContext), SyntaxKind.IdentifierName);
});
}
private void AnalyzeTypeUsage(SymbolAnalysisContext context)
{
var ns = (INamespaceSymbol)context.Symbol;
if (IsInternal(ns))
{
return;
}
foreach (var namespaceOrTypeSymbol in ns.GetMembers())
{
if (namespaceOrTypeSymbol.IsType)
{
CheckType((ITypeSymbol)namespaceOrTypeSymbol, context);
}
}
}
private void CheckType(ITypeSymbol typeSymbol, SymbolAnalysisContext context)
{
if (IsPrivate(typeSymbol) || IsPrivate(typeSymbol.ContainingType))
{
return;
}
if (typeSymbol.BaseType != null)
{
CheckType(context, typeSymbol.BaseType, typeSymbol.DeclaringSyntaxReferences);
}
foreach (var member in typeSymbol.GetMembers())
{
CheckMember(context, member);
}
foreach (var innerType in typeSymbol.GetTypeMembers())
{
CheckType(innerType, context);
}
if (typeSymbol is INamedTypeSymbol namedTypeSymbol)
{
// Check delegate signatures
if (namedTypeSymbol.DelegateInvokeMethod != null)
{
CheckMethod(context, namedTypeSymbol.DelegateInvokeMethod);
}
}
}
private void CheckMember(SymbolAnalysisContext context, ISymbol symbol)
{
if (IsPrivate(symbol))
{
return;
}
switch (symbol)
{
case IFieldSymbol fieldSymbol:
{
CheckType(context, fieldSymbol.Type, fieldSymbol.DeclaringSyntaxReferences);
break;
}
case IPropertySymbol propertySymbol:
{
CheckType(context, propertySymbol.Type, propertySymbol.DeclaringSyntaxReferences);
break;
}
case IMethodSymbol methodSymbol:
{
// Skip compiler generated members that we already explicitly check
switch (methodSymbol.MethodKind)
{
case MethodKind.EventAdd:
case MethodKind.EventRaise:
case MethodKind.EventRemove:
case MethodKind.PropertyGet:
case MethodKind.PropertySet:
case MethodKind.DelegateInvoke:
case MethodKind.Ordinary when methodSymbol.ContainingType.TypeKind == TypeKind.Delegate:
return;
}
CheckMethod(context, methodSymbol);
break;
}
case IEventSymbol eventSymbol:
CheckType(context, eventSymbol.Type, eventSymbol.DeclaringSyntaxReferences);
break;
}
}
private void CheckMethod(SymbolAnalysisContext context, IMethodSymbol methodSymbol)
{
if (IsPrivate(methodSymbol))
{
return;
}
foreach (var parameter in methodSymbol.Parameters)
{
CheckType(context, parameter.Type, parameter.DeclaringSyntaxReferences);
}
CheckType(context, methodSymbol.ReturnType, methodSymbol.DeclaringSyntaxReferences);
}
private static bool IsPrivate(ISymbol symbol)
{
return symbol != null &&
(symbol.DeclaredAccessibility == Accessibility.Private ||
symbol.DeclaredAccessibility == Accessibility.Internal ||
IsInternal(symbol.ContainingNamespace));
}
private void CheckAttributes(SymbolAnalysisContext context, ImmutableArray<AttributeData> attributes)
{
foreach (var attributeData in attributes)
{
CheckType(context, attributeData.AttributeClass, attributeData.ApplicationSyntaxReference);
}
}
private void CheckType(SymbolAnalysisContext context, ITypeSymbol symbol, SyntaxReference syntax)
{
var pubternalType = GetPubternalType(symbol);
if (pubternalType != null)
{
ReportPUB0001(context, pubternalType, syntax);
}
}
private void CheckType(SymbolAnalysisContext context, ITypeSymbol symbol, ImmutableArray<SyntaxReference> syntaxReferences)
{
var pubternalType = GetPubternalType(symbol);
if (pubternalType != null)
{
foreach (var syntaxReference in syntaxReferences)
{
ReportPUB0001(context, pubternalType, syntaxReference);
}
}
}
private static void ReportPUB0001(SymbolAnalysisContext context, ITypeSymbol pubternalType, SyntaxReference syntax)
{
var syntaxNode = syntax.GetSyntax();
var location = syntaxNode.GetLocation();
if (syntaxNode is BaseTypeDeclarationSyntax baseTypeDeclarationSyntax)
{
location = baseTypeDeclarationSyntax.Identifier.GetLocation();
}
if (syntaxNode is DelegateDeclarationSyntax delegateDeclarationSyntax)
{
location = delegateDeclarationSyntax.ReturnType.GetLocation();
}
if (syntaxNode is BasePropertyDeclarationSyntax propertyDeclaration)
{
location = propertyDeclaration.Type.GetLocation();
}
if (syntaxNode is MethodDeclarationSyntax method)
{
location = method.ReturnType.GetLocation();
}
if (syntaxNode is VariableDeclaratorSyntax variableDeclarator)
{
if (variableDeclarator.Parent is VariableDeclarationSyntax fieldDeclaration)
{
location = fieldDeclaration.Type.GetLocation();
}
}
context.ReportDiagnostic(Diagnostic.Create(PubturnalityDescriptors.PUB0001, location, pubternalType.ToDisplayString()));
}
private ITypeSymbol GetPubternalType(ITypeSymbol symbol)
{
if (IsInternal(symbol.ContainingNamespace))
{
return symbol;
}
else
{
if (symbol is INamedTypeSymbol namedTypeSymbol && namedTypeSymbol.IsGenericType)
{
foreach (var argument in namedTypeSymbol.TypeArguments)
{
var argumentSymbol = GetPubternalType(argument);
if (argumentSymbol != null)
{
return argumentSymbol;
}
}
}
}
return null;
}
private void AnalyzeTypeUsage(SyntaxNodeAnalysisContext syntaxContext)
{
var identifier = (IdentifierNameSyntax)syntaxContext.Node;
var symbolInfo = ModelExtensions.GetTypeInfo(syntaxContext.SemanticModel, identifier, syntaxContext.CancellationToken);
if (symbolInfo.Type == null)
{
return;
}
var type = symbolInfo.Type;
if (!IsInternal(type.ContainingNamespace))
{
// don't care about non-pubternal type references
return;
}
if (!syntaxContext.ContainingSymbol.ContainingAssembly.Equals(type.ContainingAssembly))
{
syntaxContext.ReportDiagnostic(Diagnostic.Create(PubturnalityDescriptors.PUB0002, identifier.GetLocation(), type.ToDisplayString()));
}
}
private static bool IsInternal(INamespaceSymbol ns)
{
while (ns != null)
{
if (ns.Name == "Internal")
{
return true;
}
ns = ns.ContainingNamespace;
}
return false;
}
}
}

View File

@ -1,25 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CodeAnalysis;
namespace Internal.AspNetCore.Analyzers
{
internal class PubturnalityDescriptors
{
public static DiagnosticDescriptor PUB0001 = new DiagnosticDescriptor(
"PUB0001",
"Pubternal type in public API",
"Pubternal type ('{0}') usage in public API",
"Usage",
DiagnosticSeverity.Warning, true);
public static DiagnosticDescriptor PUB0002 = new DiagnosticDescriptor(
"PUB0002",
"Cross assembly pubternal reference",
"Cross assembly pubternal type ('{0}') reference",
"Usage",
DiagnosticSeverity.Error, false);
}
}

View File

@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
<PreserveCompilationContext>true</PreserveCompilationContext>
<!-- Analyzers tests can't find netfx ref assemblies from a package -->
<UsingToolNetFrameworkReferenceAssemblies Condition="'$(OS)' == 'Windows_NT'">false</UsingToolNetFrameworkReferenceAssemblies>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\src\Internal.AspNetCore.Analyzers.csproj" />
<ProjectReference Include="..\..\Microsoft.AspNetCore.Analyzer.Testing\src\Microsoft.AspNetCore.Analyzer.Testing.csproj" />
</ItemGroup>
</Project>

View File

@ -1,263 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Analyzer.Testing;
using Xunit;
using Xunit.Abstractions;
namespace Internal.AspNetCore.Analyzers.Tests
{
public class PubternabilityAnalyzerTests : DiagnosticVerifier
{
private const string InternalDefinitions = @"
namespace A.Internal.Namespace
{
public class C {}
public delegate C CD ();
public class CAAttribute: System.Attribute {}
public class Program
{
public static void Main() {}
}
}";
public PubternabilityAnalyzerTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
{
}
[Theory]
[MemberData(nameof(PublicMemberDefinitions))]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/22440")]
public async Task PublicExposureOfPubternalTypeProducesPUB0001(string member)
{
var code = GetSourceFromNamespaceDeclaration($@"
namespace A
{{
public class T
{{
{member}
}}
}}");
var diagnostic = Assert.Single(await GetDiagnostics(code.Source));
Assert.Equal("PUB0001", diagnostic.Id);
AnalyzerAssert.DiagnosticLocation(code.DefaultMarkerLocation, diagnostic.Location);
}
[Theory]
[MemberData(nameof(PublicMemberWithAllowedDefinitions))]
public async Task PublicExposureOfPubternalMembersSometimesAllowed(string member)
{
var code = GetSourceFromNamespaceDeclaration($@"
namespace A
{{
public class T
{{
{member}
}}
}}");
Assert.Empty(await GetDiagnostics(code.Source));
}
[Theory]
[MemberData(nameof(PublicTypeDefinitions))]
public async Task PublicExposureOfPubternalTypeProducesInTypeDefinitionPUB0001(string member)
{
var code = GetSourceFromNamespaceDeclaration($@"
namespace A
{{
{member}
}}");
var diagnostic = Assert.Single(await GetDiagnostics(code.Source));
Assert.Equal("PUB0001", diagnostic.Id);
AnalyzerAssert.DiagnosticLocation(code.DefaultMarkerLocation, diagnostic.Location);
}
[Theory]
[MemberData(nameof(PublicMemberDefinitions))]
public async Task PrivateUsageOfPubternalTypeDoesNotProduce(string member)
{
var code = GetSourceFromNamespaceDeclaration($@"
namespace A
{{
internal class T
{{
{member}
}}
}}");
var diagnostics = await GetDiagnostics(code.Source);
Assert.Empty(diagnostics);
}
[Theory]
[MemberData(nameof(PrivateMemberDefinitions))]
public async Task PrivateUsageOfPubternalTypeDoesNotProduceInPublicClasses(string member)
{
var code = GetSourceFromNamespaceDeclaration($@"
namespace A
{{
public class T
{{
{member}
}}
}}");
var diagnostics = await GetDiagnostics(code.Source);
Assert.Empty(diagnostics);
}
[Theory]
[MemberData(nameof(PublicTypeWithAllowedDefinitions))]
public async Task PublicExposureOfPubternalTypeSometimesAllowed(string member)
{
var code = GetSourceFromNamespaceDeclaration($@"
namespace A
{{
{member}
}}");
var diagnostics = await GetDiagnostics(code.Source);
Assert.Empty(diagnostics);
}
[Theory]
[MemberData(nameof(PrivateMemberDefinitions))]
[MemberData(nameof(PublicMemberDefinitions))]
[QuarantinedTest]
public async Task DefinitionOfPubternalCrossAssemblyProducesPUB0002(string member)
{
var code = TestSource.Read($@"
using A.Internal.Namespace;
namespace A
{{
internal class T
{{
{member}
}}
}}");
var diagnostic = Assert.Single(await GetDiagnosticWithProjectReference(code.Source));
Assert.Equal("PUB0002", diagnostic.Id);
AnalyzerAssert.DiagnosticLocation(code.DefaultMarkerLocation, diagnostic.Location);
}
[Theory]
[MemberData(nameof(TypeUsages))]
public async Task UsageOfPubternalCrossAssemblyProducesPUB0002(string usage)
{
var code = TestSource.Read($@"
using A.Internal.Namespace;
namespace A
{{
public class T
{{
private void M()
{{
{usage}
}}
}}
}}");
var diagnostic = Assert.Single(await GetDiagnosticWithProjectReference(code.Source));
Assert.Equal("PUB0002", diagnostic.Id);
AnalyzerAssert.DiagnosticLocation(code.DefaultMarkerLocation, diagnostic.Location);
}
public static IEnumerable<object[]> PublicMemberDefinitions =>
ApplyModifiers(MemberDefinitions, "public", "protected");
public static IEnumerable<object[]> PublicMemberWithAllowedDefinitions =>
ApplyModifiers(AllowedMemberDefinitions, "public");
public static IEnumerable<object[]> PublicTypeDefinitions =>
ApplyModifiers(TypeDefinitions, "public");
public static IEnumerable<object[]> PublicTypeWithAllowedDefinitions =>
ApplyModifiers(AllowedDefinitions, "public");
public static IEnumerable<object[]> PrivateMemberDefinitions =>
ApplyModifiers(MemberDefinitions, "private", "internal");
public static IEnumerable<object[]> TypeUsages =>
ApplyModifiers(TypeUsageStrings, string.Empty);
public static string[] MemberDefinitions => new []
{
"/*MM*/C c;",
"T(/*MM*/C c) {}",
"/*MM*/CD c { get; }",
"event /*MM*/CD c;",
"delegate /*MM*/C WOW();"
};
public static string[] TypeDefinitions => new []
{
"delegate /*MM*/C WOW();",
"class /*MM*/T: P<C> { } public class P<T> {}",
"class /*MM*/T: C {}",
"class T { public class /*MM*/T1: C { } }"
};
public static string[] AllowedMemberDefinitions => new []
{
"T([CA]int c) {}",
"[CA] MOD int f;",
"[CA] MOD int f { get; set; }",
"[CA] MOD class CC { }"
};
public static string[] AllowedDefinitions => new []
{
"class T: I<C> { } interface I<T> {}"
};
public static string[] TypeUsageStrings => new []
{
"/*MM*/var c = new C();",
"/*MM*/CD d = () => null;",
"var t = typeof(/*MM*/CAAttribute);"
};
private static IEnumerable<object[]> ApplyModifiers(string[] code, params string[] mods)
{
foreach (var mod in mods)
{
foreach (var s in code)
{
if (s.Contains("MOD"))
{
yield return new object[] { s.Replace("MOD", mod) };
}
else
{
yield return new object[] { mod + " " + s };
}
}
}
}
private TestSource GetSourceFromNamespaceDeclaration(string namespaceDefinition)
{
return TestSource.Read("using A.Internal.Namespace;" + InternalDefinitions + namespaceDefinition);
}
private Task<Diagnostic[]> GetDiagnosticWithProjectReference(string code)
{
var libraray = CreateProject(InternalDefinitions);
var mainProject = CreateProject(code).AddProjectReference(new ProjectReference(libraray.Id));
return GetDiagnosticsAsync(mainProject.Documents.ToArray(), new PubternalityAnalyzer(), new [] { "PUB0002" });
}
private Task<Diagnostic[]> GetDiagnostics(string code)
{
return GetDiagnosticsAsync(new[] { code }, new PubternalityAnalyzer(), new [] { "PUB0002" });
}
}
}

View File

@ -6,7 +6,6 @@
<IsPackable>false</IsPackable>
<IsShipping>false</IsShipping>
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
<UseAppHost>false</UseAppHost>
<RuntimeIdentifier />

View File

@ -6,7 +6,6 @@
<!-- Shared between targeting pack and runtime build. -->
<PlatformManifestFileName>PlatformManifest.txt</PlatformManifestFileName>
<PlatformManifestOutputPath>$(ArtifactsObjDir)$(PlatformManifestFileName)</PlatformManifestOutputPath>
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
<!-- Platform manifest and package override metatdata -->
<ReferencePackSharedFxVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).0</ReferencePackSharedFxVersion>

View File

@ -2,7 +2,6 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
<PropertyGroup>
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
<OutputPath>$(InstallersOutputPath)</OutputPath>
<IntermediateOutputPath>$(IntermediateOutputPath)$(TargetRuntimeIdentifier)\</IntermediateOutputPath>

View File

@ -13,8 +13,6 @@
<NoWarn>$(NoWarn);NU5100</NoWarn>
<!-- It is intentional to not include build/netstandard2.0/Microsoft.NET.Sdk.Razor.targets -->
<NoWarn>$(NoWarn);NU5129</NoWarn>
<!-- Cannot run pubternal check on net46 -->
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
<!-- Need to build this project in source build -->
<ExcludeFromSourceBuild>false</ExcludeFromSourceBuild>
</PropertyGroup>

View File

@ -1,7 +1,6 @@
<Project>
<PropertyGroup>
<ToolSharedSourceRoot>$(MSBuildThisFileDirectory)Shared\</ToolSharedSourceRoot>
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
</PropertyGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />