private static void GenerateGetUnaryOperatorPrecedence(KindList kinds, SourceWriter writer) { writer.WriteLine("/// <summary>"); writer.WriteLine("/// Returns the precedence for a given unary operator or 0 if not a unary operator."); writer.WriteLine("/// </summary>"); writer.WriteLine("/// <param name=\"kind\"></param>"); writer.WriteLine("/// <returns>"); writer.WriteLine("/// A positive number indicating the binary operator precedence or 0 if the kind is not a binary operator."); writer.WriteLine("/// </returns>"); using (writer.CurlyIndenter("public static int GetUnaryOperatorPrecedence(SyntaxKind kind)")) using (writer.CurlyIndenter("switch(kind)")) { var groups = kinds.UnaryOperators.GroupBy(kind => kind.UnaryOperatorInfo !.Value.Precedence); foreach (var group in groups.OrderByDescending(g => g.Key)) { foreach (var kind in group.OrderByDescending(info => info.Field.Name)) { writer.WriteLine($"case SyntaxKind.{kind.Field.Name}:"); } using (writer.Indenter()) writer.WriteLine($"return {group.Key};"); } writer.WriteLine("default:"); using (writer.Indenter()) writer.WriteLine("return 0;"); } }
private static void GenerateGetText(KindList kinds, SourceWriter writer) { writer.WriteLine("/// <summary>"); writer.WriteLine("/// Gets the predefined text that corresponds to the provided syntax kind."); writer.WriteLine("/// </summary>"); writer.WriteLine("/// <param name=\"kind\">The kind to obtain the text for.</param>"); writer.WriteLine("/// <returns>The text corresponding to the provided kind or <see cref=\"string.Emtpy\" /> if none.</returns>"); using (writer.Indenter("public static string GetText (SyntaxKind kind) =>")) using (writer.CurlyIndenter("kind switch", ";")) { writer.WriteLine("#region Tokens"); writer.WriteLineNoTabs(""); foreach (var token in kinds.Tokens.OrderBy(tok => tok.Field.Name)) { writer.WriteLine($"SyntaxKind.{token.Field.Name} => \"{token.TokenInfo!.Value.Text}\","); } writer.WriteLineNoTabs(""); writer.WriteLine("#endregion Tokens"); writer.WriteLine("#region Keywords"); writer.WriteLineNoTabs(""); foreach (var keyword in kinds.Keywords.OrderBy(kw => kw.Field.Name)) { writer.WriteLine($"SyntaxKind.{keyword.Field.Name} => \"{keyword.TokenInfo!.Value.Text}\","); } writer.WriteLineNoTabs(""); writer.WriteLine("#endregion Keywords"); writer.WriteLine("_ => string.Empty,"); } }
private static void GenerateIsX(KindList kinds, SourceWriter writer, string typeName, Func <KindInfo, bool> filter) { writer.WriteLine("/// <summary>"); writer.WriteLine($"/// Checks whether the provided <see cref=\"SyntaxKind\"/> is a {typeName.ToLower()}'s."); writer.WriteLine("/// </summary>"); writer.WriteLine("/// <param name=\"kind\"></param>"); writer.WriteLine("/// <returns></returns>"); using (writer.CurlyIndenter($"public static bool Is{typeName}(SyntaxKind kind)")) using (writer.CurlyIndenter("switch(kind)")) { var filteredKinds = kinds.Where(filter); foreach (var keyword in filteredKinds.OrderBy(kw => kw.Field.Name)) { writer.WriteLine($"case SyntaxKind.{keyword.Field.Name}:"); } using (writer.Indenter()) writer.WriteLine("return true;"); writer.WriteLineNoTabs(""); using (writer.Indenter("default:")) writer.WriteLine("return false;"); } }
private static void GenerateGetKeywordKind(KindList kinds, SourceWriter writer) { writer.WriteLine("/// <summary>"); writer.WriteLine("/// Returns the <see cref=\"SyntaxKind\"/> for a given keyword."); writer.WriteLine("/// </summary>"); writer.WriteLine("/// <param name=\"text\"></param>"); writer.WriteLine("/// <returns></returns>"); using (writer.Indenter("public static SyntaxKind GetKeywordKind(String text) =>")) using (writer.CurlyIndenter("text switch", ";")) { foreach (var keyword in kinds.Keywords.OrderBy(kind => kind.Field.Name)) { writer.WriteLine($"\"{keyword.TokenInfo!.Value.Text}\" => SyntaxKind.{keyword.Field.Name},"); } writer.WriteLine($"_ => SyntaxKind.IdentifierToken,"); } }
private static void GenerateGetBinaryExpression(KindList kinds, SourceWriter writer) { writer.WriteLine("/// <summary>"); writer.WriteLine("/// Returns the expression kind for a given unary operator or None if not a unary operator."); writer.WriteLine("/// </summary>"); writer.WriteLine("/// <param name=\"kind\"></param>"); writer.WriteLine("/// <returns>"); writer.WriteLine("/// A positive number indicating the binary operator precedence or 0 if the kind is not a binary operator."); writer.WriteLine("/// </returns>"); using (writer.Indenter("public static Option<SyntaxKind> GetBinaryExpression(SyntaxKind kind) =>")) using (writer.CurlyIndenter("kind switch", ";")) { foreach (var binaryOperator in kinds.BinaryOperators) { writer.WriteLine($"SyntaxKind.{binaryOperator.Field.Name} => {binaryOperator.BinaryOperatorInfo!.Value.Expression.ToCSharpString()},"); } writer.WriteLine("_ => default,"); } }
public void Initialize(IncrementalGeneratorInitializationContext context) { var errorCodeType = context.CompilationProvider.Select((comp, _) => comp.GetTypeByMetadataName("Loretta.CodeAnalysis.Lua.ErrorCode")); var errorCodeFields = errorCodeType.SelectMany((type, _) => type?.GetMembers().OfType <IFieldSymbol>() ?? Enumerable.Empty <IFieldSymbol>()) .Collect(); context.RegisterSourceOutput(errorCodeFields, (context, codes) => { if (codes.IsEmpty) { return; } else { using var writer = new SourceWriter(); using (writer.CurlyIndenter("namespace Loretta.CodeAnalysis.Lua")) using (writer.CurlyIndenter("internal static partial class ErrorFacts")) { using (writer.CurlyIndenter("public static partial bool IsWarning(ErrorCode code)")) using (writer.CurlyIndenter("switch(code)")) { var warnings = codes.Where(field => field.Name.StartsWith("WRN_", StringComparison.OrdinalIgnoreCase)); if (warnings.Any()) { foreach (var code in warnings) { writer.WriteLine($"case ErrorCode.{code.Name}:"); } using (writer.Indenter()) writer.WriteLine("return true;"); } writer.WriteLine("default:"); using (writer.Indenter()) writer.WriteLine("return false;"); } writer.WriteLine(); using (writer.CurlyIndenter("public static partial bool IsFatal(ErrorCode code)")) using (writer.CurlyIndenter("switch(code)")) { var fatals = codes.Where(field => field.Name.StartsWith("FTL_", StringComparison.OrdinalIgnoreCase)); if (fatals.Any()) { foreach (var code in fatals) { writer.WriteLine($"case ErrorCode.{code.Name}:"); } using (writer.Indenter()) writer.WriteLine("return true;"); } writer.WriteLine("default:"); using (writer.Indenter()) writer.WriteLine("return false;"); } writer.WriteLine(); using (writer.CurlyIndenter("public static partial bool IsInfo(ErrorCode code)")) using (writer.CurlyIndenter("switch(code)")) { var infos = codes.Where(field => field.Name.StartsWith("INF_", StringComparison.OrdinalIgnoreCase)); if (infos.Any()) { foreach (var code in infos) { writer.WriteLine($"case ErrorCode.{code.Name}:"); } using (writer.Indenter()) writer.WriteLine("return true;"); } writer.WriteLine("default:"); using (writer.Indenter()) writer.WriteLine("return false;"); } writer.WriteLine(); using (writer.CurlyIndenter("public static partial bool IsHidden(ErrorCode code)")) using (writer.CurlyIndenter("switch(code)")) { var hidden = codes.Where(field => field.Name.StartsWith("HDN_", StringComparison.OrdinalIgnoreCase)); if (hidden.Any()) { foreach (var code in hidden) { writer.WriteLine($"case ErrorCode.{code.Name}:"); } using (writer.Indenter()) writer.WriteLine("return true;"); } writer.WriteLine("default:"); using (writer.Indenter()) writer.WriteLine("return false;"); } } context.AddSource("ErrorFacts.g.cs", writer.GetText()); } }); }
protected override void GenerateFiles(GeneratorExecutionContext context, CSharpCompilation compilation) { var errorCodeType = compilation.GetTypeByMetadataName("Loretta.CodeAnalysis.Lua.ErrorCode"); if (errorCodeType is null) { return; } var codes = errorCodeType.GetMembers().OfType <IFieldSymbol>().ToImmutableArray(); SourceText sourceText; using (var writer = new SourceWriter()) { using (writer.CurlyIndenter("namespace Loretta.CodeAnalysis.Lua")) using (writer.CurlyIndenter("internal static partial class ErrorFacts")) { using (writer.CurlyIndenter("public static partial bool IsWarning(ErrorCode code)")) using (writer.CurlyIndenter("switch(code)")) { var warnings = codes.Where(field => field.Name.StartsWith("WRN_", StringComparison.OrdinalIgnoreCase)); if (warnings.Any()) { foreach (var code in warnings) { writer.WriteLine($"case ErrorCode.{code.Name}:"); } using (writer.Indenter()) writer.WriteLine("return true;"); } writer.WriteLine("default:"); using (writer.Indenter()) writer.WriteLine("return false;"); } writer.WriteLine(); using (writer.CurlyIndenter("public static partial bool IsFatal(ErrorCode code)")) using (writer.CurlyIndenter("switch(code)")) { var fatals = codes.Where(field => field.Name.StartsWith("FTL_", StringComparison.OrdinalIgnoreCase)); if (fatals.Any()) { foreach (var code in fatals) { writer.WriteLine($"case ErrorCode.{code.Name}:"); } using (writer.Indenter()) writer.WriteLine("return true;"); } writer.WriteLine("default:"); using (writer.Indenter()) writer.WriteLine("return false;"); } writer.WriteLine(); using (writer.CurlyIndenter("public static partial bool IsInfo(ErrorCode code)")) using (writer.CurlyIndenter("switch(code)")) { var infos = codes.Where(field => field.Name.StartsWith("INF_", StringComparison.OrdinalIgnoreCase)); if (infos.Any()) { foreach (var code in infos) { writer.WriteLine($"case ErrorCode.{code.Name}:"); } using (writer.Indenter()) writer.WriteLine("return true;"); } writer.WriteLine("default:"); using (writer.Indenter()) writer.WriteLine("return false;"); } writer.WriteLine(); using (writer.CurlyIndenter("public static partial bool IsHidden(ErrorCode code)")) using (writer.CurlyIndenter("switch(code)")) { var hidden = codes.Where(field => field.Name.StartsWith("HDN_", StringComparison.OrdinalIgnoreCase)); if (hidden.Any()) { foreach (var code in hidden) { writer.WriteLine($"case ErrorCode.{code.Name}:"); } using (writer.Indenter()) writer.WriteLine("return true;"); } writer.WriteLine("default:"); using (writer.Indenter()) writer.WriteLine("return false;"); } } sourceText = writer.GetText(); } context.AddSource("ErrorFacts.g.cs", sourceText); Utilities.DoVsCodeHack(errorCodeType, "ErrorFacts.g.cs", sourceText); }