Skip to content

Commit ffcab93

Browse files
committed
synthesize RawRepresentable
1 parent 0d0af8b commit ffcab93

File tree

5 files changed

+112
-1
lines changed

5 files changed

+112
-1
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
public enum Alignment: String {
16+
case horizontal
17+
case vertical
18+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
package com.example.swift;
16+
17+
import org.junit.jupiter.api.Test;
18+
import org.swift.swiftkit.core.ConfinedSwiftMemorySession;
19+
20+
import java.util.Optional;
21+
22+
import static org.junit.jupiter.api.Assertions.*;
23+
24+
public class AlignmentTest {
25+
@Test
26+
void rawValue() {
27+
try (var arena = new ConfinedSwiftMemorySession()) {
28+
Optional<Alignment> invalid = Alignment.init("invalid", arena);
29+
assertFalse(invalid.isPresent());
30+
31+
Optional<Alignment> horizontal = Alignment.init("horizontal", arena);
32+
assertTrue(horizontal.isPresent());
33+
assertEquals("horizontal", horizontal.get().getRawValue());
34+
35+
Optional<Alignment> vertical = Alignment.init("vertical", arena);
36+
assertTrue(vertical.isPresent());
37+
assertEquals("vertical", vertical.get().getRawValue());
38+
}
39+
}
40+
}

Sources/JExtractSwiftLib/Swift2JavaVisitor.swift

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ final class Swift2JavaVisitor {
4646
case .structDecl(let node):
4747
self.visit(nominalDecl: node, in: parent)
4848
case .enumDecl(let node):
49-
self.visit(nominalDecl: node, in: parent)
49+
self.visit(enumDecl: node, in: parent)
5050
case .protocolDecl(let node):
5151
self.visit(nominalDecl: node, in: parent)
5252
case .extensionDecl(let node):
@@ -85,6 +85,12 @@ final class Swift2JavaVisitor {
8585
}
8686
}
8787

88+
func visit(enumDecl node: EnumDeclSyntax, in parent: ImportedNominalType?) {
89+
self.visit(nominalDecl: node, in: parent)
90+
91+
self.synthesizeRawRepresentableConformance(enumDecl: node, in: parent)
92+
}
93+
8894
func visit(extensionDecl node: ExtensionDeclSyntax, in parent: ImportedNominalType?) {
8995
guard parent != nil else {
9096
// 'extension' in a nominal type is invalid. Ignore
@@ -256,6 +262,32 @@ final class Swift2JavaVisitor {
256262

257263
typeContext.initializers.append(imported)
258264
}
265+
266+
private func synthesizeRawRepresentableConformance(enumDecl node: EnumDeclSyntax, in parent: ImportedNominalType?) {
267+
guard let imported = translator.importedNominalType(node, parent: parent) else {
268+
return
269+
}
270+
271+
if let firstInheritanceType = imported.swiftNominal.firstInheritanceType,
272+
let inheritanceType = try? SwiftType(
273+
firstInheritanceType,
274+
lookupContext: translator.lookupContext
275+
),
276+
inheritanceType.isRawTypeCompatible
277+
{
278+
if !imported.variables.contains(where: { $0.name == "rawValue" && $0.functionSignature.result.type != inheritanceType }) {
279+
let decl: DeclSyntax = "public var rawValue: \(raw: inheritanceType.description) { get }"
280+
self.visit(decl: decl, in: imported)
281+
}
282+
283+
imported.variables.first?.signatureString
284+
285+
if !imported.initializers.contains(where: { $0.functionSignature.parameters.count == 1 && $0.functionSignature.parameters.first?.parameterName == "rawValue" && $0.functionSignature.parameters.first?.type == inheritanceType }) {
286+
let decl: DeclSyntax = "public init?(rawValue: \(raw: inheritanceType))"
287+
self.visit(decl: decl, in: imported)
288+
}
289+
}
290+
}
259291
}
260292

261293
extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyntax {

Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ package class SwiftNominalTypeDeclaration: SwiftTypeDeclaration {
8585
super.init(moduleName: moduleName, name: node.name.text)
8686
}
8787

88+
lazy var firstInheritanceType: TypeSyntax? = {
89+
guard let firstInheritanceType = self.syntax?.inheritanceClause?.inheritedTypes.first else {
90+
return nil
91+
}
92+
93+
return firstInheritanceType.type
94+
}()
95+
8896
/// Returns true if this type conforms to `Sendable` and therefore is "threadsafe".
8997
lazy var isSendable: Bool = {
9098
// Check if Sendable is in the inheritance list

Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,19 @@ enum SwiftType: Equatable {
103103
default: false
104104
}
105105
}
106+
107+
var isRawTypeCompatible: Bool {
108+
switch self {
109+
case .nominal(let nominal):
110+
switch nominal.nominalTypeDecl.knownTypeKind {
111+
case .int, .uint, .int8, .uint8, .int16, .uint16, .int32, .uint32, .int64, .uint64, .float, .double, .string:
112+
true
113+
default:
114+
false
115+
}
116+
default: false
117+
}
118+
}
106119
}
107120

108121
extension SwiftType: CustomStringConvertible {

0 commit comments

Comments
 (0)