Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
5d1ba27f
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,发现更多精彩内容 >>
未验证
提交
5d1ba27f
编写于
7月 28, 2020
作者:
A
AlekseyTs
提交者:
GitHub
7月 28, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Adjust records behavior around IOperations and analyzer actions. (#46308)
上级
1386d0fd
变更
9
展开全部
显示空白变更内容
内联
并排
Showing
9 changed file
with
1999 addition
and
45 deletion
+1999
-45
src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs
.../CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs
+21
-1
src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs
...pilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs
+1
-28
src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
...pilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
+5
-0
src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs
...rs/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs
+106
-5
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
+1835
-7
src/Compilers/Core/AnalyzerDriver/DeclarationComputer.cs
src/Compilers/Core/AnalyzerDriver/DeclarationComputer.cs
+5
-0
src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs
...pilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs
+5
-0
src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs
...lers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs
+14
-1
src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
+7
-3
未找到文件。
src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs
浏览文件 @
5d1ba27f
...
...
@@ -5,6 +5,7 @@
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Linq
;
using
System.Threading
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
...
...
@@ -95,10 +96,29 @@ private static bool InvalidLevel(int? level)
return
;
}
case
SyntaxKind
.
RecordDeclaration
:
{
if
(
associatedSymbol
is
IMethodSymbol
ctor
)
{
var
recordDeclaration
=
(
RecordDeclarationSyntax
)
node
;
Debug
.
Assert
(
ctor
.
MethodKind
==
MethodKind
.
Constructor
&&
recordDeclaration
.
ParameterList
is
object
);
var
codeBlocks
=
GetParameterListInitializersAndAttributes
(
recordDeclaration
.
ParameterList
);
if
(
recordDeclaration
.
BaseList
?.
Types
.
FirstOrDefault
()
is
PrimaryConstructorBaseTypeSyntax
initializer
)
{
codeBlocks
=
codeBlocks
.
Concat
(
initializer
);
}
builder
.
Add
(
GetDeclarationInfo
(
node
,
associatedSymbol
,
codeBlocks
));
return
;
}
goto
case
SyntaxKind
.
ClassDeclaration
;
}
case
SyntaxKind
.
ClassDeclaration
:
case
SyntaxKind
.
StructDeclaration
:
case
SyntaxKind
.
InterfaceDeclaration
:
case
SyntaxKind
.
RecordDeclaration
:
{
var
t
=
(
TypeDeclarationSyntax
)
node
;
foreach
(
var
decl
in
t
.
Members
)
...
...
src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs
浏览文件 @
5d1ba27f
...
...
@@ -5106,34 +5106,7 @@ internal override void ComputeDeclarationsInNode(SyntaxNode node, ISymbol associ
CSharpDeclarationComputer
.
ComputeDeclarationsInNode
(
this
,
associatedSymbol
,
node
,
getSymbol
,
builder
,
cancellationToken
,
levelsToCompute
);
}
internal
override
Func
<
SyntaxNode
,
bool
>
GetSyntaxNodesToAnalyzeFilter
(
SyntaxNode
declaredNode
,
ISymbol
declaredSymbol
)
{
if
(
declaredNode
is
CompilationUnitSyntax
unit
&&
SimpleProgramNamedTypeSymbol
.
GetSimpleProgramEntryPoint
(
Compilation
,
unit
,
fallbackToMainEntryPoint
:
false
)
is
SynthesizedSimpleProgramEntryPointSymbol
entryPoint
)
{
switch
(
declaredSymbol
.
Kind
)
{
case
SymbolKind
.
Namespace
:
Debug
.
Assert
(((
INamespaceSymbol
)
declaredSymbol
).
IsGlobalNamespace
);
// Do not include top level global statements into a global namespace
return
(
node
)
=>
node
.
Kind
()
!=
SyntaxKind
.
GlobalStatement
||
node
.
Parent
!=
unit
;
case
SymbolKind
.
Method
:
Debug
.
Assert
((
object
)
declaredSymbol
.
GetSymbol
()
==
(
object
)
entryPoint
);
// Include only global statements at the top level
return
(
node
)
=>
node
.
Parent
!=
unit
||
node
.
Kind
()
==
SyntaxKind
.
GlobalStatement
;
case
SymbolKind
.
NamedType
:
Debug
.
Assert
((
object
)
declaredSymbol
.
GetSymbol
()
==
(
object
)
entryPoint
.
ContainingSymbol
);
return
(
node
)
=>
false
;
default
:
ExceptionUtilities
.
UnexpectedValue
(
declaredSymbol
.
Kind
);
break
;
}
}
return
base
.
GetSyntaxNodesToAnalyzeFilter
(
declaredNode
,
declaredSymbol
);
}
internal
abstract
override
Func
<
SyntaxNode
,
bool
>
GetSyntaxNodesToAnalyzeFilter
(
SyntaxNode
declaredNode
,
ISymbol
declaredSymbol
);
protected
internal
override
SyntaxNode
GetTopmostNodeForDiagnosticAnalysis
(
ISymbol
symbol
,
SyntaxNode
declaringSyntax
)
{
...
...
src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
浏览文件 @
5d1ba27f
...
...
@@ -2323,6 +2323,11 @@ internal override Symbol RemapSymbolIfNecessaryCore(Symbol symbol)
}
}
internal
sealed
override
Func
<
SyntaxNode
,
bool
>
GetSyntaxNodesToAnalyzeFilter
(
SyntaxNode
declaredNode
,
ISymbol
declaredSymbol
)
{
throw
ExceptionUtilities
.
Unreachable
;
}
/// <summary>
/// The incremental binder is used when binding statements. Whenever a statement
/// is bound, it checks the bound node cache to see if that statement was bound,
...
...
src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs
浏览文件 @
5d1ba27f
...
...
@@ -178,7 +178,9 @@ internal override IOperation GetOperationWorker(CSharpSyntaxNode node, Cancellat
case
AccessorDeclarationSyntax
accessor
:
model
=
(
accessor
.
Body
!=
null
||
accessor
.
ExpressionBody
!=
null
)
?
GetOrAddModel
(
node
)
:
null
;
break
;
case
RecordDeclarationSyntax
{
ParameterList
:
{
},
PrimaryConstructorBaseType
:
{
}
}
recordDeclaration
when
TryGetSynthesizedRecordConstructor
(
recordDeclaration
)
is
SynthesizedRecordConstructor
ctor
:
model
=
GetOrAddModel
(
recordDeclaration
);
break
;
default
:
model
=
this
.
GetMemberModel
(
node
);
break
;
...
...
@@ -1087,10 +1089,9 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
case
SyntaxKind
.
RecordDeclaration
:
{
var
recordType
=
GetDeclaredSymbol
((
TypeDeclarationSyntax
)
node
).
GetSymbol
<
NamedTypeSymbol
>();
var
symbol
=
recordType
.
GetMembersUnordered
().
OfType
<
SynthesizedRecordConstructor
>().
SingleOrDefault
();
SynthesizedRecordConstructor
symbol
=
TryGetSynthesizedRecordConstructor
((
RecordDeclarationSyntax
)
node
);
if
(
symbol
?.
GetSyntax
()
!=
node
)
if
(
symbol
is
null
)
{
return
null
;
}
...
...
@@ -1250,6 +1251,19 @@ MemberSemanticModel createMethodBodySemanticModel(CSharpSyntaxNode memberDecl, S
}
}
private
SynthesizedRecordConstructor
TryGetSynthesizedRecordConstructor
(
RecordDeclarationSyntax
node
)
{
NamedTypeSymbol
recordType
=
GetDeclaredType
(
node
);
var
symbol
=
recordType
.
GetMembersUnordered
().
OfType
<
SynthesizedRecordConstructor
>().
SingleOrDefault
();
if
(
symbol
?.
GetSyntax
()
!=
node
)
{
return
null
;
}
return
symbol
;
}
private
AttributeSemanticModel
CreateModelForAttribute
(
Binder
enclosingBinder
,
AttributeSyntax
attribute
,
MemberSemanticModel
containingModel
)
{
AliasSymbol
aliasOpt
;
...
...
@@ -2006,7 +2020,14 @@ internal override ImmutableArray<ISymbol> GetDeclaredSymbols(BaseFieldDeclaratio
MethodSymbol
method
;
if
(
memberDecl
is
RecordDeclarationSyntax
recordDecl
&&
recordDecl
.
ParameterList
==
paramList
)
{
method
=
TryGetSynthesizedRecordConstructor
(
recordDecl
);
}
else
{
method
=
(
GetDeclaredSymbol
(
memberDecl
,
cancellationToken
)
as
IMethodSymbol
).
GetSymbol
();
}
if
((
object
)
method
==
null
)
{
...
...
@@ -2334,5 +2355,85 @@ internal override Symbol RemapSymbolIfNecessaryCore(Symbol symbol)
var
memberModel
=
GetMemberModel
(
position
);
return
memberModel
?.
RemapSymbolIfNecessaryCore
(
symbol
)
??
symbol
;
}
internal
override
Func
<
SyntaxNode
,
bool
>
GetSyntaxNodesToAnalyzeFilter
(
SyntaxNode
declaredNode
,
ISymbol
declaredSymbol
)
{
switch
(
declaredNode
)
{
case
CompilationUnitSyntax
unit
when
SimpleProgramNamedTypeSymbol
.
GetSimpleProgramEntryPoint
(
Compilation
,
unit
,
fallbackToMainEntryPoint
:
false
)
is
SynthesizedSimpleProgramEntryPointSymbol
entryPoint
:
switch
(
declaredSymbol
.
Kind
)
{
case
SymbolKind
.
Namespace
:
Debug
.
Assert
(((
INamespaceSymbol
)
declaredSymbol
).
IsGlobalNamespace
);
// Do not include top level global statements into a global namespace
return
(
node
)
=>
node
.
Kind
()
!=
SyntaxKind
.
GlobalStatement
||
node
.
Parent
!=
unit
;
case
SymbolKind
.
Method
:
Debug
.
Assert
((
object
)
declaredSymbol
.
GetSymbol
()
==
(
object
)
entryPoint
);
// Include only global statements at the top level
return
(
node
)
=>
node
.
Parent
!=
unit
||
node
.
Kind
()
==
SyntaxKind
.
GlobalStatement
;
case
SymbolKind
.
NamedType
:
Debug
.
Assert
((
object
)
declaredSymbol
.
GetSymbol
()
==
(
object
)
entryPoint
.
ContainingSymbol
);
return
(
node
)
=>
false
;
default
:
ExceptionUtilities
.
UnexpectedValue
(
declaredSymbol
.
Kind
);
break
;
}
break
;
case
RecordDeclarationSyntax
recordDeclaration
when
TryGetSynthesizedRecordConstructor
(
recordDeclaration
)
is
SynthesizedRecordConstructor
ctor
:
switch
(
declaredSymbol
.
Kind
)
{
case
SymbolKind
.
Method
:
Debug
.
Assert
((
object
)
declaredSymbol
.
GetSymbol
()
==
(
object
)
ctor
);
return
(
node
)
=>
{
// Accept only nodes that either match, or above/below of a 'parameter list'/'base arguments list'.
if
(
node
.
Parent
==
recordDeclaration
)
{
return
node
==
recordDeclaration
.
ParameterList
||
node
==
recordDeclaration
.
BaseList
;
}
else
if
(
node
.
Parent
is
BaseListSyntax
baseList
)
{
return
node
==
recordDeclaration
.
PrimaryConstructorBaseType
;
}
else
if
(
node
.
Parent
is
PrimaryConstructorBaseTypeSyntax
baseType
&&
baseType
==
recordDeclaration
.
PrimaryConstructorBaseType
)
{
return
node
==
baseType
.
ArgumentList
;
}
return
true
;
};
case
SymbolKind
.
NamedType
:
Debug
.
Assert
((
object
)
declaredSymbol
.
GetSymbol
()
==
(
object
)
ctor
.
ContainingSymbol
);
// Accept nodes that do not match a 'parameter list'/'base arguments list'.
return
(
node
)
=>
node
!=
recordDeclaration
.
ParameterList
&&
!(
node
.
Kind
()
==
SyntaxKind
.
ArgumentList
&&
node
==
recordDeclaration
.
PrimaryConstructorBaseType
?.
ArgumentList
);
default
:
ExceptionUtilities
.
UnexpectedValue
(
declaredSymbol
.
Kind
);
break
;
}
break
;
case
PrimaryConstructorBaseTypeSyntax
{
Parent
:
BaseListSyntax
{
Parent
:
RecordDeclarationSyntax
recordDeclaration
}
}
baseType
when
recordDeclaration
.
PrimaryConstructorBaseType
==
declaredNode
&&
TryGetSynthesizedRecordConstructor
(
recordDeclaration
)
is
SynthesizedRecordConstructor
ctor
:
if
((
object
)
declaredSymbol
.
GetSymbol
()
==
(
object
)
ctor
)
{
// Only 'base arguments list' or nodes below it
return
(
node
)
=>
node
!=
baseType
.
Type
;
}
break
;
case
ParameterSyntax
param
when
declaredSymbol
.
Kind
==
SymbolKind
.
Property
&&
param
.
Parent
?.
Parent
is
RecordDeclarationSyntax
recordDeclaration
&&
recordDeclaration
.
ParameterList
==
param
.
Parent
:
Debug
.
Assert
(
declaredSymbol
.
GetSymbol
()
is
SynthesizedRecordPropertySymbol
);
return
(
node
)
=>
false
;
}
return
null
;
}
}
}
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
浏览文件 @
5d1ba27f
此差异已折叠。
点击以展开。
src/Compilers/Core/AnalyzerDriver/DeclarationComputer.cs
浏览文件 @
5d1ba27f
...
...
@@ -18,6 +18,11 @@ internal class DeclarationComputer
internal
static
DeclarationInfo
GetDeclarationInfo
(
SemanticModel
model
,
SyntaxNode
node
,
bool
getSymbol
,
IEnumerable
<
SyntaxNode
>?
executableCodeBlocks
,
CancellationToken
cancellationToken
)
{
var
declaredSymbol
=
GetDeclaredSymbol
(
model
,
node
,
getSymbol
,
cancellationToken
);
return
GetDeclarationInfo
(
node
,
declaredSymbol
,
executableCodeBlocks
);
}
internal
static
DeclarationInfo
GetDeclarationInfo
(
SyntaxNode
node
,
ISymbol
?
declaredSymbol
,
IEnumerable
<
SyntaxNode
>?
executableCodeBlocks
)
{
var
codeBlocks
=
executableCodeBlocks
?.
Where
(
c
=>
c
!=
null
).
AsImmutableOrEmpty
()
??
ImmutableArray
<
SyntaxNode
>.
Empty
;
return
new
DeclarationInfo
(
node
,
codeBlocks
,
declaredSymbol
);
}
...
...
src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs
浏览文件 @
5d1ba27f
...
...
@@ -2767,6 +2767,7 @@ private static bool IsEquivalentSymbol(ISymbol declaredSymbol, ISymbol otherSymb
{
case
OperationKind
.
MethodBody
:
case
OperationKind
.
ConstructorBody
:
Debug
.
Assert
(!
operationBlock
.
Parent
.
IsImplicit
);
operationsToAnalyze
.
Add
(
operationBlock
.
Parent
);
break
;
...
...
@@ -2776,6 +2777,10 @@ private static bool IsEquivalentSymbol(ISymbol declaredSymbol, ISymbol otherSymb
Debug
.
Assert
(
operationBlock
.
Parent
.
IsImplicit
);
Debug
.
Assert
(
operationBlock
.
Parent
.
Parent
is
IConstructorBodyOperation
ctorBody
&&
ctorBody
.
Initializer
==
operationBlock
.
Parent
);
Debug
.
Assert
(!
operationBlock
.
Parent
.
Parent
.
IsImplicit
);
operationsToAnalyze
.
Add
(
operationBlock
.
Parent
.
Parent
);
break
;
default
:
...
...
src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs
浏览文件 @
5d1ba27f
...
...
@@ -943,7 +943,20 @@ public void MarkSymbolEndAnalysisComplete(ISymbol symbol, DiagnosticAnalyzer ana
{
ExecuteBlockActionsCore
<
CodeBlockStartAnalyzerAction
<
TLanguageKindEnum
>,
CodeBlockAnalyzerAction
,
SyntaxNodeAnalyzerAction
<
TLanguageKindEnum
>,
SyntaxNodeAnalyzerStateData
,
SyntaxNode
,
TLanguageKindEnum
>(
codeBlockStartActions
,
codeBlockActions
,
codeBlockEndActions
,
analyzer
,
declaredNode
,
declaredSymbol
,
executableCodeBlocks
,
(
codeBlocks
)
=>
codeBlocks
.
SelectMany
(
cb
=>
cb
.
DescendantNodesAndSelf
()),
declaredNode
,
declaredSymbol
,
executableCodeBlocks
,
(
codeBlocks
)
=>
codeBlocks
.
SelectMany
(
cb
=>
{
var
filter
=
semanticModel
.
GetSyntaxNodesToAnalyzeFilter
(
cb
,
declaredSymbol
);
if
(
filter
is
object
)
{
return
cb
.
DescendantNodesAndSelf
(
descendIntoChildren
:
filter
).
Where
(
filter
);
}
else
{
return
cb
.
DescendantNodesAndSelf
();
}
}),
semanticModel
,
getKind
,
analyzerStateOpt
?.
CodeBlockAnalysisState
,
isGeneratedCode
);
return
true
;
}
...
...
src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
浏览文件 @
5d1ba27f
...
...
@@ -1769,9 +1769,13 @@ protected static IOperation VerifyOperationTreeForTest<TSyntaxNode>(CSharpCompil
protected
static
void
VerifyOperationTreeForNode
(
CSharpCompilation
compilation
,
SemanticModel
model
,
SyntaxNode
syntaxNode
,
string
expectedOperationTree
)
{
var
actualOperation
=
model
.
GetOperation
(
syntaxNode
);
Assert
.
NotNull
(
actualOperation
);
var
actualOperationTree
=
GetOperationTreeForTest
(
compilation
,
actualOperation
);
VerifyOperationTree
(
compilation
,
model
.
GetOperation
(
syntaxNode
),
expectedOperationTree
);
}
protected
static
void
VerifyOperationTree
(
CSharpCompilation
compilation
,
IOperation
operation
,
string
expectedOperationTree
)
{
Assert
.
NotNull
(
operation
);
var
actualOperationTree
=
GetOperationTreeForTest
(
compilation
,
operation
);
OperationTreeVerifier
.
Verify
(
expectedOperationTree
,
actualOperationTree
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录