Skip to content

Commit d639a1c

Browse files
committed
Merge branch 'master' into generators
2 parents 131cc54 + 66358ef commit d639a1c

File tree

12 files changed

+440
-17
lines changed

12 files changed

+440
-17
lines changed

Package.resolved

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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 */,

ResourceApp/ResourceApp/Info.plist

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44
<dict>
55
<key>CFBundleDevelopmentRegion</key>
66
<string>en</string>
7+
<key>CFBundleDocumentTypes</key>
8+
<array>
9+
<dict>
10+
<key>CFBundleTypeName</key>
11+
<string>MKDirectionsRequest</string>
12+
<key>LSItemContentTypes</key>
13+
<array>
14+
<string>com.apple.maps.directionsrequest</string>
15+
</array>
16+
</dict>
17+
</array>
718
<key>CFBundleExecutable</key>
819
<string>$(EXECUTABLE_NAME)</string>
920
<key>CFBundleIdentifier</key>
@@ -22,10 +33,6 @@
2233
<string>1</string>
2334
<key>LSRequiresIPhoneOS</key>
2435
<true/>
25-
<key>UILaunchStoryboardName</key>
26-
<string>LaunchScreen</string>
27-
<key>UIMainStoryboardFile</key>
28-
<string>Main</string>
2936
<key>UIAppFonts</key>
3037
<array>
3138
<string>AveriaLibre-B.ttf</string>
@@ -34,10 +41,73 @@
3441
<string>AveriaLibre.ttf</string>
3542
<string>GdyBkltter1911.ttf</string>
3643
</array>
44+
<key>UIApplicationShortcutItems</key>
45+
<array>
46+
<dict>
47+
<key>UIApplicationShortcutItemIconFile</key>
48+
<string>ShortcutQrScanning</string>
49+
<key>UIApplicationShortcutItemTitle</key>
50+
<string>Scan QR-code</string>
51+
<key>UIApplicationShortcutItemType</key>
52+
<string>nl.mathijskadijk.shortcuts.qr-scanning</string>
53+
</dict>
54+
<dict>
55+
<key>UIApplicationShortcutItemIconFile</key>
56+
<string>ShortcutSendParcel</string>
57+
<key>UIApplicationShortcutItemTitle</key>
58+
<string>Send a Parcel</string>
59+
<key>UIApplicationShortcutItemType</key>
60+
<string>nl.mathijskadijk.shortcuts.send-parcel</string>
61+
</dict>
62+
</array>
63+
<key>UIApplicationSupportsMultipleScenes</key>
64+
<true/>
65+
<key>UILaunchStoryboardName</key>
66+
<string>LaunchScreen</string>
67+
<key>UIMainStoryboardFile</key>
68+
<string>Main</string>
3769
<key>UIRequiredDeviceCapabilities</key>
3870
<array>
3971
<string>armv7</string>
4072
</array>
73+
<key>UISceneConfigurations</key>
74+
<dict>
75+
<key>UIWindowSceneSessionRoleApplication</key>
76+
<array>
77+
<dict>
78+
<key>UILaunchStoryboardName</key>
79+
<string>LaunchScreen</string>
80+
<key>UISceneConfigurationName</key>
81+
<string>Default Configuration</string>
82+
<key>UISceneDelegateClassName</key>
83+
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
84+
</dict>
85+
</array>
86+
</dict>
87+
<key>NSUserActivityTypes</key>
88+
<array>
89+
<string>PlanTripIntent</string>
90+
<string>ShowDeparturesIntent</string>
91+
</array>
92+
<key>NSExtension</key>
93+
<dict>
94+
<key>NSExtensionAttributes</key>
95+
<dict>
96+
<key>IntentsRestrictedWhileLocked</key>
97+
<array/>
98+
<key>IntentsRestrictedWhileProtectedDataUnavailable</key>
99+
<array/>
100+
<key>IntentsSupported</key>
101+
<array>
102+
<string>PlanTripIntent</string>
103+
<string>ShowDeparturesIntent</string>
104+
</array>
105+
</dict>
106+
<key>NSExtensionPointIdentifier</key>
107+
<string>com.apple.intents-service</string>
108+
<key>NSExtensionPrincipalClass</key>
109+
<string>$(PRODUCT_MODULE_NAME).IntentHandler</string>
110+
</dict>
41111
<key>UIStatusBarTintParameters</key>
42112
<dict>
43113
<key>UINavigationBar</key>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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+
XCTAssertEqual(R.info.nsExtension.nsExtensionPrincipalClass, "ResourceApp.IntentHandler")
21+
}
22+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
//
2+
// PropertyListGenerator.swift
3+
// R.swift
4+
//
5+
// Created by Tom Lokhorst on 2018-07-07.
6+
// From: https://github.com/mac-cain13/R.swift
7+
// License: MIT License
8+
//
9+
10+
import Foundation
11+
12+
struct PropertyListGenerator: ExternalOnlyStructGenerator {
13+
private let name: SwiftIdentifier
14+
private let plists: [PropertyList]
15+
private let toplevelKeysWhitelist: [String]?
16+
17+
init(name: SwiftIdentifier, plists: [PropertyList], toplevelKeysWhitelist: [String]?) {
18+
self.name = name
19+
self.plists = plists
20+
self.toplevelKeysWhitelist = toplevelKeysWhitelist
21+
}
22+
23+
func generatedStruct(at externalAccessLevel: AccessLevel, prefix: SwiftIdentifier) -> Struct {
24+
guard let plist = plists.first else { return .empty }
25+
26+
guard plists.all(where: { $0.url == plist.url }) else {
27+
let configs = plists.map { $0.buildConfigurationName }
28+
warn("Build configurations \(configs) use different \(name) files, this is not yet supported")
29+
return .empty
30+
}
31+
32+
let contents: PropertyList.Contents
33+
if let whitelist = toplevelKeysWhitelist {
34+
contents = plist.contents.filter { (key, _) in whitelist.contains(key) }
35+
} else {
36+
contents = plist.contents
37+
}
38+
39+
let qualifiedName = prefix + name
40+
41+
return Struct(
42+
availables: [],
43+
comments: ["This `\(qualifiedName)` struct is generated, and contains static references to \(contents.count) properties."],
44+
accessModifier: externalAccessLevel,
45+
type: Type(module: .host, name: name),
46+
implements: [],
47+
typealiasses: [],
48+
properties: propertiesFromInfoPlist(contents: contents, path: [], at: externalAccessLevel),
49+
functions: [],
50+
structs: structsFromInfoPlist(contents: contents, path: [], at: externalAccessLevel),
51+
classes: [],
52+
os: []
53+
)
54+
}
55+
56+
private func propertiesFromInfoPlist(contents: [String: Any], path: [String], at externalAccessLevel: AccessLevel) -> [Let] {
57+
58+
return contents
59+
.compactMap { (key, value) -> Let? in
60+
switch value {
61+
case let value as Bool:
62+
return Let(
63+
comments: [],
64+
accessModifier: externalAccessLevel,
65+
isStatic: true,
66+
name: SwiftIdentifier(name: key),
67+
typeDefinition: .inferred(Type._Bool),
68+
value: "\(value)"
69+
)
70+
case let value as String:
71+
return propertyFromInfoString(key: key, value: value, path: path, at: externalAccessLevel)
72+
default:
73+
return nil
74+
}
75+
}
76+
}
77+
78+
private func propertyFromInfoString(key: String, value: String, path: [String], at externalAccessLevel: AccessLevel) -> Let {
79+
80+
let steps = path.map { "\"\($0.escapedStringLiteral)\"" }.joined(separator: ", ")
81+
82+
let isKey = key == "_key"
83+
let letValue: String = isKey
84+
? "\"\(value.escapedStringLiteral)\""
85+
: "infoPlistString(path: [\(steps)], key: \"\(key.escapedStringLiteral)\") ?? \"\(value.escapedStringLiteral)\""
86+
87+
return Let(
88+
comments: [],
89+
accessModifier: externalAccessLevel,
90+
isStatic: true,
91+
name: SwiftIdentifier(name: key),
92+
typeDefinition: .inferred(Type._String),
93+
value: letValue
94+
)
95+
}
96+
97+
private func structsFromInfoPlist(contents: [String: Any], path: [String], at externalAccessLevel: AccessLevel) -> [Struct] {
98+
99+
return contents
100+
.compactMap { (key, value) -> Struct? in
101+
var ps = path
102+
ps.append(key)
103+
104+
switch value {
105+
case let array as [String]:
106+
return Struct(
107+
availables: [],
108+
comments: [],
109+
accessModifier: externalAccessLevel,
110+
type: Type(module: .host, name: SwiftIdentifier(name: key)),
111+
implements: [],
112+
typealiasses: [],
113+
properties: array.map { item in
114+
propertyFromInfoString(key: item, value: item, path: ps, at: externalAccessLevel)
115+
},
116+
functions: [],
117+
structs: [],
118+
classes: [],
119+
os: []
120+
)
121+
122+
case var dict as [String: Any]:
123+
dict["_key"] = key
124+
125+
return Struct(
126+
availables: [],
127+
comments: [],
128+
accessModifier: externalAccessLevel,
129+
type: Type(module: .host, name: SwiftIdentifier(name: key)),
130+
implements: [],
131+
typealiasses: [],
132+
properties: propertiesFromInfoPlist(contents: dict, path: ps, at: externalAccessLevel),
133+
functions: [],
134+
structs: structsFromInfoPlist(contents: dict, path: ps, at: externalAccessLevel),
135+
classes: [],
136+
os: []
137+
)
138+
139+
case let dicts as [[String: Any]] where arrayOfDictionariesPrimaryKeys.keys.contains(key):
140+
return structForArrayOfDictionaries(key: key, dicts: dicts, path: path, at: externalAccessLevel)
141+
142+
default:
143+
return nil
144+
}
145+
}
146+
}
147+
148+
// For arrays of dictionaries we need a primary key.
149+
// This key will be used as a name for the struct in the generated code.
150+
private let arrayOfDictionariesPrimaryKeys: [String: String] = [
151+
"UIWindowSceneSessionRoleExternalDisplay": "UISceneConfigurationName",
152+
"UIWindowSceneSessionRoleApplication": "UISceneConfigurationName",
153+
"UIApplicationShortcutItems": "UIApplicationShortcutItemType",
154+
"CFBundleDocumentTypes": "CFBundleTypeName",
155+
"CFBundleURLTypes": "CFBundleURLName"
156+
]
157+
158+
private func structForArrayOfDictionaries(key: String, dicts: [[String: Any]], path: [String], at externalAccessLevel: AccessLevel) -> Struct {
159+
let kvs = dicts.compactMap { dict -> (String, [String: Any])? in
160+
if
161+
let primaryKey = arrayOfDictionariesPrimaryKeys[key],
162+
let type = dict[primaryKey] as? String
163+
{
164+
return (type, dict)
165+
}
166+
167+
return nil
168+
}
169+
170+
var ps = path
171+
ps.append(key)
172+
173+
let contents = Dictionary(kvs, uniquingKeysWith: { (l, _) in l })
174+
return Struct(
175+
availables: [],
176+
comments: [],
177+
accessModifier: externalAccessLevel,
178+
type: Type(module: .host, name: SwiftIdentifier(name: key)),
179+
implements: [],
180+
typealiasses: [],
181+
properties: [],
182+
functions: [],
183+
structs: structsFromInfoPlist(contents: contents, path: ps, at: externalAccessLevel),
184+
classes: [],
185+
os: []
186+
)
187+
}
188+
}

Sources/RswiftCore/ResourceTypes/Font.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//
99

1010
import Foundation
11+
import CoreGraphics
1112

1213
struct Font: WhiteListedExtensionsResourceType {
1314
static let supportedExtensions: Set<String> = ["otf", "ttf"]

0 commit comments

Comments
 (0)