Skip to content

Commit d784e83

Browse files
REF: simplify resolvable pattern usage
1 parent c572dbe commit d784e83

2 files changed

Lines changed: 37 additions & 63 deletions

File tree

Sources/Resolvable/Resolvable.swift

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@ public enum ResolvableDefault {
77
case overridable // All properties are overridable unless marked @Identity
88
}
99

10-
/// Which nested types the @Resolvable macro should generate.
11-
public struct ResolvableParts: OptionSet, Hashable, Codable, Sendable {
12-
public let rawValue: UInt8
13-
public init(rawValue: UInt8) { self.rawValue = rawValue }
10+
/// Defines the pattern of code generation for a @Resolvable type.
11+
public enum ResolvablePattern {
12+
/// Generates `.Definition`, `.Instance`, and `.Override`.
13+
case full
1414

15-
public static let definition = ResolvableParts(rawValue: 1 << 0)
16-
public static let instance = ResolvableParts(rawValue: 1 << 1)
17-
public static let overrides = ResolvableParts(rawValue: 1 << 2)
18-
19-
public static let all: ResolvableParts = [.definition, .instance, .overrides]
15+
/// Generates only `.Definition` and `.Override`.
16+
case nonInstantiable
2017
}
2118

2219
/// The `@Resolvable` macro generates all the necessary boilerplate for the
@@ -35,7 +32,7 @@ public struct ResolvableParts: OptionSet, Hashable, Codable, Sendable {
3532
@attached(memberAttribute)
3633
public macro Resolvable(
3734
default: ResolvableDefault = .optIn,
38-
generate: ResolvableParts = .all
35+
pattern: ResolvablePattern = .full
3936
) = #externalMacro(module: "ResolvableMacros", type: "ResolvableMacro")
4037

4138
/// A property wrapper to mark which properties of a model can be

Sources/ResolvableMacros/ResolvableMacro.swift

Lines changed: 30 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@ public struct ResolvableMacro: MemberMacro, MemberAttributeMacro {
1313
}
1414

1515
// Generate flags parsed from `generate:` option set
16+
private enum ResolvablePattern {
17+
case full
18+
case nonInstantiable
19+
}
20+
1621
private struct GenerateFlags {
17-
var hasDefinition = true
18-
var hasInstance = true
19-
// Whether override fields should be generated + applied.
20-
// The Override type still exists whenever hasDefinition is true.
21-
var includeOverrideFields = true
22-
23-
var hasAnySource: Bool { hasDefinition || hasInstance }
22+
var hasDefinition: Bool
23+
var hasInstance: Bool
24+
// This can be simplified. If a definition exists, overrides should be included.
25+
var includeOverrideFields: Bool
2426
}
2527

2628
public static func expansion(
@@ -43,31 +45,15 @@ public struct ResolvableMacro: MemberMacro, MemberAttributeMacro {
4345
}
4446
}
4547

46-
// Parse @Resolvable(generate: <ResolvableParts>)
47-
let generateFlags = parseGenerateFlags(from: node)
48-
49-
// If nothing to resolve from
50-
if !generateFlags.hasAnySource {
51-
context.diagnose(Diagnostic(
52-
node: Syntax(node),
53-
message: ResolvableMessage(
54-
id: "noSourcesSelected",
55-
message: "At least one of '.definition' or '.instance' must be included in 'generate:' to produce 'Source', 'Resolved', and 'Resolver'.",
56-
severity: .error
57-
)
58-
))
59-
}
60-
// If override fields requested but no definitions exist
61-
if generateFlags.includeOverrideFields && !generateFlags.hasDefinition {
62-
context.diagnose(Diagnostic(
63-
node: Syntax(node),
64-
message: ResolvableMessage(
65-
id: "overridesWithoutDefinition",
66-
message: "'.overrides' has no effect without '.definition'. The resolver will ignore overrides.",
67-
severity: .warning
68-
)
69-
))
70-
}
48+
let pattern = parsePattern(from: node)
49+
50+
let generateFlags: GenerateFlags
51+
switch pattern {
52+
case .full:
53+
generateFlags = GenerateFlags(hasDefinition: true, hasInstance: true, includeOverrideFields: true)
54+
case .nonInstantiable:
55+
generateFlags = GenerateFlags(hasDefinition: true, hasInstance: false, includeOverrideFields: true)
56+
}
7157

7258
var allProperties: [VariableDeclSyntax] = []
7359
var fullOverrides: [VariableDeclSyntax] = []
@@ -217,7 +203,7 @@ public struct ResolvableMacro: MemberMacro, MemberAttributeMacro {
217203
decls.append(createInstanceStruct(baseName: baseName, properties: allProperties))
218204
}
219205

220-
if generateFlags.hasAnySource {
206+
if generateFlags.hasDefinition || generateFlags.hasInstance {
221207
decls.append(createSourceEnum(baseName: baseName,
222208
hasDefinition: generateFlags.hasDefinition,
223209
hasInstance: generateFlags.hasInstance))
@@ -519,30 +505,21 @@ public struct ResolvableMacro: MemberMacro, MemberAttributeMacro {
519505
}
520506
return text
521507
}
522-
523-
// Parse generate flags from the attribute's `generate:` argument.
524-
private static func parseGenerateFlags(from node: AttributeSyntax) -> GenerateFlags {
525-
var flags = GenerateFlags() // default == .all
508+
509+
private static func parsePattern(from node: AttributeSyntax) -> ResolvablePattern {
526510
guard let args = node.arguments?.as(LabeledExprListSyntax.self),
527-
let generateArg = args.first(where: { $0.label?.text == "generate" })
528-
else { return flags }
529-
530-
let text = generateArg.expression.trimmedDescription
531-
532-
if text.contains(".all") {
533-
return flags
511+
let patternArg = args.first(where: { $0.label?.text == "pattern" })
512+
else {
513+
// If the `pattern` argument is omitted, default to `.full`.
514+
return .full
534515
}
535516

536-
// Reset and enable selectively
537-
flags.hasDefinition = false
538-
flags.hasInstance = false
539-
flags.includeOverrideFields = false
540-
541-
if text.contains(".definition") { flags.hasDefinition = true }
542-
if text.contains(".instance") { flags.hasInstance = true }
543-
if text.contains(".overrides") { flags.includeOverrideFields = true }
517+
let text = patternArg.expression.trimmedDescription
518+
if text.contains("nonInstantiable") {
519+
return .nonInstantiable
520+
}
544521

545-
return flags
522+
return .full
546523
}
547524
}
548525

0 commit comments

Comments
 (0)