Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
"methods" : [
{
"abiName" : "bjs_PlayBridgeJS_updateDetailed",
"documentation" : "Structured entry point used by the playground so JS doesn't need to parse diagnostics.",
"effects" : {
"isAsync" : false,
"isStatic" : false,
Expand Down
84 changes: 71 additions & 13 deletions Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -1266,10 +1266,56 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
returnType: returnType,
effects: effects,
namespace: finalNamespace,
staticContext: staticContext
staticContext: staticContext,
documentation: extractDocumentation(from: node)
)
}

/// Returns the doc comment (`///` or `/** */`) attached to a declaration, with
/// markers stripped and DocC field lists (`- Parameters:`, `- Returns:`) preserved.
private func extractDocumentation(from node: some SyntaxProtocol) -> String? {
var run: [String] = []
for piece in node.leadingTrivia {
switch piece {
case .docLineComment(let text):
var line = Substring(text)
if line.hasPrefix("///") { line = line.dropFirst(3) }
if line.first == " " { line = line.dropFirst() }
if line.last == "\r" { line = line.dropLast() }
run.append(String(line))
case .docBlockComment(let text):
run.append(contentsOf: stripBlockComment(text))
case .newlines(let count), .carriageReturns(let count), .carriageReturnLineFeeds(let count):
if count >= 2 { run.removeAll() }
case .lineComment, .blockComment:
run.removeAll()
default:
continue
}
}
// Trim boundary blank lines so line (`///`) and block (`/** */`) comments
// produce a consistent skeleton value.
while run.first?.trimmingCharacters(in: .whitespaces).isEmpty == true { run.removeFirst() }
while run.last?.trimmingCharacters(in: .whitespaces).isEmpty == true { run.removeLast() }
return run.isEmpty ? nil : run.joined(separator: "\n")
}

private func stripBlockComment(_ text: String) -> [String] {
var body = Substring(text)
if body.hasPrefix("/**") { body = body.dropFirst(3) }
if body.hasSuffix("*/") { body = body.dropLast(2) }
return body.split(separator: "\n", omittingEmptySubsequences: false).map { raw -> String in
var line = raw[...]
if line.last == "\r" { line = line.dropLast() }
while let first = line.first, first == " " || first == "\t" { line = line.dropFirst() }
if line.first == "*" {
line = line.dropFirst()
if line.first == " " { line = line.dropFirst() }
}
return String(line)
}
}

private func collectEffects(signature: FunctionSignatureSyntax, isStatic: Bool = false) -> Effects? {
let isAsync = signature.effectSpecifiers?.asyncSpecifier != nil
var isThrows = false
Expand DownExpand Up@@ -1360,7 +1406,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
let constructor = ExportedConstructor(
abiName: "bjs_\(classAbiName)_init",
parameters: parameters,
effects: effects
effects: effects,
documentation: extractDocumentation(from: node)
)
exportedClassByName[classKey]?.constructor = constructor

Expand All@@ -1383,7 +1430,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
let constructor = ExportedConstructor(
abiName: "bjs_\(structAbiName)_init",
parameters: parameters,
effects: effects
effects: effects,
documentation: extractDocumentation(from: node)
)
exportedStructByName[structKey]?.constructor = constructor

Expand DownExpand Up@@ -1490,7 +1538,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
isReadonly: isReadonly,
isStatic: isStatic,
namespace: finalNamespace,
staticContext: staticContext
staticContext: staticContext,
documentation: extractDocumentation(from: node)
)

if case .enumBody(_, let key) = state {
Expand DownExpand Up@@ -1537,7 +1586,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
methods: [],
properties: [],
namespace: effectiveNamespace,
identityMode: classIdentityMode
identityMode: classIdentityMode,
documentation: extractDocumentation(from: node)
)
let uniqueKey = makeKey(name: name, namespace: effectiveNamespace)

Expand DownExpand Up@@ -1657,7 +1707,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
namespace: effectiveNamespace,
emitStyle: emitStyle,
staticMethods: [],
staticProperties: []
staticProperties: [],
documentation: extractDocumentation(from: node)
)

let enumUniqueKey = makeKey(name: name, namespace: effectiveNamespace)
Expand DownExpand Up@@ -1774,7 +1825,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
name: name,
methods: [],
properties: [],
namespace: effectiveNamespace
namespace: effectiveNamespace,
documentation: extractDocumentation(from: node)
)

stateStack.push(state: .protocolBody(name: name, key: protocolUniqueKey))
Expand All@@ -1798,7 +1850,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
name: name,
methods: methods,
properties: exportedProtocolByName[protocolUniqueKey]?.properties ?? [],
namespace: effectiveNamespace
namespace: effectiveNamespace,
documentation: extractDocumentation(from: node)
)

exportedProtocolByName[protocolUniqueKey] = exportedProtocol
Expand DownExpand Up@@ -1874,7 +1927,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
isReadonly: true,
isStatic: false,
namespace: effectiveNamespace,
staticContext: nil
staticContext: nil,
documentation: extractDocumentation(from: varDecl)
)
properties.append(property)
}
Expand All@@ -1888,7 +1942,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
explicitAccessControl: explicitAccessControl,
properties: properties,
methods: [],
namespace: effectiveNamespace
namespace: effectiveNamespace,
documentation: extractDocumentation(from: node)
)

exportedStructByName[structUniqueKey] = exportedStruct
Expand DownExpand Up@@ -1981,7 +2036,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
returnType: returnType,
effects: effects,
namespace: namespace,
staticContext: nil
staticContext: nil,
documentation: extractDocumentation(from: node)
)
}

Expand DownExpand Up@@ -2022,7 +2078,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
let exportedProperty = ExportedProtocolProperty(
name: propertyName,
type: propertyType,
isReadonly: isReadonly
isReadonly: isReadonly,
documentation: extractDocumentation(from: node)
)

if var currentProtocol = exportedProtocolByName[protocolKey] {
Expand All@@ -2033,7 +2090,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
name: currentProtocol.name,
methods: currentProtocol.methods,
properties: properties,
namespace: currentProtocol.namespace
namespace: currentProtocol.namespace,
documentation: currentProtocol.documentation
)
exportedProtocolByName[protocolKey] = currentProtocol
}
Expand Down
Loading
Loading