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
49 changes: 43 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ let package = Package(
targets: ["SwiftRuntimeFunctions"]
),

.library(
name: "SwiftExtract",
targets: ["SwiftExtract"]
),

.library(
name: "JExtractSwiftLib",
targets: ["JExtractSwiftLib"]
Expand Down Expand Up @@ -336,6 +341,30 @@ let package = Package(
]
),

.target(
name: "SwiftExtract",
dependencies: [
.product(name: "SwiftBasicFormat", package: "swift-syntax"),
.product(name: "SwiftIfConfig", package: "swift-syntax"),
.product(name: "SwiftLexicalLookup", package: "swift-syntax"),
.product(name: "SwiftParser", package: "swift-syntax"),
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
.product(name: "Logging", package: "swift-log"),
"SwiftJavaConfigurationShared",
],
path: "Sources/SwiftExtract",
resources: [
.process("Resources")
],
swiftSettings: [
.swiftLanguageMode(.v5)
],
plugins: [
.plugin(name: "_StaticBuildConfigPlugin")
]
),

.target(
name: "JExtractSwiftLib",
dependencies: [
Expand All @@ -347,19 +376,14 @@ let package = Package(
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "OrderedCollections", package: "swift-collections"),
.product(name: "SwiftJavaJNICore", package: "swift-java-jni-core"),
"SwiftExtract",
"SwiftJavaShared",
"SwiftJavaConfigurationShared",
"CodePrinting",
],
resources: [
.process("Resources")
],
swiftSettings: [
.swiftLanguageMode(.v5),
.enableUpcomingFeature("BareSlashRegexLiterals"),
],
plugins: [
.plugin(name: "_StaticBuildConfigPlugin")
]
),

Expand Down Expand Up @@ -435,13 +459,26 @@ let package = Package(
name: "JExtractSwiftTests",
dependencies: [
"JExtractSwiftLib",
"SwiftExtract",
"CodePrinting",
],
swiftSettings: [
.swiftLanguageMode(.v5)
]
),

.testTarget(
name: "SwiftExtractTests",
dependencies: [
"SwiftExtract",
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftParser", package: "swift-syntax"),
],
swiftSettings: [
.swiftLanguageMode(.v5)
]
),

