Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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,28 @@
//===----------------------------------------------------------------------===//
//
// 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 class ConcreteProtocolAB: ProtocolA, ProtocolB {
public let constantA: Int64
public let constantB: Int64
public var mutable: Int64 = 0

public func name() -> String {
return "ConcreteProtocolAB"
}

public init(constantA: Int64, constantB: Int64) {
self.constantA = constantA
self.constantB = constantB
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===----------------------------------------------------------------------===//
//
// 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 protocol ProtocolA {
var constantA: Int64 { get }
var mutable: Int64 { get set }

func name() -> String
}

public func takeProtocol(_ proto1: any ProtocolA, _ proto2: some ProtocolA) -> Int64 {
return proto1.constantA + proto2.constantA
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// 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 protocol ProtocolB {
var constantB: Int64 { get }
}

public func takeCombinedProtocol(_ proto: some ProtocolA & ProtocolB) -> Int64 {
return proto.constantA + proto.constantB
}

public func takeGenericProtocol<First: ProtocolA, Second: ProtocolB>(_ proto1: First, _ proto2: Second) -> Int64 {
return proto1.constantA + proto2.constantB
}

public func takeCombinedGenericProtocol<T: ProtocolA & ProtocolB>(_ proto: T) -> Int64 {
return proto.constantA + proto.constantB
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.ConfinedSwiftMemorySession;
import org.swift.swiftkit.core.JNISwiftInstance;
import org.swift.swiftkit.core.SwiftArena;

import java.util.Optional;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 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 ProtocolTest {
@Test
void takeProtocol() {
try (var arena = SwiftArena.ofConfined()) {
ConcreteProtocolAB proto1 = ConcreteProtocolAB.init(10, 5, arena);
ConcreteProtocolAB proto2 = ConcreteProtocolAB.init(20, 1, arena);
assertEquals(30, MySwiftLibrary.takeProtocol(proto1, proto2));
}
}

@Test
void takeCombinedProtocol() {
try (var arena = SwiftArena.ofConfined()) {
ConcreteProtocolAB proto1 = ConcreteProtocolAB.init(10, 5, arena);
assertEquals(15, MySwiftLibrary.takeCombinedProtocol(proto1));
}
}

@Test
void takeGenericProtocol() {
try (var arena = SwiftArena.ofConfined()) {
ConcreteProtocolAB proto1 = ConcreteProtocolAB.init(10, 5, arena);
ConcreteProtocolAB proto2 = ConcreteProtocolAB.init(20, 1, arena);
assertEquals(11, MySwiftLibrary.takeGenericProtocol(proto1, proto2));
}
}

@Test
void takeCombinedGenericProtocol() {
try (var arena = SwiftArena.ofConfined()) {
ConcreteProtocolAB proto1 = ConcreteProtocolAB.init(10, 5, arena);
assertEquals(15, MySwiftLibrary.takeCombinedGenericProtocol(proto1));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,11 @@ extension DeclModifierSyntax {
}

extension WithModifiersSyntax {
var isPublic: Bool {
func isPublic(in type: NominalTypeDeclSyntaxNode?) -> Bool {
if let type, case .protocolDecl(let protocolDecl) = Syntax(type).as(SyntaxEnum.self) {
return protocolDecl.isPublic(in: nil)
}

return self.modifiers.contains { modifier in
modifier.isPublic
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ extension CType {
case .optional(let wrapped) where wrapped.isPointer:
try self.init(cdeclType: wrapped)

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

case .optional(let wrapped):
return try lowerOptionalParameter(wrapped, convention: convention, parameterName: parameterName, genericParameters: genericParameters, genericRequirements: genericRequirements)

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

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

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

case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque:
case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite:
// TODO: Implement
throw LoweringError.unhandledType(type)
}
Expand Down Expand Up @@ -667,7 +670,7 @@ struct CdeclLowering {
conversion: .tupleExplode(conversions, name: outParameterName)
)

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

// Indirect return receivers.
for outParameter in translatedSignature.result.outParameters {
let memoryLayout = renderMemoryLayoutValue(for: outParameter.type)
guard case .concrete(let type) = outParameter.type else {
continue
}
let memoryLayout = renderMemoryLayoutValue(for: type)

let arena = if let className = outParameter.type.className,
let arena = if let className = type.className,
analysis.importedTypes[className] != nil {
// Use passed-in 'SwiftArena' for 'SwiftValue'.
"swiftArena$"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,9 @@ extension FFMSwift2JavaGenerator {
genericParameters: genericParameters,
genericRequirements: genericRequirements
)

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

Expand Down Expand Up @@ -691,7 +694,7 @@ extension FFMSwift2JavaGenerator {
// TODO: Implement.
throw JavaTranslationError.unhandledType(swiftType)

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

Expand Down
6 changes: 5 additions & 1 deletion Sources/JExtractSwiftLib/ImportedDecls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@ package class ImportedNominalType: ImportedDecl {
package var methods: [ImportedFunc] = []
package var variables: [ImportedFunc] = []
package var cases: [ImportedEnumCase] = []
var inheritedTypes: [SwiftType]

init(swiftNominal: SwiftNominalTypeDeclaration) {
init(swiftNominal: SwiftNominalTypeDeclaration, lookupContext: SwiftTypeLookupContext) throws {
self.swiftNominal = swiftNominal
self.inheritedTypes = try swiftNominal.inheritanceTypes?.compactMap {
try SwiftType($0.type, lookupContext: lookupContext)
} ?? []
}

var swiftType: SwiftType {
Expand Down
Loading
Loading