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 all 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
5 changes: 4 additions & 1 deletion Sources/MacroToolkit/ClassRestrictionType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ public struct ClassRestrictionType: TypeProtocol {
public var _baseSyntax: ClassRestrictionTypeSyntax
public var _attributedSyntax: AttributedTypeSyntax?

public init(_ syntax: ClassRestrictionTypeSyntax, attributedSyntax: AttributedTypeSyntax? = nil) {
public init(
_ syntax: ClassRestrictionTypeSyntax,
attributedSyntax: AttributedTypeSyntax? = nil
) {
_baseSyntax = syntax
_attributedSyntax = attributedSyntax
}
Expand Down
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, RepresentableBySyntax {
/// The underlying syntax node for the `actor` declaration.
public var _syntax: 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) {
_syntax = 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, RepresentableBySyntax {
/// The underlying syntax node for the `class` declaration.
public var _syntax: 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) {
_syntax = syntax
}
}
57 changes: 57 additions & 0 deletions Sources/MacroToolkit/DeclGroup/DeclGroup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import SwiftSyntax

/// An enum that encapsulates various types of declaration groups (`struct`, `class`, `enum`, `actor`, `extension`)
/// and provides a unified interface for interacting with them. This enum conforms to `DeclGroupProtocol`,
/// allowing access to common properties of declaration groups.
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.
///
/// This property is used internally to access the underlying implementation of the declaration group.
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 syntax: 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(_ syntax: DeclGroupSyntax) {
if let syntax = syntax.as(ActorDeclSyntax.self) {
self = .actor(Actor(syntax))
} else if let syntax = syntax.as(ClassDeclSyntax.self) {
self = .class(Class(syntax))
} else if let syntax = syntax.as(EnumDeclSyntax.self) {
self = .enum(Enum(syntax))
} else if let syntax = syntax.as(ExtensionDeclSyntax.self) {
self = .extension(Extension(syntax))
} else if let syntax = syntax.as(StructDeclSyntax.self) {
self = .struct(Struct(syntax))
} else {
fatalError("Unhandled decl group type '\(type(of: syntax))'")
}
}

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

/// All members declared within the declaration group.
public var members: [Decl] { wrapped.members }

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

/// All types that the declaration group inherits from or conforms to.
public var inheritedTypes: [Type] { wrapped.inheritedTypes }
}
64 changes: 64 additions & 0 deletions Sources/MacroToolkit/DeclGroup/DeclGroupProtocol.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import SwiftSyntax

/// A protocol that represents a declaration group, such as a `struct`, `class`, `enum`, or `protocol`.
/// This protocol defines common properties that all declaration groups should have.
public protocol DeclGroupProtocol {
/// The identifier of the declaration group.
var identifier: String { get }

/// All members declared within the declaration group.
var members: [Decl] { get }

/// All properties declared within the declaration group.
var properties: [Property] { get }

/// All types that the declaration group inherits from or conforms to.
var inheritedTypes: [Type] { get }
}

extension DeclGroupProtocol where UnderlyingSyntax: DeclGroupSyntax, Self: RepresentableBySyntax {
/// 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 syntax = syntax as? UnderlyingSyntax else { return nil }
self.init(syntax)
}

public var members: [Decl] {
_syntax.memberBlock.members.map(\.decl).map(Decl.init)
}

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
}
}

public var inheritedTypes: [Type] {
_syntax.inheritanceClause?.inheritedTypes.map(\.type).map(Type.init) ?? []
}

public var accessLevel: AccessModifier? {
AccessModifier(firstModifierOfKindIn: _syntax.modifiers)
}

public var declarationContext: DeclarationContextModifier? {
DeclarationContextModifier(firstModifierOfKindIn: _syntax.modifiers)
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import SwiftSyntax

/// Wraps an `enum` declaration.
public struct Enum: DeclGroupProtocol {
public struct Enum: DeclGroupProtocol, RepresentableBySyntax {
/// The underlying syntax node for the `enum` declaration.
public var _syntax: 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
}
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, RepresentableBySyntax {
/// The underlying syntax node for the `extension` declaration.
public var _syntax: 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) {
_syntax = 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, RepresentableBySyntax {
/// The underlying syntax node for the `struct` declaration.
public var _syntax: 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) {
_syntax = syntax
}
}
71 changes: 0 additions & 71 deletions Sources/MacroToolkit/DeclGroupProtocol.swift

This file was deleted.

3 changes: 2 additions & 1 deletion Sources/MacroToolkit/FunctionParameter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ extension Sequence where Element == FunctionParameter {
let parameters = Array(self)
for (index, parameter) in parameters.enumerated() {
let isLast = index == parameters.count - 1
let syntax = parameter._syntax.with(\.trailingComma, isLast ? nil : TokenSyntax.commaToken())
let syntax = parameter._syntax
.with(\.trailingComma, isLast ? nil : TokenSyntax.commaToken())
list += [syntax]
}
return list
Expand Down
5 changes: 4 additions & 1 deletion Sources/MacroToolkit/ImplicitlyUnwrappedOptionalType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ public struct ImplicitlyUnwrappedOptionalType: TypeProtocol {
public var _baseSyntax: ImplicitlyUnwrappedOptionalTypeSyntax
public var _attributedSyntax: AttributedTypeSyntax?

public init(_ syntax: ImplicitlyUnwrappedOptionalTypeSyntax, attributedSyntax: AttributedTypeSyntax? = nil) {
public init(
_ syntax: ImplicitlyUnwrappedOptionalTypeSyntax,
attributedSyntax: AttributedTypeSyntax? = nil
) {
_baseSyntax = syntax
_attributedSyntax = attributedSyntax
}
Expand Down
Loading