Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
4 changes: 2 additions & 2 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 8 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ let package = Package(
name: "ExtractCaseValue",
targets: ["ExtractCaseValue"]
),
.library(name: "ExtractCaseValueTypes", targets: ["ExtractCaseValueTypes"]),
.executable(
name: "ExtractCaseValueClient",
targets: ["ExtractCaseValueClient"]
),
],
dependencies: [
// Depend on the latest Swift 5.9 prerelease of SwiftSyntax
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0-swift-5.9-DEVELOPMENT-SNAPSHOT-2023-04-25-b")
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0-swift-DEVELOPMENT-SNAPSHOT-2023-08-28-a")
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
Expand All @@ -30,12 +31,16 @@ let package = Package(
name: "ExtractCaseValueMacros",
dependencies: [
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
"ExtractCaseValueTypes"
]
),

// Library that exposes a macro as part of its API, which is used in client programs.
.target(name: "ExtractCaseValue", dependencies: ["ExtractCaseValueMacros"]),
.target(name: "ExtractCaseValue", dependencies: ["ExtractCaseValueMacros", "ExtractCaseValueTypes"]),
.target(name: "ExtractCaseValueTypes", dependencies: [
.product(name: "SwiftSyntax", package: "swift-syntax"),
]),

// A client of the library, which is able to use the macro in its own code.
.executableTarget(name: "ExtractCaseValueClient", dependencies: ["ExtractCaseValue"]),
Expand Down
4 changes: 3 additions & 1 deletion Sources/ExtractCaseValue/ExtractCaseValue.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import ExtractCaseValueMacros

//import ExtractCaseValueMacros
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should remove this line

import ExtractCaseValueTypes

/// A macro that extracts an associated value from enum cases using a default value if
/// extraction is not possible.
Expand Down
53 changes: 20 additions & 33 deletions Sources/ExtractCaseValueMacros/CaseExtractionKind.swift
Original file line number Diff line number Diff line change
@@ -1,40 +1,27 @@
import SwiftSyntax

/// The available kinds of case value extractions.
public enum CaseExtractionKind {
/// Extract a value at a position in the associated values.
case position(Int)

/// Extract a value with a certain name.
case associatedValueName(String)

/// Extract the first value with a matching type.
case firstMatchingType

public static let `default` = Self.firstMatchingType
}
import ExtractCaseValueTypes

extension CaseExtractionKind {
init?(expr: ExprSyntax) {
guard
let functionCall = expr.as(FunctionCallExprSyntax.self),
let memberAccessExpr = functionCall.calledExpression.as(MemberAccessExprSyntax.self)
else { return nil }
init?(expr: ExprSyntax) {
guard
let functionCall = expr.as(FunctionCallExprSyntax.self),
let memberAccessExpr = functionCall.calledExpression.as(MemberAccessExprSyntax.self)
else { return nil }

let firstIntArgument = (functionCall.argumentList.first?.expression.as(IntegerLiteralExprSyntax.self)?.digits.text).flatMap(Int.init)
let firstStringArgument = functionCall.argumentList.first?.expression.stringLiteralSegment
let firstIntArgument = (functionCall.argumentList.first?.expression.as(IntegerLiteralExprSyntax.self)?.digits.text).flatMap(Int.init)
let firstStringArgument = functionCall.argumentList.first?.expression.stringLiteralSegment

switch memberAccessExpr.name.text {
case "position" :
guard let position = firstIntArgument else { return nil }
self = .position(position)
case "associatedValueName":
guard let name = firstStringArgument?.content.text else { return nil }
self = .associatedValueName(name)
case "firstMatchingType":
self = .firstMatchingType
default:
return nil
switch memberAccessExpr.name.text {
case "position" :
guard let position = firstIntArgument else { return nil }
self = .position(position)
case "associatedValueName":
guard let name = firstStringArgument?.content.text else { return nil }
self = .associatedValueName(name)
case "firstMatchingType":
self = .firstMatchingType
default:
return nil
}
}
}
}
3 changes: 2 additions & 1 deletion Sources/ExtractCaseValueMacros/ExtractCaseValueMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import SwiftDiagnostics
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros
import ExtractCaseValueTypes

// Argument labels
let caseParamExtractionPropertyNameArgumentLabel = "name"
Expand Down Expand Up @@ -98,7 +99,7 @@ extension ExtractCaseValueMacro: MemberMacro {
let elements = caseDecls.flatMap(\.elements)

// infer access modifier from enum
let access = enumDecl.modifiers?.first(where: \.isNeededAccessLevelModifier)
let access = enumDecl.modifiers.first(where: \.isNeededAccessLevelModifier)

var switchCaseSyntaxes: [SwitchCaseSyntax] = []

Expand Down
23 changes: 23 additions & 0 deletions Sources/ExtractCaseValueTypes/CaseExtractionKind.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// CaseExtractionKind.swift
//
//
// Created by Tomas Harkema on 02/09/2023.
//

import Foundation

/// The available kinds of case value extractions.
public enum CaseExtractionKind {
/// Extract a value at a position in the associated values.
case position(Int)

/// Extract a value with a certain name.
case associatedValueName(String)

/// Extract the first value with a matching type.
case firstMatchingType

public static let `default` = Self.firstMatchingType
}