using System; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace CapnpC.CSharp.Generator.CodeGen { static class SyntaxHelpers { public static string MakeUpperCamel(string name) => $"{char.ToUpperInvariant(name[0])}{name.Substring(1)}"; public static string MakeLowerCamel(string name) => $"{char.ToLowerInvariant(name[0])}{name.Substring(1)}"; public static readonly SyntaxToken Async = Token(SyntaxKind.AsyncKeyword); public static readonly SyntaxToken Public = Token(SyntaxKind.PublicKeyword); public static readonly SyntaxToken Private = Token(SyntaxKind.PrivateKeyword); public static readonly SyntaxToken Readonly = Token(SyntaxKind.ReadOnlyKeyword); public static readonly SyntaxToken Static = Token(SyntaxKind.StaticKeyword); public static readonly SyntaxToken Override = Token(SyntaxKind.OverrideKeyword); public static readonly SyntaxToken Partial = Token(SyntaxKind.PartialKeyword); public static readonly SyntaxToken This = Token(SyntaxKind.ThisKeyword); public static TypeSyntax NonNullableType(Type type) { switch (0) { case 0 when type == typeof(bool): return PredefinedType(Token(SyntaxKind.BoolKeyword)); case 0 when type == typeof(sbyte): return PredefinedType(Token(SyntaxKind.SByteKeyword)); case 0 when type == typeof(byte): return PredefinedType(Token(SyntaxKind.ByteKeyword)); case 0 when type == typeof(short): return PredefinedType(Token(SyntaxKind.ShortKeyword)); case 0 when type == typeof(ushort): return PredefinedType(Token(SyntaxKind.UShortKeyword)); case 0 when type == typeof(int): return PredefinedType(Token(SyntaxKind.IntKeyword)); case 0 when type == typeof(uint): return PredefinedType(Token(SyntaxKind.UIntKeyword)); case 0 when type == typeof(long): return PredefinedType(Token(SyntaxKind.LongKeyword)); case 0 when type == typeof(ulong): return PredefinedType(Token(SyntaxKind.ULongKeyword)); case 0 when type == typeof(float): return PredefinedType(Token(SyntaxKind.FloatKeyword)); case 0 when type == typeof(double): return PredefinedType(Token(SyntaxKind.DoubleKeyword)); case 0 when type == typeof(string): return PredefinedType(Token(SyntaxKind.StringKeyword)); case 0 when type == typeof(object): return PredefinedType(Token(SyntaxKind.ObjectKeyword)); case 0 when type.IsGenericType: return GenericName(type.Name.Substring(0, type.Name.IndexOf('`'))) .AddTypeArgumentListArguments(type.GetGenericArguments().Select(NonNullableType).ToArray()); default: return ParseTypeName(type.Name); } } public static TypeSyntax NonNullableType() => NonNullableType(typeof(T)); public static ExpressionSyntax ValueOf(object value) { switch (value) { case bool x: return LiteralExpression(x ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression); case sbyte x: return CastExpression(NonNullableType(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); case byte x: return CastExpression(NonNullableType(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); case short x: return CastExpression(NonNullableType(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); case ushort x: return CastExpression(NonNullableType(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); case int x: return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); case uint x: return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); case long x: return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); case ulong x: return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); case float x: return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); case double x: return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); case string x: return LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(x)); case null: return LiteralExpression(SyntaxKind.NullLiteralExpression); default: throw new NotImplementedException(); } } public static TypeSyntax MakeNonNullableType(TypeSyntax type) { if (type is NullableTypeSyntax nts) { type = nts.ElementType; } return type; } } }