-
-
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.
refactor: modify macro implementation (#12)
BREAKING CHANGE: replaced `CodablePath` with `CodedAt` BREAKING CHANGE: replaced `CodableCompose` with `CodedAt` without args BREAKING CHANGE: renamed `ExternalHelperCoder` to `HelperCoder` BREAKING CHANGE: replaced `default:` with `@Default` BREAKING CHANGE: replaced `helper:` with `@CodedBy`
- Loading branch information
1 parent
a6bc3a2
commit 8d61676
Showing
55 changed files
with
4,954 additions
and
1,414 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
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
72 changes: 72 additions & 0 deletions
72
Sources/CodableMacroPlugin/Attributes/AttributableDeclSyntax.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,72 @@ | ||
import SwiftSyntax | ||
|
||
/// An extension that manages fetching attributes | ||
/// attached to declarations. | ||
extension SyntaxProtocol { | ||
/// Provides all the attributes attached to this declaration of | ||
/// the provided type. | ||
/// | ||
/// All the attribute syntaxes are checked and those matching | ||
/// the provided type are returned. | ||
/// | ||
/// - Parameter type: The macro-attribute type to search. | ||
/// - Returns: All the attributes of provided type. | ||
func attributes<A: Attribute>(for type: A.Type) -> [A] { | ||
guard | ||
case .choices(let choices) = Self.structure | ||
else { return [] } | ||
|
||
let declSyntaxChoice = choices.first { choice in | ||
if case .node(let type) = choice { | ||
return type is AttributableDeclSyntax.Type | ||
&& self.is(type) | ||
} else { | ||
return false | ||
} | ||
} | ||
|
||
guard | ||
let declSyntaxChoice, | ||
case .node(let declSyntaxType) = declSyntaxChoice, | ||
let declaration = self.as(declSyntaxType), | ||
let declaration = declaration as? AttributableDeclSyntax | ||
else { return [] } | ||
|
||
return declaration.attributes?.compactMap { attribute in | ||
guard case .attribute(let attribute) = attribute else { return nil } | ||
return type.init(from: attribute) | ||
} ?? [] | ||
} | ||
} | ||
|
||
/// A declaration syntax type that supports macro-attribute. | ||
/// | ||
/// This type can check whether an `AttributeSyntax` | ||
/// is for this attribute and perform validation of this attribute usage. | ||
protocol AttributableDeclSyntax: DeclSyntaxProtocol { | ||
/// The list of attributes attached to this declaration. | ||
var attributes: AttributeListSyntax? { get } | ||
} | ||
|
||
extension AccessorDeclSyntax: AttributableDeclSyntax {} | ||
extension ActorDeclSyntax: AttributableDeclSyntax {} | ||
extension AssociatedtypeDeclSyntax: AttributableDeclSyntax {} | ||
extension ClassDeclSyntax: AttributableDeclSyntax {} | ||
extension DeinitializerDeclSyntax: AttributableDeclSyntax {} | ||
extension EditorPlaceholderDeclSyntax: AttributableDeclSyntax {} | ||
extension EnumCaseDeclSyntax: AttributableDeclSyntax {} | ||
extension EnumDeclSyntax: AttributableDeclSyntax {} | ||
extension ExtensionDeclSyntax: AttributableDeclSyntax {} | ||
extension FunctionDeclSyntax: AttributableDeclSyntax {} | ||
extension ImportDeclSyntax: AttributableDeclSyntax {} | ||
extension InitializerDeclSyntax: AttributableDeclSyntax {} | ||
extension MacroDeclSyntax: AttributableDeclSyntax {} | ||
extension MacroExpansionDeclSyntax: AttributableDeclSyntax {} | ||
extension MissingDeclSyntax: AttributableDeclSyntax {} | ||
extension OperatorDeclSyntax: AttributableDeclSyntax {} | ||
extension PrecedenceGroupDeclSyntax: AttributableDeclSyntax {} | ||
extension ProtocolDeclSyntax: AttributableDeclSyntax {} | ||
extension StructDeclSyntax: AttributableDeclSyntax {} | ||
extension SubscriptDeclSyntax: AttributableDeclSyntax {} | ||
extension TypealiasDeclSyntax: AttributableDeclSyntax {} | ||
extension VariableDeclSyntax: AttributableDeclSyntax {} |
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,72 @@ | ||
import SwiftSyntax | ||
import SwiftDiagnostics | ||
import SwiftSyntaxMacros | ||
|
||
/// A type indicating a macro-attribute. | ||
/// | ||
/// This type can check whether an `AttributeSyntax` | ||
/// is for this attribute and perform validation and code generation | ||
/// for this attribute usage. | ||
protocol Attribute: AttachedMacro { | ||
/// The name of this attribute. | ||
static var name: String { get } | ||
/// The syntax used for this attribute instance. | ||
var node: AttributeSyntax { get } | ||
/// 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) | ||
/// Validates this attribute is used properly with the declaration provided. | ||
/// | ||
/// This type checks the attribute usage doesn't violate any conditions | ||
/// and produces diagnostics for such violations in the macro expansion | ||
/// context provided. | ||
/// | ||
/// - Parameters: | ||
/// - declaration: The declaration this macro attribute is attached to. | ||
/// - context: The macro expansion context validation performed in. | ||
/// | ||
/// - Returns: True if attribute usage satisfies all conditions, | ||
/// false otherwise. | ||
@discardableResult | ||
func validate( | ||
declaration: some DeclSyntaxProtocol, | ||
in context: some MacroExpansionContext | ||
) -> Bool | ||
} | ||
|
||
extension Attribute { | ||
/// The name of this attribute. | ||
/// | ||
/// Type name is used as attribute name. | ||
static var name: String { "\(Self.self)" } | ||
/// The name of this attribute. | ||
/// | ||
/// By default type name is used as attribute name. | ||
var name: String { Self.name } | ||
/// The lowercased-name of this attribute. | ||
/// | ||
/// This is used for attribute related diagnostics. | ||
var id: String { name.lowercased() } | ||
|
||
/// Message id for misuse of this attribute. | ||
/// | ||
/// This attribute can must be removed or its usage condition must be satisfied. | ||
var misuseMessageID: MessageID { .messageID("\(id)-misuse") } | ||
/// Message id for unnecessary usage of this attribute. | ||
/// | ||
/// This attribute can be omitted in such scenario and the final result will still be the same. | ||
var unusedMessageID: MessageID { .messageID("\(id)-unused") } | ||
|
||
/// Checks whether this attribute is applied more than once to provided declaration. | ||
/// | ||
/// - Parameter declaration: The declaration this macro attribute is attached to. | ||
/// - Returns: Whether this attribute is applied more than once. | ||
func isDuplicated(in declaration: some SyntaxProtocol) -> Bool { | ||
return declaration.attributes(for: Self.self).count > 1 | ||
} | ||
} |
Oops, something went wrong.