Пример #1
0
        private void PopulateDictionary(BuilderState state, PropertyInformation propertyInformation)
        {
            var propertyName = propertyInformation.Property.Name;

            state.AppendLine($"if({propertyName} != null)");
            state.AppendLine("{");
            var ifBody = state.IncrementIdentation();

            ifBody.AppendLine($"foreach(var item in {propertyName})");
            ifBody.AppendLine("{");
            var foreachBody = ifBody.IncrementIdentation();

            foreachBody.AppendLine("if(item.Value is null)");
            foreachBody.IncrementIdentation().AppendLine($"input.{propertyName}.Remove(item.Key);");
            foreachBody.AppendLine("else");
            if (propertyInformation.IsConvertedToNullableType)
            {
                foreachBody.IncrementIdentation().AppendLine($"input.{propertyName}[item.Key] = item.Value.Value;");
            }
            else
            {
                foreachBody.IncrementIdentation().AppendLine($"input.{propertyName}[item.Key] = item.Value;");
            }
            ifBody.AppendLine("}");
            state.AppendLine("}");
        }
Пример #2
0
 private void SetReadWriteProperties(BuilderState state)
 {
     for (int i = 0; i < state.TypeInfo.Properties.Count; i++)
     {
         var currentProperty = state.TypeInfo.Properties[i].Property;
         if (!IsInitOnlyProperty(currentProperty))
         {
             state.AppendLine($"if (Properties[{i}])");
             if (GeneratedTypeFilter.IsGeneratableType(currentProperty.Type))
             {
                 state.IncrementIdentation().AppendLine($"input.{currentProperty.Name} = {currentProperty.Name}?.ApplyPatch(input.{currentProperty.Name});");
             }
             else if (state.TypeInfo.Properties[i].IsGenericDictionary)
             {
                 state.IncrementIdentation().AppendLine($"input.{currentProperty.Name} ??= new();");
             }
             else if (state.TypeInfo.Properties[i].IsConvertedToNullableType)
             {
                 state.IncrementIdentation().AppendLine($"input.{currentProperty.Name} = {currentProperty.Name}.HasValue ? {currentProperty.Name}.Value : default;");
             }
             else
             {
                 state.IncrementIdentation().AppendLine($"input.{currentProperty.Name} = {currentProperty.Name};");
             }
         }
     }
 }
Пример #3
0
 private void BuildClassBody(BuilderState state)
 {
     BuildConstructor(state);
     state.AppendLine();
     BuildAllProperties(state);
     BuildApplyPath(state);
 }
Пример #4
0
 private void BuildClassDeclaration(BuilderState state, Action <BuilderState>?addBody = null)
 {
     BuildAttributes(state, state.TypeInfo.TypeSymbol.GetAttributes());
     state.AppendLine($"public class {state.TypeInfo.Name} : LaDeak.JsonMergePatch.Abstractions.Patch<{state.TypeInfo.SourceTypeName}>");
     state.AppendLine("{");
     addBody?.Invoke(state.IncrementIdentation());
     state.AppendLine("}");
 }
Пример #5
0
 private void BuildAllProperties(BuilderState state)
 {
     for (int i = 0; i < state.TypeInfo.Properties.Count; i++)
     {
         BuildPropery(state, state.TypeInfo.Properties[i], i);
         state.AppendLine();
     }
 }
Пример #6
0
 private void BuildNamespace(BuilderState state, Action <BuilderState>?addBody = null)
 {
     state.AppendLine($"#nullable enable");
     state.AppendLine($"namespace {NameBuilder.GetNamespace(state.TypeInfo.TypeSymbol)}");
     state.AppendLine("{");
     addBody?.Invoke(state.IncrementIdentation());
     state.AppendLine("}");
     state.AppendLine($"#nullable disable");
 }
Пример #7
0
        private void BuildConstructor(BuilderState state, Action <BuilderState>?addBody = null)
        {
            state.AppendLine($"public {state.TypeInfo.Name}()");
            state.AppendLine("{");
            var innerState = state.IncrementIdentation();

            innerState.AppendLine($"Properties = new bool[{state.TypeInfo.Properties.Count}];");
            addBody?.Invoke(innerState);
            state.AppendLine("}");
        }
Пример #8
0
 private void PopulateDictionaryProperties(BuilderState state)
 {
     for (int i = 0; i < state.TypeInfo.Properties.Count; i++)
     {
         var currentProperty = state.TypeInfo.Properties[i].Property;
         if (!GeneratedTypeFilter.IsGeneratableType(currentProperty.Type) && state.TypeInfo.Properties[i].IsGenericDictionary)
         {
             PopulateDictionary(state, state.TypeInfo.Properties[i]);
         }
     }
 }
Пример #9
0
 private void BuildAttributes(BuilderState state, IEnumerable <AttributeData> attributes)
 {
     foreach (var attribute in attributes)
     {
         if (attribute.AttributeClass?.ToDisplayString() != "System.Runtime.CompilerServices.NullableContextAttribute" &&
             attribute.AttributeClass?.ToDisplayString() != "System.Runtime.CompilerServices.NullableAttribute" &&
             attribute.AttributeClass?.ToDisplayString() != "LaDeak.JsonMergePatch.Abstractions.PatchableAttribute")
         {
             BuildAttribute(state, attribute);
         }
     }
 }
