Skip to content

Commit 030c0d6

Browse files
committed
Load info.plist dictionary from bundle
1 parent a417339 commit 030c0d6

File tree

3 files changed

+108
-30
lines changed

3 files changed

+108
-30
lines changed

ResourceApp/ResourceApp.xcodeproj/project.pbxproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
E296935C1CAD666200401D53 /* #column in Resources */ = {isa = PBXBuildFile; fileRef = E296935B1CAD666200401D53 /* #column */; };
104104
E2A10EF81CD13779006BFC63 /* RelativeToProject.xib in Resources */ = {isa = PBXBuildFile; fileRef = E2A10EF71CD13779006BFC63 /* RelativeToProject.xib */; };
105105
E2CD68671D7CADEA00BEBE59 /* hello.txt in Resources */ = {isa = PBXBuildFile; fileRef = E2CD68641D7CACC100BEBE59 /* hello.txt */; };
106+
E2DB0EB02334DCC100815AAF /* InfoPlistTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DB0EAF2334DCC100815AAF /* InfoPlistTests.swift */; };
106107
/* End PBXBuildFile section */
107108

108109
/* Begin PBXContainerItemProxy section */
@@ -284,6 +285,7 @@
284285
E2CD68631D7CACC100BEBE59 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text; name = Base; path = Base.lproj/hello.txt; sourceTree = "<group>"; };
285286
E2CD68651D7CACCA00BEBE59 /* es */ = {isa = PBXFileReference; lastKnownFileType = text; name = es; path = es.lproj/hello.txt; sourceTree = "<group>"; };
286287
E2CD68661D7CACCB00BEBE59 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text; name = nl; path = nl.lproj/hello.txt; sourceTree = "<group>"; };
288+
E2DB0EAF2334DCC100815AAF /* InfoPlistTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoPlistTests.swift; sourceTree = "<group>"; };
287289
EF513940333862726B930435 /* Pods_Shared_ResourceApp_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Shared_ResourceApp_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
288290
/* End PBXFileReference section */
289291

@@ -520,13 +522,14 @@
520522
children = (
521523
D5F05D471BB520B1003AE55E /* FilesTests.swift */,
522524
D5E513BF1B8E11810035ECAA /* FontsTests.swift */,
525+
D5D398EB20D43ADE00D67745 /* IgnoreTests.swift */,
526+
E2DB0EAF2334DCC100815AAF /* InfoPlistTests.swift */,
523527
D51F47221B8FAF9F0028BAFD /* NibTests.swift */,
524528
D55C6CD51B5D757300301B0D /* ResourceAppTests.swift */,
525529
E20983231D585E78005ACBAA /* SegueTests.swift */,
526530
D56DC76F1C42A5E700623437 /* StoryboardTests.swift */,
527531
5D9E41331C96918E002172D3 /* StringsTests.swift */,
528532
D5EB326E1B63AD6B005C7B47 /* ValidationTests.swift */,
529-
D5D398EB20D43ADE00D67745 /* IgnoreTests.swift */,
530533
D55C6CD31B5D757300301B0D /* Supporting Files */,
531534
);
532535
path = ResourceAppTests;
@@ -1150,6 +1153,7 @@
11501153
D5E513C01B8E11810035ECAA /* FontsTests.swift in Sources */,
11511154
D56DC7701C42A5E700623437 /* StoryboardTests.swift in Sources */,
11521155
5D9E41341C96918E002172D3 /* StringsTests.swift in Sources */,
1156+
E2DB0EB02334DCC100815AAF /* InfoPlistTests.swift in Sources */,
11531157
D51F47231B8FAF9F0028BAFD /* NibTests.swift in Sources */,
11541158
D55C6CD61B5D757300301B0D /* ResourceAppTests.swift in Sources */,
11551159
D5D398EC20D43ADE00D67745 /* IgnoreTests.swift in Sources */,
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// InfoPlistTests.swift
3+
// ResourceAppTests
4+
//
5+
// Created by Tom Lokhorst on 2019-09-20.
6+
// Copyright © 2019 Mathijs Kadijk. All rights reserved.
7+
//
8+
9+
import UIKit
10+
import XCTest
11+
@testable import ResourceApp
12+
13+
class InfoPlistTests: XCTestCase {
14+
15+
func testUserActivityTypes() {
16+
XCTAssertNotNil(R.info.nsUserActivityTypes.planTripIntent)
17+
}
18+
19+
func testVariable() {
20+
// let x = (Bundle.main.object(forInfoDictionaryKey: "NSExtension") as? [String: Any])?["NSExtensionPrincipalClass"] as? String
21+
XCTAssertEqual(R.info.nsExtension.nsExtensionPrincipalClass, "ResourceApp.IntentHandler")
22+
}
23+
}
24+
25+
//<key>NSExtension</key>
26+
//<dict>
27+
// <key>NSExtensionAttributes</key>
28+
// <dict>
29+
// <key>IntentsRestrictedWhileLocked</key>
30+
// <array/>
31+
// <key>IntentsRestrictedWhileProtectedDataUnavailable</key>
32+
// <array/>
33+
// <key>IntentsSupported</key>
34+
// <array>
35+
// <string>PlanTripIntent</string>
36+
// <string>ShowDeparturesIntent</string>
37+
// </array>
38+
// </dict>
39+
// <key>NSExtensionPointIdentifier</key>
40+
// <string>com.apple.intents-service</string>
41+
// <key>NSExtensionPrincipalClass</key>
42+
// <string>$(PRODUCT_MODULE_NAME).IntentHandler</string>
43+
//</dict>

