1
0
forked from liza/Questionable

Update source gen

This commit is contained in:
Liza 2024-07-21 23:10:16 +02:00
parent 26e881abc3
commit 527fa3440e
Signed by: liza
GPG Key ID: 7199F8D727D55F67
7 changed files with 331 additions and 234 deletions

View File

@ -0,0 +1,26 @@
using Questionable.Model.V1;
using Questionable.QuestPathGenerator;
using Xunit;
namespace QuestPathGenerator.Tests;
public sealed class QuestGeneratorTest
{
[Fact]
public void SyntaxNodeListWithNullValues()
{
var complexCombatData = new ComplexCombatData
{
DataId = 47,
IgnoreQuestMarker = true,
MinimumKillCount = 1,
};
var list =
RoslynShortcuts.SyntaxNodeList(
RoslynShortcuts.AssignmentList(nameof(ComplexCombatData.CompletionQuestVariablesFlags),
complexCombatData.CompletionQuestVariablesFlags)).ToList();
Assert.Empty(list);
}
}

View File

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="xunit" Version="2.5.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\QuestPathGenerator\QuestPathGenerator.csproj" />
</ItemGroup>
</Project>

View File

@ -208,38 +208,45 @@ public class QuestSourceGenerator : ISourceGenerator
private static IEnumerable<SyntaxNodeOrToken> CreateQuestInitializer(ushort questId, QuestRoot quest) private static IEnumerable<SyntaxNodeOrToken> CreateQuestInitializer(ushort questId, QuestRoot quest)
{ {
return new SyntaxNodeOrToken[] try
{ {
InitializerExpression( return new SyntaxNodeOrToken[]
SyntaxKind.ComplexElementInitializerExpression, {
SeparatedList<ExpressionSyntax>( InitializerExpression(
new SyntaxNodeOrToken[] SyntaxKind.ComplexElementInitializerExpression,
{ SeparatedList<ExpressionSyntax>(
LiteralExpression( new SyntaxNodeOrToken[]
SyntaxKind.NumericLiteralExpression, {
Literal(questId)), LiteralExpression(
Token(SyntaxKind.CommaToken), SyntaxKind.NumericLiteralExpression,
ObjectCreationExpression( Literal(questId)),
IdentifierName(nameof(QuestRoot))) Token(SyntaxKind.CommaToken),
.WithInitializer( ObjectCreationExpression(
InitializerExpression( IdentifierName(nameof(QuestRoot)))
SyntaxKind.ObjectInitializerExpression, .WithInitializer(
SeparatedList<ExpressionSyntax>( InitializerExpression(
SyntaxNodeList( SyntaxKind.ObjectInitializerExpression,
AssignmentList(nameof(QuestRoot.Author), quest.Author) SeparatedList<ExpressionSyntax>(
.AsSyntaxNodeOrToken(), SyntaxNodeList(
Assignment(nameof(QuestRoot.Comment), quest.Comment, null) AssignmentList(nameof(QuestRoot.Author), quest.Author)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
AssignmentList(nameof(QuestRoot.TerritoryBlacklist), Assignment(nameof(QuestRoot.Comment), quest.Comment, null)
quest.TerritoryBlacklist).AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
AssignmentExpression( AssignmentList(nameof(QuestRoot.TerritoryBlacklist),
SyntaxKind.SimpleAssignmentExpression, quest.TerritoryBlacklist).AsSyntaxNodeOrToken(),
IdentifierName(nameof(QuestRoot.QuestSequence)), AssignmentExpression(
CreateQuestSequence(quest.QuestSequence)) SyntaxKind.SimpleAssignmentExpression,
)))) IdentifierName(nameof(QuestRoot.QuestSequence)),
})), CreateQuestSequence(quest.QuestSequence))
Token(SyntaxKind.CommaToken) ))))
}; })),
Token(SyntaxKind.CommaToken)
};
}
catch (Exception e)
{
throw new Exception($"QuestGen[{questId}]: {e.Message}", e);
}
} }
private static ExpressionSyntax CreateQuestSequence(List<QuestSequence> sequences) private static ExpressionSyntax CreateQuestSequence(List<QuestSequence> sequences)
@ -321,13 +328,15 @@ public class QuestSourceGenerator : ISourceGenerator
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.Sprint), step.Sprint, emptyStep.Sprint) Assignment(nameof(QuestStep.Sprint), step.Sprint, emptyStep.Sprint)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.IgnoreDistanceToObject), step.IgnoreDistanceToObject, emptyStep.IgnoreDistanceToObject) Assignment(nameof(QuestStep.IgnoreDistanceToObject),
step.IgnoreDistanceToObject, emptyStep.IgnoreDistanceToObject)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.Comment), step.Comment, emptyStep.Comment) Assignment(nameof(QuestStep.Comment), step.Comment, emptyStep.Comment)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.Aetheryte), step.Aetheryte, emptyStep.Aetheryte) Assignment(nameof(QuestStep.Aetheryte), step.Aetheryte, emptyStep.Aetheryte)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.AethernetShard), step.AethernetShard, emptyStep.AethernetShard) Assignment(nameof(QuestStep.AethernetShard), step.AethernetShard,
emptyStep.AethernetShard)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.AetheryteShortcut), step.AetheryteShortcut, Assignment(nameof(QuestStep.AetheryteShortcut), step.AetheryteShortcut,
emptyStep.AetheryteShortcut) emptyStep.AetheryteShortcut)
@ -357,7 +366,8 @@ public class QuestSourceGenerator : ISourceGenerator
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
AssignmentList(nameof(QuestStep.ComplexCombatData), step.ComplexCombatData) AssignmentList(nameof(QuestStep.ComplexCombatData), step.ComplexCombatData)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.CombatDelaySecondsAtStart), step.CombatDelaySecondsAtStart, Assignment(nameof(QuestStep.CombatDelaySecondsAtStart),
step.CombatDelaySecondsAtStart,
emptyStep.CombatDelaySecondsAtStart) emptyStep.CombatDelaySecondsAtStart)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.JumpDestination), step.JumpDestination, Assignment(nameof(QuestStep.JumpDestination), step.JumpDestination,
@ -378,11 +388,14 @@ public class QuestSourceGenerator : ISourceGenerator
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
AssignmentList(nameof(QuestStep.PointMenuChoices), step.PointMenuChoices) AssignmentList(nameof(QuestStep.PointMenuChoices), step.PointMenuChoices)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.PickUpQuestId), step.PickUpQuestId, emptyStep.PickUpQuestId) Assignment(nameof(QuestStep.PickUpQuestId), step.PickUpQuestId,
emptyStep.PickUpQuestId)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.TurnInQuestId), step.TurnInQuestId, emptyStep.TurnInQuestId) Assignment(nameof(QuestStep.TurnInQuestId), step.TurnInQuestId,
emptyStep.TurnInQuestId)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.NextQuestId), step.NextQuestId, emptyStep.NextQuestId) Assignment(nameof(QuestStep.NextQuestId), step.NextQuestId,
emptyStep.NextQuestId)
.AsSyntaxNodeOrToken()))))), .AsSyntaxNodeOrToken()))))),
Token(SyntaxKind.CommaToken), Token(SyntaxKind.CommaToken),
}.ToArray()))); }.ToArray())));

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
@ -14,7 +15,7 @@ public static class RoslynShortcuts
{ {
public static IEnumerable<SyntaxNodeOrToken> SyntaxNodeList(params SyntaxNodeOrToken?[] nodes) public static IEnumerable<SyntaxNodeOrToken> SyntaxNodeList(params SyntaxNodeOrToken?[] nodes)
{ {
nodes = nodes.Where(x => x != null).ToArray(); nodes = nodes.Where(x => x != null && x.Value.RawKind != 0).ToArray();
if (nodes.Length == 0) if (nodes.Length == 0)
return []; return [];
@ -31,222 +32,251 @@ public static class RoslynShortcuts
public static ExpressionSyntax LiteralValue<T>(T? value) public static ExpressionSyntax LiteralValue<T>(T? value)
{ {
if (value is string s) try
return LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(s));
else if (value is bool b)
return LiteralExpression(b ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression);
else if (value is short i16)
return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(i16));
else if (value is int i32)
return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(i32));
else if (value is byte u8)
return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u8));
else if (value is ushort u16)
return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u16));
else if (value is uint u32)
return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u32));
else if (value is float f)
return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(f));
else if (value != null && value.GetType().IsEnum)
return MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName(value.GetType().Name),
IdentifierName(value.GetType().GetEnumName(value)!));
else if (value is Vector3 vector)
{ {
return ObjectCreationExpression( if (value is string s)
IdentifierName(nameof(Vector3))) return LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(s));
.WithArgumentList( else if (value is bool b)
ArgumentList( return LiteralExpression(b ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression);
SeparatedList<ArgumentSyntax>( else if (value is short i16)
new SyntaxNodeOrToken[] return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(i16));
{ else if (value is int i32)
Argument(LiteralValue(vector.X)), return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(i32));
Token(SyntaxKind.CommaToken), else if (value is byte u8)
Argument(LiteralValue(vector.Y)), return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u8));
Token(SyntaxKind.CommaToken), else if (value is ushort u16)
Argument(LiteralValue(vector.Z)) return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u16));
}))); else if (value is uint u32)
} return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u32));
else if (value is AethernetShortcut aethernetShortcut) else if (value is float f)
{ return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(f));
return ObjectCreationExpression( else if (value != null && value.GetType().IsEnum)
IdentifierName(nameof(AethernetShortcut))) return MemberAccessExpression(
.WithInitializer( SyntaxKind.SimpleMemberAccessExpression,
InitializerExpression( IdentifierName(value.GetType().Name),
SyntaxKind.ObjectInitializerExpression, IdentifierName(value.GetType().GetEnumName(value)!));
SeparatedList<ExpressionSyntax>( else if (value is Vector3 vector)
SyntaxNodeList(
Assignment<EAetheryteLocation?>(nameof(AethernetShortcut.From), aethernetShortcut.From,
null)
.AsSyntaxNodeOrToken(),
Assignment<EAetheryteLocation?>(nameof(AethernetShortcut.To), aethernetShortcut.To,
null)
.AsSyntaxNodeOrToken()))));
}
else if (value is ChatMessage chatMessage)
{
ChatMessage emptyMessage = new();
return ObjectCreationExpression(
IdentifierName(nameof(ChatMessage)))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
Assignment(nameof(ChatMessage.ExcelSheet), chatMessage.ExcelSheet,
emptyMessage.ExcelSheet)
.AsSyntaxNodeOrToken(),
Assignment(nameof(ChatMessage.Key), chatMessage.Key,
emptyMessage.Key)
.AsSyntaxNodeOrToken()))));
}
else if (value is DialogueChoice dialogueChoice)
{
DialogueChoice emptyChoice = new();
return ObjectCreationExpression(
IdentifierName(nameof(DialogueChoice)))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
Assignment<EDialogChoiceType?>(nameof(DialogueChoice.Type), dialogueChoice.Type, null)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.ExcelSheet), dialogueChoice.ExcelSheet,
emptyChoice.ExcelSheet)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.Prompt), dialogueChoice.Prompt, emptyChoice.Prompt)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.Yes), dialogueChoice.Yes, emptyChoice.Yes)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.Answer), dialogueChoice.Answer, emptyChoice.Answer)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.DataId), dialogueChoice.DataId, emptyChoice.DataId)
.AsSyntaxNodeOrToken()))));
}
else if (value is JumpDestination jumpDestination)
{
return ObjectCreationExpression(
IdentifierName(nameof(JumpDestination)))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
Assignment<Vector3?>(nameof(JumpDestination.Position), jumpDestination.Position, null)
.AsSyntaxNodeOrToken(),
Assignment(nameof(JumpDestination.StopDistance), jumpDestination.StopDistance, null)
.AsSyntaxNodeOrToken(),
Assignment(nameof(JumpDestination.DelaySeconds), jumpDestination.DelaySeconds, null)
.AsSyntaxNodeOrToken()))));
}
else if (value is ExcelRef excelRef)
{
if (excelRef.Type == ExcelRef.EType.Key)
{ {
return ObjectCreationExpression( return ObjectCreationExpression(
IdentifierName(nameof(ExcelRef))) IdentifierName(nameof(Vector3)))
.WithArgumentList( .WithArgumentList(
ArgumentList( ArgumentList(
SingletonSeparatedList( SeparatedList<ArgumentSyntax>(
Argument(LiteralValue(excelRef.AsKey()))))); new SyntaxNodeOrToken[]
{
Argument(LiteralValue(vector.X)),
Token(SyntaxKind.CommaToken),
Argument(LiteralValue(vector.Y)),
Token(SyntaxKind.CommaToken),
Argument(LiteralValue(vector.Z))
})));
} }
else if (excelRef.Type == ExcelRef.EType.RowId) else if (value is AethernetShortcut aethernetShortcut)
{ {
return ObjectCreationExpression( return ObjectCreationExpression(
IdentifierName(nameof(ExcelRef))) IdentifierName(nameof(AethernetShortcut)))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
Assignment<EAetheryteLocation?>(nameof(AethernetShortcut.From),
aethernetShortcut.From,
null)
.AsSyntaxNodeOrToken(),
Assignment<EAetheryteLocation?>(nameof(AethernetShortcut.To), aethernetShortcut.To,
null)
.AsSyntaxNodeOrToken()))));
}
else if (value is ChatMessage chatMessage)
{
ChatMessage emptyMessage = new();
return ObjectCreationExpression(
IdentifierName(nameof(ChatMessage)))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
Assignment(nameof(ChatMessage.ExcelSheet), chatMessage.ExcelSheet,
emptyMessage.ExcelSheet)
.AsSyntaxNodeOrToken(),
Assignment(nameof(ChatMessage.Key), chatMessage.Key,
emptyMessage.Key)
.AsSyntaxNodeOrToken()))));
}
else if (value is DialogueChoice dialogueChoice)
{
DialogueChoice emptyChoice = new();
return ObjectCreationExpression(
IdentifierName(nameof(DialogueChoice)))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
Assignment<EDialogChoiceType?>(nameof(DialogueChoice.Type), dialogueChoice.Type,
null)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.ExcelSheet), dialogueChoice.ExcelSheet,
emptyChoice.ExcelSheet)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.Prompt), dialogueChoice.Prompt, emptyChoice.Prompt)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.Yes), dialogueChoice.Yes, emptyChoice.Yes)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.Answer), dialogueChoice.Answer, emptyChoice.Answer)
.AsSyntaxNodeOrToken(),
Assignment(nameof(DialogueChoice.DataId), dialogueChoice.DataId, emptyChoice.DataId)
.AsSyntaxNodeOrToken()))));
}
else if (value is JumpDestination jumpDestination)
{
return ObjectCreationExpression(
IdentifierName(nameof(JumpDestination)))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
Assignment<Vector3?>(nameof(JumpDestination.Position), jumpDestination.Position,
null)
.AsSyntaxNodeOrToken(),
Assignment(nameof(JumpDestination.StopDistance), jumpDestination.StopDistance, null)
.AsSyntaxNodeOrToken(),
Assignment(nameof(JumpDestination.DelaySeconds), jumpDestination.DelaySeconds, null)
.AsSyntaxNodeOrToken()))));
}
else if (value is ExcelRef excelRef)
{
if (excelRef.Type == ExcelRef.EType.Key)
{
return ObjectCreationExpression(
IdentifierName(nameof(ExcelRef)))
.WithArgumentList(
ArgumentList(
SingletonSeparatedList(
Argument(LiteralValue(excelRef.AsKey())))));
}
else if (excelRef.Type == ExcelRef.EType.RowId)
{
return ObjectCreationExpression(
IdentifierName(nameof(ExcelRef)))
.WithArgumentList(
ArgumentList(
SingletonSeparatedList(
Argument(LiteralValue(excelRef.AsRowId())))));
}
else
throw new Exception($"Unsupported ExcelRef type {excelRef.Type}");
}
else if (value is ComplexCombatData complexCombatData)
{
var emptyData = new ComplexCombatData();
return ObjectCreationExpression(
IdentifierName(nameof(ComplexCombatData)))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
Assignment(nameof(ComplexCombatData.DataId), complexCombatData.DataId,
emptyData.DataId)
.AsSyntaxNodeOrToken(),
Assignment(nameof(ComplexCombatData.MinimumKillCount),
complexCombatData.MinimumKillCount, emptyData.MinimumKillCount)
.AsSyntaxNodeOrToken(),
Assignment(nameof(ComplexCombatData.RewardItemId), complexCombatData.RewardItemId,
emptyData.RewardItemId)
.AsSyntaxNodeOrToken(),
Assignment(nameof(ComplexCombatData.RewardItemCount),
complexCombatData.RewardItemCount,
emptyData.RewardItemCount)
.AsSyntaxNodeOrToken(),
AssignmentList(nameof(ComplexCombatData.CompletionQuestVariablesFlags),
complexCombatData.CompletionQuestVariablesFlags),
Assignment(nameof(ComplexCombatData.IgnoreQuestMarker),
complexCombatData.IgnoreQuestMarker,
emptyData.IgnoreQuestMarker)
.AsSyntaxNodeOrToken()))));
}
else if (value is QuestWorkValue qwv)
{
return ObjectCreationExpression(
IdentifierName(nameof(QuestWorkValue)))
.WithArgumentList( .WithArgumentList(
ArgumentList( ArgumentList(
SingletonSeparatedList( SeparatedList<ArgumentSyntax>(
Argument(LiteralValue(excelRef.AsRowId()))))); new SyntaxNodeOrToken[]
{
Argument(LiteralValue(qwv.High)),
Token(SyntaxKind.CommaToken),
Argument(LiteralValue(qwv.Low))
})));
} }
else else if (value is List<QuestWorkValue> list)
throw new Exception($"Unsupported ExcelRef type {excelRef.Type}"); {
return CollectionExpression(
SeparatedList<CollectionElementSyntax>(
SyntaxNodeList(list.Select(x => ExpressionElement(
LiteralValue(x)).AsSyntaxNodeOrToken()).ToArray())));
}
else if (value is null)
return LiteralExpression(SyntaxKind.NullLiteralExpression);
} }
else if (value is ComplexCombatData complexCombatData) catch (Exception e)
{ {
var emptyData = new ComplexCombatData(); throw new Exception($"Unable to handle literal [{value}]: {e.StackTrace}", e);
return ObjectCreationExpression(
IdentifierName(nameof(ComplexCombatData)))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(
SyntaxNodeList(
Assignment(nameof(ComplexCombatData.DataId), complexCombatData.DataId, emptyData.DataId)
.AsSyntaxNodeOrToken(),
Assignment(nameof(ComplexCombatData.MinimumKillCount),
complexCombatData.MinimumKillCount, emptyData.MinimumKillCount)
.AsSyntaxNodeOrToken(),
Assignment(nameof(ComplexCombatData.RewardItemId), complexCombatData.RewardItemId,
emptyData.RewardItemId)
.AsSyntaxNodeOrToken(),
Assignment(nameof(ComplexCombatData.RewardItemCount), complexCombatData.RewardItemCount,
emptyData.RewardItemCount)
.AsSyntaxNodeOrToken(),
AssignmentList(nameof(ComplexCombatData.CompletionQuestVariablesFlags),
complexCombatData.CompletionQuestVariablesFlags),
Assignment(nameof(ComplexCombatData.IgnoreQuestMarker),
complexCombatData.IgnoreQuestMarker,
emptyData.IgnoreQuestMarker)
.AsSyntaxNodeOrToken()))));
} }
else if (value is QuestWorkValue qwv)
{ throw new Exception($"Unsupported data type {value.GetType()} = {value}");
return ObjectCreationExpression(
IdentifierName(nameof(QuestWorkValue)))
.WithArgumentList(
ArgumentList(
SeparatedList<ArgumentSyntax>(
new SyntaxNodeOrToken[]
{
Argument(LiteralValue(qwv.High)),
Token(SyntaxKind.CommaToken),
Argument(LiteralValue(qwv.Low))
})));
}
else if (value is List<QuestWorkValue> list)
{
return CollectionExpression(
SeparatedList<CollectionElementSyntax>(
SyntaxNodeList(list.Select(x => ExpressionElement(
LiteralValue(x)).AsSyntaxNodeOrToken()).ToArray())));
}
else if (value is null)
return LiteralExpression(SyntaxKind.NullLiteralExpression);
else
throw new Exception($"Unsupported data type {value.GetType()} = {value}");
} }
public static AssignmentExpressionSyntax? Assignment<T>(string name, T? value, T? defaultValue) public static AssignmentExpressionSyntax? Assignment<T>(string name, T? value, T? defaultValue)
{ {
if (value == null && defaultValue == null) try
return null; {
if (value == null && defaultValue == null)
return null;
if (value != null && defaultValue != null && value.Equals(defaultValue)) if (value != null && defaultValue != null && value.Equals(defaultValue))
return null; return null;
return AssignmentExpression( return AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression, SyntaxKind.SimpleAssignmentExpression,
IdentifierName(name), IdentifierName(name),
LiteralValue(value)); LiteralValue(value));
}
catch (Exception e)
{
throw new Exception($"Unable to handle assignment [{name}]: {e.Message}", e);
}
} }
public static AssignmentExpressionSyntax? AssignmentList<T>(string name, IEnumerable<T> value) public static AssignmentExpressionSyntax? AssignmentList<T>(string name, IEnumerable<T>? value)
{ {
IEnumerable<T> list = value.ToList(); try
if (!list.Any()) {
return null; if (value == null)
return null;
return AssignmentExpression( IEnumerable<T> list = value.ToList();
SyntaxKind.SimpleAssignmentExpression, if (!list.Any())
IdentifierName(name), return null;
CollectionExpression(
SeparatedList<CollectionElementSyntax>( return AssignmentExpression(
SyntaxNodeList(list.Select(x => ExpressionElement( SyntaxKind.SimpleAssignmentExpression,
LiteralValue(x)).AsSyntaxNodeOrToken()).ToArray()) IdentifierName(name),
))); CollectionExpression(
SeparatedList<CollectionElementSyntax>(
SyntaxNodeList(list.Select(x => ExpressionElement(
LiteralValue(x)).AsSyntaxNodeOrToken()).ToArray())
)));
}
catch (Exception e)
{
throw new Exception($"Unable to handle list [{name}]: {e.StackTrace}", e);
}
} }
public static SyntaxNodeOrToken? AsSyntaxNodeOrToken(this SyntaxNode? node) public static SyntaxNodeOrToken? AsSyntaxNodeOrToken(this SyntaxNode? node)

