Skip to content

Commit da44f44

Browse files
committed
WIP - tests pass
1 parent d30b5b9 commit da44f44

3 files changed

Lines changed: 93 additions & 46 deletions

File tree

Sources/Compiler/Gen/Language.swift

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public protocol Language {
3030
migrations: [String],
3131
tables: [GeneratedModel],
3232
queries: [(String?, [GeneratedQuery])],
33-
adapters: [String]
33+
adapters: [AdapterReference]
3434
) throws -> String
3535

3636
/// Function to generate a interpolation segment in a string
@@ -65,24 +65,28 @@ extension Language {
6565
) throws -> (
6666
tables: [GeneratedModel],
6767
queries: [(String?, [GeneratedQuery])],
68-
adapters: [String]
68+
adapters: [AdapterReference]
6969
) {
7070
let tables = Dictionary(schema.tables.map { ($0.key.name, model(for: $0.value)) }, uniquingKeysWith: { $1 })
7171
let queries = queries.map { ($0.map { "\($0)Queries" }, $1.map { query(for: $0, tables: tables) }) }
7272

7373
let builtinAdapters = builtinAdapterTypes
74-
.map(adapterName(from:))
74+
.map { adapterReference(name: $0, typeName: $0) }
7575

7676
// Get a list of all adapters used. Right now we only have to look at the
7777
// tables since any output would inhereit the encoding of the source table.
78-
let adapters: Set<String> = tables.reduce(into: []) { adapters, table in
78+
let adapters: Set<AdapterReference> = tables.reduce(into: []) { adapters, table in
7979
for field in table.value.fields.values {
8080
guard let adapter = field.type.adapter else { continue }
8181
adapters.insert(adapter)
8282
}
8383
}
8484

85-
return (tables.values.sorted{ $0.name < $1.name }, queries, adapters.subtracting(builtinAdapters).sorted())
85+
return (
86+
tables.values.sorted{ $0.name < $1.name },
87+
queries,
88+
adapters.subtracting(builtinAdapters).sorted{ $0.name < $1.name }
89+
)
8690
}
8791

8892
private func query(
@@ -221,7 +225,7 @@ extension Language {
221225
return .encoded(
222226
generationType(for: root),
223227
alias: alias,
224-
adapter: adapter.map(adapterName(from:)) ?? adapterName(from: alias)
228+
adapter: adapterReference(name: adapter?.description ?? alias, typeName: alias)
225229
)
226230
case let .optional(type):
227231
return .optional(generationType(for: type))
@@ -332,17 +336,17 @@ extension Language {
332336
/// Int -> int
333337
/// UUID -> uuid
334338
/// Foo.ID -> fooID
335-
private func adapterName<S: StringProtocol>(from typeName: S) -> String {
339+
private func adapterReference(name: String, typeName: String) -> AdapterReference {
336340
var result = ""
337-
result.reserveCapacity(typeName.count)
341+
result.reserveCapacity(name.count)
338342

339343
// Right now we only support Swift so we are expecting the input
340344
// to be upper camel case so we really only have to worry about
341345
// lower casing the initial characters until we hit the first lower
342346
// cased character
343347
var hasHitLowerCase = false
344348

345-
for c in typeName {
349+
for c in name {
346350
guard identifierCharacters.contains(c) else { continue }
347351

348352
if !hasHitLowerCase {
@@ -354,7 +358,7 @@ extension Language {
354358
hasHitLowerCase = hasHitLowerCase || c.isLowercase
355359
}
356360

357-
return result
361+
return AdapterReference(name: result, type: typeName)
358362
}
359363
}
360364

@@ -442,7 +446,7 @@ public struct GeneratedQuery {
442446
name: String,
443447
owner: String? = nil,
444448
isOptional: Bool = false,
445-
adapter: (name: String, storage: String)? = nil
449+
adapter: (adapter: AdapterReference, storage: String)? = nil
446450
)
447451
case arrayStart(name: String, elementName: String)
448452
case arrayEnd
@@ -455,7 +459,7 @@ public enum GenerationType: Equatable {
455459
case model(GeneratedModel)
456460
indirect case optional(Self)
457461
indirect case array(Self)
458-
indirect case encoded(Self, alias: String, adapter: String)
462+
indirect case encoded(Self, alias: String, adapter: AdapterReference)
459463

460464
var model: GeneratedModel? {
461465
switch self {
@@ -467,7 +471,7 @@ public enum GenerationType: Equatable {
467471
}
468472
}
469473

470-
var adapter: String? {
474+
var adapter: AdapterReference? {
471475
switch self {
472476
case .void, .builtin, .model: nil
473477
case .optional(let optional): optional.adapter
@@ -486,3 +490,8 @@ public enum GenerationType: Equatable {
486490
}
487491
}
488492
}
493+
494+
public struct AdapterReference: Hashable {
495+
let name: String
496+
let type: String
497+
}

Sources/Compiler/Gen/SwiftLanguage.swift

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public struct SwiftLanguage: Language {
7373
migrations: [String],
7474
tables: [GeneratedModel],
7575
queries: [(String?, [GeneratedQuery])],
76-
adapters: [String]
76+
adapters: [AdapterReference]
7777
) throws -> String {
7878
// Note: For now just going to ignore the `adapters`
7979
// Kotlin will need that info which is why it exists.
@@ -130,7 +130,7 @@ public struct SwiftLanguage: Language {
130130
tables: [GeneratedModel],
131131
queries: [GeneratedQuery],
132132
addConnection: Bool,
133-
adapters: [String]
133+
adapters: [AdapterReference]
134134
) -> [String] {
135135
var decls: [String] = []
136136

@@ -170,7 +170,7 @@ public struct SwiftLanguage: Language {
170170
private func dbStruct(
171171
queries: [(String?, [GeneratedQuery])],
172172
migrations: [String],
173-
adapters: [String]
173+
adapters: [AdapterReference]
174174
) {
175175
writer.write(line: "struct ", options.databaseName, ": Database")
176176

@@ -214,7 +214,7 @@ public struct SwiftLanguage: Language {
214214
}
215215
}
216216

217-
private func adapters(adapters: [String]) {
217+
private func adapters(adapters: [AdapterReference]) {
218218
writer.write(line: "let adapters: Adapters")
219219
writer.newline()
220220

@@ -224,7 +224,26 @@ public struct SwiftLanguage: Language {
224224
writer.write(line: "struct Adapters: Otter.Adapters ")
225225
writer.braces {
226226
for adapter in adapters {
227-
writer.write(line: "let ", adapter, ": AnyDatabaseValueAdapter")
227+
writer.write(line: "let ", adapter.name, ": AnyDatabaseValueAdapter<", adapter.type, ">")
228+
}
229+
230+
writer.blankLine()
231+
writer.write(line: "init(")
232+
writer.indented {
233+
for (position, adapter) in adapters.positional() {
234+
writer.write(line: adapter.name, ": any DatabaseValueAdapter<", adapter.type, ">")
235+
236+
if !position.isLast {
237+
writer.write(",")
238+
}
239+
}
240+
}
241+
writer.write(line: ")")
242+
243+
writer.braces {
244+
for adapter in adapters {
245+
writer.write(line: "self.", adapter.name, " = AnyDatabaseValueAdapter<", adapter.type, ">(", adapter.name, ")")
246+
}
228247
}
229248
}
230249
}
@@ -274,36 +293,43 @@ public struct SwiftLanguage: Language {
274293
}
275294

276295
private func queriesNoop(name: String, queries: [GeneratedQuery]) {
277-
writer.write(line: "static var noop: ", name, " {")
296+
writer.write(line: "static func noop(")
297+
writer.indented {
298+
for (position, query) in queries.positional() {
299+
writer.write(line: query.variableName, ": any ", query.typealiasName, " = ")
300+
301+
switch query.output {
302+
case .model:
303+
// We might be able to initialize one in the future with all default values
304+
// but it seems hacky so just fail
305+
writer.write("Queries.Fail()")
306+
case .builtin(let name):
307+
let defaultValue = switch name {
308+
case "Double": "0.0"
309+
case "Int": "0"
310+
case "String": "\"\""
311+
case "Data": "Data()"
312+
default: "SQLAny.int(0)"
313+
}
314+
writer.write("Queries.Just(", defaultValue, ")")
315+
default:
316+
writer.write("Queries.Just()")
317+
}
318+
319+
if !position.isLast {
320+
writer.write(",")
321+
}
322+
}
323+
}
324+
writer.write(line: ")")
325+
278326
writer.indent()
279327

280328
writer.write(line: name, "(")
281329
writer.indent()
282330

283-
for (position, query) in queries.positional() {
284-
writer.write(line: query.variableName, ": ")
285-
286-
switch query.output {
287-
case .model:
288-
// We might be able to initialize one in the future with all default values
289-
// but it seems hacky so just fail
290-
writer.write("Queries.Fail()")
291-
case .builtin(let name):
292-
let defaultValue = switch name {
293-
case "Double": "0.0"
294-
case "Int": "0"
295-
case "String": "\"\""
296-
case "Data": "Data()"
297-
default: "SQLAny.int(0)"
298-
}
299-
writer.write("Queries.Just(", defaultValue, ")")
300-
default:
301-
writer.write("Queries.Just()")
302-
}
303-
304-
if !position.isLast {
305-
writer.write(",")
306-
}
331+
for query in queries {
332+
writer.write(line: "self.", query.variableName, " = ", query.variableName)
307333
}
308334

309335
writer.unindent()
@@ -542,10 +568,10 @@ public struct SwiftLanguage: Language {
542568
writer.write(")")
543569
index += model.fields.count
544570
case let .encoded(storage, _, adapter):
545-
writer.write("row.value(at: start + ", index.description, ", using: adapters.", adapter, ", storage: ", typeName(for: storage), ".self)")
571+
writer.write("row.value(at: start + ", index.description, ", using: adapters.", adapter.name, ", storage: ", typeName(for: storage), ".self)")
546572
index += 1
547573
case let .optional(.encoded(storage, _, adapter)):
548-
writer.write("row.optionalValue(at: start + ", index.description, ", using: adapters.", adapter, ", storage: ", typeName(for: storage), ".self)")
574+
writer.write("row.optionalValue(at: start + ", index.description, ", using: adapters.", adapter.name, ", storage: ", typeName(for: storage), ".self)")
549575
index += 1
550576
default:
551577
fatalError("Invalid field type \(field.typeName) \(field.type)")
@@ -708,7 +734,7 @@ public struct SwiftLanguage: Language {
708734
writer.write(name, ", to: ", index.description)
709735

710736
if let adapter {
711-
writer.write(", using: adapters.", adapter.name, ", as: ", adapter.storage, ".self")
737+
writer.write(", using: adapters.", adapter.adapter.name, ", as: ", adapter.storage, ".self")
712738
}
713739

714740
writer.write(")")

Sources/Otter/Queries/Just.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ public extension Queries {
3535
self = Just(())
3636
}
3737

38+
public init() where Output: ExpressibleByStringLiteral {
39+
self = Just("")
40+
}
41+
42+
public init() where Output: ExpressibleByIntegerLiteral {
43+
self = Just(0)
44+
}
45+
46+
public init() where Output: ExpressibleByBooleanLiteral {
47+
self = Just(false)
48+
}
49+
3850
public init() where Output: ExpressibleByArrayLiteral {
3951
self = Just([])
4052
}

0 commit comments

Comments
 (0)