Skip to content

Commit

Permalink
Merge pull request #55 from EvoEsports/bugfix/slots-and-variables
Browse files Browse the repository at this point in the history
Bugfix/slots and variables
  • Loading branch information
araszka authored Feb 8, 2024
2 parents 8289e76 + 5f92f86 commit 4d7d853
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 85 deletions.
2 changes: 1 addition & 1 deletion src/ManiaTemplates/Components/MtComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ private static HashSet<string> GetSlotNamesInTemplate(XmlNode node)
{
foreach (var slotName in GetSlotNamesInTemplate(childNode))
{
if (slotNames.Contains(slotName))
if (slotNames.Contains(slotName) && slotName != "default")
{
throw new DuplicateSlotException($"""A slot with the name "{slotName}" already exists.""");
}
Expand Down
6 changes: 1 addition & 5 deletions src/ManiaTemplates/Components/MtComponentSlot.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
using ManiaTemplates.ControlElements;
using ManiaTemplates.Lib;

namespace ManiaTemplates.Components;
namespace ManiaTemplates.Components;

public class MtComponentSlot
{
public required int Scope { get; init; }
public required string RenderMethodT4 { get; init; }
public required MtDataContext Context { get; init; }
public string Name { get; init; } = "default";
}
3 changes: 1 addition & 2 deletions src/ManiaTemplates/ControlElements/MtDataContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public MtDataContext NewContext(MtDataContext otherContext)

public override string ToString()
{
return $"C{_name}";
// return $"MtContext_{_name}_" + GetHashCode().ToString().Replace("-", "N");
return _name ?? "";
}
}
134 changes: 71 additions & 63 deletions src/ManiaTemplates/Lib/MtTransformer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.CodeDom;
using System.Diagnostics;
using System.Dynamic;
using System.Globalization;
using System.Text;
Expand Down Expand Up @@ -46,6 +45,9 @@ public string BuildManialink(MtComponent rootComponent, string className, int ve
{
_namespaces.AddRange(rootComponent.Namespaces);

var renderBodyArguments =
string.Join(',', rootComponent.Slots.Select(slotName => "DoNothing").ToList());

var body = ProcessNode(
XmlStringToNode(rootComponent.TemplateContent),
_engine.BaseMtComponents.Overload(rootComponent.ImportedComponents),
Expand All @@ -61,7 +63,7 @@ public string BuildManialink(MtComponent rootComponent, string className, int ve
CreateImportStatements(),
ManiaLinkStart(className, version, rootComponent.DisplayLayer),
"<#",
"RenderBody();",
$"RenderBody({renderBodyArguments});",
"#>",
ManiaLinkEnd(),
CreateTemplatePropertiesBlock(rootComponent),
Expand All @@ -79,7 +81,7 @@ public string BuildManialink(MtComponent rootComponent, string className, int ve
/// </summary>
private string CreateDoNothingMethod()
{
return _maniaTemplateLanguage.FeatureBlock("""string DoNothing(){ return ""; }""").ToString();
return _maniaTemplateLanguage.FeatureBlock("private static void DoNothing(){}").ToString();
}

/// <summary>
Expand All @@ -89,8 +91,8 @@ private string CreateInsertedManiaScriptsList()
{
return new StringBuilder()
.AppendLine(_maniaTemplateLanguage.FeatureBlockStart())
.AppendLine("List<string> __insertedOneTimeManiaScripts = new List<string>();")
.AppendLine("List<Action> __maniaScriptRenderMethods = new List<Action>();")
.AppendLine("private List<string> __insertedOneTimeManiaScripts = new List<string>();")
.AppendLine("private List<Action> __maniaScriptRenderMethods = new List<Action>();")
.AppendLine(_maniaTemplateLanguage.FeatureBlockEnd())
.ToString();
}
Expand All @@ -102,7 +104,7 @@ private string CreateBodyRenderMethod(string body, MtComponent rootComponent)
{
var methodArguments = new List<string>();
AppendSlotRenderArgumentsToList(methodArguments, rootComponent);
var bodyRenderMethod = new StringBuilder($"void RenderBody({string.Join(',', methodArguments)}) {{\n");
var bodyRenderMethod = new StringBuilder($"private void RenderBody({string.Join(',', methodArguments)}) {{\n");

//Root mania script block
var rootScriptBlock = "";
Expand Down Expand Up @@ -196,45 +198,43 @@ private string CreateRenderMethodsBlock()
/// Creates the slot-render method for a given data context.
/// </summary>
private string CreateSlotRenderMethod(MtComponent component, int scope, MtDataContext context, string slotName,
MtComponent rootComponent, string slotContent, MtComponent? parentComponent = null)
MtComponent rootComponent, string slotContent, MtComponent parentComponent)
{
var methodArguments = new List<string>();
var methodName = GetSlotRenderMethodName(scope, slotName);

//Add slot render methods
AppendSlotRenderArgumentsToList(methodArguments, parentComponent);

//Add component properties as arguments
if (parentComponent != null)
foreach (var (localVariableName, localVariableType) in context)
{
foreach (var (localVariableName, localVariableType) in context)
{
if (!rootComponent.Properties.ContainsKey(localVariableName))
{
methodArguments.Add($"{localVariableType} {localVariableName}");
}
}

if (parentComponent != rootComponent)
if (!rootComponent.Properties.ContainsKey(localVariableName))
{
AppendComponentPropertiesToMethodArgumentsList(parentComponent, methodArguments);
methodArguments.Add($"{localVariableType} {localVariableName}");
}
}
else

if (parentComponent != rootComponent)
{
foreach (var (localVariableName, localVariableType) in context)
{
if (!rootComponent.Properties.ContainsKey(localVariableName))
{
methodArguments.Add($"{localVariableType} {localVariableName}");
}
}
AppendComponentPropertiesToMethodArgumentsList(parentComponent, methodArguments);
}

//Add slot render methods
AppendSlotRenderArgumentsToList(methodArguments, parentComponent ?? component);

//Start slot render method declaration
var output = new StringBuilder(_maniaTemplateLanguage.FeatureBlockStart())
.AppendLine("void " + CreateMethodCall(methodName, string.Join(',', methodArguments), "") + " {");
.AppendLine("private void " + CreateMethodCall(methodName, string.Join(',', methodArguments), "") + " {");

//Declare component default variables
foreach (var prop in component.Properties.Values)
{
if (prop.Default == null || (parentComponent.Properties.ContainsKey(prop.Name)))
{
continue;
}

output.AppendLine($"const {prop.Type} {prop.Name} = {WrapIfString(prop, prop.Default)};");
}

output
.AppendLine(_maniaTemplateLanguage.FeatureBlockEnd())
.AppendLine(slotContent)
Expand All @@ -249,8 +249,7 @@ private string CreateSlotRenderMethod(MtComponent component, int scope, MtDataCo
/// Process a ManiaTemplate node.
/// </summary>
private string ProcessNode(XmlNode node, MtComponentMap availableMtComponents, MtDataContext context,
MtComponent rootComponent,
MtComponent? parentComponent = null)
MtComponent rootComponent, MtComponent parentComponent)
{
Snippet snippet = new();

Expand All @@ -277,11 +276,12 @@ private string ProcessNode(XmlNode node, MtComponentMap availableMtComponents, M
var component = _engine.GetComponent(availableMtComponents[tag].TemplateKey);
var slotContents =
GetSlotContentsBySlotName(childNode, component, availableMtComponents, currentContext,
rootComponent);
parentComponent, rootComponent);

var componentRenderMethodCall = ProcessComponentNode(
childNode.GetHashCode(),
component,
parentComponent,
currentContext,
attributeList,
ProcessNode(
Expand All @@ -292,8 +292,7 @@ private string ProcessNode(XmlNode node, MtComponentMap availableMtComponents, M
parentComponent: component
),
slotContents,
rootComponent: rootComponent,
parentComponent: parentComponent
rootComponent: rootComponent
);

subSnippet.AppendLine(_maniaTemplateLanguage.FeatureBlockStart())
Expand All @@ -314,7 +313,7 @@ private string ProcessNode(XmlNode node, MtComponentMap availableMtComponents, M
case "slot":
var slotName = GetNameFromNodeAttributes(attributeList);
subSnippet.AppendLine(_maniaTemplateLanguage.FeatureBlockStart())
.AppendLine(CreateMethodCall($"__slotRenderer_{slotName.ToLower()}?.Invoke"))
.AppendLine(CreateMethodCall($"__slotRenderer_{slotName.ToLower()}"))
.AppendLine(_maniaTemplateLanguage.FeatureBlockEnd());
break;

Expand Down Expand Up @@ -355,7 +354,7 @@ private string ProcessNode(XmlNode node, MtComponentMap availableMtComponents, M
}

private Dictionary<string, string> GetSlotContentsBySlotName(XmlNode componentNode,
MtComponent component, MtComponentMap availableMtComponents, MtDataContext context, MtComponent rootComponent)
MtComponent component, MtComponentMap availableMtComponents, MtDataContext context, MtComponent parentComponent, MtComponent rootComponent)
{
var contentsByName = new Dictionary<string, XmlNode>();

Expand Down Expand Up @@ -394,7 +393,7 @@ private Dictionary<string, string> GetSlotContentsBySlotName(XmlNode componentNo

return contentsByName.ToDictionary(
kvp => kvp.Key,
kvp => ProcessNode(kvp.Value, availableMtComponents, context, rootComponent)
kvp => ProcessNode(kvp.Value, availableMtComponents, context, rootComponent, parentComponent)
);
}

Expand All @@ -404,12 +403,12 @@ private Dictionary<string, string> GetSlotContentsBySlotName(XmlNode componentNo
private string ProcessComponentNode(
int scope,
MtComponent component,
MtComponent parentComponent,
MtDataContext currentContext,
MtComponentAttributes attributeList,
string componentBody,
IReadOnlyDictionary<string, string> slotContents,
MtComponent rootComponent,
MtComponent? parentComponent = null
MtComponent rootComponent
)
{
foreach (var slotName in component.Slots)
Expand All @@ -423,7 +422,6 @@ private string ProcessComponentNode(
_slots.Add(new MtComponentSlot
{
Scope = scope,
Context = currentContext,
Name = slotName,
RenderMethodT4 = CreateSlotRenderMethod(
component,
Expand All @@ -432,17 +430,17 @@ private string ProcessComponentNode(
slotName,
rootComponent,
slotContent,
parentComponent: parentComponent
parentComponent
)
});
}

var renderMethodName = GetComponentRenderMethodName(component);
var renderMethodName = GetComponentRenderMethodName(component, currentContext);
if (!_renderMethods.ContainsKey(renderMethodName))
{
_renderMethods.Add(
renderMethodName,
CreateComponentRenderMethod(component, renderMethodName, componentBody)
CreateComponentRenderMethod(component, renderMethodName, componentBody, currentContext)
);
}

Expand All @@ -451,6 +449,12 @@ private string ProcessComponentNode(

//Create available arguments
var renderArguments = new List<string>();

//Add local variables to component render method call
foreach (var localVariableName in currentContext.Keys)
{
renderArguments.Add($"{localVariableName}: {localVariableName}");
}

//Attach attributes to render method call
foreach (var (attributeName, attributeValue) in attributeList)
Expand Down Expand Up @@ -490,29 +494,27 @@ private string ProcessComponentNode(

var slotArguments = new HashSet<string>();

//Add local variables
//Add local variables to slot render call
foreach (var localVariableName in currentContext.Keys)
{
slotArguments.Add(localVariableName);
slotArguments.Add($"{localVariableName}: {localVariableName}");
}

//Pass slot renderers
if (parentComponent != null && parentComponent != rootComponent)
if (parentComponent != rootComponent)
{
foreach (var propertyName in parentComponent.Properties.Keys)
{
slotArguments.Add(propertyName);
}

foreach (var parentSlotName in parentComponent.Slots)
{
slotArguments.Add($"__slotRenderer_{parentSlotName}");
slotArguments.Add($"{propertyName}: {propertyName}");
}
}

var joinedSlotArguments = slotArguments.Select(argument => $"{argument}: {argument}");
foreach (var parentSlotName in parentComponent.Slots)
{
slotArguments.Add($"__slotRenderer_{parentSlotName}: __slotRenderer_{parentSlotName}");
}

renderComponentCall.Append(string.Join(", ", joinedSlotArguments)).Append(')');
renderComponentCall.Append(string.Join(", ", slotArguments)).Append(')');

i++;
}
Expand All @@ -528,21 +530,27 @@ private string ProcessComponentNode(
/// <summary>
/// Creates the method which renders the contents of a component.
/// </summary>
private string CreateComponentRenderMethod(MtComponent component, string renderMethodName, string componentBody)
private string CreateComponentRenderMethod(MtComponent component, string renderMethodName, string componentBody, MtDataContext currentContext)
{
var renderMethod = new StringBuilder(_maniaTemplateLanguage.FeatureBlockStart())
.Append("void ")
.Append("private void ")
.Append(renderMethodName)
.Append('(');

//open method arguments
var arguments = new List<string>();

//add component properties as arguments with defaults
AppendComponentPropertiesToMethodArgumentsList(component, arguments);

//Add local variables to component render method call
foreach (var (localVariableName, localVariableType) in currentContext)
{
arguments.Add($"{localVariableType} {localVariableName}");
}

//add slot render methods
AppendSlotRenderArgumentsToList(arguments, component);

//add component properties as arguments with defaults
AppendComponentPropertiesToMethodArgumentsList(component, arguments);

//close method arguments
renderMethod.Append(string.Join(", ", arguments))
Expand Down Expand Up @@ -591,7 +599,7 @@ private static void AppendComponentPropertiesToMethodArgumentsList(MtComponent c
/// </summary>
private static void AppendSlotRenderArgumentsToList(List<string> arguments, MtComponent component)
{
arguments.AddRange(component.Slots.Select(slotName => $"Action __slotRenderer_{slotName} = null"));
arguments.AddRange(component.Slots.Select(slotName => $"Action __slotRenderer_{slotName}"));
}

/// <summary>
Expand Down Expand Up @@ -859,9 +867,9 @@ private static string CreateMethodCall(string methodName, string methodArguments
/// <summary>
/// Returns the method name that renders the given component.
/// </summary>
private string GetComponentRenderMethodName(MtComponent component)
private string GetComponentRenderMethodName(MtComponent component, MtDataContext context)
{
return $"Render_Component_{component.Id()}";
return $"Render_Component_{component.Id()}{context}";
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,20 @@
<label text="this is child content" />
<label text="this is parent content" />
<label text="this is root content" />
<label text="this is child content" />
<label text="this is parent content" />
<label text="this is child content" />
<label text="this is parent content" />
<label text="this is child content" />
<label text="this is parent content" />
<label text="this is root2 content" />
<label text="this is child content" />
<label text="this is child content" />
<label text="this is parent content" />
<label text="this is child content" />
<label text="this is child content" />
<label text="this is parent content" />
<label text="this is child content" />
<label text="this is parent content" />
<label text="this is root3 content" />
</manialink>
Loading

0 comments on commit 4d7d853

Please sign in to comment.