mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
127 lines
5.1 KiB
C#
127 lines
5.1 KiB
C#
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;
|
|
|
|
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
|
{
|
|
class TestReorder : AbstractTokenTest<ICommandParserState>
|
|
{
|
|
private const string TypeNameToken = "typeName";
|
|
private const string ReorderMemberNameToken = "member";
|
|
private const string TokenFindFirst = "findFirst";
|
|
|
|
private static readonly TokenMatcher[] matchers =
|
|
{
|
|
new MatcherLiteral("reorder"),
|
|
new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)),
|
|
new MatcherLiteral(":"),
|
|
new MatcherGroupOptional(new MatcherLiteral(".", ".", ".").WithName(TokenFindFirst)),
|
|
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<MemberInformation>(typeToReorder.OrderedMembers);
|
|
|
|
// Create a list that will be the sorted list at the end.
|
|
var sortedMembers = new List<MemberInformation>(memberPool.Count);
|
|
|
|
if (HasMatcherTokens(TokenFindFirst))
|
|
{
|
|
var firstMemberName = NextMatch(ReorderMemberNameToken);
|
|
var firstMember =
|
|
memberPool.FirstOrDefault(information => information.Member.Name.Equals(firstMemberName));
|
|
|
|
if (firstMember == null)
|
|
{
|
|
throw new TestFailedException(
|
|
$"Cannot find member with name '{firstMemberName}' in type '{typeToReorder.Type.FullName}'.");
|
|
}
|
|
|
|
var firstMemberIndex = memberPool.IndexOf(firstMember);
|
|
sortedMembers.AddRange(memberPool.GetRange(0, firstMemberIndex + 1));
|
|
memberPool.RemoveRange(0, firstMemberIndex + 1);
|
|
}
|
|
|
|
string nextMemberName;
|
|
while ((nextMemberName = NextMatch(ReorderMemberNameToken)) != null)
|
|
{
|
|
var nextMember =
|
|
memberPool.FirstOrDefault(information => information.Member.Name.Equals(nextMemberName));
|
|
|
|
if (nextMember != null)
|
|
{
|
|
sortedMembers.Add(nextMember);
|
|
memberPool.Remove(nextMember);
|
|
}
|
|
else
|
|
{
|
|
nextMember =
|
|
sortedMembers.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.Remove(nextMember);
|
|
sortedMembers.Add(nextMember);
|
|
}
|
|
}
|
|
|
|
// Insert members that have not been mentioned at the end.
|
|
sortedMembers.AddRange(memberPool);
|
|
|
|
// Apply new members to the StructureInformation
|
|
typeToReorder.OrderedMembers = sortedMembers;
|
|
}
|
|
}
|
|
} |