Skip to content

Commit

Permalink
Refactor ScopeStack (#9158)
Browse files Browse the repository at this point in the history
Co-authored-by: Chris Sienkiewicz <chsienki@microsoft.com>
  • Loading branch information
jjonescz and chsienki authored Aug 30, 2023
1 parent 835e75f commit f3fac03
Showing 1 changed file with 20 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,23 @@ namespace Microsoft.AspNetCore.Razor.Language.Components;
internal class ScopeStack
{
private readonly Stack<ScopeEntry> _stack = new Stack<ScopeEntry>();
private int _builderVarNumber = 1;

public string BuilderVarName { get; private set; } = ComponentsApi.RenderTreeBuilder.BuilderParameter;
public string BuilderVarName =>
Current.BuilderVarNumber == 1
? ComponentsApi.RenderTreeBuilder.BuilderParameter
: $"{ComponentsApi.RenderTreeBuilder.BuilderParameter}{Current.BuilderVarNumber}";

public int Depth => _stack.Count;
public int Depth => _stack.Count - 1;

public void OpenComponentScope(CodeRenderingContext context, string name, string parameterName)
{
var scope = new ScopeEntry(name, ScopeKind.Component);
_stack.Push(scope);
private ScopeEntry Current => _stack.Peek();

OffsetBuilderVarNumber(1);
public ScopeStack()
{
_stack.Push(new ScopeEntry() { BuilderVarNumber = 1 });
}

public void OpenComponentScope(CodeRenderingContext context, string name, string parameterName)
{
// Writes code that looks like:
//
// ((__builder) => { ... })
Expand All @@ -40,55 +44,27 @@ public void OpenComponentScope(CodeRenderingContext context, string name, string
{
context.CodeWriter.Write($"({parameterName}) => ");
}

scope.LambdaScope = context.CodeWriter.BuildLambda(BuilderVarName);
OpenScope(context);
}

public void OpenTemplateScope(CodeRenderingContext context)
{
var currentScope = new ScopeEntry("__template", ScopeKind.Template);
_stack.Push(currentScope);
public void OpenTemplateScope(CodeRenderingContext context) => OpenScope(context);

// Templates always get a lambda scope, because they are defined as a lambda.
OffsetBuilderVarNumber(1);
currentScope.LambdaScope = context.CodeWriter.BuildLambda(BuilderVarName);
private void OpenScope(CodeRenderingContext context)
{
var scope = new ScopeEntry() { BuilderVarNumber = Current.BuilderVarNumber + 1 };
_stack.Push(scope);
scope.LambdaScope = context.CodeWriter.BuildLambda(BuilderVarName);
}

public void CloseScope(CodeRenderingContext context)
{
var currentScope = _stack.Pop();
currentScope.LambdaScope.Dispose();
OffsetBuilderVarNumber(-1);
}

private void OffsetBuilderVarNumber(int delta)
{
_builderVarNumber += delta;
BuilderVarName = _builderVarNumber == 1
? ComponentsApi.RenderTreeBuilder.BuilderParameter
: $"{ComponentsApi.RenderTreeBuilder.BuilderParameter}{_builderVarNumber}";
}

private class ScopeEntry
{
public readonly string Name;
public ScopeKind Kind;
public int ChildCount;
public int BuilderVarNumber;
public IDisposable LambdaScope;

public ScopeEntry(string name, ScopeKind kind)
{
Name = name;
Kind = kind;
ChildCount = 0;
}

public override string ToString() => $"<{Name}> ({Kind})";
}

private enum ScopeKind
{
Component,
Template,
}
}

0 comments on commit f3fac03

Please sign in to comment.