Skip to content
Draft
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,43 @@
//===----------------------------------------------------------------------===//
//
// 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 func makeStringSet() -> Set<String> {
["hello", "world"]
}

public func stringSet(set: Set<String>) -> Set<String> {
set
}

public func insertIntoStringSet(set: Set<String>, element: String) -> Set<String> {
var copy = set
copy.insert(element)
return copy
}

public func makeIntegerSet() -> Set<Int32> {
[1, 2, 3]
}

public func integerSet(set: Set<Int32>) -> Set<Int32> {
set
}

public func makeLongSet() -> Set<Int> {
[10, 20, 30]
}

public func longSet(set: Set<Int>) -> Set<Int> {
set
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//===----------------------------------------------------------------------===//
//
// 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 java.util.HashSet;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.collections.SwiftSet;
import org.swift.swiftkit.core.SwiftArena;

import static org.junit.jupiter.api.Assertions.*;

public class SwiftSetTest {
@Test
void makeStringSet() {
try (var arena = SwiftArena.ofConfined()) {
SwiftSet<String> set = MySwiftLibrary.makeStringSet(arena);
assertEquals(2, set.size());
assertTrue(set.contains("hello"));
assertTrue(set.contains("world"));
assertFalse(set.contains("missing"));
}
}

@Test
void stringSetRoundtrip() {
try (var arena = SwiftArena.ofConfined()) {
SwiftSet<String> original = MySwiftLibrary.makeStringSet(arena);
SwiftSet<String> roundtripped = MySwiftLibrary.stringSet(original, arena);
assertEquals(original.size(), roundtripped.size());
assertTrue(roundtripped.contains("hello"));
assertTrue(roundtripped.contains("world"));
}
}

@Test
void insertIntoStringSet() {
try (var arena = SwiftArena.ofConfined()) {
SwiftSet<String> original = MySwiftLibrary.makeStringSet(arena);
assertEquals(2, original.size());

// Insert a new element by passing the set through Swift
SwiftSet<String> modified =
MySwiftLibrary.insertIntoStringSet(original, "swift", arena);

// The modified set has the new element
assertEquals(3, modified.size());
assertTrue(modified.contains("hello"));
assertTrue(modified.contains("world"));
assertTrue(modified.contains("swift"));

// The original set is unchanged (Swift value semantics — it's a copy)
assertEquals(2, original.size());
assertFalse(original.contains("swift"));
}
}

@Test
void toJavaSet() {
Set<String> javaSet;
try (var arena = SwiftArena.ofConfined()) {
SwiftSet<String> set = MySwiftLibrary.makeStringSet(arena);
javaSet = set.toJavaSet();

// The copy has the same contents as the original
assertEquals(2, javaSet.size());
assertTrue(javaSet.contains("hello"));
assertTrue(javaSet.contains("world"));
assertFalse(javaSet.contains("missing"));

// It's a plain HashSet, not the native-backed set
assertInstanceOf(HashSet.class, javaSet);
}

// The Java set copy survives arena closure
assertEquals(2, javaSet.size());
assertTrue(javaSet.contains("hello"));
assertTrue(javaSet.contains("world"));
}

// ==== Swift Set<Int32> -> Java Set<Integer> tests ====

@Test
void makeIntegerSet() {
try (var arena = SwiftArena.ofConfined()) {
SwiftSet<Integer> set = MySwiftLibrary.makeIntegerSet(arena);
assertEquals(3, set.size());
assertTrue(set.contains(1));
assertTrue(set.contains(2));
assertTrue(set.contains(3));
assertFalse(set.contains(42));
}
}

@Test
void integerSetRoundtrip() {
try (var arena = SwiftArena.ofConfined()) {
SwiftSet<Integer> original = MySwiftLibrary.makeIntegerSet(arena);
SwiftSet<Integer> roundtripped = MySwiftLibrary.integerSet(original, arena);
assertEquals(original.size(), roundtripped.size());
assertTrue(roundtripped.contains(1));
assertTrue(roundtripped.contains(2));
assertTrue(roundtripped.contains(3));
}
}

// ==== Swift Set<Int> -> Java Set<Long> tests ====

@Test
void makeLongSet() {
try (var arena = SwiftArena.ofConfined()) {
SwiftSet<Long> set = MySwiftLibrary.makeLongSet(arena);
assertEquals(3, set.size());
assertTrue(set.contains(10L));
assertTrue(set.contains(20L));
assertTrue(set.contains(30L));
assertFalse(set.contains(99L));
}
}

@Test
void longSetRoundtrip() {
try (var arena = SwiftArena.ofConfined()) {
SwiftSet<Long> original = MySwiftLibrary.makeLongSet(arena);
SwiftSet<Long> roundtripped = MySwiftLibrary.longSet(original, arena);
assertEquals(original.size(), roundtripped.size());
assertTrue(roundtripped.contains(10L));
assertTrue(roundtripped.contains(20L));
assertTrue(roundtripped.contains(30L));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ extension CType {
case .optional(let wrapped) where wrapped.isPointer:
try self.init(cdeclType: wrapped)

case .genericParameter, .metatype, .optional, .tuple, .opaque, .existential, .composite, .array, .dictionary:
case .genericParameter, .metatype, .optional, .tuple, .opaque, .existential, .composite, .array, .dictionary, .set:
throw CDeclToCLoweringError.invalidCDeclType(cdeclType)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,9 @@ struct CdeclLowering {

case .dictionary:
throw LoweringError.unhandledType(type)

case .set:
throw LoweringError.unhandledType(type)
}
}

Expand Down Expand Up @@ -530,7 +533,7 @@ struct CdeclLowering {
}
throw LoweringError.unhandledType(.optional(wrappedType))

case .function, .metatype, .optional, .composite, .array, .dictionary:
case .function, .metatype, .optional, .composite, .array, .dictionary, .set:
throw LoweringError.unhandledType(.optional(wrappedType))
}
}
Expand Down Expand Up @@ -632,7 +635,7 @@ struct CdeclLowering {
// Custom types are not supported yet.
throw LoweringError.unhandledType(type)

case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite, .array, .dictionary:
case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite, .array, .dictionary, .set:
// TODO: Implement
throw LoweringError.unhandledType(type)
}
Expand Down Expand Up @@ -835,7 +838,7 @@ struct CdeclLowering {
)
)

case .genericParameter, .function, .optional, .existential, .opaque, .composite, .array, .dictionary:
case .genericParameter, .function, .optional, .existential, .opaque, .composite, .array, .dictionary, .set:
throw LoweringError.unhandledType(type)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,9 @@ extension FFMSwift2JavaGenerator {

case .dictionary:
throw JavaTranslationError.unhandledType(swiftType)

case .set:
throw JavaTranslationError.unhandledType(swiftType)
}
}

