/
SyntaxWalker.cs
105 lines (98 loc) · 3.77 KB
/
SyntaxWalker.cs
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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CodeAnalysis
{
/// <summary>
/// Walks the syntax tree, allowing subclasses to operate on all nodes, token and trivia. The
/// walker will perform a depth first walk of the tree.
/// </summary>
public abstract class SyntaxWalker
{
/// <summary>
/// Syntax the <see cref="SyntaxWalker"/> should descend into.
/// </summary>
protected SyntaxWalkerDepth Depth { get; }
/// <summary>
/// Creates a new walker instance.
/// </summary>
/// <param name="depth">Syntax the <see cref="SyntaxWalker"/> should descend into.</param>
protected SyntaxWalker(SyntaxWalkerDepth depth = SyntaxWalkerDepth.Node)
{
this.Depth = depth;
}
/// <summary>
/// Called when the walker visits a node. This method may be overridden if subclasses want
/// to handle the node. Overrides should call back into this base method if they want the
/// children of this node to be visited.
/// </summary>
/// <param name="node">The current node that the walker is visiting.</param>
public virtual void Visit(SyntaxNode node)
{
foreach (var child in node.ChildNodesAndTokens())
{
if (child.IsNode)
{
if (this.Depth >= SyntaxWalkerDepth.Node)
{
Visit(child.AsNode()!);
}
}
else if (child.IsToken)
{
if (this.Depth >= SyntaxWalkerDepth.Token)
{
VisitToken(child.AsToken());
}
}
}
}
/// <summary>
/// Called when the walker visits a token. This method may be overridden if subclasses want
/// to handle the token. Overrides should call back into this base method if they want the
/// trivia of this token to be visited.
/// </summary>
/// <param name="token">The current token that the walker is visiting.</param>
protected virtual void VisitToken(SyntaxToken token)
{
if (this.Depth >= SyntaxWalkerDepth.Trivia)
{
this.VisitLeadingTrivia(token);
this.VisitTrailingTrivia(token);
}
}
private void VisitLeadingTrivia(in SyntaxToken token)
{
if (token.HasLeadingTrivia)
{
foreach (var trivia in token.LeadingTrivia)
{
VisitTrivia(trivia);
}
}
}
private void VisitTrailingTrivia(in SyntaxToken token)
{
if (token.HasTrailingTrivia)
{
foreach (var trivia in token.TrailingTrivia)
{
VisitTrivia(trivia);
}
}
}
/// <summary>
/// Called when the walker visits a trivia syntax. This method may be overridden if
/// subclasses want to handle the token. Overrides should call back into this base method if
/// they want the children of this trivia syntax to be visited.
/// </summary>
/// <param name="trivia">The current trivia syntax that the walker is visiting.</param>
protected virtual void VisitTrivia(SyntaxTrivia trivia)
{
if (this.Depth >= SyntaxWalkerDepth.StructuredTrivia && trivia.HasStructure)
{
this.Visit(trivia.GetStructure()!);
}
}
}
}