Exemplo n.º 1
0
    static void Initialize(OutputModel outputModel, ClassModel?classModel, OutputPlan outputPlan, DbAttributeModel dbAttribute)
    {
        var name   = dbAttribute.Name ?? "";
        var symbol = classModel?.ClassSymbol as ISymbol ?? outputModel.Compilation.Assembly;

        if (outputPlan.DatabasePlansByName.TryGetValue(name, out var plan))
        {
            if (dbAttribute.Namespace.NullIfEmpty() is not null &&
                dbAttribute.Namespace != plan.Namespace)
            {
                if (plan.IsDefaultNamespace)
                {
                    plan.IsDefaultNamespace = false;
                    plan.Namespace          = dbAttribute.Namespace !;
                    plan.ClassModel         = classModel;
                }
                else
                {
                    outputModel.Report(Diagnostics.Errors.DbMultipleNamespace, symbol);
                }
            }
        }
        else
        {
            plan = new DatabasePlan
            {
                Namespace                    = dbAttribute.Namespace.NullIfEmpty() !,
                Name                         = name,
                ClassModel                   = classModel,
                DbClassName                  = name.WithSuffix(Suffixes.Database),
                PartitionsClassName          = name.WithSuffix(Suffixes.Partitions),
                QueryBuilderClassName        = name.WithSuffix(Suffixes.QueryBuilder),
                QueryBuilderUnionsClassName  = name.WithSuffix(Suffixes.QueryBuilderUnions),
                QueryClassName               = name.WithSuffix(Suffixes.Query),
                QueryUnionsClassName         = name.WithSuffix(Suffixes.QueryUnions),
                ReadClassName                = name.WithSuffix(Suffixes.Read),
                SerializerClassName          = name.WithSuffix(Suffixes.Serializer),
                ConverterClassName           = name.WithSuffix(Suffixes.Converter),
                TypesClassName               = name.WithSuffix(Suffixes.Types),
                BatchHandlersClassName       = name.WithSuffix(Suffixes.BatchHandlers),
                ChangeFeedProcessorClassName = name.WithSuffix(Suffixes.ChangeFeedProcessor)
            };
            plan.BatchHandlersArgumentName = plan.BatchHandlersClassName.ToArgumentName();
            plan.IsDefaultNamespace        = plan.Namespace is null;
            plan.Namespace ??= classModel?.ClassSymbol.ContainingNamespace?.ToDisplayString() ?? outputModel.Compilation.Assembly.Name.NullIfEmpty() ?? "Cosmogenesis.Generated";
            plan.DbClassNameArgument           = plan.DbClassName.ToArgumentName();
            plan.QueryBuilderClassNameArgument = plan.QueryBuilderClassName.ToArgumentName();
            outputModel.ValidateNames(
                symbol,
                plan.Name,
                plan.DbClassName,
                plan.PartitionsClassName,
                plan.QueryBuilderClassName,
                plan.QueryClassName,
                plan.ReadClassName,
                plan.SerializerClassName,
                plan.ConverterClassName,
                plan.TypesClassName,
                plan.BatchHandlersClassName,
                plan.ChangeFeedProcessorClassName,
                plan.QueryBuilderUnionsClassName,
                plan.QueryUnionsClassName);
            outputModel.ValidateIdentifiers(
                symbol,
                plan.BatchHandlersArgumentName,
                plan.DbClassNameArgument,
                plan.QueryBuilderClassNameArgument);
            plan.Namespace.ValidateNamespace(outputModel, symbol);
            outputPlan.DatabasePlansByName[name] = plan;
        }
        if (classModel is not null)
        {
            outputPlan.DatabasePlansByClass[classModel].Add(plan);
        }
    }
}
Exemplo n.º 2
0
    static void AddPartitionDefinition(OutputModel outputModel, DatabasePlan databasePlan, MethodModel methodModel, string name)
    {
        if (databasePlan.PartitionPlansByName.TryGetValue(name, out var partitionPlan))
        {
            if (!SymbolEqualityComparer.Default.Equals(partitionPlan.GetPkModel.MethodSymbol, methodModel.MethodSymbol))
            {
                outputModel.Report(Diagnostics.Errors.PartitionAlreadyDefined, methodModel.MethodSymbol);
            }
        }
        else
        {
            partitionPlan = new PartitionPlan
            {
                Name                        = name,
                PluralName                  = name.Pluralize(),
                ClassName                   = name.WithSuffix(Suffixes.Partition),
                BatchHandlersClassName      = name.WithSuffix(Suffixes.BatchHandlers),
                CreateOrReplaceClassName    = name.WithSuffix(Suffixes.CreateOrReplace),
                ReadClassName               = name.WithSuffix(Suffixes.Read),
                ReadOrThrowClassName        = name.WithSuffix(Suffixes.ReadOrThrow),
                ReadManyClassName           = name.WithSuffix(Suffixes.ReadMany),
                ReadUnionsClassName         = name.WithSuffix(Suffixes.ReadUnions),
                ReadOrThrowUnionsClassName  = name.WithSuffix(Suffixes.ReadOrThrowUnions),
                ReadManyUnionsClassName     = name.WithSuffix(Suffixes.ReadManyUnions),
                QueryBuilderClassName       = name.WithSuffix(Suffixes.QueryBuilder),
                QueryBuilderUnionsClassName = name.WithSuffix(Suffixes.QueryBuilderUnions),
                QueryClassName              = name.WithSuffix(Suffixes.Query),
                QueryUnionsClassName        = name.WithSuffix(Suffixes.QueryUnions),
                ReadOrCreateClassName       = name.WithSuffix(Suffixes.ReadOrCreate),
                CreateClassName             = name.WithSuffix(Suffixes.Create),
                BatchClassName              = name.WithSuffix(Suffixes.Batch),
                GetPkModel                  = methodModel
            };
            partitionPlan.BatchHandlersClassNameArgument = partitionPlan.BatchHandlersClassName.ToArgumentName();
            partitionPlan.ClassNameArgument             = partitionPlan.ClassName.ToArgumentName();
            databasePlan.PartitionPlansByName[name]     = partitionPlan;
            partitionPlan.QueryBuilderClassNameArgument = partitionPlan.QueryBuilderClassName.ToArgumentName();

            outputModel.ValidateNames(
                methodModel.MethodSymbol,
                partitionPlan.Name,
                partitionPlan.PluralName,
                partitionPlan.ClassName,
                partitionPlan.BatchHandlersClassName,
                partitionPlan.CreateOrReplaceClassName,
                partitionPlan.ReadClassName,
                partitionPlan.ReadOrThrowClassName,
                partitionPlan.ReadManyClassName,
                partitionPlan.QueryBuilderClassName,
                partitionPlan.QueryClassName,
                partitionPlan.ReadOrCreateClassName,
                partitionPlan.CreateClassName,
                partitionPlan.BatchClassName,
                partitionPlan.QueryBuilderUnionsClassName,
                partitionPlan.QueryUnionsClassName,
                partitionPlan.ReadManyUnionsClassName,
                partitionPlan.ReadOrThrowUnionsClassName,
                partitionPlan.ReadUnionsClassName);

            outputModel.ValidateIdentifiers(
                methodModel.MethodSymbol,
                partitionPlan.ClassNameArgument,
                partitionPlan.BatchHandlersClassNameArgument,
                partitionPlan.QueryBuilderClassNameArgument);
        }
    }
