Skip to content

Commit e56a81e

Browse files
committed
Merge branch 'main' into platform-arg
2 parents a1b912b + a31b50d commit e56a81e

File tree

10 files changed

+141
-29
lines changed

10 files changed

+141
-29
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -981,12 +981,23 @@ public class ExportSwift {
981981
rawValue = stringLiteral.segments.first?.as(StringSegmentSyntax.self)?.content.text
982982
} else if let boolLiteral = element.rawValue?.value.as(BooleanLiteralExprSyntax.self) {
983983
rawValue = boolLiteral.literal.text
984-
} else if let intLiteral = element.rawValue?.value.as(IntegerLiteralExprSyntax.self) {
985-
rawValue = intLiteral.literal.text
986-
} else if let floatLiteral = element.rawValue?.value.as(FloatLiteralExprSyntax.self) {
987-
rawValue = floatLiteral.literal.text
988984
} else {
989-
rawValue = nil
985+
var numericExpr = element.rawValue?.value
986+
var isNegative = false
987+
if let prefixExpr = numericExpr?.as(PrefixOperatorExprSyntax.self),
988+
prefixExpr.operator.text == "-"
989+
{
990+
numericExpr = prefixExpr.expression
991+
isNegative = true
992+
}
993+
994+
if let intLiteral = numericExpr?.as(IntegerLiteralExprSyntax.self) {
995+
rawValue = isNegative ? "-\(intLiteral.literal.text)" : intLiteral.literal.text
996+
} else if let floatLiteral = numericExpr?.as(FloatLiteralExprSyntax.self) {
997+
rawValue = isNegative ? "-\(floatLiteral.literal.text)" : floatLiteral.literal.text
998+
} else {
999+
rawValue = nil
1000+
}
9901001
}
9911002
} else {
9921003
rawValue = nil

Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumRawType.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
}
2929

3030
@JS enum Priority: Int32 {
31-
case lowest = 1
31+
case lowest = -1
3232
case low = 2
3333
case medium = 3
3434
case high = 4

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export enum TSHttpStatus {
3737
}
3838

3939
export const PriorityValues: {
40-
readonly Lowest: 1;
40+
readonly Lowest: -1;
4141
readonly Low: 2;
4242
readonly Medium: 3;
4343
readonly High: 4;

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const TSHttpStatus = {
3434
};
3535

3636
export const PriorityValues = {
37-
Lowest: 1,
37+
Lowest: -1,
3838
Low: 2,
3939
Medium: 3,
4040
High: 4,

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@
178178

179179
],
180180
"name" : "lowest",
181-
"rawValue" : "1"
181+
"rawValue" : "-1"
182182
},
183183
{
184184
"associatedValues" : [

Plugins/PackageToJS/Sources/MiniMake.swift

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,18 @@ struct MiniMake {
9393
private var tasks: [TaskKey: Task]
9494
/// Whether to explain why tasks are built
9595
private var shouldExplain: Bool
96+
/// File system operations
97+
private var fileSystem: MiniMakeFileSystem
9698
/// Prints progress of the build
9799
private var printProgress: ProgressPrinter.PrintProgress
98100

99101
init(
100102
explain: Bool = false,
103+
fileSystem: MiniMakeFileSystem = DefaultMiniMakeFileSystem(),
101104
printProgress: @escaping ProgressPrinter.PrintProgress
102105
) {
103106
self.tasks = [:]
107+
self.fileSystem = fileSystem
104108
self.shouldExplain = explain
105109
self.printProgress = printProgress
106110
}
@@ -222,7 +226,7 @@ struct MiniMake {
222226
/// Cleans all outputs of all tasks
223227
func cleanEverything(scope: VariableScope) {
224228
for task in self.tasks.values {
225-
try? FileManager.default.removeItem(at: scope.resolve(path: task.output))
229+
try? fileSystem.removeItem(at: scope.resolve(path: task.output))
226230
}
227231
}
228232

@@ -234,26 +238,20 @@ struct MiniMake {
234238
return true
235239
}
236240
let outputURL = scope.resolve(path: task.output)
237-
if !FileManager.default.fileExists(atPath: outputURL.path) {
241+
if !fileSystem.fileExists(at: outputURL) {
238242
explain("Task \(task.output) should be built because it doesn't exist")
239243
return true
240244
}
241-
let outputMtime = try? outputURL.resourceValues(forKeys: [.contentModificationDateKey])
242-
.contentModificationDate
245+
let outputMtime = try? fileSystem.modificationDate(of: outputURL)
243246
return task.inputs.contains { input in
244247
let inputURL = scope.resolve(path: input)
245248
// Ignore directory modification times
246-
var isDirectory: ObjCBool = false
247-
let fileExists = FileManager.default.fileExists(
248-
atPath: inputURL.path,
249-
isDirectory: &isDirectory
250-
)
251-
if fileExists && isDirectory.boolValue {
249+
let (fileExists, isDirectory) = fileSystem.fileExists(at: inputURL)
250+
if fileExists && isDirectory {
252251
return false
253252
}
254253

255-
let inputMtime = try? inputURL.resourceValues(forKeys: [.contentModificationDateKey]
256-
).contentModificationDate
254+
let inputMtime = try? fileSystem.modificationDate(of: inputURL)
257255
let shouldBuild =
258256
outputMtime == nil || inputMtime == nil || outputMtime! < inputMtime!
259257
if shouldBuild {
@@ -337,3 +335,32 @@ struct BuildPath: Encodable, Hashable, CustomStringConvertible {
337335
try container.encode(self.description)
338336
}
339337
}
338+
339+
/// Abstraction over file system operations
340+
protocol MiniMakeFileSystem {
341+
func removeItem(at url: URL) throws
342+
func fileExists(at url: URL) -> Bool
343+
func fileExists(at url: URL) -> (exists: Bool, isDirectory: Bool)
344+
func modificationDate(of url: URL) throws -> Date?
345+
}
346+
347+
/// Default implementation of MiniMakeFileSystem using FileManager
348+
struct DefaultMiniMakeFileSystem: MiniMakeFileSystem {
349+
func removeItem(at url: URL) throws {
350+
try FileManager.default.removeItem(at: url)
351+
}
352+
353+
func fileExists(at url: URL) -> Bool {
354+
FileManager.default.fileExists(atPath: url.path)
355+
}
356+
357+
func fileExists(at url: URL) -> (exists: Bool, isDirectory: Bool) {
358+
var isDirectory: ObjCBool = false
359+
let exists = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory)
360+
return (exists, isDirectory.boolValue)
361+
}
362+
363+
func modificationDate(of url: URL) throws -> Date? {
364+
try url.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate
365+
}
366+
}

Plugins/PackageToJS/Tests/MiniMakeTests.swift

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,67 @@ import Testing
44
@testable import PackageToJS
55

66
@Suite struct MiniMakeTests {
7+
final class InMemoryFileSystem: MiniMakeFileSystem {
8+
struct FileEntry {
9+
var content: Data
10+
var modificationDate: Date
11+
var isDirectory: Bool
12+
}
13+
private var storage: [URL: FileEntry] = [:]
14+
15+
struct MonotonicDateGenerator {
16+
private var currentDate: Date
17+
18+
init(startingFrom date: Date = Date()) {
19+
self.currentDate = date
20+
}
21+
22+
mutating func next() -> Date {
23+
currentDate = currentDate.addingTimeInterval(1)
24+
return currentDate
25+
}
26+
}
27+
var dateGenerator = MonotonicDateGenerator()
28+
29+
// MARK: - MiniMakeFileSystem conformance
30+
31+
func removeItem(at url: URL) throws {
32+
storage.removeValue(forKey: url)
33+
}
34+
35+
func fileExists(at url: URL) -> Bool {
36+
return storage[url] != nil
37+
}
38+
39+
func fileExists(at url: URL) -> (exists: Bool, isDirectory: Bool) {
40+
if let entry = storage[url] {
41+
return (true, entry.isDirectory)
42+
} else {
43+
return (false, false)
44+
}
45+
}
46+
47+
func modificationDate(of url: URL) throws -> Date? {
48+
return storage[url]?.modificationDate
49+
}
50+
51+
func writeFile(at url: URL, content: Data) {
52+
storage[url] = FileEntry(content: content, modificationDate: dateGenerator.next(), isDirectory: false)
53+
}
54+
55+
// MARK: - Helpers for tests
56+
57+
func touch(_ url: URL) {
58+
let date = dateGenerator.next()
59+
if var entry = storage[url] {
60+
entry.modificationDate = date
61+
storage[url] = entry
62+
} else {
63+
storage[url] = FileEntry(content: Data(), modificationDate: date, isDirectory: false)
64+
}
65+
}
66+
}
67+
768
// Test basic task management functionality
869
@Test func basicTaskManagement() throws {
970
try withTemporaryDirectory { tempDir, _ in
@@ -114,7 +175,11 @@ import Testing
114175
// Test that rebuilds are controlled by timestamps
115176
@Test func timestampBasedRebuild() throws {
116177
try withTemporaryDirectory { tempDir, _ in
117-
var make = MiniMake(printProgress: { _, _ in })
178+
let fs = InMemoryFileSystem()
179+
var make = MiniMake(
180+
fileSystem: fs,
181+
printProgress: { _, _ in }
182+
)
118183
let prefix = BuildPath(prefix: "PREFIX")
119184
let scope = MiniMake.VariableScope(variables: [
120185
"PREFIX": tempDir.path
@@ -123,25 +188,25 @@ import Testing
123188
let output = prefix.appending(path: "output.txt")
124189
var buildCount = 0
125190

126-
try "Initial".write(toFile: scope.resolve(path: input).path, atomically: true, encoding: .utf8)
191+
// Create initial input file
192+
fs.touch(scope.resolve(path: input))
127193

128194
let task = make.addTask(inputFiles: [input], output: output) { task, scope in
129195
buildCount += 1
130-
let content = try String(contentsOfFile: scope.resolve(path: task.inputs[0]).path, encoding: .utf8)
131-
try content.write(toFile: scope.resolve(path: task.output).path, atomically: true, encoding: .utf8)
196+
fs.touch(scope.resolve(path: task.output))
132197
}
133198

134199
// First build
135-
try make.build(output: task, scope: scope)
200+
#expect(throws: Never.self) { try make.build(output: task, scope: scope) }
136201
#expect(buildCount == 1, "First build should occur")
137202

138203
// Second build without changes
139-
try make.build(output: task, scope: scope)
204+
#expect(throws: Never.self) { try make.build(output: task, scope: scope) }
140205
#expect(buildCount == 1, "No rebuild should occur if input is not modified")
141206

142207
// Modify input and rebuild
143-
try "Modified".write(toFile: scope.resolve(path: input).path, atomically: true, encoding: .utf8)
144-
try make.build(output: task, scope: scope)
208+
fs.touch(scope.resolve(path: input))
209+
#expect(throws: Never.self) { try make.build(output: task, scope: scope) }
145210
#expect(buildCount == 2, "Should rebuild when input is modified")
146211
}
147212
}

Tests/BridgeJSRuntimeTests/ExportAPITests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ struct TestError: Error {
153153
case ok = 200
154154
case notFound = 404
155155
case serverError = 500
156+
case unknown = -1
156157
}
157158

158159
@JS(enumStyle: .tsEnum) enum TSDirection {

Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,6 +1290,13 @@
12901290
],
12911291
"name" : "serverError",
12921292
"rawValue" : "500"
1293+
},
1294+
{
1295+
"associatedValues" : [
1296+
1297+
],
1298+
"name" : "unknown",
1299+
"rawValue" : "-1"
12931300
}
12941301
],
12951302
"emitStyle" : "const",

Tests/prelude.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) {
401401
assert.equal(exports.HttpStatus.Ok, 200);
402402
assert.equal(exports.HttpStatus.NotFound, 404);
403403
assert.equal(HttpStatusValues.ServerError, 500);
404+
assert.equal(HttpStatusValues.Unknown, -1);
404405

405406
assert.equal(exports.setTheme(exports.Theme.Light), exports.Theme.Light);
406407
assert.equal(exports.setTheme(exports.Theme.Dark), exports.Theme.Dark);

0 commit comments

Comments
 (0)