Skip to content

Commit

Permalink
improve AttributeTypeRef to handle type refs and other types of values
Browse files Browse the repository at this point in the history
  • Loading branch information
volkanceylan committed Oct 18, 2023
1 parent f7c27ec commit cc295d7
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 114 deletions.
17 changes: 9 additions & 8 deletions src/Serenity.Net.CodeGenerator/Commands/GenerateCommand.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Serenity.CodeGeneration;
using Serenity.Data.Schema;
using Spectre.Console;

Expand Down Expand Up @@ -121,18 +122,18 @@ public ExitCodes Run(string csproj, string[] args)

if (what != null)
{
config.GenerateRow = what.Contains('R', StringComparison.OrdinalIgnoreCase);
config.GenerateService = what.Contains('S', StringComparison.OrdinalIgnoreCase);
config.GenerateUI = what.Contains('U', StringComparison.OrdinalIgnoreCase);
config.GenerateCustom = what.Contains('C', StringComparison.OrdinalIgnoreCase);
config.GenerateRow = what == "*" || what.Contains('R', StringComparison.OrdinalIgnoreCase);
config.GenerateService = what == "*" || what.Contains('S', StringComparison.OrdinalIgnoreCase);
config.GenerateUI = what == "*" || what.Contains('U', StringComparison.OrdinalIgnoreCase);
config.GenerateCustom = what == "*" || what.Contains('C', StringComparison.OrdinalIgnoreCase);
}
else
{
var whatToGenerate = SelectWhatToGenerate();
config.GenerateRow = whatToGenerate.Contains("Row");
config.GenerateService = whatToGenerate.Contains("Services");
config.GenerateUI = whatToGenerate.Contains("User Interface");
config.GenerateCustom = whatToGenerate.Contains("Custom");
config.GenerateRow = whatToGenerate.Contains("Row", StringComparer.Ordinal);
config.GenerateService = whatToGenerate.Contains("Services", StringComparer.Ordinal);
config.GenerateUI = whatToGenerate.Contains("User Interface", StringComparer.Ordinal);
config.GenerateCustom = whatToGenerate.Contains("Custom", StringComparer.Ordinal);
}

foreach (var inputs in inputsList)
Expand Down
34 changes: 17 additions & 17 deletions src/Serenity.Net.CodeGenerator/Generator/EntityModelGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ private static EntityField ToEntityField(Data.Schema.FieldInfo fieldInfo, int pr
flags.Add(new("Serenity.Data.Mapping.PrimaryKey"));
else if (version)
{
flags.Add(new("Serenity.ComponentModel.Insertable", "false"));
flags.Add(new("Serenity.ComponentModel.Updatable", "false"));
flags.Add(new("Serenity.ComponentModel.Insertable", false));
flags.Add(new("Serenity.ComponentModel.Updatable", false));
}

if (!fieldInfo.IsNullable || version)
Expand Down Expand Up @@ -272,7 +272,7 @@ void makeUniquePropertyName(EntityField f)
if (tableField.PropertyName == model.Identity)
{
tableField.ColAttributeList.Add(new("Serenity.ComponentModel.EditLink"));
tableField.ColAttributeList.Add(new("System.ComponentModel.DisplayName", "\"Db.Shared.RecordId\""));
tableField.ColAttributeList.Add(new("System.ComponentModel.DisplayName", "Db.Shared.RecordId"));
tableField.ColAttributeList.Add(new("Serenity.ComponentModel.AlignRight"));
tableField.OmitInForm = true;
}
Expand Down Expand Up @@ -357,13 +357,13 @@ void makeUniquePropertyName(EntityField f)
foreignField.FieldName[foreignPrefixLength..]))?.Trim();

viewField.AttributeList.Add(new("System.ComponentModel.DisplayName",
"\"" + viewField.Title + "\""));
viewField.Title));

viewField.Expression = entityJoin.Alias + ".[" + viewField.Name + "]";

