using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Questionable.Model.Common; using Questionable.Model.Gathering; using Questionable.Model.Questing; using Questionable.QuestPathGenerator.RoslynElements; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace Questionable.QuestPathGenerator; public static class RoslynShortcuts { public static IEnumerable<SyntaxNodeOrToken> SyntaxNodeList(params SyntaxNodeOrToken?[] nodes) { nodes = nodes.Where(x => x != null && x.Value.RawKind != 0).ToArray(); if (nodes.Length == 0) return []; List<SyntaxNodeOrToken> list = new(); for (int i = 0; i < nodes.Length; ++i) { if (i > 0) list.Add(Token(SyntaxKind.CommaToken)); list.Add(nodes[i].GetValueOrDefault()); } return list; } public static ExpressionSyntax LiteralValue<T>(T? value) { try { return value switch { null => LiteralExpression(SyntaxKind.NullLiteralExpression), string s => LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(s)), bool b => LiteralExpression(b ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression), short i16 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(i16)), int i32 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(i32)), byte u8 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u8)), ushort u16 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u16)), uint u32 => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u32)), float f => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(f)), QuestStep step => step.ToExpressionSyntax(), QuestId questId => questId.ToExpressionSyntax(), LeveId leveId => leveId.ToExpressionSyntax(), SatisfactionSupplyNpcId satisfactionSupplyNpcId => satisfactionSupplyNpcId.ToExpressionSyntax(), Vector3 vector => vector.ToExpressionSyntax(), AethernetShortcut aethernetShortcut => aethernetShortcut.ToExpressionSyntax(), ChatMessage chatMessage => chatMessage.ToExpressionSyntax(), DialogueChoice dialogueChoice => dialogueChoice.ToExpressionSyntax(), JumpDestination jumpDestination => jumpDestination.ToExpressionSyntax(), ExcelRef excelRef => excelRef.ToExpressionSyntax(), ComplexCombatData complexCombatData => complexCombatData.ToExpressionSyntax(), QuestWorkValue questWorkValue => questWorkValue.ToExpressionSyntax(), List<QuestWorkValue> list => list.ToExpressionSyntax(), // TODO fix in AssignmentList SkipConditions skipConditions => skipConditions.ToExpressionSyntax(), SkipStepConditions skipStepConditions => skipStepConditions.ToExpressionSyntax(), SkipItemConditions skipItemCondition => skipItemCondition.ToExpressionSyntax(), NearPositionCondition nearPositionCondition => nearPositionCondition.ToExpressionSyntax(), SkipAetheryteCondition skipAetheryteCondition => skipAetheryteCondition.ToExpressionSyntax(), GatheredItem gatheredItem => gatheredItem.ToExpressionSyntax(), GatheringNodeGroup nodeGroup => nodeGroup.ToExpressionSyntax(), GatheringNode nodeLocation => nodeLocation.ToExpressionSyntax(), GatheringLocation location => location.ToExpressionSyntax(), not null when value.GetType().IsEnum => MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(value.GetType().Name), IdentifierName(value.GetType().GetEnumName(value)!)), _ => throw new Exception($"Unsupported data type {value.GetType()} = {value}") }; } catch (Exception e) { throw new Exception($"Unable to handle literal [{value}]: {e}", e); } } public static AssignmentExpressionSyntax? Assignment<T>(string name, T? value, T? defaultValue) { try { if (value == null && defaultValue == null) return null; if (value != null && defaultValue != null && value.Equals(defaultValue)) return null; return AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(name), LiteralValue(value)); } catch (Exception e) { throw new Exception($"Unable to handle assignment [{name}]: {e}", e); } } public static AssignmentExpressionSyntax? AssignmentList<T>(string name, IEnumerable<T>? value) { try { if (value == null) return null; IEnumerable<T> list = value.ToList(); if (!list.Any()) return null; return AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, 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}", e); } } public static SyntaxNodeOrToken? AsSyntaxNodeOrToken(this SyntaxNode? node) { if (node == null) return null; return node; } }