diff --git a/Example/JustTweak/Accessors/GeneratedTweakAccessor.swift b/Example/JustTweak/Accessors/GeneratedTweakAccessor.swift index 244c7ea..f09d6ef 100644 --- a/Example/JustTweak/Accessors/GeneratedTweakAccessor.swift +++ b/Example/JustTweak/Accessors/GeneratedTweakAccessor.swift @@ -8,79 +8,49 @@ import JustTweak class GeneratedTweakAccessor { - static let tweakManager: TweakManager = { - var tweakProviders: [TweakProvider] = [] + private(set) var tweakManager: TweakManager - // EphemeralTweakProvider - #if DEBUG || CONFIGURATION_UI_TESTS - let ephemeralTweakProvider_1 = NSMutableDictionary() - tweakProviders.append(ephemeralTweakProvider_1) - #endif - - // UserDefaultsTweakProvider - #if DEBUG || CONFIGURATION_DEBUG - let userDefaultsTweakProvider_1 = UserDefaultsTweakProvider(userDefaults: UserDefaults.standard) - tweakProviders.append(userDefaultsTweakProvider_1) - #endif - - // LocalTweakProvider - #if DEBUG - let jsonFileURL_1 = Bundle.main.url(forResource: "LocalTweaks_TopPriority_example", withExtension: "json")! - let localTweakProvider_1 = LocalTweakProvider(jsonURL: jsonFileURL_1) - tweakProviders.append(localTweakProvider_1) - #endif - - // LocalTweakProvider - let jsonFileURL_2 = Bundle.main.url(forResource: "LocalTweaks_example", withExtension: "json")! - let localTweakProvider_2 = LocalTweakProvider(jsonURL: jsonFileURL_2) - tweakProviders.append(localTweakProvider_2) - - let tweakManager = TweakManager(tweakProviders: tweakProviders) - tweakManager.useCache = true - return tweakManager - }() - - var tweakManager: TweakManager { - return Self.tweakManager + init(with tweakManager: TweakManager) { + self.tweakManager = tweakManager } - @TweakProperty(feature: Features.general, - variable: Variables.answerToTheUniverse, - tweakManager: tweakManager) - var meaningOfLife: Int + var canShowGreenView: Bool { + get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayGreenView)?.boolValue ?? false } + set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.displayGreenView) } + } - @TweakProperty(feature: Features.general, - variable: Variables.greetOnAppDidBecomeActive, - tweakManager: tweakManager) - var shouldShowAlert: Bool + var canShowRedView: Bool { + get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayRedView)?.boolValue ?? false } + set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.displayRedView) } + } - @TweakProperty(feature: Features.general, - variable: Variables.tapToChangeColorEnabled, - tweakManager: tweakManager) - var isTapGestureToChangeColorEnabled: Bool + var canShowYellowView: Bool { + get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayYellowView)?.boolValue ?? false } + set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.displayYellowView) } + } - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.displayGreenView, - tweakManager: tweakManager) - var canShowGreenView: Bool + var isTapGestureToChangeColorEnabled: Bool { + get { tweakManager.tweakWith(feature: Features.general, variable: Variables.tapToChangeColorEnabled)?.boolValue ?? false } + set { tweakManager.set(newValue, feature: Features.general, variable: Variables.tapToChangeColorEnabled) } + } - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.displayRedView, - tweakManager: tweakManager) - var canShowRedView: Bool + var labelText: String { + get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.labelText)?.stringValue ?? "" } + set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.labelText) } + } - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.displayYellowView, - tweakManager: tweakManager) - var canShowYellowView: Bool + var meaningOfLife: Int { + get { tweakManager.tweakWith(feature: Features.general, variable: Variables.answerToTheUniverse)?.intValue ?? 0 } + set { tweakManager.set(newValue, feature: Features.general, variable: Variables.answerToTheUniverse) } + } - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.labelText, - tweakManager: tweakManager) - var labelText: String + var redViewAlpha: Double { + get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.redViewAlphaComponent)?.doubleValue ?? 0.0 } + set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.redViewAlphaComponent) } + } - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.redViewAlphaComponent, - tweakManager: tweakManager) - var redViewAlpha: Double + var shouldShowAlert: Bool { + get { tweakManager.tweakWith(feature: Features.general, variable: Variables.greetOnAppDidBecomeActive)?.boolValue ?? false } + set { tweakManager.set(newValue, feature: Features.general, variable: Variables.greetOnAppDidBecomeActive) } + } } \ No newline at end of file diff --git a/Example/JustTweak/Code/AppDelegate.swift b/Example/JustTweak/Code/AppDelegate.swift index 154f139..d678a25 100644 --- a/Example/JustTweak/Code/AppDelegate.swift +++ b/Example/JustTweak/Code/AppDelegate.swift @@ -10,13 +10,14 @@ import UIKit class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - let tweakAccessor = GeneratedTweakAccessor() + var tweakAccessor: GeneratedTweakAccessor! func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { let navigationController = window?.rootViewController as! UINavigationController let viewController = navigationController.topViewController as! ViewController + tweakAccessor = GeneratedTweakAccessor(with: makeTweakManager()) viewController.tweakAccessor = tweakAccessor - viewController.tweakManager = TweakAccessor.tweakManager + viewController.tweakManager = tweakAccessor.tweakManager return true } @@ -29,4 +30,36 @@ class AppDelegate: UIResponder, UIApplicationDelegate { window?.rootViewController?.present(alertController, animated: true, completion: nil) } } + + func makeTweakManager() -> TweakManager { + var tweakProviders: [TweakProvider] = [] + + // EphemeralTweakProvider + #if DEBUG || CONFIGURATION_UI_TESTS + let ephemeralTweakProvider_1 = NSMutableDictionary() + tweakProviders.append(ephemeralTweakProvider_1) + #endif + + // UserDefaultsTweakProvider + #if DEBUG || CONFIGURATION_DEBUG + let userDefaultsTweakProvider_1 = UserDefaultsTweakProvider(userDefaults: UserDefaults.standard) + tweakProviders.append(userDefaultsTweakProvider_1) + #endif + + // LocalTweakProvider + #if DEBUG + let jsonFileURL_1 = Bundle.main.url(forResource: "LocalTweaks_TopPriority_example", withExtension: "json")! + let localTweakProvider_1 = LocalTweakProvider(jsonURL: jsonFileURL_1) + tweakProviders.append(localTweakProvider_1) + #endif + + // LocalTweakProvider + let jsonFileURL_2 = Bundle.main.url(forResource: "LocalTweaks_example", withExtension: "json")! + let localTweakProvider_2 = LocalTweakProvider(jsonURL: jsonFileURL_2) + tweakProviders.append(localTweakProvider_2) + + let tweakManager = TweakManager(tweakProviders: tweakProviders) + tweakManager.useCache = true + return tweakManager + } } diff --git a/Example/JustTweak/CodeGeneration/config.json b/Example/JustTweak/CodeGeneration/config.json index a56235a..8498651 100644 --- a/Example/JustTweak/CodeGeneration/config.json +++ b/Example/JustTweak/CodeGeneration/config.json @@ -1,25 +1,3 @@ { - "tweakProviders": [ - { - "type": "EphemeralTweakProvider", - "macros": ["DEBUG", "CONFIGURATION_UI_TESTS"] - }, - { - "type": "UserDefaultsTweakProvider", - "parameter": "UserDefaults.standard", - "macros": ["DEBUG", "CONFIGURATION_DEBUG"] - }, - { - "type": "LocalTweakProvider", - "parameter": "LocalTweaks_TopPriority_example", - "macros": ["DEBUG"] - }, - { - "type": "LocalTweakProvider", - "parameter": "LocalTweaks_example" - } - ], - "shouldCacheTweaks": true, - "usePropertyWrappers": true, "accessorName": "GeneratedTweakAccessor" } diff --git a/JustTweak/Assets/TweakAccessorGenerator.bundle/TweakAccessorGenerator b/JustTweak/Assets/TweakAccessorGenerator.bundle/TweakAccessorGenerator index 2f19c4e..7de7e71 100755 Binary files a/JustTweak/Assets/TweakAccessorGenerator.bundle/TweakAccessorGenerator and b/JustTweak/Assets/TweakAccessorGenerator.bundle/TweakAccessorGenerator differ diff --git a/README.md b/README.md index 8592c3d..86c7ef3 100644 --- a/README.md +++ b/README.md @@ -77,70 +77,11 @@ static let tweakManager: TweakManager = { ```json { - "tweakProviders": [ - { - "type": "EphemeralTweakProvider", - "macros": ["DEBUG", "CONFIGURATION_UI_TESTS"] - }, - { - "type": "UserDefaultsTweakProvider", - "parameter": "UserDefaults.standard", - "macros": ["DEBUG", "CONFIGURATION_DEBUG"] - }, - { - "type": "LocalTweakProvider", - "parameter": "LocalTweaks_TopPriority_example", - "macros": ["DEBUG"] - }, - { - "type": "LocalTweakProvider", - "parameter": "LocalTweaks_example" - } - ], - "shouldCacheTweaks": true, - "usePropertyWrappers": true, "accessorName": "GeneratedTweakAccessor" } ``` -Supported tweak provider types are: - -- `EphemeralTweakProvider` -- `UserDefaultsTweakProvider` -- `LocalTweakProvider` -- `CustomTweakProvider` - -The content of the `parameter` value depends on the type: -- `EphemeralTweakProvider`: is not needed -- `UserDefaultsTweakProvider`: should specify the `UserDefaults` instance to be used -- `LocalTweakProvider`: should specify the filename of the json file containing the tweaks -- `CustomTweakProvider`: should specify the filename of a file containing the setup code needed to instantiate and add your custom tweak provider. - -``` -...json -{ - "type": "CustomTweakProvider", - "parameter": "FirebaseTweakProviderSetupCode", - "macros": ["CONFIGURATION_APPSTORE"] -}, -... -``` - -Example content from `FirebaseTweakProviderSetupCode`. Store any CustomTweakProvider setup code file in the same folder of `config.json` and mind not to add them in any target in Xcode. - -```swift -let firebaseTweakProvider = FirebaseTweakProvider() -firebaseTweakProvider.someValue = true -tweakProviders.append(firebaseTweakProvider) -``` - -It's important to include the `tweakProviders.append(<#property_name#>)` statement at the end of your code block that will be included in the generated code. - -Other supported configuration: - -`shouldCacheTweaks`: enables/disable the JustTweak cache (see [Caching notes](#caching-notes)). -`usePropertyWrappers`: property wrappers are definitely one of the most exciting new features in Swift 5.1. In order to be used for the stack, they need a single instance of `TweakManager`. If this is not a possible approach for you codebase, you can set this value to `false` to allow the generation of code that doesn't rely on a `static let`. -`accessorName`: the name of the generated class. +the only currently supported value is `accessorName` that defines the name of the generated class. - Add the following to your `Podfile` @@ -164,7 +105,7 @@ Every time the target is built, the code generator tool will regenerate the code If you have used the code generator tool, the generated stack includes all the feature flags. Simply allocate the accessor object (which name you have defined in the `.json` configuration and use it to access the feature flags. ```swift -let accessor = GeneratedTweakAccessor() +let accessor = GeneratedTweakAccessor(with: <#tweak_manager_instance#>) if accessor.meaningOfLife == 42 { ... } diff --git a/TweakAccessorGenerator/TweakAccessorGenerator.xcodeproj/project.pbxproj b/TweakAccessorGenerator/TweakAccessorGenerator.xcodeproj/project.pbxproj index 80da1b7..5a256cf 100644 --- a/TweakAccessorGenerator/TweakAccessorGenerator.xcodeproj/project.pbxproj +++ b/TweakAccessorGenerator/TweakAccessorGenerator.xcodeproj/project.pbxproj @@ -12,10 +12,7 @@ 12273D382625E45F00732559 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 12273D372625E45F00732559 /* ArgumentParser */; }; 12BE964D2626FA5000C1B6C3 /* TweakAccessorCodeGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12BE964C2626FA5000C1B6C3 /* TweakAccessorCodeGeneratorTests.swift */; }; 12BE987A2627243D00C1B6C3 /* Tweaks.json in Resources */ = {isa = PBXBuildFile; fileRef = 12BE98792627243D00C1B6C3 /* Tweaks.json */; }; - 4F3F85E426400B6D00A7B8B8 /* GeneratedTweakAccessorContent_NoPropertyWrappers in Resources */ = {isa = PBXBuildFile; fileRef = 4F3F85E226400B6D00A7B8B8 /* GeneratedTweakAccessorContent_NoPropertyWrappers */; }; - 4F3F85E526400B6E00A7B8B8 /* GeneratedTweakAccessorContent_PropertyWrappers in Resources */ = {isa = PBXBuildFile; fileRef = 4F3F85E326400B6D00A7B8B8 /* GeneratedTweakAccessorContent_PropertyWrappers */; }; - 4F5B53E22632DD6100513C18 /* OptimizelyTweakProviderSetupCode in Resources */ = {isa = PBXBuildFile; fileRef = 4F5B53E02632DD6100513C18 /* OptimizelyTweakProviderSetupCode */; }; - 4F5B53E32632DD6100513C18 /* FirebaseTweakProviderSetupCode in Resources */ = {isa = PBXBuildFile; fileRef = 4F5B53E12632DD6100513C18 /* FirebaseTweakProviderSetupCode */; }; + 4F3F85E426400B6D00A7B8B8 /* GeneratedTweakAccessorContent in Resources */ = {isa = PBXBuildFile; fileRef = 4F3F85E226400B6D00A7B8B8 /* GeneratedTweakAccessorContent */; }; 4F65E88B2629CF8C009E8C3B /* ValidTweaks_TopPriority.json in Resources */ = {isa = PBXBuildFile; fileRef = 4F65E8892629CF8C009E8C3B /* ValidTweaks_TopPriority.json */; }; 4F65E88C2629CF8C009E8C3B /* ValidTweaks_LowPriority.json in Resources */ = {isa = PBXBuildFile; fileRef = 4F65E88A2629CF8C009E8C3B /* ValidTweaks_LowPriority.json */; }; 4F7750762627338700A0A3F5 /* TweakValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F7750732627338700A0A3F5 /* TweakValue.swift */; }; @@ -63,13 +60,8 @@ 12BE964C2626FA5000C1B6C3 /* TweakAccessorCodeGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TweakAccessorCodeGeneratorTests.swift; sourceTree = ""; }; 12BE964E2626FA5000C1B6C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 12BE98792627243D00C1B6C3 /* Tweaks.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Tweaks.json; sourceTree = ""; }; - 4F3F85E226400B6D00A7B8B8 /* GeneratedTweakAccessorContent_NoPropertyWrappers */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GeneratedTweakAccessorContent_NoPropertyWrappers; sourceTree = ""; }; - 4F3F85E326400B6D00A7B8B8 /* GeneratedTweakAccessorContent_PropertyWrappers */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GeneratedTweakAccessorContent_PropertyWrappers; sourceTree = ""; }; - 4F5B53E02632DD6100513C18 /* OptimizelyTweakProviderSetupCode */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = OptimizelyTweakProviderSetupCode; sourceTree = ""; }; - 4F5B53E12632DD6100513C18 /* FirebaseTweakProviderSetupCode */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = FirebaseTweakProviderSetupCode; sourceTree = ""; }; - 4F5B54AF263413BE00513C18 /* OptimizelyTweakProviderSetupCode */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = OptimizelyTweakProviderSetupCode; sourceTree = ""; }; + 4F3F85E226400B6D00A7B8B8 /* GeneratedTweakAccessorContent */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GeneratedTweakAccessorContent; sourceTree = ""; }; 4F5B54B0263413BE00513C18 /* config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = config.json; sourceTree = ""; }; - 4F5B54B1263413BE00513C18 /* FirebaseTweakProviderSetupCode */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = FirebaseTweakProviderSetupCode; sourceTree = ""; }; 4F5B54B3263413BE00513C18 /* config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = config.json; sourceTree = ""; }; 4F65E8892629CF8C009E8C3B /* ValidTweaks_TopPriority.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ValidTweaks_TopPriority.json; sourceTree = ""; }; 4F65E88A2629CF8C009E8C3B /* ValidTweaks_LowPriority.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ValidTweaks_LowPriority.json; sourceTree = ""; }; @@ -151,9 +143,7 @@ 4F5B54AE263413BE00513C18 /* TestConfiguration2 */ = { isa = PBXGroup; children = ( - 4F5B54AF263413BE00513C18 /* OptimizelyTweakProviderSetupCode */, 4F5B54B0263413BE00513C18 /* config.json */, - 4F5B54B1263413BE00513C18 /* FirebaseTweakProviderSetupCode */, ); path = TestConfiguration2; sourceTree = ""; @@ -191,8 +181,6 @@ 4F7750A82627602200A0A3F5 /* Assets */ = { isa = PBXGroup; children = ( - 4F5B53E12632DD6100513C18 /* FirebaseTweakProviderSetupCode */, - 4F5B53E02632DD6100513C18 /* OptimizelyTweakProviderSetupCode */, 4FD526F726283EBB000F6780 /* InvalidTweaks_DuplicateGeneratedPropertyName.json */, 4FD526FD26283F91000F6780 /* InvalidTweaks_InvalidJSON.json */, 4F7750C026277B6300A0A3F5 /* InvalidTweaks_MissingValues.json */, @@ -200,8 +188,7 @@ 4F65E88A2629CF8C009E8C3B /* ValidTweaks_LowPriority.json */, 4F65E8892629CF8C009E8C3B /* ValidTweaks_TopPriority.json */, 120B0A1D26285CE70066F2C2 /* GeneratedTweakAccessor+ConstantsContent */, - 4F3F85E226400B6D00A7B8B8 /* GeneratedTweakAccessorContent_NoPropertyWrappers */, - 4F3F85E326400B6D00A7B8B8 /* GeneratedTweakAccessorContent_PropertyWrappers */, + 4F3F85E226400B6D00A7B8B8 /* GeneratedTweakAccessorContent */, ); path = Assets; sourceTree = ""; @@ -311,17 +298,14 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4F5B53E32632DD6100513C18 /* FirebaseTweakProviderSetupCode in Resources */, 120B0A1E26285CE70066F2C2 /* GeneratedTweakAccessor+ConstantsContent in Resources */, 4FD526FE26283F91000F6780 /* InvalidTweaks_InvalidJSON.json in Resources */, 4FD526F826283EBB000F6780 /* InvalidTweaks_DuplicateGeneratedPropertyName.json in Resources */, 4F7750C126277B6300A0A3F5 /* InvalidTweaks_MissingValues.json in Resources */, - 4F5B53E22632DD6100513C18 /* OptimizelyTweakProviderSetupCode in Resources */, - 4F3F85E426400B6D00A7B8B8 /* GeneratedTweakAccessorContent_NoPropertyWrappers in Resources */, + 4F3F85E426400B6D00A7B8B8 /* GeneratedTweakAccessorContent in Resources */, 12BE987A2627243D00C1B6C3 /* Tweaks.json in Resources */, 4F65E88C2629CF8C009E8C3B /* ValidTweaks_LowPriority.json in Resources */, 4F65E88B2629CF8C009E8C3B /* ValidTweaks_TopPriority.json in Resources */, - 4F3F85E526400B6E00A7B8B8 /* GeneratedTweakAccessorContent_PropertyWrappers in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration1/config.json b/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration1/config.json index a56235a..8498651 100644 --- a/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration1/config.json +++ b/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration1/config.json @@ -1,25 +1,3 @@ { - "tweakProviders": [ - { - "type": "EphemeralTweakProvider", - "macros": ["DEBUG", "CONFIGURATION_UI_TESTS"] - }, - { - "type": "UserDefaultsTweakProvider", - "parameter": "UserDefaults.standard", - "macros": ["DEBUG", "CONFIGURATION_DEBUG"] - }, - { - "type": "LocalTweakProvider", - "parameter": "LocalTweaks_TopPriority_example", - "macros": ["DEBUG"] - }, - { - "type": "LocalTweakProvider", - "parameter": "LocalTweaks_example" - } - ], - "shouldCacheTweaks": true, - "usePropertyWrappers": true, "accessorName": "GeneratedTweakAccessor" } diff --git a/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/FirebaseTweakProviderSetupCode b/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/FirebaseTweakProviderSetupCode deleted file mode 100644 index 19b150c..0000000 --- a/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/FirebaseTweakProviderSetupCode +++ /dev/null @@ -1,3 +0,0 @@ -let fc = FirebaseTweakProvider() -fc.someValue = true -tweakProviders.append(fc) diff --git a/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/OptimizelyTweakProviderSetupCode b/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/OptimizelyTweakProviderSetupCode deleted file mode 100644 index 209ec24..0000000 --- a/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/OptimizelyTweakProviderSetupCode +++ /dev/null @@ -1,3 +0,0 @@ -let optimizelyTweakProvider = OptimizelyTweakProvider() -optimizelyTweakProvider.someValue = 42 -tweakProviders.append(optimizelyTweakProvider) diff --git a/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/config.json b/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/config.json index 9682f7c..8498651 100644 --- a/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/config.json +++ b/TweakAccessorGenerator/TweakAccessorGenerator/Assets/TestConfiguration2/config.json @@ -1,35 +1,3 @@ { - "tweakProviders": [ - { - "type": "EphemeralTweakProvider", - "macros": ["DEBUG", "CONFIGURATION_UI_TESTS"] - }, - { - "type": "UserDefaultsTweakProvider", - "parameter": "UserDefaults.standard", - "macros": ["DEBUG", "CONFIGURATION_DEBUG"] - }, - { - "type": "CustomTweakProvider", - "parameter": "OptimizelyTweakProviderSetupCode", - "macros": ["CONFIGURATION_APPSTORE"] - }, - { - "type": "CustomTweakProvider", - "parameter": "FirebaseTweakProviderSetupCode", - "macros": ["CONFIGURATION_APPSTORE"] - }, - { - "type": "LocalTweakProvider", - "parameter": "LocalTweaks_TopPriority_example", - "macros": ["DEBUG"] - }, - { - "type": "LocalTweakProvider", - "parameter": "LocalTweaks_example" - } - ], - "shouldCacheTweaks": true, - "usePropertyWrappers": true, "accessorName": "GeneratedTweakAccessor" } diff --git a/TweakAccessorGenerator/TweakAccessorGenerator/Core/Models.swift b/TweakAccessorGenerator/TweakAccessorGenerator/Core/Models.swift index a1006fc..4016de6 100644 --- a/TweakAccessorGenerator/TweakAccessorGenerator/Core/Models.swift +++ b/TweakAccessorGenerator/TweakAccessorGenerator/Core/Models.swift @@ -16,14 +16,5 @@ struct Tweak: Equatable { } struct Configuration: Decodable { - let tweakProviders: [TweakProvider] - let shouldCacheTweaks: Bool - let usePropertyWrappers: Bool let accessorName: String } - -struct TweakProvider: Decodable { - let type: String - let parameter: String? - let macros: [String]? -} diff --git a/TweakAccessorGenerator/TweakAccessorGenerator/Core/TweakAccessorCodeGenerator.swift b/TweakAccessorGenerator/TweakAccessorGenerator/Core/TweakAccessorCodeGenerator.swift index f6b1d71..c0b7a3e 100644 --- a/TweakAccessorGenerator/TweakAccessorGenerator/Core/TweakAccessorCodeGenerator.swift +++ b/TweakAccessorGenerator/TweakAccessorGenerator/Core/TweakAccessorCodeGenerator.swift @@ -33,10 +33,9 @@ extension TweakAccessorCodeGenerator { func generateAccessorFileContent(tweaksFilename: String, tweaks: [Tweak], - configuration: Configuration, - customTweakProvidersSetupCode: [Filename: CodeBlock]) -> String { + configuration: Configuration) -> String { let template = self.accessorTemplate(with: configuration.accessorName) - let tweakManager = self.tweakManagerCodeBlock(with: configuration, customTweakProvidersSetupCode: customTweakProvidersSetupCode) + let tweakManager = self.tweakManagerCodeBlock() let classContent = self.classContent(with: tweaks, configuration: configuration) let content = template @@ -117,139 +116,20 @@ extension TweakAccessorCodeGenerator { """ } - private func tweakManagerCodeBlock(with configuration: Configuration, - customTweakProvidersSetupCode: [Filename: CodeBlock]) -> String { - let tweakProvidersCodeBlock = self.tweakProvidersCodeBlock(with: configuration, - customTweakProvidersSetupCode: customTweakProvidersSetupCode) - - if configuration.usePropertyWrappers { - return """ - static let tweakManager: TweakManager = { - \(tweakProvidersCodeBlock) - let tweakManager = TweakManager(tweakProviders: tweakProviders) - tweakManager.useCache = \(configuration.shouldCacheTweaks) - return tweakManager - }() - - var tweakManager: TweakManager { - return Self.tweakManager - } - """ - } - else { - return """ - lazy var tweakManager: TweakManager = { - \(tweakProvidersCodeBlock) - let tweakManager = TweakManager(tweakProviders: tweakProviders) - tweakManager.useCache = \(configuration.shouldCacheTweaks) - return tweakManager - }() - """ - } - } - - private func tweakProvidersCodeBlock(with configuration: Configuration, - customTweakProvidersSetupCode: [Filename: CodeBlock]) -> String { - let grouping = Dictionary(grouping: configuration.tweakProviders) { $0.type } - - var tweakProvidersString: [String] = [ - """ - var tweakProviders: [TweakProvider] = []\n - """ - ] - - var currentIndexByConf: [String: Int] = grouping.mapValues{ _ in 0 } - - for tweakProvider in configuration.tweakProviders { - let value = grouping[tweakProvider.type]! - let index = currentIndexByConf[tweakProvider.type]! - let tweakProvider = value[index] - let tweakProviderName = "\(tweakProvider.type.lowercasedFirstChar())_\(index+1)" - var generatedString: [String] = [] - let macros = tweakProvider.macros?.joined(separator: " || ") - - let jsonFileURL = "jsonFileURL_\(index+1)" - let headerComment = """ - // \(tweakProvider.type) - """ - generatedString.append(headerComment) - - if macros != nil { - let macroStarting = """ - #if \(macros!) - """ - generatedString.append(macroStarting) - } - - switch tweakProvider.type { - case "EphemeralTweakProvider": - let tweakProviderAllocation = - """ - let \(tweakProviderName) = NSMutableDictionary() - tweakProviders.append(\(tweakProviderName)) - """ - generatedString.append(tweakProviderAllocation) + private func tweakManagerCodeBlock() -> String { + """ + private(set) var tweakManager: TweakManager - case "UserDefaultsTweakProvider": - assert(tweakProvider.parameter != nil, "Missing value 'parameter' for TweakProvider '\(tweakProvider)'") - let tweakProviderAllocation = - """ - let \(tweakProviderName) = \(tweakProvider.type)(userDefaults: \(tweakProvider.parameter!)) - tweakProviders.append(\(tweakProviderName)) - """ - generatedString.append(tweakProviderAllocation) - - case "LocalTweakProvider": - assert(tweakProvider.parameter != nil, "Missing value 'parameter' for TweakProvider '\(tweakProvider)'") - let tweakProviderAllocation = - """ - let \(jsonFileURL) = Bundle.main.url(forResource: \"\(tweakProvider.parameter!)\", withExtension: "json")! - let \(tweakProviderName) = \(tweakProvider.type)(jsonURL: \(jsonFileURL)) - tweakProviders.append(\(tweakProviderName)) - """ - generatedString.append(tweakProviderAllocation) - - case "CustomTweakProvider": - assert(tweakProvider.parameter != nil, "Missing value 'parameter' for TweakProvider '\(tweakProvider)'") - let setupCode = customTweakProvidersSetupCode[tweakProvider.parameter!]! - let formattedSetupCode = formatCustomTweakProviderSetupCode(setupCode) - let tweakProviderAllocation = - """ - \(formattedSetupCode.trimmingCharacters(in: .newlines)) - """ - generatedString.append(tweakProviderAllocation) - - default: - assertionFailure("Unsupported TweakProvider \(tweakProvider)") - break - } - - if macros != nil { - let macroClosing = """ - #endif - """ - generatedString.append(macroClosing) + init(with tweakManager: TweakManager) { + self.tweakManager = tweakManager } - generatedString.append("") - - tweakProvidersString.append(contentsOf: generatedString) - currentIndexByConf[tweakProvider.type] = currentIndexByConf[tweakProvider.type]! + 1 - } - - return tweakProvidersString.joined(separator: "\n") + """ } private func classContent(with tweaks: [Tweak], configuration: Configuration) -> String { var content: Set = [] - if configuration.usePropertyWrappers { - tweaks.forEach { - content.insert(tweakPropertyWrapper(for: $0)) - } - } - else { - tweaks.forEach { - content.insert(tweakComputedProperty(for: $0)) - } + tweaks.forEach { + content.insert(tweakComputedProperty(for: $0)) } return content.sorted().joined(separator: "\n\n") } diff --git a/TweakAccessorGenerator/TweakAccessorGenerator/Core/Types.swift b/TweakAccessorGenerator/TweakAccessorGenerator/Core/Types.swift index 19f1490..f9cdca5 100644 --- a/TweakAccessorGenerator/TweakAccessorGenerator/Core/Types.swift +++ b/TweakAccessorGenerator/TweakAccessorGenerator/Core/Types.swift @@ -5,8 +5,6 @@ import Foundation -typealias Filename = String -typealias CodeBlock = String typealias TweaksFormat = [FeatureKey: FeatureFormat] typealias FeatureFormat = [VariableKey: TweakFormat] typealias TweakFormat = [String: Any] diff --git a/TweakAccessorGenerator/TweakAccessorGenerator/main.swift b/TweakAccessorGenerator/TweakAccessorGenerator/main.swift index d8ad21e..5604b72 100644 --- a/TweakAccessorGenerator/TweakAccessorGenerator/main.swift +++ b/TweakAccessorGenerator/TweakAccessorGenerator/main.swift @@ -33,20 +33,6 @@ struct TweakAccessorGenerator: ParsableCommand { return decodedResult } - private func loadCustomTweakProvidersCode() -> [Filename: CodeBlock] { - let configuration = loadConfigurationFromJson() - let customTweakProviders = configuration.tweakProviders.filter { $0.type == "CustomTweakProvider" } // costantise - let filenameReferences = customTweakProviders.map { $0.parameter! } - - var customTweakProvidersCode: [Filename: CodeBlock] = [:] - for reference in filenameReferences { - let configurationUrl = configurationFolderURL.appendingPathComponent(reference) - let content = try! String(contentsOf: configurationUrl) - customTweakProvidersCode[reference] = content - } - return customTweakProvidersCode - } - func run() throws { let codeGenerator = TweakAccessorCodeGenerator() let tweakLoader = TweakLoader() @@ -82,13 +68,11 @@ extension TweakAccessorGenerator { tweaks: [Tweak], outputFolder: String, configuration: Configuration) { - let customTweakProvidersSetupCode = loadCustomTweakProvidersCode() let fileName = "\(configuration.accessorName).swift" let url: URL = URL(fileURLWithPath: outputFolder).appendingPathComponent(fileName) let constants = codeGenerator.generateAccessorFileContent(tweaksFilename: tweaksFilename, tweaks: tweaks, - configuration: configuration, - customTweakProvidersSetupCode: customTweakProvidersSetupCode) + configuration: configuration) try! constants.write(to: url, atomically: true, encoding: .utf8) } } diff --git a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/FirebaseTweakProviderSetupCode b/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/FirebaseTweakProviderSetupCode deleted file mode 100644 index dd591d0..0000000 --- a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/FirebaseTweakProviderSetupCode +++ /dev/null @@ -1,3 +0,0 @@ -let firebaseTweakProvider = FirebaseTweakProvider() -firebaseTweakProvider.someValue = true -tweakProviders.append(firebaseTweakProvider) diff --git a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/GeneratedTweakAccessorContent_NoPropertyWrappers b/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/GeneratedTweakAccessorContent similarity index 58% rename from TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/GeneratedTweakAccessorContent_NoPropertyWrappers rename to TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/GeneratedTweakAccessorContent index 4c5a57d..184b2c6 100644 --- a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/GeneratedTweakAccessorContent_NoPropertyWrappers +++ b/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/GeneratedTweakAccessorContent @@ -8,51 +8,11 @@ import JustTweak class GeneratedTweakAccessorContent { - lazy var tweakManager: TweakManager = { - var tweakProviders: [TweakProvider] = [] + let tweakManager: TweakManager - // EphemeralTweakProvider - #if DEBUG || CONFIGURATION_UI_TESTS - let ephemeralTweakProvider_1 = NSMutableDictionary() - tweakProviders.append(ephemeralTweakProvider_1) - #endif - - // UserDefaultsTweakProvider - #if DEBUG || CONFIGURATION_DEBUG - let userDefaultsTweakProvider_1 = UserDefaultsTweakProvider(userDefaults: UserDefaults.standard) - tweakProviders.append(userDefaultsTweakProvider_1) - #endif - - // CustomTweakProvider - #if CONFIGURATION_APPSTORE - let optimizelyTweakProvider = OptimizelyTweakProvider() - optimizelyTweakProvider.someValue = 42 - tweakProviders.append(optimizelyTweakProvider) - #endif - - // CustomTweakProvider - #if CONFIGURATION_APPSTORE - let firebaseTweakProvider = FirebaseTweakProvider() - firebaseTweakProvider.someValue = true - tweakProviders.append(firebaseTweakProvider) - #endif - - // LocalTweakProvider - #if DEBUG - let jsonFileURL_1 = Bundle.main.url(forResource: "ValidTweaks_TopPriority", withExtension: "json")! - let localTweakProvider_1 = LocalTweakProvider(jsonURL: jsonFileURL_1) - tweakProviders.append(localTweakProvider_1) - #endif - - // LocalTweakProvider - let jsonFileURL_2 = Bundle.main.url(forResource: "ValidTweaks_LowPriority", withExtension: "json")! - let localTweakProvider_2 = LocalTweakProvider(jsonURL: jsonFileURL_2) - tweakProviders.append(localTweakProvider_2) - - let tweakManager = TweakManager(tweakProviders: tweakProviders) - tweakManager.useCache = true - return tweakManager - }() + init(with tweakManager: TweakManager) { + self.tweakManager = tweakManager + } var canShowGreenView: Bool { get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayGreenView)?.boolValue ?? false } diff --git a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/GeneratedTweakAccessorContent_PropertyWrappers b/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/GeneratedTweakAccessorContent_PropertyWrappers deleted file mode 100644 index ff848ec..0000000 --- a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/GeneratedTweakAccessorContent_PropertyWrappers +++ /dev/null @@ -1,101 +0,0 @@ -// -// GeneratedTweakAccessorContent.swift -// Generated by TweakAccessorGenerator -// - -import Foundation -import JustTweak - -class GeneratedTweakAccessorContent { - - static let tweakManager: TweakManager = { - var tweakProviders: [TweakProvider] = [] - - // EphemeralTweakProvider - #if DEBUG || CONFIGURATION_UI_TESTS - let ephemeralTweakProvider_1 = NSMutableDictionary() - tweakProviders.append(ephemeralTweakProvider_1) - #endif - - // UserDefaultsTweakProvider - #if DEBUG || CONFIGURATION_DEBUG - let userDefaultsTweakProvider_1 = UserDefaultsTweakProvider(userDefaults: UserDefaults.standard) - tweakProviders.append(userDefaultsTweakProvider_1) - #endif - - // CustomTweakProvider - #if CONFIGURATION_APPSTORE - let optimizelyTweakProvider = OptimizelyTweakProvider() - optimizelyTweakProvider.someValue = 42 - tweakProviders.append(optimizelyTweakProvider) - #endif - - // CustomTweakProvider - #if CONFIGURATION_APPSTORE - let firebaseTweakProvider = FirebaseTweakProvider() - firebaseTweakProvider.someValue = true - tweakProviders.append(firebaseTweakProvider) - #endif - - // LocalTweakProvider - #if DEBUG - let jsonFileURL_1 = Bundle.main.url(forResource: "ValidTweaks_TopPriority", withExtension: "json")! - let localTweakProvider_1 = LocalTweakProvider(jsonURL: jsonFileURL_1) - tweakProviders.append(localTweakProvider_1) - #endif - - // LocalTweakProvider - let jsonFileURL_2 = Bundle.main.url(forResource: "ValidTweaks_LowPriority", withExtension: "json")! - let localTweakProvider_2 = LocalTweakProvider(jsonURL: jsonFileURL_2) - tweakProviders.append(localTweakProvider_2) - - let tweakManager = TweakManager(tweakProviders: tweakProviders) - tweakManager.useCache = true - return tweakManager - }() - - var tweakManager: TweakManager { - return Self.tweakManager - } - - @TweakProperty(feature: Features.general, - variable: Variables.answerToTheUniverse, - tweakManager: tweakManager) - var meaningOfLife: Int - - @TweakProperty(feature: Features.general, - variable: Variables.greetOnAppDidBecomeActive, - tweakManager: tweakManager) - var shouldShowAlert: Bool - - @TweakProperty(feature: Features.general, - variable: Variables.tapToChangeColorEnabled, - tweakManager: tweakManager) - var isTapGestureToChangeColorEnabled: Bool - - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.displayGreenView, - tweakManager: tweakManager) - var canShowGreenView: Bool - - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.displayRedView, - tweakManager: tweakManager) - var canShowRedView: Bool - - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.displayYellowView, - tweakManager: tweakManager) - var canShowYellowView: Bool - - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.labelText, - tweakManager: tweakManager) - var labelText: String - - @TweakProperty(feature: Features.uiCustomization, - variable: Variables.redViewAlphaComponent, - tweakManager: tweakManager) - var redViewAlpha: Double -} - diff --git a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/OptimizelyTweakProviderSetupCode b/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/OptimizelyTweakProviderSetupCode deleted file mode 100644 index 209ec24..0000000 --- a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Assets/OptimizelyTweakProviderSetupCode +++ /dev/null @@ -1,3 +0,0 @@ -let optimizelyTweakProvider = OptimizelyTweakProvider() -optimizelyTweakProvider.someValue = 42 -tweakProviders.append(optimizelyTweakProvider) diff --git a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Suites/TweakAccessorCodeGeneratorTests.swift b/TweakAccessorGenerator/TweakAccessorGeneratorTests/Suites/TweakAccessorCodeGeneratorTests.swift index 2a34950..fd524e6 100644 --- a/TweakAccessorGenerator/TweakAccessorGeneratorTests/Suites/TweakAccessorCodeGeneratorTests.swift +++ b/TweakAccessorGenerator/TweakAccessorGeneratorTests/Suites/TweakAccessorCodeGeneratorTests.swift @@ -32,91 +32,19 @@ class TweakAccessorCodeGeneratorTests: XCTestCase { } func test_generateConstants_output() throws { - let configuration = Configuration(tweakProviders: [], - shouldCacheTweaks: true, - usePropertyWrappers: true, - accessorName: "GeneratedTweakAccessorContent") + let configuration = Configuration(accessorName: "GeneratedTweakAccessorContent") let content = codeGenerator.generateConstantsFileContent(tweaks: tweaks, configuration: configuration) let testContentPath = bundle.path(forResource: "GeneratedTweakAccessor+ConstantsContent", ofType: "")! let testContent = try String(contentsOfFile: testContentPath, encoding: .utf8).trimmingCharacters(in: .newlines) XCTAssertEqual(content, testContent) } - func test_generateAccessor_PropertyWrappers_output() throws { - let tweakProviders = [ - TweakProvider(type: "EphemeralTweakProvider", - parameter: nil, - macros: ["DEBUG", "CONFIGURATION_UI_TESTS"]), - TweakProvider(type: "UserDefaultsTweakProvider", - parameter: "UserDefaults.standard", - macros: ["DEBUG", "CONFIGURATION_DEBUG"]), - TweakProvider(type: "CustomTweakProvider", - parameter: "OptimizelyTweakProviderSetupCode", - macros: ["CONFIGURATION_APPSTORE"]), - TweakProvider(type: "CustomTweakProvider", - parameter: "FirebaseTweakProviderSetupCode", - macros: ["CONFIGURATION_APPSTORE"]), - TweakProvider(type: "LocalTweakProvider", - parameter: "ValidTweaks_TopPriority", - macros: ["DEBUG"]), - TweakProvider(type: "LocalTweakProvider", - parameter: "ValidTweaks_LowPriority", - macros: nil) - ] - let configuration = Configuration(tweakProviders: tweakProviders, - shouldCacheTweaks: true, - usePropertyWrappers: true, - accessorName: "GeneratedTweakAccessorContent") - let customTweakProvidersSetupCode = [ - "FirebaseTweakProviderSetupCode": codeBlock(for: "FirebaseTweakProviderSetupCode"), - "OptimizelyTweakProviderSetupCode": codeBlock(for: "OptimizelyTweakProviderSetupCode"), - - ] + func test_generateAccessor_output() throws { + let configuration = Configuration(accessorName: "GeneratedTweakAccessorContent") let content = codeGenerator.generateAccessorFileContent(tweaksFilename: tweaksFilename, tweaks: tweaks, - configuration: configuration, - customTweakProvidersSetupCode: customTweakProvidersSetupCode) - let testContentPath = bundle.path(forResource: "GeneratedTweakAccessorContent_PropertyWrappers", ofType: "")! - let testContent = try String(contentsOfFile: testContentPath, encoding: .utf8).trimmingCharacters(in: .newlines) - - XCTAssertEqual(content, testContent) - } - - func test_generateAccessor_NoPropertyWrappers_output() throws { - let tweakProviders = [ - TweakProvider(type: "EphemeralTweakProvider", - parameter: nil, - macros: ["DEBUG", "CONFIGURATION_UI_TESTS"]), - TweakProvider(type: "UserDefaultsTweakProvider", - parameter: "UserDefaults.standard", - macros: ["DEBUG", "CONFIGURATION_DEBUG"]), - TweakProvider(type: "CustomTweakProvider", - parameter: "OptimizelyTweakProviderSetupCode", - macros: ["CONFIGURATION_APPSTORE"]), - TweakProvider(type: "CustomTweakProvider", - parameter: "FirebaseTweakProviderSetupCode", - macros: ["CONFIGURATION_APPSTORE"]), - TweakProvider(type: "LocalTweakProvider", - parameter: "ValidTweaks_TopPriority", - macros: ["DEBUG"]), - TweakProvider(type: "LocalTweakProvider", - parameter: "ValidTweaks_LowPriority", - macros: nil) - ] - let configuration = Configuration(tweakProviders: tweakProviders, - shouldCacheTweaks: true, - usePropertyWrappers: false, - accessorName: "GeneratedTweakAccessorContent") - let customTweakProvidersSetupCode = [ - "FirebaseTweakProviderSetupCode": codeBlock(for: "FirebaseTweakProviderSetupCode"), - "OptimizelyTweakProviderSetupCode": codeBlock(for: "OptimizelyTweakProviderSetupCode"), - - ] - let content = codeGenerator.generateAccessorFileContent(tweaksFilename: tweaksFilename, - tweaks: tweaks, - configuration: configuration, - customTweakProvidersSetupCode: customTweakProvidersSetupCode) - let testContentPath = bundle.path(forResource: "GeneratedTweakAccessorContent_NoPropertyWrappers", ofType: "")! + configuration: configuration) + let testContentPath = bundle.path(forResource: "GeneratedTweakAccessorContent", ofType: "")! let testContent = try String(contentsOfFile: testContentPath, encoding: .utf8).trimmingCharacters(in: .newlines) XCTAssertEqual(content, testContent) diff --git a/_TweakAccessorGenerator b/_TweakAccessorGenerator index 2f19c4e..7de7e71 100755 Binary files a/_TweakAccessorGenerator and b/_TweakAccessorGenerator differ