From 6ccdbdbf430ffa06773dbc1c167728c8d45abbfe Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Fri, 16 May 2025 22:15:13 -0700 Subject: [PATCH 1/6] [Swiftify] Copy doc comment from clang node Swift nodes imported from clang don't have doc comments carried over, but IDEs are clever enough to fetch the comments from the associated clang node. The swift node in the macro expansion from _SwiftifyImport doesn't have a clang node directly associated with it however. This patch adds the same comment from the clang node to the _SwiftifyImport macro invocation node. Since the macro has access to this node, it can easily copy over its leading trivia. For now the comment is not altered at all, meaning @param still remains even if the parmeter is removed. rdar://151346977 --- lib/ClangImporter/ImportDecl.cpp | 11 ++++- .../SwiftMacros/SwiftifyImportMacro.swift | 1 + .../C/swiftify-import/Inputs/comments.h | 30 ++++++++++++++ .../C/swiftify-import/Inputs/module.modulemap | 4 ++ test/Interop/C/swiftify-import/comments.swift | 41 +++++++++++++++++++ 5 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 test/Interop/C/swiftify-import/Inputs/comments.h create mode 100644 test/Interop/C/swiftify-import/comments.swift diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 365f96fad1667..d3049e5c1ff65 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -9281,10 +9281,17 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) { attachMacro = true; printer.printAvailability(); printer.printTypeMapping(typeMapping); + } - if (attachMacro) - importNontrivialAttribute(MappedDecl, MacroString); + if (attachMacro) { + if (clang::RawComment *raw = getClangASTContext().getRawCommentForDeclNoCache(ClangDecl)) { + auto commentString = raw->getRawText(getClangASTContext().getSourceManager()); + importNontrivialAttribute(MappedDecl, (commentString + "\n" + MacroString).str()); + } else { + importNontrivialAttribute(MappedDecl, MacroString); + } + } } static bool isUsingMacroName(clang::SourceManager &SM, diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index 726f1a78186cd..ee450d48fb439 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -1550,6 +1550,7 @@ public struct SwiftifyImportMacro: PeerMacro { + availabilityAttr + lifetimeAttrs + disfavoredOverload) + .with(\.leadingTrivia, node.leadingTrivia) return [DeclSyntax(newFunc)] } catch let error as DiagnosticError { context.diagnose( diff --git a/test/Interop/C/swiftify-import/Inputs/comments.h b/test/Interop/C/swiftify-import/Inputs/comments.h new file mode 100644 index 0000000000000..900e240b070ef --- /dev/null +++ b/test/Interop/C/swiftify-import/Inputs/comments.h @@ -0,0 +1,30 @@ +#pragma once + +#define __counted_by(x) __attribute__((__counted_by__(x))) + +void begin(); + +// line comment +void lineComment(int len, int * __counted_by(len) p); + +/// line doc comment +/// +/// Here's a more complete description. +/// +/// @param len the buffer length +/// @param p the buffer +void lineDocComment(int len, int * __counted_by(len) p); + +/* + block comment + */ +void blockComment(int len, int * __counted_by(len) p); + +/** + * block doc comment + * + * NB: it's very important to pass the correct length to this function + * @param len don't mess this one up + * @param p some integers to play with + */ +void blockDocComment(int len, int * __counted_by(len) p); diff --git a/test/Interop/C/swiftify-import/Inputs/module.modulemap b/test/Interop/C/swiftify-import/Inputs/module.modulemap index 5b19de151cc09..6f25ce2a38c29 100644 --- a/test/Interop/C/swiftify-import/Inputs/module.modulemap +++ b/test/Interop/C/swiftify-import/Inputs/module.modulemap @@ -14,3 +14,7 @@ module SizedByNoEscapeClang { header "sized-by-noescape.h" export * } +module CommentsClang { + header "comments.h" + export * +} diff --git a/test/Interop/C/swiftify-import/comments.swift b/test/Interop/C/swiftify-import/comments.swift new file mode 100644 index 0000000000000..399a391ee753b --- /dev/null +++ b/test/Interop/C/swiftify-import/comments.swift @@ -0,0 +1,41 @@ +// REQUIRES: swift_feature_SafeInteropWrappers + +// RUN: %target-swift-ide-test -print-module -module-to-print=CommentsClang -plugin-path %swift-plugin-dir -I %S/Inputs -source-filename=x -enable-experimental-feature SafeInteropWrappers | %FileCheck %s --strict-whitespace --match-full-lines + +// Check that doc comments are carried over from clang to the safe macro expansion. + +// CHECK:func begin() +// CHECK-NEXT:func lineComment(_ len: {{.*}}, _ p: UnsafeMutablePointer<{{.*}}>!) +// CHECK-NEXT:/// line doc comment +// CHECK-NEXT:/// +// CHECK-NEXT:/// Here's a more complete description. +// CHECK-NEXT:/// +// CHECK-NEXT:/// @param len the buffer length +// CHECK-NEXT:/// @param p the buffer +// CHECK-NEXT:func lineDocComment(_ len: {{.*}}, _ p: UnsafeMutablePointer<{{.*}}>!) +// CHECK-NEXT:func blockComment(_ len: {{.*}}, _ p: UnsafeMutablePointer<{{.*}}>!) +// CHECK-NEXT:/** +// CHECK-NEXT: * block doc comment +// CHECK-NEXT: * +// CHECK-NEXT: * NB: it's very important to pass the correct length to this function +// CHECK-NEXT: * @param len don't mess this one up +// CHECK-NEXT: * @param p some integers to play with +// CHECK-NEXT: */ +// CHECK-NEXT:func blockDocComment(_ len: {{.*}}, _ p: UnsafeMutablePointer<{{.*}}>!) +// CHECK-NEXT:@_alwaysEmitIntoClient public func blockComment(_ p: UnsafeMutableBufferPointer<{{.*}}>) +// CHECK-NEXT:/** +// CHECK-NEXT: * block doc comment +// CHECK-NEXT: * +// CHECK-NEXT: * NB: it's very important to pass the correct length to this function +// CHECK-NEXT: * @param len don't mess this one up +// CHECK-NEXT: * @param p some integers to play with +// CHECK-NEXT: */ +// CHECK-NEXT:@_alwaysEmitIntoClient public func blockDocComment(_ p: UnsafeMutableBufferPointer<{{.*}}>) +// CHECK-NEXT:@_alwaysEmitIntoClient public func lineComment(_ p: UnsafeMutableBufferPointer<{{.*}}>) +// CHECK-NEXT:/// line doc comment +// CHECK-NEXT:/// +// CHECK-NEXT:/// Here's a more complete description. +// CHECK-NEXT:/// +// CHECK-NEXT:/// @param len the buffer length +// CHECK-NEXT:/// @param p the buffer +// CHECK-NEXT:@_alwaysEmitIntoClient public func lineDocComment(_ p: UnsafeMutableBufferPointer<{{.*}}>) \ No newline at end of file From ad8f2c80ec8f2d0c4ad29f24527f7ed109e4ed1a Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Fri, 16 May 2025 22:31:21 -0700 Subject: [PATCH 2/6] add comment --- lib/ClangImporter/ImportDecl.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index d3049e5c1ff65..98646359b522b 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -9285,9 +9285,20 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) { } if (attachMacro) { - if (clang::RawComment *raw = getClangASTContext().getRawCommentForDeclNoCache(ClangDecl)) { - auto commentString = raw->getRawText(getClangASTContext().getSourceManager()); - importNontrivialAttribute(MappedDecl, (commentString + "\n" + MacroString).str()); + if (clang::RawComment *raw = + getClangASTContext().getRawCommentForDeclNoCache(ClangDecl)) { + // swift::RawDocCommentAttr doesn't contain its text directly, but instead + // references the source range of the parsed comment. Instead of creating + // a new source file just to parse the doc comment, we can add the + // comment to the macro invocation attribute, which the macro has access + // to. Waiting until we know that the macro will be attached before + // emitting the comment to the string, despite the comment occurring + // first, avoids copying a bunch of potentially long comments for nodes + // that don't end up with wrappers. + auto commentString = + raw->getRawText(getClangASTContext().getSourceManager()); + importNontrivialAttribute(MappedDecl, + (commentString + "\n" + MacroString).str()); } else { importNontrivialAttribute(MappedDecl, MacroString); } From f0a7cba7ffeaf2d96dde3064c2a0c7056f313baf Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Sat, 17 May 2025 11:47:46 -0700 Subject: [PATCH 3/6] add sourcekit test --- ..._doc_comment_from_clang_safe_wrapper.swift | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift diff --git a/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift new file mode 100644 index 0000000000000..9dd14c800d289 --- /dev/null +++ b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift @@ -0,0 +1,29 @@ +// RUN: %empty-directory(%t) +// RUN: split-file --leading-lines %s %t + +//--- header.h + +/// This comment contains `markup`. +/// +/// - And a list +void testCDecl(const int * __attribute__((__counted_by__(len))) __attribute__((noescape)) p, int len); + +//--- module.modulemap + +module MyClangModule { header "header.h" } + +//--- test.swift + +import MyClangModule + +func test(_ s: Span) { + // RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):4 %s -- %s -I %t -enable-experimental-feature SafeInteropWrappers | %FileCheck %s + testCDecl(s) +} + +// CHECK-LABEL: DOC COMMENT +// CHECK: This comment contains `markup`. +// CHECK: - And a list +// CHECK-LABEL: DOC COMMENT XML +// CHECK: testCDecl(_:)s:SC9testCDeclyys4SpanVys5Int32VGF@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: public func testCDecl(_ p: Span<Int32>)This comment contains markup.And a list \ No newline at end of file From f9507b90620d0f46661919c4710c3ca102c25a81 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Sat, 17 May 2025 12:31:34 -0700 Subject: [PATCH 4/6] add comment about being auto-generated wrapper --- .../SwiftMacros/SwiftifyImportMacro.swift | 2 +- test/Interop/C/swiftify-import/comments.swift | 27 +++++++---- .../swiftify-import/counted-by-noescape.swift | 23 +++++++++- .../C/swiftify-import/counted-by.swift | 38 ++++++++++++++- .../C/swiftify-import/sized-by-noescape.swift | 20 +++++++- test/Interop/C/swiftify-import/sized-by.swift | 20 +++++++- .../Cxx/stdlib/std-span-interface.swift | 46 ++++++++++++++++++- ..._doc_comment_from_clang_safe_wrapper.swift | 11 +++-- 8 files changed, 166 insertions(+), 21 deletions(-) diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index ee450d48fb439..0738f8752161c 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -1550,7 +1550,7 @@ public struct SwiftifyImportMacro: PeerMacro { + availabilityAttr + lifetimeAttrs + disfavoredOverload) - .with(\.leadingTrivia, node.leadingTrivia) + .with(\.leadingTrivia, node.leadingTrivia + .docLineComment("/// This is an auto-generated wrapper for safer interop\n")) return [DeclSyntax(newFunc)] } catch let error as DiagnosticError { context.diagnose( diff --git a/test/Interop/C/swiftify-import/comments.swift b/test/Interop/C/swiftify-import/comments.swift index 399a391ee753b..fbb87b26e3823 100644 --- a/test/Interop/C/swiftify-import/comments.swift +++ b/test/Interop/C/swiftify-import/comments.swift @@ -5,15 +5,18 @@ // Check that doc comments are carried over from clang to the safe macro expansion. // CHECK:func begin() -// CHECK-NEXT:func lineComment(_ len: {{.*}}, _ p: UnsafeMutablePointer<{{.*}}>!) +// CHECK-NEXT:func lineComment(_ len: Int32, _ p: UnsafeMutablePointer!) + // CHECK-NEXT:/// line doc comment // CHECK-NEXT:/// // CHECK-NEXT:/// Here's a more complete description. // CHECK-NEXT:/// // CHECK-NEXT:/// @param len the buffer length // CHECK-NEXT:/// @param p the buffer -// CHECK-NEXT:func lineDocComment(_ len: {{.*}}, _ p: UnsafeMutablePointer<{{.*}}>!) -// CHECK-NEXT:func blockComment(_ len: {{.*}}, _ p: UnsafeMutablePointer<{{.*}}>!) +// CHECK-NEXT:func lineDocComment(_ len: Int32, _ p: UnsafeMutablePointer!) + +// CHECK-NEXT:func blockComment(_ len: Int32, _ p: UnsafeMutablePointer!) + // CHECK-NEXT:/** // CHECK-NEXT: * block doc comment // CHECK-NEXT: * @@ -21,8 +24,11 @@ // CHECK-NEXT: * @param len don't mess this one up // CHECK-NEXT: * @param p some integers to play with // CHECK-NEXT: */ -// CHECK-NEXT:func blockDocComment(_ len: {{.*}}, _ p: UnsafeMutablePointer<{{.*}}>!) -// CHECK-NEXT:@_alwaysEmitIntoClient public func blockComment(_ p: UnsafeMutableBufferPointer<{{.*}}>) +// CHECK-NEXT:func blockDocComment(_ len: Int32, _ p: UnsafeMutablePointer!) + +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient public func blockComment(_ p: UnsafeMutableBufferPointer) + // CHECK-NEXT:/** // CHECK-NEXT: * block doc comment // CHECK-NEXT: * @@ -30,12 +36,17 @@ // CHECK-NEXT: * @param len don't mess this one up // CHECK-NEXT: * @param p some integers to play with // CHECK-NEXT: */ -// CHECK-NEXT:@_alwaysEmitIntoClient public func blockDocComment(_ p: UnsafeMutableBufferPointer<{{.*}}>) -// CHECK-NEXT:@_alwaysEmitIntoClient public func lineComment(_ p: UnsafeMutableBufferPointer<{{.*}}>) +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient public func blockDocComment(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient public func lineComment(_ p: UnsafeMutableBufferPointer) + // CHECK-NEXT:/// line doc comment // CHECK-NEXT:/// // CHECK-NEXT:/// Here's a more complete description. // CHECK-NEXT:/// // CHECK-NEXT:/// @param len the buffer length // CHECK-NEXT:/// @param p the buffer -// CHECK-NEXT:@_alwaysEmitIntoClient public func lineDocComment(_ p: UnsafeMutableBufferPointer<{{.*}}>) \ No newline at end of file +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient public func lineDocComment(_ p: UnsafeMutableBufferPointer) diff --git a/test/Interop/C/swiftify-import/counted-by-noescape.swift b/test/Interop/C/swiftify-import/counted-by-noescape.swift index f0ffb4a660fa0..d230834b58679 100644 --- a/test/Interop/C/swiftify-import/counted-by-noescape.swift +++ b/test/Interop/C/swiftify-import/counted-by-noescape.swift @@ -11,33 +11,52 @@ import CountedByNoEscapeClang -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(_param1: copy _param1) // CHECK-NEXT: @_alwaysEmitIntoClient public func anonymous(_ _param1: inout MutableSpan?) -// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ p: inout MutableSpan?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func returnLifetimeBound(_ len1: Int32, _ p: inout MutableSpan) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int32) -> UnsafeMutableBufferPointer + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p1: copy p1) // CHECK-NEXT: @lifetime(p2: copy p2) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int32, _ p1: inout MutableSpan, _ p2: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: inout MutableSpan) diff --git a/test/Interop/C/swiftify-import/counted-by.swift b/test/Interop/C/swiftify-import/counted-by.swift index d77ce9d33475f..6623b7ccf9650 100644 --- a/test/Interop/C/swiftify-import/counted-by.swift +++ b/test/Interop/C/swiftify-import/counted-by.swift @@ -10,23 +10,59 @@ import CountedByClang -// CHECK: @_alwaysEmitIntoClient public func bitshift(_ m: Int32, _ n: Int32, _ o: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @_alwaysEmitIntoClient public func bitshift(_ m: Int32, _ n: Int32, _ o: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func bitwise(_ m: Int32, _ n: Int32, _ o: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func constFloatCastedToInt(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func constInt(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ p: UnsafeMutableBufferPointer?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func offByOne(_ len: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func offBySome(_ len: Int32, _ offset: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeMutableBufferPointer + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func scalar(_ m: Int32, _ n: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: UnsafeMutableBufferPointer, _ p2: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func simpleFlipped(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func sizeofParam(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func sizeofType(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: UnsafeMutableBufferPointer) @inlinable diff --git a/test/Interop/C/swiftify-import/sized-by-noescape.swift b/test/Interop/C/swiftify-import/sized-by-noescape.swift index c2ff0a5647b3a..e8372becc5321 100644 --- a/test/Interop/C/swiftify-import/sized-by-noescape.swift +++ b/test/Interop/C/swiftify-import/sized-by-noescape.swift @@ -9,21 +9,39 @@ // Check that ClangImporter correctly infers and expands @_SwiftifyImport macros for functions with __sized_by __noescape parameters. import SizedByNoEscapeClang -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) + +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ p: RawSpan?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func opaque(_ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeRawBufferPointer + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: RawSpan, _ p2: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: RawSpan) diff --git a/test/Interop/C/swiftify-import/sized-by.swift b/test/Interop/C/swiftify-import/sized-by.swift index b9435f2d89ab9..316fc0e6c791f 100644 --- a/test/Interop/C/swiftify-import/sized-by.swift +++ b/test/Interop/C/swiftify-import/sized-by.swift @@ -9,14 +9,32 @@ // Check that ClangImporter correctly infers and expands @_SwiftifyImport macros for functions with __sized_by parameters. import SizedByClang -// CHECK: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: UnsafeMutableRawBufferPointer) + +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ p: UnsafeMutableRawBufferPointer?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func opaque(_ p: UnsafeRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeMutableRawBufferPointer + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: UnsafeMutableRawBufferPointer, _ p2: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: UnsafeMutableRawBufferPointer) @inlinable diff --git a/test/Interop/Cxx/stdlib/std-span-interface.swift b/test/Interop/Cxx/stdlib/std-span-interface.swift index 56535285b230a..b084d3492331f 100644 --- a/test/Interop/Cxx/stdlib/std-span-interface.swift +++ b/test/Interop/Cxx/stdlib/std-span-interface.swift @@ -23,70 +23,112 @@ import CxxStdlib // CHECK-NEXT: func funcWithSafeWrapper3(_ v: borrowing VecOfInt) -> ConstSpanOfInt // CHECK: struct X { // CHECK-NEXT: init() +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public mutating func methodWithSafeWrapper(_ s: Span) // CHECK-NEXT: mutating func methodWithSafeWrapper(_ s: ConstSpanOfInt) // CHECK-NEXT: } // CHECK: struct SpanWithoutTypeAlias { // CHECK-NEXT: init() +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow self) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public mutating func bar() -> Span // CHECK-NEXT: mutating func bar() -> std.{{.*}}span<__cxxConst, _C{{.*}}_{{.*}}> +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public mutating func foo(_ s: Span) // CHECK-NEXT: mutating func foo(_ s: std.{{.*}}span<__cxxConst, _C{{.*}}_{{.*}}>) // CHECK-NEXT: } -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func FuncWithMutableSafeWrapper(_ s: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy s) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func FuncWithMutableSafeWrapper2(_ s: inout MutableSpan) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func FuncWithMutableSafeWrapper3(_ v: inout VecOfInt) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper1(_ p: inout MutableSpan) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func MixedFuncWithMutableSafeWrapper2(_ v: inout VecOfInt, _ len: Int32) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper3(_ s: inout MutableSpan, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper4(_ s: inout MutableSpan, _ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper5(_ s: SpanOfInt, _ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper6(_ s: SpanOfInt, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper7(_ p: UnsafeMutableBufferPointer) -> SpanOfInt -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) + +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper(_ s: Span) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper2(_ s: Span) -> Span + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func funcWithSafeWrapper3(_ v: borrowing VecOfInt) -> Span + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper1(_ p: Span) -> Span + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func mixedFuncWithSafeWrapper2(_ v: borrowing VecOfInt, _ len: Int32) -> Span + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper3(_ s: Span, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper4(_ s: Span, _ p: Span) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper5(_ s: ConstSpanOfInt, _ p: Span) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper6(_ s: ConstSpanOfInt, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper7(_ p: UnsafeBufferPointer) -> ConstSpanOfInt diff --git a/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift index 9dd14c800d289..96815a97d179d 100644 --- a/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift +++ b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift @@ -3,9 +3,10 @@ //--- header.h -/// This comment contains `markup`. -/// -/// - And a list +/** This comment contains `markup`. + * + * - And a list + */ void testCDecl(const int * __attribute__((__counted_by__(len))) __attribute__((noescape)) p, int len); //--- module.modulemap @@ -25,5 +26,5 @@ func test(_ s: Span) { // CHECK: This comment contains `markup`. // CHECK: - And a list // CHECK-LABEL: DOC COMMENT XML -// CHECK: testCDecl(_:)s:SC9testCDeclyys4SpanVys5Int32VGF@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) -// CHECK-NEXT: public func testCDecl(_ p: Span<Int32>)This comment contains markup.And a list \ No newline at end of file +// CHECK: testCDecl(_:)s:SC9testCDeclyys4SpanVys5Int32VGF@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: public func testCDecl(_ p: Span<Int32>)This comment contains markup. *And a listThis is an auto-generated wrapper for safer interop From a907481178f41a63e7c5a78c36798e245c34bfef Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Sat, 17 May 2025 20:30:57 -0700 Subject: [PATCH 5/6] add REQUIRES SafeInteropWrappers to test --- .../CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift index 96815a97d179d..be665f2f7dc3e 100644 --- a/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift +++ b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift @@ -1,3 +1,5 @@ +// REQUIRES: swift_feature_SafeInteropWrappers + // RUN: %empty-directory(%t) // RUN: split-file --leading-lines %s %t From 7e78a6f2f0b6b299b285e5ac7a6dd500c1a04532 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Mon, 19 May 2025 17:59:29 -0700 Subject: [PATCH 6/6] check symbol graph --- ..._doc_comment_from_clang_safe_wrapper.swift | 75 ++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift index be665f2f7dc3e..a9a69647c73ce 100644 --- a/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift +++ b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift @@ -20,7 +20,7 @@ module MyClangModule { header "header.h" } import MyClangModule func test(_ s: Span) { - // RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):4 %s -- %s -I %t -enable-experimental-feature SafeInteropWrappers | %FileCheck %s + // RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):4 -req-opts=retrieve_symbol_graph=1 %s -- %s -I %t -enable-experimental-feature SafeInteropWrappers | %FileCheck %s testCDecl(s) } @@ -30,3 +30,76 @@ func test(_ s: Span) { // CHECK-LABEL: DOC COMMENT XML // CHECK: testCDecl(_:)s:SC9testCDeclyys4SpanVys5Int32VGF@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: public func testCDecl(_ p: Span<Int32>)This comment contains markup. *And a listThis is an auto-generated wrapper for safer interop + +// CHECK-LABEL: SYMBOL GRAPH BEGIN +// CHECK: "docComment": { +// CHECK-NEXT: "lines": [ +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 35, +// CHECK-NEXT: "line": 0 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 4, +// CHECK-NEXT: "line": 0 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "This comment contains `markup`." +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 2, +// CHECK-NEXT: "line": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 1, +// CHECK-NEXT: "line": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "*" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 15, +// CHECK-NEXT: "line": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 1, +// CHECK-NEXT: "line": 2 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "* - And a list" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 1, +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 1, +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 55, +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 4, +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "This is an auto-generated wrapper for safer interop" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "module": "MyClangModule", +// CHECK-NEXT: "uri": "file://@__swiftmacro_So9testCDecl15_SwiftifyImportfMp_.swift" +// CHECK-NEXT: }