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:
parent
5fbd1eb007
commit
059e2fdc49
|
|
@ -140,20 +140,6 @@
|
||||||
<InternalInstallerBaseName>$(RuntimeInstallerBaseName)-internal</InternalInstallerBaseName>
|
<InternalInstallerBaseName>$(RuntimeInstallerBaseName)-internal</InternalInstallerBaseName>
|
||||||
</PropertyGroup>
|
</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 -->
|
<!-- Compilation options which apply to all languages. Language-specific options should be set in eng/targets/$(lang).Common.props -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<BuildArchitecture>$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant())</BuildArchitecture>
|
<BuildArchitecture>$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant())</BuildArchitecture>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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>
|
|
||||||
|
|
@ -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" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<IsShipping>false</IsShipping>
|
<IsShipping>false</IsShipping>
|
||||||
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
|
|
||||||
|
|
||||||
<UseAppHost>false</UseAppHost>
|
<UseAppHost>false</UseAppHost>
|
||||||
<RuntimeIdentifier />
|
<RuntimeIdentifier />
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
<!-- Shared between targeting pack and runtime build. -->
|
<!-- Shared between targeting pack and runtime build. -->
|
||||||
<PlatformManifestFileName>PlatformManifest.txt</PlatformManifestFileName>
|
<PlatformManifestFileName>PlatformManifest.txt</PlatformManifestFileName>
|
||||||
<PlatformManifestOutputPath>$(ArtifactsObjDir)$(PlatformManifestFileName)</PlatformManifestOutputPath>
|
<PlatformManifestOutputPath>$(ArtifactsObjDir)$(PlatformManifestFileName)</PlatformManifestOutputPath>
|
||||||
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
|
|
||||||
|
|
||||||
<!-- Platform manifest and package override metatdata -->
|
<!-- Platform manifest and package override metatdata -->
|
||||||
<ReferencePackSharedFxVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).0</ReferencePackSharedFxVersion>
|
<ReferencePackSharedFxVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).0</ReferencePackSharedFxVersion>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
|
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
|
|
||||||
<OutputPath>$(InstallersOutputPath)</OutputPath>
|
<OutputPath>$(InstallersOutputPath)</OutputPath>
|
||||||
<IntermediateOutputPath>$(IntermediateOutputPath)$(TargetRuntimeIdentifier)\</IntermediateOutputPath>
|
<IntermediateOutputPath>$(IntermediateOutputPath)$(TargetRuntimeIdentifier)\</IntermediateOutputPath>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@
|
||||||
<NoWarn>$(NoWarn);NU5100</NoWarn>
|
<NoWarn>$(NoWarn);NU5100</NoWarn>
|
||||||
<!-- It is intentional to not include build/netstandard2.0/Microsoft.NET.Sdk.Razor.targets -->
|
<!-- It is intentional to not include build/netstandard2.0/Microsoft.NET.Sdk.Razor.targets -->
|
||||||
<NoWarn>$(NoWarn);NU5129</NoWarn>
|
<NoWarn>$(NoWarn);NU5129</NoWarn>
|
||||||
<!-- Cannot run pubternal check on net46 -->
|
|
||||||
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
|
|
||||||
<!-- Need to build this project in source build -->
|
<!-- Need to build this project in source build -->
|
||||||
<ExcludeFromSourceBuild>false</ExcludeFromSourceBuild>
|
<ExcludeFromSourceBuild>false</ExcludeFromSourceBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ToolSharedSourceRoot>$(MSBuildThisFileDirectory)Shared\</ToolSharedSourceRoot>
|
<ToolSharedSourceRoot>$(MSBuildThisFileDirectory)Shared\</ToolSharedSourceRoot>
|
||||||
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
|
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue