[Generator] Refactor more string extensions. (#17532)
Move all the string methods that can be an extension to a static class (re-use the present one) and add tests. --------- Co-authored-by: GitHub Actions Autoformatter <github-actions-autoformatter@xamarin.com> Co-authored-by: TJ Lambert <50846373+tj-devel709@users.noreply.github.com>
This commit is contained in:
Родитель
ec67c91627
Коммит
be1bee04b4
|
@ -160,86 +160,3 @@ public static class ReflectionExtensions {
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixes bug 27430 - btouch doesn't escape identifiers with the same name as C# keywords
|
|
||||||
public static class StringExtensions {
|
|
||||||
public static string? GetSafeParamName (this string? paramName)
|
|
||||||
{
|
|
||||||
if (paramName is null)
|
|
||||||
return paramName;
|
|
||||||
|
|
||||||
if (!IsValidIdentifier (paramName, out var hasIllegalChars)) {
|
|
||||||
return hasIllegalChars ? null : "@" + paramName;
|
|
||||||
}
|
|
||||||
return paramName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since we're building against the iOS assemblies and there's no code generation there,
|
|
||||||
// I'm bringing the implementation from:
|
|
||||||
// mono/mcs/class//System/Microsoft.CSharp/CSharpCodeGenerator.cs
|
|
||||||
static bool IsValidIdentifier (string? identifier, out bool hasIllegalChars)
|
|
||||||
{
|
|
||||||
hasIllegalChars = false;
|
|
||||||
if (identifier is null || identifier.Length == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (keywordsTable is null)
|
|
||||||
FillKeywordTable ();
|
|
||||||
|
|
||||||
if (keywordsTable!.Contains (identifier))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!is_identifier_start_character (identifier [0])) {
|
|
||||||
// if we are dealing with a number, we are ok, we can prepend @, else we have a problem
|
|
||||||
hasIllegalChars = !Char.IsNumber (identifier [0]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < identifier.Length; i++)
|
|
||||||
if (!is_identifier_part_character (identifier [i])) {
|
|
||||||
hasIllegalChars = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_identifier_start_character (char c)
|
|
||||||
{
|
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '@' || Char.IsLetter (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_identifier_part_character (char c)
|
|
||||||
{
|
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9') || Char.IsLetter (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FillKeywordTable ()
|
|
||||||
{
|
|
||||||
lock (keywords) {
|
|
||||||
if (keywordsTable is null) {
|
|
||||||
keywordsTable = new Hashtable ();
|
|
||||||
foreach (string keyword in keywords) {
|
|
||||||
keywordsTable.Add (keyword, keyword);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Hashtable? keywordsTable;
|
|
||||||
|
|
||||||
static string [] keywords = new string [] {
|
|
||||||
"abstract","event","new","struct","as","explicit","null","switch","base","extern",
|
|
||||||
"this","false","operator","throw","break","finally","out","true",
|
|
||||||
"fixed","override","try","case","params","typeof","catch","for",
|
|
||||||
"private","foreach","protected","checked","goto","public",
|
|
||||||
"unchecked","class","if","readonly","unsafe","const","implicit","ref",
|
|
||||||
"continue","in","return","using","virtual","default",
|
|
||||||
"interface","sealed","volatile","delegate","internal","do","is",
|
|
||||||
"sizeof","while","lock","stackalloc","else","static","enum",
|
|
||||||
"namespace",
|
|
||||||
"object","bool","byte","float","uint","char","ulong","ushort",
|
|
||||||
"decimal","int","sbyte","short","double","long","string","void",
|
|
||||||
"partial", "yield", "where"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -215,7 +215,7 @@ public partial class Generator {
|
||||||
if (sel.StartsWith ("input", StringComparison.Ordinal))
|
if (sel.StartsWith ("input", StringComparison.Ordinal))
|
||||||
name = sel;
|
name = sel;
|
||||||
else
|
else
|
||||||
name = "input" + Capitalize (sel);
|
name = "input" + sel.Capitalize ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.GetGetMethod () is not null) {
|
if (p.GetGetMethod () is not null) {
|
||||||
|
@ -239,7 +239,7 @@ public partial class Generator {
|
||||||
|
|
||||||
var selector = export.Selector;
|
var selector = export.Selector;
|
||||||
if (setter)
|
if (setter)
|
||||||
selector = "set" + Capitalize (selector) + ":";
|
selector = "set" + selector.Capitalize () + ":";
|
||||||
|
|
||||||
if (export.ArgumentSemantic != ArgumentSemantic.None && !p.PropertyType.IsPrimitive)
|
if (export.ArgumentSemantic != ArgumentSemantic.None && !p.PropertyType.IsPrimitive)
|
||||||
print ($"[Export (\"{selector}\", ArgumentSemantic.{export.ArgumentSemantic})]");
|
print ($"[Export (\"{selector}\", ArgumentSemantic.{export.ArgumentSemantic})]");
|
||||||
|
|
|
@ -5815,7 +5815,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
if (p == null)
|
if (p == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
print ($"[Advice ({Quote (p.Message)})]");
|
print ($"[Advice ({p.Message.Quote ()})]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintRequiresSuperAttribute (ICustomAttributeProvider mi)
|
public void PrintRequiresSuperAttribute (ICustomAttributeProvider mi)
|
||||||
|
@ -5833,7 +5833,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
if (p == null)
|
if (p == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
print ($"[NotImplemented ({Quote (p.Message)})]");
|
print ($"[NotImplemented ({p.Message.Quote ()})]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintBindAsAttribute (ICustomAttributeProvider mi, StringBuilder sb = null)
|
public void PrintBindAsAttribute (ICustomAttributeProvider mi, StringBuilder sb = null)
|
||||||
|
@ -6849,7 +6849,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
var sender = pars.Length == 0 ? "this" : pars [0].Name;
|
var sender = pars.Length == 0 ? "this" : pars [0].Name;
|
||||||
|
|
||||||
var miname = PascalCase (mi.Name);
|
var miname = mi.Name.PascalCase ();
|
||||||
if (miname == previous_miname) {
|
if (miname == previous_miname) {
|
||||||
// overloads, add a numbered suffix (it's internal)
|
// overloads, add a numbered suffix (it's internal)
|
||||||
previous_miname = miname;
|
previous_miname = miname;
|
||||||
|
@ -6889,7 +6889,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
} else
|
} else
|
||||||
eaname = "<NOTREACHED>";
|
eaname = "<NOTREACHED>";
|
||||||
|
|
||||||
print ("var handler = {0};", PascalCase (miname));
|
print ("var handler = {0};", miname.PascalCase ());
|
||||||
print ("if (handler != null){");
|
print ("if (handler != null){");
|
||||||
indent++;
|
indent++;
|
||||||
string eventArgs;
|
string eventArgs;
|
||||||
|
@ -6926,7 +6926,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
if (debug)
|
if (debug)
|
||||||
print ("Console.WriteLine (\"Method {0}.{1} invoked\");", dtype.Name, mi.Name);
|
print ("Console.WriteLine (\"Method {0}.{1} invoked\");", dtype.Name, mi.Name);
|
||||||
|
|
||||||
print ("var handler = {0};", PascalCase (miname));
|
print ("var handler = {0};", miname.PascalCase ());
|
||||||
print ("if (handler != null)");
|
print ("if (handler != null)");
|
||||||
print (" return handler ({0}{1});",
|
print (" return handler ({0}{1});",
|
||||||
sender,
|
sender,
|
||||||
|
@ -6989,7 +6989,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
print ("if (selHandle.Equals (sel{0}Handle))", mi.Name);
|
print ("if (selHandle.Equals (sel{0}Handle))", mi.Name);
|
||||||
}
|
}
|
||||||
++indent;
|
++indent;
|
||||||
print ("return {0} != null;", PascalCase (mi.Name));
|
print ("return {0} != null;", mi.Name.PascalCase ());
|
||||||
--indent;
|
--indent;
|
||||||
}
|
}
|
||||||
print ("return global::" + ns.Messaging + ".bool_objc_msgSendSuper_IntPtr (SuperHandle, " + selRespondsToSelector + ", selHandle);");
|
print ("return global::" + ns.Messaging + ".bool_objc_msgSendSuper_IntPtr (SuperHandle, " + selRespondsToSelector + ", selHandle);");
|
||||||
|
@ -7023,7 +7023,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
string ensureArg = bta.KeepRefUntil == null ? "" : "this";
|
string ensureArg = bta.KeepRefUntil == null ? "" : "this";
|
||||||
|
|
||||||
var miname = PascalCase (mi.Name);
|
var miname = mi.Name.PascalCase ();
|
||||||
if (miname == prev_miname) {
|
if (miname == prev_miname) {
|
||||||
// overloads, add a numbered suffix (it's internal)
|
// overloads, add a numbered suffix (it's internal)
|
||||||
prev_miname = miname;
|
prev_miname = miname;
|
||||||
|
@ -7035,14 +7035,14 @@ public partial class Generator : IMemberGatherer {
|
||||||
PrintObsoleteAttributes (mi);
|
PrintObsoleteAttributes (mi);
|
||||||
|
|
||||||
if (bta.Singleton && mi.GetParameters ().Length == 0 || mi.GetParameters ().Length == 1)
|
if (bta.Singleton && mi.GetParameters ().Length == 0 || mi.GetParameters ().Length == 1)
|
||||||
print ("public event EventHandler {0} {{", CamelCase (GetEventName (mi)));
|
print ("public event EventHandler {0} {{", GetEventName (mi).CamelCase ());
|
||||||
else
|
else
|
||||||
print ("public event EventHandler<{0}> {1} {{", GetEventArgName (mi), CamelCase (GetEventName (mi)));
|
print ("public event EventHandler<{0}> {1} {{", GetEventArgName (mi), GetEventName (mi).CamelCase ());
|
||||||
print ("\tadd {{ Ensure{0} ({1})!.{2} += value; }}", dtype.Name, ensureArg, miname);
|
print ("\tadd {{ Ensure{0} ({1})!.{2} += value; }}", dtype.Name, ensureArg, miname);
|
||||||
print ("\tremove {{ Ensure{0} ({1})!.{2} -= value; }}", dtype.Name, ensureArg, miname);
|
print ("\tremove {{ Ensure{0} ({1})!.{2} -= value; }}", dtype.Name, ensureArg, miname);
|
||||||
print ("}\n");
|
print ("}\n");
|
||||||
} else {
|
} else {
|
||||||
print ("public {0}? {1} {{", GetDelegateName (mi), CamelCase (GetDelegateApiName (mi)));
|
print ("public {0}? {1} {{", GetDelegateName (mi), GetDelegateApiName (mi).CamelCase ());
|
||||||
print ("\tget {{ return Ensure{0} ({1})!.{2}; }}", dtype.Name, ensureArg, miname);
|
print ("\tget {{ return Ensure{0} ({1})!.{2}; }}", dtype.Name, ensureArg, miname);
|
||||||
print ("\tset {{ Ensure{0} ({1})!.{2} = value; }}", dtype.Name, ensureArg, miname);
|
print ("\tset {{ Ensure{0} ({1})!.{2} = value; }}", dtype.Name, ensureArg, miname);
|
||||||
print ("}\n");
|
print ("}\n");
|
||||||
|
@ -7269,7 +7269,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
var safe_name = pi.Name.GetSafeParamName ();
|
var safe_name = pi.Name.GetSafeParamName ();
|
||||||
print ("public {0} {1} {{ get; set; }}",
|
print ("public {0} {1} {{ get; set; }}",
|
||||||
FormatType (type, pi.ParameterType),
|
FormatType (type, pi.ParameterType),
|
||||||
Capitalize (safe_name));
|
safe_name.Capitalize ());
|
||||||
|
|
||||||
if (comma)
|
if (comma)
|
||||||
ctor.Append (", ");
|
ctor.Append (", ");
|
||||||
|
@ -7282,7 +7282,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
print ("\npublic {0} ({1}) {{", async_type.Item1, ctor); indent++;
|
print ("\npublic {0} ({1}) {{", async_type.Item1, ctor); indent++;
|
||||||
foreach (var pi in async_type.Item2) {
|
foreach (var pi in async_type.Item2) {
|
||||||
var safe_name = pi.Name.GetSafeParamName ();
|
var safe_name = pi.Name.GetSafeParamName ();
|
||||||
print ("this.{0} = {1};", Capitalize (safe_name), safe_name);
|
print ("this.{0} = {1};", safe_name.Capitalize (), safe_name);
|
||||||
}
|
}
|
||||||
print ("Initialize ();");
|
print ("Initialize ();");
|
||||||
indent--; print ("}");
|
indent--; print ("}");
|
||||||
|
@ -7450,14 +7450,6 @@ public partial class Generator : IMemberGatherer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string Capitalize (string str)
|
|
||||||
{
|
|
||||||
if (str.StartsWith ("@", StringComparison.Ordinal))
|
|
||||||
return char.ToUpper (str [1]) + str.Substring (2);
|
|
||||||
|
|
||||||
return char.ToUpper (str [0]) + str.Substring (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
string GetNotificationCenter (PropertyInfo pi)
|
string GetNotificationCenter (PropertyInfo pi)
|
||||||
{
|
{
|
||||||
var a = AttributeManager.GetCustomAttributes<NotificationAttribute> (pi);
|
var a = AttributeManager.GetCustomAttributes<NotificationAttribute> (pi);
|
||||||
|
@ -7512,10 +7504,10 @@ public partial class Generator : IMemberGatherer {
|
||||||
{
|
{
|
||||||
var attrs = AttributeManager.GetCustomAttributes<EventNameAttribute> (pi);
|
var attrs = AttributeManager.GetCustomAttributes<EventNameAttribute> (pi);
|
||||||
if (attrs.Length == 0)
|
if (attrs.Length == 0)
|
||||||
return CamelCase (pi.Name).GetSafeParamName ();
|
return pi.Name.CamelCase ().GetSafeParamName ();
|
||||||
|
|
||||||
var a = attrs [0];
|
var a = attrs [0];
|
||||||
return CamelCase (a.EvtName).GetSafeParamName ();
|
return a.EvtName.CamelCase ().GetSafeParamName ();
|
||||||
}
|
}
|
||||||
|
|
||||||
string RenderArgs (IEnumerable<ParameterInfo> pi)
|
string RenderArgs (IEnumerable<ParameterInfo> pi)
|
||||||
|
@ -7533,16 +7525,6 @@ public partial class Generator : IMemberGatherer {
|
||||||
return parameters.Any (pi => pi.ParameterType.IsByRef);
|
return parameters.Any (pi => pi.ParameterType.IsByRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
string CamelCase (string ins)
|
|
||||||
{
|
|
||||||
return Char.ToUpper (ins [0]) + ins.Substring (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
string PascalCase (string ins)
|
|
||||||
{
|
|
||||||
return Char.ToLower (ins [0]) + ins.Substring (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<string, bool> skipGeneration = new Dictionary<string, bool> ();
|
Dictionary<string, bool> skipGeneration = new Dictionary<string, bool> ();
|
||||||
string GetEventName (MethodInfo mi)
|
string GetEventName (MethodInfo mi)
|
||||||
{
|
{
|
||||||
|
@ -7720,16 +7702,6 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Quote (string s)
|
|
||||||
{
|
|
||||||
if (s == null)
|
|
||||||
return String.Empty;
|
|
||||||
if (s == string.Empty)
|
|
||||||
return @"""""";
|
|
||||||
|
|
||||||
return $"@\"{s.Replace ("\"", "\"\"")}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string FormatPropertyInfo (PropertyInfo pi)
|
private static string FormatPropertyInfo (PropertyInfo pi)
|
||||||
{
|
{
|
||||||
return pi.DeclaringType.FullName + " " + pi.Name;
|
return pi.DeclaringType.FullName + " " + pi.Name;
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
// Fixes bug 27430 - btouch doesn't escape identifiers with the same name as C# keywords
|
||||||
|
public static class StringExtensions {
|
||||||
|
|
||||||
|
public static string Quote (this string? self)
|
||||||
|
{
|
||||||
|
return self switch {
|
||||||
|
null => String.Empty,
|
||||||
|
"" => @"""""",
|
||||||
|
_ => $"@\"{self.Replace ("\"", "\"\"")}\""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string CamelCase (this string ins)
|
||||||
|
{
|
||||||
|
return Char.ToUpper (ins [0]) + ins.Substring (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string PascalCase (this string ins)
|
||||||
|
{
|
||||||
|
return Char.ToLower (ins [0]) + ins.Substring (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Capitalize (this string str)
|
||||||
|
{
|
||||||
|
if (str.StartsWith ("@", StringComparison.Ordinal))
|
||||||
|
return char.ToUpper (str [1]) + str.Substring (2);
|
||||||
|
|
||||||
|
return char.ToUpper (str [0]) + str.Substring (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string? GetSafeParamName (this string? paramName)
|
||||||
|
{
|
||||||
|
if (paramName is null)
|
||||||
|
return paramName;
|
||||||
|
|
||||||
|
if (!IsValidIdentifier (paramName, out var hasIllegalChars)) {
|
||||||
|
return hasIllegalChars ? null : "@" + paramName;
|
||||||
|
}
|
||||||
|
return paramName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since we're building against the iOS assemblies and there's no code generation there,
|
||||||
|
// I'm bringing the implementation from:
|
||||||
|
// mono/mcs/class//System/Microsoft.CSharp/CSharpCodeGenerator.cs
|
||||||
|
static bool IsValidIdentifier (string? identifier, out bool hasIllegalChars)
|
||||||
|
{
|
||||||
|
hasIllegalChars = false;
|
||||||
|
if (String.IsNullOrEmpty (identifier))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (keywordsTable is null)
|
||||||
|
FillKeywordTable ();
|
||||||
|
|
||||||
|
if (keywordsTable!.Contains (identifier))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!is_identifier_start_character (identifier [0])) {
|
||||||
|
// if we are dealing with a number, we are ok, we can prepend @, else we have a problem
|
||||||
|
hasIllegalChars = !Char.IsNumber (identifier [0]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < identifier.Length; i++)
|
||||||
|
if (!is_identifier_part_character (identifier [i])) {
|
||||||
|
hasIllegalChars = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_identifier_start_character (char c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '@' || Char.IsLetter (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_identifier_part_character (char c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9') || Char.IsLetter (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillKeywordTable ()
|
||||||
|
{
|
||||||
|
lock (keywords) {
|
||||||
|
if (keywordsTable is null) {
|
||||||
|
keywordsTable = new Hashtable ();
|
||||||
|
foreach (string keyword in keywords) {
|
||||||
|
keywordsTable.Add (keyword, keyword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Hashtable? keywordsTable;
|
||||||
|
|
||||||
|
static string [] keywords = new string [] {
|
||||||
|
"abstract","event","new","struct","as","explicit","null","switch","base","extern",
|
||||||
|
"this","false","operator","throw","break","finally","out","true",
|
||||||
|
"fixed","override","try","case","params","typeof","catch","for",
|
||||||
|
"private","foreach","protected","checked","goto","public",
|
||||||
|
"unchecked","class","if","readonly","unsafe","const","implicit","ref",
|
||||||
|
"continue","in","return","using","virtual","default",
|
||||||
|
"interface","sealed","volatile","delegate","internal","do","is",
|
||||||
|
"sizeof","while","lock","stackalloc","else","static","enum",
|
||||||
|
"namespace",
|
||||||
|
"object","bool","byte","float","uint","char","ulong","ushort",
|
||||||
|
"decimal","int","sbyte","short","double","long","string","void",
|
||||||
|
"partial", "yield", "where"
|
||||||
|
};
|
||||||
|
}
|
|
@ -114,6 +114,7 @@
|
||||||
<Compile Include="..\src\bgen\NamespaceManager.cs" />
|
<Compile Include="..\src\bgen\NamespaceManager.cs" />
|
||||||
<Compile Include="..\src\bgen\NullabilityInfoContext.cs" />
|
<Compile Include="..\src\bgen\NullabilityInfoContext.cs" />
|
||||||
<Compile Include="..\src\bgen\PlatformNameExtensions.cs" />
|
<Compile Include="..\src\bgen\PlatformNameExtensions.cs" />
|
||||||
|
<Compile Include="..\src\bgen\StringExtensions.cs" />
|
||||||
<Compile Include="..\src\bgen\TrampolineInfo.cs" />
|
<Compile Include="..\src\bgen\TrampolineInfo.cs" />
|
||||||
<Compile Include="..\src\bgen\TypeManager.cs" />
|
<Compile Include="..\src\bgen\TypeManager.cs" />
|
||||||
<Compile Include="..\src\bgen\WrapPropMemberInformation.cs" />
|
<Compile Include="..\src\bgen\WrapPropMemberInformation.cs" />
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace GeneratorTests {
|
namespace GeneratorTests {
|
||||||
public class StringExtensionTests {
|
public class StringExtensionTests {
|
||||||
|
|
||||||
|
@ -45,5 +48,46 @@ namespace GeneratorTests {
|
||||||
Assert.IsNotNull (legal, "legal != null");
|
Assert.IsNotNull (legal, "legal != null");
|
||||||
Assert.AreEqual ("@" + illegal, legal, "legal");
|
Assert.AreEqual ("@" + illegal, legal, "legal");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void QuoteNullString ()
|
||||||
|
{
|
||||||
|
string? str = null;
|
||||||
|
Assert.AreEqual (string.Empty, str.Quote ());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void QuoteEmptyString ()
|
||||||
|
{
|
||||||
|
string str = String.Empty;
|
||||||
|
Assert.AreEqual (@"""""", str.Quote ());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase ("No quotes", "@\"No quotes\"")]
|
||||||
|
[TestCase ("\"quotes\"", "@\"\"\"quotes\"\"\"")]
|
||||||
|
public void QuoteString (string input, string output)
|
||||||
|
{
|
||||||
|
Assert.AreEqual (output, input.Quote ());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CamelCaseTest ()
|
||||||
|
{
|
||||||
|
var str = "pascalCaseExample";
|
||||||
|
Assert.AreEqual ("PascalCaseExample", str.CamelCase ());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void PascalCaseTest ()
|
||||||
|
{
|
||||||
|
var str = "CamelCaseExample";
|
||||||
|
Assert.AreEqual ("camelCaseExample", str.PascalCase ());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase ("@thisIsNotCapitalized", "ThisIsNotCapitalized")]
|
||||||
|
[TestCase ("thisIsNotCapitalized", "ThisIsNotCapitalized")]
|
||||||
|
[TestCase ("t", "T")]
|
||||||
|
public void CapitalizeTest (string input, string output)
|
||||||
|
=> Assert.AreEqual (output, input.Capitalize ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче