Skip to content
5 changes: 5 additions & 0 deletions Sources/NodesGenerator/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public struct Config: Codable, Equatable {
public var builderImports: Set<String>
public var flowImports: Set<String>
public var pluginListImports: Set<String>
public var pluginListInterfaceImports: Set<String>
public var viewControllerImports: Set<String>
public var dependencies: [Variable]
public var analyticsProperties: [Variable]
Expand Down Expand Up @@ -95,6 +96,7 @@ extension Config {
builderImports = []
flowImports = []
pluginListImports = []
pluginListInterfaceImports = []
viewControllerImports = []
dependencies = []
analyticsProperties = []
Expand Down Expand Up @@ -171,6 +173,9 @@ extension Config {
pluginListImports =
(try? decoder.decode(CodingKeys.pluginListImports))
?? defaults.pluginListImports
pluginListInterfaceImports =
(try? decoder.decode(CodingKeys.pluginListInterfaceImports))
?? defaults.pluginListInterfaceImports
viewControllerImports =
(try? decoder.decode(CodingKeys.viewControllerImports))
?? defaults.viewControllerImports
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public struct PluginListStencilContext: StencilContext {
private let fileHeader: String
private let pluginListName: String
private let pluginListImports: [String]
private let pluginListInterfaceImports: [String]
private let pluginListTestsImports: [String]
private let viewControllableFlowType: String
private let isPeripheryCommentEnabled: Bool
Expand All @@ -22,6 +23,7 @@ public struct PluginListStencilContext: StencilContext {
"file_header": fileHeader,
"plugin_list_name": pluginListName,
"plugin_list_imports": pluginListImports,
"plugin_list_interface_imports": pluginListInterfaceImports,
"plugin_list_tests_imports": pluginListTestsImports,
"view_controllable_flow_type": viewControllableFlowType,
"is_periphery_comment_enabled": isPeripheryCommentEnabled,
Expand All @@ -33,6 +35,7 @@ public struct PluginListStencilContext: StencilContext {
fileHeader: String,
pluginListName: String,
pluginListImports: Set<String>,
pluginListInterfaceImports: Set<String>,
pluginListTestsImports: Set<String>,
viewControllableFlowType: String,
isPeripheryCommentEnabled: Bool,
Expand All @@ -41,6 +44,7 @@ public struct PluginListStencilContext: StencilContext {
self.fileHeader = fileHeader
self.pluginListName = pluginListName
self.pluginListImports = pluginListImports.sortedImports()
self.pluginListInterfaceImports = pluginListInterfaceImports.sortedImports()
self.pluginListTestsImports = pluginListTestsImports.sortedImports()
self.viewControllableFlowType = viewControllableFlowType
self.isPeripheryCommentEnabled = isPeripheryCommentEnabled
Expand Down
2 changes: 1 addition & 1 deletion Sources/NodesGenerator/StencilRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public final class StencilRenderer {
includeTests: Bool
) throws -> [String: String] {
let additional: [StencilTemplate] = includeTests ? [.pluginListTests] : []
let stencils: [StencilTemplate] = [.pluginList] + additional
let stencils: [StencilTemplate] = [.pluginList, .pluginListInterface] + additional
return try render(stencils: stencils, with: context.dictionary)
}

Expand Down
7 changes: 7 additions & 0 deletions Sources/NodesGenerator/StencilTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public enum StencilTemplate: CustomStringConvertible, Equatable, Sendable {
case pluginInterface
case pluginTests
case pluginList
case pluginListInterface
case pluginListTests
case state
case viewController(Variation)
Expand Down Expand Up @@ -199,6 +200,8 @@ public enum StencilTemplate: CustomStringConvertible, Equatable, Sendable {
"PluginTests"
case .pluginList:
"PluginList"
case .pluginListInterface:
"PluginListInterface"
case .pluginListTests:
"PluginListTests"
case .state:
Expand Down Expand Up @@ -238,6 +241,8 @@ public enum StencilTemplate: CustomStringConvertible, Equatable, Sendable {
description.appending(variation.suffix)
case .pluginList, .pluginListTests:
description
case .pluginListInterface:
description
case .state:
description
case let .viewController(variation), let .viewControllerTests(variation):
Expand Down Expand Up @@ -296,6 +301,8 @@ public enum StencilTemplate: CustomStringConvertible, Equatable, Sendable {
.union(["Nodes"])
.union(config.dependencyInjectionImports)
.union(config.pluginListImports)
case .pluginListInterface:
config.baseImports
case .pluginListTests:
config.baseTestImports
.union(["NodesTesting"])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ internal struct PluginListXcodeTemplatePermutation: XcodeTemplatePermutation {
internal init(name: String, config: Config) {
self.name = name
let pluginList: StencilTemplate = .pluginList
let pluginListInterface: StencilTemplate = .pluginListInterface
let pluginListTests: StencilTemplate = .pluginListTests
stencils = [pluginList] + (config.isTestTemplatesGenerationEnabled ? [pluginListTests] : [])
stencils = [pluginList, pluginListInterface]
+ (config.isTestTemplatesGenerationEnabled ? [pluginListTests] : [])
stencilContext = PluginListStencilContext(
fileHeader: XcodeTemplateConstants.fileHeader,
pluginListName: XcodeTemplateConstants.variable(XcodeTemplateConstants.productName),
pluginListImports: pluginList.imports(with: config),
pluginListInterfaceImports: pluginListInterface.imports(with: config),
pluginListTestsImports: pluginListTests.imports(with: config),
viewControllableFlowType: config.viewControllableFlowType,
isPeripheryCommentEnabled: config.isPeripheryCommentEnabled,
Expand Down
4 changes: 2 additions & 2 deletions Tests/NodesGeneratorTests/StencilRendererTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ final class StencilRendererTests: XCTestCase, TestFactories {
let context: PluginListStencilContext = givenPluginListStencilContext(mockCount: count)
let templates: [String: String] = try stencilRenderer
.renderPluginList(context: context, includeTests: false)
expect(templates.keys.sorted()) == ["PluginList"]
expect(templates.keys.sorted()) == ["PluginList", "PluginListInterface"]
templates.forEach { name, template in
assertSnapshot(of: template,
as: .lines,
Expand All @@ -311,7 +311,7 @@ final class StencilRendererTests: XCTestCase, TestFactories {
let context: PluginListStencilContext = givenPluginListStencilContext(mockCount: count)
let templates: [String: String] = try stencilRenderer
.renderPluginList(context: context, includeTests: true)
expect(templates.keys.sorted()) == ["PluginList", "PluginListTests"]
expect(templates.keys.sorted()) == ["PluginList", "PluginListInterface", "PluginListTests"]
templates.forEach { name, template in
assertSnapshot(of: template,
as: .lines,
Expand Down
13 changes: 13 additions & 0 deletions Tests/NodesGeneratorTests/StencilTemplateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ final class StencilTemplateTests: XCTestCase, TestFactories {
expect(name) == "PluginTests"
case .pluginList:
expect(name) == "PluginList"
case .pluginListInterface:
expect(name) == "PluginListInterface"
case .pluginListTests:
expect(name) == "PluginListTests"
case .state:
Expand Down Expand Up @@ -125,6 +127,8 @@ final class StencilTemplateTests: XCTestCase, TestFactories {
expect(filename) == "PluginTests"
case .pluginList:
expect(filename) == "PluginList"
case .pluginListInterface:
expect(filename) == "PluginListInterface"
case .pluginListTests:
expect(filename) == "PluginListTests"
case .state:
Expand Down Expand Up @@ -361,6 +365,10 @@ final class StencilTemplateTests: XCTestCase, TestFactories {
"<pluginListImport>",
"Nodes"
]
case .pluginListInterface:
expect(imports) == [
"<baseImport>"
]
case .pluginListTests:
expect(imports) == [
"<baseTestImport>",
Expand Down Expand Up @@ -482,6 +490,10 @@ final class StencilTemplateTests: XCTestCase, TestFactories {
"<pluginListImport>",
"Nodes"
]
case .pluginListInterface:
expect(imports) == [
"<baseImport>"
]
case .pluginListTests:
expect(imports) == [
"<baseTestImport>",
Expand Down Expand Up @@ -533,6 +545,7 @@ extension StencilTemplate {
.pluginInterface,
.pluginTests,
.pluginList,
.pluginListInterface,
.pluginListTests,
.state,
.viewController(.regular),
Expand Down
1 change: 1 addition & 0 deletions Tests/NodesGeneratorTests/Support/TestFactories.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ extension TestFactories {
fileHeader: "<fileHeader>",
pluginListName: "<pluginListName>",
pluginListImports: .mock(with: "pluginListImport", count: mockCount),
pluginListInterfaceImports: .mock(with: "pluginListInterfaceImport", count: mockCount),
pluginListTestsImports: .mock(with: "pluginListTestsImports", count: mockCount),
viewControllableFlowType: "<viewControllableFlowType>",
isPeripheryCommentEnabled: mockCount > 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
▿ pluginListImports: 2 members
- "<pluginListImports-1>"
- "<pluginListImports-2>"
- pluginListInterfaceImports: 0 members
- publisherFailureType: "<publisherFailureType>"
- publisherType: "<publisherType>"
▿ reactiveImports: 2 members
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- isTestTemplatesGenerationEnabled: true
- isViewInjectedTemplateEnabled: true
- pluginListImports: 0 members
- pluginListInterfaceImports: 0 members
- publisherFailureType: "Never"
- publisherType: "AnyPublisher"
▿ reactiveImports: 1 member
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- isTestTemplatesGenerationEnabled: true
- isViewInjectedTemplateEnabled: true
- pluginListImports: 0 members
- pluginListInterfaceImports: 0 members
- publisherFailureType: "Never"
- publisherType: "AnyPublisher"
▿ reactiveImports: 1 member
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- isTestTemplatesGenerationEnabled: true
- isViewInjectedTemplateEnabled: true
- pluginListImports: 0 members
- pluginListInterfaceImports: 0 members
- publisherFailureType: "Never"
- publisherType: "AnyPublisher"
▿ reactiveImports: 1 member
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
7 key/value pairs
8 key/value pairs
▿ (2 elements)
- key: "file_header"
- value: "<fileHeader>"
Expand All @@ -12,6 +12,10 @@
- key: "plugin_list_imports"
▿ value: 1 element
- "<pluginListImport>"
▿ (2 elements)
- key: "plugin_list_interface_imports"
▿ value: 1 element
- "<pluginListInterfaceImport>"
▿ (2 elements)
- key: "plugin_list_name"
- value: "<pluginListName>"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//<fileHeader>

// This file defines the protocols and types in the Plugin List interface requiring public ACL for use in another module.

/// Declares the type of key used to identify plugins within the collection.
/// - NOTE: May be any ``Hashable`` type such as ``String`` or an enumeration.
internal typealias <pluginListName>PluginListKeyType = String

/// Dynamic state from the caller provided to the plugins to use in determining whether they are enabled.
/// - NOTE: An alias to a tuple is supported.
internal typealias <pluginListName>PluginListStateType = Void

/// @mockable
@MainActor
internal protocol <pluginListName>PluginList {
func createAll() -> [<pluginListName>Builder]
func create() -> <pluginListName>Builder?
func create(key: <pluginListName>PluginListKeyType) -> <pluginListName>Builder?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//<fileHeader>

import <pluginListInterfaceImport>

// This file defines the protocols and types in the Plugin List interface requiring public ACL for use in another module.

/// Declares the type of key used to identify plugins within the collection.
/// - NOTE: May be any ``Hashable`` type such as ``String`` or an enumeration.
internal typealias <pluginListName>PluginListKeyType = String

/// Dynamic state from the caller provided to the plugins to use in determining whether they are enabled.
/// - NOTE: An alias to a tuple is supported.
internal typealias <pluginListName>PluginListStateType = Void

// periphery:ignore
/// @mockable
@MainActor
internal protocol <pluginListName>PluginList {
func createAll() -> [<pluginListName>Builder]
func create() -> <pluginListName>Builder?
func create(key: <pluginListName>PluginListKeyType) -> <pluginListName>Builder?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//<fileHeader>

import <pluginListInterfaceImport1>
import <pluginListInterfaceImport2>

// This file defines the protocols and types in the Plugin List interface requiring public ACL for use in another module.

/// Declares the type of key used to identify plugins within the collection.
/// - NOTE: May be any ``Hashable`` type such as ``String`` or an enumeration.
internal typealias <pluginListName>PluginListKeyType = String

/// Dynamic state from the caller provided to the plugins to use in determining whether they are enabled.
/// - NOTE: An alias to a tuple is supported.
internal typealias <pluginListName>PluginListStateType = Void

// periphery:ignore
/// @mockable
@MainActor
internal protocol <pluginListName>PluginList {
func createAll() -> [<pluginListName>Builder]
func create() -> <pluginListName>Builder?
func create(key: <pluginListName>PluginListKeyType) -> <pluginListName>Builder?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//<fileHeader>

// This file defines the protocols and types in the Plugin List interface requiring public ACL for use in another module.

/// Declares the type of key used to identify plugins within the collection.
/// - NOTE: May be any ``Hashable`` type such as ``String`` or an enumeration.
internal typealias <pluginListName>PluginListKeyType = String

/// Dynamic state from the caller provided to the plugins to use in determining whether they are enabled.
/// - NOTE: An alias to a tuple is supported.
internal typealias <pluginListName>PluginListStateType = Void

/// @mockable
@MainActor
internal protocol <pluginListName>PluginList {
func createAll() -> [<pluginListName>Builder]
func create() -> <pluginListName>Builder?
func create(key: <pluginListName>PluginListKeyType) -> <pluginListName>Builder?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//<fileHeader>

import <pluginListInterfaceImport>

// This file defines the protocols and types in the Plugin List interface requiring public ACL for use in another module.

/// Declares the type of key used to identify plugins within the collection.
/// - NOTE: May be any ``Hashable`` type such as ``String`` or an enumeration.
internal typealias <pluginListName>PluginListKeyType = String

/// Dynamic state from the caller provided to the plugins to use in determining whether they are enabled.
/// - NOTE: An alias to a tuple is supported.
internal typealias <pluginListName>PluginListStateType = Void

// periphery:ignore
/// @mockable
@MainActor
internal protocol <pluginListName>PluginList {
func createAll() -> [<pluginListName>Builder]
func create() -> <pluginListName>Builder?
func create(key: <pluginListName>PluginListKeyType) -> <pluginListName>Builder?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//<fileHeader>

import <pluginListInterfaceImport1>
import <pluginListInterfaceImport2>

// This file defines the protocols and types in the Plugin List interface requiring public ACL for use in another module.

/// Declares the type of key used to identify plugins within the collection.
/// - NOTE: May be any ``Hashable`` type such as ``String`` or an enumeration.
internal typealias <pluginListName>PluginListKeyType = String

/// Dynamic state from the caller provided to the plugins to use in determining whether they are enabled.
/// - NOTE: An alias to a tuple is supported.
internal typealias <pluginListName>PluginListStateType = Void

// periphery:ignore
/// @mockable
@MainActor
internal protocol <pluginListName>PluginList {
func createAll() -> [<pluginListName>Builder]
func create() -> <pluginListName>Builder?
func create(key: <pluginListName>PluginListKeyType) -> <pluginListName>Builder?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//___FILEHEADER___

// This file defines the protocols and types in the Plugin List interface requiring public ACL for use in another module.

/// Declares the type of key used to identify plugins within the collection.
/// - NOTE: May be any ``Hashable`` type such as ``String`` or an enumeration.
internal typealias ___VARIABLE_productName___PluginListKeyType = String

/// Dynamic state from the caller provided to the plugins to use in determining whether they are enabled.
/// - NOTE: An alias to a tuple is supported.
internal typealias ___VARIABLE_productName___PluginListStateType = Void

/// @mockable
@MainActor
internal protocol ___VARIABLE_productName___PluginList {
func createAll() -> [___VARIABLE_productName___Builder]
func create() -> ___VARIABLE_productName___Builder?
func create(key: ___VARIABLE_productName___PluginListKeyType) -> ___VARIABLE_productName___Builder?
}
Loading