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
2 changes: 2 additions & 0 deletions .github/scripts/validate_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
set -e
set -x

swift run generate-config-docs --check

DEPENDENCY='.package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0")'

if grep -q "$DEPENDENCY" Package.swift; then
Expand Down
1 change: 1 addition & 0 deletions .licenseignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ Sources/_Subprocess/**
Sources/_SubprocessCShims/**
Samples/gradle
SwiftKitCore/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro
Snippets/__DO_NOT_EDIT_SYMLINK_ONLY__
30 changes: 29 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ if let localPath = Context.environment["SWIFT_JAVA_JNI_CORE_PATH"] {
swiftJavaJNICoreDep = .package(url: "https://github.com/swiftlang/swift-java-jni-core", branch: "main")
}

// Opt-in swift-docc-plugin dependency, only pulled in when generating documentation
// Set DOCC_PLUGIN=1 to enable, or DOCC_PLUGIN_PATH=<path> to point at a local checkout
let doccPluginDep: [Package.Dependency]
if let localPath = Context.environment["DOCC_PLUGIN_PATH"] {
doccPluginDep = [.package(path: localPath)]
} else if Context.environment["DOCC_PLUGIN"] != nil {
doccPluginDep = [.package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.5.0")]
} else {
doccPluginDep = []
}

let package = Package(
name: "swift-java",
platforms: [
Expand Down Expand Up @@ -159,7 +170,7 @@ let package = Package(

// Benchmarking
.package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")),
],
] + doccPluginDep,
targets: [
.target(
name: "SwiftJavaDocumentation",
Expand Down Expand Up @@ -416,6 +427,23 @@ let package = Package(
]
),

// Dev-time tool: regenerates the "Supported configuration options" table in
// `Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaConfigFile.md`
// straight from the doc comments on `Configuration.swift` and the enums it
// references, so the two never drift apart.
//
// Run manually via `swift run generate-config-docs`; CI validates freshness
// with `swift run generate-config-docs --check`.
.executableTarget(
name: "generate-config-docs",
dependencies: [
.product(name: "SwiftParser", package: "swift-syntax"),
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
],
path: "Sources/GenerateConfigDocs"
),

.plugin(
name: "_StaticBuildConfigPlugin",
capability: .buildTool(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ print("Start Sample app...")
// TODO: locating the classpath is more complex, need to account for dependencies of our module
let swiftJavaClasspath = findSwiftJavaClasspaths() // scans for .classpath files

// snippet.dependencyUsage
// 1) Start a JVM with appropriate classpath
let jvm = try JavaVirtualMachine.shared(classpath: swiftJavaClasspath)

Expand All @@ -50,5 +51,6 @@ for record in try CSVFormatClass.RFC4180.parse(reader)!.getRecords()! {
print("Field: \(field)")
}
}
// snippet.end

print("Done.")
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ enum SwiftWrappedError: Error {
case message(String)
}

// snippet.implementation
@JavaImplementation("com.example.swift.HelloSwift")
extension HelloSwift: HelloSwiftNativeMethods {
@JavaMethod
Expand All @@ -27,20 +28,24 @@ extension HelloSwift: HelloSwiftNativeMethods {
let answer = self.sayHelloBack(i + j)
print("Swift got back \(answer) from Java")

// snippet.staticFieldAccess
print("We expect the above value to be the initial value, \(self.javaClass.initialValue)")
// snippet.end

print("Updating Java field value to something different")
self.value = 2.71828

let newAnswer = self.sayHelloBack(17)
print("Swift got back updated \(newAnswer) from Java")

// snippet.classDefinition
let newHello = HelloSwift(environment: javaEnvironment)
print("Swift created a new Java instance with the value \(newHello.value)")

let name = newHello.name
print("Hello to \(name)")
newHello.greet("Swift 👋🏽 How's it going")
// snippet.end

self.name = "a 🗑️-collected language"
_ = self.sayHelloBack(42)
Expand All @@ -49,9 +54,12 @@ extension HelloSwift: HelloSwiftNativeMethods {
let value = predicate.test(JavaInteger(3))
print("Running a JavaPredicate from swift 3 < 10 = \(value)")

// snippet.arraysWrapper
let strings = doublesToStrings([3.14159, 2.71828])
print("Converting doubles to strings: \(strings)")
// snippet.end

// snippet.castPattern
// Try downcasting
if let helloSub = self.as(HelloSubclass.self) {
print("Hello from the subclass!")
Expand All @@ -61,6 +69,7 @@ extension HelloSwift: HelloSwiftNativeMethods {
} else {
fatalError("Expected subclass here")
}
// snippet.end

// Check escaped name
assert(self.`init`(42) == 42)
Expand All @@ -70,25 +79,34 @@ extension HelloSwift: HelloSwiftNativeMethods {
assert(newHello.is(HelloSwift.self))
assert(!newHello.is(HelloSubclass.self))

// Create a new instance.
// snippet.inheritance
// Create a new instance of the subclass; Swift mirrors the Java hierarchy.
let helloSubFromSwift = HelloSubclass("Hello from Swift", environment: javaEnvironment)
helloSubFromSwift.greetMe()
// snippet.end

// snippet.throwingMethods
do {
try throwMessage("I am an error")
} catch {
print("Caught Java error: \(error)")
}
// snippet.end

// Make sure that the thread safe class is sendable
// snippet.sendableConformance
// Java classes annotated with @ThreadSafe surface as Sendable on the Swift side.
let helper = ThreadSafeHelperClass(environment: javaEnvironment)
let threadSafe: Sendable = helper
_ = threadSafe
// snippet.end

checkOptionals(helper: helper)

return i * j
}
// snippet.end

// snippet.optionalsWrapper
func checkOptionals(helper: ThreadSafeHelperClass) {
let text: JavaString? = helper.textOptional
let value: String? = helper.getValueOptional(Optional<JavaString>.none)
Expand All @@ -101,6 +119,7 @@ extension HelloSwift: HelloSwiftNativeMethods {
print("Optional double function returned \(doubleOpt)")
print("Optional long function returned \(longOpt)")
}
// snippet.end

@JavaMethod
func throwMessageFromSwift(_ message: String) throws -> String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package com.example.swift;

// snippet.arrays
public class HelloJavaKitArrays {

public byte[] getFixedBytes() {
Expand Down Expand Up @@ -57,3 +58,4 @@ public String[] getGreetings() {
return new String[] { "hello", "world", "from", "java" };
}
}
// snippet.end
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package com.example.swift;

// snippet.helloSubclass
public class HelloSubclass extends HelloSwift {
private String greeting;

Expand All @@ -25,3 +26,4 @@ public void greetMe() {
super.greet(greeting);
}
}
// snippet.end
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import java.util.function.Predicate;

// snippet.helloClass
public class HelloSwift {
public double value;
public static double initialValue = 3.14159;
Expand Down Expand Up @@ -71,3 +72,4 @@ public void throwMessage(String message) throws Exception {
throw new Exception(message);
}
}
// snippet.end
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

// snippet.threadSafe
@Retention(RetentionPolicy.RUNTIME)
public @interface ThreadSafe {
}
// snippet.end
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.OptionalInt;
import java.util.OptionalDouble;

// snippet.threadSafeHelper
@ThreadSafe
public class ThreadSafeHelperClass {
public ThreadSafeHelperClass() { }
Expand Down Expand Up @@ -53,3 +54,4 @@ public OptionalLong from(OptionalInt value) {
return OptionalLong.of(value.getAsInt());
}
}
// snippet.end
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct JavaKitArrayRuntimeTests {

let jvm = try JavaKitSampleJVM.shared

// snippet.arraysUsage
@Test
func getFixedBytes() throws {
let env = try jvm.environment()
Expand All @@ -31,30 +32,40 @@ struct JavaKitArrayRuntimeTests {
}

@Test
func getEmptyBytes() throws {
func reverseBytes() throws {
let env = try jvm.environment()
let arrays = HelloJavaKitArrays(environment: env)

let bytes: [Int8] = arrays.getEmptyBytes()
#expect(bytes.isEmpty)
let reversed: [Int8] = arrays.reverseBytes([10, 20, 30])
#expect(reversed == [30, 20, 10])
}

@Test
func filledBytes() throws {
func getGreetings() throws {
let env = try jvm.environment()
let arrays = HelloJavaKitArrays(environment: env)

let bytes: [Int8] = arrays.filledBytes(4, 42)
#expect(bytes == [42, 42, 42, 42])
let greetings: [String] = arrays.getGreetings()
#expect(greetings == ["hello", "world", "from", "java"])
}
// snippet.end

@Test
func reverseBytes() throws {
func getEmptyBytes() throws {
let env = try jvm.environment()
let arrays = HelloJavaKitArrays(environment: env)

let reversed: [Int8] = arrays.reverseBytes([10, 20, 30])
#expect(reversed == [30, 20, 10])
let bytes: [Int8] = arrays.getEmptyBytes()
#expect(bytes.isEmpty)
}

@Test
func filledBytes() throws {
let env = try jvm.environment()
let arrays = HelloJavaKitArrays(environment: env)

let bytes: [Int8] = arrays.filledBytes(4, 42)
#expect(bytes == [42, 42, 42, 42])
}

@Test
Expand Down Expand Up @@ -84,13 +95,4 @@ struct JavaKitArrayRuntimeTests {
// "Hi" in UTF-8 is [0x48, 0x69]
#expect(bytes == [0x48, 0x69])
}

@Test
func getGreetings() throws {
let env = try jvm.environment()
let arrays = HelloJavaKitArrays(environment: env)

let greetings: [String] = arrays.getGreetings()
#expect(greetings == ["hello", "world", "from", "java"])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ struct ProbablyPrime: ParsableCommand {
var certainty: Int32 = 10

func run() throws {
// snippet.probablyPrime
let bigInt = BigInteger(number)
if bigInt.isProbablePrime(certainty) {
print("\(number) is probably prime")
} else {
print("\(number) is definitely not prime")
}
// snippet.end
}
}
2 changes: 2 additions & 0 deletions Samples/JavaSieve/Sources/JavaSieve/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import SwiftJava

let jvm = try JavaVirtualMachine.shared()

// snippet.sieveUsage
do {
let sieveClass = try JavaClass<SieveOfEratosthenes>(environment: jvm.environment())
for prime in sieveClass.findPrimes(100)! {
Expand All @@ -27,3 +28,4 @@ do {
} catch {
print("Failure: \(error)")
}
// snippet.end
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
public class DataImportTest {
@Test
void test_Data_receiveAndReturn() {
// snippet.dataUsageJava
try (var arena = AllocatingSwiftArena.ofConfined()) {
var origBytes = arena.allocateFrom("foobar");
var origDat = Data.init(origBytes, origBytes.byteSize(), arena);
Expand All @@ -37,6 +38,7 @@ void test_Data_receiveAndReturn() {
assertEquals("foobar", str);
});
}
// snippet.end
}

@Test
Expand Down
Loading
Loading