Skip to content

Add Wrappers for Class, Actor, Extension #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 0 additions & 33 deletions Sources/MacroToolkit/DeclGroup.swift

This file was deleted.

19 changes: 19 additions & 0 deletions Sources/MacroToolkit/DeclGroup/Actor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import SwiftSyntax

/// Wraps an `actor` declaration.
public struct Actor: DeclGroupProtocol {
/// The underlying syntax node for the `actor` declaration.
public var rawValue: ActorDeclSyntax

/// The identifier (name) of the `actor`.
public var identifier: String {
_syntax.name.withoutTrivia().text
}

/// Initializes an `Actor` instance with the given syntax node.
///
/// - Parameter syntax: The syntax node representing the `actor` declaration.
public init(_ syntax: ActorDeclSyntax) {
rawValue = syntax
}
}
19 changes: 19 additions & 0 deletions Sources/MacroToolkit/DeclGroup/Class.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import SwiftSyntax

/// Wraps a `class` declaration.
public struct Class: DeclGroupProtocol {
/// The underlying syntax node for the `class` declaration.
public var rawValue: ClassDeclSyntax

/// The identifier (name) of the `class`.
public var identifier: String {
_syntax.name.withoutTrivia().text
}

/// Initializes a `Class` instance with the given syntax node.
///
/// - Parameter syntax: The syntax node representing the `class` declaration.
public init(_ syntax: ClassDeclSyntax) {
rawValue = syntax
}
}
66 changes: 66 additions & 0 deletions Sources/MacroToolkit/DeclGroup/DeclGroup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import SwiftSyntax

/// An enumeration representing different types of declaration groups (e.g., `struct`, `class`, `enum`, `actor`, `extension`).
/// This enum conforms to `DeclGroupProtocol` and wraps specific declaration group types.
public enum DeclGroup: DeclGroupProtocol {
case `struct`(Struct)
case `enum`(Enum)
case `class`(Class)
case actor(Actor)
case `extension`(Extension)

/// A private computed property that returns the wrapped `DeclGroupProtocol` instance.
private var wrapped: any DeclGroupProtocol {
switch self {
case .struct(let wrapped): return wrapped
case .enum(let wrapped): return wrapped
case .class(let wrapped): return wrapped
case .actor(let wrapped): return wrapped
case .extension(let wrapped): return wrapped
}
}

/// Initializes a `DeclGroup` instance from a `DeclGroupSyntax`.
///
/// - Parameter rawValue: The syntax node representing the declaration group.
/// - Note: This initializer will fatalError if the syntax node does not match any known declaration group type.
public init(_ rawValue: any DeclGroupSyntax) {
switch rawValue {
case let syntax as ActorDeclSyntax:
self = .actor(Actor(syntax))
case let syntax as ClassDeclSyntax:
self = .class(Class(syntax))
case let syntax as EnumDeclSyntax:
self = .enum(Enum(syntax))
case let syntax as ExtensionDeclSyntax:
self = .extension(Extension(syntax))
case let syntax as StructDeclSyntax:
self = .struct(Struct(syntax))
default:
fatalError("Unhandled decl group type '\(type(of: rawValue))'")
}
}

/// The underlying syntax node for the declaration group.
public var rawValue: any DeclGroupSyntax {
switch self {
case .struct(let wrapped): return wrapped.rawValue
case .enum(let wrapped): return wrapped.rawValue
case .class(let wrapped): return wrapped.rawValue
case .actor(let wrapped): return wrapped.rawValue
case .extension(let wrapped): return wrapped.rawValue
}
}

/// The identifier of the declaration group.
public var identifier: String { wrapped.identifier }

/// The members of the declaration group.
public var members: [Decl] { wrapped.members }

/// The properties declared in the declaration group.
public var properties: [Property] { wrapped.properties }

/// The types inherited in the declaration group.
public var inheritedTypes: [Type] { wrapped.inheritedTypes }
}
99 changes: 99 additions & 0 deletions Sources/MacroToolkit/DeclGroup/DeclGroupProtocol.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import SwiftSyntax

/// A protocol for declaration groups (e.g., `struct`, `class`, `enum`) that can contain members and properties.
/// Declaration groups are higher-level constructs compared to regular declarations such as `var`.
public protocol DeclGroupProtocol: RawRepresentable {
/// The underlying syntax node for the declaration group.
var rawValue: RawValue { get }

/// The declaration's identifier.
///
/// Note: SwiftSyntax's `DeclGroupSyntax` protocol does not include the declaration's identifier.
/// This must be implemented manually for each declaration wrapper. This omission might be due to
/// the fact that extensions technically do not have a name, even though they are always attached to a specific identifier.
var identifier: String { get }

/// The members of the declaration group.
var members: [Decl] { get }

/// The properties declared in the declaration group.
var properties: [Property] { get }

/// The inherited types of the declaration group.
var inheritedTypes: [Type] { get }

/// Initializes the declaration group with the given syntax node.
///
/// - Parameter syntax: The underlying syntax node representing the declaration group.
init(_ syntax: RawValue)
}