Exemplo n.º 3
0
    public static void AddDocuments(OutputModel outputModel, OutputPlan outputPlan)
    {
        outputModel.CancellationToken.ThrowIfCancellationRequested();
        if (!outputModel.CanGenerate)
        {
            return;
        }

        foreach (var kvp in outputPlan.DatabasePlansByClass)
        {
            var classModel    = kvp.Key;
            var databasePlans = kvp.Value;
            if (classModel.IsDbDoc && !classModel.ClassSymbol.IsAbstract)
            {
                if (databasePlans.Count == 0)
                {
                    outputModel.Report(Diagnostics.Errors.NoDatabase, classModel.ClassSymbol);
                }
                else if (classModel.PartitionAttribute is null)
                {
                    outputModel.Report(Diagnostics.Warnings.DbDocWithoutPartition, classModel.ClassSymbol, classModel.ClassSymbol.Name);
                }
                else
                {
                    if (!classModel.ClassSymbol.Constructors.Any(x => x.Parameters.IsDefaultOrEmpty && x.DeclaredAccessibility.IsAccessible()))
                    {
                        outputModel.Report(Diagnostics.Errors.ParameterlessConstructor, classModel.ClassSymbol);
                    }
                    var implicitGetIds = classModel.Methods
                                         .Where(x => x.MethodSymbol.Name == "GetId")
                                         .Where(x => x.MethodSymbol.IsStatic)
                                         .Where(x => x.MethodSymbol.ReturnType.SpecialType == SpecialType.System_String)
                                         .Where(x => x.MethodSymbol.DeclaredAccessibility.IsAccessible())
                                         .ToList();
                    if (implicitGetIds.Count == 0)
                    {
                        outputModel.Report(Diagnostics.Errors.NoGetId, classModel.ClassSymbol);
                    }
                    else if (implicitGetIds.Count > 1)
                    {
                        outputModel.Report(Diagnostics.Errors.MultipleGetId, classModel.ClassSymbol);
                    }
                    else
                    {
                        var getId         = implicitGetIds[0];
                        var partitionName = classModel.PartitionAttribute.Name;
                        var name          = classModel.ClassSymbol.Name.WithoutSuffix(Suffixes.Doc).WithoutSuffix(Suffixes.Document);
                        var type          = classModel.DocTypeAttribute?.Name.NullIfEmpty() ?? name;
                        type.ValidateDocType(outputModel, classModel.ClassSymbol);
                        foreach (var databasePlan in databasePlans)
                        {
                            if (!databasePlan.PartitionPlansByName.TryGetValue(partitionName, out var partitionPlan))
                            {
                                outputModel.Report(Diagnostics.Errors.NoGetPk, classModel.ClassSymbol);
                            }
                            else
                            {
                                var documentPlan = new DocumentPlan
                                {
                                    DocType           = type,
                                    FullTypeName      = classModel.ClassSymbol.ToDisplayString(),
                                    ClassModel        = classModel,
                                    IsMutable         = classModel.MutableAttribute is not null,
                                    IsTransient       = classModel.TransientAttribute is not null,
                                    ClassName         = name,
                                    ClassNameArgument = name.ToArgumentName(),
                                    PluralName        = name.Pluralize(),
                                    ConstDocType      = $"{databasePlan.Namespace}.{databasePlan.TypesClassName}.{partitionPlan.ClassName}.{name}",
                                    GetIdPlan         = new GetPkIdPlan
                                    {
                                        FullMethodName = $"{getId.MethodSymbol.ContainingType.ToDisplayString()}.{getId.MethodSymbol.Name}",
                                        Arguments      = getId
                                                         .MethodSymbol
                                                         .Parameters
                                                         .Select(x => new GetPkIdPlan.Argument
                                        {
                                            ArgumentName = x.Name.ToArgumentName(),
                                            FullTypeName = x.Type.ToDisplayString()
                                        })
                                                         .ToList()
                                    }
                                };

                                partitionPlan.Documents.Add(documentPlan);

                                outputModel.ValidateNames(
                                    classModel.ClassSymbol,
                                    documentPlan.ClassName,
                                    documentPlan.PluralName);
                                outputModel.ValidateIdentifiers(
                                    classModel.ClassSymbol,
                                    documentPlan.ClassNameArgument);

                                PropertyPlanBuilder.AddProperties(outputModel, classModel, documentPlan);

                                documentPlan.GetIdPlan = GetPkIdPlanBuilder.Build(outputModel, getId.MethodSymbol, documentPlan.PropertiesByName, documentPlan.PropertiesByArgumentName);
                                if (partitionPlan.GetPkPlan is null)
                                {
                                    partitionPlan.GetPkPlan = GetPkIdPlanBuilder.Build(outputModel, partitionPlan.GetPkModel.MethodSymbol, documentPlan.PropertiesByName, documentPlan.PropertiesByArgumentName);
                                }
                                else
                                {
                                    foreach (var arg in partitionPlan.GetPkPlan.Arguments)
                                    {
                                        if (arg.PropertyName is not null && !documentPlan.PropertiesByName.ContainsKey(arg.PropertyName))
                                        {
                                            outputModel.Report(Diagnostics.Errors.PropertyResolvePkIdConsistency, partitionPlan.GetPkModel.MethodSymbol, arg.ArgumentName, arg.PropertyName);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}