Skip to content

Commit

Permalink
improve related highlight performance
Browse files Browse the repository at this point in the history
See #336
  • Loading branch information
WebFreak001 committed Aug 10, 2023
1 parent 5a8cbbb commit a5929bb
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 8 deletions.
29 changes: 21 additions & 8 deletions workspace-d/source/workspaced/com/dcdext.d
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,15 @@ class DCDExtComponent : ComponentWrapper
if (token >= tokens.length || !tokens[token].isLikeIdentifier)
return null;

Module _parsed;
RollbackAllocator rba;
Module parsed()
{
if (_parsed)
return _parsed;
return _parsed = parseModule(tokens, "stdin", &rba);
}

Related[] ret;

switch (tokens[token].type)
Expand All @@ -908,8 +917,6 @@ class DCDExtComponent : ComponentWrapper
// if lister
auto finder = new IfFinder();
finder.target = tokens[token].index;
RollbackAllocator rba;
auto parsed = parseModule(tokens, "stdin", &rba);
finder.visit(parsed);
foreach (ifToken; finder.foundIf)
ret ~= Related(Related.Type.controlFlow, [ifToken.index, ifToken.index + ifToken.tokenText.length]);
Expand All @@ -929,8 +936,6 @@ class DCDExtComponent : ComponentWrapper
finder.isLoop = !(tokens[token].type == tok!"break" || tokens[token].type == tok!"continue");
if (token + 1 < tokens.length && tokens[token + 1].type == tok!"identifier")
finder.label = tokens[token + 1].text;
RollbackAllocator rba;
auto parsed = parseModule(tokens, "stdin", &rba);
finder.visit(parsed);

if (finder.isLoop && finder.foundBlock.length)
Expand All @@ -951,8 +956,6 @@ class DCDExtComponent : ComponentWrapper
// switch/case lister
auto finder = new SwitchFinder();
finder.target = tokens[token].index;
RollbackAllocator rba;
auto parsed = parseModule(tokens, "stdin", &rba);
finder.visit(parsed);
foreach (switchToken; finder.foundSwitch)
ret ~= Related(Related.Type.controlFlow, [switchToken.index, switchToken.index + switchToken.tokenText.length]);
Expand All @@ -961,8 +964,6 @@ class DCDExtComponent : ComponentWrapper
// return effect lister
auto finder = new ReturnFinder();
finder.target = tokens[token].index;
RollbackAllocator rba;
auto parsed = parseModule(tokens, "stdin", &rba);
finder.visit(parsed);
foreach (switchToken; finder.related)
ret ~= Related(Related.Type.controlFlow, [switchToken.index, switchToken.index + switchToken.tokenText.length]);
Expand Down Expand Up @@ -2149,6 +2150,9 @@ final class IfFinder : ASTVisitor

alias visit = ASTVisitor.visit;

mixin ASTSearchScopeLimit!("target", FunctionBody);
mixin ASTFinisher;

static foreach (If; AliasSeq!(IfStatement, ConditionalStatement))
override void visit(const If ifStatement)
{
Expand Down Expand Up @@ -2279,6 +2283,7 @@ final class IfFinder : ASTVisitor
if (v.index == target)
{
foundIf = currentIf;
exitVisitor = true;
return;
}
}
Expand Down Expand Up @@ -2340,6 +2345,9 @@ final class SwitchFinder : ASTVisitor

alias visit = ASTVisitor.visit;

mixin ASTSearchScopeLimit!("target", FunctionBody);
mixin ASTFinisher;

override void visit(const SwitchStatement stmt)
{
if (foundSwitch.length)
Expand Down Expand Up @@ -2404,6 +2412,7 @@ final class SwitchFinder : ASTVisitor
if (v.index == target)
{
foundSwitch = currentSwitch;
exitVisitor = true;
return;
}
}
Expand Down Expand Up @@ -2457,6 +2466,9 @@ final class BreakFinder : ASTVisitor

alias visit = ASTVisitor.visit;

mixin ASTSearchScopeLimit!("target", FunctionBody);
mixin ASTFinisher;

override void visit(const LabeledStatement stmt)
{
if (foundBlock.length)
Expand Down Expand Up @@ -2622,6 +2634,7 @@ final class BreakFinder : ASTVisitor
if (v.index == target)
{
foundBlock = currentBlock;
exitVisitor = true;
return;
}
}
Expand Down
28 changes: 28 additions & 0 deletions workspace-d/source/workspaced/dparseext.d
Original file line number Diff line number Diff line change
Expand Up @@ -434,3 +434,31 @@ C[] substr(C)(C[] s, size_t start, size_t end)
return s[start .. start];
return s[start .. end];
}

/// Overrides visit for each ASTScopes to only travese them when the ast node
/// tokens contain a token at index `mixin(member)`
mixin template ASTSearchScopeLimit(string member, ASTScopes...)
{
static foreach (ASTScope; ASTScopes)
override void visit(const ASTScope n)
{
if (!n.tokens.length ||
(mixin(member) >= n.tokens[0].index && mixin(member) <= n.tokens[$ - 1].index + n.tokens[$ - 1].textLength))
super.visit(n);
}
}

/// Defines a `exitVisitor` method, when it's set to true, almost all traversing
/// will be skipped. This is realized by overriding DeclarationOrStatement and
/// just returning if it's true.
mixin template ASTFinisher()
{
bool exitVisitor;

override void visit(const DeclarationOrStatement decl)
{
if (exitVisitor)
return;
super.visit(decl);
}
}

0 comments on commit a5929bb

Please sign in to comment.