Sources/RswiftCore/Generators/PropertyListGenerator.swift

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct PropertyListGenerator: ExternalOnlyStructGenerator {
2525

2626
guard plists.all(where: { $0.url == plist.url }) else {
2727
let configs = plists.map { $0.buildConfigurationName }
28-
warn("Build configrurations \(configs) use different \(name) files, this is not yet supported")
28+
warn("Build configurations \(configs) use different \(name) files, this is not yet supported")
2929
return .empty
3030
}
3131

@@ -45,15 +45,15 @@ struct PropertyListGenerator: ExternalOnlyStructGenerator {
4545
type: Type(module: .host, name: name),
4646
implements: [],
4747
typealiasses: [],
48-
properties: propertiesFromInfoPlist(contents: contents, at: externalAccessLevel),
48+
properties: propertiesFromInfoPlist(contents: contents, path: [], at: externalAccessLevel),
4949
functions: [],
50-
structs: structsFromInfoPlist(contents: contents, at: externalAccessLevel),
50+
structs: structsFromInfoPlist(contents: contents, path: [], at: externalAccessLevel),
5151
classes: [],
5252
os: []
5353
)
5454
}
5555

56-
private func propertiesFromInfoPlist(contents: [String: Any], at externalAccessLevel: AccessLevel) -> [Let] {
56+
private func propertiesFromInfoPlist(contents: [String: Any], path: [String], at externalAccessLevel: AccessLevel) -> [Let] {
5757

5858
return contents
5959
.compactMap { (key, value) -> Let? in
@@ -68,43 +68,66 @@ struct PropertyListGenerator: ExternalOnlyStructGenerator {
6868
value: "\(value)"
6969
)
7070
case let value as String:
71-
return Let(
72-
comments: [],
73-
accessModifier: externalAccessLevel,
74-
isStatic: true,
75-
name: SwiftIdentifier(name: key),
76-
typeDefinition: .inferred(Type._String),
77-
value: "\"\(value.escapedStringLiteral)\""
78-
)
71+
return propertyFromInfoString(key: key, value: value, path: path, at: externalAccessLevel)
7972
default:
8073
return nil
8174
}
82-
}
75+
}
76+
}
77+
78+
private func propertyFromInfoString(key: String, value: String, path: [String], at externalAccessLevel: AccessLevel) -> Let {
79+
80+
let isKey = key == "_key"
81+
let letValue: String = isKey
82+
? "\"\(value.escapedStringLiteral)\""
83+
: "_infoDictionary?[\"\(key)\"] as? String ?? \"\(value.escapedStringLiteral)\""
84+
85+
return Let(
86+
comments: isKey ? [] : [value],
87+
accessModifier: externalAccessLevel,
88+
isStatic: true,
89+
name: SwiftIdentifier(name: key),
90+
typeDefinition: .inferred(Type._String),
91+
value: letValue
92+
)
8393
}
8494

