Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
76c02fed
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
76c02fed
编写于
11月 15, 2018
作者:
D
dotnet-automerge-bot
提交者:
GitHub
11月 15, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #31193 from dotnet/merges/dev16.0-preview2-to-master
Merge dev16.0-preview2 to master
上级
027d0f25
8740f8bc
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
193 addition
and
21 deletion
+193
-21
src/Compilers/Core/Portable/DiagnosticAnalyzer/SuppressMessageAttributeState.cs
...table/DiagnosticAnalyzer/SuppressMessageAttributeState.cs
+59
-17
src/Test/Utilities/Portable/Diagnostics/SuppressMessageAttributeTests.cs
...ies/Portable/Diagnostics/SuppressMessageAttributeTests.cs
+134
-4
未找到文件。
src/Compilers/Core/Portable/DiagnosticAnalyzer/SuppressMessageAttributeState.cs
浏览文件 @
76c02fed
// 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
,
i
sImmediatelyContainingSymbol
:
false
,
i
nfo
:
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
}
}
}
src/Test/Utilities/Portable/Diagnostics/SuppressMessageAttributeTests.cs
浏览文件 @
76c02fed
...
...
@@ -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
DontSuppressSyntaxDiagnosticsInRootNamespace
Basic
()
[
Fact
,
WorkItem
(
486
,
"https://github.com/dotnet/roslyn/issues/486"
)
]
public
async
Task
SuppressSyntaxDiagnosticsOnNamespaceAndChildrenDeclaration
Basic
()
{
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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录