Skip to content

Commit

Permalink
experimenting with @signal macro
Browse files Browse the repository at this point in the history
  • Loading branch information
samdeane committed Dec 6, 2024
1 parent ac3dc30 commit 1e42792
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Sources/SwiftGodot/MacroDefs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,8 @@ public macro signal(_ signalName: String, arguments: Dictionary<String, Any.Type
@freestanding(declaration, names: arbitrary)
public macro nusignal(_ signalName: String, arguments: [String: Any.Type] = [:]) = #externalMacro(module: "SwiftGodotMacroLibrary", type: "NuSignalMacro")

@attached(accessor)
public macro Signal() = #externalMacro(module: "SwiftGodotMacroLibrary", type: "NuSignalMacro2")


#endif
1 change: 1 addition & 0 deletions Sources/SwiftGodotMacroLibrary/MacroGodot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,7 @@ struct godotMacrosPlugin: CompilerPlugin {
Texture2DLiteralMacro.self,
SignalMacro.self,
NuSignalMacro.self,
NuSignalMacro2.self,
]
}

Expand Down
91 changes: 91 additions & 0 deletions Sources/SwiftGodotMacroLibrary/NuSignalMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,94 @@ public struct NuSignalMacro: DeclarationMacro {
}

}


public struct NuSignalMacro2: AccessorMacro {

enum ProviderDiagnostic: Error, DiagnosticMessage {
case invalidDeclaration
case missingTypeAnnotation

var severity: DiagnosticSeverity { .error }

var message: String {
switch self {
case .invalidDeclaration:
"Signal can only be applied to stored properties"
case .missingTypeAnnotation:
"SceneTree requires an explicit type declaration"
}
}

var diagnosticID: MessageID {
MessageID(domain: "SwiftGodotMacros", id: message)
}
}

public static func expansion(of node: AttributeSyntax,
providingAccessorsOf declaration: some DeclSyntaxProtocol,
in context: some MacroExpansionContext) throws -> [AccessorDeclSyntax]
{
guard let varDecl = declaration.as(VariableDeclSyntax.self) else {
let invalidUsageErr = Diagnostic(node: node.root, message: ProviderDiagnostic.invalidDeclaration)
context.diagnose(invalidUsageErr)
return []
}

guard let signalType = varDecl.bindings.first?.typeAnnotation?.type else {
let missingAnnotationErr = Diagnostic(node: node.root, message: ProviderDiagnostic.missingTypeAnnotation)
context.diagnose(missingAnnotationErr)
return []
}

guard let nodeIdentifier = varDecl.bindings.first?.pattern.as(IdentifierPatternSyntax.self)?.identifier else {
fatalError("No identifier for this expression could be found.")
}

var signalName = SignalName(godotName: nodeIdentifier.text.camelCaseToSnakeCase(), swiftName: nodeIdentifier.text)
var arguments = [(name: String, type: String)]()

// for (index, argument) in node.arguments {
// if index == 0 {
// signalName = argument.expression.signalName()
// }
// if index == 1 {
// if argument.expression.description == ".init()" {
// // its an empty dictionary, so no arguments
// continue
// }
//
// guard let dictSyntax = DictionaryExprSyntax(argument.expression) else {
// throw ProviderDiagnostic.argumentsInUnexpectedSyntax
// }
//
// if case .colon = dictSyntax.content {
// // its an empty dictionary, so no arguments
// continue
// }
//
// guard let pairList = DictionaryElementListSyntax(dictSyntax.content) else {
// throw ProviderDiagnostic.argumentsInUnexpectedSyntax
// }
//
// for pair in pairList {
// guard let typeName = pair.value.typeName() else {
// throw ProviderDiagnostic.argumentsInUnexpectedSyntax
// }
// arguments.append((pair.key.description, typeName))
// }
// }
// }

// let genericTypeList = arguments.map { $0.type }.joined(separator: ", ")
//
// let signalWrapperType = arguments.isEmpty ? "GenericSignal< /* no args */ >" : "GenericSignal<\(genericTypeList)>"

return [
"""
get { \(raw: signalType)(target: self, signalName: \"\(raw: signalName.godotName)\") }
"""
]
}

}
16 changes: 15 additions & 1 deletion Tests/SwiftGodotTests/SignalTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import SwiftGodotTestability
private class TestSignalNode: Node {
#signal("mySignal", arguments: ["age": Int.self, "name": String.self])
#nusignal("nuSignal", arguments: ["age": Int.self, "name": String.self])
@Signal var anotherSignal: GenericSignal< /* no args */ >
var receivedInt: Int? = nil
var receivedString: String? = nil
Expand All @@ -32,7 +33,7 @@ final class SignalTests: GodotTestCase {
}

func testNuSignal() {
let node = TestNode()
let node = TestSignalNode()
var signalReceived = false

node.nuSignal.connect { age, name in
Expand All @@ -44,6 +45,19 @@ final class SignalTests: GodotTestCase {
XCTAssertTrue (signalReceived, "signal should have been received")
}

func testNuSignal2() {
let node = TestSignalNode()
var signalReceived = false

node.nuSignal.connect { age, name in
XCTAssertEqual (age, 22)
XCTAssertEqual (name, "Sam")
signalReceived = true
}
node.nuSignal.emit(22, "Sam")
XCTAssertTrue (signalReceived, "signal should have been received")
}

func testBuiltInSignalWithNoArgument() {
let node = Node()
var signalReceived = false
Expand Down

0 comments on commit 1e42792

Please sign in to comment.