From 73424c9bc1e60cbdabc902ac54fe432705cb9639 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 10 Nov 2019 22:14:01 +0100 Subject: [PATCH] ZoneCodeGenerator: Add tests for reordering, scriptstring, string --- .../Domain/Information/MemberInformation.cs | 22 +++++- .../Information/StructureInformation.cs | 2 +- .../PostProcessor/PostProcessorUsages.cs | 33 +-------- .../Parsing/CommandFile/Tests/TestReorder.cs | 74 +++++++++++++++++-- .../CommandFile/Tests/TestScriptString.cs | 28 +++++++ .../Parsing/CommandFile/Tests/TestString.cs | 34 +++++++++ 6 files changed, 156 insertions(+), 37 deletions(-) diff --git a/src/ZoneCodeGenerator/Domain/Information/MemberInformation.cs b/src/ZoneCodeGenerator/Domain/Information/MemberInformation.cs index 30444395..7279c6d5 100644 --- a/src/ZoneCodeGenerator/Domain/Information/MemberInformation.cs +++ b/src/ZoneCodeGenerator/Domain/Information/MemberInformation.cs @@ -1,4 +1,5 @@ -using ZoneCodeGenerator.Domain.Evaluation; +using System.Linq; +using ZoneCodeGenerator.Domain.Evaluation; namespace ZoneCodeGenerator.Domain.Information { @@ -6,15 +7,32 @@ namespace ZoneCodeGenerator.Domain.Information { public StructureInformation StructureType { get; } public Variable Member { get; set; } + public bool IsString { get; set; } public bool IsScriptString { get; set; } public IEvaluation Condition { get; set; } + public bool IsNonEmbeddedReference => Member.VariableType.References.Any(); + + public bool IsSinglePointerReference => Member.VariableType.References.Any() + && Member.VariableType.References.Last() is ReferenceTypePointer + pointerReference + && !pointerReference.IsArray; + + public bool IsArrayPointerReference => Member.VariableType.References.Any() + && Member.VariableType.References.Last() is ReferenceTypePointer + pointerReference + && pointerReference.IsArray; + + public bool IsArrayReference => Member.VariableType.References.Any() + && Member.VariableType.References.Last() is ReferenceTypeArray; + public MemberInformation(Variable member, StructureInformation structureType) { Member = member; StructureType = structureType; + IsString = false; IsScriptString = false; Condition = null; } } -} +} \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Domain/Information/StructureInformation.cs b/src/ZoneCodeGenerator/Domain/Information/StructureInformation.cs index bd65c692..83a0647b 100644 --- a/src/ZoneCodeGenerator/Domain/Information/StructureInformation.cs +++ b/src/ZoneCodeGenerator/Domain/Information/StructureInformation.cs @@ -24,7 +24,7 @@ namespace ZoneCodeGenerator.Domain.Information } public List Usages { get; } - public List OrderedMembers { get; } + public List OrderedMembers { get; set; } public bool NonEmbeddedReferenceExists { get; set; } public bool SinglePointerReferenceExists { get; set; } public bool ArrayPointerReferenceExists { get; set; } diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorUsages.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorUsages.cs index afee570f..411e0708 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorUsages.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorUsages.cs @@ -20,46 +20,21 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor memberInformation.StructureType.Usages.Add(information); - if (IsNonEmbeddedReference(memberInformation.Member)) + if (memberInformation.IsNonEmbeddedReference) memberInformation.StructureType.NonEmbeddedReferenceExists = true; - if (IsSinglePointerReference(memberInformation.Member)) + if (memberInformation.IsSinglePointerReference) memberInformation.StructureType.SinglePointerReferenceExists = true; - if (IsArrayPointerReference(memberInformation.Member)) + if (memberInformation.IsArrayPointerReference) memberInformation.StructureType.ArrayPointerReferenceExists = true; - if (IsArrayReference(memberInformation.Member)) + if (memberInformation.IsArrayReference) memberInformation.StructureType.ArrayReferenceExists = true; } } return true; } - - private static bool IsNonEmbeddedReference(Variable var) - { - return var.VariableType.References.Any(); - } - - private static bool IsSinglePointerReference(Variable var) - { - return var.VariableType.References.Any() - && var.VariableType.References.Last() is ReferenceTypePointer pointerReference - && !pointerReference.IsArray; - } - - private static bool IsArrayPointerReference(Variable var) - { - return var.VariableType.References.Any() - && var.VariableType.References.Last() is ReferenceTypePointer pointerReference - && pointerReference.IsArray; - } - - private static bool IsArrayReference(Variable var) - { - return var.VariableType.References.Any() - && var.VariableType.References.Last() is ReferenceTypeArray; - } } } \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReorder.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReorder.cs index 2c327250..3a58c64f 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReorder.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReorder.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; +using ZoneCodeGenerator.Domain; +using ZoneCodeGenerator.Domain.Information; using ZoneCodeGenerator.Parsing.Matching; using ZoneCodeGenerator.Parsing.Matching.Matchers; using ZoneCodeGenerator.Parsing.Testing; @@ -12,22 +15,83 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests private const string TypeNameToken = "typeName"; private const string ReorderMemberNameToken = "member"; - private static readonly TokenMatcher[] matchers = { + private static readonly TokenMatcher[] matchers = + { new MatcherLiteral("reorder"), - new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)), + new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)), new MatcherLiteral(":"), - new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherName().WithName(ReorderMemberNameToken)), + new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, + new MatcherName().WithName(ReorderMemberNameToken)), new MatcherLiteral(";") }; public TestReorder() : base(matchers) { - } protected override void ProcessMatch(ICommandParserState state) { + StructureInformation typeToReorder; + if (HasMatcherTokens(TypeNameToken)) + { + // If there was a type specified then use it to reorder. + var typeName = NextMatch(TypeNameToken); + var typeNameParts = typeName.Split(new[] {"::"}, StringSplitOptions.None); + + if (!state.GetTypenameAndMembersFromParts(typeNameParts, out typeToReorder, out var memberList)) + { + throw new TestFailedException($"Could not parse type with name '{typeName}'."); + } + + // If there were members specified, use the type of the member. + if (memberList.Any()) + { + var lastMember = memberList.Last(); + + typeToReorder = lastMember.StructureType + ?? throw new TestFailedException( + $"Cannot reorder type of '{lastMember.Member.Name}'. Type is not a data type with members."); + } + } + else if (state.DataTypeInUse != null) + { + // If there was no type specified try to use the one currently in use. + typeToReorder = state.DataTypeInUse; + } + else + { + // No type specified and no type in use. We don't know what to reorder. + throw new TestFailedException("A type to reorder needs to be specified."); + } + + // Create a pool of all members that have not been sorted yet. + var memberPool = new List(typeToReorder.OrderedMembers); + + // Create a list that will be the sorted list at the end. + var sortedMembers = new List(memberPool.Count); + + string nextMemberName; + while ((nextMemberName = NextMatch(ReorderMemberNameToken)) != null) + { + var nextMember = + memberPool.FirstOrDefault(information => information.Member.Name.Equals(nextMemberName)); + + if (nextMember == null) + { + throw new TestFailedException( + $"Cannot find member with name '{nextMemberName}' in type '{typeToReorder.Type.FullName}'."); + } + + sortedMembers.Add(nextMember); + memberPool.Remove(nextMember); + } + + // Insert members that have not been mentioned at the end. + sortedMembers.AddRange(memberPool); + + // Apply new members to the StructureInformation + typeToReorder.OrderedMembers = sortedMembers; } } -} +} \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestScriptString.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestScriptString.cs index 3063fec8..797a7049 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestScriptString.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestScriptString.cs @@ -27,7 +27,35 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests protected override void ProcessMatch(ICommandParserState state) { + var typeName = NextMatch(MemberTypeNameToken); + var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None); + if (state.DataTypeInUse != null && + state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var memberList)) + { + // Do nothing + } + else if (state.GetTypenameAndMembersFromParts(typeNameParts, out _, out memberList)) + { + // Do nothing + } + else + { + throw new TestFailedException($"Could not find type '{typeName}'."); + } + + if (memberList == null || !memberList.Any()) + { + throw new TestFailedException("Need to specify a member when trying to set to a script string."); + } + + var lastMember = memberList.Last(); + if (!(lastMember.Member.VariableType.Type is DataTypeBaseType)) + { + throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is not a base type and therefore cannot be a script string."); + } + + lastMember.IsScriptString = true; } } } diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs index 998a2e97..b777c72a 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using ZoneCodeGenerator.Domain; using ZoneCodeGenerator.Parsing.Matching; using ZoneCodeGenerator.Parsing.Matching.Matchers; using ZoneCodeGenerator.Parsing.Testing; @@ -27,7 +28,40 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests protected override void ProcessMatch(ICommandParserState state) { + var typeName = NextMatch(MemberTypeNameToken); + var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None); + if (state.DataTypeInUse != null && + state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var memberList)) + { + // Do nothing + } + else if (state.GetTypenameAndMembersFromParts(typeNameParts, out _, out memberList)) + { + // Do nothing + } + else + { + throw new TestFailedException($"Could not find type '{typeName}'."); + } + + if (memberList == null || !memberList.Any()) + { + throw new TestFailedException("Need to specify a member when trying to set to a string."); + } + + var lastMember = memberList.Last(); + if (lastMember.Member.VariableType.Type != DataTypeBaseType.CHAR) + { + throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is not char type and therefore cannot be a string."); + } + + if (!lastMember.IsSinglePointerReference) + { + throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is a single pointer reference and therefore cannot be a string."); + } + + lastMember.IsString = true; } } }