Skip to content

Commit 9727d38

Browse files
committed
Made GetDescendentsContainingTokenIndex more efficient.
1 parent cdba060 commit 9727d38

File tree

1 file changed

+23
-27
lines changed

1 file changed

+23
-27
lines changed

Rubberduck.Parsing/ParserRuleContextExtensions.cs

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,31 @@ public static TContext GetDescendentContainingTokenIndex<TContext>(this ParserRu
222222

223223
/// <summary>
224224
/// Returns all the context's descendents of the generic type containing the token with the specified token index.
225+
/// If there are multiple matches, they are ordered from outermost to innermost context.
225226
/// </summary>
226227
public static IEnumerable<TContext> GetDescendentsContainingTokenIndex<TContext>(this ParserRuleContext context, int tokenIndex) where TContext : ParserRuleContext
227228
{
228-
var walker = new ParseTreeWalker();
229-
var listener = new ChildNodeWithTokenPositionListener<TContext>(tokenIndex);
230-
walker.Walk(listener, context);
231-
return listener.Matches;
229+
if (!context.ContainsTokenIndex(tokenIndex))
230+
{
231+
return new List<TContext>();
232+
}
233+
234+
var matches = new List<TContext>();
235+
if (context is TContext match)
236+
{
237+
matches.Add(match);
238+
}
239+
240+
foreach (var child in context.children)
241+
{
242+
if (child is ParserRuleContext childContext && childContext.ContainsTokenIndex(tokenIndex))
243+
{
244+
matches.AddRange(childContext.GetDescendentsContainingTokenIndex<TContext>(tokenIndex));
245+
break; //Only one child can contain the token index.
246+
}
247+
}
248+
249+
return matches;
232250
}
233251

234252
/// <summary>
@@ -277,27 +295,6 @@ public static bool TryGetFollowingContext<TContext>(this ParserRuleContext conte
277295
return followingContext != null;
278296
}
279297

280-
private class ChildNodeWithTokenPositionListener<TContext> : VBAParserBaseListener where TContext : ParserRuleContext
281-
{
282-
private readonly int _tokenIndex;
283-
284-
private readonly HashSet<TContext> _matches = new HashSet<TContext>();
285-
public IEnumerable<TContext> Matches => _matches;
286-
287-
public ChildNodeWithTokenPositionListener(int tokenIndex)
288-
{
289-
_tokenIndex = tokenIndex;
290-
}
291-
292-
public override void EnterEveryRule(ParserRuleContext context)
293-
{
294-
var match = context as TContext;
295-
if (match != null && match.ContainsTokenIndex(_tokenIndex))
296-
{
297-
_matches.Add(match);
298-
}
299-
}
300-
}
301298

302299
private class ChildNodeListener<TContext> : VBAParserBaseListener where TContext : ParserRuleContext
303300
{
@@ -306,8 +303,7 @@ private class ChildNodeListener<TContext> : VBAParserBaseListener where TContext
306303

307304
public override void EnterEveryRule(ParserRuleContext context)
308305
{
309-
var match = context as TContext;
310-
if (match != null)
306+
if (context is TContext match)
311307
{
312308
_matches.Add(match);
313309
}

0 commit comments

Comments
 (0)