@@ -26,6 +26,8 @@ public static Selection GetSelection(this ParserRuleContext context)
26
26
context . Stop . EndColumn ( ) + 1 ) ;
27
27
}
28
28
29
+ //TODO: Question - remove? None of the GetProcedureSelection overloads below are referenced (except for one...in a test)
30
+ //https://github.com/rubberduck-vba/Rubberduck/issues/2164
29
31
//This set of overloads returns the selection for the entire procedure statement body, i.e. Public Function Foo(bar As String) As String
30
32
public static Selection GetProcedureSelection ( this VBAParser . FunctionStmtContext context ) { return GetProcedureContextSelection ( context ) ; }
31
33
public static Selection GetProcedureSelection ( this VBAParser . SubStmtContext context ) { return GetProcedureContextSelection ( context ) ; }
@@ -35,126 +37,83 @@ public static Selection GetSelection(this ParserRuleContext context)
35
37
36
38
private static Selection GetProcedureContextSelection ( ParserRuleContext context )
37
39
{
38
- var endContext = context . GetRuleContext < VBAParser . EndOfStatementContext > ( 0 ) ;
40
+ var endContext1 = context . GetRuleContext < VBAParser . EndOfStatementContext > ( 0 ) ;
41
+ var endContext = context . GetChild < VBAParser . EndOfStatementContext > ( ) ;
39
42
return new Selection ( context . Start . Line == 0 ? 1 : context . Start . Line ,
40
43
context . Start . Column + 1 ,
41
44
endContext . Start . Line == 0 ? 1 : endContext . Start . Line ,
42
45
endContext . Start . Column + 1 ) ;
43
46
}
44
47
45
- //public static IEnumerable<TContext> FindChildrenX<TContext>(this ParserRuleContext context) where TContext : ParserRuleContext
46
- //{
47
- // var walker = new ParseTreeWalker();
48
- // var listener = new ChildNodeListener<TContext>();
49
- // walker.Walk(listener, context);
50
- // return listener.Matches;
51
- //}
52
-
48
+ /// <summary>
49
+ /// Gets the tokens belonging to the context from the token stream.
50
+ /// </summary>
53
51
public static IEnumerable < IToken > GetTokens ( this ParserRuleContext context , CommonTokenStream tokenStream )
54
52
{
55
53
var sourceInterval = context . SourceInterval ;
56
54
if ( sourceInterval . Equals ( Interval . Invalid ) || sourceInterval . b < sourceInterval . a )
57
55
{
58
56
return new List < IToken > ( ) ;
59
57
}
60
- // Gets the tokens belonging to the context from the token stream.
61
58
return tokenStream . GetTokens ( sourceInterval . a , sourceInterval . b ) ;
62
59
}
63
60
61
+ /// <summary>
62
+ /// Gets the original source, without "synthetic" text such as "<EOF>
63
+ /// </summary>
64
64
public static string GetText ( this ParserRuleContext context , ICharStream stream )
65
65
{
66
66
// Can be null if the input is empty it seems.
67
67
if ( context . Stop == null )
68
68
{
69
69
return string . Empty ;
70
70
}
71
- // Gets the original source, without "synthetic" text such as "<EOF>".
72
71
return stream . GetText ( new Interval ( context . Start . StartIndex , context . Stop . StopIndex ) ) ;
73
72
}
74
73
75
- public static T GetChild < T > ( this ParserRuleContext context )
74
+ /// <summary>
75
+ /// Returns the first direct child of 'context' that is of the generic Type.
76
+ /// </summary>
77
+ public static TContext GetChild < TContext > ( this ParserRuleContext context ) where TContext : ParserRuleContext
76
78
{
77
79
if ( context == null )
78
80
{
79
81
return default ;
80
82
}
81
83
82
- for ( var index = 0 ; index < context . ChildCount ; index ++ )
84
+ var results = context . children . Where ( child => child is TContext ) ;
85
+ return results . Any ( ) ? ( TContext ) results . First ( ) : default ;
86
+ }
87
+
88
+ /// <summary>
89
+ /// Determines if any of the context's ancestors are the generic Type.
90
+ /// </summary>
91
+ public static bool IsDescendentOf < TContext > ( this ParserRuleContext context )
92
+ {
93
+ if ( context is TContext )
83
94
{
84
- var child = context . GetChild ( index ) ;
85
- if ( context . GetChild ( index ) is T )
86
- {
87
- return ( T ) child ;
88
- }
95
+ return GetParent_Recursive < TContext > ( ( ParserRuleContext ) context . Parent ) != null ;
89
96
}
90
-
91
- return default ;
97
+ return GetParent_Recursive < TContext > ( context ) != null ;
92
98
}
93
99
94
- //public static IEnumerable<T> GetChildren<T>(this RuleContext context)
95
- //{
96
- // if (context == null)
97
- // {
98
- // yield break;
99
- // }
100
-
101
- // for (var index = 0; index < context.ChildCount; index++)
102
- // {
103
- // var child = context.GetChild(index);
104
- // if (child is T)
105
- // {
106
- // yield return (T)child;
107
- // }
108
- // }
109
- //}
110
-
111
- public static T GetParent < T > ( this ParserRuleContext context )
100
+ /// <summary>
101
+ /// Determines if any of the context's ancestors are equal to the parameter 'parent'.
102
+ /// </summary>
103
+ public static bool IsDescendentOf < T > ( this ParserRuleContext context , T parent ) where T : ParserRuleContext
112
104
{
113
- if ( context == null )
105
+ if ( context == null || parent == null )
114
106
{
115
- return default ;
107
+ return false ;
116
108
}
117
- if ( context is T )
109
+ if ( context != parent )
118
110
{
119
- return ( T ) System . Convert . ChangeType ( context , typeof ( T ) ) ;
111
+ return IsDescendentOf_Recursive ( context , parent ) ;
120
112
}
121
- //return GetMyParent<T>(context); //.Parent);
122
- return GetParent < T > ( ( ParserRuleContext ) context . Parent ) ;
113
+ return false ;
123
114
}
124
115
125
- //private static T GetMyParent<T>(ParserRuleContext context)
126
- //{
127
- // if (context == null)
128
- // {
129
- // return default;
130
- // }
131
- // if (context is T)
132
- // {
133
- // return (T)System.Convert.ChangeType(context, typeof(T));
134
- // }
135
- // return GetMyParent<T>((ParserRuleContext)context.Parent);
136
- //}
137
-
138
- public static bool HasParent < TContext > ( this ParserRuleContext context )
139
- {
140
- //return TryGetAncestor(context, out TContext _);
141
- return GetParent < TContext > ( context ) != null ;
142
- }
143
-
144
- public static bool HasParent ( this ParserRuleContext context , IParseTree parent )
145
- {
146
- return HasParent ( ( IParseTree ) context , parent ) ;
147
- //if (TryGetAncestor(context, out IParseTree ancestor))
148
- //{
149
- // if (ancestor == parent)
150
- // {
151
- // return true;
152
- // }
153
- //}
154
- //return HasParent(ancestor, parent);
155
- }
156
-
157
- private static bool HasParent ( this IParseTree context , IParseTree targetParent )
116
+ private static bool IsDescendentOf_Recursive ( IParseTree context , IParseTree targetParent )
158
117
{
159
118
if ( context == null )
160
119
{
@@ -164,90 +123,63 @@ private static bool HasParent(this IParseTree context, IParseTree targetParent)
164
123
{
165
124
return true ;
166
125
}
167
- return HasParent ( context . Parent , targetParent ) ;
126
+ return IsDescendentOf_Recursive ( context . Parent , targetParent ) ;
168
127
}
169
128
170
- private static bool TryGetAncestor < TContext > ( this ParserRuleContext context , out TContext ancestor )
171
- {
172
- ancestor = GetParent < TContext > ( context ) ;
173
- return ancestor != null ;
174
- }
129
+ //TODO: Question: I would like to rename GetParent<T>(...) function to GetAncestor<T>(...)
130
+ //With a name like GetParent, I would expected the code to simply be: "return context.Parent;"
131
+ //This function is called when the caller is interested in looking 'up' the hierarchy including
132
+ //and above the immediate parent.
175
133
176
- public static TContext FindChild < TContext > ( this ParserRuleContext context ) where TContext : ParserRuleContext
134
+ /// <summary>
135
+ /// Returns the context's first ancestor of the generic Type.
136
+ /// </summary>
137
+ public static TContext GetParent < TContext > ( this ParserRuleContext context )
177
138
{
178
139
if ( context == null )
179
140
{
180
141
return default ;
181
142
}
182
-
183
- for ( var index = 0 ; index < context . ChildCount ; index ++ )
143
+ if ( context is TContext )
184
144
{
185
- var child = context . GetChild ( index ) ;
186
- if ( context . GetChild ( index ) is TContext )
187
- {
188
- return ( TContext ) child ;
189
- }
145
+ return GetParent_Recursive < TContext > ( ( ParserRuleContext ) context . Parent ) ;
190
146
}
191
- return default ;
192
- }
193
-
194
- //public static bool HasChildToken(this IParseTree context, string token)
195
- //{
196
- // for (var index = 0; index < context.ChildCount; index++)
197
- // {
198
- // var child = context.GetChild(index);
199
- // if (context.GetChild(index).GetText().Equals(token))
200
- // {
201
- // return true;
202
- // }
203
- // }
204
- // return false;
205
- //}
206
-
207
- public static bool HasChildToken ( this ParserRuleContext context , string token )
208
- {
209
- return context . children . Any ( ch => ch . GetText ( ) . Equals ( token ) ) ;
210
- //for (var index = 0; index < context.ChildCount; index++)
211
- //{
212
- // var child = context.GetChild(index);
213
- // if (context.GetChild(index).GetText().Equals(token))
214
- // {
215
- // return true;
216
- // }
217
- //}
218
- //return false;
219
- }
220
-
221
- public static T GetDescendent < T > ( this ParserRuleContext context )
222
- {
223
- return GetDescendent < T > ( ( IParseTree ) context ) ;
147
+ return GetParent_Recursive < TContext > ( context ) ;
224
148
}
225
149
226
- private static T GetDescendent < T > ( this IParseTree context )
150
+ private static TContext GetParent_Recursive < TContext > ( ParserRuleContext context )
227
151
{
228
152
if ( context == null )
229
153
{
230
154
return default ;
231
155
}
232
-
233
- for ( var index = 0 ; index < context . ChildCount ; index ++ )
156
+ if ( context is TContext )
234
157
{
235
- var child = context . GetChild ( index ) ;
236
- if ( context . GetChild ( index ) is T )
237
- {
238
- return ( T ) child ;
239
- }
240
-
241
- var descendent = child . GetDescendent < T > ( ) ;
242
- if ( descendent != null )
243
- {
244
- return descendent ;
245
- }
158
+ return ( TContext ) System . Convert . ChangeType ( context , typeof ( TContext ) ) ;
246
159
}
160
+ return GetParent_Recursive < TContext > ( ( ParserRuleContext ) context . Parent ) ;
161
+ }
247
162
248
- return default ;
163
+ /// <summary>
164
+ /// Determines if the any of the child contexts child.GetText() equals token .
165
+ /// </summary>
166
+ public static bool HasChildToken ( this ParserRuleContext context , string token )
167
+ {
168
+ return context . children . Any ( ch => ch . GetText ( ) . Equals ( token ) ) ;
169
+ }
170
+
171
+ /// <summary>
172
+ /// Returns the context's first descendent of the generic Type.
173
+ /// </summary>
174
+ public static TContext GetDescendent < TContext > ( this ParserRuleContext context ) where TContext : ParserRuleContext
175
+ {
176
+ var descendents = GetDescendents < TContext > ( context ) ;
177
+ return descendents . Any ( ) ? descendents . First ( ) : null ;
249
178
}
250
179
180
+ /// <summary>
181
+ /// Returns all the context's descendents of the generic Type.
182
+ /// </summary>
251
183
public static IEnumerable < TContext > GetDescendents < TContext > ( this ParserRuleContext context ) where TContext : ParserRuleContext
252
184
{
253
185
var walker = new ParseTreeWalker ( ) ;
0 commit comments