diff --git a/CHANGELOG.md b/CHANGELOG.md index 20f0153..54bc4e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,9 @@ _None_ ### New Features -_None_ +* Storyboards: Added a new `ignoreTargetModule` parameter if you're using storyboards in multiple targets, to avoid issues with the generated code. + [Julien Quéré](https://github.com/juli1quere) + [#36](https://github.com/SwiftGen/templates/pull/36) ### Internal Changes diff --git a/Documentation/storyboards/swift2.md b/Documentation/storyboards/swift2.md index babe0ea..041fd69 100644 --- a/Documentation/storyboards/swift2.md +++ b/Documentation/storyboards/swift2.md @@ -22,6 +22,7 @@ You can customize some elements of this template by overriding the following par | `sceneEnumName` | `StoryboardScene` | Allows you to change the name of the generated `enum` containing all storyboard scenes. | | `segueEnumName` | `StoryboardSegue` | Allows you to change the name of the generated `enum` containing all storyboard segues. | | `module` | N/A | By default, the template will import the needed modules for custom classes, but won’t import the target’s module to avoid an import warning — using the `PRODUCT_MODULE_NAME` environment variable to detect it. Should you need to ignore an additional module, you can provide it here. | +| `ignoreTargetModule` | N/A | Setting this parameter will disable the behaviour of prefixing classes with their module name for (only) the target module. | ## Generated Code diff --git a/Documentation/storyboards/swift3.md b/Documentation/storyboards/swift3.md index b87a3f8..a359820 100644 --- a/Documentation/storyboards/swift3.md +++ b/Documentation/storyboards/swift3.md @@ -21,6 +21,7 @@ You can customize some elements of this template by overriding the following par | `sceneEnumName` | `StoryboardScene` | Allows you to change the name of the generated `enum` containing all storyboard scenes. | | `segueEnumName` | `StoryboardSegue` | Allows you to change the name of the generated `enum` containing all storyboard segues. | | `module` | N/A | By default, the template will import the needed modules for custom classes, but won’t import the target’s module to avoid an import warning — using the `PRODUCT_MODULE_NAME` environment variable to detect it. Should you need to ignore an additional module, you can provide it here. | +| `ignoreTargetModule` | N/A | Setting this parameter will disable the behaviour of prefixing classes with their module name for (only) the target module. | ## Generated Code diff --git a/Documentation/storyboards/swift4.md b/Documentation/storyboards/swift4.md index 7cf84be..435154d 100644 --- a/Documentation/storyboards/swift4.md +++ b/Documentation/storyboards/swift4.md @@ -21,6 +21,7 @@ You can customize some elements of this template by overriding the following par | `sceneEnumName` | `StoryboardScene` | Allows you to change the name of the generated `enum` containing all storyboard scenes. | | `segueEnumName` | `StoryboardSegue` | Allows you to change the name of the generated `enum` containing all storyboard segues. | | `module` | N/A | By default, the template will import the needed modules for custom classes, but won’t import the target’s module to avoid an import warning — using the `PRODUCT_MODULE_NAME` environment variable to detect it. Should you need to ignore an additional module, you can provide it here. | +| `ignoreTargetModule` | N/A | Setting this parameter will disable the behaviour of prefixing classes with their module name for (only) the target module. | ## Generated Code diff --git a/Fixtures/stub-env/ExtraDefinitions.swift b/Fixtures/stub-env/ExtraDefinitions.swift new file mode 100644 index 0000000..00c07cf --- /dev/null +++ b/Fixtures/stub-env/ExtraDefinitions.swift @@ -0,0 +1,11 @@ +#if os(iOS) + import UIKit + + public class SLKTextViewController: UIViewController { + } +#elseif os(OSX) + import Cocoa + + class DBPrefsWindowController: NSWindowController { + } +#endif diff --git a/Rakefile b/Rakefile index b9b6f02..f17ca3a 100755 --- a/Rakefile +++ b/Rakefile @@ -124,9 +124,15 @@ namespace :output do end sdks = sdks(f) + if f.match('extra-definitions') + definitions = %("#{MODULE_OUTPUT_PATH}/Definitions.swift" "#{MODULE_OUTPUT_PATH}/ExtraDefinitions.swift") + else + definitions = %("#{MODULE_OUTPUT_PATH}/Definitions.swift") + end + commands = sdks.map do |sdk| %(--toolchain #{toolchain[:toolchain]} -sdk #{sdk} swiftc -swift-version #{toolchain[:version]} ) + - %(-typecheck -target #{SDKS[sdk]} -I #{toolchain[:module_path]} "#{MODULE_OUTPUT_PATH}/Definitions.swift" #{f}) + %(-typecheck -target #{SDKS[sdk]} -I #{toolchain[:module_path]} #{definitions} #{f}) end subtask = File.basename(f, '.*') diff --git a/Tests/Expected/Storyboards-iOS/swift2-context-all-ignore-module-need-extra-definitions.swift b/Tests/Expected/Storyboards-iOS/swift2-context-all-ignore-module-need-extra-definitions.swift new file mode 100644 index 0000000..406d7c9 --- /dev/null +++ b/Tests/Expected/Storyboards-iOS/swift2-context-all-ignore-module-need-extra-definitions.swift @@ -0,0 +1,120 @@ +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +// swiftlint:disable sorted_imports +import Foundation +import UIKit +import CustomSegue +import LocationPicker + +// swiftlint:disable file_length + +protocol StoryboardType { + static var storyboardName: String { get } +} + +extension StoryboardType { + static var storyboard: UIStoryboard { + return UIStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) + } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiateViewControllerWithIdentifier(identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") + } + return controller + } +} + +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller + } +} + +protocol SegueType: RawRepresentable { } + +extension UIViewController { + func performSegue(segue: S, sender: AnyObject? = nil) { + performSegueWithIdentifier(segue.rawValue, sender: sender) + } +} + +// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name +enum StoryboardScene { + enum AdditionalImport: StoryboardType { + static let storyboardName = "AdditionalImport" + + static let initialScene = InitialSceneType(AdditionalImport.self) + + static let Public = SceneType(AdditionalImport.self, identifier: "public") + } + enum Anonymous: StoryboardType { + static let storyboardName = "Anonymous" + + static let initialScene = InitialSceneType(Anonymous.self) + } + enum Dependency: StoryboardType { + static let storyboardName = "Dependency" + + static let Dependent = SceneType(Dependency.self, identifier: "Dependent") + } + enum Message: StoryboardType { + static let storyboardName = "Message" + + static let initialScene = InitialSceneType(Message.self) + + static let Composer = SceneType(Message.self, identifier: "Composer") + + static let MessagesList = SceneType(Message.self, identifier: "MessagesList") + + static let NavCtrl = SceneType(Message.self, identifier: "NavCtrl") + + static let URLChooser = SceneType(Message.self, identifier: "URLChooser") + } + enum Placeholder: StoryboardType { + static let storyboardName = "Placeholder" + + static let Navigation = SceneType(Placeholder.self, identifier: "Navigation") + } + enum Wizard: StoryboardType { + static let storyboardName = "Wizard" + + static let initialScene = InitialSceneType(Wizard.self) + + static let AcceptCGU = SceneType(Wizard.self, identifier: "Accept-CGU") + + static let CreateAccount = SceneType(Wizard.self, identifier: "CreateAccount") + + static let Preferences = SceneType(Wizard.self, identifier: "Preferences") + + static let ValidatePassword = SceneType(Wizard.self, identifier: "Validate_Password") + } +} + +enum StoryboardSegue { + enum AdditionalImport: String, SegueType { + case Private = "private" + } + enum Message: String, SegueType { + case CustomBack + case Embed + case NonCustom + case ShowNavCtrl = "Show-NavCtrl" + } + enum Wizard: String, SegueType { + case ShowPassword + } +} +// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name + +private final class BundleToken {} diff --git a/Tests/Expected/Storyboards-iOS/swift3-context-all-ignore-module-need-extra-definitions.swift b/Tests/Expected/Storyboards-iOS/swift3-context-all-ignore-module-need-extra-definitions.swift new file mode 100644 index 0000000..0001d1a --- /dev/null +++ b/Tests/Expected/Storyboards-iOS/swift3-context-all-ignore-module-need-extra-definitions.swift @@ -0,0 +1,120 @@ +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +// swiftlint:disable sorted_imports +import Foundation +import UIKit +import CustomSegue +import LocationPicker + +// swiftlint:disable file_length + +protocol StoryboardType { + static var storyboardName: String { get } +} + +extension StoryboardType { + static var storyboard: UIStoryboard { + return UIStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) + } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + func instantiate() -> T { + guard let controller = storyboard.storyboard.instantiateViewController(withIdentifier: identifier) as? T else { + fatalError("ViewController '\(identifier)' is not of the expected class \(T.self).") + } + return controller + } +} + +struct InitialSceneType { + let storyboard: StoryboardType.Type + + func instantiate() -> T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("ViewController is not of the expected class \(T.self).") + } + return controller + } +} + +protocol SegueType: RawRepresentable { } + +extension UIViewController { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + performSegue(withIdentifier: segue.rawValue, sender: sender) + } +} + +// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name +enum StoryboardScene { + enum AdditionalImport: StoryboardType { + static let storyboardName = "AdditionalImport" + + static let initialScene = InitialSceneType(storyboard: AdditionalImport.self) + + static let `public` = SceneType(storyboard: AdditionalImport.self, identifier: "public") + } + enum Anonymous: StoryboardType { + static let storyboardName = "Anonymous" + + static let initialScene = InitialSceneType(storyboard: Anonymous.self) + } + enum Dependency: StoryboardType { + static let storyboardName = "Dependency" + + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") + } + enum Message: StoryboardType { + static let storyboardName = "Message" + + static let initialScene = InitialSceneType(storyboard: Message.self) + + static let composer = SceneType(storyboard: Message.self, identifier: "Composer") + + static let messagesList = SceneType(storyboard: Message.self, identifier: "MessagesList") + + static let navCtrl = SceneType(storyboard: Message.self, identifier: "NavCtrl") + + static let urlChooser = SceneType(storyboard: Message.self, identifier: "URLChooser") + } + enum Placeholder: StoryboardType { + static let storyboardName = "Placeholder" + + static let navigation = SceneType(storyboard: Placeholder.self, identifier: "Navigation") + } + enum Wizard: StoryboardType { + static let storyboardName = "Wizard" + + static let initialScene = InitialSceneType(storyboard: Wizard.self) + + static let acceptCGU = SceneType(storyboard: Wizard.self, identifier: "Accept-CGU") + + static let createAccount = SceneType(storyboard: Wizard.self, identifier: "CreateAccount") + + static let preferences = SceneType(storyboard: Wizard.self, identifier: "Preferences") + + static let validatePassword = SceneType(storyboard: Wizard.self, identifier: "Validate_Password") + } +} + +enum StoryboardSegue { + enum AdditionalImport: String, SegueType { + case `private` + } + enum Message: String, SegueType { + case customBack = "CustomBack" + case embed = "Embed" + case nonCustom = "NonCustom" + case showNavCtrl = "Show-NavCtrl" + } + enum Wizard: String, SegueType { + case showPassword = "ShowPassword" + } +} +// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name + +private final class BundleToken {} diff --git a/Tests/Expected/Storyboards-iOS/swift4-context-all-ignore-module-need-extra-definitions.swift b/Tests/Expected/Storyboards-iOS/swift4-context-all-ignore-module-need-extra-definitions.swift new file mode 100644 index 0000000..be149b7 --- /dev/null +++ b/Tests/Expected/Storyboards-iOS/swift4-context-all-ignore-module-need-extra-definitions.swift @@ -0,0 +1,123 @@ +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +// swiftlint:disable sorted_imports +import Foundation +import UIKit +import CustomSegue +import LocationPicker + +// swiftlint:disable file_length + +protocol StoryboardType { + static var storyboardName: String { get } +} + +extension StoryboardType { + static var storyboard: UIStoryboard { + let name = self.storyboardName + return UIStoryboard(name: name, bundle: Bundle(for: BundleToken.self)) + } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + func instantiate() -> T { + let identifier = self.identifier + guard let controller = storyboard.storyboard.instantiateViewController(withIdentifier: identifier) as? T else { + fatalError("ViewController '\(identifier)' is not of the expected class \(T.self).") + } + return controller + } +} + +struct InitialSceneType { + let storyboard: StoryboardType.Type + + func instantiate() -> T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("ViewController is not of the expected class \(T.self).") + } + return controller + } +} + +protocol SegueType: RawRepresentable { } + +extension UIViewController { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + let identifier = segue.rawValue + performSegue(withIdentifier: identifier, sender: sender) + } +} + +// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name +enum StoryboardScene { + enum AdditionalImport: StoryboardType { + static let storyboardName = "AdditionalImport" + + static let initialScene = InitialSceneType(storyboard: AdditionalImport.self) + + static let `public` = SceneType(storyboard: AdditionalImport.self, identifier: "public") + } + enum Anonymous: StoryboardType { + static let storyboardName = "Anonymous" + + static let initialScene = InitialSceneType(storyboard: Anonymous.self) + } + enum Dependency: StoryboardType { + static let storyboardName = "Dependency" + + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") + } + enum Message: StoryboardType { + static let storyboardName = "Message" + + static let initialScene = InitialSceneType(storyboard: Message.self) + + static let composer = SceneType(storyboard: Message.self, identifier: "Composer") + + static let messagesList = SceneType(storyboard: Message.self, identifier: "MessagesList") + + static let navCtrl = SceneType(storyboard: Message.self, identifier: "NavCtrl") + + static let urlChooser = SceneType(storyboard: Message.self, identifier: "URLChooser") + } + enum Placeholder: StoryboardType { + static let storyboardName = "Placeholder" + + static let navigation = SceneType(storyboard: Placeholder.self, identifier: "Navigation") + } + enum Wizard: StoryboardType { + static let storyboardName = "Wizard" + + static let initialScene = InitialSceneType(storyboard: Wizard.self) + + static let acceptCGU = SceneType(storyboard: Wizard.self, identifier: "Accept-CGU") + + static let createAccount = SceneType(storyboard: Wizard.self, identifier: "CreateAccount") + + static let preferences = SceneType(storyboard: Wizard.self, identifier: "Preferences") + + static let validatePassword = SceneType(storyboard: Wizard.self, identifier: "Validate_Password") + } +} + +enum StoryboardSegue { + enum AdditionalImport: String, SegueType { + case `private` + } + enum Message: String, SegueType { + case customBack = "CustomBack" + case embed = "Embed" + case nonCustom = "NonCustom" + case showNavCtrl = "Show-NavCtrl" + } + enum Wizard: String, SegueType { + case showPassword = "ShowPassword" + } +} +// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name + +private final class BundleToken {} diff --git a/Tests/Expected/Storyboards-macOS/swift2-context-all-ignore-module-need-extra-definitions.swift b/Tests/Expected/Storyboards-macOS/swift2-context-all-ignore-module-need-extra-definitions.swift new file mode 100644 index 0000000..db5a9c5 --- /dev/null +++ b/Tests/Expected/Storyboards-macOS/swift2-context-all-ignore-module-need-extra-definitions.swift @@ -0,0 +1,102 @@ +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +// swiftlint:disable sorted_imports +import Foundation +import Cocoa +import FadeSegue + +// swiftlint:disable file_length + +protocol StoryboardType { + static var storyboardName: String { get } +} + +extension StoryboardType { + static var storyboard: NSStoryboard { + return NSStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) + } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiateControllerWithIdentifier(identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") + } + return controller + } +} + +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller + } +} + +protocol SegueType: RawRepresentable { } + +extension NSSeguePerforming { + func performSegue(segue: S, sender: AnyObject? = nil) { + performSegueWithIdentifier?(segue.rawValue, sender: sender) + } +} + +// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name +enum StoryboardScene { + enum AdditionalImport: StoryboardType { + static let storyboardName = "AdditionalImport" + + static let Private = SceneType(AdditionalImport.self, identifier: "private") + } + enum Anonymous: StoryboardType { + static let storyboardName = "Anonymous" + } + enum Dependency: StoryboardType { + static let storyboardName = "Dependency" + + static let Dependent = SceneType(Dependency.self, identifier: "Dependent") + } + enum Message: StoryboardType { + static let storyboardName = "Message" + + static let MessageDetails = SceneType(Message.self, identifier: "MessageDetails") + + static let MessageList = SceneType(Message.self, identifier: "MessageList") + + static let MessageListFooter = SceneType(Message.self, identifier: "MessageListFooter") + + static let MessagesTab = SceneType(Message.self, identifier: "MessagesTab") + + static let SplitMessages = SceneType(Message.self, identifier: "SplitMessages") + + static let WindowCtrl = SceneType(Message.self, identifier: "WindowCtrl") + } + enum Placeholder: StoryboardType { + static let storyboardName = "Placeholder" + + static let Dependent = SceneType(Placeholder.self, identifier: "Dependent") + + static let Window = SceneType(Placeholder.self, identifier: "Window") + } +} + +enum StoryboardSegue { + enum Message: String, SegueType { + case Embed + case Modal + case Popover + case Sheet + case Show + case Public = "public" + } +} +// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name + +private final class BundleToken {} diff --git a/Tests/Expected/Storyboards-macOS/swift3-context-all-ignore-module-need-extra-definitions.swift b/Tests/Expected/Storyboards-macOS/swift3-context-all-ignore-module-need-extra-definitions.swift new file mode 100644 index 0000000..cb35cbd --- /dev/null +++ b/Tests/Expected/Storyboards-macOS/swift3-context-all-ignore-module-need-extra-definitions.swift @@ -0,0 +1,102 @@ +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +// swiftlint:disable sorted_imports +import Foundation +import Cocoa +import FadeSegue + +// swiftlint:disable file_length + +protocol StoryboardType { + static var storyboardName: String { get } +} + +extension StoryboardType { + static var storyboard: NSStoryboard { + return NSStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) + } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + func instantiate() -> T { + guard let controller = storyboard.storyboard.instantiateController(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") + } + return controller + } +} + +struct InitialSceneType { + let storyboard: StoryboardType.Type + + func instantiate() -> T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller + } +} + +protocol SegueType: RawRepresentable { } + +extension NSSeguePerforming { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + performSegue?(withIdentifier: segue.rawValue, sender: sender) + } +} + +// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name +enum StoryboardScene { + enum AdditionalImport: StoryboardType { + static let storyboardName = "AdditionalImport" + + static let `private` = SceneType(storyboard: AdditionalImport.self, identifier: "private") + } + enum Anonymous: StoryboardType { + static let storyboardName = "Anonymous" + } + enum Dependency: StoryboardType { + static let storyboardName = "Dependency" + + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") + } + enum Message: StoryboardType { + static let storyboardName = "Message" + + static let messageDetails = SceneType(storyboard: Message.self, identifier: "MessageDetails") + + static let messageList = SceneType(storyboard: Message.self, identifier: "MessageList") + + static let messageListFooter = SceneType(storyboard: Message.self, identifier: "MessageListFooter") + + static let messagesTab = SceneType(storyboard: Message.self, identifier: "MessagesTab") + + static let splitMessages = SceneType(storyboard: Message.self, identifier: "SplitMessages") + + static let windowCtrl = SceneType(storyboard: Message.self, identifier: "WindowCtrl") + } + enum Placeholder: StoryboardType { + static let storyboardName = "Placeholder" + + static let dependent = SceneType(storyboard: Placeholder.self, identifier: "Dependent") + + static let window = SceneType(storyboard: Placeholder.self, identifier: "Window") + } +} + +enum StoryboardSegue { + enum Message: String, SegueType { + case embed = "Embed" + case modal = "Modal" + case popover = "Popover" + case sheet = "Sheet" + case show = "Show" + case `public` + } +} +// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name + +private final class BundleToken {} diff --git a/Tests/Expected/Storyboards-macOS/swift4-context-all-ignore-module-need-extra-definitions.swift b/Tests/Expected/Storyboards-macOS/swift4-context-all-ignore-module-need-extra-definitions.swift new file mode 100644 index 0000000..1c6b9a7 --- /dev/null +++ b/Tests/Expected/Storyboards-macOS/swift4-context-all-ignore-module-need-extra-definitions.swift @@ -0,0 +1,105 @@ +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +// swiftlint:disable sorted_imports +import Foundation +import Cocoa +import FadeSegue + +// swiftlint:disable file_length + +protocol StoryboardType { + static var storyboardName: String { get } +} + +extension StoryboardType { + static var storyboard: NSStoryboard { + let name = NSStoryboard.Name(self.storyboardName) + return NSStoryboard(name: name, bundle: Bundle(for: BundleToken.self)) + } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + func instantiate() -> T { + let identifier = NSStoryboard.SceneIdentifier(self.identifier) + guard let controller = storyboard.storyboard.instantiateController(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") + } + return controller + } +} + +struct InitialSceneType { + let storyboard: StoryboardType.Type + + func instantiate() -> T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller + } +} + +protocol SegueType: RawRepresentable { } + +extension NSSeguePerforming { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + let identifier = NSStoryboardSegue.Identifier(segue.rawValue) + performSegue?(withIdentifier: identifier, sender: sender) + } +} + +// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name +enum StoryboardScene { + enum AdditionalImport: StoryboardType { + static let storyboardName = "AdditionalImport" + + static let `private` = SceneType(storyboard: AdditionalImport.self, identifier: "private") + } + enum Anonymous: StoryboardType { + static let storyboardName = "Anonymous" + } + enum Dependency: StoryboardType { + static let storyboardName = "Dependency" + + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") + } + enum Message: StoryboardType { + static let storyboardName = "Message" + + static let messageDetails = SceneType(storyboard: Message.self, identifier: "MessageDetails") + + static let messageList = SceneType(storyboard: Message.self, identifier: "MessageList") + + static let messageListFooter = SceneType(storyboard: Message.self, identifier: "MessageListFooter") + + static let messagesTab = SceneType(storyboard: Message.self, identifier: "MessagesTab") + + static let splitMessages = SceneType(storyboard: Message.self, identifier: "SplitMessages") + + static let windowCtrl = SceneType(storyboard: Message.self, identifier: "WindowCtrl") + } + enum Placeholder: StoryboardType { + static let storyboardName = "Placeholder" + + static let dependent = SceneType(storyboard: Placeholder.self, identifier: "Dependent") + + static let window = SceneType(storyboard: Placeholder.self, identifier: "Window") + } +} + +enum StoryboardSegue { + enum Message: String, SegueType { + case embed = "Embed" + case modal = "Modal" + case popover = "Popover" + case sheet = "Sheet" + case show = "Show" + case `public` + } +} +// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name + +private final class BundleToken {} diff --git a/Tests/TemplatesTests/StoryboardsMacOSTests.swift b/Tests/TemplatesTests/StoryboardsMacOSTests.swift index 847432b..475d49b 100644 --- a/Tests/TemplatesTests/StoryboardsMacOSTests.swift +++ b/Tests/TemplatesTests/StoryboardsMacOSTests.swift @@ -36,7 +36,21 @@ class StoryboardsMacOSTests: XCTestCase { suffix: ""), (context: try StencilContext.enrich(context: context, parameters: ["module=FadeSegue"]), - suffix: "-ignore-module") + suffix: "-ignore-module"), + (context: try StencilContext.enrich(context: context, + parameters: ["ignoreTargetModule"], + environment: ["PRODUCT_MODULE_NAME": "Test"]), + suffix: ""), + (context: try StencilContext.enrich(context: context, + parameters: ["ignoreTargetModule"], + environment: ["PRODUCT_MODULE_NAME": "PrefsWindowController"]), + suffix: "-ignore-module-need-extra-definitions"), + (context: try StencilContext.enrich(context: context, + parameters: ["module=Test", "ignoreTargetModule"]), + suffix: ""), + (context: try StencilContext.enrich(context: context, + parameters: ["module=PrefsWindowController", "ignoreTargetModule"]), + suffix: "-ignore-module-need-extra-definitions") ] } diff --git a/Tests/TemplatesTests/StoryboardsiOSTests.swift b/Tests/TemplatesTests/StoryboardsiOSTests.swift index 38baf13..fcc7ffc 100644 --- a/Tests/TemplatesTests/StoryboardsiOSTests.swift +++ b/Tests/TemplatesTests/StoryboardsiOSTests.swift @@ -36,7 +36,21 @@ class StoryboardsiOSTests: XCTestCase { suffix: ""), (context: try StencilContext.enrich(context: context, parameters: ["module=CustomSegue"]), - suffix: "-ignore-module") + suffix: "-ignore-module"), + (context: try StencilContext.enrich(context: context, + parameters: ["ignoreTargetModule"], + environment: ["PRODUCT_MODULE_NAME": "Test"]), + suffix: ""), + (context: try StencilContext.enrich(context: context, + parameters: ["ignoreTargetModule"], + environment: ["PRODUCT_MODULE_NAME": "SlackTextViewController"]), + suffix: "-ignore-module-need-extra-definitions"), + (context: try StencilContext.enrich(context: context, + parameters: ["module=Test", "ignoreTargetModule"]), + suffix: ""), + (context: try StencilContext.enrich(context: context, + parameters: ["module=SlackTextViewController", "ignoreTargetModule"]), + suffix: "-ignore-module-need-extra-definitions") ] } diff --git a/templates/storyboards/swift2.stencil b/templates/storyboards/swift2.stencil index f3360d9..b3f056e 100644 --- a/templates/storyboards/swift2.stencil +++ b/templates/storyboards/swift2.stencil @@ -60,7 +60,11 @@ extension {% if isAppKit %}NSSeguePerforming{% else %}UIViewController{% endif % {% set sceneEnumName %}{{param.sceneEnumName|default:"StoryboardScene"}}{% endset %} {% macro className scene %}{% filter removeNewlines %} {% if scene.customClass %} - {% if scene.customModule %}{{scene.customModule}}.{% endif %} + {% if scene.customModule %} + {% if not param.ignoreTargetModule or scene.customModule != env.PRODUCT_MODULE_NAME and scene.customModule != param.module %} + {{scene.customModule}}. + {% endif %} + {% endif %} {{scene.customClass}} {% else %} {{prefix}}{{scene.baseType}} diff --git a/templates/storyboards/swift3.stencil b/templates/storyboards/swift3.stencil index 91b3d31..2ccddac 100644 --- a/templates/storyboards/swift3.stencil +++ b/templates/storyboards/swift3.stencil @@ -60,7 +60,11 @@ extension {% if isAppKit %}NSSeguePerforming{% else %}UIViewController{% endif % {% set sceneEnumName %}{{param.sceneEnumName|default:"StoryboardScene"}}{% endset %} {% macro className scene %}{% filter removeNewlines %} {% if scene.customClass %} - {% if scene.customModule %}{{scene.customModule}}.{% endif %} + {% if scene.customModule %} + {% if not param.ignoreTargetModule or scene.customModule != env.PRODUCT_MODULE_NAME and scene.customModule != param.module %} + {{scene.customModule}}. + {% endif %} + {% endif %} {{scene.customClass}} {% else %} {{prefix}}{{scene.baseType}} diff --git a/templates/storyboards/swift4.stencil b/templates/storyboards/swift4.stencil index c0910a4..62bdfed 100644 --- a/templates/storyboards/swift4.stencil +++ b/templates/storyboards/swift4.stencil @@ -63,7 +63,11 @@ extension {% if isAppKit %}NSSeguePerforming{% else %}UIViewController{% endif % {% set sceneEnumName %}{{param.sceneEnumName|default:"StoryboardScene"}}{% endset %} {% macro className scene %}{% filter removeNewlines %} {% if scene.customClass %} - {% if scene.customModule %}{{scene.customModule}}.{% endif %} + {% if scene.customModule %} + {% if not param.ignoreTargetModule or scene.customModule != env.PRODUCT_MODULE_NAME and scene.customModule != param.module %} + {{scene.customModule}}. + {% endif %} + {% endif %} {{scene.customClass}} {% else %} {{prefix}}{{scene.baseType}}