From 760c3e5449c1cb7b539756d6a9d9e7024409153f Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Sat, 9 Nov 2024 11:36:26 -0500 Subject: [PATCH 1/4] Start field --- Sources/JavaKitMacros/JavaFieldMacro.swift | 19 +++++++++++++++++++ .../JavaClassMacroTests.swift | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index 7f60f26d..a3679aee 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -33,6 +33,11 @@ extension JavaFieldMacro: AccessorMacro { return [] } + let isStatic = node.attributeName.trimmedDescription == "JavaStaticMethod" + guard !isStatic || isInStaticContext(context: context) else { + throw MacroExpansionErrorMessage("Cannot use @JavaStaticMethod outside of a JavaClass instance") + } + // Dig out the Java field name, if provided. Otherwise, use the name as written. let fieldName = if case .argumentList(let arguments) = node.arguments, @@ -79,4 +84,18 @@ extension JavaFieldMacro: AccessorMacro { return accessors } + + private static func isInStaticContext(context: some MacroExpansionContext) -> Bool { + for lexicalContext in context.lexicalContext { + if let classSyntax = lexicalContext.as(StructDeclSyntax.self) { + if classSyntax.name.trimmedDescription.starts(with: "JavaClass") { + return true + } else { + return false + } + } + } + + return false + } } diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index e639800b..f235efcc 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -26,6 +26,25 @@ class JavaKitMacroTests: XCTestCase { "JavaField": JavaFieldMacro.self ] + func testJavaStaticMethodFailure() throws { + assertMacroExpansion( + """ + @JavaClass("org.swift.example.HelloWorld") + public struct HelloWorld { + @JavaStaticMethod + public init(environment: JNIEnvironment? = nil) + } + """, + expandedSource: """ + + public struct HelloWorld { + } + """, + diagnostics: [DiagnosticSpec(message: "", line: 0, column: 0)], + macros: Self.javaKitMacros + ) + } + func testJavaClass() throws { assertMacroExpansion(""" @JavaClass("org.swift.example.HelloWorld") From d56bb3d302c17afccb63b2f4df49be97a21aa6b2 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Sat, 9 Nov 2024 11:54:47 -0500 Subject: [PATCH 2/4] Update Text --- Sources/JavaKitMacros/JavaFieldMacro.swift | 8 +++--- .../JavaClassMacroTests.swift | 25 +++++++++++++------ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index a3679aee..a6271c58 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -33,9 +33,9 @@ extension JavaFieldMacro: AccessorMacro { return [] } - let isStatic = node.attributeName.trimmedDescription == "JavaStaticMethod" + let isStatic = node.attributeName.trimmedDescription == "JavaStaticField" guard !isStatic || isInStaticContext(context: context) else { - throw MacroExpansionErrorMessage("Cannot use @JavaStaticMethod outside of a JavaClass instance") + throw MacroExpansionErrorMessage("Cannot use @JavaStaticField outside of a JavaClass instance") } // Dig out the Java field name, if provided. Otherwise, use the name as written. @@ -87,8 +87,8 @@ extension JavaFieldMacro: AccessorMacro { private static func isInStaticContext(context: some MacroExpansionContext) -> Bool { for lexicalContext in context.lexicalContext { - if let classSyntax = lexicalContext.as(StructDeclSyntax.self) { - if classSyntax.name.trimmedDescription.starts(with: "JavaClass") { + if let classSyntax = lexicalContext.as(ClassDeclSyntax.self) { + if classSyntax.name.trimmedDescription.starts(with: "JavaClass<") { return true } else { return false diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index f235efcc..c93648d7 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -23,24 +23,35 @@ class JavaKitMacroTests: XCTestCase { static let javaKitMacros: [String: any Macro.Type] = [ "JavaClass": JavaClassMacro.self, "JavaMethod": JavaMethodMacro.self, - "JavaField": JavaFieldMacro.self + "JavaField": JavaFieldMacro.self, + "JavaStaticField": JavaFieldMacro.self ] func testJavaStaticMethodFailure() throws { assertMacroExpansion( """ @JavaClass("org.swift.example.HelloWorld") - public struct HelloWorld { - @JavaStaticMethod - public init(environment: JNIEnvironment? = nil) + public class HelloWorld { + @JavaStaticField + public var test: String } """, expandedSource: """ - - public struct HelloWorld { + + public class HelloWorld { + public var test: String + + /// The full Java class name for this Swift type. + open override class var fullJavaClassName: String { + "org.swift.example.HelloWorld" + } + + public required init(javaHolder: JavaObjectHolder) { + super.init(javaHolder: javaHolder) + } } """, - diagnostics: [DiagnosticSpec(message: "", line: 0, column: 0)], + diagnostics: [DiagnosticSpec(message: "Cannot use @JavaStaticField outside of a JavaClass instance", line: 3, column: 5)], macros: Self.javaKitMacros ) } From b0d2fca81145be45290376c113750e75e27426b4 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Thu, 14 Nov 2024 21:57:56 -0500 Subject: [PATCH 3/4] Fix macro to use extension --- Sources/JavaKitMacros/JavaFieldMacro.swift | 12 +++------ .../JavaClassMacroTests.swift | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index a6271c58..1ab31cab 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -34,7 +34,7 @@ extension JavaFieldMacro: AccessorMacro { } let isStatic = node.attributeName.trimmedDescription == "JavaStaticField" - guard !isStatic || isInStaticContext(context: context) else { + guard !isStatic || isInJavaClassContext(context: context) else { throw MacroExpansionErrorMessage("Cannot use @JavaStaticField outside of a JavaClass instance") } @@ -85,14 +85,10 @@ extension JavaFieldMacro: AccessorMacro { return accessors } - private static func isInStaticContext(context: some MacroExpansionContext) -> Bool { + private static func isInJavaClassContext(context: some MacroExpansionContext) -> Bool { for lexicalContext in context.lexicalContext { - if let classSyntax = lexicalContext.as(ClassDeclSyntax.self) { - if classSyntax.name.trimmedDescription.starts(with: "JavaClass<") { - return true - } else { - return false - } + if let classSyntax = lexicalContext.as(ExtensionDeclSyntax.self) { + return classSyntax.extendedType.trimmedDescription.starts(with: "JavaClass<") } } diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index c93648d7..1dc08ba8 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -56,6 +56,31 @@ class JavaKitMacroTests: XCTestCase { ) } + func testJavaStaticMethodSuccess() throws { + assertMacroExpansion( + """ + extension JavaClass { + @JavaStaticField + public var test: String + } + """, + expandedSource: """ + + extension JavaClass { + public var test: String { + get { + self[javaFieldName: "test", fieldType: String.self] + } + set { + self[javaFieldName: "test", fieldType: String.self] = newValue + } + } + } + """, + macros: Self.javaKitMacros + ) + } + func testJavaClass() throws { assertMacroExpansion(""" @JavaClass("org.swift.example.HelloWorld") From 3f437c3965af0d0a93366766a52f86d1c807f738 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Thu, 14 Nov 2024 22:08:44 -0500 Subject: [PATCH 4/4] This doesn't work for class itself --- Sources/JavaKitMacros/JavaFieldMacro.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index 1ab31cab..29eb966c 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -88,7 +88,7 @@ extension JavaFieldMacro: AccessorMacro { private static func isInJavaClassContext(context: some MacroExpansionContext) -> Bool { for lexicalContext in context.lexicalContext { if let classSyntax = lexicalContext.as(ExtensionDeclSyntax.self) { - return classSyntax.extendedType.trimmedDescription.starts(with: "JavaClass<") + return classSyntax.extendedType.trimmedDescription.starts(with: "JavaClass") } }