Skip to content

Commit 95dc44f

Browse files
committed
refactor: align named registration APIs
1 parent deef91a commit 95dc44f

73 files changed

Lines changed: 827 additions & 508 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/fory_compiler/generators/dart.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -436,13 +436,15 @@ def _dart_string_literal(self, value: str) -> str:
436436
escaped = value.replace("\\", "\\\\").replace("'", "\\'")
437437
return f"'{escaped}'"
438438

439-
def _registration_defaults(self, type_def: object) -> Tuple[str, str, str]:
439+
def _registration_defaults(self, type_def: object) -> Tuple[str, str]:
440440
if self.should_register_by_id(type_def):
441-
return str(type_def.type_id), "null", "null"
441+
return str(type_def.type_id), "null"
442+
name = self.registration_type_name(type_def)
443+
if self.package:
444+
name = f"{self.package}.{name}"
442445
return (
443446
"null",
444-
self._dart_string_literal(self.package or ""),
445-
self._dart_string_literal(self.registration_type_name(type_def)),
447+
self._dart_string_literal(name),
446448
)
447449

448450
def _supports_direct_container_cast(
@@ -1300,12 +1302,10 @@ def generate_module_type(self, indent: int) -> List[str]:
13001302

13011303
def registration_lines(type_def: object, call_line: str) -> List[str]:
13021304
n = self.local_name(type_def)
1303-
default_id, default_namespace, default_type_name = (
1304-
self._registration_defaults(type_def)
1305-
)
1305+
default_id, default_name = self._registration_defaults(type_def)
13061306
return [
13071307
f"{self.indent_str * (indent + 2)}if (type == {n}) {{",
1308-
f"{self.indent_str * (indent + 3)}{call_line.format(id=default_id, namespace=default_namespace, type_name=default_type_name)}",
1308+
f"{self.indent_str * (indent + 3)}{call_line.format(id=default_id, name=default_name)}",
13091309
f"{self.indent_str * (indent + 3)}return;",
13101310
f"{self.indent_str * (indent + 2)}}}",
13111311
]
@@ -1318,7 +1318,7 @@ def registration_lines(type_def: object, call_line: str) -> List[str]:
13181318
lines.extend(
13191319
registration_lines(
13201320
enum,
1321-
f"registerGeneratedEnum(fory, {schema_name}, id: {{id}}, namespace: {{namespace}}, typeName: {{type_name}});",
1321+
f"registerGeneratedEnum(fory, {schema_name}, id: {{id}}, name: {{name}});",
13221322
)
13231323
)
13241324
for union in self.schema.unions:
@@ -1328,7 +1328,7 @@ def registration_lines(type_def: object, call_line: str) -> List[str]:
13281328
lines.extend(
13291329
registration_lines(
13301330
union,
1331-
f"fory.registerSerializer({n}, const _{n}ForySerializer(), id: {{id}}, namespace: {{namespace}}, typeName: {{type_name}});",
1331+
f"fory.registerSerializer({n}, const _{n}ForySerializer(), id: {{id}}, name: {{name}});",
13321332
)
13331333
)
13341334

@@ -1340,7 +1340,7 @@ def visit_message(message: Message):
13401340
lines.extend(
13411341
registration_lines(
13421342
message,
1343-
f"registerGeneratedStruct(fory, {schema_name}, id: {{id}}, namespace: {{namespace}}, typeName: {{type_name}});",
1343+
f"registerGeneratedStruct(fory, {schema_name}, id: {{id}}, name: {{name}});",
13441344
)
13451345
)
13461346
for enum in message.nested_enums:
@@ -1349,15 +1349,15 @@ def visit_message(message: Message):
13491349
lines.extend(
13501350
registration_lines(
13511351
enum,
1352-
f"registerGeneratedEnum(fory, {schema_name}, id: {{id}}, namespace: {{namespace}}, typeName: {{type_name}});",
1352+
f"registerGeneratedEnum(fory, {schema_name}, id: {{id}}, name: {{name}});",
13531353
)
13541354
)
13551355
for union in message.nested_unions:
13561356
un = self.local_name(union)
13571357
lines.extend(
13581358
registration_lines(
13591359
union,
1360-
f"fory.registerSerializer({un}, const _{un}ForySerializer(), id: {{id}}, namespace: {{namespace}}, typeName: {{type_name}});",
1360+
f"fory.registerSerializer({un}, const _{un}ForySerializer(), id: {{id}}, name: {{name}});",
13611361
)
13621362
)
13631363
for nested in message.nested_messages:

compiler/fory_compiler/generators/python.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ def generate_enum_registration(
10311031
else:
10321032
ns = self.package or "default"
10331033
lines.append(
1034-
f' fory.register_type({class_ref}, namespace="{ns}", typename="{type_name}")'
1034+
f' fory.register_type({class_ref}, name="{ns}.{type_name}")'
10351035
)
10361036

10371037
def generate_message_registration(
@@ -1048,7 +1048,7 @@ def generate_message_registration(
10481048
else:
10491049
ns = self.package or "default"
10501050
lines.append(
1051-
f' fory.register_type({class_ref}, namespace="{ns}", typename="{type_name}")'
1051+
f' fory.register_type({class_ref}, name="{ns}.{type_name}")'
10521052
)
10531053

10541054
# Register nested enums
@@ -1081,5 +1081,5 @@ def generate_union_registration(
10811081
else:
10821082
ns = self.package or "default"
10831083
lines.append(
1084-
f' fory.register_union({class_ref}, namespace="{ns}", typename="{type_name}", serializer={serializer_ref}(fory.type_resolver))'
1084+
f' fory.register_union({class_ref}, name="{ns}.{type_name}", serializer={serializer_ref}(fory.type_resolver))'
10851085
)

compiler/fory_compiler/generators/swift.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,16 +1262,12 @@ def generate_module_type(self, indent: int = 0) -> List[str]:
12621262
continue
12631263

12641264
schema_type_name = self.schema_type_name(type_def)
1265-
escaped_name = schema_type_name.replace('"', '\\"')
12661265
if namespace:
1267-
escaped_ns = namespace.replace('"', '\\"')
1268-
lines.append(
1269-
f'{ind}{self.indent_str * 2}try fory.register({type_name}.self, namespace: "{escaped_ns}", name: "{escaped_name}")'
1270-
)
1271-
else:
1272-
lines.append(
1273-
f'{ind}{self.indent_str * 2}try fory.register({type_name}.self, name: "{escaped_name}")'
1274-
)
1266+
schema_type_name = f"{namespace}.{schema_type_name}"
1267+
escaped_name = schema_type_name.replace('"', '\\"')
1268+
lines.append(
1269+
f'{ind}{self.indent_str * 2}try fory.register({type_name}.self, name: "{escaped_name}")'
1270+
)
12751271
lines.append(f"{ind}{self.indent_str}" + "}")
12761272

12771273
lines.append(f"{ind}" + "}")

compiler/fory_compiler/tests/test_generated_code.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,77 @@ def test_java_nested_name_registration_uses_owner_namespace():
613613
)
614614

615615

616+
def test_generated_registration_uses_single_name_for_dart_python_swift():
617+
schema = parse_fdl(
618+
"""
619+
option enable_auto_type_id = false;
620+
package demo;
621+
622+
message Envelope {
623+
message Payload {
624+
int32 value = 1;
625+
}
626+
627+
enum Kind {
628+
UNKNOWN = 0;
629+
ACTIVE = 1;
630+
}
631+
632+
union Choice {
633+
Payload payload = 1;
634+
string note = 2;
635+
}
636+
637+
Payload payload = 1;
638+
Kind kind = 2;
639+
Choice choice = 3;
640+
}
641+
"""
642+
)
643+
644+
dart_output = render_files(generate_files(schema, DartGenerator))
645+
assert (
646+
"registerGeneratedStruct(fory, _envelopeForySchema, id: null, name: 'demo.Envelope');"
647+
in dart_output
648+
)
649+
assert (
650+
"registerGeneratedEnum(fory, _envelopeKindForySchema, id: null, name: 'demo.Envelope.Kind');"
651+
in dart_output
652+
)
653+
assert (
654+
"fory.registerSerializer(Envelope_Choice, const _Envelope_ChoiceForySerializer(), id: null, name: 'demo.Envelope.Choice');"
655+
in dart_output
656+
)
657+
assert "namespace:" not in dart_output
658+
assert "typeName:" not in dart_output
659+
660+
python_output = render_files(generate_files(schema, PythonGenerator))
661+
assert 'fory.register_type(Envelope, name="demo.Envelope")' in python_output
662+
assert (
663+
'fory.register_type(Envelope.Kind, name="demo.Envelope.Kind")' in python_output
664+
)
665+
assert (
666+
'fory.register_union(Envelope.Choice, name="demo.Envelope.Choice", serializer=Envelope.ChoiceSerializer(fory.type_resolver))'
667+
in python_output
668+
)
669+
assert "namespace=" not in python_output
670+
assert "typename=" not in python_output
671+
672+
swift_output = render_files(generate_files(schema, SwiftGenerator))
673+
assert (
674+
'try fory.register(Demo.Envelope.self, name: "demo.Envelope")' in swift_output
675+
)
676+
assert (
677+
'try fory.register(Demo.Envelope.Kind.self, name: "demo.Envelope.Kind")'
678+
in swift_output
679+
)
680+
assert (
681+
'try fory.register(Demo.Envelope.Choice.self, name: "demo.Envelope.Choice")'
682+
in swift_output
683+
)
684+
assert "namespace:" not in swift_output
685+
686+
616687
def test_java_default_package_import_registers_dependency(tmp_path):
617688
common = tmp_path / "common.fdl"
618689
common.write_text(

csharp/src/Fory/Fory.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,15 @@ public Fory Register<T>(uint typeId)
7777
}
7878

7979
/// <summary>
80-
/// Registers a user type by name using an empty namespace.
80+
/// Registers a user type by name.
8181
/// </summary>
8282
/// <typeparam name="T">Type to register.</typeparam>
83-
/// <param name="typeName">Type name used on the wire.</param>
83+
/// <param name="name">Name used on the wire. A dotted name is split at the last dot.</param>
8484
/// <returns>The same runtime instance.</returns>
85-
public Fory Register<T>(string typeName)
85+
public Fory Register<T>(string name)
8686
{
87-
_typeResolver.Register(typeof(T), string.Empty, typeName);
87+
(string namespaceName, string typeName) = TypeResolver.SplitTypeName(name);
88+
_typeResolver.Register(typeof(T), namespaceName, typeName);
8889
return this;
8990
}
9091

@@ -116,6 +117,22 @@ public Fory Register<T, TSerializer>(uint typeId)
116117
return this;
117118
}
118119

120+
/// <summary>
121+
/// Registers a user type by name with a custom serializer.
122+
/// </summary>
123+
/// <typeparam name="T">Type to register.</typeparam>
124+
/// <typeparam name="TSerializer">Serializer implementation used for <typeparamref name="T"/>.</typeparam>
125+
/// <param name="name">Name used on the wire. A dotted name is split at the last dot.</param>
126+
/// <returns>The same runtime instance.</returns>
127+
public Fory Register<T, TSerializer>(string name)
128+
where TSerializer : Serializer<T>, new()
129+
{
130+
(string namespaceName, string typeName) = TypeResolver.SplitTypeName(name);
131+
TypeInfo typeInfo = _typeResolver.RegisterSerializer<T, TSerializer>();
132+
_typeResolver.Register(typeof(T), namespaceName, typeName, typeInfo);
133+
return this;
134+
}
135+
119136
/// <summary>
120137
/// Registers a user type by namespace and name with a custom serializer.
121138
/// </summary>
@@ -127,6 +144,7 @@ public Fory Register<T, TSerializer>(uint typeId)
127144
public Fory Register<T, TSerializer>(string typeNamespace, string typeName)
128145
where TSerializer : Serializer<T>, new()
129146
{
147+
TypeResolver.ValidateSplitTypeName(typeNamespace, typeName);
130148
TypeInfo typeInfo = _typeResolver.RegisterSerializer<T, TSerializer>();
131149
_typeResolver.Register(typeof(T), typeNamespace, typeName, typeInfo);
132150
return this;

csharp/src/Fory/ThreadSafeFory.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,12 @@ public ThreadSafeFory Register<T>(uint typeId)
5757
/// Registers a user type by name for all current and future thread-local runtimes.
5858
/// </summary>
5959
/// <typeparam name="T">Type to register.</typeparam>
60-
/// <param name="typeName">Type name used on the wire.</param>
60+
/// <param name="name">Name used on the wire. A dotted name is split at the last dot.</param>
6161
/// <returns>The same runtime instance.</returns>
62-
public ThreadSafeFory Register<T>(string typeName)
62+
public ThreadSafeFory Register<T>(string name)
6363
{
64-
ApplyRegistration(fory => fory.Register<T>(typeName));
64+
_ = TypeResolver.SplitTypeName(name);
65+
ApplyRegistration(fory => fory.Register<T>(name));
6566
return this;
6667
}
6768

@@ -74,6 +75,7 @@ public ThreadSafeFory Register<T>(string typeName)
7475
/// <returns>The same runtime instance.</returns>
7576
public ThreadSafeFory Register<T>(string typeNamespace, string typeName)
7677
{
78+
TypeResolver.ValidateSplitTypeName(typeNamespace, typeName);
7779
ApplyRegistration(fory => fory.Register<T>(typeNamespace, typeName));
7880
return this;
7981
}
@@ -92,6 +94,21 @@ public ThreadSafeFory Register<T, TSerializer>(uint typeId)
9294
return this;
9395
}
9496

97+
/// <summary>
98+
/// Registers a user type by name with a custom serializer for all thread-local runtimes.
99+
/// </summary>
100+
/// <typeparam name="T">Type to register.</typeparam>
101+
/// <typeparam name="TSerializer">Serializer implementation used for <typeparamref name="T"/>.</typeparam>
102+
/// <param name="name">Name used on the wire. A dotted name is split at the last dot.</param>
103+
/// <returns>The same runtime instance.</returns>
104+
public ThreadSafeFory Register<T, TSerializer>(string name)
105+
where TSerializer : Serializer<T>, new()
106+
{
107+
_ = TypeResolver.SplitTypeName(name);
108+
ApplyRegistration(fory => fory.Register<T, TSerializer>(name));
109+
return this;
110+
}
111+
95112
/// <summary>
96113
/// Registers a user type by namespace and name with a custom serializer for all thread-local runtimes.
97114
/// </summary>
@@ -103,6 +120,7 @@ public ThreadSafeFory Register<T, TSerializer>(uint typeId)
103120
public ThreadSafeFory Register<T, TSerializer>(string typeNamespace, string typeName)
104121
where TSerializer : Serializer<T>, new()
105122
{
123+
TypeResolver.ValidateSplitTypeName(typeNamespace, typeName);
106124
ApplyRegistration(fory => fory.Register<T, TSerializer>(typeNamespace, typeName));
107125
return this;
108126
}

csharp/src/Fory/TypeResolver.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,43 @@ internal void Register(Type type, uint id, TypeInfo? explicitTypeInfo = null)
293293
InvalidateFinalizedVersion();
294294
}
295295

296+
internal static (string NamespaceName, string TypeName) SplitTypeName(string name)
297+
{
298+
ArgumentNullException.ThrowIfNull(name);
299+
if (name.Length == 0)
300+
{
301+
throw new ArgumentException("registration name must not be empty", nameof(name));
302+
}
303+
304+
int separator = name.LastIndexOf('.');
305+
if (separator == name.Length - 1)
306+
{
307+
throw new ArgumentException("registration name must end with a non-empty type name", nameof(name));
308+
}
309+
310+
return separator < 0
311+
? (string.Empty, name)
312+
: (name[..separator], name[(separator + 1)..]);
313+
}
314+
315+
internal static void ValidateSplitTypeName(string namespaceName, string typeName)
316+
{
317+
ArgumentNullException.ThrowIfNull(namespaceName);
318+
ArgumentNullException.ThrowIfNull(typeName);
319+
if (typeName.Length == 0)
320+
{
321+
throw new ArgumentException("typeName must not be empty", nameof(typeName));
322+
}
323+
324+
if (typeName.Contains(".", StringComparison.Ordinal))
325+
{
326+
throw new ArgumentException("typeName must not contain '.'", nameof(typeName));
327+
}
328+
}
329+
296330
internal void Register(Type type, string namespaceName, string typeName, TypeInfo? explicitTypeInfo = null)
297331
{
332+
ValidateSplitTypeName(namespaceName, typeName);
298333
TypeInfo typeInfo = GetOrCreateTypeInfo(type, explicitTypeInfo);
299334
MetaString namespaceMeta = MetaStringEncoder.Namespace.Encode(namespaceName, TypeMetaEncodings.NamespaceMetaStringEncodings);
300335
MetaString typeNameMeta = MetaStringEncoder.TypeName.Encode(typeName, TypeMetaEncodings.TypeNameMetaStringEncodings);

0 commit comments

Comments
 (0)