.testTarget(
name: "SwiftRuntimeFunctionsTests",
dependencies: [
Expand Down
19 changes: 0 additions & 19 deletions Sources/JExtractSwiftLib/AnalysisResult.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import SwiftExtract
import SwiftJavaJNICore

extension JavaType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,7 @@
import SwiftJavaJNICore

extension String {

var firstCharacterUppercased: String {
guard let f = first else {
return self
}

return "\(f.uppercased())\(String(dropFirst()))"
}

var firstCharacterLowercased: String {
guard let f = first else {
return self
}

return "\(f.lowercased())\(String(dropFirst()))"
}

/// Returns whether the string is of the format `isX`
var hasJavaBooleanNamingConvention: Bool {
guard self.hasPrefix("is"), self.count > 2 else {
return false
}

let thirdCharacterIndex = self.index(self.startIndex, offsetBy: 2)
return self[thirdCharacterIndex].isUppercase
}

/// Returns a version of the string correctly escaped for a JNI
/// Returns a version of the string correctly escaped for a JNI identifier
var escapedJNIIdentifier: String {
self.map {
if $0 == "_" {
Expand All @@ -66,15 +39,6 @@ extension String {
.joined()
}

/// If the string ends with `.swift`, return it without that suffix;
/// otherwise return self unchanged
func dropSwiftFileSuffix() -> String {
if hasSuffix(".swift") {
return String(dropLast(".swift".count))
}
return self
}

/// Looks up self as a SwiftJava wrapped class name and converts it
/// into a `JavaType.class` if it exists in `lookupTable`.
func parseJavaClassFromSwiftJavaName(in lookupTable: [String: String]) -> JavaType? {
Expand All @@ -87,14 +51,6 @@ extension String {

return .class(package: javaPackageName, name: javaClassName)
}

/// Unescapes the name if it is surrounded by backticks.
var unescapedSwiftName: String {
if count >= 2 && hasPrefix("`") && hasSuffix("`") {
return String(dropFirst().dropLast())
}
return self
}
}

extension Array where Element == String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
//
//===----------------------------------------------------------------------===//

import SwiftExtract

extension CType {
/// Lower the given Swift type down to a its corresponding C type.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import SwiftExtract
import SwiftJavaJNICore
import SwiftSyntax

Expand Down
1 change: 1 addition & 0 deletions Sources/JExtractSwiftLib/FFM/ConversionStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import SwiftExtract
import SwiftSyntax
import SwiftSyntaxBuilder

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

import CodePrinting
import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore
import SwiftSyntax
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

import CodePrinting
import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

import CodePrinting
import SwiftExtract
import SwiftSyntax
import SwiftSyntaxBuilder

Expand Down
3 changes: 2 additions & 1 deletion Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

import CodePrinting
import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore
import SwiftSyntax
Expand Down Expand Up @@ -69,7 +70,7 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator {

package init(
config: Configuration,
translator: Swift2JavaTranslator,
translator: SwiftAnalyzer,
javaPackage: String,
swiftOutputDirectory: String,
javaOutputDirectory: String,
Expand Down
79 changes: 79 additions & 0 deletions Sources/JExtractSwiftLib/ImportedDecls+JavaNaming.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024-2026 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
//
//===----------------------------------------------------------------------===//

import SwiftExtract

// ==== -----------------------------------------------------------------------
// MARK: Java-facing name aliases for ImportedNominalType

extension ImportedNominalType {
package var effectiveJavaTypeName: SwiftQualifiedTypeName { effectiveOutputTypeName }
package var effectiveJavaName: String { effectiveOutputName }
package var effectiveJavaSimpleName: String { effectiveOutputSimpleName }
package var javaGenericClause: String { outputGenericClause }
}

// ==== -----------------------------------------------------------------------
// MARK: Java-facing name aliases for ImportedFunc

extension ImportedFunc {
/// The Java getter name for a Swift property/subscript getter, following
/// Java Beans conventions: `get<Name>` for non-boolean, `is<Name>` for
/// boolean (unless the property already starts with `is`, in which case
/// the original name is preserved).
///
/// Returns `nil` when the underlying declaration is not a getter — i.e. a
/// regular function, initializer, enum case, or setter — since those don't
/// have a Java getter name.
package var javaGetterName: String? {
switch apiKind {
case .getter, .subscriptGetter: break
case .setter, .subscriptSetter, .function, .initializer, .enumCase: return nil
}

let returnsBoolean = self.functionSignature.result.type.asNominalTypeDeclaration?.knownTypeKind == .bool

if !returnsBoolean {
return "get\(self.name.firstCharacterUppercased)"
} else if !self.name.hasJavaBooleanNamingConvention {
return "is\(self.name.firstCharacterUppercased)"
} else {
return self.name
}
}

/// The Java setter name for a Swift property/subscript setter. If the
/// property already starts with `is` (boolean naming), the `is` prefix is
/// stripped so the setter becomes `set<Name>` per Java Beans spec.
///
/// Returns `nil` when the underlying declaration is not a setter — i.e. a
/// regular function, initializer, enum case, or getter — since those don't
/// have a Java setter name.
package var javaSetterName: String? {
switch apiKind {
case .setter, .subscriptSetter: break
case .getter, .subscriptGetter, .function, .initializer, .enumCase: return nil
}

let isBooleanSetter = self.functionSignature.parameters.first?.type.asNominalTypeDeclaration?.knownTypeKind == .bool

if isBooleanSetter && self.name.hasJavaBooleanNamingConvention {
// Safe to force unwrap due to `hasJavaBooleanNamingConvention` check.
let propertyName = self.name.split(separator: "is", maxSplits: 1).last!
return "set\(propertyName)"
} else {
return "set\(self.name.firstCharacterUppercased)"
}
}
}
2 changes: 2 additions & 0 deletions Sources/JExtractSwiftLib/JNI/JNICaching.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
//
//===----------------------------------------------------------------------===//

import SwiftExtract

enum JNICaching {
static func cacheName(for type: ImportedNominalType) -> String {
cacheName(for: type.effectiveJavaTypeName)
Expand Down
1 change: 1 addition & 0 deletions Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

import CodePrinting
import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore
import SwiftSyntax
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import CodePrinting
import Foundation
import OrderedCollections
import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

import CodePrinting
import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore
import SwiftSyntax
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

import CodePrinting
import SwiftExtract
import SwiftJavaConfigurationShared
import SwiftJavaJNICore

Expand Down
Loading
Loading