View File

@ -9,8 +9,8 @@
}, },
"System.Text.Json": { "System.Text.Json": {
"type": "Transitive", "type": "Transitive",
"resolved": "8.0.3", "resolved": "8.0.4",
"contentHash": "hpagS9joOwv6efWfrMmV9MjQXpiXZH72PgN067Ysfr6AWMSD1/1hEcvh/U5mUpPLezEWsOJSuVrmqDIVD958iA==", "contentHash": "bAkhgDJ88XTsqczoxEMliSrpijKZHhbJQldhAmObj/RbrN3sU5dcokuXmWJWsdQAhiMJ9bTayWsL1C9fbbCRhw==",
"dependencies": { "dependencies": {
"System.Text.Encodings.Web": "8.0.0" "System.Text.Encodings.Web": "8.0.0"
} }
@ -18,7 +18,7 @@
"questionable.model": { "questionable.model": {
"type": "Project", "type": "Project",
"dependencies": { "dependencies": {
"System.Text.Json": "[8.0.3, )" "System.Text.Json": "[8.0.4, )"
} }
} }
} }

View File

@ -12,5 +12,5 @@ public sealed class ComplexCombatData
public uint? RewardItemId { get; set; } public uint? RewardItemId { get; set; }
public int? RewardItemCount { get; set; } public int? RewardItemCount { get; set; }
public IList<short?> CompletionQuestVariablesFlags { get; set; } = new List<short?>(); public IList<short?> CompletionQuestVariablesFlags { get; set; } = new List<short?>();
public bool IgnoreQuestMarker { get; } public bool IgnoreQuestMarker { get; set; }
} }

View File

@ -10,6 +10,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPaths", "QuestPathGene
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Questionable.Model", "Questionable.Model\Questionable.Model.csproj", "{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Questionable.Model", "Questionable.Model\Questionable.Model.csproj", "{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPathGenerator.Tests", "QuestPathGenerator.Tests\QuestPathGenerator.Tests.csproj", "{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -36,5 +38,9 @@ Global
{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|Any CPU.Build.0 = Debug|Any CPU {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|Any CPU.ActiveCfg = Release|Any CPU {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|Any CPU.Build.0 = Release|Any CPU {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|Any CPU.Build.0 = Release|Any CPU
{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal