Skip to content

Commit 9f898e4

Browse files
committed
wip
1 parent 0919860 commit 9f898e4

File tree

7 files changed

+147
-124
lines changed

7 files changed

+147
-124
lines changed

Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,21 @@ final class JExtractSwiftCommandPlugin: SwiftJavaPluginProtocol, BuildToolPlugin
6969
let sourceDir = target.directory.string
7070

7171
let configuration = try readConfiguration(sourceDir: "\(sourceDir)")
72-
guard let javaPackage = configuration.javaPackage else {
73-
throw SwiftJavaPluginError.missingConfiguration(sourceDir: "\(sourceDir)", key: "javaPackage")
74-
}
7572

7673
var arguments: [String] = [
74+
"--input-swift", sourceDir,
7775
"--swift-module", sourceModule.name,
78-
"--package-name", javaPackage,
79-
"--output-directory-java", context.outputDirectoryJava.path(percentEncoded: false),
80-
"--output-directory-swift", context.outputDirectorySwift.path(percentEncoded: false),
76+
"--output-java", context.outputJavaDirectory.path(percentEncoded: false),
77+
"--output-swift", context.outputSwiftDirectory.path(percentEncoded: false),
8178
// TODO: "--build-cache-directory", ...
8279
// Since plugins cannot depend on libraries we cannot detect what the output files will be,
8380
// as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin.
8481
// We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc.
8582
]
86-
arguments.append(sourceDir)
83+
// arguments.append(sourceDir) // TODO: we could do this shape maybe? to have the dirs last?
84+
if let package = configuration.javaPackage, !package.isEmpty {
85+
["--java-package", package]
86+
}
8787

8888
return arguments
8989
}

Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,23 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
5050

5151
// We use the the usual maven-style structure of "src/[generated|main|test]/java/..."
5252
// that is common in JVM ecosystem
53-
let outputDirectoryJava = context.outputDirectoryJava
54-
let outputDirectorySwift = context.outputDirectorySwift
53+
let outputJavaDirectory = context.outputJavaDirectory
54+
let outputSwiftDirectory = context.outputSwiftDirectory
5555

5656
var arguments: [String] = [
57+
"--input-swift", sourceDir,
5758
"--swift-module", sourceModule.name,
58-
"--package-name", javaPackage,
59-
"--output-directory-java", outputDirectoryJava.path(percentEncoded: false),
60-
"--output-directory-swift", outputDirectorySwift.path(percentEncoded: false),
59+
"--output-java", outputJavaDirectory.path(percentEncoded: false),
60+
"--output-swift", outputSwiftDirectory.path(percentEncoded: false),
6161
// TODO: "--build-cache-directory", ...
6262
// Since plugins cannot depend on libraries we cannot detect what the output files will be,
6363
// as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin.
6464
// We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc.
6565
]
66-
arguments.append(sourceDir)
66+
// arguments.append(sourceDir)
67+
if !javaPackage.isEmpty {
68+
arguments.append(contentsOf: ["--java-package", javaPackage])
69+
}
6770

6871
return [
6972
.prebuildCommand(
@@ -72,7 +75,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
7275
arguments: arguments,
7376
// inputFiles: [ configFile ] + swiftFiles,
7477
// outputFiles: outputJavaFiles
75-
outputFilesDirectory: outputDirectorySwift
78+
outputFilesDirectory: outputSwiftDirectory
7679
)
7780
]
7881
}

Plugins/PluginsShared/PluginUtils.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ func getEnvironmentBool(_ name: String) -> Bool {
6060
}
6161

