";
73 | };
74 | /* End PBXGroup section */
75 |
76 | /* Begin PBXNativeTarget section */
77 | 281ABF362A420B7F00E56E02 /* Demo App */ = {
78 | isa = PBXNativeTarget;
79 | buildConfigurationList = 281ABF462A420B8000E56E02 /* Build configuration list for PBXNativeTarget "Demo App" */;
80 | buildPhases = (
81 | 281ABF332A420B7F00E56E02 /* Sources */,
82 | 281ABF342A420B7F00E56E02 /* Frameworks */,
83 | 281ABF352A420B7F00E56E02 /* Resources */,
84 | );
85 | buildRules = (
86 | );
87 | dependencies = (
88 | );
89 | name = "Demo App";
90 | packageProductDependencies = (
91 | 285272922A420BE500318D7E /* SFSymbolsMacro */,
92 | );
93 | productName = "Demo App";
94 | productReference = 281ABF372A420B7F00E56E02 /* Demo App.app */;
95 | productType = "com.apple.product-type.application";
96 | };
97 | /* End PBXNativeTarget section */
98 |
99 | /* Begin PBXProject section */
100 | 281ABF2F2A420B7F00E56E02 /* Project object */ = {
101 | isa = PBXProject;
102 | attributes = {
103 | BuildIndependentTargetsInParallel = 1;
104 | LastSwiftUpdateCheck = 1500;
105 | LastUpgradeCheck = 1500;
106 | TargetAttributes = {
107 | 281ABF362A420B7F00E56E02 = {
108 | CreatedOnToolsVersion = 15.0;
109 | };
110 | };
111 | };
112 | buildConfigurationList = 281ABF322A420B7F00E56E02 /* Build configuration list for PBXProject "Demo App" */;
113 | compatibilityVersion = "Xcode 14.0";
114 | developmentRegion = en;
115 | hasScannedForEncodings = 0;
116 | knownRegions = (
117 | en,
118 | Base,
119 | );
120 | mainGroup = 281ABF2E2A420B7F00E56E02;
121 | packageReferences = (
122 | 285272912A420BE500318D7E /* XCLocalSwiftPackageReference ".." */,
123 | );
124 | productRefGroup = 281ABF382A420B7F00E56E02 /* Products */;
125 | projectDirPath = "";
126 | projectRoot = "";
127 | targets = (
128 | 281ABF362A420B7F00E56E02 /* Demo App */,
129 | );
130 | };
131 | /* End PBXProject section */
132 |
133 | /* Begin PBXResourcesBuildPhase section */
134 | 281ABF352A420B7F00E56E02 /* Resources */ = {
135 | isa = PBXResourcesBuildPhase;
136 | buildActionMask = 2147483647;
137 | files = (
138 | 281ABF432A420B8000E56E02 /* Preview Assets.xcassets in Resources */,
139 | 281ABF3F2A420B8000E56E02 /* Assets.xcassets in Resources */,
140 | );
141 | runOnlyForDeploymentPostprocessing = 0;
142 | };
143 | /* End PBXResourcesBuildPhase section */
144 |
145 | /* Begin PBXSourcesBuildPhase section */
146 | 281ABF332A420B7F00E56E02 /* Sources */ = {
147 | isa = PBXSourcesBuildPhase;
148 | buildActionMask = 2147483647;
149 | files = (
150 | 281ABF3D2A420B7F00E56E02 /* ContentView.swift in Sources */,
151 | 281ABF3B2A420B7F00E56E02 /* Demo_AppApp.swift in Sources */,
152 | );
153 | runOnlyForDeploymentPostprocessing = 0;
154 | };
155 | /* End PBXSourcesBuildPhase section */
156 |
157 | /* Begin XCBuildConfiguration section */
158 | 281ABF442A420B8000E56E02 /* Debug */ = {
159 | isa = XCBuildConfiguration;
160 | buildSettings = {
161 | ALWAYS_SEARCH_USER_PATHS = NO;
162 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
163 | CLANG_ANALYZER_NONNULL = YES;
164 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
165 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
166 | CLANG_ENABLE_MODULES = YES;
167 | CLANG_ENABLE_OBJC_ARC = YES;
168 | CLANG_ENABLE_OBJC_WEAK = YES;
169 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
170 | CLANG_WARN_BOOL_CONVERSION = YES;
171 | CLANG_WARN_COMMA = YES;
172 | CLANG_WARN_CONSTANT_CONVERSION = YES;
173 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
174 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
175 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
176 | CLANG_WARN_EMPTY_BODY = YES;
177 | CLANG_WARN_ENUM_CONVERSION = YES;
178 | CLANG_WARN_INFINITE_RECURSION = YES;
179 | CLANG_WARN_INT_CONVERSION = YES;
180 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
181 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
182 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
183 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
184 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
185 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
186 | CLANG_WARN_STRICT_PROTOTYPES = YES;
187 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
188 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
189 | CLANG_WARN_UNREACHABLE_CODE = YES;
190 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
191 | COPY_PHASE_STRIP = NO;
192 | DEBUG_INFORMATION_FORMAT = dwarf;
193 | ENABLE_STRICT_OBJC_MSGSEND = YES;
194 | ENABLE_TESTABILITY = YES;
195 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
196 | GCC_C_LANGUAGE_STANDARD = gnu17;
197 | GCC_DYNAMIC_NO_PIC = NO;
198 | GCC_NO_COMMON_BLOCKS = YES;
199 | GCC_OPTIMIZATION_LEVEL = 0;
200 | GCC_PREPROCESSOR_DEFINITIONS = (
201 | "DEBUG=1",
202 | "$(inherited)",
203 | );
204 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
205 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
206 | GCC_WARN_UNDECLARED_SELECTOR = YES;
207 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
208 | GCC_WARN_UNUSED_FUNCTION = YES;
209 | GCC_WARN_UNUSED_VARIABLE = YES;
210 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
211 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
212 | MTL_FAST_MATH = YES;
213 | ONLY_ACTIVE_ARCH = YES;
214 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
215 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
216 | };
217 | name = Debug;
218 | };
219 | 281ABF452A420B8000E56E02 /* Release */ = {
220 | isa = XCBuildConfiguration;
221 | buildSettings = {
222 | ALWAYS_SEARCH_USER_PATHS = NO;
223 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
224 | CLANG_ANALYZER_NONNULL = YES;
225 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
226 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
227 | CLANG_ENABLE_MODULES = YES;
228 | CLANG_ENABLE_OBJC_ARC = YES;
229 | CLANG_ENABLE_OBJC_WEAK = YES;
230 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
231 | CLANG_WARN_BOOL_CONVERSION = YES;
232 | CLANG_WARN_COMMA = YES;
233 | CLANG_WARN_CONSTANT_CONVERSION = YES;
234 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
235 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
236 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
237 | CLANG_WARN_EMPTY_BODY = YES;
238 | CLANG_WARN_ENUM_CONVERSION = YES;
239 | CLANG_WARN_INFINITE_RECURSION = YES;
240 | CLANG_WARN_INT_CONVERSION = YES;
241 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
242 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
243 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
244 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
245 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
246 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
247 | CLANG_WARN_STRICT_PROTOTYPES = YES;
248 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
249 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
250 | CLANG_WARN_UNREACHABLE_CODE = YES;
251 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
252 | COPY_PHASE_STRIP = NO;
253 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
254 | ENABLE_NS_ASSERTIONS = NO;
255 | ENABLE_STRICT_OBJC_MSGSEND = YES;
256 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
257 | GCC_C_LANGUAGE_STANDARD = gnu17;
258 | GCC_NO_COMMON_BLOCKS = YES;
259 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
260 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
261 | GCC_WARN_UNDECLARED_SELECTOR = YES;
262 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
263 | GCC_WARN_UNUSED_FUNCTION = YES;
264 | GCC_WARN_UNUSED_VARIABLE = YES;
265 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
266 | MTL_ENABLE_DEBUG_INFO = NO;
267 | MTL_FAST_MATH = YES;
268 | SWIFT_COMPILATION_MODE = wholemodule;
269 | };
270 | name = Release;
271 | };
272 | 281ABF472A420B8000E56E02 /* Debug */ = {
273 | isa = XCBuildConfiguration;
274 | buildSettings = {
275 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
276 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
277 | CODE_SIGN_ENTITLEMENTS = "Demo App/Demo_App.entitlements";
278 | CODE_SIGN_STYLE = Automatic;
279 | CURRENT_PROJECT_VERSION = 1;
280 | DEVELOPMENT_ASSET_PATHS = "\"Demo App/Preview Content\"";
281 | DEVELOPMENT_TEAM = F992DREF6G;
282 | ENABLE_HARDENED_RUNTIME = YES;
283 | ENABLE_PREVIEWS = YES;
284 | GENERATE_INFOPLIST_FILE = YES;
285 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
286 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
287 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
288 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
289 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
290 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
291 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
292 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
293 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
294 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
295 | IPHONEOS_DEPLOYMENT_TARGET = 17.0;
296 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
297 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
298 | MACOSX_DEPLOYMENT_TARGET = 13.1;
299 | MARKETING_VERSION = 1.0;
300 | PRODUCT_BUNDLE_IDENTIFIER = "com.demo.Demo-App";
301 | PRODUCT_NAME = "$(TARGET_NAME)";
302 | SDKROOT = auto;
303 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
304 | SWIFT_EMIT_LOC_STRINGS = YES;
305 | SWIFT_VERSION = 5.0;
306 | TARGETED_DEVICE_FAMILY = "1,2";
307 | };
308 | name = Debug;
309 | };
310 | 281ABF482A420B8000E56E02 /* Release */ = {
311 | isa = XCBuildConfiguration;
312 | buildSettings = {
313 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
314 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
315 | CODE_SIGN_ENTITLEMENTS = "Demo App/Demo_App.entitlements";
316 | CODE_SIGN_STYLE = Automatic;
317 | CURRENT_PROJECT_VERSION = 1;
318 | DEVELOPMENT_ASSET_PATHS = "\"Demo App/Preview Content\"";
319 | DEVELOPMENT_TEAM = F992DREF6G;
320 | ENABLE_HARDENED_RUNTIME = YES;
321 | ENABLE_PREVIEWS = YES;
322 | GENERATE_INFOPLIST_FILE = YES;
323 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
324 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
325 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
326 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
327 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
328 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
329 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
330 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
331 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
332 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
333 | IPHONEOS_DEPLOYMENT_TARGET = 17.0;
334 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
335 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
336 | MACOSX_DEPLOYMENT_TARGET = 13.1;
337 | MARKETING_VERSION = 1.0;
338 | PRODUCT_BUNDLE_IDENTIFIER = "com.demo.Demo-App";
339 | PRODUCT_NAME = "$(TARGET_NAME)";
340 | SDKROOT = auto;
341 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
342 | SWIFT_EMIT_LOC_STRINGS = YES;
343 | SWIFT_VERSION = 5.0;
344 | TARGETED_DEVICE_FAMILY = "1,2";
345 | };
346 | name = Release;
347 | };
348 | /* End XCBuildConfiguration section */
349 |
350 | /* Begin XCConfigurationList section */
351 | 281ABF322A420B7F00E56E02 /* Build configuration list for PBXProject "Demo App" */ = {
352 | isa = XCConfigurationList;
353 | buildConfigurations = (
354 | 281ABF442A420B8000E56E02 /* Debug */,
355 | 281ABF452A420B8000E56E02 /* Release */,
356 | );
357 | defaultConfigurationIsVisible = 0;
358 | defaultConfigurationName = Release;
359 | };
360 | 281ABF462A420B8000E56E02 /* Build configuration list for PBXNativeTarget "Demo App" */ = {
361 | isa = XCConfigurationList;
362 | buildConfigurations = (
363 | 281ABF472A420B8000E56E02 /* Debug */,
364 | 281ABF482A420B8000E56E02 /* Release */,
365 | );
366 | defaultConfigurationIsVisible = 0;
367 | defaultConfigurationName = Release;
368 | };
369 | /* End XCConfigurationList section */
370 |
371 | /* Begin XCLocalSwiftPackageReference section */
372 | 285272912A420BE500318D7E /* XCLocalSwiftPackageReference ".." */ = {
373 | isa = XCLocalSwiftPackageReference;
374 | relativePath = ..;
375 | };
376 | /* End XCLocalSwiftPackageReference section */
377 |
378 | /* Begin XCSwiftPackageProductDependency section */
379 | 285272922A420BE500318D7E /* SFSymbolsMacro */ = {
380 | isa = XCSwiftPackageProductDependency;
381 | productName = SFSymbolsMacro;
382 | };
383 | /* End XCSwiftPackageProductDependency section */
384 | };
385 | rootObject = 281ABF2F2A420B7F00E56E02 /* Project object */;
386 | }
387 |
--------------------------------------------------------------------------------
/Demo App/Demo App.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo App/Demo App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo App/Demo App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "pins" : [
3 | {
4 | "identity" : "swift-syntax",
5 | "kind" : "remoteSourceControl",
6 | "location" : "https://github.com/apple/swift-syntax.git",
7 | "state" : {
8 | "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d",
9 | "version" : "509.1.1"
10 | }
11 | }
12 | ],
13 | "version" : 2
14 | }
15 |
--------------------------------------------------------------------------------
/Demo App/Demo App/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demo App/Demo App/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "scale" : "1x",
11 | "size" : "16x16"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "scale" : "2x",
16 | "size" : "16x16"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "scale" : "1x",
21 | "size" : "32x32"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "scale" : "2x",
26 | "size" : "32x32"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "scale" : "1x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "scale" : "2x",
36 | "size" : "128x128"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "scale" : "1x",
41 | "size" : "256x256"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "2x",
46 | "size" : "256x256"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "scale" : "1x",
51 | "size" : "512x512"
52 | },
53 | {
54 | "idiom" : "mac",
55 | "scale" : "2x",
56 | "size" : "512x512"
57 | }
58 | ],
59 | "info" : {
60 | "author" : "xcode",
61 | "version" : 1
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Demo App/Demo App/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo App/Demo App/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // Demo App
4 | //
5 | // Created by Lukas Pistrol on 20.06.23.
6 | //
7 |
8 | import SwiftUI
9 | import SFSymbolsMacro
10 |
11 | @SFSymbol
12 | enum Symbols: String, CaseIterable {
13 | case globe
14 | case folder
15 | case folderFill = "folder.fill"
16 | case folderBadgeMinus = "folder.badge.minus"
17 | case folderBadgeQuestionmark = "folder.badge.questionmark"
18 | case square
19 | case squareSlash = "square.slash"
20 | case squareLefthalfFilled = "square.lefthalf.filled"
21 | case squareInsetFilled = "square.inset.filled"
22 | case squareSplitDiagonalFill = "square.split.diagonal.fill"
23 | }
24 |
25 | struct ContentView: View {
26 | var body: some View {
27 | VStack {
28 | Label("Hello, World!", systemImage: Symbols.globe())
29 | Spacer()
30 | LazyVGrid(columns: columns) {
31 | ForEach(Symbols.allCases) { symbol in
32 | symbol.image
33 | .imageScale(.medium)
34 | .font(.largeTitle)
35 | }
36 | }
37 | }
38 | .padding()
39 | }
40 |
41 | private var columns: [GridItem] {
42 | .init(repeating: GridItem(.fixed(50)), count: 5)
43 | }
44 | }
45 |
46 | extension Symbols: Identifiable {
47 | var id: String { self.rawValue }
48 | }
49 |
50 | #Preview {
51 | ContentView()
52 | }
53 |
--------------------------------------------------------------------------------
/Demo App/Demo App/Demo_App.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Demo App/Demo App/Demo_AppApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Demo_AppApp.swift
3 | // Demo App
4 | //
5 | // Created by Lukas Pistrol on 20.06.23.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct Demo_AppApp: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | ContentView()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Demo App/Demo App/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Lukas Pistrol
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "pins" : [
3 | {
4 | "identity" : "swift-syntax",
5 | "kind" : "remoteSourceControl",
6 | "location" : "https://github.com/swiftlang/swift-syntax",
7 | "state" : {
8 | "revision" : "0687f71944021d616d34d922343dcef086855920",
9 | "version" : "600.0.1"
10 | }
11 | }
12 | ],
13 | "version" : 2
14 | }
15 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.9
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 | import CompilerPluginSupport
6 |
7 | let package = Package(
8 | name: "SFSymbolsMacro",
9 | platforms: [.macOS(.v11), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)],
10 | products: [
11 | .library(
12 | name: "SFSymbolsMacro",
13 | targets: ["SFSymbolsMacro"]
14 | ),
15 | ],
16 | dependencies: [
17 | .package(url: "https://github.com/swiftlang/swift-syntax", from: "600.0.1"),
18 | ],
19 | targets: [
20 | .macro(
21 | name: "SFSymbolsMacroImpl",
22 | dependencies: [
23 | .product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
24 | .product(name: "SwiftCompilerPlugin", package: "swift-syntax")
25 | ]
26 | ),
27 |
28 | .target(name: "SFSymbolsMacro", dependencies: ["SFSymbolsMacroImpl"]),
29 |
30 | .testTarget(
31 | name: "SFSymbolsMacroTests",
32 | dependencies: [
33 | "SFSymbolsMacroImpl",
34 | .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
35 | ]
36 | ),
37 | ]
38 | )
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | # SFSymbolsMacro
14 |
15 | This Swift Macro provides an easy way to make the use of SF Symbols in Swift more or less *"type-safe"*.
16 |
17 | ## Installation
18 |
19 | ### Xcode
20 |
21 | 1. Click File > Add Package Dependencies
22 | 2. Paste the following link into the search field on the upper-right:
23 | ```
24 | https://github.com/lukepistrol/SFSymbolsMacro.git
25 | ```
26 |
27 | ### Swift Package Manager
28 |
29 | In `Package.swift`:
30 |
31 | ```swift
32 | dependencies: [
33 | .package(url: "https://github.com/lukepistrol/SFSymbolsMacro.git", from: "0.1.0")
34 | ]
35 | ```
36 |
37 | And then add the dependency to your targets.
38 |
39 | ## Usage
40 |
41 | Simply create an `enum` which will hold all the SF Symbols for your project:
42 |
43 | ```swift
44 | enum Symbols: String {
45 | case circle
46 | case circleFill = "circle.fill"
47 | case shareIcon = "square.and.arrow.up"
48 | case globe
49 | }
50 | ```
51 |
52 | Then simply import `SFSymbolsMacro` and add the `@SFSymbol` macro annotation to the enum:
53 |
54 | ```swift
55 | import SFSymbolsMacro
56 | import SwiftUI
57 |
58 | @SFSymbol
59 | enum Symbols: String { ... }
60 | ```
61 |
62 | The macro will then validate each `case` and the expanded macro will look something like this:
63 |
64 | ```swift
65 | enum Symbols: String {
66 | case circle
67 | case circleFill = "circle.fill"
68 | case shareIcon = "square.and.arrow.up"
69 | case globe
70 |
71 | var image: Image {
72 | Image(systemName: self.rawValue)
73 | }
74 | var name: String {
75 | self.rawValue
76 | }
77 | #if canImport(UIKit)
78 | func uiImage(configuration: UIImage.Configuration? = nil) -> UIImage {
79 | UIImage(systemName: self.rawValue, withConfiguration: configuration)!
80 | }
81 | #else
82 | func nsImage(accessibilityDescription: String? = nil) -> NSImage {
83 | return NSImage(systemSymbolName: self.rawValue, accessibilityDescription: accessibilityDescription)!
84 | }
85 | #endif
86 | func callAsFunction() -> String {
87 | return self.rawValue
88 | }
89 | }
90 | ```
91 |
92 | In your code you can then call a symbol:
93 |
94 | ```swift
95 | var body: some View {
96 | VStack {
97 | Symbols.circleFill.image
98 | Label("Globe", systemImage: Symbols.globe.name)
99 | // the above can also be written as
100 | Label("Globe", systemImage: Symbols.globe())
101 | }
102 | }
103 | ```
104 |
105 | In case the provided raw value is not a valid SF Symbol, Xcode will show a compile error at the `enum-case` in question:
106 |
107 | 
108 |
109 | 
110 |
111 |
112 | ## Contribution
113 |
114 | If you have any ideas on how to take this further I'm happy to discuss things in an issue.
115 |
116 | -----
117 |
118 |
119 |
--------------------------------------------------------------------------------
/Sources/SFSymbolsMacro/SFSymbol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SFSymbol.swift
3 | // SFSymbolsMacro/SFSymbolsMacro
4 | //
5 | // Created by Lukas Pistrol on 14.06.23.
6 | //
7 |
8 | /**
9 | A Swift macro for *"type-safe"* SF Symbols.
10 |
11 | ## Initialization
12 | ```swift
13 | @SFSymbol
14 | enum Symbols: String {
15 | case globe
16 | case circleFill = "circle.fill"
17 | }
18 | ```
19 |
20 | ## Usage
21 | ```swift
22 | var body: some View {
23 | Symbols.circleFill.image // ~= Image(systemName: "circle.fill")
24 | Label("Globe", systemImage: Symbols.globe.name) // ~= Label("Globe", systemImage: "globe")
25 | // the above can also be written as
26 | Label("Globe", systemImage: Symbols.globe())
27 | }
28 | ```
29 | */
30 | @attached(member, names: arbitrary)
31 | public macro SFSymbol() = #externalMacro(module: "SFSymbolsMacroImpl", type: "SFSymbolMacro")
32 |
--------------------------------------------------------------------------------
/Sources/SFSymbolsMacroImpl/SFSymbolsDiagnostic.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SFSymbolsDiagnostic.swift
3 | // SFSymbolsMacro/SFSymbolsMacroImpl
4 | //
5 | // Created by Lukas Pistrol on 14.06.23.
6 | //
7 |
8 | import SwiftDiagnostics
9 |
10 | enum SFSymbolDiagnostic: DiagnosticMessage {
11 | case notAnEnum
12 | case missingStringProtocolConformance(symbol: String)
13 | case noValidSFSymbol(symbol: String)
14 |
15 | var severity: DiagnosticSeverity { return .error }
16 |
17 | var message: String {
18 | switch self {
19 | case .noValidSFSymbol(let symbol):
20 | "\"\(symbol)\" is not a valid SF Symbol."
21 | case .notAnEnum:
22 | "Macro \"@SFSymbol\" can only be applied to enums."
23 | case .missingStringProtocolConformance(let symbol):
24 | "Enum \"\(symbol)\" must declare a raw value type of String."
25 | }
26 | }
27 |
28 | var diagnosticID: MessageID {
29 | MessageID(domain: "SFSymbolMacro", id: self.message)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/SFSymbolsMacroImpl/SFSymbolsMacro.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SFSymbolsMacro.swift
3 | // SFSymbolsMacro/SFSymbolsMacroImpl
4 | //
5 | // Created by Lukas Pistrol on 14.06.23.
6 | //
7 |
8 | import SwiftDiagnostics
9 | import SwiftSyntax
10 | import SwiftSyntaxMacros
11 | import SwiftUI
12 |
13 | public struct SFSymbolMacro: MemberMacro {
14 |
15 | private typealias SymbolPair = (id: String, node: Syntax)
16 |
17 | public static func expansion<
18 | Declaration: DeclGroupSyntax, Context: MacroExpansionContext
19 | >(
20 | of node: AttributeSyntax,
21 | providingMembersOf declaration: Declaration,
22 | in context: Context
23 | ) throws -> [DeclSyntax] {
24 | try validate(declaration)
25 | let accessLevel = try getAccessLevel(declaration)
26 |
27 | return [
28 | """
29 | \(raw: accessLevel)var image: Image {
30 | Image(systemName: self.rawValue)
31 | }
32 | """,
33 | """
34 | \(raw: accessLevel)var name: String {
35 | self.rawValue
36 | }
37 | """,
38 | """
39 | #if canImport(UIKit)
40 | \(raw: accessLevel)func uiImage(configuration: UIImage.Configuration? = nil) -> UIImage {
41 | UIImage(systemName: self.rawValue, withConfiguration: configuration)!
42 | }
43 | #else
44 | \(raw: accessLevel)func nsImage(accessibilityDescription: String? = nil) -> NSImage {
45 | return NSImage(systemSymbolName: self.rawValue, accessibilityDescription: accessibilityDescription)!
46 | }
47 | #endif
48 | """,
49 | """
50 | \(raw: accessLevel)func callAsFunction() -> String {
51 | return self.rawValue
52 | }
53 | """
54 | ]
55 | }
56 |
57 | // MARK: Helper Methods
58 |
59 | private static func validate(_ declaration: DeclGroupSyntax) throws {
60 | try validateStringProtocolInheritance(declaration)
61 | let members = declaration.memberBlock.members
62 | let cases = members.compactMap { $0.decl.as(EnumCaseDeclSyntax.self) }
63 | let ids = getIdentifiers(from: cases)
64 | try ids.forEach { id throws in
65 | try assertUINSImage(for: id)
66 | }
67 | }
68 |
69 | private static func validateStringProtocolInheritance(_ declaration: DeclGroupSyntax) throws {
70 | guard let enumDecl = declaration.as(EnumDeclSyntax.self) else {
71 | throw DiagnosticsError(diagnostics: [
72 | .init(node: Syntax(declaration), message: SFSymbolDiagnostic.notAnEnum)
73 | ])
74 | }
75 | let identifier = enumDecl.name
76 | guard enumDecl.inheritanceClause?.inheritedTypes.contains(where: {
77 | $0.type.as(IdentifierTypeSyntax.self)?.name.text == "String"
78 | }) ?? false else {
79 | throw DiagnosticsError(diagnostics: [
80 | .init(node: Syntax(identifier), message: SFSymbolDiagnostic.missingStringProtocolConformance(symbol: identifier.text))
81 | ])
82 | }
83 | }
84 |
85 | /// Gets either the rawValue (if available) or the identifier of the enum case.
86 | private static func getIdentifiers(from cases: [EnumCaseDeclSyntax]) -> [SymbolPair] {
87 | return cases.flatMap { enumCase in
88 | let a = enumCase.elements.map {
89 | let idNode = $0.rawValue?.value.as(StringLiteralExprSyntax.self)?.segments.first {
90 | $0.as(StringSegmentSyntax.self) != nil
91 | }
92 | let id = idNode?.as(StringSegmentSyntax.self)?.content.text ?? $0.name.text
93 | let syntax = Syntax(enumCase)
94 | return (id: id, node: syntax)
95 | }
96 | return a
97 | }
98 | }
99 |
100 | private static func assertUINSImage(for id: (SymbolPair)) throws {
101 | #if canImport(UIKit)
102 | if let _ = UIImage(systemName: id.id) { return }
103 | #else
104 | if let _ = NSImage(systemSymbolName: id.id, accessibilityDescription: nil) { return }
105 | #endif
106 | throw DiagnosticsError(diagnostics: [
107 | .init(node: id.node, message: SFSymbolDiagnostic.noValidSFSymbol(symbol: id.0))
108 | ])
109 | }
110 |
111 | /// Gets access level
112 | private static func getAccessLevel(_ declaration: DeclGroupSyntax) throws -> String {
113 | guard let enumdeclaration = declaration.as(EnumDeclSyntax.self) else {
114 | throw DiagnosticsError(diagnostics: [
115 | .init(node: Syntax(declaration), message: SFSymbolDiagnostic.notAnEnum)
116 | ])
117 | }
118 | guard let accessLevel = enumdeclaration.modifiers.first(where: \.isNeededAccessLevelModifier)?.name.trimmed else {
119 | return ""
120 | }
121 | return "\(accessLevel.text) "
122 | }
123 | }
124 |
125 | extension DeclModifierSyntax {
126 | var isNeededAccessLevelModifier: Bool {
127 | switch self.name.tokenKind {
128 | case .keyword(.public): return true
129 | case .keyword(.internal): return true
130 | case .keyword(.fileprivate): return true
131 | case .keyword(.private): return true
132 | default: return false
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/Sources/SFSymbolsMacroImpl/SFSymbolsMacroPlugin.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SFSymbolsMacroPlugin.swift
3 | // SFSymbolsMacro/SFSymbolsMacroImpl
4 | //
5 | // Created by Lukas Pistrol on 14.06.23.
6 | //
7 |
8 | import SwiftCompilerPlugin
9 | import SwiftSyntaxMacros
10 |
11 | @main
12 | struct SFSymbolsMacroPlugin: CompilerPlugin {
13 | let providingMacros: [Macro.Type] = [
14 | SFSymbolMacro.self
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/Tests/SFSymbolsMacroTests/SFSymbolsMacroTests.swift:
--------------------------------------------------------------------------------
1 | import SwiftSyntaxMacros
2 | import SwiftSyntaxMacrosTestSupport
3 | import XCTest
4 | import SFSymbolsMacroImpl
5 |
6 | let testMacros: [String: Macro.Type] = [
7 | "SFSymbol": SFSymbolMacro.self,
8 | ]
9 |
10 | final class SFSymbolsMacroTests: XCTestCase {
11 |
12 | func testSFSymbolMacro() {
13 | assertMacroExpansion(
14 | """
15 | @SFSymbol
16 | enum Symbols: String {
17 | case globe
18 | case circleFill = "circle.fill"
19 | }
20 | """,
21 | expandedSource:
22 | """
23 |
24 | enum Symbols: String {
25 | case globe
26 | case circleFill = "circle.fill"
27 |
28 | var image: Image {
29 | Image(systemName: self.rawValue)
30 | }
31 |
32 | var name: String {
33 | self.rawValue
34 | }
35 |
36 | #if canImport(UIKit)
37 | func uiImage(configuration: UIImage.Configuration? = nil) -> UIImage {
38 | UIImage(systemName: self.rawValue, withConfiguration: configuration)!
39 | }
40 | #else
41 | func nsImage(accessibilityDescription: String? = nil) -> NSImage {
42 | return NSImage(systemSymbolName: self.rawValue, accessibilityDescription: accessibilityDescription)!
43 | }
44 | #endif
45 |
46 | func callAsFunction() -> String {
47 | return self.rawValue
48 | }
49 | }
50 | """,
51 | macros: testMacros
52 | )
53 | }
54 |
55 | func testPublicSFSymbolMacro() {
56 | assertMacroExpansion(
57 | """
58 | @SFSymbol
59 | public enum Symbols: String {
60 | case globe
61 | case circleFill = "circle.fill"
62 | }
63 | """,
64 | expandedSource:
65 | """
66 |
67 | public enum Symbols: String {
68 | case globe
69 | case circleFill = "circle.fill"
70 |
71 | public var image: Image {
72 | Image(systemName: self.rawValue)
73 | }
74 |
75 | public var name: String {
76 | self.rawValue
77 | }
78 |
79 | #if canImport(UIKit)
80 | public func uiImage(configuration: UIImage.Configuration? = nil) -> UIImage {
81 | UIImage(systemName: self.rawValue, withConfiguration: configuration)!
82 | }
83 | #else
84 | public func nsImage(accessibilityDescription: String? = nil) -> NSImage {
85 | return NSImage(systemSymbolName: self.rawValue, accessibilityDescription: accessibilityDescription)!
86 | }
87 | #endif
88 |
89 | public func callAsFunction() -> String {
90 | return self.rawValue
91 | }
92 | }
93 | """,
94 | macros: testMacros
95 | )
96 | }
97 |
98 | func testInternalSFSymbolMacro() {
99 | assertMacroExpansion(
100 | """
101 | @SFSymbol
102 | internal enum Symbols: String {
103 | case globe
104 | case circleFill = "circle.fill"
105 | }
106 | """,
107 | expandedSource:
108 | """
109 |
110 | internal enum Symbols: String {
111 | case globe
112 | case circleFill = "circle.fill"
113 |
114 | internal var image: Image {
115 | Image(systemName: self.rawValue)
116 | }
117 |
118 | internal var name: String {
119 | self.rawValue
120 | }
121 |
122 | #if canImport(UIKit)
123 | internal func uiImage(configuration: UIImage.Configuration? = nil) -> UIImage {
124 | UIImage(systemName: self.rawValue, withConfiguration: configuration)!
125 | }
126 | #else
127 | internal func nsImage(accessibilityDescription: String? = nil) -> NSImage {
128 | return NSImage(systemSymbolName: self.rawValue, accessibilityDescription: accessibilityDescription)!
129 | }
130 | #endif
131 |
132 | internal func callAsFunction() -> String {
133 | return self.rawValue
134 | }
135 | }
136 | """,
137 | macros: testMacros
138 | )
139 | }
140 |
141 | func testFilePrivateSFSymbolMacro() {
142 | assertMacroExpansion(
143 | """
144 | @SFSymbol
145 | fileprivate enum Symbols: String {
146 | case globe
147 | case circleFill = "circle.fill"
148 | }
149 | """,
150 | expandedSource:
151 | """
152 |
153 | fileprivate enum Symbols: String {
154 | case globe
155 | case circleFill = "circle.fill"
156 |
157 | fileprivate var image: Image {
158 | Image(systemName: self.rawValue)
159 | }
160 |
161 | fileprivate var name: String {
162 | self.rawValue
163 | }
164 |
165 | #if canImport(UIKit)
166 | fileprivate func uiImage(configuration: UIImage.Configuration? = nil) -> UIImage {
167 | UIImage(systemName: self.rawValue, withConfiguration: configuration)!
168 | }
169 | #else
170 | fileprivate func nsImage(accessibilityDescription: String? = nil) -> NSImage {
171 | return NSImage(systemSymbolName: self.rawValue, accessibilityDescription: accessibilityDescription)!
172 | }
173 | #endif
174 |
175 | fileprivate func callAsFunction() -> String {
176 | return self.rawValue
177 | }
178 | }
179 | """,
180 | macros: testMacros
181 | )
182 | }
183 |
184 | func testPrivateSFSymbolMacro() {
185 | assertMacroExpansion(
186 | """
187 | @SFSymbol
188 | private enum Symbols: String {
189 | case globe
190 | case circleFill = "circle.fill"
191 | }
192 | """,
193 | expandedSource:
194 | """
195 |
196 | private enum Symbols: String {
197 | case globe
198 | case circleFill = "circle.fill"
199 |
200 | private var image: Image {
201 | Image(systemName: self.rawValue)
202 | }
203 |
204 | private var name: String {
205 | self.rawValue
206 | }
207 |
208 | #if canImport(UIKit)
209 | private func uiImage(configuration: UIImage.Configuration? = nil) -> UIImage {
210 | UIImage(systemName: self.rawValue, withConfiguration: configuration)!
211 | }
212 | #else
213 | private func nsImage(accessibilityDescription: String? = nil) -> NSImage {
214 | return NSImage(systemSymbolName: self.rawValue, accessibilityDescription: accessibilityDescription)!
215 | }
216 | #endif
217 |
218 | private func callAsFunction() -> String {
219 | return self.rawValue
220 | }
221 | }
222 | """,
223 | macros: testMacros
224 | )
225 | }
226 |
227 | func testInvalidSFSymbolError() {
228 | assertMacroExpansion(
229 | """
230 | @SFSymbol
231 | enum Symbols: String {
232 | case circleFill
233 | }
234 | """,
235 | expandedSource:
236 | """
237 |
238 | enum Symbols: String {
239 | case circleFill
240 | }
241 | """,
242 | diagnostics: [
243 | .init(message: "\"circleFill\" is not a valid SF Symbol.", line: 3, column: 5)
244 | ],
245 | macros: testMacros
246 | )
247 | }
248 |
249 | func testInvalidSFSymbolErrorExplicit() {
250 | assertMacroExpansion(
251 | """
252 | @SFSymbol
253 | enum Symbols: String {
254 | case xyz = "xyz"
255 | }
256 | """,
257 | expandedSource:
258 | """
259 |
260 | enum Symbols: String {
261 | case xyz = "xyz"
262 | }
263 | """,
264 | diagnostics: [
265 | .init(message: "\"xyz\" is not a valid SF Symbol.", line: 3, column: 5)
266 | ],
267 | macros: testMacros
268 | )
269 | }
270 |
271 | func testInvalidEnum() {
272 | assertMacroExpansion(
273 | """
274 | @SFSymbol
275 | enum Symbols {
276 | case globe
277 | }
278 | """,
279 | expandedSource:
280 | """
281 |
282 | enum Symbols {
283 | case globe
284 | }
285 | """,
286 | diagnostics: [
287 | .init(message: "Enum \"Symbols\" must declare a raw value type of String.", line: 2, column: 6)
288 | ],
289 | macros: testMacros
290 | )
291 | }
292 |
293 | func testInvalidType() {
294 | assertMacroExpansion(
295 | """
296 | @SFSymbol
297 | struct Symbols {
298 | let xyz = "xyz"
299 | }
300 | """,
301 | expandedSource:
302 | """
303 |
304 | struct Symbols {
305 | let xyz = "xyz"
306 | }
307 | """,
308 | diagnostics: [
309 | .init(message: "Macro \"@SFSymbol\" can only be applied to enums.", line: 1, column: 1)
310 | ],
311 | macros: testMacros
312 | )
313 | }
314 |
315 | func testInvalidModifier() {
316 | assertMacroExpansion(
317 | """
318 | @SFSymbol
319 | struct Symbols {
320 | let xyz = "xyz"
321 | }
322 | """,
323 | expandedSource:
324 | """
325 |
326 | struct Symbols {
327 | let xyz = "xyz"
328 | }
329 | """,
330 | diagnostics: [
331 | .init(message: "Macro \"@SFSymbol\" can only be applied to enums.", line: 1, column: 1)
332 | ],
333 | macros: testMacros
334 | )
335 | }
336 | }
337 |
--------------------------------------------------------------------------------