Skip to content

Commit

Permalink
Merge pull request #713 from martinholden-skillsoft/master
Browse files Browse the repository at this point in the history
Updated to support Forcing ENUM to be bitwise
  • Loading branch information
RicoSuter committed Jun 19, 2018
2 parents 8975d6b + 3860621 commit f5ed433
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 1 deletion.
35 changes: 35 additions & 0 deletions src/NJsonSchema.CodeGeneration.CSharp.Tests/EnumTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,41 @@ public async Task When_enum_has_no_type_then_enum_is_generated()
Assert.Contains("public enum MyClassCategory", code);
}

[Fact]
public async Task When_enum_has_no_type_then_enum_is_generated_with_flags()
{
//// Arrange
var json =
@"{
""type"": ""object"",
""properties"": {
""category"" : {
""enum"" : [
""commercial"",
""residential"",
""government"",
""military"",
""foreigngovernment""
]
}
}
}";

var schema = await JsonSchema4.FromJsonAsync(json);
var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings { EnforceFlagEnums = true });

//// Act
var code = generator.GenerateFile("MyClass");

//// Assert
Assert.Contains("[System.Flags]", code);
Assert.Contains("Commercial = 1,", code);
Assert.Contains("Residential = 2,", code);
Assert.Contains("Government = 4,", code);
Assert.Contains("Military = 8,", code);
Assert.Contains("Foreigngovernment = 16,", code);
}

[Fact]
public async Task When_enum_name_contains_colon_then_it_is_removed_and_next_word_converted_to_upper_case()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public CSharpGeneratorSettings()
TypeAccessModifier = "public";
PropertySetterAccessModifier = string.Empty;
GenerateJsonMethods = true;
EnforceFlagEnums = false;

ValueGenerator = new CSharpValueGenerator(this);
PropertyNameGenerator = new CSharpPropertyNameGenerator();
Expand Down Expand Up @@ -104,5 +105,8 @@ public CSharpGeneratorSettings()

/// <summary>Gets or sets a value indicating whether to render ToJson() and FromJson() methods (default: true).</summary>
public bool GenerateJsonMethods { get; set; }

/// <summary>Gets or sets a value indicating whether enums should be always generated as bit flags (default: false).</summary>
public bool EnforceFlagEnums { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public EnumTemplateModel(string typeName, JsonSchema4 schema, CSharpGeneratorSet
/// <summary>Gets or sets the access modifier of generated classes and interfaces.</summary>
public string TypeAccessModifier => _settings.TypeAccessModifier;

/// <summary>Gets or sets if we output as Bit Flags.</summary>
public bool IsEnumAsBitFlags => _settings.EnforceFlagEnums || _schema.IsFlagEnumerable;

/// <summary>Gets the enum values.</summary>
public IEnumerable<EnumerationItemModel> Enums
{
Expand All @@ -65,7 +68,8 @@ public IEnumerable<EnumerationItemModel> Enums
{
Name = _settings.EnumNameGenerator.Generate(i, name, value, _schema),
Value = value.ToString(),
InternalValue = _schema.Type.HasFlag(JsonObjectType.Integer) ? value.ToString() : i.ToString()
InternalValue = _schema.Type.HasFlag(JsonObjectType.Integer) ? value.ToString() : i.ToString(),
InternalFlagValue = (1 << i).ToString()
});
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/NJsonSchema.CodeGeneration.CSharp/Templates/Enum.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@
/// <summary>{{ Description | csharpdocs }}</summary>
{% endif -%}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "{{ ToolchainVersion }}")]
{% if IsEnumAsBitFlags -%}
[System.Flags]
{% endif -%}
{{ TypeAccessModifier }} enum {{ Name }}
{
{% for enum in Enums -%}
{% if IsStringEnum -%}
[System.Runtime.Serialization.EnumMember(Value = "{{ enum.Value }}")]
{% endif -%}

{% if IsEnumAsBitFlags -%}
{{ enum.Name }} = {{ enum.InternalFlagValue }},
{% else -%}
{{ enum.Name }} = {{ enum.InternalValue }},
{% endif -%}


{% endfor -%}
}
3 changes: 3 additions & 0 deletions src/NJsonSchema.CodeGeneration/Models/EnumerationItemModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@ public class EnumerationItemModel