/// Default implementations and helper initializers for `DeclGroupProtocol`.
extension DeclGroupProtocol {
/// The underlying syntax node for the declaration group.
public var _syntax: RawValue {
rawValue
}

/// Initializes the declaration group with the given raw value.
///
/// - Parameter rawValue: The raw value representing the declaration group.
public init?(rawValue: RawValue) {
self.init(rawValue)
}
}

/// Additional functionality for `DeclGroupProtocol` where the raw value conforms to `DeclGroupSyntax`.
extension DeclGroupProtocol where RawValue: DeclGroupSyntax {
/// Attempts to initialize the wrapper from an arbitrary declaration group.
///
/// - Parameter syntax: The syntax node representing the declaration group.
/// - Note: This initializer will return `nil` if the syntax node does not match the expected type.
public init?(_ syntax: any DeclGroupSyntax) {
guard let rawValue = syntax as? RawValue else { return nil }
self.init(rawValue: rawValue)
}

/// The members of the declaration group.
public var members: [Decl] {
_syntax.memberBlock.members.map(\.decl).map(Decl.init)
}

/// The properties declared in the declaration group.
public var properties: [Property] {
members.compactMap(\.asVariable).flatMap { variable in
var bindings = variable._syntax.bindings.flatMap { binding in
Property.properties(from: binding, in: variable)
}
// For the declaration `var a, b: Int` where `a` doesn't have an annotation,
// `a` gets given the type of `b` (`Int`). To implement this, we 'drag' the
// type annotations backwards over the non-annotated bindings.
var lastSeenType: Type?
for (i, binding) in bindings.enumerated().reversed() {
if let type = binding.type {
lastSeenType = type
} else {
bindings[i].type = lastSeenType
}
}
return bindings
}
}

/// The types inherited from or conformed to by the declaration group.
///
/// - Note: This does not include conformances added by other declaration groups such as extensions.
public var inheritedTypes: [Type] {
_syntax.inheritanceClause?.inheritedTypes.map(\.type).map(Type.init) ?? []
}

/// The access level of the declaration group.
public var accessLevel: AccessModifier? {
AccessModifier(modifiers: _syntax.modifiers)
}

/// The context-specific modifiers of the declaration group.
public var declarationContext: DeclarationContextModifier? {
DeclarationContextModifier(modifiers: _syntax.modifiers)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@ import SwiftSyntax

/// Wraps an `enum` declaration.
public struct Enum: DeclGroupProtocol {
public var _syntax: EnumDeclSyntax
/// The underlying syntax node for the `enum` declaration.
public var rawValue: EnumDeclSyntax

/// The identifier (name) of the `enum`.
public var identifier: String {
_syntax.name.withoutTrivia().text
}

/// Initializes an `Enum` instance with the given syntax node.
///
/// - Parameter syntax: The syntax node representing the `enum` declaration.
public init(_ syntax: EnumDeclSyntax) {
_syntax = syntax
rawValue = syntax
}

/// The `enum`'s cases.
Expand Down
19 changes: 19 additions & 0 deletions Sources/MacroToolkit/DeclGroup/Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import SwiftSyntax

/// Wraps an `extension` declaration.
public struct Extension: DeclGroupProtocol {
/// The underlying syntax node for the `extension` declaration.
public var rawValue: ExtensionDeclSyntax

/// The identifier (extended type) of the `extension`.
public var identifier: String {
_syntax.extendedType.withoutTrivia().description
}

/// Initializes an `Extension` instance with the given syntax node.
///
/// - Parameter syntax: The syntax node representing the `extension` declaration.
public init(_ syntax: ExtensionDeclSyntax) {
rawValue = syntax
}
}
19 changes: 19 additions & 0 deletions Sources/MacroToolkit/DeclGroup/Struct.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import SwiftSyntax

/// Wraps a `struct` declaration.
public struct Struct: DeclGroupProtocol {
/// The underlying syntax node for the `struct` declaration.
public var rawValue: StructDeclSyntax

/// The identifier (name) of the `struct`.
public var identifier: String {
_syntax.name.withoutTrivia().text
}

/// Initializes a `Struct` instance with the given syntax node.
///
/// - Parameter syntax: The syntax node representing the `struct` declaration.
public init(_ syntax: StructDeclSyntax) {
rawValue = syntax
}
}
71 changes: 0 additions & 71 deletions Sources/MacroToolkit/DeclGroupProtocol.swift

This file was deleted.

Loading