-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathSyntaxWalkerBase.cs
More file actions
105 lines (92 loc) · 3.59 KB
/
SyntaxWalkerBase.cs
File metadata and controls
105 lines (92 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using CodeGraph.Graph;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace CodeParser.Parser;
/// <summary>
/// Handling here does not distinguish between method or lambda bodies.
/// </summary>
internal class SyntaxWalkerBase : CSharpSyntaxWalker
{
protected readonly ISyntaxNodeHandler Analyzer;
protected readonly bool IsFieldInitializer;
protected readonly SemanticModel SemanticModel;
protected readonly CodeElement SourceElement;
protected SyntaxWalkerBase(ISyntaxNodeHandler analyzer, CodeElement sourceElement, SemanticModel semanticModel, bool isFieldInitializer)
{
Analyzer = analyzer;
SourceElement = sourceElement;
SemanticModel = semanticModel;
IsFieldInitializer = isFieldInitializer;
}
/// <summary>
/// We need this also for lambdas to capture: x => Foo(SomeMethod)
/// </summary>
public override void VisitArgument(ArgumentSyntax node)
{
Analyzer.AnalyzeArgument(SourceElement, node, SemanticModel);
base.VisitArgument(node);
}
// Note: VisitIdentifierName is NOT overridden here because concrete walkers need to specify
// their relationship type (Calls for MethodBodyWalker, Uses for LambdaBodyWalker).
// Each walker overrides VisitIdentifierName with the appropriate RelationshipType parameter.
public override void VisitLocalDeclarationStatement(LocalDeclarationStatementSyntax node)
{
Analyzer.AnalyzeLocalDeclaration(SourceElement, node, SemanticModel);
base.VisitLocalDeclarationStatement(node);
}
/// <summary>
/// typeof(Foo)
/// </summary>
public override void VisitTypeOfExpression(TypeOfExpressionSyntax node)
{
Analyzer.AnalyzeTypeSyntax(SourceElement, SemanticModel, node.Type);
// Don't get down to the identifier
//base.VisitTypeOfExpression(node);
}
/// <summary>
/// sizeof(Foo)
/// </summary>
public override void VisitSizeOfExpression(SizeOfExpressionSyntax node)
{
Analyzer.AnalyzeTypeSyntax(SourceElement, SemanticModel, node.Type);
base.VisitSizeOfExpression(node);
}
/// <summary>
/// default(Foo)
/// </summary>
public override void VisitDefaultExpression(DefaultExpressionSyntax node)
{
// default(Foo) - Uses relationship to type
Analyzer.AnalyzeTypeSyntax(SourceElement, SemanticModel, node.Type);
base.VisitDefaultExpression(node);
}
/// <summary>
/// var x = (Foo)y
/// </summary>
public override void VisitCastExpression(CastExpressionSyntax node)
{
// (Foo)obj - Uses relationship to cast type
Analyzer.AnalyzeTypeSyntax(SourceElement, SemanticModel, node.Type);
base.VisitCastExpression(node);
}
/// <summary>
/// var x = y as Foo
/// var x = y is Foo
/// </summary>
public override void VisitBinaryExpression(BinaryExpressionSyntax node)
{
// Note: var y = x as BaseClass; would capture the using to BaseClass twice. See AnalyzeLocalDeclaration.
// Handle: obj is Foo
if (node.IsKind(SyntaxKind.IsExpression) || node.IsKind(SyntaxKind.AsExpression))
{
var typeInfo = SemanticModel.GetTypeInfo(node.Right);
if (typeInfo.Type != null)
{
var location = node.Right.GetSyntaxLocation();
Analyzer.AddTypeRelationshipPublic(SourceElement, typeInfo.Type, RelationshipType.Uses, location);
}
}
base.VisitBinaryExpression(node);
}
}