public void Execute(GeneratorExecutionContext context) { // retrieve the populated receiver if (!(context.SyntaxReceiver is RecursionSyntaxReceiver receiver)) { return; } var compilation = context.Compilation; if ("C#" != compilation.Language) { context.ReportUnsupportedLanguageError(compilation.Language); return; } var goodCandidates = receiver.CandidateMethods.Select(methodSyntax => { var methodModel = compilation.GetSemanticModel(methodSyntax.SyntaxTree); var methodSymbol = methodModel.GetDeclaredSymbol(methodSyntax); var attr = methodSymbol.GetAttributes().SingleOrDefault(a => a.AttributeClass.MatchesRuntimeType(TargetAttribute)); var codeGenProps = (attr != null) ? SafeRecursionCodeGenProps.ParseFromAttribute(context, methodSyntax, attr) : null; return(new RecursiveMethodInfo(methodSyntax, methodSymbol, methodModel, codeGenProps)); }) .Where(t => t.CodeGenProps != null) .GroupBy(t => t.CodeGenProps.MutualRecursionId ?? "") //convert null to empty string for GroupBy .ToDictionary(g => g.Key, g => g.ToList()); if (!goodCandidates.TryGetValue("", out var simpleCandidates)) { simpleCandidates = new List <RecursiveMethodInfo>(); } context.Log($"Found {simpleCandidates.Count} method(s) for simple recursion and {goodCandidates.Count - 1} method group(s) for mutual recursion generation."); foreach (var methodInfo in simpleCandidates) { try { var generatedCode = CalculatorClassGenerator.GenerateSimpleSafeRec(context, methodInfo); if (generatedCode != null) { context.AddSource($"{methodInfo.MethodSymbol.ContainingType.Name}_{methodInfo.MethodSymbol.Name}_SafeRecursion.cs", SourceText.From(generatedCode, Encoding.UTF8)); } } catch (Exception e) { context.LogInternalError(methodInfo.MethodSyntax.GetLocation(), $"Processing '{methodInfo.MethodSymbol.ContainingType.Name}' resulted in an internal error '{e}'"); } } foreach (var(recursionId, methodInfos) in goodCandidates) { // skip the simple candidates if (string.IsNullOrEmpty(recursionId)) { continue; } var someMethodInfo = methodInfos.First(); try { var generatedCode = CalculatorClassGenerator.GenerateMutualSafeRec(context, methodInfos); if (generatedCode != null) { context.AddSource($"{someMethodInfo.MethodSymbol.ContainingType.Name}_{recursionId}_SafeRecursion.cs", SourceText.From(generatedCode, Encoding.UTF8)); } } catch (Exception e) { context.LogInternalError(someMethodInfo.MethodSyntax.Parent.GetLocation(), $"Processing '{recursionId}' mutual recursion resulted in an internal error '{e}'"); } } }