85-
private func structsFromInfoPlist(contents: [String: Any], at externalAccessLevel: AccessLevel) -> [Struct] {
95+
private func structsFromInfoPlist(contents: [String: Any], path: [String], at externalAccessLevel: AccessLevel) -> [Struct] {
8696

8797
return contents
8898
.compactMap { (key, value) -> Struct? in
99+
var ps = path
100+
ps.append(key)
101+
102+
let info = path.reduce("hostingBundle.infoDictionary", { (source, step) in
103+
"(\(source)?[\"\(step)\"] as? [String: Any])"
104+
})
105+
let object = Let(
106+
comments: [],
107+
accessModifier: .privateLevel,
108+
isStatic: true,
109+
name: "_infoDictionary",
110+
typeDefinition: .inferred(nil),
111+
value: info
112+
)
113+
89114
switch value {
90115
case let array as [String]:
116+
var props = array.map { item in
117+
propertyFromInfoString(key: item, value: item, path: ps, at: externalAccessLevel)
118+
}
119+
if !props.isEmpty {
120+
props.append(object)
121+
}
122+
91123
return Struct(
92124
availables: [],
93125
comments: [],
94126
accessModifier: externalAccessLevel,
95127
type: Type(module: .host, name: SwiftIdentifier(name: key)),
96128
implements: [],
97129
typealiasses: [],
98-
properties: array.map { item in
99-
return Let(
100-
comments: [],
101-
accessModifier: externalAccessLevel,
102-
isStatic: true,
103-
name: SwiftIdentifier(name: item),
104-
typeDefinition: .inferred(Type._String),
105-
value: "\"\(item.escapedStringLiteral)\""
106-
)
107-
},
130+
properties: props,
108131
functions: [],
109132
structs: [],
110133
classes: [],
@@ -113,22 +136,27 @@ struct PropertyListGenerator: ExternalOnlyStructGenerator {
113136

114137
case var dict as [String: Any]:
115138
dict["_key"] = key
139+
var props = propertiesFromInfoPlist(contents: dict, path: ps, at: externalAccessLevel)
140+
if !props.isEmpty {
141+
props.append(object)
142+
}
143+
116144
return Struct(
117145
availables: [],
118146
comments: [],
119147
accessModifier: externalAccessLevel,
120148
type: Type(module: .host, name: SwiftIdentifier(name: key)),
121149
implements: [],
122150
typealiasses: [],
123-
properties: propertiesFromInfoPlist(contents: dict, at: externalAccessLevel),
151+
properties: props,
124152
functions: [],
125-
structs: structsFromInfoPlist(contents: dict, at: externalAccessLevel),
153+
structs: structsFromInfoPlist(contents: dict, path: ps, at: externalAccessLevel),
126154
classes: [],
127155
os: []
128156
)
129157

130158
case let dicts as [[String: Any]] where arrayOfDictionariesPrimaryKeys.keys.contains(key):
131-
return structForArrayOfDictionaries(key: key, dicts: dicts, at: externalAccessLevel)
159+
return structForArrayOfDictionaries(key: key, dicts: dicts, path: path, at: externalAccessLevel)
132160

133161
default:
134162
return nil
@@ -146,7 +174,7 @@ struct PropertyListGenerator: ExternalOnlyStructGenerator {
146174
"CFBundleURLTypes": "CFBundleURLName"
147175
]
148176

149-
private func structForArrayOfDictionaries(key: String, dicts: [[String: Any]], at externalAccessLevel: AccessLevel) -> Struct {
177+
private func structForArrayOfDictionaries(key: String, dicts: [[String: Any]], path: [String], at externalAccessLevel: AccessLevel) -> Struct {
150178
let kvs = dicts.compactMap { dict -> (String, [String: Any])? in
151179
if
152180
let primaryKey = arrayOfDictionariesPrimaryKeys[key],
@@ -158,6 +186,9 @@ struct PropertyListGenerator: ExternalOnlyStructGenerator {
158186
return nil
159187
}
160188

189+
var ps = path
190+
ps.append(key)
191+
161192
let contents = Dictionary(kvs, uniquingKeysWith: { (l, _) in l })
162193
return Struct(
163194
availables: [],
@@ -168,7 +199,7 @@ struct PropertyListGenerator: ExternalOnlyStructGenerator {
168199
typealiasses: [],
169200
properties: [],
170201
functions: [],
171-
structs: structsFromInfoPlist(contents: contents, at: externalAccessLevel),
202+
structs: structsFromInfoPlist(contents: contents, path: ps, at: externalAccessLevel),
172203
classes: [],
173204
os: []
174205
)

0 commit comments

Comments
 (0)