Skip to content

Commit

Permalink
Adding Proper Snake Case for issue efcore#151
Browse files Browse the repository at this point in the history
  • Loading branch information
jtenos committed Jan 29, 2024
1 parent 3df96e8 commit e085c9c
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public static IEnumerable<object[]> Convention()
NamingConvention.CamelCase => new NamingConventionsOptionsExtension().WithCamelCaseNamingConvention(),
NamingConvention.UpperCase => new NamingConventionsOptionsExtension().WithUpperCaseNamingConvention(),
NamingConvention.UpperSnakeCase => new NamingConventionsOptionsExtension().WithUpperSnakeCaseNamingConvention(),
NamingConvention.ProperSnakeCase => new NamingConventionsOptionsExtension().WithProperSnakeCaseNamingConvention(),
_ => throw new ArgumentOutOfRangeException($"Unhandled enum value: {convention}, NamingConventionsOptionsExtension not defined for the test")
};
}
Expand Down
4 changes: 4 additions & 0 deletions EFCore.NamingConventions.Test/RewriterTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ public void Camel_case()
[Fact]
public void Upper_case()
=> Assert.Equal("FULLNAME", new UpperCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));

[Fact]
public void Proper_snake_case()
=> Assert.Equal("Full_Name", new ProperSnakeCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
}
3 changes: 2 additions & 1 deletion EFCore.NamingConventions/Internal/NamingConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ public enum NamingConvention
LowerCase,
CamelCase,
UpperCase,
UpperSnakeCase
UpperSnakeCase,
ProperSnakeCase
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public ConventionSet ModifyConventions(ConventionSet conventionSet)
NamingConvention.CamelCase => new CamelCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
NamingConvention.UpperCase => new UpperCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
NamingConvention.UpperSnakeCase => new UpperSnakeCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
NamingConvention.ProperSnakeCase => new ProperSnakeCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
_ => throw new ArgumentOutOfRangeException("Unhandled enum value: " + namingStyle)
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ public virtual NamingConventionsOptionsExtension WithCamelCaseNamingConvention(C
return clone;
}

public virtual NamingConventionsOptionsExtension WithProperSnakeCaseNamingConvention(CultureInfo? culture = null)
{
var clone = Clone();
clone._namingConvention = NamingConvention.ProperSnakeCase;
clone._culture = culture;
return clone;
}

public void Validate(IDbContextOptions options) {}

public void ApplyServices(IServiceCollection services)
Expand Down Expand Up @@ -106,6 +114,7 @@ public override string LogFragment
NamingConvention.UpperCase => "using upper case naming",
NamingConvention.UpperSnakeCase => "using upper snake-case naming",
NamingConvention.CamelCase => "using camel-case naming",
NamingConvention.ProperSnakeCase => "using proper snake-case naming",
_ => throw new ArgumentOutOfRangeException("Unhandled enum value: " + Extension._namingConvention)
});

Expand Down
41 changes: 41 additions & 0 deletions EFCore.NamingConventions/Internal/ProperSnakeCaseNameRewriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Globalization;
using System.Text;

namespace EFCore.NamingConventions.Internal;

public class ProperSnakeCaseNameRewriter : SnakeCaseNameRewriter
{
private readonly CultureInfo _culture;

public ProperSnakeCaseNameRewriter(CultureInfo culture) : base(culture)
=> _culture = culture;

public override string RewriteName(string name)
{
if (string.IsNullOrEmpty(name))
{
return name;
}

name = base.RewriteName(name);

var arr = name.ToCharArray();
var shouldCapitalizeNext = true;

for (var i = 0; i < arr.Length; i++)
{
if (arr[i] == '_')
{
shouldCapitalizeNext = true;
}
else if (shouldCapitalizeNext)
{
arr[i] = char.ToUpper(arr[i]);
shouldCapitalizeNext = false;
}
}

return new(arr);
}
}
21 changes: 21 additions & 0 deletions EFCore.NamingConventions/NamingConventionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,25 @@ public static DbContextOptionsBuilder<TContext> UseCamelCaseNamingConvention<TCo
CultureInfo? culture = null)
where TContext : DbContext
=> (DbContextOptionsBuilder<TContext>)UseCamelCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);

public static DbContextOptionsBuilder UseProperSnakeCaseNamingConvention(
this DbContextOptionsBuilder optionsBuilder,
CultureInfo? culture = null)
{
Check.NotNull(optionsBuilder, nameof(optionsBuilder));

var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
?? new NamingConventionsOptionsExtension())
.WithProperSnakeCaseNamingConvention(culture);

((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);

return optionsBuilder;
}

public static DbContextOptionsBuilder<TContext> UseProperSnakeCaseNamingConvention<TContext>(
this DbContextOptionsBuilder<TContext> optionsBuilder,
CultureInfo? culture = null)
where TContext : DbContext
=> (DbContextOptionsBuilder<TContext>)UseProperSnakeCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);
}

0 comments on commit e085c9c

Please sign in to comment.