@@ -1266,10 +1266,56 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
12661266 returnType: returnType,
12671267 effects: effects,
12681268 namespace: finalNamespace,
1269- staticContext: staticContext
1269+ staticContext: staticContext,
1270+ documentation: extractDocumentation ( from: node)
12701271 )
12711272 }
12721273
1274+ /// Returns the doc comment (`///` or `/** */`) attached to a declaration, with
1275+ /// markers stripped and DocC field lists (`- Parameters:`, `- Returns:`) preserved.
1276+ private func extractDocumentation( from node: some SyntaxProtocol ) -> String ? {
1277+ var run : [ String ] = [ ]
1278+ for piece in node. leadingTrivia {
1279+ switch piece {
1280+ case . docLineComment( let text) :
1281+ var line = Substring ( text)
1282+ if line. hasPrefix ( " /// " ) { line = line. dropFirst ( 3 ) }
1283+ if line. first == " " { line = line. dropFirst ( ) }
1284+ if line. last == " \r " { line = line. dropLast ( ) }
1285+ run. append ( String ( line) )
1286+ case . docBlockComment( let text) :
1287+ run. append ( contentsOf: stripBlockComment ( text) )
1288+ case . newlines( let count) , . carriageReturns( let count) , . carriageReturnLineFeeds( let count) :
1289+ if count >= 2 { run. removeAll ( ) }
1290+ case . lineComment, . blockComment:
1291+ run. removeAll ( )
1292+ default :
1293+ continue
1294+ }
1295+ }
1296+ // Trim boundary blank lines so line (`///`) and block (`/** */`) comments
1297+ // produce a consistent skeleton value.
1298+ while run. first? . trimmingCharacters ( in: . whitespaces) . isEmpty == true { run. removeFirst ( ) }
1299+ while run. last? . trimmingCharacters ( in: . whitespaces) . isEmpty == true { run. removeLast ( ) }
1300+ return run. isEmpty ? nil : run. joined ( separator: " \n " )
1301+ }
1302+
1303+ private func stripBlockComment( _ text: String ) -> [ String ] {
1304+ var body = Substring ( text)
1305+ if body. hasPrefix ( " /**") { body = body.dropFirst(3) }
1306+ if body.hasSuffix("*/" ) { body = body. dropLast ( 2 ) }
1307+ return body. split ( separator: " \n " , omittingEmptySubsequences: false ) . map { raw -> String in
1308+ var line = raw [ ... ]
1309+ if line. last == " \r " { line = line. dropLast ( ) }
1310+ while let first = line. first, first == " " || first == " \t " { line = line. dropFirst ( ) }
1311+ if line. first == " * " {
1312+ line = line. dropFirst ( )
1313+ if line. first == " " { line = line. dropFirst ( ) }
1314+ }
1315+ return String ( line)
1316+ }
1317+ }
1318+
12731319 private func collectEffects( signature: FunctionSignatureSyntax , isStatic: Bool = false ) -> Effects ? {
12741320 let isAsync = signature. effectSpecifiers? . asyncSpecifier != nil
12751321 var isThrows = false
@@ -1360,7 +1406,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
13601406 let constructor = ExportedConstructor (
13611407 abiName: " bjs_ \( classAbiName) _init " ,
13621408 parameters: parameters,
1363- effects: effects
1409+ effects: effects,
1410+ documentation: extractDocumentation ( from: node)
13641411 )
13651412 exportedClassByName [ classKey] ? . constructor = constructor
13661413
@@ -1383,7 +1430,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
13831430 let constructor = ExportedConstructor (
13841431 abiName: " bjs_ \( structAbiName) _init " ,
13851432 parameters: parameters,
1386- effects: effects
1433+ effects: effects,
1434+ documentation: extractDocumentation ( from: node)
13871435 )
13881436 exportedStructByName [ structKey] ? . constructor = constructor
13891437
@@ -1490,7 +1538,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
14901538 isReadonly: isReadonly,
14911539 isStatic: isStatic,
14921540 namespace: finalNamespace,
1493- staticContext: staticContext
1541+ staticContext: staticContext,
1542+ documentation: extractDocumentation ( from: node)
14941543 )
14951544
14961545 if case . enumBody( _, let key) = state {
@@ -1537,7 +1586,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
15371586 methods: [ ] ,
15381587 properties: [ ] ,
15391588 namespace: effectiveNamespace,
1540- identityMode: classIdentityMode
1589+ identityMode: classIdentityMode,
1590+ documentation: extractDocumentation ( from: node)
15411591 )
15421592 let uniqueKey = makeKey ( name: name, namespace: effectiveNamespace)
15431593
@@ -1657,7 +1707,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
16571707 namespace: effectiveNamespace,
16581708 emitStyle: emitStyle,
16591709 staticMethods: [ ] ,
1660- staticProperties: [ ]
1710+ staticProperties: [ ] ,
1711+ documentation: extractDocumentation ( from: node)
16611712 )
16621713
16631714 let enumUniqueKey = makeKey ( name: name, namespace: effectiveNamespace)
@@ -1774,7 +1825,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
17741825 name: name,
17751826 methods: [ ] ,
17761827 properties: [ ] ,
1777- namespace: effectiveNamespace
1828+ namespace: effectiveNamespace,
1829+ documentation: extractDocumentation ( from: node)
17781830 )
17791831
17801832 stateStack. push ( state: . protocolBody( name: name, key: protocolUniqueKey) )
@@ -1798,7 +1850,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
17981850 name: name,
17991851 methods: methods,
18001852 properties: exportedProtocolByName [ protocolUniqueKey] ? . properties ?? [ ] ,
1801- namespace: effectiveNamespace
1853+ namespace: effectiveNamespace,
1854+ documentation: extractDocumentation ( from: node)
18021855 )
18031856
18041857 exportedProtocolByName [ protocolUniqueKey] = exportedProtocol
@@ -1874,7 +1927,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
18741927 isReadonly: true ,
18751928 isStatic: false ,
18761929 namespace: effectiveNamespace,
1877- staticContext: nil
1930+ staticContext: nil ,
1931+ documentation: extractDocumentation ( from: varDecl)
18781932 )
18791933 properties. append ( property)
18801934 }
@@ -1888,7 +1942,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
18881942 explicitAccessControl: explicitAccessControl,
18891943 properties: properties,
18901944 methods: [ ] ,
1891- namespace: effectiveNamespace
1945+ namespace: effectiveNamespace,
1946+ documentation: extractDocumentation ( from: node)
18921947 )
18931948
18941949 exportedStructByName [ structUniqueKey] = exportedStruct
@@ -1981,7 +2036,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
19812036 returnType: returnType,
19822037 effects: effects,
19832038 namespace: namespace,
1984- staticContext: nil
2039+ staticContext: nil ,
2040+ documentation: extractDocumentation ( from: node)
19852041 )
19862042 }
19872043
@@ -2022,7 +2078,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
20222078 let exportedProperty = ExportedProtocolProperty (
20232079 name: propertyName,
20242080 type: propertyType,
2025- isReadonly: isReadonly
2081+ isReadonly: isReadonly,
2082+ documentation: extractDocumentation ( from: node)
20262083 )
20272084
20282085 if var currentProtocol = exportedProtocolByName [ protocolKey] {
@@ -2033,7 +2090,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
20332090 name: currentProtocol. name,
20342091 methods: currentProtocol. methods,
20352092 properties: properties,
2036- namespace: currentProtocol. namespace
2093+ namespace: currentProtocol. namespace,
2094+ documentation: currentProtocol. documentation
20372095 )
20382096 exportedProtocolByName [ protocolKey] = currentProtocol
20392097 }
0 commit comments