Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

public enum EnumCaseCollision {
case enumCaseCollision(Int64)
case `case`(Int64)
case plain(Int64)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

package com.example.swift;

import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
import static org.junit.jupiter.api.Assertions.*;

public class EnumCaseCollisionTest {
@Test
void renamedRecordsPreserveTheirPayloads() {
try (var arena = SwiftArena.ofConfined()) {
var value = EnumCaseCollision.enumCaseCollision(42, arena);
var payload = assertInstanceOf(EnumCaseCollision.Case.EnumCaseCollisionCase.class, value.getCase());
assertEquals(42, payload.arg0());
var keyword = EnumCaseCollision.case_(7, arena);
assertEquals(7, assertInstanceOf(EnumCaseCollision.Case.CaseCase.class, keyword.getCase()).arg0());
var plain = EnumCaseCollision.plain(9, arena);
assertEquals(9, assertInstanceOf(EnumCaseCollision.Case.Plain.class, plain.getCase()).arg0());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,13 @@ extension JNISwift2JavaGenerator {
let associatedValueTypes = enumCase.parameters.map { param in
param.type.description
}.joined(separator: .comma)
let javaCaseClassName = enumCase.name.firstCharacterUppercased
var javaCaseClassName = enumCase.name.firstCharacterUppercased
// Java forbids a nested record from sharing an enclosing type's name.
// For example Calendar.Component.Case.Calendar must be CalendarCase.
let enclosingNames = enumCase.enumType.nominalTypeDecl.qualifiedTypeName.components + ["Case"]
while enclosingNames.contains(javaCaseClassName) {
javaCaseClassName += "Case"
}
let resultType = knownTypes.optionalSugar(
.tuple(
enumCase.parameters.map {
Expand Down
23 changes: 23 additions & 0 deletions Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,29 @@ struct JNIEnumTests {
}
"""

@Test(
"Enum case records avoid enclosing Java type names",
arguments: [("message", "MessageCase"), ("caseCase", "CaseCaseCase"), ("`case`", "CaseCaseCase"), ("plain", "Plain")]
)
func enclosingNameCollisions_java(caseName: String, recordName: String) throws {
try assertOutput(
input: """
public struct CaseCase {
public enum Message {
case \(caseName)(Int64)
}
}
""",
.jni,
.java,
expectedChunks: [
"record \(recordName)(long arg0) implements Case {}",
"public java.util.Optional<Case.\(recordName)> getAs\(recordName)()",
],
notExpectedChunks: ["record Message(", "record Case(", "record CaseCase("]
)
}

@Test
func generatesJavaClass() throws {
try assertOutput(
Expand Down
Loading