mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-21 08:35:43 +00:00
ZoneCodeGenerator: Add tests for reordering, scriptstring, string
This commit is contained in:
parent
6ca7f18f9f
commit
73424c9bc1
@ -1,4 +1,5 @@
|
|||||||
using ZoneCodeGenerator.Domain.Evaluation;
|
using System.Linq;
|
||||||
|
using ZoneCodeGenerator.Domain.Evaluation;
|
||||||
|
|
||||||
namespace ZoneCodeGenerator.Domain.Information
|
namespace ZoneCodeGenerator.Domain.Information
|
||||||
{
|
{
|
||||||
@ -6,13 +7,30 @@ namespace ZoneCodeGenerator.Domain.Information
|
|||||||
{
|
{
|
||||||
public StructureInformation StructureType { get; }
|
public StructureInformation StructureType { get; }
|
||||||
public Variable Member { get; set; }
|
public Variable Member { get; set; }
|
||||||
|
public bool IsString { get; set; }
|
||||||
public bool IsScriptString { get; set; }
|
public bool IsScriptString { get; set; }
|
||||||
public IEvaluation Condition { 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)
|
public MemberInformation(Variable member, StructureInformation structureType)
|
||||||
{
|
{
|
||||||
Member = member;
|
Member = member;
|
||||||
StructureType = structureType;
|
StructureType = structureType;
|
||||||
|
IsString = false;
|
||||||
IsScriptString = false;
|
IsScriptString = false;
|
||||||
Condition = null;
|
Condition = null;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace ZoneCodeGenerator.Domain.Information
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<StructureInformation> Usages { get; }
|
public List<StructureInformation> Usages { get; }
|
||||||
public List<MemberInformation> OrderedMembers { get; }
|
public List<MemberInformation> OrderedMembers { get; set; }
|
||||||
public bool NonEmbeddedReferenceExists { get; set; }
|
public bool NonEmbeddedReferenceExists { get; set; }
|
||||||
public bool SinglePointerReferenceExists { get; set; }
|
public bool SinglePointerReferenceExists { get; set; }
|
||||||
public bool ArrayPointerReferenceExists { get; set; }
|
public bool ArrayPointerReferenceExists { get; set; }
|
||||||
|
@ -20,46 +20,21 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
|
|||||||
|
|
||||||
memberInformation.StructureType.Usages.Add(information);
|
memberInformation.StructureType.Usages.Add(information);
|
||||||
|
|
||||||
if (IsNonEmbeddedReference(memberInformation.Member))
|
if (memberInformation.IsNonEmbeddedReference)
|
||||||
memberInformation.StructureType.NonEmbeddedReferenceExists = true;
|
memberInformation.StructureType.NonEmbeddedReferenceExists = true;
|
||||||
|
|
||||||
if (IsSinglePointerReference(memberInformation.Member))
|
if (memberInformation.IsSinglePointerReference)
|
||||||
memberInformation.StructureType.SinglePointerReferenceExists = true;
|
memberInformation.StructureType.SinglePointerReferenceExists = true;
|
||||||
|
|
||||||
if (IsArrayPointerReference(memberInformation.Member))
|
if (memberInformation.IsArrayPointerReference)
|
||||||
memberInformation.StructureType.ArrayPointerReferenceExists = true;
|
memberInformation.StructureType.ArrayPointerReferenceExists = true;
|
||||||
|
|
||||||
if (IsArrayReference(memberInformation.Member))
|
if (memberInformation.IsArrayReference)
|
||||||
memberInformation.StructureType.ArrayReferenceExists = true;
|
memberInformation.StructureType.ArrayReferenceExists = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using ZoneCodeGenerator.Domain;
|
||||||
|
using ZoneCodeGenerator.Domain.Information;
|
||||||
using ZoneCodeGenerator.Parsing.Matching;
|
using ZoneCodeGenerator.Parsing.Matching;
|
||||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||||
using ZoneCodeGenerator.Parsing.Testing;
|
using ZoneCodeGenerator.Parsing.Testing;
|
||||||
@ -12,22 +15,83 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
|||||||
private const string TypeNameToken = "typeName";
|
private const string TypeNameToken = "typeName";
|
||||||
private const string ReorderMemberNameToken = "member";
|
private const string ReorderMemberNameToken = "member";
|
||||||
|
|
||||||
private static readonly TokenMatcher[] matchers = {
|
private static readonly TokenMatcher[] matchers =
|
||||||
|
{
|
||||||
new MatcherLiteral("reorder"),
|
new MatcherLiteral("reorder"),
|
||||||
new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)),
|
new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)),
|
||||||
new MatcherLiteral(":"),
|
new MatcherLiteral(":"),
|
||||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherName().WithName(ReorderMemberNameToken)),
|
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple,
|
||||||
|
new MatcherName().WithName(ReorderMemberNameToken)),
|
||||||
new MatcherLiteral(";")
|
new MatcherLiteral(";")
|
||||||
};
|
};
|
||||||
|
|
||||||
public TestReorder() : base(matchers)
|
public TestReorder() : base(matchers)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessMatch(ICommandParserState state)
|
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<MemberInformation>(typeToReorder.OrderedMembers);
|
||||||
|
|
||||||
|
// Create a list that will be the sorted list at the end.
|
||||||
|
var sortedMembers = new List<MemberInformation>(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,7 +27,35 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
|||||||
|
|
||||||
protected override void ProcessMatch(ICommandParserState state)
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using ZoneCodeGenerator.Domain;
|
||||||
using ZoneCodeGenerator.Parsing.Matching;
|
using ZoneCodeGenerator.Parsing.Matching;
|
||||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||||
using ZoneCodeGenerator.Parsing.Testing;
|
using ZoneCodeGenerator.Parsing.Testing;
|
||||||
@ -27,7 +28,40 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
|||||||
|
|
||||||
protected override void ProcessMatch(ICommandParserState state)
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user