Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
4d285574
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,发现更多精彩内容 >>
未验证
提交
4d285574
编写于
5月 15, 2018
作者:
J
Julien Couvreur
提交者:
GitHub
5月 15, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Use [NotNullWhenFalse] and [EnsuresNotNull] to drive nullability analysis (#26656)
上级
4355cc42
变更
17
展开全部
隐藏空白更改
内联
并排
Showing
17 changed file
with
2212 addition
and
32 deletion
+2212
-32
src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
+9
-0
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPassBase.cs
...ompilers/CSharp/Portable/FlowAnalysis/DataFlowPassBase.cs
+10
-1
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+209
-20
src/Compilers/CSharp/Portable/Symbols/ExtraAnnotations.cs
src/Compilers/CSharp/Portable/Symbols/ExtraAnnotations.cs
+202
-0
src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs
.../CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs
+47
-8
src/Compilers/CSharp/Portable/Symbols/ParameterSymbol.cs
src/Compilers/CSharp/Portable/Symbols/ParameterSymbol.cs
+21
-0
src/Compilers/CSharp/Portable/Symbols/SignatureOnlyParameterSymbol.cs
...s/CSharp/Portable/Symbols/SignatureOnlyParameterSymbol.cs
+2
-0
src/Compilers/CSharp/Portable/Symbols/Source/SourceClonedParameterSymbol.cs
...rp/Portable/Symbols/Source/SourceClonedParameterSymbol.cs
+5
-0
src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs
...p/Portable/Symbols/Source/SourceComplexParameterSymbol.cs
+27
-0
src/Compilers/CSharp/Portable/Symbols/Source/SourceSimpleParameterSymbol.cs
...rp/Portable/Symbols/Source/SourceSimpleParameterSymbol.cs
+9
-0
src/Compilers/CSharp/Portable/Symbols/Source/ThisParameterSymbol.cs
...ers/CSharp/Portable/Symbols/Source/ThisParameterSymbol.cs
+5
-0
src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs
...ortable/Symbols/Synthesized/SynthesizedParameterSymbol.cs
+5
-0
src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs
...CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs
+7
-1
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking.cs
...lers/CSharp/Test/Semantic/Semantics/StaticNullChecking.cs
+1610
-0
src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs
.../Core/Portable/Symbols/Attributes/AttributeDescription.cs
+4
-0
src/Compilers/Core/Portable/Symbols/Attributes/CommonParameterWellKnownAttributeData.cs
...mbols/Attributes/CommonParameterWellKnownAttributeData.cs
+33
-0
src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
+7
-2
未找到文件。
src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
浏览文件 @
4d285574
...
...
@@ -4660,6 +4660,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Feature '{0}' is not available in C# 7.3. Please use language version {1} or greater..
/// </summary>
internal static string ERR_FeatureNotAvailableInVersion7_3 {
get {
return ResourceManager.GetString("ERR_FeatureNotAvailableInVersion7_3", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Feature '{0}' is not available in C# 8. Please use language version {1} or greater..
/// </summary>
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPassBase.cs
浏览文件 @
4d285574
...
...
@@ -116,7 +116,16 @@ protected int GetOrCreateSlot(Symbol symbol, int containingSlot = 0)
variableBySlot
[
slot
]
=
identifier
;
}
Normalize
(
ref
this
.
State
);
if
(
IsConditionalState
)
{
Normalize
(
ref
this
.
StateWhenTrue
);
Normalize
(
ref
this
.
StateWhenFalse
);
}
else
{
Normalize
(
ref
this
.
State
);
}
return
slot
;
}
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
浏览文件 @
4d285574
...
...
@@ -59,6 +59,12 @@ internal sealed partial class NullableWalker : DataFlowPassBase<NullableWalker.L
/// </summary>
private
PooledDictionary
<
BoundExpression
,
ObjectCreationPlaceholderLocal
>
_placeholderLocals
;
/// <summary>
/// For methods with annotations, we'll need to visit the arguments twice.
/// Once for diagnostics and once for result state (but disabling diagnostics).
/// </summary>
private
bool
_disableDiagnostics
=
false
;
protected
override
void
Free
()
{
_variableTypes
.
Free
();
...
...
@@ -464,7 +470,10 @@ private bool IsByRefTarget(int slot)
private
void
ReportStaticNullCheckingDiagnostics
(
ErrorCode
errorCode
,
SyntaxNode
syntaxNode
,
params
object
[]
arguments
)
{
Diagnostics
.
Add
(
errorCode
,
syntaxNode
.
GetLocation
(),
arguments
);
if
(!
_disableDiagnostics
)
{
Diagnostics
.
Add
(
errorCode
,
syntaxNode
.
GetLocation
(),
arguments
);
}
}
private
void
InheritNullableStateOfTrackableStruct
(
TypeSymbol
targetType
,
int
targetSlot
,
int
valueSlot
,
bool
isByRefTarget
,
int
slotWatermark
)
...
...
@@ -1578,12 +1587,14 @@ public override BoundNode VisitCall(BoundCall node)
{
ImmutableArray
<
RefKind
>
refKindsOpt
=
node
.
ArgumentRefKindsOpt
;
ImmutableArray
<
BoundExpression
>
arguments
=
RemoveArgumentConversions
(
node
.
Arguments
,
refKindsOpt
);
ImmutableArray
<
Result
>
results
=
VisitArgumentsEvaluate
(
arguments
,
refKindsOpt
,
node
.
Expanded
);
ImmutableArray
<
int
>
argsToParamsOpt
=
node
.
ArgsToParamsOpt
;
ImmutableArray
<
Result
>
results
=
VisitArgumentsEvaluate
(
arguments
,
refKindsOpt
,
method
.
Parameters
,
argsToParamsOpt
,
node
.
Expanded
);
if
(
method
.
IsGenericMethod
&&
HasImplicitTypeArguments
(
node
))
{
method
=
InferMethod
(
node
,
method
,
results
.
SelectAsArray
(
r
=>
r
.
Type
));
}
VisitArgumentsWarn
(
arguments
,
refKindsOpt
,
method
.
Parameters
,
node
.
A
rgsToParamsOpt
,
node
.
Expanded
,
results
);
VisitArgumentsWarn
(
arguments
,
refKindsOpt
,
method
.
Parameters
,
a
rgsToParamsOpt
,
node
.
Expanded
,
results
);
}
UpdateStateForCall
(
node
);
...
...
@@ -1594,7 +1605,6 @@ public override BoundNode VisitCall(BoundCall node)
ReplayReadsAndWrites
(
localFunc
,
node
.
Syntax
,
writes
:
true
);
}
Debug
.
Assert
(!
IsConditionalState
);
//if (this.State.Reachable) // PROTOTYPE(NullableReferenceTypes): Consider reachability?
{
_result
=
method
.
ReturnType
;
...
...
@@ -1603,6 +1613,49 @@ public override BoundNode VisitCall(BoundCall node)
return
null
;
}
/// <summary>
/// For each argument, figure out if its corresponding parameter is annotated with NotNullWhenFalse or
/// EnsuresNotNull.
/// </summary>
private
static
ImmutableArray
<
AttributeAnnotations
>
GetAnnotations
(
int
numArguments
,
bool
expanded
,
ImmutableArray
<
ParameterSymbol
>
parameters
,
ImmutableArray
<
int
>
argsToParamsOpt
)
{
ArrayBuilder
<
AttributeAnnotations
>
builder
=
null
;
for
(
int
i
=
0
;
i
<
numArguments
;
i
++)
{
(
ParameterSymbol
parameter
,
_
)
=
GetCorrespondingParameter
(
i
,
parameters
,
argsToParamsOpt
,
expanded
);
AttributeAnnotations
annotations
=
parameter
?.
FlowAnalysisAnnotations
??
AttributeAnnotations
.
None
;
// We'll ignore NotNullWhenFalse that is misused in metadata
if
((
annotations
&
AttributeAnnotations
.
NotNullWhenFalse
)
!=
0
&&
parameter
.
ContainingSymbol
.
GetTypeOrReturnType
().
SpecialType
!=
SpecialType
.
System_Boolean
)
{
annotations
&=
~
AttributeAnnotations
.
NotNullWhenFalse
;
}
// We'll ignore EnsuresNotNull that is misused in metadata
if
((
annotations
&
AttributeAnnotations
.
EnsuresNotNull
)
!=
0
&&
(
parameter
.
Type
?.
IsValueType
!=
false
||
parameter
.
IsParams
))
{
annotations
&=
~
AttributeAnnotations
.
EnsuresNotNull
;
}
if
(
annotations
!=
AttributeAnnotations
.
None
&&
builder
==
null
)
{
builder
=
ArrayBuilder
<
AttributeAnnotations
>.
GetInstance
(
numArguments
);
builder
.
AddMany
(
AttributeAnnotations
.
None
,
i
);
}
if
(
builder
!=
null
)
{
builder
.
Add
(
annotations
);
}
}
return
builder
==
null
?
default
:
builder
.
ToImmutableAndFree
();
}
// PROTOTYPE(NullableReferenceTypes): Record in the node whether type
// arguments were implicit, to allow for cases where the syntax is not an
// invocation (such as a synthesized call from a query interpretation).
...
...
@@ -1661,7 +1714,7 @@ protected override void VisitArguments(ImmutableArray<BoundExpression> arguments
bool
expanded
)
{
Debug
.
Assert
(!
arguments
.
IsDefault
);
ImmutableArray
<
Result
>
results
=
VisitArgumentsEvaluate
(
arguments
,
refKindsOpt
,
expanded
);
ImmutableArray
<
Result
>
results
=
VisitArgumentsEvaluate
(
arguments
,
refKindsOpt
,
parameters
,
argsToParamsOpt
,
expanded
);
// PROTOTYPE(NullableReferenceTypes): Can we handle some error cases?
// (Compare with CSharpOperationFactory.CreateBoundCallOperation.)
if
(!
node
.
HasErrors
&&
!
parameters
.
IsDefault
)
...
...
@@ -1673,7 +1726,31 @@ protected override void VisitArguments(ImmutableArray<BoundExpression> arguments
private
ImmutableArray
<
Result
>
VisitArgumentsEvaluate
(
ImmutableArray
<
BoundExpression
>
arguments
,
ImmutableArray
<
RefKind
>
refKindsOpt
,
ImmutableArray
<
ParameterSymbol
>
parameters
,
ImmutableArray
<
int
>
argsToParamsOpt
,
bool
expanded
)
{
var
savedState
=
this
.
State
.
Clone
();
// We do a first pass to work through the arguments without making any assumptions
var
results
=
VisitArgumentsEvaluate
(
arguments
,
refKindsOpt
);
// We do a second pass through the arguments, ignoring any diagnostics produced, but honoring the annotations,
// to get the proper result state.
ImmutableArray
<
AttributeAnnotations
>
annotations
=
GetAnnotations
(
arguments
.
Length
,
expanded
,
parameters
,
argsToParamsOpt
);
if
(!
annotations
.
IsDefault
)
{
this
.
SetState
(
savedState
);
VisitArgumentsEvaluateHonoringAnnotations
(
arguments
,
refKindsOpt
,
annotations
);
}
return
results
;
}
private
ImmutableArray
<
Result
>
VisitArgumentsEvaluate
(
ImmutableArray
<
BoundExpression
>
arguments
,
ImmutableArray
<
RefKind
>
refKindsOpt
)
{
Debug
.
Assert
(!
IsConditionalState
);
int
n
=
arguments
.
Length
;
...
...
@@ -1684,22 +1761,118 @@ protected override void VisitArguments(ImmutableArray<BoundExpression> arguments
var
builder
=
ArrayBuilder
<
Result
>.
GetInstance
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
RefKind
refKind
=
GetRefKind
(
refKindsOpt
,
i
);
var
argument
=
arguments
[
i
];
if
(
refKind
!=
RefKind
.
Out
)
VisitArgumentEvaluate
(
arguments
,
refKindsOpt
,
i
);
builder
.
Add
(
_result
);
}
_result
=
_invalidType
;
return
builder
.
ToImmutableAndFree
();
}
private
void
VisitArgumentEvaluate
(
ImmutableArray
<
BoundExpression
>
arguments
,
ImmutableArray
<
RefKind
>
refKindsOpt
,
int
i
)
{
RefKind
refKind
=
GetRefKind
(
refKindsOpt
,
i
);
var
argument
=
arguments
[
i
];
if
(
refKind
!=
RefKind
.
Out
)
{
// PROTOTYPE(NullReferenceTypes): `ref` arguments should be treated as l-values
// for assignment. See `ref x3` in StaticNullChecking.PassingParameters_01.
VisitRvalue
(
argument
);
}
else
{
VisitLvalue
(
argument
);
}
}
/// <summary>
/// Visit all the arguments for the purpose of computing the exit state of the method,
/// given the annotations, but disabling warnings.
/// </summary>
private
void
VisitArgumentsEvaluateHonoringAnnotations
(
ImmutableArray
<
BoundExpression
>
arguments
,
ImmutableArray
<
RefKind
>
refKindsOpt
,
ImmutableArray
<
AttributeAnnotations
>
annotations
)
{
Debug
.
Assert
(!
IsConditionalState
);
bool
saveDisableDiagnostics
=
_disableDiagnostics
;
_disableDiagnostics
=
true
;
Debug
.
Assert
(
annotations
.
Length
==
arguments
.
Length
);
for
(
int
i
=
0
;
i
<
arguments
.
Length
;
i
++)
{
if
(
this
.
IsConditionalState
)
{
// PROTOTYPE(NullReferenceTypes): `ref` arguments should be treated as l-values
// for assignment. See `ref x3` in StaticNullChecking.PassingParameters_01.
VisitRvalue
(
argument
);
// We could be in a conditional state because of NotNullWhenFalse annotation
// Then WhenTrue/False states correspond to the invocation returning true/false
// We'll assume that we're in the unconditional state where the method returns true,
// then we'll repeat assuming the method returns false.
LocalState
whenTrue
=
this
.
StateWhenTrue
.
Clone
();
LocalState
whenFalse
=
this
.
StateWhenFalse
.
Clone
();
this
.
SetState
(
whenTrue
);
VisitArgumentEvaluate
(
arguments
,
refKindsOpt
,
i
);
Debug
.
Assert
(!
IsConditionalState
);
whenTrue
=
this
.
State
;
// LocalState may be a struct
this
.
SetState
(
whenFalse
);
VisitArgumentEvaluate
(
arguments
,
refKindsOpt
,
i
);
Debug
.
Assert
(!
IsConditionalState
);
whenFalse
=
this
.
State
;
// LocalState may be a struct
this
.
SetConditionalState
(
whenTrue
,
whenFalse
);
}
else
{
VisitLvalue
(
argument
);
VisitArgumentEvaluate
(
arguments
,
refKindsOpt
,
i
);
}
var
argument
=
arguments
[
i
];
if
(
argument
.
Type
?.
IsReferenceType
!=
true
)
{
continue
;
}
int
slot
=
MakeSlot
(
argument
);
if
(
slot
<=
0
)
{
continue
;
}
AttributeAnnotations
annotation
=
annotations
[
i
];
bool
notNullWhenFalse
=
(
annotation
&
AttributeAnnotations
.
NotNullWhenFalse
)
!=
0
;
bool
ensuresNotNull
=
(
annotation
&
AttributeAnnotations
.
EnsuresNotNull
)
!=
0
;
if
(
ensuresNotNull
)
{
// The variable in this slot is not null
if
(
this
.
IsConditionalState
)
{
this
.
StateWhenTrue
[
slot
]
=
true
;
this
.
StateWhenFalse
[
slot
]
=
true
;
}
else
{
this
.
State
[
slot
]
=
true
;
}
}
else
if
(
notNullWhenFalse
)
{
// We'll use the WhenTrue/False states to represent whether the invocation returns true/false
// PROTOTYPE(NullableReferenceTypes): Consider splitting for the entire method, not just once the first annotated argument is encountered
Split
();
// The variable in this slot is not null when the method returns false
this
.
StateWhenFalse
[
slot
]
=
true
;
}
builder
.
Add
(
_result
);
}
_result
=
_invalidType
;
return
builder
.
ToImmutableAndFree
()
;
_disableDiagnostics
=
saveDisableDiagnostics
;
}
private
void
VisitArgumentsWarn
(
...
...
@@ -1813,7 +1986,10 @@ private static ImmutableArray<BoundExpression> RemoveArgumentConversions(Immutab
private
static
(
ParameterSymbol
,
TypeSymbolWithAnnotations
)
GetCorrespondingParameter
(
int
argumentOrdinal
,
ImmutableArray
<
ParameterSymbol
>
parameters
,
ImmutableArray
<
int
>
argsToParamsOpt
,
bool
expanded
)
{
Debug
.
Assert
(!
parameters
.
IsDefault
);
if
(
parameters
.
IsDefault
)
{
return
(
null
,
null
);
}
int
n
=
parameters
.
Length
;
ParameterSymbol
parameter
;
...
...
@@ -3068,7 +3244,7 @@ public override BoundNode VisitArgList(BoundArgList node)
public
override
BoundNode
VisitArgListOperator
(
BoundArgListOperator
node
)
{
VisitArgumentsEvaluate
(
node
.
Arguments
,
node
.
ArgumentRefKindsOpt
,
expanded
:
false
);
VisitArgumentsEvaluate
(
node
.
Arguments
,
node
.
ArgumentRefKindsOpt
);
Debug
.
Assert
((
object
)
node
.
Type
==
null
);
SetResult
(
node
);
return
null
;
...
...
@@ -3148,7 +3324,7 @@ public override BoundNode VisitDynamicMemberAccess(BoundDynamicMemberAccess node
public
override
BoundNode
VisitDynamicInvocation
(
BoundDynamicInvocation
node
)
{
VisitRvalue
(
node
.
Expression
);
VisitArgumentsEvaluate
(
node
.
Arguments
,
node
.
ArgumentRefKindsOpt
,
expanded
:
false
);
VisitArgumentsEvaluate
(
node
.
Arguments
,
node
.
ArgumentRefKindsOpt
);
Debug
.
Assert
(
node
.
Type
.
IsDynamic
());
Debug
.
Assert
(
node
.
Type
.
IsReferenceType
);
...
...
@@ -3176,7 +3352,7 @@ public override BoundNode VisitEventAssignmentOperator(BoundEventAssignmentOpera
public
override
BoundNode
VisitDynamicObjectCreationExpression
(
BoundDynamicObjectCreationExpression
node
)
{
Debug
.
Assert
(!
IsConditionalState
);
VisitArgumentsEvaluate
(
node
.
Arguments
,
node
.
ArgumentRefKindsOpt
,
expanded
:
false
);
VisitArgumentsEvaluate
(
node
.
Arguments
,
node
.
ArgumentRefKindsOpt
);
VisitObjectOrDynamicObjectCreation
(
node
,
node
.
InitializerExpressionOpt
);
return
null
;
}
...
...
@@ -3255,7 +3431,7 @@ public override BoundNode VisitDynamicIndexerAccess(BoundDynamicIndexerAccess no
var
receiver
=
node
.
ReceiverOpt
;
VisitRvalue
(
receiver
);
CheckPossibleNullReceiver
(
receiver
);
VisitArgumentsEvaluate
(
node
.
Arguments
,
node
.
ArgumentRefKindsOpt
,
expanded
:
false
);
VisitArgumentsEvaluate
(
node
.
Arguments
,
node
.
ArgumentRefKindsOpt
);
Debug
.
Assert
(
node
.
Type
.
IsDynamic
());
...
...
@@ -3421,7 +3597,7 @@ public override BoundNode VisitThrowExpression(BoundThrowExpression node)
return
result
;
}
#endregion Visitors
#
endregion
Visitors
protected
override
string
Dump
(
LocalState
state
)
{
...
...
@@ -3573,6 +3749,19 @@ public bool Reachable
return
_knownNullState
.
Capacity
>
0
;
}
}
public
override
string
ToString
()
{
var
pooledBuilder
=
PooledStringBuilder
.
GetInstance
();
var
builder
=
pooledBuilder
.
Builder
;
builder
.
Append
(
" "
);
for
(
int
i
=
this
.
Capacity
-
1
;
i
>=
0
;
i
--)
{
builder
.
Append
(
_knownNullState
[
i
]
?
(
_notNull
[
i
]
?
"!"
:
"?"
)
:
"_"
);
}
return
pooledBuilder
.
ToStringAndFree
();
}
}
}
}
src/Compilers/CSharp/Portable/Symbols/
Metadata/PE/External
Annotations.cs
→
src/Compilers/CSharp/Portable/Symbols/
Extra
Annotations.cs
浏览文件 @
4d285574
// 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.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Text
;
using
Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
static
Microsoft
.
CodeAnalysis
.
CSharp
.
Symbols
.
AttributeAnnotations
;
namespace
Microsoft.CodeAnalysis.CSharp.Symbols
.Metadata.PE
namespace
Microsoft.CodeAnalysis.CSharp.Symbols
{
[
Flags
]
internal
enum
AttributeAnnotations
{
None
=
0
,
NotNullWhenFalse
,
EnsuresNotNull
,
}
// PROTOTYPE(NullableReferenceTypes): external annotations should be removed or fully designed/productized
// If we choose to stick with an ad-hoc key (rather than annotations as source or as PE/ref assembly),
// we should consider the assembly qualified name format used in metadata (with backticks and such).
...
...
@@ -16,19 +27,28 @@ internal static class ExtraAnnotations
// APIs that are useful to annotate:
// 1) don't accept null input
// 2) return a reference type
// All types in a member which can be annotated should be annotated. Value types and void can be skipped (with a `default`)
private
static
readonly
ImmutableDictionary
<
string
,
ImmutableArray
<
ImmutableArray
<
bool
>>>
Annotations
=
new
Dictionary
<
string
,
ImmutableArray
<
ImmutableArray
<
bool
>>>
{
{
"System.Boolean System.Boolean.Parse(System.String)"
,
Parameters
(
skip
,
Nullable
(
false
))
},
{
"System.Void System.Buffer.BlockCopy(System.Array, System.Int32, System.Array, System.Int32, System.Int32)"
,
Parameters
(
skip
,
Nullable
(
false
),
skip
,
Nullable
(
false
),
skip
,
skip
)
},
{
"System.Int32 System.Buffer.ByteLength(System.Array)"
,
Parameters
(
skip
,
Nullable
(
false
))
},
{
"System.Byte System.Buffer.GetByte(System.Array, System.Int32)"
,
Parameters
(
skip
,
Nullable
(
false
),
skip
)
},
{
"System.Void System.Buffer.SetByte(System.Array, System.Int32, System.Byte)"
,
Parameters
(
skip
,
Nullable
(
false
),
skip
,
skip
)
},
{
"System.Byte System.Byte.Parse(System.String)"
,
Parameters
(
skip
,
Nullable
(
false
))
},
{
"System.Byte System.Byte.Parse(System.String, System.IFormatProvider)"
,
Parameters
(
skip
,
Nullable
(
false
),
skip
)
},
{
"System.Byte System.Byte.Parse(System.String, System.Globalization.NumberStyles)"
,
Parameters
(
skip
,
Nullable
(
false
),
Nullable
(
false
))
},
{
"System.Byte System.Byte.Parse(System.String, System.Globalization.NumberStyles, System.IFormatProvider)"
,
Parameters
(
skip
,
Nullable
(
false
),
Nullable
(
false
),
skip
)
},
{
"System.String System.String.Concat(System.String, System.String)"
,
Parameters
(
Nullable
(
false
),
Nullable
(
true
),
Nullable
(
true
))
},
{
"System.Boolean System.Boolean.Parse(System.String)"
,
Array
(
default
,
Nullable
(
false
))
},
{
"System.Void System.Buffer.BlockCopy(System.Array, System.Int32, System.Array, System.Int32, System.Int32)"
,
Array
(
default
,
Nullable
(
false
),
default
,
Nullable
(
false
),
default
,
default
)
},
{
"System.Int32 System.Buffer.ByteLength(System.Array)"
,
Array
(
default
,
Nullable
(
false
))
},
{
"System.Byte System.Buffer.GetByte(System.Array, System.Int32)"
,
Array
(
default
,
Nullable
(
false
),
default
)
},
{
"System.Void System.Buffer.SetByte(System.Array, System.Int32, System.Byte)"
,
Array
(
default
,
Nullable
(
false
),
default
,
default
)
},
{
"System.Byte System.Byte.Parse(System.String)"
,
Array
(
default
,
Nullable
(
false
))
},
{
"System.Byte System.Byte.Parse(System.String, System.IFormatProvider)"
,
Array
(
default
,
Nullable
(
false
),
default
)
},
{
"System.Byte System.Byte.Parse(System.String, System.Globalization.NumberStyles)"
,
Array
(
default
,
Nullable
(
false
),
Nullable
(
false
))
},
{
"System.Byte System.Byte.Parse(System.String, System.Globalization.NumberStyles, System.IFormatProvider)"
,
Array
(
default
,
Nullable
(
false
),
Nullable
(
false
),
default
)
},
{
"System.String System.String.Concat(System.String, System.String)"
,
Array
(
Nullable
(
false
),
Nullable
(
true
),
Nullable
(
true
))
},
}.
ToImmutableDictionary
();
private
static
readonly
ImmutableDictionary
<
string
,
ImmutableArray
<
AttributeAnnotations
>>
Attributes
=
new
Dictionary
<
string
,
ImmutableArray
<
AttributeAnnotations
>>
{
{
"System.Boolean System.String.IsNullOrEmpty(System.String)"
,
Array
(
default
,
NotNullWhenFalse
)
},
{
"System.Boolean System.String.IsNullOrWhiteSpace(System.String)"
,
Array
(
default
,
NotNullWhenFalse
)
},
{
"System.Boolean System.String.Contains(System.String)"
,
Array
(
default
,
EnsuresNotNull
)
},
}.
ToImmutableDictionary
();
internal
static
string
MakeMethodKey
(
PEMethodSymbol
method
,
ParamInfo
<
TypeSymbol
>[]
paramInfo
)
...
...
@@ -65,12 +85,51 @@ internal static string MakeMethodKey(PEMethodSymbol method, ParamInfo<TypeSymbol
// use assembly qualified name format (used in metadata) rather than symbol display?
}
/// <summary>
/// All types in a member which can be annotated should be annotated. Value types and void can be skipped.
/// </summary>
private
static
readonly
ImmutableArray
<
bool
>
skip
=
default
;
internal
static
string
MakeMethodKey
(
MethodSymbol
method
)
{
var
containingType
=
method
.
ContainingSymbol
as
TypeSymbol
;
if
(
containingType
is
null
)
{
return
null
;
}
var
pooledBuilder
=
PooledStringBuilder
.
GetInstance
();
StringBuilder
builder
=
pooledBuilder
.
Builder
;
Add
(
method
.
ReturnType
.
TypeSymbol
,
builder
);
builder
.
Append
(
' '
);
Add
(
containingType
,
builder
);
builder
.
Append
(
'.'
);
builder
.
Append
(
method
.
Name
);
builder
.
Append
(
'('
);
var
parameterTypes
=
method
.
ParameterTypes
;
for
(
int
i
=
0
;
i
<
parameterTypes
.
Length
;
i
++)
{
Add
(
parameterTypes
[
i
].
TypeSymbol
,
builder
);
if
(
i
<
parameterTypes
.
Length
-
1
)
{
builder
.
Append
(
", "
);
}
}
builder
.
Append
(
')'
);
return
pooledBuilder
.
ToStringAndFree
();
// PROTOTYPE(NullableReferenceTypes): Many cases are not yet handled
// generic type args
// ref kind
// 'this'
// static vs. instance
// use assembly qualified name format (used in metadata) rather than symbol display?
}
private
static
ImmutableArray
<
ImmutableArray
<
bool
>>
Parameters
(
params
ImmutableArray
<
bool
>[]
values
)
private
static
ImmutableArray
<
ImmutableArray
<
bool
>>
Array
(
params
ImmutableArray
<
bool
>[]
values
)
=>
values
.
ToImmutableArray
();
private
static
ImmutableArray
<
AttributeAnnotations
>
Array
(
params
AttributeAnnotations
[]
values
)
=>
values
.
ToImmutableArray
();
private
static
ImmutableArray
<
bool
>
Nullable
(
params
bool
[]
values
)
...
...
@@ -81,6 +140,11 @@ private static ImmutableArray<bool> Nullable(params bool[] values)
internal
static
ImmutableArray
<
ImmutableArray
<
bool
>>
GetExtraAnnotations
(
string
key
)
{
if
(
key
is
null
)
{
return
default
;
}
if
(!
Annotations
.
TryGetValue
(
key
,
out
var
flags
))
{
return
default
;
...
...
@@ -97,5 +161,42 @@ private static void Add(TypeSymbol type, StringBuilder builder)
.
AddMiscellaneousOptions
(
SymbolDisplayMiscellaneousOptions
.
IncludeNullableReferenceTypeModifier
)
// displaying tuple syntax causes to load the members of ValueTuple, which can cause a cycle, so we use long-hand format instead
.
WithCompilerInternalOptions
(
SymbolDisplayCompilerInternalOptions
.
UseValueTuple
)));
/// <summary>
/// index 0 is used for return type
/// other parameters follow
/// </summary>
internal
static
(
bool
hasAny
,
AttributeAnnotations
annotations
)
GetExtraAttributes
(
string
key
,
int
parameterIndex
)
{
if
(
key
is
null
)
{
return
(
false
,
default
);
}
if
(!
Attributes
.
TryGetValue
(
key
,
out
var
extraAttributes
))
{
return
(
false
,
default
);
}
return
(
true
,
extraAttributes
[
parameterIndex
+
1
]);
}
}
internal
static
class
ParameterAnnotationsExtensions
{
internal
static
AttributeAnnotations
With
(
this
AttributeAnnotations
value
,
bool
notNullWhenFalse
,
bool
ensuresNotNull
)
{
if
(
notNullWhenFalse
)
{
value
|=
NotNullWhenFalse
;
}
if
(
ensuresNotNull
)
{
value
|=
EnsuresNotNull
;
}
return
value
;
}
}
}
src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs
浏览文件 @
4d285574
...
...
@@ -31,27 +31,29 @@ private enum WellKnownAttributeFlags
IsCallerFilePath
=
0x1
<<
5
,
IsCallerLineNumber
=
0x1
<<
6
,
IsCallerMemberName
=
0x1
<<
7
,
NotNullWhenFalse
=
0x1
<<
8
,
EnsuresNotNull
=
0x1
<<
9
,
}
private
struct
PackedFlags
{
// Layout:
// |.........
....|n|rr|cccccccc|
vvvvvvvv|
// |.........
|n|rr|cccccccccc|vv
vvvvvvvv|
//
// v = decoded well known attribute values.
8
bits.
// c = completion states for well known attributes. 1 if given attribute has been decoded, 0 otherwise.
8
bits.
// v = decoded well known attribute values.
10
bits.
// c = completion states for well known attributes. 1 if given attribute has been decoded, 0 otherwise.
10
bits.
// r = RefKind. 2 bits.
// n = hasNameInMetadata. 1 bit.
private
const
int
WellKnownAttributeDataOffset
=
0
;
private
const
int
WellKnownAttributeCompletionFlagOffset
=
8
;
private
const
int
RefKindOffset
=
16
;
private
const
int
WellKnownAttributeCompletionFlagOffset
=
10
;
private
const
int
RefKindOffset
=
20
;
private
const
int
RefKindMask
=
0x3
;
private
const
int
WellKnownAttributeDataMask
=
0xFF
;
private
const
int
WellKnownAttributeDataMask
=
0x
3
FF
;
private
const
int
WellKnownAttributeCompletionFlagMask
=
WellKnownAttributeDataMask
;
private
const
int
HasNameInMetadataBit
=
0x1
<<
18
;
private
const
int
HasNameInMetadataBit
=
0x1
<<
22
;
private
const
int
AllWellKnownAttributesCompleteNoData
=
WellKnownAttributeCompletionFlagMask
<<
WellKnownAttributeCompletionFlagOffset
;
...
...
@@ -645,6 +647,44 @@ internal override bool IsCallerMemberName
}
}
internal
override
AttributeAnnotations
FlowAnalysisAnnotations
{
get
{
const
WellKnownAttributeFlags
notNullWhenFalse
=
WellKnownAttributeFlags
.
NotNullWhenFalse
;
const
WellKnownAttributeFlags
ensuresNotNull
=
WellKnownAttributeFlags
.
EnsuresNotNull
;
// PROTOTYPE(NullableReferenceTypes): the flags could be packed more
if
(!
_packedFlags
.
TryGetWellKnownAttribute
(
notNullWhenFalse
,
out
bool
hasNotNullWhenFalse
)
||
!
_packedFlags
.
TryGetWellKnownAttribute
(
ensuresNotNull
,
out
bool
hasEnsuresNotNull
))
{
(
bool
memberHasAny
,
AttributeAnnotations
annotations
)
=
TryGetExtraAttributeAnnotations
();
if
(
memberHasAny
)
{
// External annotations win, if any is present on the member
hasNotNullWhenFalse
=
(
annotations
&
AttributeAnnotations
.
NotNullWhenFalse
)
!=
0
;
hasEnsuresNotNull
=
(
annotations
&
AttributeAnnotations
.
EnsuresNotNull
)
!=
0
;
}
else
{
hasNotNullWhenFalse
=
_moduleSymbol
.
Module
.
HasAttribute
(
_handle
,
AttributeDescription
.
NotNullWhenFalseAttribute
);
hasEnsuresNotNull
=
_moduleSymbol
.
Module
.
HasAttribute
(
_handle
,
AttributeDescription
.
EnsuresNotNullAttribute
);
}
_packedFlags
.
SetWellKnownAttribute
(
notNullWhenFalse
,
hasNotNullWhenFalse
);
_packedFlags
.
SetWellKnownAttribute
(
ensuresNotNull
,
hasEnsuresNotNull
);
if
(
memberHasAny
)
{
return
annotations
;
}
}
return
AttributeAnnotations
.
None
.
With
(
notNullWhenFalse
:
hasNotNullWhenFalse
,
ensuresNotNull
:
hasEnsuresNotNull
);
}
}
public
override
TypeSymbolWithAnnotations
Type
{
get
...
...
@@ -653,7 +693,6 @@ public override TypeSymbolWithAnnotations Type
}
}
public
override
ImmutableArray
<
CustomModifier
>
RefCustomModifiers
{
get
...
...
src/Compilers/CSharp/Portable/Symbols/ParameterSymbol.cs
浏览文件 @
4d285574
...
...
@@ -385,6 +385,27 @@ internal sealed override ObsoleteAttributeData ObsoleteAttributeData
internal
abstract
bool
IsCallerMemberName
{
get
;
}
internal
abstract
AttributeAnnotations
FlowAnalysisAnnotations
{
get
;
}
/// <summary>
/// If there are any annotations on the member (not just that parameter), then memberHasExtra is true. The purpose is to ensure
/// that if some annotations are present on the member, then annotations win over the attributes on the member in all positions.
/// That could mean removing an attribute.
/// </summary>
protected
(
bool
memberHasExtra
,
AttributeAnnotations
annotations
)
TryGetExtraAttributeAnnotations
()
{
ParameterSymbol
originalParameter
=
this
.
OriginalDefinition
;
var
containingMethod
=
originalParameter
.
ContainingSymbol
as
MethodSymbol
;
if
(
containingMethod
is
null
)
{
return
(
false
,
AttributeAnnotations
.
None
);
}
string
key
=
ExtraAnnotations
.
MakeMethodKey
(
containingMethod
);
return
ExtraAnnotations
.
GetExtraAttributes
(
key
,
this
.
Ordinal
);
}
protected
sealed
override
int
HighestPriorityUseSiteError
{
get
...
...
src/Compilers/CSharp/Portable/Symbols/SignatureOnlyParameterSymbol.cs
浏览文件 @
4d285574
...
...
@@ -71,6 +71,8 @@ public override bool IsImplicitlyDeclared
internal
override
bool
IsCallerMemberName
{
get
{
throw
ExceptionUtilities
.
Unreachable
;
}
}
internal
override
AttributeAnnotations
FlowAnalysisAnnotations
{
get
{
throw
ExceptionUtilities
.
Unreachable
;
}
}
public
override
Symbol
ContainingSymbol
{
get
{
throw
ExceptionUtilities
.
Unreachable
;
}
}
public
override
ImmutableArray
<
Location
>
Locations
{
get
{
throw
ExceptionUtilities
.
Unreachable
;
}
}
...
...
src/Compilers/CSharp/Portable/Symbols/Source/SourceClonedParameterSymbol.cs
浏览文件 @
4d285574
...
...
@@ -151,6 +151,11 @@ internal override bool IsCallerMemberName
get
{
return
_originalParam
.
IsCallerMemberName
;
}
}
internal
override
AttributeAnnotations
FlowAnalysisAnnotations
{
get
{
return
AttributeAnnotations
.
None
;
}
}
#
endregion
}
}
src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs
浏览文件 @
4d285574
...
...
@@ -127,6 +127,25 @@ private bool HasCallerMemberNameAttribute
&&
!
HasCallerFilePathAttribute
&&
HasCallerMemberNameAttribute
;
internal
override
AttributeAnnotations
FlowAnalysisAnnotations
{
get
{
(
bool
memberHasAny
,
AttributeAnnotations
annotations
)
=
TryGetExtraAttributeAnnotations
();
if
(
memberHasAny
)
{
// PROTOTYPE(NullableReferenceTypes): Make sure this is covered by test
return
annotations
;
}
CommonParameterWellKnownAttributeData
attributeData
=
GetDecodedWellKnownAttributeData
();
return
AttributeAnnotations
.
None
.
With
(
notNullWhenFalse
:
attributeData
?.
HasNotNullWhenFalseAttribute
==
true
,
ensuresNotNull
:
attributeData
?.
HasEnsuresNotNullAttribute
==
true
);
}
}
private
ConstantValue
DefaultSyntaxValue
{
get
...
...
@@ -605,6 +624,14 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu
// NullableAttribute should not be set explicitly.
arguments
.
Diagnostics
.
Add
(
ErrorCode
.
ERR_ExplicitNullableAttribute
,
arguments
.
AttributeSyntaxOpt
.
Location
);
}
else
if
(
attribute
.
IsTargetAttribute
(
this
,
AttributeDescription
.
NotNullWhenFalseAttribute
))
{
arguments
.
GetOrCreateData
<
CommonParameterWellKnownAttributeData
>().
HasNotNullWhenFalseAttribute
=
true
;
}
else
if
(
attribute
.
IsTargetAttribute
(
this
,
AttributeDescription
.
EnsuresNotNullAttribute
))
{
arguments
.
GetOrCreateData
<
CommonParameterWellKnownAttributeData
>().
HasEnsuresNotNullAttribute
=
true
;
}
}
private
void
DecodeDefaultParameterValueAttribute
(
AttributeDescription
description
,
ref
DecodeWellKnownAttributeArguments
<
AttributeSyntax
,
CSharpAttributeData
,
AttributeLocation
>
arguments
)
...
...
src/Compilers/CSharp/Portable/Symbols/Source/SourceSimpleParameterSymbol.cs
浏览文件 @
4d285574
...
...
@@ -82,6 +82,15 @@ internal override bool IsCallerMemberName
get
{
return
false
;
}
}
internal
override
AttributeAnnotations
FlowAnalysisAnnotations
{
get
{
(
_
,
AttributeAnnotations
annotations
)
=
TryGetExtraAttributeAnnotations
();
return
annotations
;
}
}
internal
override
MarshalPseudoCustomAttributeData
MarshallingInformation
{
get
{
return
null
;
}
...
...
src/Compilers/CSharp/Portable/Symbols/Source/ThisParameterSymbol.cs
浏览文件 @
4d285574
...
...
@@ -114,6 +114,11 @@ internal override bool IsCallerMemberName
get
{
return
false
;
}
}
internal
override
AttributeAnnotations
FlowAnalysisAnnotations
{
get
{
return
AttributeAnnotations
.
None
;
}
}
public
override
int
Ordinal
{
get
{
return
-
1
;
}
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs
浏览文件 @
4d285574
...
...
@@ -115,6 +115,11 @@ internal override bool IsCallerMemberName
get
{
return
false
;
}
}
internal
override
AttributeAnnotations
FlowAnalysisAnnotations
{
get
{
return
AttributeAnnotations
.
None
;
}
}
public
override
Symbol
ContainingSymbol
{
get
{
return
_container
;
}
...
...
src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs
浏览文件 @
4d285574
...
...
@@ -153,7 +153,13 @@ internal override bool IsCallerMemberName
get
{
return
_underlyingParameter
.
IsCallerMemberName
;
}
}
public
override
string
GetDocumentationCommentXml
(
CultureInfo
preferredCulture
=
null
,
bool
expandIncludes
=
false
,
CancellationToken
cancellationToken
=
default
(
CancellationToken
))
internal
override
AttributeAnnotations
FlowAnalysisAnnotations
{
// PROTOTYPE(NullableReferenceTypes): Consider moving to leaf types
get
{
return
_underlyingParameter
.
FlowAnalysisAnnotations
;
}
}
public
override
string
GetDocumentationCommentXml
(
CultureInfo
preferredCulture
=
null
,
bool
expandIncludes
=
false
,
CancellationToken
cancellationToken
=
default
)
{
return
_underlyingParameter
.
GetDocumentationCommentXml
(
preferredCulture
,
expandIncludes
,
cancellationToken
);
}
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/StaticNullChecking.cs
浏览文件 @
4d285574
此差异已折叠。
点击以展开。
src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs
浏览文件 @
4d285574
...
...
@@ -258,6 +258,8 @@ static AttributeDescription()
private
static
readonly
byte
[][]
s_signaturesOfOutAttribute
=
{
s_signature_HasThis_Void
};
private
static
readonly
byte
[][]
s_signaturesOfIsReadOnlyAttribute
=
{
s_signature_HasThis_Void
};
private
static
readonly
byte
[][]
s_signaturesOfIsUnmanagedAttribute
=
{
s_signature_HasThis_Void
};
private
static
readonly
byte
[][]
s_signaturesOfNotNullWhenFalseAttribute
=
{
s_signature_HasThis_Void
};
private
static
readonly
byte
[][]
s_signaturesOfEnsuresNotNullAttribute
=
{
s_signature_HasThis_Void
};
private
static
readonly
byte
[][]
s_signaturesOfFixedBufferAttribute
=
{
s_signature_HasThis_Void_Type_Int32
};
private
static
readonly
byte
[][]
s_signaturesOfSuppressUnmanagedCodeSecurityAttribute
=
{
s_signature_HasThis_Void
};
private
static
readonly
byte
[][]
s_signaturesOfPrincipalPermissionAttribute
=
{
s_signature_HasThis_Void_SecurityAction
};
...
...
@@ -454,6 +456,8 @@ static AttributeDescription()
internal
static
readonly
AttributeDescription
StructLayoutAttribute
=
new
AttributeDescription
(
"System.Runtime.InteropServices"
,
"StructLayoutAttribute"
,
s_signaturesOfStructLayoutAttribute
);
internal
static
readonly
AttributeDescription
FieldOffsetAttribute
=
new
AttributeDescription
(
"System.Runtime.InteropServices"
,
"FieldOffsetAttribute"
,
s_signaturesOfFieldOffsetAttribute
);
internal
static
readonly
AttributeDescription
FixedBufferAttribute
=
new
AttributeDescription
(
"System.Runtime.CompilerServices"
,
"FixedBufferAttribute"
,
s_signaturesOfFixedBufferAttribute
);
internal
static
readonly
AttributeDescription
NotNullWhenFalseAttribute
=
new
AttributeDescription
(
"System.Runtime.CompilerServices"
,
"NotNullWhenFalseAttribute"
,
s_signaturesOfNotNullWhenFalseAttribute
);
internal
static
readonly
AttributeDescription
EnsuresNotNullAttribute
=
new
AttributeDescription
(
"System.Runtime.CompilerServices"
,
"EnsuresNotNullAttribute"
,
s_signaturesOfEnsuresNotNullAttribute
);
internal
static
readonly
AttributeDescription
MarshalAsAttribute
=
new
AttributeDescription
(
"System.Runtime.InteropServices"
,
"MarshalAsAttribute"
,
s_signaturesOfMarshalAsAttribute
);
internal
static
readonly
AttributeDescription
InAttribute
=
new
AttributeDescription
(
"System.Runtime.InteropServices"
,
"InAttribute"
,
s_signaturesOfInAttribute
);
internal
static
readonly
AttributeDescription
OutAttribute
=
new
AttributeDescription
(
"System.Runtime.InteropServices"
,
"OutAttribute"
,
s_signaturesOfOutAttribute
);
...
...
src/Compilers/Core/Portable/Symbols/Attributes/CommonParameterWellKnownAttributeData.cs
浏览文件 @
4d285574
...
...
@@ -109,5 +109,38 @@ public bool HasIUnknownConstantAttribute
}
}
#
endregion
// PROTOTYPE(NullableReferenceTypes): Consider moving the attribute for nullability to C#-specific type
private
bool
_hasNotNullWhenFalseAttribute
;
public
bool
HasNotNullWhenFalseAttribute
{
get
{
VerifySealed
(
expected
:
true
);
return
_hasNotNullWhenFalseAttribute
;
}
set
{
VerifySealed
(
expected
:
false
);
_hasNotNullWhenFalseAttribute
=
value
;
SetDataStored
();
}
}
private
bool
_hasEnsuresNotNullAttribute
;
public
bool
HasEnsuresNotNullAttribute
{
get
{
VerifySealed
(
expected
:
true
);
return
_hasEnsuresNotNullAttribute
;
}
set
{
VerifySealed
(
expected
:
false
);
_hasEnsuresNotNullAttribute
=
value
;
SetDataStored
();
}
}
}
}
src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
浏览文件 @
4d285574
...
...
@@ -306,7 +306,11 @@ public static SyntaxTree ParseWithRoundTripCheck(string text, CSharpParseOptions
string
ilSource
,
IEnumerable
<
MetadataReference
>
references
=
null
,
CSharpCompilationOptions
options
=
null
,
bool
appendDefaultHeader
=
true
)
=>
CreateCompilationWithILAndMscorlib40
(
source
,
ilSource
,
TargetFramework
.
Standard
,
references
,
options
,
appendDefaultHeader
);
CSharpParseOptions
parseOptions
=
null
,
bool
appendDefaultHeader
=
true
)
{
return
CreateCompilationWithILAndMscorlib40
(
source
,
ilSource
,
TargetFramework
.
Standard
,
references
,
options
,
parseOptions
,
appendDefaultHeader
);
}
public
static
CSharpCompilation
CreateCompilationWithILAndMscorlib40
(
CSharpTestSource
source
,
...
...
@@ -314,11 +318,12 @@ public static SyntaxTree ParseWithRoundTripCheck(string text, CSharpParseOptions
TargetFramework
targetFramework
=
TargetFramework
.
Mscorlib40
,
IEnumerable
<
MetadataReference
>
references
=
null
,
CSharpCompilationOptions
options
=
null
,
CSharpParseOptions
parseOptions
=
null
,
bool
appendDefaultHeader
=
true
)
{
MetadataReference
ilReference
=
CompileIL
(
ilSource
,
appendDefaultHeader
);
var
allReferences
=
TargetFrameworkUtil
.
GetReferences
(
targetFramework
,
references
).
Add
(
ilReference
);
return
CreateEmptyCompilation
(
source
,
allReferences
,
options
);
return
CreateEmptyCompilation
(
source
,
allReferences
,
options
,
parseOptions
);
}
public
static
CSharpCompilation
CreateCompilationWithMscorlib40
(
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录