public static ClassDeclarationSyntax GenerateFrom(SystemBaseDescription systemBaseDescription)
        {
            var emptyClassWithSameIdentifierBaseListAndModifiers =
                ClassDeclaration(systemBaseDescription.DeclaringType.Identifier)
                .WithBaseList(systemBaseDescription.DeclaringType.BaseList)
                .WithModifiers(systemBaseDescription.DeclaringType.Modifiers);

            MethodDeclarationSyntax rewrittenOnUpdateMethod = GetOnUpdateMethodReplacement(systemBaseDescription);

            var nonOverrideModifiers =
                new SyntaxTokenList(rewrittenOnUpdateMethod.Modifiers.Where(m => !m.IsKind(SyntaxKind.OverrideKeyword)));

            return
                (emptyClassWithSameIdentifierBaseListAndModifiers
                 .AddMembers(OnUpdateEntityQuery())
                 .AddMembers(
                     rewrittenOnUpdateMethod
                     .WithIdentifier(
                         SyntaxFactory.Identifier($"{systemBaseDescription.OriginalSystemBaseOnUpdateMethod.Identifier.Text}_Patched"))
                     .WithModifiers(nonOverrideModifiers))
                 .AddMembers(OnCreateForCompiler(systemBaseDescription)));
        }
        public void Execute(GeneratorExecutionContext sourceGeneratorContext)
        {
            try
            {
                var iJobEntityReceiver = (IJobEntityReceiver)sourceGeneratorContext.SyntaxReceiver;

                if (!iJobEntityReceiver.JobEntityTypeCandidates.Any())
                {
                    return;
                }

                var syntaxTreeToCandidates =
                    iJobEntityReceiver
                    .JobEntityTypeCandidates
                    .GroupBy(j => j.TypeNode.SyntaxTree)
                    .ToDictionary(group => group.Key, group => group.ToArray());

                foreach (var kvp in syntaxTreeToCandidates)
                {
                    var syntaxTree = kvp.Key;
                    var candidates = kvp.Value;

                    try
                    {
                        foreach (var(typeNode, onUpdateMethodNode) in candidates)
                        {
                            SemanticModel semanticModel       = sourceGeneratorContext.Compilation.GetSemanticModel(typeNode.SyntaxTree);
                            ITypeSymbol   candidateTypeSymbol = (ITypeSymbol)semanticModel.GetDeclaredSymbol(typeNode);

                            if (!candidateTypeSymbol.InheritsFromInterface("Unity.Entities.IJobEntity"))
                            {
                                continue;
                            }

                            var jobEntityDescription =
                                new JobEntityDescription(typeNode, onUpdateMethodNode, candidateTypeSymbol, sourceGeneratorContext);

                            if (jobEntityDescription.FieldDescriptions.Any(f => !f.IsValueType))
                            {
                                throw new ArgumentException("IJobEntity types may only contain value-type fields.");
                            }

                            var jobEntityData = new JobEntityData
                            {
                                UserWrittenJobEntity         = jobEntityDescription,
                                GeneratedIJobEntityBatchType = JobEntityBatchTypeGenerator.GenerateFrom(jobEntityDescription),
                            };

                            AllJobEntityTypes[jobEntityDescription.DeclaringTypeFullyQualifiedName] = jobEntityData;

                            AddJobEntityBatchSourceToContext(jobEntityData, sourceGeneratorContext);
                        }
                    }
                    catch (Exception exception)
                    {
                        sourceGeneratorContext.LogError("SGICE001", "JobEntity", exception.ToString(), syntaxTree.GetRoot().GetLocation());
                    }
                }

                SyntaxNode[] entitiesInSystemBaseDerivedTypes =
                    GetEntitiesInSystemBaseDerivedTypes(
                        sourceGeneratorContext, iJobEntityReceiver.EntitiesGetterCandidates).ToArray();

                if (!entitiesInSystemBaseDerivedTypes.Any())
                {
                    return;
                }

                var syntaxTreesToEntities =
                    entitiesInSystemBaseDerivedTypes
                    .GroupBy(e => e.SyntaxTree)
                    .ToDictionary(group => group.Key, group => group.ToArray());

                foreach (var kvp in syntaxTreesToEntities)
                {
                    var syntaxTree  = kvp.Key;
                    var entityNodes = kvp.Value;

                    try
                    {
                        foreach (SyntaxNode entityNode in entityNodes)
                        {
                            var systemBaseDescription        = SystemBaseDescription.From(entityNode, sourceGeneratorContext);
                            var updatedSystemBaseDescription = UpdatedSystemBaseTypeGenerator.GenerateFrom(systemBaseDescription);

                            AddUpdatedSystemBaseSourceToContext(
                                systemBaseDescription,
                                updatedSystemBaseDescription,
                                sourceGeneratorContext);
                        }
                    }
                    catch (Exception exception)
                    {
                        sourceGeneratorContext.LogError("SGICE001", "JobEntity", exception.ToString(), syntaxTree.GetRoot().GetLocation());
                    }
                }
            }
            catch (Exception exception)
            {
                sourceGeneratorContext.LogError(
                    "SG0002",
                    "Unknown Exception",
                    exception.ToString(),
                    sourceGeneratorContext.Compilation.SyntaxTrees.First().GetRoot().GetLocation());
            }
        }
 private static void AddUpdatedSystemBaseSourceToContext(
     SystemBaseDescription systemBaseDescription,
     ClassDeclarationSyntax updatedSystemBaseType,
     in GeneratorExecutionContext sourceGeneratorContext)