From c0a0a91299f4771047408b86584fd50ba214f388 Mon Sep 17 00:00:00 2001 From: Alexander Raszka Date: Sat, 3 Feb 2024 14:25:41 +0100 Subject: [PATCH] Add use local variables for fallthrough arguments - Add component node names to render method names --- src/ManiaTemplates/Components/MtComponent.cs | 2 +- src/ManiaTemplates/Lib/MtTransformer.cs | 63 +++++++++++-------- .../IntegrationTests/ManialinkEngineTest.cs | 6 +- .../expected/fallthrough-multi-child.xml | 4 ++ .../IntegrationTests/expected/fallthrough.xml | 4 +- .../expected/property-test.xml | 10 +-- .../templates/fallthrough-component.mt | 5 +- .../templates/fallthrough-wrapper.mt | 5 +- tests/ManiaTemplates.Tests/Lib/expected.tt | 35 +++++++---- 9 files changed, 85 insertions(+), 49 deletions(-) diff --git a/src/ManiaTemplates/Components/MtComponent.cs b/src/ManiaTemplates/Components/MtComponent.cs index 64512a4..7c05cc6 100644 --- a/src/ManiaTemplates/Components/MtComponent.cs +++ b/src/ManiaTemplates/Components/MtComponent.cs @@ -258,6 +258,6 @@ private static HashSet GetSlotNamesInTemplate(XmlNode node) public string Id() { - return "MtContext" + GetHashCode().ToString().Replace("-", "N"); + return GetHashCode().ToString().Replace("-", "N"); } } \ No newline at end of file diff --git a/src/ManiaTemplates/Lib/MtTransformer.cs b/src/ManiaTemplates/Lib/MtTransformer.cs index d858d26..477b18b 100644 --- a/src/ManiaTemplates/Lib/MtTransformer.cs +++ b/src/ManiaTemplates/Lib/MtTransformer.cs @@ -210,11 +210,11 @@ private string CreateRenderMethodsBlock() /// /// Creates the slot-render method for a given data context. /// - private string CreateSlotRenderMethod(MtComponent component, int scope, MtDataContext context, string slotName, + private string CreateSlotRenderMethod(string nodeName, MtComponent component, int scope, MtDataContext context, string slotName, string? slotContent = null, MtComponent? parentComponent = null) { var variablesInherited = new List(); - var methodName = GetSlotRenderMethodName(scope, slotName); + var methodName = GetSlotRenderMethodName(nodeName, scope, slotName, context); var methodArguments = new List { @@ -299,6 +299,7 @@ private string ProcessNode(XmlNode node, MtComponentMap availableMtComponents, M var component = _engine.GetComponent(availableMtComponents[tag].TemplateKey); var slotContents = GetSlotContentsBySlotName(childNode, component, availableMtComponents, currentContext); var componentRenderMethodCall = ProcessComponentNode( + childNode.Name, context != currentContext, childNode.GetHashCode(), component, @@ -340,9 +341,12 @@ private string ProcessNode(XmlNode node, MtComponentMap availableMtComponents, M default: { var hasChildren = childNode.HasChildNodes; - if (node.ChildNodes.Count == 1 && parentAttributes != null) + if (node.ChildNodes.Count == 1 && parentAttributes != null && parentComponent != null) { - foreach (var attribute in parentAttributes) + var attributesThatArentProperties = parentAttributes.Where(attribute => + !parentComponent.Properties.ContainsKey(attribute.Key)); + + foreach (var attribute in attributesThatArentProperties) { attributeList.TryAdd(attribute.Key, attribute.Value); } @@ -427,6 +431,7 @@ private Dictionary GetSlotContentsBySlotName(XmlNode componentNo /// Process a node that has been identified as an component. /// private string ProcessComponentNode( + string nodeName, bool newScopeCreated, int scope, MtComponent component, @@ -451,6 +456,7 @@ private string ProcessComponentNode( Context = currentContext, Name = slotName, RenderMethodT4 = CreateSlotRenderMethod( + nodeName, component, scope, currentContext, @@ -461,12 +467,12 @@ private string ProcessComponentNode( }); } - var renderMethodName = GetComponentRenderMethodName(component); + var renderMethodName = GetComponentRenderMethodName(nodeName, component, currentContext); if (!_renderMethods.ContainsKey(renderMethodName)) { _renderMethods.Add( renderMethodName, - CreateComponentRenderMethod(component, renderMethodName, componentBody) + CreateComponentRenderMethod(component, renderMethodName, componentBody, currentContext) ); } @@ -475,23 +481,19 @@ private string ProcessComponentNode( //Create available arguments var renderArguments = new List { "" }; + + //Attach variables from current context, that are not mapped to properties of component + renderArguments.AddRange(from variableName in currentContext.Keys where !attributeList.ContainsKey(variableName) select $"{variableName}: {variableName}"); //Attach attributes to render method call foreach (var (attributeName, attributeValue) in attributeList) { - if (component.Properties.TryGetValue(attributeName, out var value)) - { - if (IsStringType(value)) - { - renderArguments.Add( - $"{attributeName}: {WrapIfString(value, ReplaceCurlyBraces(attributeValue, s => $@"{{({s})}}"))}"); - } - else - { - renderArguments.Add( - $"{attributeName}: {ReplaceCurlyBraces(attributeValue, s => $"({s})")}"); - } - } + if (!component.Properties.TryGetValue(attributeName, out var value)) continue; + + renderArguments.Add( + IsStringType(value) + ? $"{attributeName}: {WrapStringInQuotes(ReplaceCurlyBraces(attributeValue, s => $"{{({s})}}"))}" + : $"{attributeName}: {ReplaceCurlyBraces(attributeValue, s => $"({s})")}"); } renderComponentCall.Append(string.Join(", ", renderArguments)); @@ -509,7 +511,7 @@ private string ProcessComponentNode( renderComponentCall.Append($"__slotRenderer_{slotName}: ") .Append("() => ") - .Append(GetSlotRenderMethodName(scope, slotName)); + .Append(GetSlotRenderMethodName(nodeName, scope, slotName, currentContext)); if (newScopeCreated) { @@ -572,7 +574,7 @@ private string ProcessComponentNode( /// /// Creates the method which renders the contents of a component. /// - 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 ") @@ -587,6 +589,15 @@ private string CreateComponentRenderMethod(MtComponent component, string renderM //add slot render methods AppendSlotRenderArgumentsToList(arguments, component); + + //Add fallthrough properties + foreach (var (variableName, variableType) in currentContext) + { + if (!component.Properties.ContainsKey(variableName)) + { + arguments.Add($"{variableType} {variableName}"); + } + } //add component properties as arguments with defaults AppendComponentPropertiesToMethodArgumentsList(component, arguments); @@ -1045,9 +1056,9 @@ private static string CreateMethodCall(string methodName, string methodArguments /// /// Returns the method name that renders the given component. /// - private string GetComponentRenderMethodName(MtComponent component) + private string GetComponentRenderMethodName(string nodeName, MtComponent component, MtDataContext dataContext) { - return $"Render_Component_{component.Id()}"; + return $"Component_{nodeName}_{dataContext}_{component.Id()}"; } /// @@ -1055,15 +1066,15 @@ private string GetComponentRenderMethodName(MtComponent component) /// private string GetComponentScriptsRenderMethodName(MtComponent component) { - return $"Render_ComponentScript_{component.Id()}"; + return $"ComponentScript_{component.Id()}"; } /// /// Returns the name of the method that renders the slot contents. /// - private static string GetSlotRenderMethodName(int scope, string name) + private static string GetSlotRenderMethodName(string nodeName, int scope, string name, MtDataContext context) { - return $"Render_Slot_{scope.GetHashCode()}_{name}"; + return $"Slot_{name}_of_{nodeName}_in_{context}_{scope.GetHashCode()}"; } /// diff --git a/tests/ManiaTemplates.Tests/IntegrationTests/ManialinkEngineTest.cs b/tests/ManiaTemplates.Tests/IntegrationTests/ManialinkEngineTest.cs index 1a1cde4..de90772 100644 --- a/tests/ManiaTemplates.Tests/IntegrationTests/ManialinkEngineTest.cs +++ b/tests/ManiaTemplates.Tests/IntegrationTests/ManialinkEngineTest.cs @@ -136,7 +136,11 @@ public async void Should_Append_Parent_Attributes_To_Single_Component_Child() _maniaTemplateEngine.AddTemplateFromString("FallthroughComponent", fallthroughComponent); _maniaTemplateEngine.AddTemplateFromString("FallthroughWrapper", fallthroughWrapper); - var template = _maniaTemplateEngine.RenderAsync("FallthroughWrapper", new { }, assemblies).Result; + var template = _maniaTemplateEngine.RenderAsync("FallthroughWrapper", new + { + testString = "unit", + index = -1 + }, assemblies).Result; Assert.Equal(expected, template, ignoreLineEndingDifferences: true); } diff --git a/tests/ManiaTemplates.Tests/IntegrationTests/expected/fallthrough-multi-child.xml b/tests/ManiaTemplates.Tests/IntegrationTests/expected/fallthrough-multi-child.xml index 9d657d0..5d55ded 100644 --- a/tests/ManiaTemplates.Tests/IntegrationTests/expected/fallthrough-multi-child.xml +++ b/tests/ManiaTemplates.Tests/IntegrationTests/expected/fallthrough-multi-child.xml @@ -1,4 +1,8 @@  diff --git a/tests/ManiaTemplates.Tests/IntegrationTests/expected/fallthrough.xml b/tests/ManiaTemplates.Tests/IntegrationTests/expected/fallthrough.xml index 1d54826..38a68f7 100644 --- a/tests/ManiaTemplates.Tests/IntegrationTests/expected/fallthrough.xml +++ b/tests/ManiaTemplates.Tests/IntegrationTests/expected/fallthrough.xml @@ -1,3 +1,5 @@  - diff --git a/tests/ManiaTemplates.Tests/IntegrationTests/expected/property-test.xml b/tests/ManiaTemplates.Tests/IntegrationTests/expected/property-test.xml index 7ecf989..ddbcf60 100644 --- a/tests/ManiaTemplates.Tests/IntegrationTests/expected/property-test.xml +++ b/tests/ManiaTemplates.Tests/IntegrationTests/expected/property-test.xml @@ -1,16 +1,16 @@  - +