Expand Down Expand Up @@ -742,7 +745,7 @@ extension FFMSwift2JavaGenerator {
)
)

case .genericParameter, .optional, .function, .existential, .opaque, .composite, .array, .dictionary:
case .genericParameter, .optional, .function, .existential, .opaque, .composite, .array, .dictionary, .set:
throw JavaTranslationError.unhandledType(swiftType)
}

Expand Down
3 changes: 3 additions & 0 deletions Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ enum JNIJavaTypeTranslator {
.essentialsData, .essentialsDataProtocol,
.array,
.dictionary,
.set,
.foundationDate, .essentialsDate,
.foundationUUID, .essentialsUUID:
return nil
Expand All @@ -75,6 +76,7 @@ enum JNIJavaTypeTranslator {
.essentialsData, .essentialsDataProtocol,
.array,
.dictionary,
.set,
.foundationDate, .essentialsDate,
.foundationUUID, .essentialsUUID:
nil
Expand All @@ -100,6 +102,7 @@ enum JNIJavaTypeTranslator {
.essentialsData, .essentialsDataProtocol,
.array,
.dictionary,
.set,
.foundationDate, .essentialsDate,
.foundationUUID, .essentialsUUID:
nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ extension JNISwift2JavaGenerator {
case .dictionary:
throw JavaTranslationError.unsupportedSwiftType(type)

case .set:
throw JavaTranslationError.unsupportedSwiftType(type)

case .genericParameter, .function, .metatype, .tuple, .existential, .opaque, .composite:
throw JavaTranslationError.unsupportedSwiftType(type)
}
Expand All @@ -259,7 +262,7 @@ extension JNISwift2JavaGenerator {
)
)

case .array, .dictionary, .composite, .existential, .function, .genericParameter, .metatype, .opaque, .optional, .tuple:
case .array, .dictionary, .set, .composite, .existential, .function, .genericParameter, .metatype, .opaque, .optional, .tuple:
throw JavaTranslationError.unsupportedSwiftType(.array(elementType))
}
}
Expand Down Expand Up @@ -330,6 +333,9 @@ extension JNISwift2JavaGenerator {
case .dictionary:
throw JavaTranslationError.unsupportedSwiftType(type)

case .set:
throw JavaTranslationError.unsupportedSwiftType(type)

case .genericParameter, .function, .metatype, .tuple, .existential, .opaque, .composite:
throw JavaTranslationError.unsupportedSwiftType(type)
}
Expand All @@ -348,7 +354,7 @@ extension JNISwift2JavaGenerator {
)
)

case .array, .dictionary, .composite, .existential, .function, .genericParameter, .metatype, .opaque, .optional, .tuple:
case .array, .dictionary, .set, .composite, .existential, .function, .genericParameter, .metatype, .opaque, .optional, .tuple:
throw JavaTranslationError.unsupportedSwiftType(.array(elementType))
}
}
Expand Down Expand Up @@ -484,7 +490,7 @@ extension SwiftType {
case .array(let elementType):
return elementType.isDirectlyTranslatedToWrapJava

case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite, .dictionary:
case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite, .dictionary, .set:
return false
}
}
Expand Down
Loading
Loading