Exemplo n.º 1
0
    public override bool GenerateRuleState(
        Compilation compilation,
        ISymbol symbol,
        ImmutableArray <AttributeData> attributes,
        ImmutableArray <INamedTypeSymbol> serializableTypes,
        ImmutableArray <INamedTypeSymbol> embeddedSerializableTypes,
        ISymbol?parentSymbol,
        out string[] ruleArguments
        )
    {
        if (symbol is not INamedTypeSymbol namedTypeSymbol || !symbol.IsList(compilation))
        {
            ruleArguments = null;
            return(false);
        }

        var listTypeSymbol = namedTypeSymbol.TypeArguments[0];

        var serializableListType = SerializableMigrationRulesEngine.GenerateSerializableProperty(
            compilation,
            "ListEntry",
            listTypeSymbol,
            0,
            attributes,
            serializableTypes,
            embeddedSerializableTypes,
            parentSymbol,
            null
            );

        var extraOptions = "";

        if (attributes.Any(a => a.IsTidy(compilation)))
        {
            extraOptions += "@Tidy";
        }

        var length = serializableListType.RuleArguments?.Length ?? 0;

        ruleArguments    = new string[length + 3];
        ruleArguments[0] = extraOptions;
        ruleArguments[1] = listTypeSymbol.ToDisplayString();
        ruleArguments[2] = serializableListType.Rule;

        if (length > 0)
        {
            Array.Copy(serializableListType.RuleArguments !, 0, ruleArguments, 3, length);
        }

        return(true);
    }
Exemplo n.º 2
0
    public override bool GenerateRuleState(
        Compilation compilation,
        ISymbol symbol,
        ImmutableArray <AttributeData> attributes,
        ImmutableArray <INamedTypeSymbol> serializableTypes,
        ImmutableArray <INamedTypeSymbol> embeddedSerializableTypes,
        ISymbol?parentSymbol,
        out string[] ruleArguments
        )
    {
        if (symbol is not IArrayTypeSymbol arrayTypeSymbol)
        {
            ruleArguments = null;
            return(false);
        }

        var serializableArrayType = SerializableMigrationRulesEngine.GenerateSerializableProperty(
            compilation,
            "ArrayEntry",
            arrayTypeSymbol.ElementType,
            0,
            attributes,
            serializableTypes,
            embeddedSerializableTypes,
            parentSymbol,
            null
            );

        var length = serializableArrayType.RuleArguments?.Length ?? 0;

        ruleArguments    = new string[length + 2];
        ruleArguments[0] = arrayTypeSymbol.ElementType.ToDisplayString();
        ruleArguments[1] = serializableArrayType.Rule;
        if (length > 0)
        {
            Array.Copy(serializableArrayType.RuleArguments !, 0, ruleArguments, 2, length);
        }

        return(true);
    }
Exemplo n.º 3
0
    public override bool GenerateRuleState(
        Compilation compilation,
        ISymbol symbol,
        ImmutableArray <AttributeData> attributes,
        ImmutableArray <INamedTypeSymbol> serializableTypes,
        ImmutableArray <INamedTypeSymbol> embeddedSerializableTypes,
        ISymbol?parentSymbol,
        out string[] ruleArguments
        )
    {
        if (symbol is not INamedTypeSymbol namedTypeSymbol || !symbol.IsDictionary(compilation))
        {
            ruleArguments = null;
            return(false);
        }

        var keySymbolType = namedTypeSymbol.TypeArguments[0];

        var serializableKeyProperty = SerializableMigrationRulesEngine.GenerateSerializableProperty(
            compilation,
            "KeyEntry",
            keySymbolType,
            0,
            attributes,
            serializableTypes,
            embeddedSerializableTypes,
            parentSymbol,
            null
            );

        var valueSymbolType = namedTypeSymbol.TypeArguments[1];

        var serializableValueProperty = SerializableMigrationRulesEngine.GenerateSerializableProperty(
            compilation,
            "ValueEntry",
            valueSymbolType,
            0,
            attributes,
            serializableTypes,
            embeddedSerializableTypes,
            parentSymbol,
            null
            );

        var extraOptions = "";

        if (attributes.Any(a => a.IsTidy(compilation)))
        {
            extraOptions += "@Tidy";
        }

        var keyArgumentsLength   = serializableKeyProperty.RuleArguments?.Length ?? 0;
        var valueArgumentsLength = serializableValueProperty.RuleArguments?.Length ?? 0;
        var index = 0;

        ruleArguments          = new string[7 + keyArgumentsLength + valueArgumentsLength];
        ruleArguments[index++] = extraOptions;
        ruleArguments[index++] = keySymbolType.ToDisplayString();
        ruleArguments[index++] = serializableKeyProperty.Rule;
        ruleArguments[index++] = keyArgumentsLength.ToString();

        if (keyArgumentsLength > 0)
        {
            Array.Copy(serializableKeyProperty.RuleArguments !, 0, ruleArguments, index, keyArgumentsLength);
            index += keyArgumentsLength;
        }

        ruleArguments[index++] = valueSymbolType.ToDisplayString();
        ruleArguments[index++] = serializableValueProperty.Rule;
        ruleArguments[index++] = valueArgumentsLength.ToString();

        if (valueArgumentsLength > 0)
        {
            Array.Copy(serializableValueProperty.RuleArguments !, 0, ruleArguments, index, valueArgumentsLength);
        }

        return(true);
    }
