Skip to content

Commit a5929bb

Browse files
committed
improve related highlight performance
See #336
1 parent 5a8cbbb commit a5929bb

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

workspace-d/source/workspaced/com/dcdext.d

+21-8
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,15 @@ class DCDExtComponent : ComponentWrapper
884884
if (token >= tokens.length || !tokens[token].isLikeIdentifier)
885885
return null;
886886

887+
Module _parsed;
888+
RollbackAllocator rba;
889+
Module parsed()
890+
{
891+
if (_parsed)
892+
return _parsed;
893+
return _parsed = parseModule(tokens, "stdin", &rba);
894+
}
895+
887896
Related[] ret;
888897

889898
switch (tokens[token].type)
@@ -908,8 +917,6 @@ class DCDExtComponent : ComponentWrapper
908917
// if lister
909918
auto finder = new IfFinder();
910919
finder.target = tokens[token].index;
911-
RollbackAllocator rba;
912-
auto parsed = parseModule(tokens, "stdin", &rba);
913920
finder.visit(parsed);
914921
foreach (ifToken; finder.foundIf)
915922
ret ~= Related(Related.Type.controlFlow, [ifToken.index, ifToken.index + ifToken.tokenText.length]);
@@ -929,8 +936,6 @@ class DCDExtComponent : ComponentWrapper
929936
finder.isLoop = !(tokens[token].type == tok!"break" || tokens[token].type == tok!"continue");
930937
if (token + 1 < tokens.length && tokens[token + 1].type == tok!"identifier")
931938
finder.label = tokens[token + 1].text;
932-
RollbackAllocator rba;
933-
auto parsed = parseModule(tokens, "stdin", &rba);
934939
finder.visit(parsed);
935940

936941
if (finder.isLoop && finder.foundBlock.length)
@@ -951,8 +956,6 @@ class DCDExtComponent : ComponentWrapper
951956
// switch/case lister
952957
auto finder = new SwitchFinder();
953958
finder.target = tokens[token].index;
954-
RollbackAllocator rba;
955-
auto parsed = parseModule(tokens, "stdin", &rba);
956959
finder.visit(parsed);
957960
foreach (switchToken; finder.foundSwitch)
958961
ret ~= Related(Related.Type.controlFlow, [switchToken.index, switchToken.index + switchToken.tokenText.length]);
@@ -961,8 +964,6 @@ class DCDExtComponent : ComponentWrapper
961964
// return effect lister
962965
auto finder = new ReturnFinder();
963966
finder.target = tokens[token].index;
964-
RollbackAllocator rba;
965-
auto parsed = parseModule(tokens, "stdin", &rba);
966967
finder.visit(parsed);
967968
foreach (switchToken; finder.related)
968969
ret ~= Related(Related.Type.controlFlow, [switchToken.index, switchToken.index + switchToken.tokenText.length]);
@@ -2149,6 +2150,9 @@ final class IfFinder : ASTVisitor
21492150

21502151
alias visit = ASTVisitor.visit;
21512152

2153+
mixin ASTSearchScopeLimit!("target", FunctionBody);
2154+
mixin ASTFinisher;
2155+
21522156
static foreach (If; AliasSeq!(IfStatement, ConditionalStatement))
21532157
override void visit(const If ifStatement)
21542158
{
@@ -2279,6 +2283,7 @@ final class IfFinder : ASTVisitor
22792283
if (v.index == target)
22802284
{
22812285
foundIf = currentIf;
2286+
exitVisitor = true;
22822287
return;
22832288
}
22842289
}
@@ -2340,6 +2345,9 @@ final class SwitchFinder : ASTVisitor
23402345

23412346
alias visit = ASTVisitor.visit;
23422347

2348+
mixin ASTSearchScopeLimit!("target", FunctionBody);
2349+
mixin ASTFinisher;
2350+
23432351
override void visit(const SwitchStatement stmt)
23442352
{
23452353
if (foundSwitch.length)
@@ -2404,6 +2412,7 @@ final class SwitchFinder : ASTVisitor
24042412
if (v.index == target)
24052413
{
24062414
foundSwitch = currentSwitch;
2415+
exitVisitor = true;
24072416
return;
24082417
}
24092418
}
@@ -2457,6 +2466,9 @@ final class BreakFinder : ASTVisitor
24572466

24582467
alias visit = ASTVisitor.visit;
24592468

2469+
mixin ASTSearchScopeLimit!("target", FunctionBody);
2470+
mixin ASTFinisher;
2471+
24602472
override void visit(const LabeledStatement stmt)
24612473
{
24622474
if (foundBlock.length)
@@ -2622,6 +2634,7 @@ final class BreakFinder : ASTVisitor
26222634
if (v.index == target)
26232635
{
26242636
foundBlock = currentBlock;
2637+
exitVisitor = true;
26252638
return;
26262639
}
26272640
}

workspace-d/source/workspaced/dparseext.d

+28
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,31 @@ C[] substr(C)(C[] s, size_t start, size_t end)
434434
return s[start .. start];
435435
return s[start .. end];
436436
}
437+
438+
/// Overrides visit for each ASTScopes to only travese them when the ast node
439+
/// tokens contain a token at index `mixin(member)`
440+
mixin template ASTSearchScopeLimit(string member, ASTScopes...)
441+
{
442+
static foreach (ASTScope; ASTScopes)
443+
override void visit(const ASTScope n)
444+
{
445+
if (!n.tokens.length ||
446+
(mixin(member) >= n.tokens[0].index && mixin(member) <= n.tokens[$ - 1].index + n.tokens[$ - 1].textLength))
447+
super.visit(n);
448+
}
449+
}
450+
451+
/// Defines a `exitVisitor` method, when it's set to true, almost all traversing
452+
/// will be skipped. This is realized by overriding DeclarationOrStatement and
453+
/// just returning if it's true.
454+
mixin template ASTFinisher()
455+
{
456+
bool exitVisitor;
457+
458+
override void visit(const DeclarationOrStatement decl)
459+
{
460+
if (exitVisitor)
461+
return;
462+
super.visit(decl);
463+
}
464+
}

0 commit comments

Comments
 (0)