Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.

Commit fa2051d

Browse files
Merge pull request #837 from xamarin/alternative-binding-approach
first swath of naming utility refactoring.
2 parents 95210c6 + 85c9d01 commit fa2051d

File tree

10 files changed

+240
-143
lines changed

10 files changed

+240
-143
lines changed

DylibBinder/SwiftTypeToString.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public static string MapSwiftTypeToString (SwiftType swiftType, string moduleNam
1919

2020
public static SLType MapSwiftTypeToSlType (SwiftType swiftType)
2121
{
22-
var typeMapper = new TypeMapper (TypeDatabasePaths, null);
22+
var typeMapper = new TypeMapper (TypeDatabasePaths);
2323
var swiftTypeToSLType = new SwiftTypeToSLType (typeMapper, true);
2424
var sLImportModules = new SLImportModules ();
2525
return swiftTypeToSLType.MapType (sLImportModules, Exceptions.ThrowOnNull (swiftType, nameof (swiftType)));

SwiftReflector/MethodWrapping.cs

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using SwiftReflector.TypeMapping;
1616
using SwiftReflector.Demangling;
1717
using ObjCRuntime;
18+
using SwiftReflector.Naming;
1819

1920
namespace SwiftReflector {
2021

@@ -80,7 +81,7 @@ public static string WrapperOperatorName (TypeMapper typeMapper, string moduleNa
8081
throw new ArgumentOutOfRangeException (nameof (type));
8182
}
8283

83-
operatorName = CleanseOperatorName (typeMapper, operatorName);
84+
operatorName = CSSafeNaming.SafeOperatorName (operatorName);
8485
var classPrefix = moduleNameOrFullClassName.Replace ('.', 'D');
8586
return $"{kXamPrefix}{classPrefix}{operatorType}{operatorName}";
8687
}
@@ -2441,44 +2442,6 @@ void RecordWarning (FunctionDeclaration fn, BaseDeclaration context, string doin
24412442
errors.Add (ErrorHelper.CreateWarning (code, $"While {doingSomething} {whoAmI} {postMessage}."));
24422443
}
24432444

2444-
static Dictionary<char, string> operatorMap = new Dictionary<char, string> {
2445-
{ '/', "Slash" },
2446-
{ '=', "Equals" },
2447-
{ '+', "Plus" },
2448-
{ '-', "Minus" },
2449-
{ '!', "Bang" },
2450-
{ '*', "Star" },
2451-
{ '%', "Percent" },
2452-
{ '<', "LessThan" },
2453-
{ '>', "GreaterThan" },
2454-
{ '&', "Ampersand" },
2455-
{ '|', "Pipe" },
2456-
{ '^', "Hat" },
2457-
{ '~', "Tilde" },
2458-
{ '?', "QuestionMark"},
2459-
{ '.', "Dot" },
2460-
};
2461-
2462-
static string OperatorCharToSafeString (char c)
2463-
{
2464-
string result = null;
2465-
operatorMap.TryGetValue (c, out result);
2466-
return result ?? c.ToString ();
2467-
}
2468-
2469-
public string CleanseOperatorName (string s)
2470-
{
2471-
return CleanseOperatorName (typeMapper, s);
2472-
}
2473-
2474-
public static string CleanseOperatorName (TypeMapper typeMapper, string s)
2475-
{
2476-
var sb = new StringBuilder ();
2477-
foreach (var c in s) {
2478-
sb.Append (OperatorCharToSafeString (c));
2479-
}
2480-
return typeMapper.SanitizeIdentifier (sb.ToString ());
2481-
}
24822445

24832446
static DelegatedCommaListElemCollection<SLArgument> StripArgumentLabels (DelegatedCommaListElemCollection<SLArgument> args)
24842447
{

SwiftReflector/Naming/CSSafeNaming.cs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Globalization;
4+
using System.Linq;
5+
using System.Text;
6+
using Dynamo.CSLang;
7+
using SwiftReflector.TypeMapping;
8+
9+
#nullable enable
10+
11+
namespace SwiftReflector.Naming
12+
{
13+
public class CSSafeNaming {
14+
15+
static UnicodeCategory [] validStarts = {
16+
UnicodeCategory.UppercaseLetter,
17+
UnicodeCategory.LowercaseLetter,
18+
UnicodeCategory.TitlecaseLetter,
19+
UnicodeCategory.ModifierLetter,
20+
UnicodeCategory.OtherLetter,
21+
UnicodeCategory.LetterNumber
22+
};
23+
24+
static bool ValidIdentifierStart (UnicodeCategory cat)
25+
{
26+
return validStarts.Contains (cat);
27+
}
28+
29+
static UnicodeCategory [] validContent = {
30+
UnicodeCategory.DecimalDigitNumber,
31+
UnicodeCategory.ConnectorPunctuation,
32+
UnicodeCategory.Format
33+
};
34+
35+
static bool ValidIdentifierContent (UnicodeCategory cat)
36+
{
37+
return ValidIdentifierStart (cat) || validContent.Contains (cat);
38+
}
39+
40+
static bool IsValidIdentifier (int position, UnicodeCategory cat)
41+
{
42+
if (position == 0)
43+
return ValidIdentifierStart (cat);
44+
else
45+
return ValidIdentifierContent (cat);
46+
}
47+
48+
static bool IsHighUnicode (string s)
49+
{
50+
// Steve says: this is arbitrary, but it solves an issue
51+
// with mcs and csc not liking certain Ll and Lu class
52+
// unicode characters (for now).
53+
// Open issue: https://github.com/dotnet/roslyn/issues/27986
54+
var encoding = Encoding.UTF32;
55+
var bytes = encoding.GetBytes (s);
56+
var utf32Value = BitConverter.ToUInt32 (bytes, 0);
57+
return utf32Value > 0xffff;
58+
}
59+
60+
public static string SafeIdentifier (string name, ScopedNaming? naming = null)
61+
{
62+
var sb = new StringBuilder ();
63+
64+
var characterEnum = StringInfo.GetTextElementEnumerator (name);
65+
while (characterEnum.MoveNext ()) {
66+
string c = characterEnum.GetTextElement ();
67+
int i = characterEnum.ElementIndex;
68+
69+
var cat = CharUnicodeInfo.GetUnicodeCategory (name, i);
70+
71+
if (IsValidIdentifier (i, cat) && !IsHighUnicode (c))
72+
sb.Append (i == 0 && cat == UnicodeCategory.LowercaseLetter ? c.ToUpper () : c);
73+
else
74+
sb.Append (UnicodeMapper.MapToUnicodeName (c));
75+
}
76+
77+
if (CSKeywords.IsKeyword (sb.ToString ()))
78+
sb.Append ('_');
79+
return naming is not null ? naming.GenSym (sb.ToString ()) : sb.ToString ();
80+
}
81+
82+
public static CSIdentifier SafeCSIdentifier (string name, ScopedNaming? naming)
83+
{
84+
return new CSIdentifier (SafeIdentifier (name, naming));
85+
}
86+
87+
static Dictionary<char, string> operatorMap = new Dictionary<char, string> {
88+
{ '/', "Slash" },
89+
{ '=', "Equals" },
90+
{ '+', "Plus" },
91+
{ '-', "Minus" },
92+
{ '!', "Bang" },
93+
{ '*', "Star" },
94+
{ '%', "Percent" },
95+
{ '<', "LessThan" },
96+
{ '>', "GreaterThan" },
97+
{ '&', "Ampersand" },
98+
{ '|', "Pipe" },
99+
{ '^', "Hat" },
100+
{ '~', "Tilde" },
101+
{ '?', "QuestionMark"},
102+
{ '.', "Dot" },
103+
};
104+
105+
static string OperatorCharToSafeString (char c)
106+
{
107+
return operatorMap.TryGetValue (c, out var result) ? result : c.ToString ();
108+
}
109+
110+
public static string SafeOperatorName (string s)
111+
{
112+
var sb = new StringBuilder ();
113+
foreach (var c in s) {
114+
sb.Append (OperatorCharToSafeString (c));
115+
}
116+
return SafeIdentifier (sb.ToString ());
117+
}
118+
119+
public static UnicodeMapper UnicodeMapper = UnicodeMapper.Default;
120+
}
121+
}
122+

SwiftReflector/Naming/ScopedNaming.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Dynamo.CSLang;
4+
5+
#nullable enable
6+
7+
namespace SwiftReflector.Naming
8+
{
9+
public class ScopedNaming
10+
{
11+
string autoSymPrefix;
12+
Stack<HashSet<string>> names = new Stack<HashSet<string>> ();
13+
14+
public ScopedNaming (string autoSymPrefix = "_symbol")
15+
{
16+
this.autoSymPrefix = autoSymPrefix;
17+
names.Push (new HashSet<string> ());
18+
}
19+
20+
public void EnterScope ()
21+
{
22+
names.Push (new HashSet<string> (names.Peek ()));
23+
}
24+
25+
public void ExitScope ()
26+
{
27+
if (names.Count == 0)
28+
throw new Exception ("exited top level scope - that's bad");
29+
}
30+
31+
HashSet<string> Top => names.Peek ();
32+
33+
bool Contains (string symbol)
34+
{
35+
return Top.Contains (symbol);
36+
}
37+
38+
public string GenSym (string prefix)
39+
{
40+
if (string.IsNullOrEmpty (prefix))
41+
throw new ArgumentException ("prefix must not be empty", nameof (prefix));
42+
lock (names) {
43+
if (Contains (prefix)) {
44+
var index = 1;
45+
while (true) {
46+
var candidate = $"{prefix}{index}";
47+
if (!Contains (candidate)) {
48+
prefix = candidate;
49+
break;
50+
}
51+
index++;
52+
}
53+
}
54+
Top.Add (prefix);
55+
return prefix;
56+
}
57+
}
58+
59+
public CSIdentifier GenID (string prefix)
60+
{
61+
return new CSIdentifier (GenSym (prefix));
62+
}
63+
64+
65+
public string GenSym ()
66+
{
67+
return GenSym (autoSymPrefix);
68+
}
69+
}
70+
}
71+

0 commit comments

Comments
 (0)