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 @@
...
@@ -5,6 +5,7 @@
using
System
;
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Linq
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
...
@@ -95,10 +96,29 @@ private static bool InvalidLevel(int? level)
...
@@ -95,10 +96,29 @@ private static bool InvalidLevel(int? level)
return
;
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
.
ClassDeclaration
:
case
SyntaxKind
.
StructDeclaration
:
case
SyntaxKind
.
StructDeclaration
:
case
SyntaxKind
.
InterfaceDeclaration
:
case
SyntaxKind
.
InterfaceDeclaration
:
case
SyntaxKind
.
RecordDeclaration
:
{
{
var
t
=
(
TypeDeclarationSyntax
)
node
;
var
t
=
(
TypeDeclarationSyntax
)
node
;
foreach
(
var
decl
in
t
.
Members
)
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
...
@@ -5106,34 +5106,7 @@ internal override void ComputeDeclarationsInNode(SyntaxNode node, ISymbol associ
CSharpDeclarationComputer
.
ComputeDeclarationsInNode
(
this
,
associatedSymbol
,
node
,
getSymbol
,
builder
,
cancellationToken
,
levelsToCompute
);
CSharpDeclarationComputer
.
ComputeDeclarationsInNode
(
this
,
associatedSymbol
,
node
,
getSymbol
,
builder
,
cancellationToken
,
levelsToCompute
);
}
}
internal
override
Func
<
SyntaxNode
,
bool
>
GetSyntaxNodesToAnalyzeFilter
(
SyntaxNode
declaredNode
,
ISymbol
declaredSymbol
)
internal
abstract
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
);
}
protected
internal
override
SyntaxNode
GetTopmostNodeForDiagnosticAnalysis
(
ISymbol
symbol
,
SyntaxNode
declaringSyntax
)
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)
...
@@ -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>
/// <summary>
/// The incremental binder is used when binding statements. Whenever a statement
/// 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,
/// 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
...
@@ -178,7 +178,9 @@ internal override IOperation GetOperationWorker(CSharpSyntaxNode node, Cancellat
case
AccessorDeclarationSyntax
accessor
:
case
AccessorDeclarationSyntax
accessor
:
model
=
(
accessor
.
Body
!=
null
||
accessor
.
ExpressionBody
!=
null
)
?
GetOrAddModel
(
node
)
:
null
;
model
=
(
accessor
.
Body
!=
null
||
accessor
.
ExpressionBody
!=
null
)
?
GetOrAddModel
(
node
)
:
null
;
break
;
break
;
case
RecordDeclarationSyntax
{
ParameterList
:
{
},
PrimaryConstructorBaseType
:
{
}
}
recordDeclaration
when
TryGetSynthesizedRecordConstructor
(
recordDeclaration
)
is
SynthesizedRecordConstructor
ctor
:
model
=
GetOrAddModel
(
recordDeclaration
);
break
;
default
:
default
:
model
=
this
.
GetMemberModel
(
node
);
model
=
this
.
GetMemberModel
(
node
);
break
;
break
;
...
@@ -1087,10 +1089,9 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
...
@@ -1087,10 +1089,9 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
case
SyntaxKind
.
RecordDeclaration
:
case
SyntaxKind
.
RecordDeclaration
:
{
{
var
recordType
=
GetDeclaredSymbol
((
TypeDeclarationSyntax
)
node
).
GetSymbol
<
NamedTypeSymbol
>();
SynthesizedRecordConstructor
symbol
=
TryGetSynthesizedRecordConstructor
((
RecordDeclarationSyntax
)
node
);
var
symbol
=
recordType
.
GetMembersUnordered
().
OfType
<
SynthesizedRecordConstructor
>().
SingleOrDefault
();
if
(
symbol
?.
GetSyntax
()
!=
node
)
if
(
symbol
is
null
)
{
{
return
null
;
return
null
;
}
}
...
@@ -1250,6 +1251,19 @@ MemberSemanticModel createMethodBodySemanticModel(CSharpSyntaxNode memberDecl, S
...
@@ -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
)
private
AttributeSemanticModel
CreateModelForAttribute
(
Binder
enclosingBinder
,
AttributeSyntax
attribute
,
MemberSemanticModel
containingModel
)
{
{
AliasSymbol
aliasOpt
;
AliasSymbol
aliasOpt
;
...
@@ -2006,7 +2020,14 @@ internal override ImmutableArray<ISymbol> GetDeclaredSymbols(BaseFieldDeclaratio
...
@@ -2006,7 +2020,14 @@ internal override ImmutableArray<ISymbol> GetDeclaredSymbols(BaseFieldDeclaratio
MethodSymbol
method
;
MethodSymbol
method
;
if
(
memberDecl
is
RecordDeclarationSyntax
recordDecl
&&
recordDecl
.
ParameterList
==
paramList
)
{
method
=
TryGetSynthesizedRecordConstructor
(
recordDecl
);
}
else
{
method
=
(
GetDeclaredSymbol
(
memberDecl
,
cancellationToken
)
as
IMethodSymbol
).
GetSymbol
();
method
=
(
GetDeclaredSymbol
(
memberDecl
,
cancellationToken
)
as
IMethodSymbol
).
GetSymbol
();
}
if
((
object
)
method
==
null
)
if
((
object
)
method
==
null
)
{
{
...
@@ -2334,5 +2355,85 @@ internal override Symbol RemapSymbolIfNecessaryCore(Symbol symbol)
...
@@ -2334,5 +2355,85 @@ internal override Symbol RemapSymbolIfNecessaryCore(Symbol symbol)
var
memberModel
=
GetMemberModel
(
position
);
var
memberModel
=
GetMemberModel
(
position
);
return
memberModel
?.
RemapSymbolIfNecessaryCore
(
symbol
)
??
symbol
;
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
...
@@ -8,9 +8,13 @@
...
@@ -8,9 +8,13 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.Immutable;
using System.Linq;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FlowAnalysis;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Test.Extensions;
using Microsoft.CodeAnalysis.Test.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Test.Utilities;
...
@@ -5755,7 +5759,6 @@ static void Main()
...
@@ -5755,7 +5759,6 @@ static void Main()
}
}
}";
}";
comp = CreateCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.RegularPreview, options: TestOptions.ReleaseExe);
comp = CreateCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.RegularPreview, options: TestOptions.ReleaseExe);
comp.VerifyDiagnostics();
var actualMembers = GetProperties(comp, "C").ToTestDisplayStrings();
var actualMembers = GetProperties(comp, "C").ToTestDisplayStrings();
AssertEx.Equal(new[] { "System.Type C.EqualityContract { get; }" }, actualMembers);
AssertEx.Equal(new[] { "System.Type C.EqualityContract { get; }" }, actualMembers);
...
@@ -14823,7 +14826,7 @@ public Base(int X, int Y)
...
@@ -14823,7 +14826,7 @@ public Base(int X, int Y)
public Base() {}
public Base() {}
}
}
record C(int X, int Y) : Base(X, Y)
record C(int X, int Y
= 123
) : Base(X, Y)
{
{
int Z = 123;
int Z = 123;
public static void Main()
public static void Main()
...
@@ -14832,7 +14835,7 @@ public static void Main()
...
@@ -14832,7 +14835,7 @@ public static void Main()
Console.WriteLine(c.Z);
Console.WriteLine(c.Z);
}
}
C(int X, int Y, int Z) : this(X, Y) {}
C(int X, int Y, int Z
= 124
) : this(X, Y) {}
}";
}";
var verifier = CompileAndVerify(src, expectedOutput: @"
var verifier = CompileAndVerify(src, expectedOutput: @"
1
1
...
@@ -14872,7 +14875,7 @@ .maxstack 3
...
@@ -14872,7 +14875,7 @@ .maxstack 3
var symbol = model.GetSymbolInfo(x).Symbol;
var symbol = model.GetSymbolInfo(x).Symbol;
Assert.Equal(SymbolKind.Parameter, symbol!.Kind);
Assert.Equal(SymbolKind.Parameter, symbol!.Kind);
Assert.Equal("System.Int32 X", symbol.ToTestDisplayString());
Assert.Equal("System.Int32 X", symbol.ToTestDisplayString());
Assert.Equal("C..ctor(System.Int32 X,
System.Int32 Y
)", symbol.ContainingSymbol.ToTestDisplayString());
Assert.Equal("C..ctor(System.Int32 X,
[System.Int32 Y = 123]
)", symbol.ContainingSymbol.ToTestDisplayString());
Assert.Equal(Accessibility.Public, symbol.ContainingSymbol.DeclaredAccessibility);
Assert.Equal(Accessibility.Public, symbol.ContainingSymbol.DeclaredAccessibility);
Assert.Same(symbol.ContainingSymbol, model.GetEnclosingSymbol(x.SpanStart));
Assert.Same(symbol.ContainingSymbol, model.GetEnclosingSymbol(x.SpanStart));
Assert.Contains(symbol, model.LookupSymbols(x.SpanStart, name: "X"));
Assert.Contains(symbol, model.LookupSymbols(x.SpanStart, name: "X"));
...
@@ -14902,17 +14905,153 @@ .maxstack 3
...
@@ -14902,17 +14905,153 @@ .maxstack 3
model = comp.GetSemanticModel(tree);
model = comp.GetSemanticModel(tree);
Assert.Empty(model.GetMemberGroup(baseWithargs));
Assert.Empty(model.GetMemberGroup(baseWithargs));
model = comp.GetSemanticModel(tree);
model = comp.GetSemanticModel(tree);
#nullable disable
var operation = model.GetOperation(baseWithargs);
VerifyOperationTree(comp, operation,
@"
IInvocationOperation ( Base..ctor(System.Int32 X, System.Int32 Y)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Base(X, Y)')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Base, IsImplicit) (Syntax: 'Base(X, Y)')
Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: X) (OperationKind.Argument, Type: null) (Syntax: 'X')
IParameterReferenceOperation: X (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'X')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: Y) (OperationKind.Argument, Type: null) (Syntax: 'Y')
IParameterReferenceOperation: Y (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'Y')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
");
Assert.Null(model.GetOperation(baseWithargs.Type));
Assert.Null(model.GetOperation(baseWithargs.Parent));
Assert.Same(operation.Parent.Parent, model.GetOperation(baseWithargs.Parent.Parent));
Assert.Equal(SyntaxKind.RecordDeclaration, baseWithargs.Parent.Parent.Kind());
VerifyOperationTree(comp, operation.Parent.Parent,
@"
IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'record C(in ... }')
Initializer:
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'Base(X, Y)')
Expression:
IInvocationOperation ( Base..ctor(System.Int32 X, System.Int32 Y)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Base(X, Y)')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Base, IsImplicit) (Syntax: 'Base(X, Y)')
Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: X) (OperationKind.Argument, Type: null) (Syntax: 'X')
IParameterReferenceOperation: X (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'X')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: Y) (OperationKind.Argument, Type: null) (Syntax: 'Y')
IParameterReferenceOperation: Y (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'Y')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
BlockBody:
IBlockOperation (0 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'record C(in ... }')
ExpressionBody:
null
");
Assert.Null(operation.Parent.Parent.Parent);
ControlFlowGraphVerifier.VerifyGraph(comp,
@"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'Base(X, Y)')
Expression:
IInvocationOperation ( Base..ctor(System.Int32 X, System.Int32 Y)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Base(X, Y)')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Base, IsImplicit) (Syntax: 'Base(X, Y)')
Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: X) (OperationKind.Argument, Type: null) (Syntax: 'X')
IParameterReferenceOperation: X (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'X')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: Y) (OperationKind.Argument, Type: null) (Syntax: 'Y')
IParameterReferenceOperation: Y (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'Y')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Next (Regular) Block[B2]
Block[B2] - Exit
Predecessors: [B1]
Statements (0)
", ControlFlowGraph.Create((IConstructorBodyOperation)operation.Parent.Parent));
var equalsValue = tree.GetRoot().DescendantNodes().OfType<EqualsValueClauseSyntax>().First();
Assert.Equal("= 123", equalsValue.ToString());
model.VerifyOperationTree(equalsValue,
@"
IParameterInitializerOperation (Parameter: [System.Int32 Y = 123]) (OperationKind.ParameterInitializer, Type: null) (Syntax: '= 123')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 123) (Syntax: '123')
");
#nullable enable
}
}
{
{
var baseWithargs = tree.GetRoot().DescendantNodes().OfType<ConstructorInitializerSyntax>().Single();
var baseWithargs = tree.GetRoot().DescendantNodes().OfType<ConstructorInitializerSyntax>().Single();
Assert.Equal(": this(X, Y)", baseWithargs.ToString());
Assert.Equal(": this(X, Y)", baseWithargs.ToString());
Assert.Equal("C..ctor(System.Int32 X,
System.Int32 Y
)", model.GetSymbolInfo((SyntaxNode)baseWithargs).Symbol.ToTestDisplayString());
Assert.Equal("C..ctor(System.Int32 X,
[System.Int32 Y = 123]
)", model.GetSymbolInfo((SyntaxNode)baseWithargs).Symbol.ToTestDisplayString());
Assert.Equal("C..ctor(System.Int32 X,
System.Int32 Y
)", model.GetSymbolInfo(baseWithargs).Symbol.ToTestDisplayString());
Assert.Equal("C..ctor(System.Int32 X,
[System.Int32 Y = 123]
)", model.GetSymbolInfo(baseWithargs).Symbol.ToTestDisplayString());
Assert.Equal("C..ctor(System.Int32 X,
System.Int32 Y
)", CSharpExtensions.GetSymbolInfo(model, baseWithargs).Symbol.ToTestDisplayString());
Assert.Equal("C..ctor(System.Int32 X,
[System.Int32 Y = 123]
)", CSharpExtensions.GetSymbolInfo(model, baseWithargs).Symbol.ToTestDisplayString());
Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs).Select(m => m.ToTestDisplayString()));
Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs).Select(m => m.ToTestDisplayString()));
Assert.Empty(model.GetMemberGroup(baseWithargs).Select(m => m.ToTestDisplayString()));
Assert.Empty(model.GetMemberGroup(baseWithargs).Select(m => m.ToTestDisplayString()));
Assert.Empty(CSharpExtensions.GetMemberGroup(model, baseWithargs).Select(m => m.ToTestDisplayString()));
Assert.Empty(CSharpExtensions.GetMemberGroup(model, baseWithargs).Select(m => m.ToTestDisplayString()));
model.VerifyOperationTree(baseWithargs,
@"
IInvocationOperation ( C..ctor(System.Int32 X, [System.Int32 Y = 123])) (OperationKind.Invocation, Type: System.Void) (Syntax: ': this(X, Y)')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: ': this(X, Y)')
Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: X) (OperationKind.Argument, Type: null) (Syntax: 'X')
IParameterReferenceOperation: X (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'X')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: Y) (OperationKind.Argument, Type: null) (Syntax: 'Y')
IParameterReferenceOperation: Y (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'Y')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
");
var equalsValue = tree.GetRoot().DescendantNodes().OfType<EqualsValueClauseSyntax>().Last();
Assert.Equal("= 124", equalsValue.ToString());
model.VerifyOperationTree(equalsValue,
@"
IParameterInitializerOperation (Parameter: [System.Int32 Z = 124]) (OperationKind.ParameterInitializer, Type: null) (Syntax: '= 124')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 124) (Syntax: '124')
");
model.VerifyOperationTree(baseWithargs.Parent,
@"
IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'C(int X, in ... is(X, Y) {}')
Initializer:
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': this(X, Y)')
Expression:
IInvocationOperation ( C..ctor(System.Int32 X, [System.Int32 Y = 123])) (OperationKind.Invocation, Type: System.Void) (Syntax: ': this(X, Y)')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: ': this(X, Y)')
Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: X) (OperationKind.Argument, Type: null) (Syntax: 'X')
IParameterReferenceOperation: X (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'X')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: Y) (OperationKind.Argument, Type: null) (Syntax: 'Y')
IParameterReferenceOperation: Y (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'Y')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
BlockBody:
IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{}')
ExpressionBody:
null
");
}
}
}
}
...
@@ -15082,6 +15221,13 @@ public Base(int X, int Y)
...
@@ -15082,6 +15221,13 @@ public Base(int X, int Y)
Assert.Same("<global namespace>", model.GetEnclosingSymbol(x.SpanStart).ToTestDisplayString());
Assert.Same("<global namespace>", model.GetEnclosingSymbol(x.SpanStart).ToTestDisplayString());
Assert.Empty(model.LookupSymbols(x.SpanStart, name: "X"));
Assert.Empty(model.LookupSymbols(x.SpanStart, name: "X"));
Assert.DoesNotContain("X", model.LookupNames(x.SpanStart));
Assert.DoesNotContain("X", model.LookupNames(x.SpanStart));
var recordDeclarations = tree.GetRoot().DescendantNodes().OfType<RecordDeclarationSyntax>().Skip(1).ToArray();
Assert.Equal("C", recordDeclarations[0].Identifier.ValueText);
Assert.Null(model.GetOperation(recordDeclarations[0]));
Assert.Equal("C", recordDeclarations[1].Identifier.ValueText);
Assert.Null(model.GetOperation(recordDeclarations[1]));
}
}
[Fact]
[Fact]
...
@@ -15136,6 +15282,14 @@ public Base(int X, int Y)
...
@@ -15136,6 +15282,14 @@ public Base(int X, int Y)
Assert.Empty(model.LookupSymbols(x.SpanStart, name: "X"));
Assert.Empty(model.LookupSymbols(x.SpanStart, name: "X"));
Assert.DoesNotContain("X", model.LookupNames(x.SpanStart));
Assert.DoesNotContain("X", model.LookupNames(x.SpanStart));
}
}
var recordDeclarations = tree.GetRoot().DescendantNodes().OfType<RecordDeclarationSyntax>().Skip(1).ToArray();
Assert.Equal("C", recordDeclarations[0].Identifier.ValueText);
Assert.Null(model.GetOperation(recordDeclarations[0]));
Assert.Equal("C", recordDeclarations[1].Identifier.ValueText);
Assert.Null(model.GetOperation(recordDeclarations[1]));
}
}
[Fact]
[Fact]
...
@@ -15196,6 +15350,35 @@ public Base(int X, int Y)
...
@@ -15196,6 +15350,35 @@ public Base(int X, int Y)
Assert.Same("<global namespace>", model.GetEnclosingSymbol(x.SpanStart).ToTestDisplayString());
Assert.Same("<global namespace>", model.GetEnclosingSymbol(x.SpanStart).ToTestDisplayString());
Assert.Empty(model.LookupSymbols(x.SpanStart, name: "X"));
Assert.Empty(model.LookupSymbols(x.SpanStart, name: "X"));
Assert.DoesNotContain("X", model.LookupNames(x.SpanStart));
Assert.DoesNotContain("X", model.LookupNames(x.SpanStart));
var recordDeclarations = tree.GetRoot().DescendantNodes().OfType<RecordDeclarationSyntax>().Skip(1).ToArray();
Assert.Equal("C", recordDeclarations[0].Identifier.ValueText);
model.VerifyOperationTree(recordDeclarations[0],
@"
IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'partial rec ... }')
Initializer:
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'Base(X, Y)')
Expression:
IInvocationOperation ( Base..ctor(System.Int32 X, System.Int32 Y)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Base(X, Y)')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Base, IsImplicit) (Syntax: 'Base(X, Y)')
Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: X) (OperationKind.Argument, Type: null) (Syntax: 'X')
IParameterReferenceOperation: X (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'X')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: Y) (OperationKind.Argument, Type: null) (Syntax: 'Y')
IParameterReferenceOperation: Y (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'Y')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
BlockBody:
IBlockOperation (0 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'partial rec ... }')
ExpressionBody:
null
");
Assert.Equal("C", recordDeclarations[1].Identifier.ValueText);
Assert.Null(model.GetOperation(recordDeclarations[1]));
}
}
[Fact]
[Fact]
...
@@ -15256,6 +15439,36 @@ public Base(int X, int Y)
...
@@ -15256,6 +15439,36 @@ public Base(int X, int Y)
Assert.Same("<global namespace>", model.GetEnclosingSymbol(x.SpanStart).ToTestDisplayString());
Assert.Same("<global namespace>", model.GetEnclosingSymbol(x.SpanStart).ToTestDisplayString());
Assert.Empty(model.LookupSymbols(x.SpanStart, name: "X"));
Assert.Empty(model.LookupSymbols(x.SpanStart, name: "X"));
Assert.DoesNotContain("X", model.LookupNames(x.SpanStart));
Assert.DoesNotContain("X", model.LookupNames(x.SpanStart));
var recordDeclarations = tree.GetRoot().DescendantNodes().OfType<RecordDeclarationSyntax>().Skip(1).ToArray();
Assert.Equal("C", recordDeclarations[0].Identifier.ValueText);
Assert.Null(model.GetOperation(recordDeclarations[0]));
Assert.Equal("C", recordDeclarations[1].Identifier.ValueText);
model.VerifyOperationTree(recordDeclarations[1],
@"
IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'partial rec ... }')
Initializer:
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'Base(X, Y)')
Expression:
IInvocationOperation ( Base..ctor(System.Int32 X, System.Int32 Y)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Base(X, Y)')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Base, IsImplicit) (Syntax: 'Base(X, Y)')
Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: X) (OperationKind.Argument, Type: null) (Syntax: 'X')
IParameterReferenceOperation: X (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'X')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: Y) (OperationKind.Argument, Type: null) (Syntax: 'Y')
IParameterReferenceOperation: Y (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'Y')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
BlockBody:
IBlockOperation (0 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'partial rec ... }')
ExpressionBody:
null
");
}
}
[Fact]
[Fact]
...
@@ -16395,6 +16608,13 @@ static void Main()
...
@@ -16395,6 +16608,13 @@ static void Main()
}
}
}";
}";
var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.RegularPreview, options: TestOptions.ReleaseExe);
var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.RegularPreview, options: TestOptions.ReleaseExe);
var tree = comp.SyntaxTrees.First();
var model = comp.GetSemanticModel(tree);
var recordDeclaration = tree.GetRoot().DescendantNodes().OfType<RecordDeclarationSyntax>().First();
Assert.Null(model.GetOperation(recordDeclaration));
var verifier = CompileAndVerify(comp, expectedOutput:
var verifier = CompileAndVerify(comp, expectedOutput:
@"True
@"True
True
True
...
@@ -16792,6 +17012,14 @@ static void Main()
...
@@ -16792,6 +17012,14 @@ static void Main()
}
}
}";
}";
var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.RegularPreview, options: TestOptions.ReleaseExe);
var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.RegularPreview, options: TestOptions.ReleaseExe);
var tree = comp.SyntaxTrees.First();
var model = comp.GetSemanticModel(tree);
var recordDeclaration = tree.GetRoot().DescendantNodes().OfType<RecordDeclarationSyntax>().ElementAt(1);
Assert.Equal("B", recordDeclaration.Identifier.ValueText);
Assert.Null(model.GetOperation(recordDeclaration));
var verifier = CompileAndVerify(comp, expectedOutput:
var verifier = CompileAndVerify(comp, expectedOutput:
@"True
@"True
False
False
...
@@ -17926,6 +18154,10 @@ public static void Main()
...
@@ -17926,6 +18154,10 @@ public static void Main()
Assert.Equal("System.Int32 C.Z", model.GetEnclosingSymbol(x.SpanStart).ToTestDisplayString());
Assert.Equal("System.Int32 C.Z", model.GetEnclosingSymbol(x.SpanStart).ToTestDisplayString());
Assert.Contains(symbol, model.LookupSymbols(x.SpanStart, name: "X"));
Assert.Contains(symbol, model.LookupSymbols(x.SpanStart, name: "X"));
Assert.Contains("X", model.LookupNames(x.SpanStart));
Assert.Contains("X", model.LookupNames(x.SpanStart));
var recordDeclaration = tree.GetRoot().DescendantNodes().OfType<RecordDeclarationSyntax>().Single();
Assert.Equal("C", recordDeclaration.Identifier.ValueText);
Assert.Null(model.GetOperation(recordDeclaration));
}
}
[Fact]
[Fact]
...
@@ -18887,5 +19119,1601 @@ public static void Main()
...
@@ -18887,5 +19119,1601 @@ public static void Main()
Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("R2<T>", "T", "int").WithLocation(10, 20)
Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("R2<T>", "T", "int").WithLocation(10, 20)
);
);
}
}
[Fact]
public void AnalyzerActions_01()
{
var text1 = @"
record A([Attr1]int X = 0) : I1
{}
record B([Attr2]int Y = 1) : A(2), I1
{
int M() => 3;
}
record C : A, I1
{
C([Attr3]int Z = 4) : base(5)
{}
}
interface I1 {}
class Attr1 : System.Attribute {}
class Attr2 : System.Attribute {}
class Attr3 : System.Attribute {}
";
var analyzer = new AnalyzerActions_01_Analyzer();
var comp = CreateCompilation(text1);
comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify();
Assert.Equal(1, analyzer.FireCount0);
Assert.Equal(1, analyzer.FireCount1);
Assert.Equal(1, analyzer.FireCount2);
Assert.Equal(1, analyzer.FireCount3);
Assert.Equal(1, analyzer.FireCount4);
Assert.Equal(1, analyzer.FireCount5);
Assert.Equal(1, analyzer.FireCount6);
Assert.Equal(1, analyzer.FireCount7);
Assert.Equal(1, analyzer.FireCount8);
Assert.Equal(1, analyzer.FireCount9);
Assert.Equal(1, analyzer.FireCount10);
Assert.Equal(1, analyzer.FireCount11);
Assert.Equal(1, analyzer.FireCount12);
Assert.Equal(1, analyzer.FireCount13);
Assert.Equal(1, analyzer.FireCount14);
Assert.Equal(1, analyzer.FireCount15);
Assert.Equal(1, analyzer.FireCount16);
Assert.Equal(1, analyzer.FireCount17);
Assert.Equal(1, analyzer.FireCount18);
Assert.Equal(1, analyzer.FireCount19);
Assert.Equal(1, analyzer.FireCount20);
Assert.Equal(1, analyzer.FireCount21);
Assert.Equal(1, analyzer.FireCount22);
Assert.Equal(1, analyzer.FireCount23);
Assert.Equal(1, analyzer.FireCount24);
Assert.Equal(1, analyzer.FireCount25);
Assert.Equal(1, analyzer.FireCount26);
Assert.Equal(1, analyzer.FireCount27);
Assert.Equal(1, analyzer.FireCount28);
Assert.Equal(1, analyzer.FireCount29);
Assert.Equal(1, analyzer.FireCount30);
Assert.Equal(1, analyzer.FireCount31);
}
private class AnalyzerActions_01_Analyzer : DiagnosticAnalyzer
{
public int FireCount0;
public int FireCount1;
public int FireCount2;
public int FireCount3;
public int FireCount4;
public int FireCount5;
public int FireCount6;
public int FireCount7;
public int FireCount8;
public int FireCount9;
public int FireCount10;
public int FireCount11;
public int FireCount12;
public int FireCount13;
public int FireCount14;
public int FireCount15;
public int FireCount16;
public int FireCount17;
public int FireCount18;
public int FireCount19;
public int FireCount20;
public int FireCount21;
public int FireCount22;
public int FireCount23;
public int FireCount24;
public int FireCount25;
public int FireCount26;
public int FireCount27;
public int FireCount28;
public int FireCount29;
public int FireCount30;
public int FireCount31;
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(Handle1, SyntaxKind.NumericLiteralExpression);
context.RegisterSyntaxNodeAction(Handle2, SyntaxKind.EqualsValueClause);
context.RegisterSyntaxNodeAction(Handle3, SyntaxKind.BaseConstructorInitializer);
context.RegisterSyntaxNodeAction(Handle4, SyntaxKind.ConstructorDeclaration);
context.RegisterSyntaxNodeAction(Handle5, SyntaxKind.PrimaryConstructorBaseType);
context.RegisterSyntaxNodeAction(Handle6, SyntaxKind.RecordDeclaration);
context.RegisterSyntaxNodeAction(Handle7, SyntaxKind.IdentifierName);
context.RegisterSyntaxNodeAction(Handle8, SyntaxKind.SimpleBaseType);
context.RegisterSyntaxNodeAction(Handle9, SyntaxKind.ParameterList);
context.RegisterSyntaxNodeAction(Handle10, SyntaxKind.ArgumentList);
}
protected void Handle1(SyntaxNodeAnalysisContext context)
{
var literal = (LiteralExpressionSyntax)context.Node;
switch (literal.ToString())
{
case "0":
Interlocked.Increment(ref FireCount0);
Assert.Equal("A..ctor([System.Int32 X = 0])", context.ContainingSymbol.ToTestDisplayString());
break;
case "1":
Interlocked.Increment(ref FireCount1);
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
break;
case "2":
Interlocked.Increment(ref FireCount2);
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
break;
case "3":
Interlocked.Increment(ref FireCount3);
Assert.Equal("System.Int32 B.M()", context.ContainingSymbol.ToTestDisplayString());
break;
case "4":
Interlocked.Increment(ref FireCount4);
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
break;
case "5":
Interlocked.Increment(ref FireCount5);
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
break;
default:
Assert.True(false);
break;
}
Assert.Same(literal.SyntaxTree, context.ContainingSymbol!.DeclaringSyntaxReferences.Single().SyntaxTree);
}
protected void Handle2(SyntaxNodeAnalysisContext context)
{
var equalsValue = (EqualsValueClauseSyntax)context.Node;
switch (equalsValue.ToString())
{
case "= 0":
Interlocked.Increment(ref FireCount15);
Assert.Equal("A..ctor([System.Int32 X = 0])", context.ContainingSymbol.ToTestDisplayString());
break;
case "= 1":
Interlocked.Increment(ref FireCount16);
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
break;
case "= 4":
Interlocked.Increment(ref FireCount6);
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
break;
default:
Assert.True(false);
break;
}
Assert.Same(equalsValue.SyntaxTree, context.ContainingSymbol!.DeclaringSyntaxReferences.Single().SyntaxTree);
}
protected void Handle3(SyntaxNodeAnalysisContext context)
{
var initializer = (ConstructorInitializerSyntax)context.Node;
switch (initializer.ToString())
{
case ": base(5)":
Interlocked.Increment(ref FireCount7);
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
break;
default:
Assert.True(false);
break;
}
Assert.Same(initializer.SyntaxTree, context.ContainingSymbol!.DeclaringSyntaxReferences.Single().SyntaxTree);
}
protected void Handle4(SyntaxNodeAnalysisContext context)
{
Interlocked.Increment(ref FireCount8);
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
}
protected void Handle5(SyntaxNodeAnalysisContext context)
{
var baseType = (PrimaryConstructorBaseTypeSyntax)context.Node;
switch (baseType.ToString())
{
case "A(2)":
switch (context.ContainingSymbol.ToTestDisplayString())
{
case "B..ctor([System.Int32 Y = 1])":
Interlocked.Increment(ref FireCount9);
break;
case "B":
Interlocked.Increment(ref FireCount17);
break;
default:
Assert.True(false);
break;
}
break;
default:
Assert.True(false);
break;
}
Assert.Same(baseType.SyntaxTree, context.ContainingSymbol!.DeclaringSyntaxReferences.Single().SyntaxTree);
}
protected void Handle6(SyntaxNodeAnalysisContext context)
{
var record = (RecordDeclarationSyntax)context.Node;
switch (context.ContainingSymbol.ToTestDisplayString())
{
case "B..ctor([System.Int32 Y = 1])":
Interlocked.Increment(ref FireCount10);
break;
case "B":
Interlocked.Increment(ref FireCount11);
break;
case "A":
Interlocked.Increment(ref FireCount12);
break;
case "C":
Interlocked.Increment(ref FireCount13);
break;
case "A..ctor([System.Int32 X = 0])":
Interlocked.Increment(ref FireCount14);
break;
default:
Assert.True(false);
break;
}
Assert.Same(record.SyntaxTree, context.ContainingSymbol!.DeclaringSyntaxReferences.Single().SyntaxTree);
}
protected void Handle7(SyntaxNodeAnalysisContext context)
{
var identifier = (IdentifierNameSyntax)context.Node;
switch (identifier.Identifier.ValueText)
{
case "A":
switch (identifier.Parent!.ToString())
{
case "A(2)":
Interlocked.Increment(ref FireCount18);
Assert.Equal("B", context.ContainingSymbol.ToTestDisplayString());
break;
case "A":
Interlocked.Increment(ref FireCount19);
Assert.Equal(SyntaxKind.SimpleBaseType, identifier.Parent.Kind());
Assert.Equal("C", context.ContainingSymbol.ToTestDisplayString());
break;
default:
Assert.True(false);
break;
}
break;
case "Attr1":
Interlocked.Increment(ref FireCount24);
Assert.Equal("A..ctor([System.Int32 X = 0])", context.ContainingSymbol.ToTestDisplayString());
break;
case "Attr2":
Interlocked.Increment(ref FireCount25);
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
break;
case "Attr3":
Interlocked.Increment(ref FireCount26);
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
break;
}
}
protected void Handle8(SyntaxNodeAnalysisContext context)
{
var baseType = (SimpleBaseTypeSyntax)context.Node;
switch (baseType.ToString())
{
case "I1":
switch (context.ContainingSymbol.ToTestDisplayString())
{
case "A":
Interlocked.Increment(ref FireCount20);
break;
case "B":
Interlocked.Increment(ref FireCount21);
break;
case "C":
Interlocked.Increment(ref FireCount22);
break;
default:
Assert.True(false);
break;
}
break;
case "A":
switch (context.ContainingSymbol.ToTestDisplayString())
{
case "C":
Interlocked.Increment(ref FireCount23);
break;
default:
Assert.True(false);
break;
}
break;
case "System.Attribute":
break;
default:
Assert.True(false);
break;
}
}
protected void Handle9(SyntaxNodeAnalysisContext context)
{
var parameterList = (ParameterListSyntax)context.Node;
switch (parameterList.ToString())
{
case "([Attr1]int X = 0)":
Interlocked.Increment(ref FireCount27);
Assert.Equal("A..ctor([System.Int32 X = 0])", context.ContainingSymbol.ToTestDisplayString());
break;
case "([Attr2]int Y = 1)":
Interlocked.Increment(ref FireCount28);
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
break;
case "([Attr3]int Z = 4)":
Interlocked.Increment(ref FireCount29);
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
break;
case "()":
break;
default:
Assert.True(false);
break;
}
}
protected void Handle10(SyntaxNodeAnalysisContext context)
{
var argumentList = (ArgumentListSyntax)context.Node;
switch (argumentList.ToString())
{
case "(2)":
Interlocked.Increment(ref FireCount30);
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
break;
case "(5)":
Interlocked.Increment(ref FireCount31);
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
break;
default:
Assert.True(false);
break;
}
}
}
[Fact]
public void AnalyzerActions_02()
{
var text1 = @"
record A(int X = 0)
{}
record C
{
C(int Z = 4)
{}
}
";
var analyzer = new AnalyzerActions_02_Analyzer();
var comp = CreateCompilation(text1);
comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify();
Assert.Equal(1, analyzer.FireCount1);
Assert.Equal(1, analyzer.FireCount2);
Assert.Equal(1, analyzer.FireCount3);
Assert.Equal(1, analyzer.FireCount4);
Assert.Equal(1, analyzer.FireCount5);
Assert.Equal(1, analyzer.FireCount6);
Assert.Equal(1, analyzer.FireCount7);
}
private class AnalyzerActions_02_Analyzer : DiagnosticAnalyzer
{
public int FireCount1;
public int FireCount2;
public int FireCount3;
public int FireCount4;
public int FireCount5;
public int FireCount6;
public int FireCount7;
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSymbolAction(Handle, SymbolKind.Method);
context.RegisterSymbolAction(Handle, SymbolKind.Property);
context.RegisterSymbolAction(Handle, SymbolKind.Parameter);
context.RegisterSymbolAction(Handle, SymbolKind.NamedType);
}
private void Handle(SymbolAnalysisContext context)
{
switch (context.Symbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
Interlocked.Increment(ref FireCount1);
break;
case "System.Int32 A.X { get; init; }":
Interlocked.Increment(ref FireCount2);
break;
case "[System.Int32 X = 0]":
Interlocked.Increment(ref FireCount3);
break;
case "C..ctor([System.Int32 Z = 4])":
Interlocked.Increment(ref FireCount4);
break;
case "[System.Int32 Z = 4]":
Interlocked.Increment(ref FireCount5);
break;
case "A":
Interlocked.Increment(ref FireCount6);
break;
case "C":
Interlocked.Increment(ref FireCount7);
break;
case "System.Runtime.CompilerServices.IsExternalInit":
break;
default:
Assert.True(false);
break;
}
}
}
[Fact]
public void AnalyzerActions_03()
{
var text1 = @"
record A(int X = 0)
{}
record C
{
C(int Z = 4)
{}
}
";
var analyzer = new AnalyzerActions_03_Analyzer();
var comp = CreateCompilation(text1);
comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify();
Assert.Equal(1, analyzer.FireCount1);
Assert.Equal(1, analyzer.FireCount2);
Assert.Equal(0, analyzer.FireCount3);
Assert.Equal(1, analyzer.FireCount4);
Assert.Equal(0, analyzer.FireCount5);
Assert.Equal(1, analyzer.FireCount6);
Assert.Equal(1, analyzer.FireCount7);
Assert.Equal(1, analyzer.FireCount8);
Assert.Equal(1, analyzer.FireCount9);
Assert.Equal(1, analyzer.FireCount10);
Assert.Equal(1, analyzer.FireCount11);
Assert.Equal(1, analyzer.FireCount12);
}
private class AnalyzerActions_03_Analyzer : DiagnosticAnalyzer
{
public int FireCount1;
public int FireCount2;
public int FireCount3;
public int FireCount4;
public int FireCount5;
public int FireCount6;
public int FireCount7;
public int FireCount8;
public int FireCount9;
public int FireCount10;
public int FireCount11;
public int FireCount12;
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSymbolStartAction(Handle1, SymbolKind.Method);
context.RegisterSymbolStartAction(Handle1, SymbolKind.Property);
context.RegisterSymbolStartAction(Handle1, SymbolKind.Parameter);
context.RegisterSymbolStartAction(Handle1, SymbolKind.NamedType);
}
private void Handle1(SymbolStartAnalysisContext context)
{
switch (context.Symbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
Interlocked.Increment(ref FireCount1);
context.RegisterSymbolEndAction(Handle2);
break;
case "System.Int32 A.X { get; init; }":
Interlocked.Increment(ref FireCount2);
context.RegisterSymbolEndAction(Handle3);
break;
case "[System.Int32 X = 0]":
Interlocked.Increment(ref FireCount3);
break;
case "C..ctor([System.Int32 Z = 4])":
Interlocked.Increment(ref FireCount4);
context.RegisterSymbolEndAction(Handle4);
break;
case "[System.Int32 Z = 4]":
Interlocked.Increment(ref FireCount5);
break;
case "A":
Interlocked.Increment(ref FireCount9);
Assert.Equal(0, FireCount1);
Assert.Equal(0, FireCount2);
Assert.Equal(0, FireCount6);
Assert.Equal(0, FireCount7);
context.RegisterSymbolEndAction(Handle5);
break;
case "C":
Interlocked.Increment(ref FireCount10);
Assert.Equal(0, FireCount4);
Assert.Equal(0, FireCount8);
context.RegisterSymbolEndAction(Handle6);
break;
case "System.Runtime.CompilerServices.IsExternalInit":
break;
default:
Assert.True(false);
break;
}
}
private void Handle2(SymbolAnalysisContext context)
{
Assert.Equal("A..ctor([System.Int32 X = 0])", context.Symbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount6);
}
private void Handle3(SymbolAnalysisContext context)
{
Assert.Equal("System.Int32 A.X { get; init; }", context.Symbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount7);
}
private void Handle4(SymbolAnalysisContext context)
{
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.Symbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount8);
}
private void Handle5(SymbolAnalysisContext context)
{
Assert.Equal("A", context.Symbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount11);
Assert.Equal(1, FireCount1);
Assert.Equal(1, FireCount2);
Assert.Equal(1, FireCount6);
Assert.Equal(1, FireCount7);
}
private void Handle6(SymbolAnalysisContext context)
{
Assert.Equal("C", context.Symbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount12);
Assert.Equal(1, FireCount4);
Assert.Equal(1, FireCount8);
}
}
[Fact]
public void AnalyzerActions_04()
{
var text1 = @"
record A([Attr1(100)]int X = 0) : I1
{}
record B([Attr2(200)]int Y = 1) : A(2), I1
{
int M() => 3;
}
record C : A, I1
{
C([Attr3(300)]int Z = 4) : base(5)
{}
}
interface I1 {}
";
var analyzer = new AnalyzerActions_04_Analyzer();
var comp = CreateCompilation(text1);
comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify();
Assert.Equal(0, analyzer.FireCount1);
Assert.Equal(1, analyzer.FireCount2);
Assert.Equal(1, analyzer.FireCount3);
Assert.Equal(1, analyzer.FireCount4);
Assert.Equal(1, analyzer.FireCount5);
Assert.Equal(1, analyzer.FireCount6);
Assert.Equal(1, analyzer.FireCount7);
Assert.Equal(1, analyzer.FireCount8);
Assert.Equal(1, analyzer.FireCount9);
Assert.Equal(1, analyzer.FireCount10);
Assert.Equal(1, analyzer.FireCount11);
Assert.Equal(1, analyzer.FireCount12);
Assert.Equal(1, analyzer.FireCount13);
Assert.Equal(1, analyzer.FireCount14);
Assert.Equal(1, analyzer.FireCount15);
Assert.Equal(1, analyzer.FireCount16);
Assert.Equal(1, analyzer.FireCount17);
}
private class AnalyzerActions_04_Analyzer : DiagnosticAnalyzer
{
public int FireCount1;
public int FireCount2;
public int FireCount3;
public int FireCount4;
public int FireCount5;
public int FireCount6;
public int FireCount7;
public int FireCount8;
public int FireCount9;
public int FireCount10;
public int FireCount11;
public int FireCount12;
public int FireCount13;
public int FireCount14;
public int FireCount15;
public int FireCount16;
public int FireCount17;
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterOperationAction(Handle1, OperationKind.ConstructorBody);
context.RegisterOperationAction(Handle2, OperationKind.Invocation);
context.RegisterOperationAction(Handle3, OperationKind.Literal);
context.RegisterOperationAction(Handle4, OperationKind.ParameterInitializer);
context.RegisterOperationAction(Handle5, OperationKind.PropertyInitializer);
context.RegisterOperationAction(Handle5, OperationKind.FieldInitializer);
}
protected void Handle1(OperationAnalysisContext context)
{
switch (context.ContainingSymbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
Interlocked.Increment(ref FireCount1);
Assert.Equal(SyntaxKind.RecordDeclaration, context.Operation.Syntax.Kind());
break;
case "B..ctor([System.Int32 Y = 1])":
Interlocked.Increment(ref FireCount2);
Assert.Equal(SyntaxKind.RecordDeclaration, context.Operation.Syntax.Kind());
break;
case "C..ctor([System.Int32 Z = 4])":
Interlocked.Increment(ref FireCount3);
Assert.Equal(SyntaxKind.ConstructorDeclaration, context.Operation.Syntax.Kind());
break;
default:
Assert.True(false);
break;
}
}
protected void Handle2(OperationAnalysisContext context)
{
switch (context.ContainingSymbol.ToTestDisplayString())
{
case "B..ctor([System.Int32 Y = 1])":
Interlocked.Increment(ref FireCount4);
Assert.Equal(SyntaxKind.PrimaryConstructorBaseType, context.Operation.Syntax.Kind());
VerifyOperationTree((CSharpCompilation)context.Compilation, context.Operation,
@"
IInvocationOperation ( A..ctor([System.Int32 X = 0])) (OperationKind.Invocation, Type: System.Void) (Syntax: 'A(2)')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: A, IsImplicit) (Syntax: 'A(2)')
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: X) (OperationKind.Argument, Type: null) (Syntax: '2')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
");
break;
case "C..ctor([System.Int32 Z = 4])":
Interlocked.Increment(ref FireCount5);
Assert.Equal(SyntaxKind.BaseConstructorInitializer, context.Operation.Syntax.Kind());
VerifyOperationTree((CSharpCompilation)context.Compilation, context.Operation,
@"
IInvocationOperation ( A..ctor([System.Int32 X = 0])) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(5)')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: A, IsImplicit) (Syntax: ': base(5)')
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: X) (OperationKind.Argument, Type: null) (Syntax: '5')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 5) (Syntax: '5')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
");
break;
default:
Assert.True(false);
break;
}
}
protected void Handle3(OperationAnalysisContext context)
{
switch (context.Operation.Syntax.ToString())
{
case "100":
Assert.Equal("A..ctor([System.Int32 X = 0])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount6);
break;
case "0":
Assert.Equal("A..ctor([System.Int32 X = 0])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount7);
break;
case "200":
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount8);
break;
case "1":
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount9);
break;
case "2":
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount10);
break;
case "300":
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount11);
break;
case "4":
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount12);
break;
case "5":
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount13);
break;
case "3":
Assert.Equal("System.Int32 B.M()", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount17);
break;
default:
Assert.True(false);
break;
}
}
protected void Handle4(OperationAnalysisContext context)
{
switch (context.Operation.Syntax.ToString())
{
case "= 0":
Assert.Equal("A..ctor([System.Int32 X = 0])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount14);
break;
case "= 1":
Assert.Equal("B..ctor([System.Int32 Y = 1])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount15);
break;
case "= 4":
Assert.Equal("C..ctor([System.Int32 Z = 4])", context.ContainingSymbol.ToTestDisplayString());
Interlocked.Increment(ref FireCount16);
break;
default:
Assert.True(false);
break;
}
}
protected void Handle5(OperationAnalysisContext context)
{
Assert.True(false);
}
}
[Fact]
public void AnalyzerActions_05()
{
var text1 = @"
record A([Attr1(100)]int X = 0) : I1
{}
record B([Attr2(200)]int Y = 1) : A(2), I1
{
int M() => 3;
}
record C : A, I1
{
C([Attr3(300)]int Z = 4) : base(5)
{}
}
interface I1 {}
";
var analyzer = new AnalyzerActions_05_Analyzer();
var comp = CreateCompilation(text1);
comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify();
Assert.Equal(1, analyzer.FireCount1);
Assert.Equal(1, analyzer.FireCount2);
Assert.Equal(1, analyzer.FireCount3);
Assert.Equal(1, analyzer.FireCount4);
}
private class AnalyzerActions_05_Analyzer : DiagnosticAnalyzer
{
public int FireCount1;
public int FireCount2;
public int FireCount3;
public int FireCount4;
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterOperationBlockAction(Handle);
}
private void Handle(OperationBlockAnalysisContext context)
{
switch (context.OwningSymbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
Interlocked.Increment(ref FireCount1);
Assert.Equal(2, context.OperationBlocks.Length);
Assert.Equal(OperationKind.ParameterInitializer, context.OperationBlocks[0].Kind);
Assert.Equal("= 0", context.OperationBlocks[0].Syntax.ToString());
Assert.Equal(OperationKind.None, context.OperationBlocks[1].Kind);
Assert.Equal("Attr1(100)", context.OperationBlocks[1].Syntax.ToString());
break;
case "B..ctor([System.Int32 Y = 1])":
Interlocked.Increment(ref FireCount2);
Assert.Equal(3, context.OperationBlocks.Length);
Assert.Equal(OperationKind.ParameterInitializer, context.OperationBlocks[0].Kind);
Assert.Equal("= 1", context.OperationBlocks[0].Syntax.ToString());
Assert.Equal(OperationKind.None, context.OperationBlocks[1].Kind);
Assert.Equal("Attr2(200)", context.OperationBlocks[1].Syntax.ToString());
Assert.Equal(OperationKind.Invocation, context.OperationBlocks[2].Kind);
Assert.Equal("A(2)", context.OperationBlocks[2].Syntax.ToString());
break;
case "C..ctor([System.Int32 Z = 4])":
Interlocked.Increment(ref FireCount3);
Assert.Equal(4, context.OperationBlocks.Length);
Assert.Equal(OperationKind.ParameterInitializer, context.OperationBlocks[0].Kind);
Assert.Equal("= 4", context.OperationBlocks[0].Syntax.ToString());
Assert.Equal(OperationKind.None, context.OperationBlocks[1].Kind);
Assert.Equal("Attr3(300)", context.OperationBlocks[1].Syntax.ToString());
Assert.Equal(OperationKind.Block, context.OperationBlocks[2].Kind);
Assert.Equal(OperationKind.Invocation, context.OperationBlocks[3].Kind);
Assert.Equal(": base(5)", context.OperationBlocks[3].Syntax.ToString());
break;
case "System.Int32 B.M()":
Interlocked.Increment(ref FireCount4);
Assert.Equal(1, context.OperationBlocks.Length);
Assert.Equal(OperationKind.Block, context.OperationBlocks[0].Kind);
break;
default:
Assert.True(false);
break;
}
}
}
[Fact]
public void AnalyzerActions_06()
{
var text1 = @"
record A([Attr1(100)]int X = 0) : I1
{}
record B([Attr2(200)]int Y = 1) : A(2), I1
{
int M() => 3;
}
record C : A, I1
{
C([Attr3(300)]int Z = 4) : base(5)
{}
}
interface I1 {}
";
var analyzer = new AnalyzerActions_06_Analyzer();
var comp = CreateCompilation(text1);
comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify();
Assert.Equal(1, analyzer.FireCount100);
Assert.Equal(1, analyzer.FireCount200);
Assert.Equal(1, analyzer.FireCount300);
Assert.Equal(1, analyzer.FireCount400);
Assert.Equal(0, analyzer.FireCount1);
Assert.Equal(1, analyzer.FireCount2);
Assert.Equal(1, analyzer.FireCount3);
Assert.Equal(1, analyzer.FireCount4);
Assert.Equal(1, analyzer.FireCount5);
Assert.Equal(1, analyzer.FireCount6);
Assert.Equal(1, analyzer.FireCount7);
Assert.Equal(1, analyzer.FireCount8);
Assert.Equal(1, analyzer.FireCount9);
Assert.Equal(1, analyzer.FireCount10);
Assert.Equal(1, analyzer.FireCount11);
Assert.Equal(1, analyzer.FireCount12);
Assert.Equal(1, analyzer.FireCount13);
Assert.Equal(1, analyzer.FireCount14);
Assert.Equal(1, analyzer.FireCount15);
Assert.Equal(1, analyzer.FireCount16);
Assert.Equal(1, analyzer.FireCount17);
Assert.Equal(1, analyzer.FireCount1000);
Assert.Equal(1, analyzer.FireCount2000);
Assert.Equal(1, analyzer.FireCount3000);
Assert.Equal(1, analyzer.FireCount4000);
}
private class AnalyzerActions_06_Analyzer : AnalyzerActions_04_Analyzer
{
public int FireCount100;
public int FireCount200;
public int FireCount300;
public int FireCount400;
public int FireCount1000;
public int FireCount2000;
public int FireCount3000;
public int FireCount4000;
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterOperationBlockStartAction(Handle);
}
private void Handle(OperationBlockStartAnalysisContext context)
{
switch (context.OwningSymbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
Interlocked.Increment(ref FireCount100);
Assert.Equal(2, context.OperationBlocks.Length);
Assert.Equal(OperationKind.ParameterInitializer, context.OperationBlocks[0].Kind);
Assert.Equal("= 0", context.OperationBlocks[0].Syntax.ToString());
Assert.Equal(OperationKind.None, context.OperationBlocks[1].Kind);
Assert.Equal("Attr1(100)", context.OperationBlocks[1].Syntax.ToString());
RegisterOperationAction(context);
context.RegisterOperationBlockEndAction(Handle6);
break;
case "B..ctor([System.Int32 Y = 1])":
Interlocked.Increment(ref FireCount200);
Assert.Equal(3, context.OperationBlocks.Length);
Assert.Equal(OperationKind.ParameterInitializer, context.OperationBlocks[0].Kind);
Assert.Equal("= 1", context.OperationBlocks[0].Syntax.ToString());
Assert.Equal(OperationKind.None, context.OperationBlocks[1].Kind);
Assert.Equal("Attr2(200)", context.OperationBlocks[1].Syntax.ToString());
Assert.Equal(OperationKind.Invocation, context.OperationBlocks[2].Kind);
Assert.Equal("A(2)", context.OperationBlocks[2].Syntax.ToString());
RegisterOperationAction(context);
context.RegisterOperationBlockEndAction(Handle6);
break;
case "C..ctor([System.Int32 Z = 4])":
Interlocked.Increment(ref FireCount300);
Assert.Equal(4, context.OperationBlocks.Length);
Assert.Equal(OperationKind.ParameterInitializer, context.OperationBlocks[0].Kind);
Assert.Equal("= 4", context.OperationBlocks[0].Syntax.ToString());
Assert.Equal(OperationKind.None, context.OperationBlocks[1].Kind);
Assert.Equal("Attr3(300)", context.OperationBlocks[1].Syntax.ToString());
Assert.Equal(OperationKind.Block, context.OperationBlocks[2].Kind);
Assert.Equal(OperationKind.Invocation, context.OperationBlocks[3].Kind);
Assert.Equal(": base(5)", context.OperationBlocks[3].Syntax.ToString());
RegisterOperationAction(context);
context.RegisterOperationBlockEndAction(Handle6);
break;
case "System.Int32 B.M()":
Interlocked.Increment(ref FireCount400);
Assert.Equal(1, context.OperationBlocks.Length);
Assert.Equal(OperationKind.Block, context.OperationBlocks[0].Kind);
RegisterOperationAction(context);
context.RegisterOperationBlockEndAction(Handle6);
break;
default:
Assert.True(false);
break;
}
}
private void RegisterOperationAction(OperationBlockStartAnalysisContext context)
{
context.RegisterOperationAction(Handle1, OperationKind.ConstructorBody);
context.RegisterOperationAction(Handle2, OperationKind.Invocation);
context.RegisterOperationAction(Handle3, OperationKind.Literal);
context.RegisterOperationAction(Handle4, OperationKind.ParameterInitializer);
context.RegisterOperationAction(Handle5, OperationKind.PropertyInitializer);
context.RegisterOperationAction(Handle5, OperationKind.FieldInitializer);
}
private void Handle6(OperationBlockAnalysisContext context)
{
switch (context.OwningSymbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
Interlocked.Increment(ref FireCount1000);
Assert.Equal(2, context.OperationBlocks.Length);
Assert.Equal(OperationKind.ParameterInitializer, context.OperationBlocks[0].Kind);
Assert.Equal("= 0", context.OperationBlocks[0].Syntax.ToString());
Assert.Equal(OperationKind.None, context.OperationBlocks[1].Kind);
Assert.Equal("Attr1(100)", context.OperationBlocks[1].Syntax.ToString());
break;
case "B..ctor([System.Int32 Y = 1])":
Interlocked.Increment(ref FireCount2000);
Assert.Equal(3, context.OperationBlocks.Length);
Assert.Equal(OperationKind.ParameterInitializer, context.OperationBlocks[0].Kind);
Assert.Equal("= 1", context.OperationBlocks[0].Syntax.ToString());
Assert.Equal(OperationKind.None, context.OperationBlocks[1].Kind);
Assert.Equal("Attr2(200)", context.OperationBlocks[1].Syntax.ToString());
Assert.Equal(OperationKind.Invocation, context.OperationBlocks[2].Kind);
Assert.Equal("A(2)", context.OperationBlocks[2].Syntax.ToString());
break;
case "C..ctor([System.Int32 Z = 4])":
Interlocked.Increment(ref FireCount3000);
Assert.Equal(4, context.OperationBlocks.Length);
Assert.Equal(OperationKind.ParameterInitializer, context.OperationBlocks[0].Kind);
Assert.Equal("= 4", context.OperationBlocks[0].Syntax.ToString());
Assert.Equal(OperationKind.None, context.OperationBlocks[1].Kind);
Assert.Equal("Attr3(300)", context.OperationBlocks[1].Syntax.ToString());
Assert.Equal(OperationKind.Block, context.OperationBlocks[2].Kind);
Assert.Equal(OperationKind.Invocation, context.OperationBlocks[3].Kind);
Assert.Equal(": base(5)", context.OperationBlocks[3].Syntax.ToString());
break;
case "System.Int32 B.M()":
Interlocked.Increment(ref FireCount4000);
Assert.Equal(1, context.OperationBlocks.Length);
Assert.Equal(OperationKind.Block, context.OperationBlocks[0].Kind);
break;
default:
Assert.True(false);
break;
}
}
}
[Fact]
public void AnalyzerActions_07()
{
var text1 = @"
record A([Attr1(100)]int X = 0) : I1
{}
record B([Attr2(200)]int Y = 1) : A(2), I1
{
int M() => 3;
}
record C : A, I1
{
C([Attr3(300)]int Z = 4) : base(5)
{}
}
interface I1 {}
";
var analyzer = new AnalyzerActions_07_Analyzer();
var comp = CreateCompilation(text1);
comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify();
Assert.Equal(1, analyzer.FireCount1);
Assert.Equal(1, analyzer.FireCount2);
Assert.Equal(1, analyzer.FireCount3);
Assert.Equal(1, analyzer.FireCount4);
}
private class AnalyzerActions_07_Analyzer : DiagnosticAnalyzer
{
public int FireCount1;
public int FireCount2;
public int FireCount3;
public int FireCount4;
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterCodeBlockAction(Handle);
}
private void Handle(CodeBlockAnalysisContext context)
{
switch (context.OwningSymbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
switch (context.CodeBlock)
{
case RecordDeclarationSyntax { Identifier: { ValueText: "A" } }:
Interlocked.Increment(ref FireCount1);
break;
default:
Assert.True(false);
break;
}
break;
case "B..ctor([System.Int32 Y = 1])":
switch (context.CodeBlock)
{
case RecordDeclarationSyntax { Identifier: { ValueText: "B" } }:
Interlocked.Increment(ref FireCount2);
break;
default:
Assert.True(false);
break;
}
break;
case "C..ctor([System.Int32 Z = 4])":
switch (context.CodeBlock)
{
case ConstructorDeclarationSyntax { Identifier: { ValueText: "C" } }:
Interlocked.Increment(ref FireCount3);
break;
default:
Assert.True(false);
break;
}
break;
case "System.Int32 B.M()":
switch (context.CodeBlock)
{
case MethodDeclarationSyntax { Identifier: { ValueText: "M" } }:
Interlocked.Increment(ref FireCount4);
break;
default:
Assert.True(false);
break;
}
break;
default:
Assert.True(false);
break;
}
}
}
[Fact]
public void AnalyzerActions_08()
{
var text1 = @"
record A([Attr1]int X = 0) : I1
{}
record B([Attr2]int Y = 1) : A(2), I1
{
int M() => 3;
}
record C : A, I1
{
C([Attr3]int Z = 4) : base(5)
{}
}
interface I1 {}
";
var analyzer = new AnalyzerActions_08_Analyzer();
var comp = CreateCompilation(text1);
comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify();
Assert.Equal(1, analyzer.FireCount100);
Assert.Equal(1, analyzer.FireCount200);
Assert.Equal(1, analyzer.FireCount300);
Assert.Equal(1, analyzer.FireCount400);
Assert.Equal(1, analyzer.FireCount0);
Assert.Equal(1, analyzer.FireCount1);
Assert.Equal(1, analyzer.FireCount2);
Assert.Equal(1, analyzer.FireCount3);
Assert.Equal(1, analyzer.FireCount4);
Assert.Equal(1, analyzer.FireCount5);
Assert.Equal(1, analyzer.FireCount6);
Assert.Equal(1, analyzer.FireCount7);
Assert.Equal(0, analyzer.FireCount8);
Assert.Equal(1, analyzer.FireCount9);
Assert.Equal(0, analyzer.FireCount10);
Assert.Equal(0, analyzer.FireCount11);
Assert.Equal(0, analyzer.FireCount12);
Assert.Equal(0, analyzer.FireCount13);
Assert.Equal(0, analyzer.FireCount14);
Assert.Equal(1, analyzer.FireCount15);
Assert.Equal(1, analyzer.FireCount16);
Assert.Equal(0, analyzer.FireCount17);
Assert.Equal(0, analyzer.FireCount18);
Assert.Equal(0, analyzer.FireCount19);
Assert.Equal(0, analyzer.FireCount20);
Assert.Equal(0, analyzer.FireCount21);
Assert.Equal(0, analyzer.FireCount22);
Assert.Equal(0, analyzer.FireCount23);
Assert.Equal(1, analyzer.FireCount24);
Assert.Equal(1, analyzer.FireCount25);
Assert.Equal(1, analyzer.FireCount26);
Assert.Equal(0, analyzer.FireCount27);
Assert.Equal(0, analyzer.FireCount28);
Assert.Equal(0, analyzer.FireCount29);
Assert.Equal(1, analyzer.FireCount30);
Assert.Equal(1, analyzer.FireCount31);
Assert.Equal(1, analyzer.FireCount1000);
Assert.Equal(1, analyzer.FireCount2000);
Assert.Equal(1, analyzer.FireCount3000);
Assert.Equal(1, analyzer.FireCount4000);
}
private class AnalyzerActions_08_Analyzer : AnalyzerActions_01_Analyzer
{
public int FireCount100;
public int FireCount200;
public int FireCount300;
public int FireCount400;
public int FireCount1000;
public int FireCount2000;
public int FireCount3000;
public int FireCount4000;
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterCodeBlockStartAction<SyntaxKind>(Handle);
}
private void Handle(CodeBlockStartAnalysisContext<SyntaxKind> context)
{
switch (context.OwningSymbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
switch (context.CodeBlock)
{
case RecordDeclarationSyntax { Identifier: { ValueText: "A" } }:
Interlocked.Increment(ref FireCount100);
break;
default:
Assert.True(false);
break;
}
break;
case "B..ctor([System.Int32 Y = 1])":
switch (context.CodeBlock)
{
case RecordDeclarationSyntax { Identifier: { ValueText: "B" } }:
Interlocked.Increment(ref FireCount200);
break;
default:
Assert.True(false);
break;
}
break;
case "C..ctor([System.Int32 Z = 4])":
switch (context.CodeBlock)
{
case ConstructorDeclarationSyntax { Identifier: { ValueText: "C" } }:
Interlocked.Increment(ref FireCount300);
break;
default:
Assert.True(false);
break;
}
break;
case "System.Int32 B.M()":
switch (context.CodeBlock)
{
case MethodDeclarationSyntax { Identifier: { ValueText: "M" } }:
Interlocked.Increment(ref FireCount400);
break;
default:
Assert.True(false);
break;
}
break;
default:
Assert.True(false);
break;
}
context.RegisterSyntaxNodeAction(Handle1, SyntaxKind.NumericLiteralExpression);
context.RegisterSyntaxNodeAction(Handle2, SyntaxKind.EqualsValueClause);
context.RegisterSyntaxNodeAction(Handle3, SyntaxKind.BaseConstructorInitializer);
context.RegisterSyntaxNodeAction(Handle4, SyntaxKind.ConstructorDeclaration);
context.RegisterSyntaxNodeAction(Handle5, SyntaxKind.PrimaryConstructorBaseType);
context.RegisterSyntaxNodeAction(Handle6, SyntaxKind.RecordDeclaration);
context.RegisterSyntaxNodeAction(Handle7, SyntaxKind.IdentifierName);
context.RegisterSyntaxNodeAction(Handle8, SyntaxKind.SimpleBaseType);
context.RegisterSyntaxNodeAction(Handle9, SyntaxKind.ParameterList);
context.RegisterSyntaxNodeAction(Handle10, SyntaxKind.ArgumentList);
context.RegisterCodeBlockEndAction(Handle11);
}
private void Handle11(CodeBlockAnalysisContext context)
{
switch (context.OwningSymbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
switch (context.CodeBlock)
{
case RecordDeclarationSyntax { Identifier: { ValueText: "A" } }:
Interlocked.Increment(ref FireCount1000);
break;
default:
Assert.True(false);
break;
}
break;
case "B..ctor([System.Int32 Y = 1])":
switch (context.CodeBlock)
{
case RecordDeclarationSyntax { Identifier: { ValueText: "B" } }:
Interlocked.Increment(ref FireCount2000);
break;
default:
Assert.True(false);
break;
}
break;
case "C..ctor([System.Int32 Z = 4])":
switch (context.CodeBlock)
{
case ConstructorDeclarationSyntax { Identifier: { ValueText: "C" } }:
Interlocked.Increment(ref FireCount3000);
break;
default:
Assert.True(false);
break;
}
break;
case "System.Int32 B.M()":
switch (context.CodeBlock)
{
case MethodDeclarationSyntax { Identifier: { ValueText: "M" } }:
Interlocked.Increment(ref FireCount4000);
break;
default:
Assert.True(false);
break;
}
break;
default:
Assert.True(false);
break;
}
}
}
[Fact]
public void AnalyzerActions_09()
{
var text1 = @"
record A([Attr1(100)]int X = 0) : I1
{}
record B([Attr2(200)]int Y = 1) : A(2), I1
{
int M() => 3;
}
record C : A, I1
{
C([Attr3(300)]int Z = 4) : base(5)
{}
}
interface I1 {}
";
var analyzer = new AnalyzerActions_09_Analyzer();
var comp = CreateCompilation(text1);
comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify();
Assert.Equal(1, analyzer.FireCount1);
Assert.Equal(1, analyzer.FireCount2);
Assert.Equal(1, analyzer.FireCount3);
Assert.Equal(1, analyzer.FireCount4);
Assert.Equal(1, analyzer.FireCount5);
Assert.Equal(1, analyzer.FireCount6);
Assert.Equal(1, analyzer.FireCount7);
Assert.Equal(1, analyzer.FireCount8);
Assert.Equal(1, analyzer.FireCount9);
}
private class AnalyzerActions_09_Analyzer : DiagnosticAnalyzer
{
public int FireCount1;
public int FireCount2;
public int FireCount3;
public int FireCount4;
public int FireCount5;
public int FireCount6;
public int FireCount7;
public int FireCount8;
public int FireCount9;
private static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSymbolAction(Handle1, SymbolKind.Method);
context.RegisterSymbolAction(Handle2, SymbolKind.Property);
context.RegisterSymbolAction(Handle3, SymbolKind.Parameter);
}
private void Handle1(SymbolAnalysisContext context)
{
switch (context.Symbol.ToTestDisplayString())
{
case "A..ctor([System.Int32 X = 0])":
Interlocked.Increment(ref FireCount1);
break;
case "B..ctor([System.Int32 Y = 1])":
Interlocked.Increment(ref FireCount2);
break;
case "C..ctor([System.Int32 Z = 4])":
Interlocked.Increment(ref FireCount3);
break;
case "System.Int32 B.M()":
Interlocked.Increment(ref FireCount4);
break;
default:
Assert.True(false);
break;
}
}
private void Handle2(SymbolAnalysisContext context)
{
switch (context.Symbol.ToTestDisplayString())
{
case "System.Int32 A.X { get; init; }":
Interlocked.Increment(ref FireCount5);
break;
case "System.Int32 B.Y { get; init; }":
Interlocked.Increment(ref FireCount6);
break;
default:
Assert.True(false);
break;
}
}
private void Handle3(SymbolAnalysisContext context)
{
switch (context.Symbol.ToTestDisplayString())
{
case "[System.Int32 X = 0]":
Interlocked.Increment(ref FireCount7);
break;
case "[System.Int32 Y = 1]":
Interlocked.Increment(ref FireCount8);
break;
case "[System.Int32 Z = 4]":
Interlocked.Increment(ref FireCount9);
break;
default:
Assert.True(false);
break;
}
}
}
}
}
}
}
src/Compilers/Core/AnalyzerDriver/DeclarationComputer.cs
浏览文件 @
5d1ba27f
...
@@ -18,6 +18,11 @@ internal class DeclarationComputer
...
@@ -18,6 +18,11 @@ internal class DeclarationComputer
internal
static
DeclarationInfo
GetDeclarationInfo
(
SemanticModel
model
,
SyntaxNode
node
,
bool
getSymbol
,
IEnumerable
<
SyntaxNode
>?
executableCodeBlocks
,
CancellationToken
cancellationToken
)
internal
static
DeclarationInfo
GetDeclarationInfo
(
SemanticModel
model
,
SyntaxNode
node
,
bool
getSymbol
,
IEnumerable
<
SyntaxNode
>?
executableCodeBlocks
,
CancellationToken
cancellationToken
)
{
{
var
declaredSymbol
=
GetDeclaredSymbol
(
model
,
node
,
getSymbol
,
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
;
var
codeBlocks
=
executableCodeBlocks
?.
Where
(
c
=>
c
!=
null
).
AsImmutableOrEmpty
()
??
ImmutableArray
<
SyntaxNode
>.
Empty
;
return
new
DeclarationInfo
(
node
,
codeBlocks
,
declaredSymbol
);
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
...
@@ -2767,6 +2767,7 @@ private static bool IsEquivalentSymbol(ISymbol declaredSymbol, ISymbol otherSymb
{
{
case
OperationKind
.
MethodBody
:
case
OperationKind
.
MethodBody
:
case
OperationKind
.
ConstructorBody
:
case
OperationKind
.
ConstructorBody
:
Debug
.
Assert
(!
operationBlock
.
Parent
.
IsImplicit
);
operationsToAnalyze
.
Add
(
operationBlock
.
Parent
);
operationsToAnalyze
.
Add
(
operationBlock
.
Parent
);
break
;
break
;
...
@@ -2776,6 +2777,10 @@ private static bool IsEquivalentSymbol(ISymbol declaredSymbol, ISymbol otherSymb
...
@@ -2776,6 +2777,10 @@ private static bool IsEquivalentSymbol(ISymbol declaredSymbol, ISymbol otherSymb
Debug
.
Assert
(
operationBlock
.
Parent
.
IsImplicit
);
Debug
.
Assert
(
operationBlock
.
Parent
.
IsImplicit
);
Debug
.
Assert
(
operationBlock
.
Parent
.
Parent
is
IConstructorBodyOperation
ctorBody
&&
Debug
.
Assert
(
operationBlock
.
Parent
.
Parent
is
IConstructorBodyOperation
ctorBody
&&
ctorBody
.
Initializer
==
operationBlock
.
Parent
);
ctorBody
.
Initializer
==
operationBlock
.
Parent
);
Debug
.
Assert
(!
operationBlock
.
Parent
.
Parent
.
IsImplicit
);
operationsToAnalyze
.
Add
(
operationBlock
.
Parent
.
Parent
);
break
;
break
;
default
:
default
:
...
...
src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs
浏览文件 @
5d1ba27f
...
@@ -943,7 +943,20 @@ public void MarkSymbolEndAnalysisComplete(ISymbol symbol, DiagnosticAnalyzer ana
...
@@ -943,7 +943,20 @@ public void MarkSymbolEndAnalysisComplete(ISymbol symbol, DiagnosticAnalyzer ana
{
{
ExecuteBlockActionsCore
<
CodeBlockStartAnalyzerAction
<
TLanguageKindEnum
>,
CodeBlockAnalyzerAction
,
SyntaxNodeAnalyzerAction
<
TLanguageKindEnum
>,
SyntaxNodeAnalyzerStateData
,
SyntaxNode
,
TLanguageKindEnum
>(
ExecuteBlockActionsCore
<
CodeBlockStartAnalyzerAction
<
TLanguageKindEnum
>,
CodeBlockAnalyzerAction
,
SyntaxNodeAnalyzerAction
<
TLanguageKindEnum
>,
SyntaxNodeAnalyzerStateData
,
SyntaxNode
,
TLanguageKindEnum
>(
codeBlockStartActions
,
codeBlockActions
,
codeBlockEndActions
,
analyzer
,
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
);
semanticModel
,
getKind
,
analyzerStateOpt
?.
CodeBlockAnalysisState
,
isGeneratedCode
);
return
true
;
return
true
;
}
}
...
...
src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
浏览文件 @
5d1ba27f
...
@@ -1769,9 +1769,13 @@ protected static IOperation VerifyOperationTreeForTest<TSyntaxNode>(CSharpCompil
...
@@ -1769,9 +1769,13 @@ protected static IOperation VerifyOperationTreeForTest<TSyntaxNode>(CSharpCompil
protected
static
void
VerifyOperationTreeForNode
(
CSharpCompilation
compilation
,
SemanticModel
model
,
SyntaxNode
syntaxNode
,
string
expectedOperationTree
)
protected
static
void
VerifyOperationTreeForNode
(
CSharpCompilation
compilation
,
SemanticModel
model
,
SyntaxNode
syntaxNode
,
string
expectedOperationTree
)
{
{
var
actualOperation
=
model
.
GetOperation
(
syntaxNode
);
VerifyOperationTree
(
compilation
,
model
.
GetOperation
(
syntaxNode
),
expectedOperationTree
);
Assert
.
NotNull
(
actualOperation
);
}
var
actualOperationTree
=
GetOperationTreeForTest
(
compilation
,
actualOperation
);
protected
static
void
VerifyOperationTree
(
CSharpCompilation
compilation
,
IOperation
operation
,
string
expectedOperationTree
)
{
Assert
.
NotNull
(
operation
);
var
actualOperationTree
=
GetOperationTreeForTest
(
compilation
,
operation
);
OperationTreeVerifier
.
Verify
(
expectedOperationTree
,
actualOperationTree
);
OperationTreeVerifier
.
Verify
(
expectedOperationTree
,
actualOperationTree
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录