/// <summary>Gets or sets the internal value (e.g. the underlying/system value).</summary>
public string InternalValue { get; set; }

/// <summary>Gets or sets the internal flag value (e.g. the underlying/system value).</summary>
public string InternalFlagValue { get; set; }
}
}
98 changes: 98 additions & 0 deletions src/NJsonSchema.Tests/Generation/EnumTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,103 @@ public async Task When_SerializerSettings_has_CamelCase_StringEnumConverter_then
Assert.Equal("Value1", schema.EnumerationNames.First());
Assert.Equal("Value2", schema.EnumerationNames.Last());
}

[Flags]
public enum EnumWithFlags
{
Foo = 1,
Bar = 2,
Baz = 4,
}

[Fact]
public async Task When_enum_has_FlagsAttribute_then_custom_property_is_set()
{
// Arrange

//// Act
var schema = await JsonSchema4.FromTypeAsync<EnumWithFlags>(new JsonSchemaGeneratorSettings
{
DefaultEnumHandling = EnumHandling.String
});
var json = schema.ToJson();

// Assert
Assert.True(schema.IsFlagEnumerable);
Assert.Contains("x-enumFlags", json);
}

public enum EnumWithoutFlags
{
Foo = 1,
Bar = 2,
Baz = 3,
}

[Fact]
public async Task When_enum_does_not_have_FlagsAttribute_then_custom_property_is_not_set()
{
// Arrange

//// Act
var schema = await JsonSchema4.FromTypeAsync<EnumWithoutFlags>(new JsonSchemaGeneratorSettings
{
DefaultEnumHandling = EnumHandling.String
});
var json = schema.ToJson();

// Assert
Assert.False(schema.IsFlagEnumerable);
Assert.DoesNotContain("x-enumFlags", json);
}

[Flags]
public enum EnumWithFlags
{
Foo = 1,
Bar = 2,
Baz = 4,
}

[Fact]
public async Task When_enum_has_FlagsAttribute_then_custom_property_is_set()
{
// Arrange

//// Act
var schema = await JsonSchema4.FromTypeAsync<EnumWithFlags>(new JsonSchemaGeneratorSettings
{
DefaultEnumHandling = EnumHandling.String
});
var json = schema.ToJson();

// Assert
Assert.True(schema.IsFlagEnumerable);
Assert.Contains("x-enumFlags", json);
}

public enum EnumWithoutFlags
{
Foo = 1,
Bar = 2,
Baz = 3,
}

[Fact]
public async Task When_enum_does_not_have_FlagsAttribute_then_custom_property_is_not_set()
{
// Arrange

//// Act
var schema = await JsonSchema4.FromTypeAsync<EnumWithoutFlags>(new JsonSchemaGeneratorSettings
{
DefaultEnumHandling = EnumHandling.String
});
var json = schema.ToJson();

// Assert
Assert.False(schema.IsFlagEnumerable);
Assert.DoesNotContain("x-enumFlags", json);
}
}
}
1 change: 1 addition & 0 deletions src/NJsonSchema/Generation/JsonSchemaGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,7 @@ private void LoadEnumerations(Type type, JsonSchema4 schema, JsonTypeDescription
schema.Type = typeDescription.Type;
schema.Enumeration.Clear();
schema.EnumerationNames.Clear();
schema.IsFlagEnumerable = type.GetTypeInfo().GetCustomAttribute<FlagsAttribute>() != null;

var underlyingType = Enum.GetUnderlyingType(type);

Expand Down
4 changes: 4 additions & 0 deletions src/NJsonSchema/JsonSchema4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,10 @@ public IDictionary<string, JsonProperty> ActualProperties
[JsonProperty("x-example", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public object Example { get; set; }

/// <summary>Gets or sets a value indicating this is an bit flag enum (custom extension, sets 'x-enumFlags', default: false).</summary>
[JsonProperty("x-enumFlags", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public bool IsFlagEnumerable { get; set; }

/// <summary>Gets the collection of required properties. </summary>
[JsonIgnore]
public ICollection<object> Enumeration { get; internal set; }
Expand Down

0 comments on commit f5ed433

Please sign in to comment.