Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
34fdb697
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,发现更多精彩内容 >>
未验证
提交
34fdb697
编写于
3月 30, 2020
作者:
R
Rikki Gibson
提交者:
GitHub
3月 30, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Customizable Obsolete diagnostics (#42518)
上级
14f447e8
变更
17
展开全部
显示空白变更内容
内联
并排
Showing
17 changed file
with
2753 addition
and
60 deletion
+2753
-60
src/Compilers/CSharp/Portable/Symbols/Attributes/AttributeData.cs
...ilers/CSharp/Portable/Symbols/Attributes/AttributeData.cs
+16
-0
src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs
...ilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs
+17
-17
src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsByRefLike.cs
...CSharp/Test/Emit/Attributes/AttributeTests_IsByRefLike.cs
+1
-1
src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs
...est/Emit/Attributes/AttributeTests_WellKnownAttributes.cs
+1164
-0
src/Compilers/Core/Portable/Diagnostic/CustomObsoleteDiagnosticInfo.cs
.../Core/Portable/Diagnostic/CustomObsoleteDiagnosticInfo.cs
+108
-0
src/Compilers/Core/Portable/Diagnostic/DiagnosticInfo.cs
src/Compilers/Core/Portable/Diagnostic/DiagnosticInfo.cs
+2
-2
src/Compilers/Core/Portable/Diagnostic/WellKnownDiagnosticTags.cs
...ilers/Core/Portable/Diagnostic/WellKnownDiagnosticTags.cs
+6
-0
src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs
...Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs
+11
-5
src/Compilers/Core/Portable/MetadataReader/PEModule.cs
src/Compilers/Core/Portable/MetadataReader/PEModule.cs
+89
-21
src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
+2
-1
src/Compilers/Core/Portable/Symbols/Attributes/CommonAttributeData.cs
...s/Core/Portable/Symbols/Attributes/CommonAttributeData.cs
+31
-2
src/Compilers/Core/Portable/Symbols/Attributes/ObsoleteAttributeData.cs
...Core/Portable/Symbols/Attributes/ObsoleteAttributeData.cs
+35
-4
src/Compilers/VisualBasic/Portable/Errors/ErrorFactories.vb
src/Compilers/VisualBasic/Portable/Errors/ErrorFactories.vb
+4
-0
src/Compilers/VisualBasic/Portable/Symbols/Attributes/AttributeData.vb
.../VisualBasic/Portable/Symbols/Attributes/AttributeData.vb
+13
-0
src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb
.../VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb
+5
-5
src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests_ObsoleteAttribute.vb
.../Test/Emit/Attributes/AttributeTests_ObsoleteAttribute.vb
+1246
-0
src/Test/Utilities/Portable/Diagnostics/DiagnosticDescription.cs
...t/Utilities/Portable/Diagnostics/DiagnosticDescription.cs
+3
-2
未找到文件。
src/Compilers/CSharp/Portable/Symbols/Attributes/AttributeData.cs
浏览文件 @
34fdb697
...
...
@@ -644,6 +644,22 @@ internal string DecodeGuidAttribute(AttributeSyntax? nodeOpt, DiagnosticBag diag
return
guidString
;
}
private
protected
sealed
override
bool
IsStringProperty
(
string
memberName
)
{
if
(
AttributeClass
is
object
)
{
foreach
(
var
member
in
AttributeClass
.
GetMembers
(
memberName
))
{
if
(
member
is
PropertySymbol
{
Type
:
{
SpecialType
:
SpecialType
.
System_String
}
})
{
return
true
;
}
}
}
return
false
;
}
#
endregion
/// <summary>
...
...
src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs
浏览文件 @
34fdb697
...
...
@@ -39,8 +39,7 @@ internal static void InitializeObsoleteDataFromMetadata(ref ObsoleteAttributeDat
/// </summary>
internal
static
ObsoleteAttributeData
GetObsoleteDataFromMetadata
(
EntityHandle
token
,
PEModuleSymbol
containingModule
,
bool
ignoreByRefLikeMarker
)
{
ObsoleteAttributeData
obsoleteAttributeData
;
obsoleteAttributeData
=
containingModule
.
Module
.
TryGetDeprecatedOrExperimentalOrObsoleteAttribute
(
token
,
ignoreByRefLikeMarker
);
var
obsoleteAttributeData
=
containingModule
.
Module
.
TryGetDeprecatedOrExperimentalOrObsoleteAttribute
(
token
,
new
MetadataDecoder
(
containingModule
),
ignoreByRefLikeMarker
);
Debug
.
Assert
(
obsoleteAttributeData
==
null
||
!
obsoleteAttributeData
.
IsUninitialized
);
return
obsoleteAttributeData
;
}
...
...
@@ -156,22 +155,23 @@ internal static DiagnosticInfo CreateObsoleteDiagnostic(Symbol symbol, BinderFla
}
// Issue a specialized diagnostic for add methods of collection initializers
bool
isColInit
=
location
.
Includes
(
BinderFlags
.
CollectionInitializerAddMethod
);
if
(
data
.
Message
==
null
)
{
// It seems like we should be able to assert that data.IsError is false, but we can't because dev11 had
// a bug in this area (i.e. always produce a warning when there's no message) and we have to match it.
// Debug.Assert(!data.IsError);
return
new
CSDiagnosticInfo
(
isColInit
?
ErrorCode
.
WRN_DeprecatedCollectionInitAdd
:
ErrorCode
.
WRN_DeprecatedSymbol
,
symbol
);
}
else
{
ErrorCode
errorCode
=
data
.
IsError
?
(
isColInit
?
ErrorCode
.
ERR_DeprecatedCollectionInitAddStr
:
ErrorCode
.
ERR_DeprecatedSymbolStr
)
:
(
isColInit
?
ErrorCode
.
WRN_DeprecatedCollectionInitAddStr
:
ErrorCode
.
WRN_DeprecatedSymbolStr
);
return
new
CSDiagnosticInfo
(
errorCode
,
symbol
,
data
.
Message
);
}
var
isColInit
=
location
.
Includes
(
BinderFlags
.
CollectionInitializerAddMethod
);
var
errorCode
=
(
message
:
data
.
Message
,
isError
:
data
.
IsError
,
isColInit
)
switch
{
// dev11 had a bug in this area (i.e. always produce a warning when there's no message) and we have to match it.
(
message
:
null
,
isError
:
_
,
isColInit
:
true
)
=>
ErrorCode
.
WRN_DeprecatedCollectionInitAdd
,
(
message
:
null
,
isError
:
_
,
isColInit
:
false
)
=>
ErrorCode
.
WRN_DeprecatedSymbol
,
(
message
:
{
},
isError
:
true
,
isColInit
:
true
)
=>
ErrorCode
.
ERR_DeprecatedCollectionInitAddStr
,
(
message
:
{
},
isError
:
true
,
isColInit
:
false
)
=>
ErrorCode
.
ERR_DeprecatedSymbolStr
,
(
message
:
{
},
isError
:
false
,
isColInit
:
true
)
=>
ErrorCode
.
WRN_DeprecatedCollectionInitAddStr
,
(
message
:
{
},
isError
:
false
,
isColInit
:
false
)
=>
ErrorCode
.
WRN_DeprecatedSymbolStr
};
var
arguments
=
data
.
Message
is
string
message
?
new
object
[]
{
symbol
,
message
}
:
new
object
[]
{
symbol
};
return
new
CustomObsoleteDiagnosticInfo
(
MessageProvider
.
Instance
,
(
int
)
errorCode
,
data
,
arguments
);
}
}
}
src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsByRefLike.cs
浏览文件 @
34fdb697
...
...
@@ -999,7 +999,7 @@ private static void AssertReferencedIsByRefLike(TypeSymbol type, bool hasObsolet
Assert
.
Empty
(
peType
.
GetAttributes
());
var
peModule
=
(
PEModuleSymbol
)
peType
.
ContainingModule
;
var
obsoleteAttribute
=
peModule
.
Module
.
TryGetDeprecatedOrExperimentalOrObsoleteAttribute
(
peType
.
Handle
,
ignoreByRefLikeMarker
:
false
);
var
obsoleteAttribute
=
peModule
.
Module
.
TryGetDeprecatedOrExperimentalOrObsoleteAttribute
(
peType
.
Handle
,
new
MetadataDecoder
(
peModule
),
ignoreByRefLikeMarker
:
false
);
if
(
hasObsolete
)
{
...
...
src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs
浏览文件 @
34fdb697
此差异已折叠。
点击以展开。
src/Compilers/Core/Portable/Diagnostic/CustomObsoleteDiagnosticInfo.cs
0 → 100644
浏览文件 @
34fdb697
// 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.
#
nullable
enable
using
System.Collections
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Threading
;
using
Microsoft.CodeAnalysis.PooledObjects
;
namespace
Microsoft.CodeAnalysis
{
internal
sealed
class
CustomObsoleteDiagnosticInfo
:
DiagnosticInfo
{
private
DiagnosticDescriptor
?
_descriptor
;
internal
ObsoleteAttributeData
Data
{
get
;
}
internal
CustomObsoleteDiagnosticInfo
(
CommonMessageProvider
messageProvider
,
int
errorCode
,
ObsoleteAttributeData
data
,
params
object
[]
arguments
)
:
base
(
messageProvider
,
errorCode
,
arguments
)
{
Data
=
data
;
}
public
override
string
MessageIdentifier
{
get
{
var
id
=
Data
.
DiagnosticId
;
if
(!
string
.
IsNullOrEmpty
(
id
))
{
return
id
;
}
return
base
.
MessageIdentifier
;
}
}
public
override
DiagnosticDescriptor
Descriptor
{
get
{
if
(
_descriptor
==
null
)
{
Interlocked
.
CompareExchange
(
ref
_descriptor
,
CreateDescriptor
(),
null
);
}
return
_descriptor
;
}
}
private
DiagnosticDescriptor
CreateDescriptor
()
{
var
baseDescriptor
=
base
.
Descriptor
;
var
diagnosticId
=
Data
.
DiagnosticId
;
var
urlFormat
=
Data
.
UrlFormat
;
if
(
diagnosticId
is
null
&&
urlFormat
is
null
)
{
return
baseDescriptor
;
}
var
id
=
MessageIdentifier
;
var
helpLinkUri
=
baseDescriptor
.
HelpLinkUri
;
if
(
urlFormat
is
object
)
{
try
{
helpLinkUri
=
string
.
Format
(
urlFormat
,
id
);
}
catch
{
// if string.Format fails we just want to use the default (non-user specified) URI.
}
}
ImmutableArray
<
string
>
customTags
;
if
(
diagnosticId
is
null
)
{
customTags
=
baseDescriptor
.
CustomTags
.
ToImmutableArray
();
}
else
{
var
capacity
=
1
;
if
(
baseDescriptor
.
CustomTags
is
ICollection
<
string
>
{
Count
:
int
count
})
{
capacity
+=
count
;
}
var
tagsBuilder
=
ArrayBuilder
<
string
>.
GetInstance
(
capacity
);
tagsBuilder
.
AddRange
(
baseDescriptor
.
CustomTags
);
tagsBuilder
.
Add
(
WellKnownDiagnosticTags
.
CustomObsolete
);
customTags
=
tagsBuilder
.
ToImmutableAndFree
();
}
return
new
DiagnosticDescriptor
(
id
:
id
,
title
:
baseDescriptor
.
Title
,
messageFormat
:
baseDescriptor
.
MessageFormat
,
category
:
baseDescriptor
.
Category
,
defaultSeverity
:
baseDescriptor
.
DefaultSeverity
,
isEnabledByDefault
:
baseDescriptor
.
IsEnabledByDefault
,
description
:
baseDescriptor
.
Description
,
helpLinkUri
:
helpLinkUri
,
customTags
:
customTags
);
}
}
}
src/Compilers/Core/Portable/Diagnostic/DiagnosticInfo.cs
浏览文件 @
34fdb697
...
...
@@ -199,7 +199,7 @@ protected DiagnosticInfo(ObjectReader reader)
/// </summary>
public
int
Code
{
get
{
return
_errorCode
;
}
}
public
DiagnosticDescriptor
Descriptor
public
virtual
DiagnosticDescriptor
Descriptor
{
get
{
...
...
@@ -314,7 +314,7 @@ public virtual IReadOnlyList<Location> AdditionalLocations
/// Get the message id (for example "CS1001") for the message. This includes both the error number
/// and a prefix identifying the source.
/// </summary>
public
string
MessageIdentifier
public
virtual
string
MessageIdentifier
{
get
{
...
...
src/Compilers/Core/Portable/Diagnostic/WellKnownDiagnosticTags.cs
浏览文件 @
34fdb697
...
...
@@ -44,5 +44,11 @@ public static class WellKnownDiagnosticTags
/// Indicates that the diagnostic is related to an exception thrown by a <see cref="DiagnosticAnalyzer"/>.
/// </summary>
public
const
string
AnalyzerException
=
nameof
(
AnalyzerException
);
/// <summary>
/// Indicates that the diagnostic is an obsolete diagnostic with a custom ID
/// specified by the 'DiagnosticId' property on 'ObsoleteAttribute'.
/// </summary>
public
const
string
CustomObsolete
=
nameof
(
CustomObsolete
);
}
}
src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs
浏览文件 @
34fdb697
...
...
@@ -71,8 +71,14 @@ internal LocalInfo<TypeSymbol> WithSignature(byte[] signature)
}
#
nullable
enable
internal
interface
IAttributeNamedArgumentDecoder
{
(
KeyValuePair
<
string
,
TypedConstant
>
nameValuePair
,
bool
isProperty
,
SerializationTypeCode
typeCode
)
DecodeCustomAttributeNamedArgumentOrThrow
(
ref
BlobReader
argReader
);
}
internal
abstract
class
MetadataDecoder
<
ModuleSymbol
,
TypeSymbol
,
MethodSymbol
,
FieldSymbol
,
Symbol
>
:
TypeNameDecoder
<
ModuleSymbol
,
TypeSymbol
>
TypeNameDecoder
<
ModuleSymbol
,
TypeSymbol
>,
IAttributeNamedArgumentDecoder
where
ModuleSymbol
:
class
,
IModuleSymbolInternal
where
TypeSymbol
:
class
,
Symbol
,
ITypeSymbolInternal
where
MethodSymbol
:
class
,
Symbol
,
IMethodSymbolInternal
...
...
@@ -1602,7 +1608,7 @@ private static TypedConstantKind GetPrimitiveOrEnumTypedConstantKind(TypeSymbol
/// <exception cref="UnsupportedSignatureContent">If the encoded named argument is invalid.</exception>
/// <exception cref="BadImageFormatException">An exception from metadata reader.</exception>
p
rivate
KeyValuePair
<
string
,
TypedConstant
>
DecodeCustomAttributeNamedArgumentOrThrow
(
ref
BlobReader
argReader
)
p
ublic
(
KeyValuePair
<
string
,
TypedConstant
>
nameValuePair
,
bool
isProperty
,
SerializationTypeCode
typeCode
)
DecodeCustomAttributeNamedArgumentOrThrow
(
ref
BlobReader
argReader
)
{
// Ecma-335 23.3 - A NamedArg is simply a FixedArg preceded by information to identify which field or
// property it represents. [Note: Recall that the CLI allows fields and properties to have the same name; so
...
...
@@ -1629,7 +1635,7 @@ private static TypedConstantKind GetPrimitiveOrEnumTypedConstantKind(TypeSymbol
?
DecodeCustomAttributeElementArrayOrThrow
(
ref
argReader
,
elementTypeCode
,
elementType
,
type
)
:
DecodeCustomAttributeElementOrThrow
(
ref
argReader
,
typeCode
,
type
);
return
new
KeyValuePair
<
string
,
TypedConstant
>(
name
,
valu
e
);
return
(
new
KeyValuePair
<
string
,
TypedConstant
>(
name
,
value
),
kind
==
CustomAttributeNamedArgumentKind
.
Property
,
typeCod
e
);
}
internal
bool
IsTargetAttribute
(
...
...
@@ -1675,7 +1681,7 @@ internal int GetTargetAttributeSignatureIndex(CustomAttributeHandle customAttrib
try
{
positionalArgs
=
Array
.
Empty
<
TypedConstant
>();
namedArgs
=
Array
.
Empty
<
KeyValuePair
<
S
tring
,
TypedConstant
>>();
namedArgs
=
Array
.
Empty
<
KeyValuePair
<
s
tring
,
TypedConstant
>>();
// We could call decoder.GetSignature and use that to decode the arguments. However, materializing the
// constructor signature is more work. We try to decode the arguments directly from the metadata bytes.
...
...
@@ -1730,7 +1736,7 @@ internal int GetTargetAttributeSignatureIndex(CustomAttributeHandle customAttrib
for
(
int
i
=
0
;
i
<
namedArgs
.
Length
;
i
++)
{
namedArgs
[
i
]
=
DecodeCustomAttributeNamedArgumentOrThrow
(
ref
argsReader
);
(
namedArgs
[
i
],
_
,
_
)
=
DecodeCustomAttributeNamedArgumentOrThrow
(
ref
argsReader
);
}
}
...
...
src/Compilers/Core/Portable/MetadataReader/PEModule.cs
浏览文件 @
34fdb697
...
...
@@ -7,6 +7,7 @@
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Diagnostics.CodeAnalysis
;
using
System.Linq
;
using
System.Reflection
;
using
System.Reflection.Metadata
;
...
...
@@ -93,7 +94,6 @@ internal sealed class PEModule : IDisposable
private
static
readonly
AttributeValueExtractor
<
ImmutableArray
<
bool
>>
s_attributeBoolArrayValueExtractor
=
CrackBoolArrayInAttributeValue
;
private
static
readonly
AttributeValueExtractor
<
ImmutableArray
<
byte
>>
s_attributeByteArrayValueExtractor
=
CrackByteArrayInAttributeValue
;
private
static
readonly
AttributeValueExtractor
<
ImmutableArray
<
string
>>
s_attributeStringArrayValueExtractor
=
CrackStringArrayInAttributeValue
;
private
static
readonly
AttributeValueExtractor
<
ObsoleteAttributeData
>
s_attributeObsoleteDataExtractor
=
CrackObsoleteAttributeData
;
private
static
readonly
AttributeValueExtractor
<
ObsoleteAttributeData
>
s_attributeDeprecatedDataExtractor
=
CrackDeprecatedAttributeData
;
private
static
readonly
AttributeValueExtractor
<
BoolAndStringArrayData
>
s_attributeBoolAndStringArrayValueExtractor
=
CrackBoolAndStringArrayInAttributeValue
;
private
static
readonly
AttributeValueExtractor
<
BoolAndStringData
>
s_attributeBoolAndStringValueExtractor
=
CrackBoolAndStringInAttributeValue
;
...
...
@@ -1080,6 +1080,7 @@ internal bool HasIsByRefLikeAttribute(EntityHandle token)
internal
ObsoleteAttributeData
TryGetDeprecatedOrExperimentalOrObsoleteAttribute
(
EntityHandle
token
,
IAttributeNamedArgumentDecoder
decoder
,
bool
ignoreByRefLikeMarker
)
{
AttributeInfo
info
;
...
...
@@ -1093,7 +1094,7 @@ internal bool HasIsByRefLikeAttribute(EntityHandle token)
info
=
FindTargetAttribute
(
token
,
AttributeDescription
.
ObsoleteAttribute
);
if
(
info
.
HasValue
)
{
ObsoleteAttributeData
obsoleteData
=
TryExtractObsoleteDataFromAttribute
(
info
);
ObsoleteAttributeData
obsoleteData
=
TryExtractObsoleteDataFromAttribute
(
info
,
decoder
);
switch
(
obsoleteData
?.
Message
)
{
case
ByRefLikeMarker
when
ignoreByRefLikeMarker
:
...
...
@@ -1332,37 +1333,74 @@ private ArrayBuilder<string> ExtractStringValuesFromAttributes(List<AttributeInf
return
result
;
}
private
ObsoleteAttributeData
TryExtractObsoleteDataFromAttribute
(
AttributeInfo
attributeInfo
)
#
nullable
enable
private
ObsoleteAttributeData
?
TryExtractObsoleteDataFromAttribute
(
AttributeInfo
attributeInfo
,
IAttributeNamedArgumentDecoder
decoder
)
{
Debug
.
Assert
(
attributeInfo
.
HasValue
);
if
(!
TryGetAttributeReader
(
attributeInfo
.
Handle
,
out
var
sig
))
{
return
null
;
}
string
?
message
=
null
;
bool
isError
=
false
;
switch
(
attributeInfo
.
SignatureIndex
)
{
case
0
:
// ObsoleteAttribute()
return
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Obsolete
,
message
:
null
,
isError
:
false
);
break
;
case
1
:
// ObsoleteAttribute(string)
string
message
;
if
(
TryExtractStringValueFromAttribute
(
attributeInfo
.
Handle
,
out
message
))
if
(
sig
.
RemainingBytes
>
0
&&
CrackStringInAttributeValue
(
out
message
,
ref
sig
))
{
return
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Obsolete
,
message
,
isError
:
false
)
;
break
;
}
return
null
;
case
2
:
// ObsoleteAttribute(string, bool)
return
TryExtractValueFromAttribute
(
attributeInfo
.
Handle
,
out
var
obsoleteData
,
s_attributeObsoleteDataExtractor
)
?
obsoleteData
:
null
;
if
(
sig
.
RemainingBytes
>
0
&&
CrackStringInAttributeValue
(
out
message
,
ref
sig
)
&&
sig
.
RemainingBytes
>
0
&&
CrackBooleanInAttributeValue
(
out
isError
,
ref
sig
))
{
break
;
}
return
null
;
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
attributeInfo
.
SignatureIndex
);
}
(
string
?
diagnosticId
,
string
?
urlFormat
)
=
sig
.
RemainingBytes
>
0
?
CrackObsoleteProperties
(
ref
sig
,
decoder
)
:
default
;
return
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Obsolete
,
message
,
isError
,
diagnosticId
,
urlFormat
);
}
private
bool
TryGetAttributeReader
(
CustomAttributeHandle
handle
,
out
BlobReader
blobReader
)
{
Debug
.
Assert
(!
handle
.
IsNil
);
try
{
var
valueBlob
=
GetCustomAttributeValueOrThrow
(
handle
);
if
(!
valueBlob
.
IsNil
)
{
blobReader
=
MetadataReader
.
GetBlobReader
(
valueBlob
);
if
(
blobReader
.
Length
>=
4
)
{
// check prolog
if
(
blobReader
.
ReadInt16
()
==
1
)
{
return
true
;
}
}
}
}
catch
(
BadImageFormatException
)
{
}
blobReader
=
default
;
return
false
;
}
#
nullable
restore
private
ObsoleteAttributeData
TryExtractDeprecatedDataFromAttribute
(
AttributeInfo
attributeInfo
)
{
Debug
.
Assert
(
attributeInfo
.
HasValue
);
...
...
@@ -1643,26 +1681,56 @@ private bool HasStringAndIntValuedAttribute(EntityHandle token, AttributeDescrip
}
}
private
static
bool
CrackObsoleteAttributeData
(
out
ObsoleteAttributeData
value
,
ref
BlobReader
sig
)
#
nullable
enable
/// <summary>
/// Gets the well-known optional named properties on ObsoleteAttribute, if present.
/// Both 'diagnosticId' and 'urlFormat' may be present, or only one, or neither.
/// </summary>
/// <remarks>
/// Failure to find any of these properties does not imply failure to decode the ObsoleteAttribute,
/// so we don't return a value indicating success or failure.
/// </remarks>
private
static
(
string
?
diagnosticId
,
string
?
urlFormat
)
CrackObsoleteProperties
(
ref
BlobReader
sig
,
IAttributeNamedArgumentDecoder
decoder
)
{
string
?
diagnosticId
=
null
;
string
?
urlFormat
=
null
;
try
{
string
message
;
if
(
CrackStringInAttributeValue
(
out
message
,
ref
sig
)
&&
sig
.
RemainingBytes
>=
1
)
// See CIL spec section II.23.3 Custom attributes
//
// Next is a description of the optional “named” fields and properties.
// This starts with NumNamed– an unsigned int16 giving the number of “named” properties or fields that follow.
var
numNamed
=
sig
.
ReadUInt16
();
for
(
int
i
=
0
;
i
<
numNamed
&&
(
diagnosticId
is
null
||
urlFormat
is
null
);
i
++)
{
bool
isError
=
sig
.
ReadBoolean
();
value
=
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Obsolete
,
message
,
isError
);
return
true
;
var
((
name
,
value
),
isProperty
,
typeCode
)
=
decoder
.
DecodeCustomAttributeNamedArgumentOrThrow
(
ref
sig
);
if
(
typeCode
==
SerializationTypeCode
.
String
&&
isProperty
&&
value
.
ValueInternal
is
string
stringValue
)
{
if
(
diagnosticId
is
null
&&
name
==
ObsoleteAttributeData
.
DiagnosticIdPropertyName
)
{
diagnosticId
=
stringValue
;
}
else
if
(
urlFormat
is
null
&&
name
==
ObsoleteAttributeData
.
UrlFormatPropertyName
)
{
urlFormat
=
stringValue
;
}
}
}
}
catch
(
BadImageFormatException
)
{
}
catch
(
UnsupportedSignatureContent
)
{
}
value
=
null
;
return
false
;
return
(
diagnosticId
,
urlFormat
);
}
#
nullable
restore
private
static
bool
CrackDeprecatedAttributeData
(
out
ObsoleteAttributeData
value
,
ref
BlobReader
sig
)
{
StringAndInt
args
;
if
(
CrackStringAndIntInAttributeValue
(
out
args
,
ref
sig
))
{
value
=
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Deprecated
,
args
.
StringValue
,
args
.
IntValue
==
1
);
value
=
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Deprecated
,
args
.
StringValue
,
args
.
IntValue
==
1
,
diagnosticId
:
null
,
urlFormat
:
null
);
return
true
;
}
...
...
src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
浏览文件 @
34fdb697
Microsoft.CodeAnalysis.CommandLineSourceFile.CommandLineSourceFile(string path, bool isScript, bool isInputRedirected) -> void
Microsoft.CodeAnalysis.CommandLineSourceFile.IsInputRedirected.get -> bool
const Microsoft.CodeAnalysis.WellKnownDiagnosticTags.CustomObsolete = "CustomObsolete" -> string
src/Compilers/Core/Portable/Symbols/Attributes/CommonAttributeData.cs
浏览文件 @
34fdb697
...
...
@@ -9,6 +9,7 @@
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Diagnostics.CodeAnalysis
;
using
System.Linq
;
using
System.Reflection
;
using
System.Runtime.CompilerServices
;
using
System.Runtime.InteropServices
;
...
...
@@ -292,9 +293,37 @@ private ObsoleteAttributeData DecodeObsoleteAttribute()
}
}
return
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Obsolete
,
message
,
isError
);
string
?
diagnosticId
=
null
;
string
?
urlFormat
=
null
;
foreach
(
var
(
name
,
value
)
in
this
.
CommonNamedArguments
)
{
if
(
diagnosticId
is
null
&&
name
==
ObsoleteAttributeData
.
DiagnosticIdPropertyName
&&
IsStringProperty
(
ObsoleteAttributeData
.
DiagnosticIdPropertyName
))
{
diagnosticId
=
value
.
ValueInternal
as
string
;
}
else
if
(
urlFormat
is
null
&&
name
==
ObsoleteAttributeData
.
UrlFormatPropertyName
&&
IsStringProperty
(
ObsoleteAttributeData
.
UrlFormatPropertyName
))
{
urlFormat
=
value
.
ValueInternal
as
string
;
}
if
(
diagnosticId
is
object
&&
urlFormat
is
object
)
{
break
;
}
}
return
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Obsolete
,
message
,
isError
,
diagnosticId
,
urlFormat
);
}
// Note: it is disallowed to declare a property and a field
// with the same name in C# or VB source, even if it is allowed in IL.
//
// We use a virtual method and override to prevent having to realize the public symbols just to decode obsolete attributes.
// Ideally we would use an abstract method, but that would require making the method visible to
// public consumers who inherit from this class, which we don't want to do.
// Therefore we just make it a 'private protected virtual' method instead.
private
protected
virtual
bool
IsStringProperty
(
string
memberName
)
=>
throw
ExceptionUtilities
.
Unreachable
;
/// <summary>
/// Decode the arguments to DeprecatedAttribute. DeprecatedAttribute can have 3 or 4 arguments.
/// </summary>
...
...
@@ -316,7 +345,7 @@ private ObsoleteAttributeData DecodeDeprecatedAttribute()
isError
=
((
int
)
args
[
1
].
ValueInternal
==
1
);
}
return
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Deprecated
,
message
,
isError
);
return
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Deprecated
,
message
,
isError
,
diagnosticId
:
null
,
urlFormat
:
null
);
}
/// <summary>
...
...
src/Compilers/Core/Portable/Symbols/Attributes/ObsoleteAttributeData.cs
浏览文件 @
34fdb697
...
...
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System
;
namespace
Microsoft.CodeAnalysis
...
...
@@ -20,14 +22,19 @@ internal enum ObsoleteAttributeKind
/// </summary>
internal
sealed
class
ObsoleteAttributeData
{
public
static
readonly
ObsoleteAttributeData
Uninitialized
=
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Uninitialized
,
null
,
false
);
public
static
readonly
ObsoleteAttributeData
Experimental
=
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Experimental
,
null
,
false
);
public
static
readonly
ObsoleteAttributeData
Uninitialized
=
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Uninitialized
,
message
:
null
,
isError
:
false
,
diagnosticId
:
null
,
urlFormat
:
null
);
public
static
readonly
ObsoleteAttributeData
Experimental
=
new
ObsoleteAttributeData
(
ObsoleteAttributeKind
.
Experimental
,
message
:
null
,
isError
:
false
,
diagnosticId
:
null
,
urlFormat
:
null
);
public
const
string
DiagnosticIdPropertyName
=
"DiagnosticId"
;
public
const
string
UrlFormatPropertyName
=
"UrlFormat"
;
public
ObsoleteAttributeData
(
ObsoleteAttributeKind
kind
,
string
message
,
bool
isError
)
public
ObsoleteAttributeData
(
ObsoleteAttributeKind
kind
,
string
?
message
,
bool
isError
,
string
?
diagnosticId
,
string
?
urlFormat
)
{
Kind
=
kind
;
Message
=
message
;
IsError
=
isError
;
DiagnosticId
=
diagnosticId
;
UrlFormat
=
urlFormat
;
}
public
readonly
ObsoleteAttributeKind
Kind
;
...
...
@@ -41,7 +48,31 @@ public ObsoleteAttributeData(ObsoleteAttributeKind kind, string message, bool is
/// <summary>
/// The message that will be shown when an error/warning is created for <see cref="ObsoleteAttribute"/>.
/// </summary>
public
readonly
string
Message
;
public
readonly
string
?
Message
;
/// <summary>
/// The custom diagnostic ID to use for obsolete diagnostics.
/// If null, diagnostics are produced using the compiler default diagnostic IDs.
/// </summary>
public
readonly
string
?
DiagnosticId
;
/// <summary>
/// <para>
/// The custom help URL format string for obsolete diagnostics.
/// Expected to contain zero or one format items.
/// </para>
/// <para>
/// When specified, the obsolete diagnostic's <see cref="DiagnosticDescriptor.HelpLinkUri"/> will be produced
/// by formatting this string using the <see cref="DiagnosticId"/> as the single argument.
/// </para>
///
/// <example>
/// e.g. with a <see cref="DiagnosticId"/> value <c>"TEST1"</c>,
/// and a <see cref="UrlFormat"/> value <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/{0}/"/>,<br/>
/// the diagnostic will have the HelpLinkUri <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/TEST1/"/>.
/// </example>
/// </summary>
public
readonly
string
?
UrlFormat
;
internal
bool
IsUninitialized
{
...
...
src/Compilers/VisualBasic/Portable/Errors/ErrorFactories.vb
浏览文件 @
34fdb697
...
...
@@ -73,6 +73,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return
New
DiagnosticInfo
(
MessageProvider
.
Instance
,
id
,
arguments
)
End
Function
Public
Shared
Function
ObsoleteErrorInfo
(
id
As
ERRID
,
data
As
ObsoleteAttributeData
,
ParamArray
arguments
As
Object
())
As
CustomObsoleteDiagnosticInfo
Return
New
CustomObsoleteDiagnosticInfo
(
MessageProvider
.
Instance
,
id
,
data
,
arguments
)
End
Function
Public
Shared
Function
ErrorInfo
(
id
As
ERRID
,
ByRef
syntaxToken
As
SyntaxToken
)
As
DiagnosticInfo
Return
ErrorInfo
(
id
,
SyntaxFacts
.
GetText
(
syntaxToken
.
Kind
))
End
Function
...
...
src/Compilers/VisualBasic/Portable/Symbols/Attributes/AttributeData.vb
浏览文件 @
34fdb697
...
...
@@ -488,6 +488,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return
Me
.
GetConstructorArgument
(
Of
String
)(
0
,
SpecialType
.
System_String
)
End
Function
Private
Protected
NotOverridable
Overrides
Function
IsStringProperty
(
memberName
As
String
)
As
Boolean
If
AttributeClass
IsNot
Nothing
Then
For
Each
member
In
AttributeClass
.
GetMembers
(
memberName
)
Dim
prop
=
TryCast
(
member
,
PropertySymbol
)
If
prop
?
.
Type
.
SpecialType
=
SpecialType
.
System_String
Then
Return
True
End
If
Next
End
If
Return
False
End
Function
#End Region
''' <summary>
...
...
src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb
浏览文件 @
34fdb697
...
...
@@ -33,7 +33,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Friend
Shared
Function
GetObsoleteDataFromMetadata
(
token
As
EntityHandle
,
containingModule
As
PEModuleSymbol
)
As
ObsoleteAttributeData
Dim
obsoleteAttributeData
As
ObsoleteAttributeData
=
Nothing
' ignoreByRefLikeMarker := False, since VB does not support ref-like types
obsoleteAttributeData
=
containingModule
.
Module
.
TryGetDeprecatedOrExperimentalOrObsoleteAttribute
(
token
,
ignoreByRefLikeMarker
:
=
False
)
obsoleteAttributeData
=
containingModule
.
Module
.
TryGetDeprecatedOrExperimentalOrObsoleteAttribute
(
token
,
New
MetadataDecoder
(
containingModule
),
ignoreByRefLikeMarker
:
=
False
)
Debug
.
Assert
(
obsoleteAttributeData
Is
Nothing
OrElse
Not
obsoleteAttributeData
.
IsUninitialized
)
Return
obsoleteAttributeData
End
Function
...
...
@@ -129,17 +129,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Dim
accessorString
=
If
(
accessorSymbol
.
MethodKind
=
MethodKind
.
PropertyGet
,
"Get"
,
"Set"
)
If
String
.
IsNullOrEmpty
(
data
.
Message
)
Then
Return
ErrorFactory
.
ErrorInfo
(
If
(
data
.
IsError
,
ERRID
.
ERR_UseOfObsoletePropertyAccessor2
,
ERRID
.
WRN_UseOfObsoletePropertyAccessor2
)
,
Return
ErrorFactory
.
ObsoleteErrorInfo
(
If
(
data
.
IsError
,
ERRID
.
ERR_UseOfObsoletePropertyAccessor2
,
ERRID
.
WRN_UseOfObsoletePropertyAccessor2
),
data
,
accessorString
,
accessorSymbol
.
AssociatedSymbol
)
Else
Return
ErrorFactory
.
ErrorInfo
(
If
(
data
.
IsError
,
ERRID
.
ERR_UseOfObsoletePropertyAccessor3
,
ERRID
.
WRN_UseOfObsoletePropertyAccessor3
)
,
Return
ErrorFactory
.
ObsoleteErrorInfo
(
If
(
data
.
IsError
,
ERRID
.
ERR_UseOfObsoletePropertyAccessor3
,
ERRID
.
WRN_UseOfObsoletePropertyAccessor3
),
data
,
accessorString
,
accessorSymbol
.
AssociatedSymbol
,
data
.
Message
)
End
If
Else
If
String
.
IsNullOrEmpty
(
data
.
Message
)
Then
Return
ErrorFactory
.
ErrorInfo
(
If
(
data
.
IsError
,
ERRID
.
ERR_UseOfObsoleteSymbolNoMessage1
,
ERRID
.
WRN_UseOfObsoleteSymbolNoMessage1
)
,
symbol
)
Return
ErrorFactory
.
ObsoleteErrorInfo
(
If
(
data
.
IsError
,
ERRID
.
ERR_UseOfObsoleteSymbolNoMessage1
,
ERRID
.
WRN_UseOfObsoleteSymbolNoMessage1
),
data
,
symbol
)
Else
Return
ErrorFactory
.
ErrorInfo
(
If
(
data
.
IsError
,
ERRID
.
ERR_UseOfObsoleteSymbol2
,
ERRID
.
WRN_UseOfObsoleteSymbol2
)
,
symbol
,
data
.
Message
)
Return
ErrorFactory
.
ObsoleteErrorInfo
(
If
(
data
.
IsError
,
ERRID
.
ERR_UseOfObsoleteSymbol2
,
ERRID
.
WRN_UseOfObsoleteSymbol2
),
data
,
symbol
,
data
.
Message
)
End
If
End
If
...
...
src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests_ObsoleteAttribute.vb
浏览文件 @
34fdb697
此差异已折叠。
点击以展开。
src/Test/Utilities/Portable/Diagnostics/DiagnosticDescription.cs
浏览文件 @
34fdb697
...
...
@@ -13,6 +13,7 @@
using
Xunit
;
using
Roslyn.Test.Utilities
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.CSharp
;
namespace
Microsoft.CodeAnalysis.Test.Utilities
{
...
...
@@ -116,7 +117,7 @@ public DiagnosticDescription(Diagnostic d, bool errorCodeOnly, bool includeDefau
_effectiveSeverityOpt
=
includeEffectiveSeverity
?
d
.
Severity
:
(
DiagnosticSeverity
?)
null
;
DiagnosticWithInfo
dinfo
=
null
;
if
(
d
.
Code
==
0
)
if
(
d
.
Code
==
0
||
d
.
Descriptor
.
CustomTags
.
Contains
(
WellKnownDiagnosticTags
.
CustomObsolete
)
)
{
_code
=
d
.
Id
;
_errorCodeType
=
typeof
(
string
);
...
...
@@ -421,7 +422,7 @@ public static string GetAssertText(DiagnosticDescription[] expected, IEnumerable
{
const
int
CSharp
=
1
;
const
int
VisualBasic
=
2
;
var
language
=
actual
.
Any
()
&&
actual
.
First
()
.
Id
.
StartsWith
(
"CS"
,
StringComparison
.
Ordinal
)
?
CSharp
:
VisualBasic
;
var
language
=
actual
.
Any
()
&&
actual
.
First
()
is
CSDiagnostic
?
CSharp
:
VisualBasic
;
var
includeDiagnosticMessagesAsComments
=
(
language
==
CSharp
);
int
indentDepth
=
(
language
==
CSharp
)
?
4
:
1
;
var
includeDefaultSeverity
=
expected
.
Any
()
&&
expected
.
All
(
d
=>
d
.
DefaultSeverity
!=
null
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录