未验证 提交 76c02fed 编写于 作者: D dotnet-automerge-bot 提交者: GitHub

Merge pull request #31193 from dotnet/merges/dev16.0-preview2-to-master

Merge dev16.0-preview2 to master
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
......@@ -12,16 +13,20 @@ namespace Microsoft.CodeAnalysis.Diagnostics
{
internal partial class SuppressMessageAttributeState
{
private static readonly SmallDictionary<string, TargetScope> s_suppressMessageScopeTypes = new SmallDictionary<string, TargetScope>()
private static readonly SmallDictionary<string, TargetScope> s_suppressMessageScopeTypes = new SmallDictionary<string, TargetScope>(StringComparer.OrdinalIgnoreCase)
{
{ null, TargetScope.None },
{ string.Empty, TargetScope.None },
{ "module", TargetScope.Module },
{ "namespace", TargetScope.Namespace },
{ "resource", TargetScope.Resource },
{ "type", TargetScope.Type },
{ "member", TargetScope.Member }
{ "member", TargetScope.Member },
{ "namespaceandchildren", TargetScope.NamespaceAndChildren }
};
private static bool TryGetTargetScope(SuppressMessageInfo info, out TargetScope scope)
=> s_suppressMessageScopeTypes.TryGetValue(info.Scope ?? string.Empty, out scope);
private readonly Compilation _compilation;
private GlobalSuppressions _lazyGlobalSuppressions;
private readonly ConcurrentDictionary<ISymbol, ImmutableDictionary<string, SuppressMessageInfo>> _localSuppressionsBySymbol;
......@@ -56,14 +61,31 @@ public bool HasCompilationWideSuppression(string id, out SuppressMessageInfo inf
return _compilationWideSuppressions.TryGetValue(id, out info);
}
public bool HasGlobalSymbolSuppression(ISymbol symbol, string id, out SuppressMessageInfo info)
public bool HasGlobalSymbolSuppression(ISymbol symbol, string id, bool isImmediatelyContainingSymbol, out SuppressMessageInfo info)
{
Debug.Assert(symbol != null);
Dictionary<string, SuppressMessageInfo> suppressions;
if (_globalSymbolSuppressions.TryGetValue(symbol, out suppressions) &&
suppressions.TryGetValue(id, out info))
{
return true;
if (symbol.Kind != SymbolKind.Namespace)
{
return true;
}
if (TryGetTargetScope(info, out TargetScope targetScope))
{
switch (targetScope)
{
case TargetScope.Namespace:
// Special case: Only suppress syntax diagnostics in namespace declarations if the namespace is the closest containing symbol.
// In other words, only apply suppression to the immediately containing namespace declaration and not to its children or parents.
return isImmediatelyContainingSymbol;
case TargetScope.NamespaceAndChildren:
return true;
}
}
}
info = default(SuppressMessageInfo);
......@@ -118,7 +140,7 @@ private bool IsDiagnosticSuppressed(string id, Location location, out SuppressMe
info = default(SuppressMessageInfo);
if (IsDiagnosticGloballySuppressed(id, symbolOpt: null, info: out info))
if (IsDiagnosticGloballySuppressed(id, symbolOpt: null, isImmediatelyContainingSymbol: false, info: out info))
{
return true;
}
......@@ -140,28 +162,46 @@ private bool IsDiagnosticSuppressed(string id, Location location, out SuppressMe
{
if (symbol.Kind == SymbolKind.Namespace)
{
// Special case: Only suppress syntax diagnostics in namespace declarations if the namespace is the closest containing symbol.
// In other words, only apply suppression to the immediately containing namespace declaration and not to its children or parents.
return inImmediatelyContainingSymbol && IsDiagnosticGloballySuppressed(id, symbol, out info);
return hasNamespaceSuppression((INamespaceSymbol)symbol, inImmediatelyContainingSymbol);
}
else if (IsDiagnosticLocallySuppressed(id, symbol, out info) || IsDiagnosticGloballySuppressed(id, symbol, out info))
else if (IsDiagnosticLocallySuppressed(id, symbol, out info) || IsDiagnosticGloballySuppressed(id, symbol, inImmediatelyContainingSymbol, out info))
{
return true;
}
}
if (!declaredSymbols.IsEmpty)
{
inImmediatelyContainingSymbol = false;
}
}
}
return false;
bool hasNamespaceSuppression(INamespaceSymbol namespaceSymbol, bool inImmediatelyContainingSymbol)
{
do
{
if (IsDiagnosticGloballySuppressed(id, namespaceSymbol, inImmediatelyContainingSymbol, out _))
{
return true;
}
namespaceSymbol = namespaceSymbol.ContainingNamespace;
inImmediatelyContainingSymbol = false;
}
while (namespaceSymbol != null);
return false;
}
}
private bool IsDiagnosticGloballySuppressed(string id, ISymbol symbolOpt, out SuppressMessageInfo info)
private bool IsDiagnosticGloballySuppressed(string id, ISymbol symbolOpt, bool isImmediatelyContainingSymbol, out SuppressMessageInfo info)
{
this.DecodeGlobalSuppressMessageAttributes();
return _lazyGlobalSuppressions.HasCompilationWideSuppression(id, out info) ||
symbolOpt != null && _lazyGlobalSuppressions.HasGlobalSymbolSuppression(symbolOpt, id, out info);
symbolOpt != null && _lazyGlobalSuppressions.HasGlobalSymbolSuppression(symbolOpt, id, isImmediatelyContainingSymbol, out info);
}
private bool IsDiagnosticLocallySuppressed(string id, ISymbol symbol, out SuppressMessageInfo info)
......@@ -251,10 +291,7 @@ private static void DecodeGlobalSuppressMessageAttributes(Compilation compilatio
continue;
}
string scopeString = info.Scope != null ? info.Scope.ToLowerInvariant() : null;
TargetScope scope;
if (s_suppressMessageScopeTypes.TryGetValue(scopeString, out scope))
if (TryGetTargetScope(info, out TargetScope scope))
{
if ((scope == TargetScope.Module || scope == TargetScope.None) && info.Target == null)
{
......@@ -294,6 +331,10 @@ internal static IEnumerable<ISymbol> ResolveTargetSymbols(Compilation compilatio
new TargetSymbolResolver(compilation, scope, target).Resolve(results);
return results;
}
case TargetScope.NamespaceAndChildren:
return ResolveTargetSymbols(compilation, target, TargetScope.Namespace);
default:
return SpecializedCollections.EmptyEnumerable<ISymbol>();
}
......@@ -341,7 +382,8 @@ internal enum TargetScope
Namespace,
Resource,
Type,
Member
Member,
NamespaceAndChildren
}
}
}
......@@ -110,6 +110,101 @@ namespace N4
Diagnostic("Declaration", "N3"));
}
[Fact, WorkItem(486, "https://github.com/dotnet/roslyn/issues/486")]
public async Task GlobalSuppressionOnNamespaces_NamespaceAndChildren()
{
await VerifyCSharpAsync(@"
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage(""Test"", ""Declaration"", Scope=""NamespaceAndChildren"", Target=""N.N1"")]
[module: SuppressMessage(""Test"", ""Declaration"", Scope=""namespaceandchildren"", Target=""N4"")]
namespace N
{
namespace N1
{
namespace N2.N3
{
}
}
}
namespace N4
{
namespace N5
{
}
}
namespace N.N1.N6.N7
{
}
",
new[] { new WarningOnNamePrefixDeclarationAnalyzer("N") },
Diagnostic("Declaration", "N"));
}
[Fact, WorkItem(486, "https://github.com/dotnet/roslyn/issues/486")]
public async Task GlobalSuppressionOnTypesAndNamespaces_NamespaceAndChildren()
{
await VerifyCSharpAsync(@"
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage(""Test"", ""Declaration"", Scope=""NamespaceAndChildren"", Target=""N.N1.N2"")]
[module: SuppressMessage(""Test"", ""Declaration"", Scope=""NamespaceAndChildren"", Target=""N4"")]
[module: SuppressMessage(""Test"", ""Declaration"", Scope=""Type"", Target=""C2"")]
namespace N
{
namespace N1
{
class C1
{
}
namespace N2.N3
{
class C2
{
}
class C3
{
class C4
{
}
}
}
}
}
namespace N4
{
namespace N5
{
class C5
{
}
}
class C6
{
}
}
namespace N.N1.N2.N7
{
class C7
{
}
}
",
new[] { new WarningOnNamePrefixDeclarationAnalyzer("N"), new WarningOnNamePrefixDeclarationAnalyzer("C") },
Diagnostic("Declaration", "N"),
Diagnostic("Declaration", "N1"),
Diagnostic("Declaration", "C1"));
}
[Fact]
public async Task GlobalSuppressionOnTypes()
{
......@@ -350,6 +445,23 @@ class C {}
Diagnostic("Token", "}").WithLocation(9, 1));
}
[Fact, WorkItem(486, "https://github.com/dotnet/roslyn/issues/486")]
public async Task SuppressSyntaxDiagnosticsOnNamespaceAndChildDeclarationCSharp()
{
await VerifyTokenDiagnosticsCSharpAsync(@"
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""Test"", ""Token"", Scope=""NamespaceAndChildren"", Target=""A.B"")]
namespace A
[|{
namespace B
{
class C {}
}
}|]
",
Diagnostic("Token", "{").WithLocation(4, 1),
Diagnostic("Token", "}").WithLocation(9, 1));
}
[Fact]
public async Task SuppressSyntaxDiagnosticsOnNamespaceDeclarationBasic()
{
......@@ -370,11 +482,29 @@ End Namespace
Diagnostic("Token", "End").WithLocation(8, 1));
}
[Fact]
public async Task DontSuppressSyntaxDiagnosticsInRootNamespaceBasic()
[Fact, WorkItem(486, "https://github.com/dotnet/roslyn/issues/486")]
public async Task SuppressSyntaxDiagnosticsOnNamespaceAndChildrenDeclarationBasic()
{
await VerifyBasicAsync(@"
<module: System.Diagnostics.SuppressMessage(""Test"", ""Comment"", Scope:=""Namespace"", Target:=""RootNamespace"")>
await VerifyTokenDiagnosticsBasicAsync(@"
<assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""Test"", ""Token"", Scope:=""NamespaceAndChildren"", Target:=""A.B"")>
Namespace [|A
Namespace B
Class C
End Class
End Namespace
End|] Namespace
",
Diagnostic("Token", "A").WithLocation(3, 11),
Diagnostic("Token", "End").WithLocation(8, 1));
}
[Theory, WorkItem(486, "https://github.com/dotnet/roslyn/issues/486")]
[InlineData("Namespace")]
[InlineData("NamespaceAndChildren")]
public async Task DontSuppressSyntaxDiagnosticsInRootNamespaceBasic(string scope)
{
await VerifyBasicAsync($@"
<module: System.Diagnostics.SuppressMessage(""Test"", ""Comment"", Scope:=""{scope}"", Target:=""RootNamespace"")>
' In root namespace
",
rootNamespace: "RootNamespace",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册