var expr = model.DeclareJoinConstants ?
"$\"{" + entityJoin.Alias + "}.[" + viewField.Name + "]\"" :
("\"" + viewField.Expression + "\"");
object expr = model.DeclareJoinConstants ?
new RawCode("$\"{" + entityJoin.Alias + "}.[" + viewField.Name + "]\"") :
(viewField.Expression);

viewField.AttributeList.Add(new("Serenity.Data.Mapping.Expression", expr));

Expand All @@ -377,27 +377,27 @@ void makeUniquePropertyName(EntityField f)
{
var attrs = tableField.AttributeList;

attrs.Add(new("System.ComponentModel.DisplayName", "\"" + tableField.Title + "\""));
attrs.Add(new("System.ComponentModel.DisplayName", tableField.Title));

if (tableField.PropertyName != tableField.Name)
attrs.Add(new("Serenity.Data.Mapping.Column", "\"" + tableField.Name + "\""));
attrs.Add(new("Serenity.Data.Mapping.Column", tableField.Name));

if ((tableField.Size ?? 0) > 0)
attrs.Add(new("Serenity.Data.Mapping.Size", tableField.Size.ToString()));
attrs.Add(new("Serenity.Data.Mapping.Size", tableField.Size ?? 0));

if (tableField.Scale > 0)
attrs.Add(new("Serenity.Data.Mapping.Scale", tableField.Scale.ToString()));
attrs.Add(new("Serenity.Data.Mapping.Scale", tableField.Scale));

if (!tableField.FlagList.IsEmptyOrNull())
attrs.AddRange(tableField.FlagList);

if (!string.IsNullOrEmpty(tableField.PKTable))
{
attrs.Add(new("Serenity.Data.Mapping.ForeignKey", "\"" +
(string.IsNullOrEmpty(tableField.PKSchema) ? tableField.PKTable : ("[" + tableField.PKSchema + "].[" + tableField.PKTable + "]")) + "\", " +
"\"" + tableField.PKColumn + "\""));
var alias = model.DeclareJoinConstants ?
tableField.ForeignJoinAlias : ("\"" + tableField.ForeignJoinAlias + "\"");
var pkTable = string.IsNullOrEmpty(tableField.PKSchema) ? tableField.PKTable : ("[" + tableField.PKSchema + "].[" + tableField.PKTable + "]");
attrs.Add(new("Serenity.Data.Mapping.ForeignKey", pkTable, tableField.PKColumn));

object alias = model.DeclareJoinConstants ?
new RawCode(tableField.ForeignJoinAlias) : tableField.ForeignJoinAlias;
attrs.Add(new("Serenity.Data.Mapping.LeftJoin", alias));
}

Expand All @@ -413,7 +413,7 @@ void makeUniquePropertyName(EntityField f)

if (tableField.TextualField != null)
attrs.Add(new("Serenity.Data.Mapping.TextualField",
"nameof(" + tableField.TextualField + ")"));
new RawCode("nameof(" + tableField.TextualField + ")")));
}

return model;
Expand Down
13 changes: 3 additions & 10 deletions src/Serenity.Net.CodeGenerator/Helpers/CSharpDynamicUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static ScriptObject GetScriptObject(CodeWriter cw)

scriptObject.Import("TYPEREF", new TypeDelegate((fullName) =>
{
return cw.ShortTypeName(cw, fullName);
return cw.ShortTypeRef(fullName);
}));

scriptObject.Import("TYPEREFLIST", new TypeListDelegate((fullNames) =>
Expand All @@ -29,7 +29,7 @@ public static ScriptObject GetScriptObject(CodeWriter cw)

foreach (var fullName in fullNames)
{
result.Add(cw.ShortTypeName(cw, fullName));
result.Add(cw.ShortTypeRef(fullName));
}

return string.Join(", ", result);
Expand All @@ -40,14 +40,7 @@ public static ScriptObject GetScriptObject(CodeWriter cw)
if (models == null)
return "";

HashSet<string> result = new();

foreach (var model in models)
{
result.Add(cw.ShortTypeName(cw, model.TypeName) + (string.IsNullOrEmpty(model.Arguments) ? "" : "(" + model.Arguments + ")"));
}

return string.Join(", ", result);
return string.Join(", ", models.Select(x => x.ToString(cw)));
}));

