Skip to content

Commit 4c4769f

Browse files
committed
Merge branch 'develop'
2 parents 82baf85 + eaeec80 commit 4c4769f

File tree

6 files changed

+91
-7
lines changed

6 files changed

+91
-7
lines changed

.github/workflows/swift.yml

+18-3
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,30 @@ on:
55
pull_request:
66

77
jobs:
8-
nextstep:
8+
xcode15:
99
runs-on: macos-13
1010
steps:
1111
- name: Select latest available Xcode
12-
uses: maxim-lobanov/setup-xcode@v1
12+
uses: maxim-lobanov/setup-xcode@v1.5.1
1313
with:
1414
xcode-version: '15.2.0'
1515
- name: Checkout Repository
16-
uses: actions/checkout@v2
16+
uses: actions/checkout@v4
17+
- name: Build Swift Debug Package
18+
run: swift build -c debug
19+
- name: Build Swift Release Package
20+
run: swift build -c release
21+
- name: Run Tests
22+
run: swift test
23+
xcode16:
24+
runs-on: macos-latest
25+
steps:
26+
- name: Select latest available Xcode
27+
uses: maxim-lobanov/[email protected]
28+
with:
29+
xcode-version: latest
30+
- name: Checkout Repository
31+
uses: actions/checkout@v4
1732
- name: Build Swift Debug Package
1833
run: swift build -c debug
1934
- name: Build Swift Release Package

Package.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ let package = Package(
1616
.library(name: "ManagedModels", targets: [ "ManagedModels" ])
1717
],
1818
dependencies: [
19-
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0")
19+
.package(url: "https://github.com/swiftlang/swift-syntax.git",
20+
"509.0.0"..<"600.0.1")
2021
],
2122
targets: [
2223
.target(

Sources/ManagedModelMacros/ModelMacro/ModelMemberAttributes.swift

+17-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ extension ModelMacro: MemberAttributeMacro { // @attached(memberAttribute)
2929
return [] // TBD: rather throw?
3030
}
3131

32+
// This is an array because the `member` declaration can contain multiple
33+
// bindings, e.g.: `var street, city, country : String`.
34+
// Those are NOT all the properties of the `declaration` (e.g. the class).
3235
var properties = [ ModelProperty ]()
3336
addModelProperties(in: member, to: &properties,
3437
context: context)
@@ -41,7 +44,20 @@ extension ModelMacro: MemberAttributeMacro { // @attached(memberAttribute)
4144
}
4245

4346
guard !property.isTransient else { return [] }
47+
48+
/*
49+
// property.declaredValueType is nil, but we detect some
50+
var firstname = "Jason"
51+
// property.declaredValueType is set
52+
var lastname : String
53+
*/
54+
let addAtObjC = property.isKnownRelationshipPropertyType
55+
|| (property.valueType?.canBeRepresentedInObjectiveC ?? false)
4456

45-
return [ "@_PersistedProperty" ]
57+
// We'd like @objc, but we don't know which ones to attach it to?
58+
// https://github.com/Data-swift/ManagedModels/issues/36
59+
return addAtObjC
60+
? [ "@_PersistedProperty", "@objc" ]
61+
: [ "@_PersistedProperty" ]
4662
}
4763
}

Sources/ManagedModelMacros/Utilities/AttributeTypes.swift

+31
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,38 @@ private let toManyRelationshipTypes : Set<String> = [
4848
]
4949

5050
extension TypeSyntax {
51+
52+
/// Whether the type can be represented in Objective-C.
53+
/// A *very* basic implementation.
54+
var canBeRepresentedInObjectiveC : Bool {
55+
// TODO: Naive shortcut
56+
if let id = self.as(IdentifierTypeSyntax.self) {
57+
return id.isKnownAttributePropertyType
58+
|| id.isKnownRelationshipPropertyType
59+
}
60+
61+
if let opt = self.as(OptionalTypeSyntax.self) {
62+
if let id = opt.wrappedType.as(IdentifierTypeSyntax.self) {
63+
return id.isKnownAttributePropertyType
64+
|| id.isKnownRelationshipPropertyType
65+
}
66+
// E.g. this is not representable: `String??`, this is `String?`.
67+
// I.e. nesting of Optional's are not representable.
68+
return false
69+
}
70+
if let array = self.as(ArrayTypeSyntax.self) {
71+
// This *is* representable: `[String]`,
72+
// even this `[ [ 10, 20 ], [ 30, 40 ] ]`
73+
return array.element.canBeRepresentedInObjectiveC
74+
}
75+
76+
return false
77+
}
5178

79+
/**
80+
* This checks for some known basetypes, like `Int`, `String` or `Data`.
81+
* It also unwraps optionals, arrays and such.
82+
*/
5283
var isKnownAttributePropertyType : Bool {
5384
if let id = self.as(IdentifierTypeSyntax.self) {
5485
return id.isKnownAttributePropertyType

Sources/ManagedModelMacros/Utilities/ExpressionType.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import SwiftSyntax
88
extension ExprSyntax {
99

1010
func detectExpressionType() -> TypeSyntax? {
11+
guard let idType = detectExpressionTypeName() else { return nil }
12+
return TypeSyntax(IdentifierTypeSyntax(name: .identifier(idType)))
13+
}
14+
func detectExpressionTypeName() -> String? {
1115
// TODO: detect base types and such
1216
// - check function expressions, like:
1317
// - `Data()`?
@@ -18,7 +22,8 @@ extension ExprSyntax {
1822
case .integerLiteralExpr : return "Swift.Int"
1923
case .floatLiteralExpr : return "Swift.Double"
2024
case .booleanLiteralExpr : return "Swift.Bool"
21-
default: break
25+
default:
26+
break
2227
}
2328

2429
return nil

Tests/ManagedModelMacrosTests/ManagedModelMacrosTests.swift

+17-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ final class ModelMacroTests: XCTestCase {
121121

122122
let explodedSource = explodedFile.description
123123
XCTAssertTrue(explodedSource.contains(
124-
"extension Person: ManagedModels.PersistentModel"))
124+
"extension MySchema.Person: ManagedModels.PersistentModel"))
125125
XCTAssertTrue (explodedSource.contains("static let x = 10"))
126126
XCTAssertFalse(explodedSource.contains("@NSManaged"))
127127
XCTAssertTrue (explodedSource.contains("static let schemaMetadata"))
@@ -131,6 +131,14 @@ final class ModelMacroTests: XCTestCase {
131131
"""
132132
))
133133

134+
XCTAssertTrue(explodedSource.contains(try Regex(
135+
#"var(\s+)addresses(\s+):(\s+)\[(\s+)Address(\s+)\]"#
136+
)))
137+
XCTAssertTrue(explodedSource.contains(
138+
#"setValue(forKey: "addresses", to: newValue)"#))
139+
XCTAssertTrue(explodedSource.contains(#"getValue(forKey: "addresses")"#))
140+
141+
134142
#if false
135143
print("Exploded:---\n")
136144
print(explodedSource)
@@ -386,11 +394,19 @@ final class ModelMacroTests: XCTestCase {
386394
]
387395
)
388396

397+
#if canImport(SwiftSyntax600)
398+
let explodedFile : Syntax = sourceFile.expand(
399+
macros: macros,
400+
contextGenerator: { _ in context },
401+
indentationWidth: .spaces(2) // what else!
402+
)
403+
#else
389404
let explodedFile : Syntax = sourceFile.expand(
390405
macros: macros,
391406
in: context,
392407
indentationWidth: .spaces(2) // what else!
393408
)
409+
#endif
394410

395411
return explodedFile
396412
}

0 commit comments

Comments
 (0)