@@ -123,10 +123,12 @@ class ExportSwift {
123123 }
124124
125125 private func visitFunction( node: FunctionDeclSyntax ) -> ExportedFunction ? {
126- guard node. attributes. hasJSAttribute ( ) else {
126+ guard let jsAttribute = node. attributes. firstJSAttribute else {
127127 return nil
128128 }
129- let name = node. name. text
129+
130+ let ( baseName, namespace) = extractNameAndNamespace ( from: node, jsAttribute: jsAttribute)
131+
130132 var parameters : [ Parameter ] = [ ]
131133 for param in node. signature. parameterClause. parameters {
132134 guard let type = self . parent. lookupType ( for: param. type) else {
@@ -151,21 +153,22 @@ class ExportSwift {
151153 let abiName : String
152154 switch state {
153155 case . topLevel:
154- abiName = " bjs_ \( name ) "
156+ abiName = " bjs_ \( baseName ) "
155157 case . classBody( let className) :
156- abiName = " bjs_ \( className) _ \( name ) "
158+ abiName = " bjs_ \( className) _ \( baseName ) "
157159 }
158160
159161 guard let effects = collectEffects ( signature: node. signature) else {
160162 return nil
161163 }
162164
163165 return ExportedFunction (
164- name: name ,
166+ name: baseName ,
165167 abiName: abiName,
166168 parameters: parameters,
167169 returnType: returnType,
168- effects: effects
170+ effects: effects,
171+ namespace: namespace
169172 )
170173 }
171174
@@ -192,6 +195,19 @@ class ExportSwift {
192195 }
193196 return Effects ( isAsync: isAsync, isThrows: isThrows)
194197 }
198+
199+ private func extractNameAndNamespace(
200+ from node: FunctionDeclSyntax ,
201+ jsAttribute: AttributeSyntax
202+ ) -> ( name: String , namespace: [ String ] ? ) {
203+ guard let arguments = jsAttribute. arguments? . as ( LabeledExprListSyntax . self) ,
204+ let firstArg = arguments. first? . expression. as ( StringLiteralExprSyntax . self) ,
205+ let namespaceString = firstArg. segments. first? . as ( StringSegmentSyntax . self) ? . content. text else {
206+ return ( node. name. text, nil )
207+ }
208+ let namespaces = namespaceString. split ( separator: " . " ) . map ( String . init)
209+ return ( node. name. text, namespaces)
210+ }
195211
196212 override func visit( _ node: InitializerDeclSyntax ) -> SyntaxVisitorContinueKind {
197213 guard node. attributes. hasJSAttribute ( ) else { return . skipChildren }
@@ -227,11 +243,13 @@ class ExportSwift {
227243 let name = node. name. text
228244 stateStack. push ( state: . classBody( name: name) )
229245
230- guard node. attributes. hasJSAttribute ( ) else { return . skipChildren }
246+ guard let jsAttribute = node. attributes. firstJSAttribute else { return . skipChildren }
247+
231248 exportedClassByName [ name] = ExportedClass (
232249 name: name,
233250 constructor: nil ,
234- methods: [ ]
251+ methods: [ ] ,
252+ namespace: nil
235253 )
236254 exportedClassNames. append ( name)
237255 return . visitChildren
@@ -635,9 +653,13 @@ class ExportSwift {
635653
636654extension AttributeListSyntax {
637655 fileprivate func hasJSAttribute( ) -> Bool {
638- return first ( where: {
656+ firstJSAttribute != nil
657+ }
658+
659+ fileprivate var firstJSAttribute : AttributeSyntax ? {
660+ first ( where: {
639661 $0. as ( AttributeSyntax . self) ? . attributeName. trimmedDescription == " JS "
640- } ) != nil
662+ } ) ? . as ( AttributeSyntax . self )
641663 }
642664}
643665
0 commit comments