Skip to content

Commit 867128b

Browse files
authored
Fail Macro Expansion if JavaStaticField is used in non-class (#174)
1 parent 0c57644 commit 867128b

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

Sources/JavaKitMacros/JavaFieldMacro.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ extension JavaFieldMacro: AccessorMacro {
3333
return []
3434
}
3535

36+
let isStatic = node.attributeName.trimmedDescription == "JavaStaticField"
37+
guard !isStatic || isInJavaClassContext(context: context) else {
38+
throw MacroExpansionErrorMessage("Cannot use @JavaStaticField outside of a JavaClass instance")
39+
}
40+
3641
// Dig out the Java field name, if provided. Otherwise, use the name as written.
3742
let fieldName =
3843
if case .argumentList(let arguments) = node.arguments,
@@ -79,4 +84,14 @@ extension JavaFieldMacro: AccessorMacro {
7984

8085
return accessors
8186
}
87+
88+
private static func isInJavaClassContext(context: some MacroExpansionContext) -> Bool {
89+
for lexicalContext in context.lexicalContext {
90+
if let classSyntax = lexicalContext.as(ExtensionDeclSyntax.self) {
91+
return classSyntax.extendedType.trimmedDescription.starts(with: "JavaClass")
92+
}
93+
}
94+
95+
return false
96+
}
8297
}

Tests/JavaKitMacroTests/JavaClassMacroTests.swift

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,64 @@ class JavaKitMacroTests: XCTestCase {
2323
static let javaKitMacros: [String: any Macro.Type] = [
2424
"JavaClass": JavaClassMacro.self,
2525
"JavaMethod": JavaMethodMacro.self,
26-
"JavaField": JavaFieldMacro.self
26+
"JavaField": JavaFieldMacro.self,
27+
"JavaStaticField": JavaFieldMacro.self
2728
]
2829

30+
func testJavaStaticMethodFailure() throws {
31+
assertMacroExpansion(
32+
"""
33+
@JavaClass("org.swift.example.HelloWorld")
34+
public class HelloWorld {
35+
@JavaStaticField
36+
public var test: String
37+
}
38+
""",
39+
expandedSource: """
40+
41+
public class HelloWorld {
42+
public var test: String
43+
44+
/// The full Java class name for this Swift type.
45+
open override class var fullJavaClassName: String {
46+
"org.swift.example.HelloWorld"
47+
}
48+
49+
public required init(javaHolder: JavaObjectHolder) {
50+
super.init(javaHolder: javaHolder)
51+
}
52+
}
53+
""",
54+
diagnostics: [DiagnosticSpec(message: "Cannot use @JavaStaticField outside of a JavaClass instance", line: 3, column: 5)],
55+
macros: Self.javaKitMacros
56+
)
57+
}
58+
59+
func testJavaStaticMethodSuccess() throws {
60+
assertMacroExpansion(
61+
"""
62+
extension JavaClass<HelloWorld> {
63+
@JavaStaticField
64+
public var test: String
65+
}
66+
""",
67+
expandedSource: """
68+
69+
extension JavaClass<HelloWorld> {
70+
public var test: String {
71+
get {
72+
self[javaFieldName: "test", fieldType: String.self]
73+
}
74+
set {
75+
self[javaFieldName: "test", fieldType: String.self] = newValue
76+
}
77+
}
78+
}
79+
""",
80+
macros: Self.javaKitMacros
81+
)
82+
}
83+
2984
func testJavaClass() throws {
3085
assertMacroExpansion("""
3186
@JavaClass("org.swift.example.HelloWorld")

0 commit comments

Comments
 (0)