Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use lower camel case names for error types in Swift bindings #2351

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

crazytonyli
Copy link
Contributor

This PR updates the Swift bindings code to use lowerCamelCase for error enum cases, to follow Swift's coding convention (example).

I'm not sure it's worth adding a new Swift-specific config to uniffi.toml here. The PR introduces breaking changes, but they are easy to fix. I'd say most Swift developers would prefer the new generated code.

Here is a before and after difference:

diff
--- ./error_types-before.swift	2024-12-11 18:12:14
+++ ./error_types-after.swift	2024-12-11 18:11:40
@@ -1286,14 +1286,14 @@
 
     
     
-    case Oops
-    case Value(value: String
-    )
-    case IntValue(value: UInt16
+    case oops
+    case value(value: String
     )
-    case FlatInnerError(error: FlatInner
+    case intValue(value: UInt16
+    )
+    case flatInnerError(error: FlatInner
     )
-    case InnerError(error: Inner
+    case innerError(error: Inner
     )
 }
 
\ No newline at end of file
@@ -1311,17 +1311,17 @@
         
 
         
-        case 1: return .Oops
-        case 2: return .Value(
+        case 1: return .oops
+        case 2: return .value(
             value: try FfiConverterString.read(from: &buf)
             )
-        case 3: return .IntValue(
+        case 3: return .intValue(
             value: try FfiConverterUInt16.read(from: &buf)
             )
-        case 4: return .FlatInnerError(
+        case 4: return .flatInnerError(
             error: try FfiConverterTypeFlatInner.read(from: &buf)
             )
-        case 5: return .InnerError(
+        case 5: return .innerError(
             error: try FfiConverterTypeInner.read(from: &buf)
             )
 
\ No newline at end of file
@@ -1336,26 +1336,26 @@
 
         
         
-        case .Oops:
+        case .oops:
             writeInt(&buf, Int32(1))
         
         
-        case let .Value(value):
+        case let .value(value):
             writeInt(&buf, Int32(2))
             FfiConverterString.write(value, into: &buf)
             
         
-        case let .IntValue(value):
+        case let .intValue(value):
             writeInt(&buf, Int32(3))
             FfiConverterUInt16.write(value, into: &buf)
             
         
-        case let .FlatInnerError(error):
+        case let .flatInnerError(error):
             writeInt(&buf, Int32(4))
             FfiConverterTypeFlatInner.write(error, into: &buf)
             
         
-        case let .InnerError(error):
+        case let .innerError(error):
             writeInt(&buf, Int32(5))
             FfiConverterTypeInner.write(error, into: &buf)
             
\ No newline at end of file
@@ -1377,9 +1377,9 @@
 
     
     
-    case CaseA(message: String)
+    case caseA(message: String)
     
-    case CaseB(message: String)
+    case caseB(message: String)
     
 }
 
\ No newline at end of file
@@ -1397,11 +1397,11 @@
         
 
         
-        case 1: return .CaseA(
+        case 1: return .caseA(
             message: try FfiConverterString.read(from: &buf)
         )
         
-        case 2: return .CaseB(
+        case 2: return .caseB(
             message: try FfiConverterString.read(from: &buf)
         )
         
\ No newline at end of file
@@ -1416,9 +1416,9 @@
         
 
         
-        case .CaseA(_ /* message is ignored*/):
+        case .caseA(_ /* message is ignored*/):
             writeInt(&buf, Int32(1))
-        case .CaseB(_ /* message is ignored*/):
+        case .caseB(_ /* message is ignored*/):
             writeInt(&buf, Int32(2))
 
         
\ No newline at end of file
@@ -1440,7 +1440,7 @@
 
     
     
-    case CaseA(String
+    case caseA(String
     )
 }
 
\ No newline at end of file
@@ -1458,7 +1458,7 @@
         
 
         
-        case 1: return .CaseA(
+        case 1: return .caseA(
             try FfiConverterString.read(from: &buf)
             )
 
\ No newline at end of file
@@ -1473,7 +1473,7 @@
 
         
         
-        case let .CaseA(v1):
+        case let .caseA(v1):
             writeInt(&buf, Int32(1))
             FfiConverterString.write(v1, into: &buf)
             
\ No newline at end of file
@@ -1495,9 +1495,9 @@
 
     
     
-    case Oops(String
+    case oops(String
     )
-    case Value(UInt16
+    case value(UInt16
     )
 }
 
\ No newline at end of file
@@ -1515,10 +1515,10 @@
         
 
         
-        case 1: return .Oops(
+        case 1: return .oops(
             try FfiConverterString.read(from: &buf)
             )
-        case 2: return .Value(
+        case 2: return .value(
             try FfiConverterUInt16.read(from: &buf)
             )
 
\ No newline at end of file
@@ -1533,12 +1533,12 @@
 
         
         
-        case let .Oops(v1):
+        case let .oops(v1):
             writeInt(&buf, Int32(1))
             FfiConverterString.write(v1, into: &buf)
             
         
-        case let .Value(v1):
+        case let .value(v1):
             writeInt(&buf, Int32(2))
             FfiConverterUInt16.write(v1, into: &buf)

@crazytonyli crazytonyli requested a review from a team as a code owner December 11, 2024 06:55
@crazytonyli crazytonyli requested review from mhammond and removed request for a team December 11, 2024 06:55
@Sajjon
Copy link
Contributor

Sajjon commented Dec 11, 2024

Yes please! What we have on main is wrong for Swift, all enums should always have cases with lowercase leading char.

@mhammond
Copy link
Member

The PR introduces breaking changes, but they are easy to fix.

I'm mildly reluctant to cause this kind of breakage - IIUC, it will break code far away from the uniffi managed world. Eg, I'm generally fine breaking, say, the UDL or the Rust code, because that will be very close to UniFFI - the developer responsible for fixing the breakage is probably the same one who is updating UniFFI. But in this kind of change, it's possible the breakage will be in code written by someone who has never heard of UniFFI (right?)

I'd say most Swift developers would prefer the new generated code.

Maybe, but it would have to be a mild preference - eg, this has been asked for very rarely in issues here and never by our internal iOS team.

Note that I'm not veto-ing this - I'd love to hear from others.

@jmartinesp
Copy link
Contributor

jmartinesp commented Dec 11, 2024

Maybe it could be enabled through some configuration option, like the ones in https://github.com/mozilla/uniffi-rs/blob/main/docs/manual/src/swift/configuration.md ?

@mhammond
Copy link
Member

Yes, if the agreement is that we don't want the breaking change, that's exactly what we would need to do, which wouldn't really complicate things too badly.

@mhammond
Copy link
Member

See also #2276, #2262.

@crazytonyli crazytonyli force-pushed the swift-error-case-names branch from c8c394c to 3afb3c7 Compare December 12, 2024 23:28
@crazytonyli
Copy link
Contributor Author

I have added a new configuration. By default (false), uniffi-rs continues to generate UpperCamelCase names for error enum cases.

I'd love to add tests to cover setting the new configuration to true, which would require the tests to override uniffi.toml configuration. But I didn't find a way to do that from the build_foreign_language_testcases! macro. Let me know if I missed anything.

@mhammond
Copy link
Member

I'd love to add tests to cover setting the new configuration to true, which would require the tests to override uniffi.toml configuration. But I didn't find a way to do that from the build_foreign_language_testcases! macro. Let me know if I missed anything.

I think you could clone the test and supply a different uniffi.toml for one of them?

@crazytonyli
Copy link
Contributor Author

@mhammond Done in 7f5b41f.

Copy link
Member

@mhammond mhammond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great, thanks! Would it be possible to trim it down a little?

I'm sorry I said "clone", but we don't really need to copy all the stuff that's not related to this rename - so most of the functions can go, and the .swift can ideally do the minimum to ensure the variants are named correct - ideally just a few lines long. A few comments could explain how the name differs from when the .toml config value isn't set.

/// Like enum_variant_swift_quoted, but a class name.
pub fn error_variant_swift_quoted(nm: &str) -> Result<String, rinja::Error> {
Ok(quote_general_keyword(oracle().class_name(nm)))
/// Get the Swift rendering of an individual enum variant for an Error type.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably worth commenting here that the default name isn't actually preferred - ie, explaining why this exists?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants