@@ -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