Skip to content
Closed
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
4 changes: 4 additions & 0 deletions MacroExamples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
46A18274294F539400217140 /* PrintArgumentsMacro.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46A18273294F539400217140 /* PrintArgumentsMacro.swift */; };
BD752BE5294D3BEC00D00A2E /* WarningMacro.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD752BE4294D3BEC00D00A2E /* WarningMacro.swift */; };
BD752BE7294D461B00D00A2E /* FontLiteralMacro.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD752BE6294D461B00D00A2E /* FontLiteralMacro.swift */; };
BD841F82294CE1F600DA4D81 /* AddBlocker.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD841F81294CE1F600DA4D81 /* AddBlocker.swift */; };
Expand Down Expand Up @@ -62,6 +63,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
46A18273294F539400217140 /* PrintArgumentsMacro.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrintArgumentsMacro.swift; sourceTree = "<group>"; };
BD752BE4294D3BEC00D00A2E /* WarningMacro.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WarningMacro.swift; sourceTree = "<group>"; };
BD752BE6294D461B00D00A2E /* FontLiteralMacro.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontLiteralMacro.swift; sourceTree = "<group>"; };
BD841F81294CE1F600DA4D81 /* AddBlocker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddBlocker.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -116,6 +118,7 @@
BD841F81294CE1F600DA4D81 /* AddBlocker.swift */,
BD752BE4294D3BEC00D00A2E /* WarningMacro.swift */,
BD752BE6294D461B00D00A2E /* FontLiteralMacro.swift */,
46A18273294F539400217140 /* PrintArgumentsMacro.swift */,
);
path = MacroExamplesPlugin;
sourceTree = "<group>";
Expand Down Expand Up @@ -352,6 +355,7 @@
files = (
BD841F82294CE1F600DA4D81 /* AddBlocker.swift in Sources */,
BD752BE5294D3BEC00D00A2E /* WarningMacro.swift in Sources */,
46A18274294F539400217140 /* PrintArgumentsMacro.swift in Sources */,
BDF5AFF82947E95C00FA119B /* StringifyMacro.swift in Sources */,
BD752BE7294D461B00D00A2E /* FontLiteralMacro.swift in Sources */,
);
Expand Down
7 changes: 7 additions & 0 deletions MacroExamples/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@ struct Font: ExpressibleByFontLiteral {
}

let font: Font = #fontLiteral(name: "Comic Sans", size: 14, weight: .thin)

func doSomething(_ a: Int, b: Int, c d: Int, e _: Int, _: Int, _ _: Int) {
#printArguments()
}

// Prints doSomething(42, b: 256, c: 512, e: _, _, _)
doSomething(42, b: 256, c: 512, e: 600, 1024, 2048)
3 changes: 3 additions & 0 deletions MacroExamplesLib/Macros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ public protocol ExpressibleByFontLiteral {
/// Font literal similar to, e.g., #colorLiteral.
public macro fontLiteral<T>(name: String, size: Int, weight: FontWeight) -> T = MacroExamplesPlugin.FontLiteralMacro
where T: ExpressibleByFontLiteral

/// Can be called inside a function to print the function name and arguments.
public macro printArguments() = MacroExamplesPlugin.PrintArgumentsMacro
49 changes: 49 additions & 0 deletions MacroExamplesPlugin/PrintArgumentsMacro.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// PrintArgumentsMacro.swift
// MacroExamplesPlugin
//
// Created by Stephen Kockentiedt on 18.12.22.
//

import SwiftSyntax
import SwiftSyntaxBuilder
import _SwiftSyntaxMacros

public struct PrintArgumentsMacro: ExpressionMacro {
public static func expansion(
of node: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
) -> ExprSyntax {
var syntax = node.as(Syntax.self)
while syntax != nil && syntax!.as(FunctionDeclSyntax.self) == nil {
syntax = syntax!.parent
Copy link
Owner

Choose a reason for hiding this comment

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

Now that macro implementations are getting "detached" nodes, the parent of the main syntax node will always be nil, so #printArguments will always return the empty string.

Copy link
Author

Choose a reason for hiding this comment

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

That's a little unfortunate. So the solution of providing a 'spine' of the hierarchy is not the way to go?

}

guard let functionSyntax = syntax!.as(FunctionDeclSyntax.self) else { return "" }
let signature: FunctionSignatureSyntax = functionSyntax.signature
let parameterList = signature.input.parameterList

// For a function `doSomething(_ a: Int, b: String, c: Double)`, the expanded epression shall be `print("doSomething(\(a), b: \(b), c: \(c))")`

let parameters = parameterList.map { parameter -> String in
let potentialLabel = parameter.firstName!.withoutTrivia().description
let label = potentialLabel == "_" ? nil : potentialLabel
let potentialName = parameter.secondName?.withoutTrivia().description ?? potentialLabel
let name = potentialName == "_" ? nil : potentialName
var string: String
if let label {
string = "\(label): "
} else {
string = ""
}
if let name {
string += "\\(\(name))"
} else {
string += "_"
}
return string
}
let parametersString = parameters.joined(separator: ", ")

return "print(\"\(raw: functionSyntax.identifier.description)(\(raw: parametersString))\")"
}
}