Пример #10
0
        private void BuildApplyPath(BuilderState state)
        {
            state.AppendLine($"public override {state.TypeInfo.SourceTypeName} ApplyPatch([System.Diagnostics.CodeAnalysis.AllowNull] {state.TypeInfo.SourceTypeName} input)");
            state.AppendLine("{");
            var bodyState = state.IncrementIdentation();

            CallConstructIfEmpty(bodyState, "input ??=", leaveOpen: false);
            SetInitOnlyProperties(bodyState);
            SetReadWriteProperties(bodyState);
            PopulateDictionaryProperties(bodyState);
            bodyState.AppendLine("return input;");
            state.AppendLine("}");
        }
Пример #11
0
        private void CallConstructIfEmpty(BuilderState state, string toInitialize, bool leaveOpen)
        {
            IEnumerable <string> parameters = Enumerable.Empty <string>();

            if (!HasDefaultConstructor(state.TypeInfo.TypeSymbol))
            {
                var typeSymbol = state.TypeInfo.TypeSymbol;
                var ctor       = typeSymbol.GetMembers().OfType <IMethodSymbol>().Where(x => x.MethodKind == MethodKind.Constructor).OrderByDescending(x => x.Parameters.Length).First();
                var properties = state.TypeInfo.Properties.Select(x => x.Property).ToList();
                parameters = Enumerable.Repeat("default", ctor.Parameters.Length);
            }
            var ending = leaveOpen ? "" : ";";

            state.AppendLine($"{toInitialize} new {state.TypeInfo.SourceTypeName}({string.Join(", ", parameters)}){ending}");
            return;
        }
Пример #12
0
        private void SetInitOnlyProperties(BuilderState state)
        {
            if (!state.TypeInfo.Properties.Any(x => IsInitOnlyProperty(x.Property)))
            {
                return;
            }
            CallConstructIfEmpty(state, "var tmp =", leaveOpen: true);
            state.AppendLine("{");
            var initializerState = state.IncrementIdentation();

            for (int i = 0; i < state.TypeInfo.Properties.Count; i++)
            {
                var currentProperty = state.TypeInfo.Properties[i].Property;
                if (IsInitOnlyProperty(currentProperty))
                {
                    if (GeneratedTypeFilter.IsGeneratableType(currentProperty.Type))
                    {
                        initializerState.AppendLine($"{currentProperty.Name} = Properties[{i}] ? this.{currentProperty.Name}?.ApplyPatch(input.{currentProperty.Name}) : input.{currentProperty.Name},");
                    }
                    else if (state.TypeInfo.Properties[i].IsGenericDictionary)
                    {
                        initializerState.AppendLine($"{currentProperty.Name} = Properties[{i}] && input.{currentProperty.Name} == null ? new() : input.Values,");
                    }
                    else if (state.TypeInfo.Properties[i].IsConvertedToNullableType)
                    {
                        initializerState.AppendLine($"{currentProperty.Name} = Properties[{i}] ? ({currentProperty.Name}.HasValue ? this.{currentProperty.Name}.Value : default) : input.{currentProperty.Name},");
                    }
                    else
                    {
                        initializerState.AppendLine($"{currentProperty.Name} = Properties[{i}] ? this.{currentProperty.Name} : input.{currentProperty.Name},");
                    }
                }
                else
                {
                    // Copy old property values onto the new object
                    initializerState.AppendLine($"{currentProperty.Name} = input.{currentProperty.Name},");
                }
            }
            state.AppendLine("};");
            state.AppendLine("input = tmp;");
        }
Пример #13
0
        private void BuildPropery(BuilderState state, PropertyInformation propertyInfo, int propertyId)
        {
            state.ToProcessTypeSymbols.Add(propertyInfo.Property.Type);
            string fieldName        = Casing.PrefixUnderscoreCamelCase(propertyInfo.Property.Name);
            string propertyTypeName = GetPropertyTypeName(propertyInfo);

            state.AppendLine($"private {propertyTypeName} {fieldName};");
            BuildAttributes(state, propertyInfo.Property.GetAttributes());
            state.AppendLine($"public {propertyTypeName} {propertyInfo.Property.Name}");
            state.AppendLine("{");
            var getterSetter = state.IncrementIdentation();

            getterSetter.AppendLine($"get {{ return {fieldName}; }}");
            getterSetter.AppendLine("set");
            getterSetter.AppendLine("{");
            var setterBody = getterSetter.IncrementIdentation();

            setterBody.AppendLine($"Properties[{propertyId}] = true;");
            setterBody.AppendLine($"{fieldName} = value;");
            getterSetter.AppendLine("}");
            state.AppendLine("}");
        }
Пример #14
0
 private void BuildClass(BuilderState state) => BuildClassDeclaration(state, s => BuildClassBody(s));
Пример #15
0
 private void BuildFile(BuilderState state) => BuildNamespace(state, BuildClass);
Пример #16
0
 private void BuildAttribute(BuilderState state, AttributeData attribute) => state.AppendLine($"[{attribute}]");