-
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added initialized variable ignore option (#17)
* feat: added initialized variable ignore option * refactor: use separate macro attribute instead of adding options
- Loading branch information
1 parent
94855a0
commit 6cd519e
Showing
52 changed files
with
1,306 additions
and
575 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
Sources/CodableMacroPlugin/Attributes/Codable/Codable.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import SwiftSyntax | ||
|
||
/// Attribute type for `Codable` macro-attribute. | ||
/// | ||
/// Describes a macro that validates `Codable` macro usage | ||
/// and generates `Codable` conformances and implementations. | ||
/// | ||
/// This macro performs two different kinds of expansion: | ||
/// * Conformance macro expansion, to confirm to `Decodable` | ||
/// and `Encodable` protocols. | ||
/// * Member macro expansion, to generate custom `CodingKey` type | ||
/// for the attached struct declaration named `CodingKeys` and use | ||
/// this type for `Codable` implementation of both `init(from:)` | ||
/// and `encode(to:)` methods by using `CodedPropertyMacro` | ||
/// declarations. Additionally member-wise initializer(s) also generated. | ||
struct Codable: Attribute { | ||
/// The node syntax provided | ||
/// during initialization. | ||
let node: AttributeSyntax | ||
|
||
/// Creates a new instance with the provided node | ||
/// | ||
/// The initializer fails to create new instance if the name | ||
/// of the provided node is different than this attribute. | ||
/// | ||
/// - Parameter node: The attribute syntax to create with. | ||
/// - Returns: Newly created attribute instance. | ||
init?(from node: AttributeSyntax) { | ||
guard | ||
node.attributeName.as(SimpleTypeIdentifierSyntax.self)! | ||
.description == Self.name | ||
else { return nil } | ||
self.node = node | ||
} | ||
|
||
/// Builds diagnoser that can validate this macro | ||
/// attached declaration. | ||
/// | ||
/// Builds diagnoser that validates attached declaration | ||
/// is `struct` declaration and macro usage is not | ||
/// duplicated for the same declaration. | ||
/// | ||
/// - Returns: The built diagnoser instance. | ||
func diagnoser() -> DiagnosticProducer { | ||
return AggregatedDiagnosticProducer { | ||
expect(syntax: StructDeclSyntax.self) | ||
cantDuplicate() | ||
} | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
Sources/CodableMacroPlugin/Attributes/Codable/IgnoreCodingInitialized.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import SwiftSyntax | ||
|
||
/// Attribute type for `IgnoreCodingInitialized` macro-attribute. | ||
/// | ||
/// This type can validate`IgnoreCodingInitialized` macro-attribute | ||
/// usage and extract data for `Codable` macro to generate implementation. | ||
/// | ||
/// Attaching this macro to type declaration indicates all the initialized | ||
/// properties for the said type will be ignored from decoding and | ||
/// encoding unless explicitly asked with attached coding attributes, | ||
/// i.e. `CodedIn`, `CodedAt` etc. | ||
struct IgnoreCodingInitialized: PeerAttribute { | ||
/// The node syntax provided | ||
/// during initialization. | ||
let node: AttributeSyntax | ||
|
||
/// Creates a new instance with the provided node | ||
/// | ||
/// The initializer fails to create new instance if the name | ||
/// of the provided node is different than this attribute. | ||
/// | ||
/// - Parameter node: The attribute syntax to create with. | ||
/// - Returns: Newly created attribute instance. | ||
init?(from node: AttributeSyntax) { | ||
guard | ||
node.attributeName.as(SimpleTypeIdentifierSyntax.self)! | ||
.description == Self.name | ||
else { return nil } | ||
self.node = node | ||
} | ||
|
||
/// Create a new instance from provided attached | ||
/// grouped declaration. | ||
/// | ||
/// This initialization will fail if this attribute not attached | ||
/// to provided variable declaration | ||
/// | ||
/// - Parameter decl: The attached grouped declaration. | ||
/// - Returns: Newly created attribute instance. | ||
init?(from decl: some DeclGroupSyntax) { | ||
guard let decl = decl as? AttributableDeclSyntax else { return nil } | ||
self.init(from: decl) | ||
} | ||
|
||
/// Builds diagnoser that can validate this macro | ||
/// attached declaration. | ||
/// | ||
/// Builds diagnoser that validates attached declaration | ||
/// has `Codable` macro attached and macro usage | ||
/// is not duplicated for the same declaration. | ||
/// | ||
/// - Returns: The built diagnoser instance. | ||
func diagnoser() -> DiagnosticProducer { | ||
return AggregatedDiagnosticProducer { | ||
mustBeCombined(with: Codable.self) | ||
shouldNotDuplicate() | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
88 changes: 88 additions & 0 deletions
88
Sources/CodableMacroPlugin/Attributes/KeyPath/KeyPathProvider.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import SwiftSyntax | ||
|
||
/// A special `PropertyAttribute` that updates | ||
/// `CodingKey` path data. | ||
/// | ||
/// Attaching attribute of this type to variables indicates | ||
/// explicit decoding/encoding of those variables. | ||
protocol KeyPathProvider: PropertyAttribute { | ||
/// Indicates whether `CodingKey` path | ||
/// data is provided to this instance. | ||
/// | ||
/// If data is provided explicitly by attaching | ||
/// the macro then `true`, otherwise `false` | ||
/// This can be used to indicate variable is | ||
/// explicitly asked to decode/encode. | ||
var provided: Bool { get } | ||
|
||
/// Updates `CodingKey` path using the provided path. | ||
/// | ||
/// The `CodingKey` path may override current data | ||
/// or just update current `CodingKey` path. | ||
/// | ||
/// - Parameter path: Current `CodingKey` path. | ||
/// - Returns: Updated `CodingKey` path. | ||
func keyPath(withExisting path: [String]) -> [String] | ||
} | ||
|
||
extension KeyPathProvider { | ||
/// Returns `CodingKey` path | ||
/// provided in this attribute. | ||
/// | ||
/// The path components are provided | ||
/// as variadic arguments without any labels. | ||
/// | ||
/// - Important: The path components must be string literals | ||
/// with single segment (i.e no interpolation, | ||
/// no string combinations). | ||
var providedPath: [String] { | ||
guard let exprs = node.argument?.as(TupleExprElementListSyntax.self) | ||
else { return [] } | ||
|
||
let path: [String] = exprs.compactMap { expr in | ||
guard expr.label == nil else { return nil } | ||
return expr.expression.as(StringLiteralExprSyntax.self)? | ||
.segments.first?.as(StringSegmentSyntax.self)? | ||
.content.text | ||
} | ||
return path | ||
} | ||
} | ||
|
||
extension CodedAt: KeyPathProvider { | ||
/// Indicates whether `CodingKey` path | ||
/// data is provided to this instance. | ||
/// | ||
/// Always `true` for this type. | ||
var provided: Bool { true } | ||
|
||
/// Updates `CodingKey` path using the provided path. | ||
/// | ||
/// The `CodingKey` path overrides current `CodingKey` path data. | ||
/// | ||
/// - Parameter path: Current `CodingKey` path. | ||
/// - Returns: Updated `CodingKey` path. | ||
func keyPath(withExisting path: [String]) -> [String] { providedPath } | ||
} | ||
|
||
extension CodedIn: KeyPathProvider { | ||
/// Indicates whether `CodingKey` path | ||
/// data is provided to this instance. | ||
/// | ||
/// If attribute is initialized with syntax node, | ||
/// then `true`, otherwise `false`. | ||
var provided: Bool { !inDefaultMode } | ||
|
||
/// Updates `CodingKey` path using the provided path. | ||
/// | ||
/// The `CodingKey` path is updated by prepending | ||
/// provided path to current `CodingKey` path. | ||
/// | ||
/// - Parameter path: Current `CodingKey` path. | ||
/// - Returns: Updated `CodingKey` path. | ||
func keyPath(withExisting path: [String]) -> [String] { | ||
var finalPath = providedPath | ||
finalPath.append(contentsOf: path) | ||
return finalPath | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.