Exemplo n.º 4
0
    public override bool GenerateRuleState(
        Compilation compilation,
        ISymbol symbol,
        ImmutableArray <AttributeData> attributes,
        ImmutableArray <INamedTypeSymbol> serializableTypes,
        ImmutableArray <INamedTypeSymbol> embeddedSerializableTypes,
        ISymbol?parentSymbol,
        out string[] ruleArguments
        )
    {
        if (symbol is not INamedTypeSymbol namedTypeSymbol || !symbol.IsKeyValuePair(compilation))
        {
            ruleArguments = null;
            return(false);
        }

        var keySymbolType = namedTypeSymbol.TypeArguments[0];

        var keySerializedProperty = SerializableMigrationRulesEngine.GenerateSerializableProperty(
            compilation,
            "key",
            keySymbolType,
            0,
            attributes,
            serializableTypes,
            embeddedSerializableTypes,
            parentSymbol,
            null
            );

        var valueSymbolType = namedTypeSymbol.TypeArguments[1];

        var valueSerializedProperty = SerializableMigrationRulesEngine.GenerateSerializableProperty(
            compilation,
            "value",
            valueSymbolType,
            1,
            attributes,
            serializableTypes,
            embeddedSerializableTypes,
            parentSymbol,
            null
            );

        var keyArgumentsLength   = keySerializedProperty.RuleArguments?.Length ?? 0;
        var valueArgumentsLength = valueSerializedProperty.RuleArguments?.Length ?? 0;
        var index = 0;

        // Key
        ruleArguments          = new string[6 + keyArgumentsLength + valueArgumentsLength];
        ruleArguments[index++] = ""; // Extra options
        ruleArguments[index++] = keySymbolType.ToDisplayString();
        ruleArguments[index++] = keySerializedProperty.Rule;
        ruleArguments[index++] = keyArgumentsLength.ToString();
        if (keyArgumentsLength > 0)
        {
            Array.Copy(keySerializedProperty.RuleArguments !, 0, ruleArguments, index, keyArgumentsLength);
            index += keyArgumentsLength;
        }

        // Value
        ruleArguments[index++] = valueSymbolType.ToDisplayString();
        ruleArguments[index++] = valueSerializedProperty.Rule;

        if (valueArgumentsLength > 0)
        {
            Array.Copy(valueSerializedProperty.RuleArguments !, 0, ruleArguments, index, valueArgumentsLength);
        }

        return(true);
    }