6262
extension PluginContext {
63-
var outputDirectoryJava: URL {
63+
var outputJavaDirectory: URL {
6464
self.pluginWorkDirectoryURL
6565
.appending(path: "src")
6666
.appending(path: "generated")
6767
.appending(path: "java")
6868
}
6969

70-
var outputDirectorySwift: URL {
70+
var outputSwiftDirectory: URL {
7171
self.pluginWorkDirectoryURL
7272
.appending(path: "Sources")
7373
}

Sources/JExtractSwiftLib/Logger.swift

Lines changed: 9 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
import Foundation
1616
import SwiftSyntax
17+
import ArgumentParser
18+
import JavaKitConfigurationShared
1719

1820
// Placeholder for some better logger, we could depend on swift-log
1921
public struct Logger {
@@ -95,47 +97,17 @@ public struct Logger {
9597
}
9698

9799
extension Logger {
98-
public enum Level: String, Hashable {
99-
case trace = "trace"
100-
case debug = "debug"
101-
case info = "info"
102-
case notice = "notice"
103-
case warning = "warning"
104-
case error = "error"
105-
case critical = "critical"
106-
}
100+
public typealias Level = JavaKitConfigurationShared.LogLevel
107101
}
108102

109-
extension Logger.Level {
110-
public init(from decoder: any Decoder) throws {
111-
var container = try decoder.unkeyedContainer()
112-
let string = try container.decode(String.self)
113-
switch string {
114-
case "trace": self = .trace
115-
case "debug": self = .debug
116-
case "info": self = .info
117-
case "notice": self = .notice
118-
case "warning": self = .warning
119-
case "error": self = .error
120-
case "critical": self = .critical
121-
default: fatalError("Unknown value for \(Logger.Level.self): \(string)")
122-
}
103+
extension Logger.Level: ExpressibleByArgument {
104+
public var defaultValueDescription: String {
105+
"log level"
123106
}
107+
public private(set) static var allValueStrings: [String] =
108+
["trace", "debug", "info", "notice", "warning", "error", "critical"]
124109

125-
public func encode(to encoder: any Encoder) throws {
126-
var container = encoder.singleValueContainer()
127-
let text =
128-
switch self {
129-
case .trace: "trace"
130-
case .debug: "debug"
131-
case .info: "info"
132-
case .notice: "notice"
133-
case .warning: "warning"
134-
case .error: "error"
135-
case .critical: "critical"
136-
}
137-
try container.encode(text)
138-
}
110+
public private(set) static var defaultCompletionKind: CompletionKind = .default
139111
}
140112

141113
extension Logger.Level {

Sources/JExtractSwiftLib/Swift2Java.swift

Lines changed: 25 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -17,50 +17,31 @@ import Foundation
1717
import SwiftSyntax
1818
import SwiftSyntaxBuilder
1919
import JavaKitShared
20+
import JavaKitConfigurationShared // TODO: this should become SwiftJavaConfigurationShared
2021

21-
/// Command-line utility, similar to `jextract` to export Swift types to Java.
22-
public struct SwiftToJava: ParsableCommand {
23-
public init() {}
22+
public struct SwiftToJava {
2423

25-
public static var _commandName: String {
26-
"jextract-swift"
27-
}
28-
29-
@Option(help: "The package the generated Java code should be emitted into.")
30-
var packageName: String
31-
32-
@Option(
33-
name: .shortAndLong,
34-
help: "The directory in which to output the generated Swift files and manifest.")
35-
var outputDirectoryJava: String = ".build/jextract-swift/generated"
36-
37-
@Option(help: "Swift output directory")
38-
var outputDirectorySwift: String
39-
40-
@Option(
41-
name: .long,
42-
help: "Name of the Swift module to import (and the swift interface files belong to)")
43-
var swiftModule: String
44-
45-
@Option(name: .shortAndLong, help: "Configure the level of lots that should be printed")
46-
var logLevel: Logger.Level = .info
47-
48-
@Argument(help: "The Swift files or directories to recursively export to Java.")
49-
var input: [String]
50-
51-
public func run() throws {
52-
let inputPaths = self.input.dropFirst().map { URL(string: $0)! }
24+
public func run(config: Configuration) throws {
25+
guard let swiftModule = config.swiftModule else {
26+
fatalError("Missing '--swift-module' name.")
27+
}
5328

5429
let translator = Swift2JavaTranslator(
55-
javaPackage: packageName,
30+
javaPackage: config.javaPackage ?? "", // no package is ok, we'd generate all into top level
5631
swiftModuleName: swiftModule
5732
)
58-
translator.log.logLevel = logLevel
33+
translator.log.logLevel = config.logLevel ?? .info
34+
35+
if config.javaPackage == nil || config.javaPackage!.isEmpty {
36+
translator.log.warning("Configured java package is '', consider specifying concrete package for generated sources.")
37+
}
38+
39+
let inputPaths = (config.inputSwiftDirectory ?? "").split(separator: ",").dropFirst().map { URL(string: String($0))! }
5940

6041
var allFiles: [URL] = []
6142
let fileManager = FileManager.default
6243
let log = translator.log
63-
44+
6445
for path in inputPaths {
6546
log.debug("Input path: \(path)")
6647
if isDirectory(url: path) {
@@ -88,10 +69,17 @@ public struct SwiftToJava: ParsableCommand {
8869
translator.add(filePath: file.path, text: text)
8970
}
9071

72+
guard let outputSwiftDirectory = config.outputSwiftDirectory else {
73+
fatalError("Missing --output-swift directory!")
74+
}
75+
guard let outputJavaDirectory = config.outputJavaDirectory else {
76+
fatalError("Missing --output-java directory!")
77+
}
78+
9179
try translator.analyze()
92-
try translator.writeSwiftThunkSources(outputDirectory: outputDirectorySwift)
93-
try translator.writeExportedJavaSources(outputDirectory: outputDirectoryJava)
94-
print("[swift-java] Generated Java sources (\(packageName)) in: \(outputDirectoryJava)/")
80+
try translator.writeSwiftThunkSources(outputDirectory: outputSwiftDirectory)
81+
try translator.writeExportedJavaSources(outputDirectory: outputJavaDirectory)
82+
print("[swift-java] Generated Java sources (\(config.javaPackage ?? "")) in: \(outputJavaDirectory)/")
9583
print("[swift-java] Imported Swift module '\(swiftModule)': " + "done.".green)
9684
}
9785

@@ -102,16 +90,6 @@ public struct SwiftToJava: ParsableCommand {
10290

10391
}
10492

105-
extension Logger.Level: ExpressibleByArgument {
106-
public var defaultValueDescription: String {
107-
"log level"
108-
}
109-
public private(set) static var allValueStrings: [String] =
110-
["trace", "debug", "info", "notice", "warning", "error", "critical"]
111-
112-
public private(set) static var defaultCompletionKind: CompletionKind = .default
113-
}
114-
11593
func isDirectory(url: URL) -> Bool {
11694
var isDirectory: ObjCBool = false
11795
_ = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory)

Sources/JavaKitConfigurationShared/Configuration.swift

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,22 @@ import Foundation
2121

2222
public typealias JavaVersion = Int
2323

24-
/// Configuration for the SwiftJava plugins, provided on a per-target basis.
24+
/// Configuration for the SwiftJava tools and plugins, provided on a per-target basis.
2525
public struct Configuration: Codable {
26-
// ==== swift 2 java ---------------------------------------------------------
26+
27+
public var logLevel: LogLevel?
28+
29+
// ==== swift 2 java / jextract swift ---------------------------------------
2730

2831
public var javaPackage: String?
2932

30-
public var inputSwift: String?
31-
public var outputSwift: String?
32-
public var outputJava: String?
33+
public var swiftModule: String?
34+
35+
public var inputSwiftDirectory: String?
36+
37+
public var outputSwiftDirectory: String?
38+
39+
public var outputJavaDirectory: String?
3340

3441
// ==== java 2 swift ---------------------------------------------------------
3542

@@ -204,3 +211,45 @@ public struct ConfigurationError: Error {
204211
self.line = line
205212
}
206213
}
214+
215+
public enum LogLevel: String, Codable, Hashable {
216+
case trace = "trace"
217+
case debug = "debug"
218+
case info = "info"
219+
case notice = "notice"
220+
case warning = "warning"
221+
case error = "error"
222+
case critical = "critical"
223+
}
224+
225+
extension LogLevel {
226+
public init(from decoder: any Decoder) throws {
227+
var container = try decoder.unkeyedContainer()
228+
let string = try container.decode(String.self)
229+
switch string {
230+
case "trace": self = .trace
231+
case "debug": self = .debug
232+
case "info": self = .info
233+
case "notice": self = .notice
234+
case "warning": self = .warning
235+
case "error": self = .error
236+
case "critical": self = .critical
237+
default: fatalError("Unknown value for \(LogLevel.self): \(string)")
238+
}
239+
}
240+
241+
public func encode(to encoder: any Encoder) throws {
242+
var container = encoder.singleValueContainer()
243+
let text =
244+
switch self {
245+
case .trace: "trace"
246+
case .debug: "debug"
247+
case .info: "info"
248+
case .notice: "notice"
249+
case .warning: "warning"
250+
case .error: "error"
251+
case .critical: "critical"
252+
}
253+
try container.encode(text)
254+
}
255+
}

0 commit comments

Comments
 (0)