@expo/expo-modules-macros-plugin 0.0.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,6 +39,122 @@ internal func classListArgument(of attribute: AttributeSyntax, label: String) ->
39
39
  return []
40
40
  }
41
41
 
42
+ /**
43
+ Returns true if the class's inheritance clause names any of the given identifiers.
44
+ Matches by base identifier only, so `Module`, `ExpoModulesCore.Module`, and
45
+ `Module<Foo>` all match an entry of "Module".
46
+ */
47
+ internal func inheritsFromAny(_ classDecl: ClassDeclSyntax, names: Set<String>) -> Bool {
48
+ guard let inherited = classDecl.inheritanceClause?.inheritedTypes else {
49
+ return false
50
+ }
51
+ for entry in inherited {
52
+ if let name = baseIdentifier(of: entry.type), names.contains(name) {
53
+ return true
54
+ }
55
+ }
56
+ return false
57
+ }
58
+
59
+ /**
60
+ Returns the rightmost identifier of a type, e.g. `Foo` for `Foo`, `Foo` for
61
+ `Module.Foo`, and nil for composed or generic shapes the macro doesn't need to handle.
62
+ */
63
+ internal func baseIdentifier(of type: TypeSyntax) -> String? {
64
+ if let identifier = type.as(IdentifierTypeSyntax.self) {
65
+ return identifier.name.text
66
+ }
67
+ if let member = type.as(MemberTypeSyntax.self) {
68
+ return member.name.text
69
+ }
70
+ return nil
71
+ }
72
+
73
+ /**
74
+ True if the declaration carries a `@JS` attribute. Works for functions, properties, and inits;
75
+ returns false for any other decl kind.
76
+ */
77
+ internal func memberHasJSAttribute(_ decl: DeclSyntaxProtocol) -> Bool {
78
+ if let funcDecl = decl.as(FunctionDeclSyntax.self) {
79
+ return funcDecl.attributes.firstAttribute(named: "JS") != nil
80
+ }
81
+ if let varDecl = decl.as(VariableDeclSyntax.self) {
82
+ return varDecl.attributes.firstAttribute(named: "JS") != nil
83
+ }
84
+ if let initDecl = decl.as(InitializerDeclSyntax.self) {
85
+ return initDecl.attributes.firstAttribute(named: "JS") != nil
86
+ }
87
+ return false
88
+ }
89
+
90
+ /**
91
+ Decides whether the macro should stamp `@JavaScriptActor` on a `@JS`-marked member.
92
+ The macro defers to the user when they've already chosen an isolation:
93
+ - the `nonisolated` modifier is present on the member
94
+ - any attribute whose name matches a known global actor (`@MainActor`, `@JavaScriptActor`)
95
+ or follows the `*Actor` naming convention is present on the member or its enclosing type
96
+ Async members never get the stamp because `AsyncFunction` controls their dispatch separately.
97
+ */
98
+ internal func shouldStampJavaScriptActor(
99
+ on member: DeclSyntaxProtocol,
100
+ enclosedBy enclosing: some DeclGroupSyntax
101
+ ) -> Bool {
102
+ let modifiers = memberModifiers(of: member)
103
+ if modifiers.contains(where: { $0.name.text == "nonisolated" }) {
104
+ return false
105
+ }
106
+
107
+ if let funcDecl = member.as(FunctionDeclSyntax.self),
108
+ funcDecl.signature.effectSpecifiers?.asyncSpecifier != nil {
109
+ return false
110
+ }
111
+
112
+ let memberAttributes = memberAttributes(of: member)
113
+ if memberAttributes.contains(where: hasGlobalActorShape) {
114
+ return false
115
+ }
116
+
117
+ if enclosing.attributes.contains(where: hasGlobalActorShape) {
118
+ return false
119
+ }
120
+
121
+ return true
122
+ }
123
+
124
+ private func memberModifiers(of decl: DeclSyntaxProtocol) -> DeclModifierListSyntax {
125
+ if let funcDecl = decl.as(FunctionDeclSyntax.self) {
126
+ return funcDecl.modifiers
127
+ }
128
+ if let varDecl = decl.as(VariableDeclSyntax.self) {
129
+ return varDecl.modifiers
130
+ }
131
+ if let initDecl = decl.as(InitializerDeclSyntax.self) {
132
+ return initDecl.modifiers
133
+ }
134
+ return DeclModifierListSyntax()
135
+ }
136
+
137
+ internal func memberAttributes(of decl: DeclSyntaxProtocol) -> AttributeListSyntax {
138
+ if let funcDecl = decl.as(FunctionDeclSyntax.self) {
139
+ return funcDecl.attributes
140
+ }
141
+ if let varDecl = decl.as(VariableDeclSyntax.self) {
142
+ return varDecl.attributes
143
+ }
144
+ if let initDecl = decl.as(InitializerDeclSyntax.self) {
145
+ return initDecl.attributes
146
+ }
147
+ return AttributeListSyntax()
148
+ }
149
+
150
+ private func hasGlobalActorShape(_ element: AttributeListSyntax.Element) -> Bool {
151
+ guard let attribute = element.as(AttributeSyntax.self) else {
152
+ return false
153
+ }
154
+ let name = attribute.attributeName.trimmedDescription
155
+ return name.hasSuffix("Actor")
156
+ }
157
+
42
158
  extension AttributeListSyntax {
43
159
  internal func firstAttribute(named name: String) -> AttributeSyntax? {
44
160
  for element in self {