Exemplo n.º 5
0
        public static string GenerateSerializationPartialClass(
            this Compilation compilation,
            INamedTypeSymbol classSymbol,
            AttributeData serializableAttr,
            string?migrationPath,
            bool embedded,
            JsonSerializerOptions?jsonSerializerOptions,
            ImmutableArray <SerializableMetadata> migrations,
            ImmutableArray <ISymbol> fieldsAndProperties,
            ImmutableArray <INamedTypeSymbol> serializableTypes,
            ImmutableArray <INamedTypeSymbol> embeddedSerializableTypes
            )
        {
            var serializableFieldAttribute =
                compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_FIELD_ATTRIBUTE);
            var serializableFieldAttrAttribute =
                compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_FIELD_ATTR_ATTRIBUTE);
            var serializableInterface =
                compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_INTERFACE);
            var parentSerializableAttribute =
                compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_PARENT_ATTRIBUTE);
            var serializableFieldSaveFlagAttribute =
                compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_FIELD_SAVE_FLAG_ATTRIBUTE);
            var serializableFieldDefaultAttribute =
                compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_FIELD_DEFAULT_ATTRIBUTE);

            // If we have a parent that is or derives from ISerializable, then we are in override
            var isOverride = classSymbol.BaseType.ContainsInterface(serializableInterface);

            if (!(embedded || isOverride || classSymbol.ContainsInterface(serializableInterface)))
            {
                return(null);
            }

            var isRawSerializable = classSymbol.HasRawSerializableInterface(compilation, ImmutableArray <INamedTypeSymbol> .Empty);

            var version        = (int)serializableAttr.ConstructorArguments[0].Value !;
            var encodedVersion = (bool)serializableAttr.ConstructorArguments[1].Value !;

            // Let's find out if we need to do serialization flags
            var serializableFieldSaveFlags = new SortedDictionary <int, SerializableFieldSaveFlagMethods>();

            foreach (var m in classSymbol.GetMembers().OfType <IMethodSymbol>())
            {
                var getSaveFlagAttribute     = m.GetAttribute(serializableFieldSaveFlagAttribute);
                var getDefaultValueAttribute = m.GetAttribute(serializableFieldDefaultAttribute);

                if (getSaveFlagAttribute == null && getDefaultValueAttribute == null)
                {
                    continue;
                }

                var attrCtorArgs = getSaveFlagAttribute?.ConstructorArguments ?? getDefaultValueAttribute.ConstructorArguments;
                var order        = (int)attrCtorArgs[0].Value !;

                serializableFieldSaveFlags.TryGetValue(order, out var saveFlagMethods);

                serializableFieldSaveFlags[order] = new SerializableFieldSaveFlagMethods
                {
                    DetermineFieldShouldSerialize = getSaveFlagAttribute != null ? m : saveFlagMethods?.DetermineFieldShouldSerialize,
                    GetFieldDefaultValue          = getDefaultValueAttribute != null ? m : saveFlagMethods?.GetFieldDefaultValue
                };
            }

            var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
            var className     = classSymbol.Name;

            StringBuilder source = new StringBuilder();

            source.AppendLine("#pragma warning disable\n");
            source.GenerateNamespaceStart(namespaceName);

            var interfaces = !embedded || isRawSerializable
                ? Array.Empty <ITypeSymbol>()
                : new ITypeSymbol[]
            {
                compilation.GetTypeByMetadataName(SymbolMetadata.RAW_SERIALIZABLE_INTERFACE)
            };

            var indent = "    ";

            source.RecursiveGenerateClassStart(classSymbol, interfaces.ToImmutableArray(), ref indent);

            source.GenerateClassField(
                indent,
                Accessibility.Private,
                InstanceModifier.Const,
                "int",
                "_version",
                version.ToString()
                );
            source.AppendLine();

            var parentFieldOrProperty = embedded ? fieldsAndProperties.FirstOrDefault(
                fieldOrPropertySymbol => fieldOrPropertySymbol.GetAttributes()
                .FirstOrDefault(
                    attr =>
                    SymbolEqualityComparer.Default.Equals(attr.AttributeClass, parentSerializableAttribute)
                    ) != null
                ) : null;

            var serializablePropertySet = new SortedDictionary <SerializableProperty, ISymbol>(new SerializablePropertyComparer());

            foreach (var fieldOrPropertySymbol in fieldsAndProperties)
            {
                var allAttributes = fieldOrPropertySymbol.GetAttributes();

                var serializableFieldAttr = allAttributes
                                            .FirstOrDefault(
                    attr =>
                    SymbolEqualityComparer.Default.Equals(attr.AttributeClass, serializableFieldAttribute)
                    );

                if (serializableFieldAttr == null)
                {
                    continue;
                }

                foreach (var attr in allAttributes)
                {
                    if (!SymbolEqualityComparer.Default.Equals(attr.AttributeClass, serializableFieldAttrAttribute))
                    {
                        continue;
                    }

                    if (attr.AttributeClass == null)
                    {
                        continue;
                    }

                    var ctorArgs    = attr.ConstructorArguments;
                    var attrTypeArg = ctorArgs[0];

                    if (attrTypeArg.Kind == TypedConstantKind.Primitive && attrTypeArg.Value is string attrStr)
                    {
                        source.AppendLine($"{indent}{attrStr}");
                    }
                    else
                    {
                        var attrType = (ITypeSymbol)attrTypeArg.Value;
                        source.GenerateAttribute(indent, attrType?.Name, ctorArgs[1].Values);
                    }
                }

                var attrCtorArgs = serializableFieldAttr.ConstructorArguments;

                var order           = (int)attrCtorArgs[0].Value !;
                var getterAccessor  = Helpers.GetAccessibility(attrCtorArgs[1].Value?.ToString());
                var setterAccessor  = Helpers.GetAccessibility(attrCtorArgs[2].Value?.ToString());
                var virtualProperty = (bool)attrCtorArgs[3].Value !;

                if (fieldOrPropertySymbol is IFieldSymbol fieldSymbol)
                {
                    source.GenerateSerializableProperty(
                        compilation,
                        indent,
                        fieldSymbol,
                        getterAccessor,
                        setterAccessor,
                        virtualProperty,
                        parentFieldOrProperty
                        );
                    source.AppendLine();
                }

                serializableFieldSaveFlags.TryGetValue(order, out var serializableFieldSaveFlagMethods);

                var serializableProperty = SerializableMigrationRulesEngine.GenerateSerializableProperty(
                    compilation,
                    fieldOrPropertySymbol,
                    order,
                    allAttributes,
                    serializableTypes,
                    embeddedSerializableTypes,
                    classSymbol,
                    serializableFieldSaveFlagMethods
                    );

                serializablePropertySet.Add(serializableProperty, fieldOrPropertySymbol);
            }

            var serializableFields     = serializablePropertySet.Keys.ToImmutableArray();
            var serializableProperties = serializablePropertySet.Select(
                kvp => kvp.Key with
            {
                Name = (kvp.Value as IFieldSymbol)?.GetPropertyName() ?? ((IPropertySymbol)kvp.Value).Name
            }