scriptObject.Import("USING", new UsingDelegate((requestedNamespace) =>
Expand Down
38 changes: 33 additions & 5 deletions src/Serenity.Net.CodeGenerator/Models/AttributeTypeRef.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,41 @@
namespace Serenity.CodeGenerator;
namespace Serenity.CodeGenerator;

public class AttributeTypeRef
{
public string TypeName { get; set; }
public string Arguments { get; set; }
public string TypeName { get; }
public object[] Arguments { get; }

public AttributeTypeRef(string typeName, string arguments = null)
public AttributeTypeRef(string typeName, params object[] arguments)
{
TypeName = typeName;
TypeName = typeName ?? throw new ArgumentNullException(nameof(typeName));
Arguments = arguments;
}

public string ToString(CodeWriter cw)
{
var s = cw.ShortTypeRef(TypeName);
if (Arguments == null || Arguments.Length == 0)
return s;

s += "(";
for (var i = 0; i < Arguments.Length; i++)
{
var value = Arguments[i];
if (i > 0)
s += ", ";

if (value is TypeNameRef tr)
s += tr.ToString(cw);
else if (value is string str)
s += StringHelper.ToDoubleQuoted(str);
else if (value is bool b)
s += b ? "true" : "false";
else if (value is IFormattable fmt)
s += fmt.ToString(null, CultureInfo.InvariantCulture);
else
s += value?.ToString() ?? "null";
}

return s + ")";
}
}
8 changes: 4 additions & 4 deletions src/Serenity.Net.CodeGenerator/Models/EntityField.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Serenity.CodeGenerator;
namespace Serenity.CodeGenerator;

public class EntityField
{
Expand All @@ -12,7 +12,7 @@ public class EntityField
public string Name { get; set; }
public string Title { get; set; }
public List<AttributeTypeRef> FlagList { get; } = new();
public string Flags { get => FlagList == null ? null : string.Join(", ", FlagList.Select(x => x.TypeName + (string.IsNullOrEmpty(x.Arguments) ? "" : "(" + x.Arguments + ")"))); }
public string Flags { get => FlagList == null ? null : string.Join(", ", FlagList.Select(x => x.ToString(new CodeWriter { IsCSharp = true }))); }
public string PKSchema { get; set; }
public string PKTable { get; set; }
public string PKColumn { get; set; }
Expand All @@ -22,9 +22,9 @@ public class EntityField
public int Scale { get; set; }
public string TextualField { get; set; }
public List<AttributeTypeRef> AttributeList { get; } = new();
public string Attributes => string.Join(", ", AttributeList.Select(x => x.TypeName + (string.IsNullOrEmpty(x.Arguments) ? "" : "(" + x.Arguments + ")")));
public string Attributes => string.Join(", ", AttributeList.Select(x => x.ToString(new CodeWriter { IsCSharp = true })));
public List<AttributeTypeRef> ColAttributeList { get; } = new();
public string ColAttributes => string.Join(", ", ColAttributeList.Select(x => x.TypeName + (string.IsNullOrEmpty(x.Arguments) ? "" : "(" + x.Arguments + ")")));
public string ColAttributes => string.Join(", ", ColAttributeList.Select(x => x.ToString(new CodeWriter { IsCSharp = true })));
public string Expression { get; set; }

public string TSEditorType
Expand Down
16 changes: 16 additions & 0 deletions src/Serenity.Net.CodeGenerator/Models/RawCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Serenity.CodeGenerator;

public class RawCode
{
public string Code { get; }

public RawCode(string code)
{
Code = code ?? throw new ArgumentNullException(nameof(code));
}

public override string ToString()
{
return Code;
}
}
16 changes: 16 additions & 0 deletions src/Serenity.Net.CodeGenerator/Models/TypeNameRef.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Serenity.CodeGenerator;

public class TypeNameRef
{
public string TypeName { get; }

public TypeNameRef(string typeName)
{
TypeName = typeName ?? throw new ArgumentNullException(nameof(typeName));
}

public string ToString(CodeWriter cw)
{
return "typeof(" + cw.ShortTypeRef(TypeName) + ")";
}
}
71 changes: 35 additions & 36 deletions src/Serenity.Net.Core/Reflection/CodeWriter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
namespace Serenity.Reflection;

/// <summary>
Expand Down Expand Up @@ -338,21 +338,21 @@ public StringBuilder Insert(int index, string text)
/// <summary>
/// Tries to add namespace
/// </summary>
/// <param name="nameSpace"></param>
/// <param name="typeName"></param>
/// <param name="ns">Namespace</param>
/// <param name="typeName">Type name</param>
/// <returns>if succeeds returns only typeName if fails returns fullName</returns>
public string ShortTypeName(string nameSpace, string typeName)
public string ShortTypeName(string ns, string typeName)
{
if (string.IsNullOrEmpty(typeName))
return string.Empty;

if (string.IsNullOrEmpty(nameSpace))
if (string.IsNullOrEmpty(ns))
return typeName;

if (Using(nameSpace))
if (Using(ns))
return typeName;
else
return nameSpace + "." + typeName;
return ns + "." + typeName;
}

/// <summary>
Expand Down Expand Up @@ -433,14 +433,13 @@ public static bool IsCSKeyword(string dataType)
}

/// <summary>
/// Converts datatype with a namespace to datatype without namespace if its namespace is in the allowed usings else returns fullname.
/// <para>
/// Converts datatype with a namespace to datatype without namespace if its namespace
/// is in the allowed usings else returns fullname.
/// This can handle nullables, CS keywords and generics to some extent.
/// Please see <see cref="IsCSharp"/> if you are using this for C#
/// </para>
/// </summary>
/// <param name="cw"></param>
/// <param name="fullName"></param>
public string ShortTypeName(CodeWriter cw, string fullName)
/// <param name="fullName">Full name of the class</param>
public string ShortTypeRef(string fullName)
{
fullName = fullName.Trim();

Expand All @@ -454,37 +453,37 @@ public string ShortTypeName(CodeWriter cw, string fullName)
nullableText = "?";
}

if (IsCSharp)
{
if (IsCSKeyword(fullName))
return fullName + nullableText;
if (!IsCSharp)
return ShortTypeName(fullName) + nullableText;

if (IsCSKeyword(fullName))
return fullName + nullableText;

if (fullName.IndexOf('.', StringComparison.OrdinalIgnoreCase) < 0)
if (fullName.IndexOf('.', StringComparison.OrdinalIgnoreCase) < 0)
{
if (fullName == "Stream")
fullName = "System.IO.Stream";
else
{
if (fullName == "Stream")
fullName = "System.IO.Stream";
else
var type = Type.GetType("System." + fullName);

if (type != null)
{
var type = Type.GetType("System." + fullName);

if (type != null)
{
fullName = type.FullName;
}
else
return fullName + nullableText;
fullName = type.FullName;
}
else
return fullName + nullableText;
}
}

if (fullName.EndsWith(">"))
{
var idx = fullName.IndexOf('<', StringComparison.OrdinalIgnoreCase);
if (idx >= 0)
return cw.ShortTypeName(fullName[..idx]) + '<' + ShortTypeName(cw, fullName[(idx + 1)..^1]) + '>' + nullableText;
}
if (fullName.EndsWith(">"))
{
var idx = fullName.IndexOf('<', StringComparison.OrdinalIgnoreCase);
if (idx >= 0)
return ShortTypeName(fullName[..idx]) + '<' + ShortTypeRef(fullName[(idx + 1)..^1]) + '>' + nullableText;
}

return cw.ShortTypeName(fullName) + nullableText;
return ShortTypeName(fullName) + nullableText;
}

/// <summary>
Expand Down
Loading

0 comments on commit cc295d7

Please sign in to comment.