Skip to content

Commit

Permalink
Compensate for bad names from stored proc results (#2731)
Browse files Browse the repository at this point in the history
fixes #2727
fixes #2729
  • Loading branch information
ErikEJ authored Dec 14, 2024
1 parent 69a1154 commit 439c844
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 36 deletions.
1 change: 1 addition & 0 deletions src/Core/RevEng.Core.80/RevEng.Core.80.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql.NetTopologySuite" Version="8.0.2" />
<PackageReference Include="SimplerSoftware.EntityFrameworkCore.SqlServer.NodaTime" Version="8.0.1" />
<PackageReference Include="System.CodeDom" Version="8.0.0" />
<PackageReference Include="UnicodeInformation" Version="2.7.1" />
</ItemGroup>

<ItemGroup>
Expand Down
71 changes: 39 additions & 32 deletions src/Core/RevEng.Core.80/Routines/ScaffoldHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Unicode;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Scaffolding;
using RevEng.Core.Abstractions.Metadata;
Expand Down Expand Up @@ -151,7 +152,7 @@ public static string GenerateIdentifierName(Routine routine, RoutineModel model,
{
var name = GenerateUniqueName(routine, model);

return CreateIdentifier(name, name, false).Item1;
return CreateIdentifier(name, name, code).Item1;
}
else
{
Expand All @@ -167,62 +168,68 @@ public static Tuple<string, string> GeneratePropertyName(string propertyName, IC

if (!usePascalCase)
{
return CreateIdentifier(propertyName, propertyName, false);
return CreateIdentifier(propertyName, propertyName, code);
}
else
{
var identifier = code.Identifier(propertyName, capitalize: true);
var name = GenerateIdentifier(code.Identifier(propertyName, capitalize: true));

return CreateIdentifier(GenerateIdentifier(identifier), propertyName, true);
string columAttribute = null;
if (!name.Equals(propertyName, StringComparison.Ordinal))
{
columAttribute = $"[Column(\"{propertyName}\")]";
}

return new Tuple<string, string>(name, columAttribute);
}
}

public static Tuple<string, string> CreateIdentifier(string name, string propertyName, bool usePascalCase)
public static Tuple<string, string> CreateIdentifier(string name, string propertyName, ICSharpHelper code)
{
if (!usePascalCase)
{
var original = name;
var original = name;

var isValid = System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(name);
var isValid = System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(name);

string columAttribute = null;
string columAttribute = null;

if (!isValid)
{
columAttribute = $"[Column(\"{name}\")]";

if (!isValid)
// File name contains invalid chars, remove them
var regex = new Regex(@"[^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Nl}\p{Mn}\p{Mc}\p{Cf}\p{Pc}\p{Lm}]", RegexOptions.None, TimeSpan.FromSeconds(5));
name = regex.Replace(name, string.Empty);

if (string.IsNullOrWhiteSpace(name))
{
columAttribute = $"[Column(\"{name}\")]";
var fixedName = string.Empty;
foreach (var chr in original)
{
#pragma warning disable S1643 // Strings should not be concatenated using '+' in a loop
fixedName += UnicodeInfo.GetName(chr) + " ";
#pragma warning restore S1643 // Strings should not be concatenated using '+' in a loop
}

// File name contains invalid chars, remove them
var regex = new Regex(@"[^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Nl}\p{Mn}\p{Mc}\p{Cf}\p{Pc}\p{Lm}]", RegexOptions.None, TimeSpan.FromSeconds(5));
name = regex.Replace(name, string.Empty);
name = GenerateIdentifier(fixedName);

if (string.IsNullOrWhiteSpace(name))
{
// we cannot fix it
name = original;
}
else if (!char.IsLetter(name, 0))
{
name = name.Insert(0, "_");
}
}

if (KeyWords.Contains(name))
else if (!char.IsLetter(name, 0))
{
name = "@" + name;
name = name.Insert(0, "_");
}

return new Tuple<string, string>(name.Replace(" ", string.Empty, StringComparison.OrdinalIgnoreCase), columAttribute);
}
else
{
string columAttribute = null;
if (!name.Equals(propertyName, StringComparison.Ordinal))
{
columAttribute = $"[Column(\"{propertyName}\")]";
}

return new Tuple<string, string>(name, columAttribute);
if (KeyWords.Contains(name))
{
name = "@" + name;
}

return new Tuple<string, string>(name.Replace(" ", string.Empty, StringComparison.OrdinalIgnoreCase), columAttribute);
}

private static string GenerateUniqueName(Routine routine, RoutineModel model)
Expand Down
21 changes: 17 additions & 4 deletions src/Core/RevEng.Core.80/Routines/Scaffolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,23 @@ private void GenerateClass(List<ModuleResultElement> resultElements, string name

private void GenerateProperties(List<ModuleResultElement> resultElements, bool nullableReferences, bool useDecimalDataAnnotation, bool usePascalCase)
{
var propertyNames = new List<string>();

int i = 0;

foreach (var property in resultElements.OrderBy(e => e.Ordinal))
{
var propertyNames = ScaffoldHelper.GeneratePropertyName(property.Name, Code, usePascalCase);
var propertyNameAndAttribute = ScaffoldHelper.GeneratePropertyName(property.Name, Code, usePascalCase);

if (property.StoreType == "decimal" && useDecimalDataAnnotation)
{
Sb.AppendLine($"[Column(\"{property.Name}\", TypeName = \"{property.StoreType}({property.Precision},{property.Scale})\")]");
}
else
{
if (!string.IsNullOrEmpty(propertyNames.Item2))
if (!string.IsNullOrEmpty(propertyNameAndAttribute.Item2))
{
Sb.AppendLine(propertyNames.Item2);
Sb.AppendLine(propertyNameAndAttribute.Item2);
}
}

Expand Down Expand Up @@ -128,7 +132,16 @@ private void GenerateProperties(List<ModuleResultElement> resultElements, bool n
}
}

Sb.AppendLine($"public {Code.Reference(propertyType)}{nullableAnnotation} {propertyNames.Item1} {{ get; set; }}{defaultAnnotation}");
var propertyName = propertyNameAndAttribute.Item1;

if (propertyNames.Contains(propertyName, StringComparer.Ordinal))
{
propertyName = $"{propertyName}_Duplicate{i++}";
}

propertyNames.Add(propertyNameAndAttribute.Item1);

Sb.AppendLine($"public {Code.Reference(propertyType)}{nullableAnnotation} {propertyName} {{ get; set; }}{defaultAnnotation}");
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Core/RevEng.Core.90/RevEng.Core.90.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql.NetTopologySuite" Version="9.0.0-preview.2.efcore.9.0.0" />
<PackageReference Include="SimplerSoftware.EntityFrameworkCore.SqlServer.NodaTime" Version="9.0.0" />
<PackageReference Include="System.CodeDom" Version="8.0.0" />
<PackageReference Include="UnicodeInformation" Version="2.7.1" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 439c844

Please sign in to comment.