|
| 1 | +// REQUIRES: swift_swift_parser |
| 2 | + |
1 | 3 | // RUN: %empty-directory(%t)
|
2 |
| -// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s |
3 |
| -// REQUIRES: OS=macosx |
| 4 | +// RUN: split-file --leading-lines %s %t |
| 5 | + |
| 6 | +// Check that we index code expanded from macros, especially nested references |
| 7 | +// (ie. calls within an added function). |
| 8 | + |
| 9 | +// Create the plugin with various macros for testing |
| 10 | +// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(IndexMacros) -module-name=IndexMacros %t/IndexMacros.swift -g -no-toolchain-stdlib-rpath |
| 11 | + |
| 12 | +// Check indexed symbols |
| 13 | +// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %t/IndexTest.swift -load-plugin-library %t/%target-library-name(IndexMacros) -parse-as-library 2>&1 | tee %t/test.idx | %FileCheck %s |
| 14 | + |
| 15 | +//--- IndexTest.swift |
| 16 | +@freestanding(expression) |
| 17 | +macro freestandingExpr() = #externalMacro(module: "IndexMacros", type: "FreestandingExprMacro") |
| 18 | +// CHECK: [[@LINE-1]]:7 | macro/Swift | freestandingExpr() | [[EXPR_USR:.*]] | Def |
| 19 | + |
| 20 | +@freestanding(declaration, names: named(TestFree)) |
| 21 | +macro freestandingDecl() = #externalMacro(module: "IndexMacros", type: "FreestandingDeclMacro") |
| 22 | +// CHECK: [[@LINE-1]]:7 | macro/Swift | freestandingDecl() | [[DECL_USR:.*]] | Def |
| 23 | + |
| 24 | +@attached(accessor) |
| 25 | +macro Accessor() = #externalMacro(module: "IndexMacros", type: "SomeAccessorMacro") |
| 26 | +// CHECK: [[@LINE-1]]:7 | macro/Swift | Accessor() | [[ACCESSOR_USR:.*]] | Def |
| 27 | + |
| 28 | +@attached(conformance) |
| 29 | +macro Conformance() = #externalMacro(module: "IndexMacros", type: "SomeConformanceMacro") |
| 30 | +// CHECK: [[@LINE-1]]:7 | macro/Swift | Conformance() | [[CONFORMANCE_USR:.*]] | Def |
| 31 | + |
| 32 | +@attached(member, names: named(memberFunc)) |
| 33 | +macro Member() = #externalMacro(module: "IndexMacros", type: "SomeMemberMacro") |
| 34 | +// CHECK: [[@LINE-1]]:7 | macro/Swift | Member() | [[MEMBER_USR:.*]] | Def |
| 35 | + |
| 36 | +@attached(memberAttribute) |
| 37 | +macro MemberAttribute() = #externalMacro(module: "IndexMacros", type: "SomeMemberAttributeMacro") |
| 38 | +// CHECK: [[@LINE-1]]:7 | macro/Swift | MemberAttribute() | [[MEMBER_ATTRIBUTE_USR:.*]] | Def |
| 39 | + |
| 40 | +@attached(peer, names: named(TestPeer)) |
| 41 | +macro Peer() = #externalMacro(module: "IndexMacros", type: "SomePeerMacro") |
| 42 | +// CHECK: [[@LINE-1]]:7 | macro/Swift | Peer() | [[PEER_USR:.*]] | Def |
| 43 | + |
| 44 | +@attached(peer, names: named(peerMember)) |
| 45 | +macro PeerMember() = #externalMacro(module: "IndexMacros", type: "SomePeerMemberMacro") |
| 46 | +// CHECK: [[@LINE-1]]:7 | macro/Swift | PeerMember() | [[PEER_MEMBER_USR:.*]] | Def |
| 47 | + |
| 48 | +protocol TestProto {} |
| 49 | +// CHECK: [[@LINE-1]]:10 | protocol/Swift | TestProto | [[PROTO_USR:.*]] | Def |
| 50 | + |
| 51 | +func accessorLog() {} |
| 52 | +// CHECK: [[@LINE-1]]:6 | function/Swift | accessorLog() | [[ACC_LOG_USR:.*]] | Def |
| 53 | +func exprLog() {} |
| 54 | +// CHECK: [[@LINE-1]]:6 | function/Swift | exprLog() | [[EXPR_LOG_USR:.*]] | Def |
| 55 | +func freeLog() {} |
| 56 | +// CHECK: [[@LINE-1]]:6 | function/Swift | freeLog() | [[FREE_LOG_USR:.*]] | Def |
| 57 | +func memberLog() {} |
| 58 | +// CHECK: [[@LINE-1]]:6 | function/Swift | memberLog() | [[MEMBER_LOG_USR:.*]] | Def |
| 59 | +func peerLog() {} |
| 60 | +// CHECK: [[@LINE-1]]:6 | function/Swift | peerLog() | [[PEER_LOG_USR:.*]] | Def |
| 61 | + |
| 62 | +// CHECK: [[@LINE+2]]:8 | struct/Swift | AddOne | [[ADD_ONE_USR:.*]] | Def |
| 63 | +@propertyWrapper |
| 64 | +struct AddOne { |
| 65 | + var value: Int = 1 |
| 66 | + var wrappedValue: Int { |
| 67 | + get { value } |
| 68 | + set { value = newValue + 1 } |
| 69 | + } |
| 70 | + init(wrappedValue: Int) { |
| 71 | + self.wrappedValue = wrappedValue |
| 72 | + } |
| 73 | +} |
| 74 | + |
| 75 | +// Creates a `TestFree` struct with `freeFunc` calling `freeLog` |
| 76 | +#freestandingDecl |
| 77 | +// CHECK: [[@LINE-1]]:2 | macro/Swift | freestandingDecl() | [[DECL_USR]] | Ref |
| 78 | +// CHECK: [[@LINE-2]]:1 | struct/Swift | TestFree | [[FREE_STRUCT_USR:.*]] | Def,Impl |
| 79 | +// CHECK: [[@LINE-3]]:1 | instance-method/Swift | freeFunc() | [[FREE_FUNC_USR:.*]] | Def,Impl,RelChild |
| 80 | +// CHECK-NEXT: RelChild | struct/Swift | TestFree | [[FREE_STRUCT_USR]] |
| 81 | +// CHECK: [[@LINE-5]]:1 | function/Swift | freeLog() | [[FREE_LOG_USR]] | Ref,Call,Impl,RelCall,RelCont |
| 82 | +// CHECK-NEXT: RelCall,RelCont | instance-method/Swift | freeFunc() | [[FREE_FUNC_USR]] |
| 83 | + |
| 84 | +// CHECK: [[@LINE+4]]:40 | macro/Swift | Peer() | [[PEER_USR]] | Ref |
| 85 | +// CHECK: [[@LINE+3]]:23 | macro/Swift | MemberAttribute() | [[MEMBER_ATTRIBUTE_USR]] | Ref |
| 86 | +// CHECK: [[@LINE+2]]:15 | macro/Swift | Member() | [[MEMBER_USR]] | Ref |
| 87 | +// CHECK: [[@LINE+1]]:2 | macro/Swift | Conformance() | [[CONFORMANCE_USR]] | Ref |
| 88 | +@Conformance @Member @MemberAttribute @Peer |
| 89 | +struct TestAttached { |
| 90 | + var attachedMember: Int |
| 91 | + |
| 92 | + @Accessor |
| 93 | + var attachedMemberAccessors: Int |
| 94 | +} |
| 95 | +// `MemberAttribute` adds `@AddOne` to attachedMember |
| 96 | +// CHECK: [[@LINE-8]]:22 | struct/Swift | AddOne | [[ADD_ONE_USR]] | Ref,Impl,RelCont |
| 97 | +// CHECK-NEXT: RelCont | instance-property/Swift | attachedMember |
| 98 | + |
| 99 | +// `Accessor` adds getters/setters to `attachedMemberAccessors` that both call `accessorLog` |
| 100 | +// CHECK: [[@LINE-8]]:3 | function/Swift | accessorLog() | [[ACC_LOG_USR]] | Ref,Call,Impl,RelCall,RelCont |
| 101 | +// CHECK-NEXT: RelCall,RelCont | instance-method/acc-get/Swift | getter:attachedMemberAccessors |
4 | 102 |
|
| 103 | +// `Member` adds a new member `memberFunc` that calls `memberLog` |
| 104 | +// CHECK: [[@LINE-16]]:14 | instance-method/Swift | memberFunc() | [[MEMBER_FUNC_USR:.*]] | Def,Impl,RelChild |
| 105 | +// CHECK: [[@LINE-17]]:14 | function/Swift | memberLog() | [[MEMBER_LOG_USR]] | Ref,Call,Impl,RelCall,RelCont |
| 106 | +// CHECK-NEXT: RelCall,RelCont | instance-method/Swift | memberFunc() | [[MEMBER_FUNC_USR]] |
5 | 107 |
|
6 |
| -@freestanding(expression) macro myLine() -> Int = #externalMacro(module: "MacroDefinition", type: "LineMacro") |
7 |
| -@freestanding(expression) macro myFilename<T: ExpressibleByStringLiteral>() -> T = #externalMacro(module: "MacroDefinition", type: "FileMacro") |
8 |
| -@freestanding(expression) macro myStringify<T>(_: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro") |
| 108 | +// `Peer` adds a new inner type `TestPeer` that contains `peerFunc` with a call to `peerLog` |
| 109 | +// CHECK: [[@LINE-21]]:39 | struct/Swift | TestPeer | [[PEER_STRUCT_USR:.*]] | Def,Impl |
| 110 | +// CHECK: [[@LINE-22]]:39 | instance-method/Swift | peerFunc() | [[PEER_FUNC_USR:.*]] | Def,Impl,RelChild |
| 111 | +// CHECK-NEXT: RelChild | struct/Swift | TestPeer | [[PEER_STRUCT_USR]] |
| 112 | +// CHECK: [[@LINE-24]]:39 | function/Swift | peerLog() | [[PEER_LOG_USR]] | Ref,Call,Impl,RelCall,RelCont |
| 113 | +// CHECK-NEXT: RelCall,RelCont | instance-method/Swift | peerFunc() | [[PEER_FUNC_USR]] |
9 | 114 |
|
10 |
| -func test(x: Int) { |
11 |
| - _ = #myLine |
12 |
| - let _: String = #myFilename |
13 |
| - _ = #myStringify(x + x) |
| 115 | +// `Conformance` adds `TestProto` as a conformance on an extension of `TestAttached` |
| 116 | +// CHECK: [[@LINE-28]]:1 | extension/ext-struct/Swift | TestAttached | {{.*}} | Def,Impl |
| 117 | +// CHECK: [[@LINE-29]]:1 | protocol/Swift | TestProto | [[PROTO_USR]] | Ref,Impl,RelBase |
| 118 | +// CHECK-NEXT: RelBase | extension/ext-struct/Swift | TestAttached |
| 119 | + |
| 120 | +// CHECK: [[@LINE+1]]:8 | struct/Swift | Outer | [[OUTER_USR:.*]] | Def |
| 121 | +struct Outer { |
| 122 | + // CHECK: [[@LINE+1]]:4 | macro/Swift | PeerMember() | [[PEER_MEMBER_USR]] | Ref |
| 123 | + @PeerMember |
| 124 | + var anyMember: Int |
| 125 | + // `PeerMember` adds a new `peerMember` |
| 126 | + // CHECK: [[@LINE-3]]:3 | instance-property/Swift | peerMember | {{.*}} | Def,Impl,RelChild |
| 127 | + // CHECK-NEXT: RelChild | struct/Swift | Outer | [[OUTER_USR]] |
| 128 | + |
| 129 | + // CHECK: [[@LINE+2]]:17 | macro/Swift | Member() | [[MEMBER_USR]] | Ref |
| 130 | + // CHECK: [[@LINE+1]]:4 | macro/Swift | Conformance() | [[CONFORMANCE_USR]] | Ref |
| 131 | + @Conformance @Member |
| 132 | + struct TestInner {} |
| 133 | +} |
| 134 | +// `Member` adds a new member `memberFunc` that calls `memberLog` |
| 135 | +// CHECK: [[@LINE-4]]:16 | instance-method/Swift | memberFunc() | [[INNER_FUNC_USR:.*]] | Def,Impl |
| 136 | +// CHECK-NEXT: RelChild | struct/Swift | TestInner |
| 137 | +// CHECK: [[@LINE-6]]:16 | function/Swift | memberLog() | [[MEMBER_LOG_USR]] | Ref,Call,Impl,RelCall,RelCont |
| 138 | +// CHECK-NEXT: RelCall,RelCont | instance-method/Swift | memberFunc() | [[INNER_FUNC_USR]] |
| 139 | + |
| 140 | +// `Conformance` adds `TestProto` as a conformance on an extension of `TestInner` |
| 141 | +// CHECK: [[@LINE-10]]:3 | extension/ext-struct/Swift | TestInner | {{.*}} | Def,Impl |
| 142 | +// CHECK: [[@LINE-11]]:3 | protocol/Swift | TestProto | [[PROTO_USR]] | Ref,Impl,RelBase |
| 143 | +// CHECK-NEXT: RelBase | extension/ext-struct/Swift | TestInner |
| 144 | + |
| 145 | +func testExpr() { |
| 146 | + #freestandingExpr |
| 147 | + // CHECK: [[@LINE-1]]:3 | function/Swift | exprLog() | [[EXPR_LOG_USR]] | Ref,Call,Impl,RelCall,RelCont |
| 148 | + // CHECK-NEXT: RelCall,RelCont | function/Swift | testExpr() |
14 | 149 | }
|
15 | 150 |
|
16 |
| -// CHECK: 6:33 | macro/Swift | myLine() | s:14swift_ide_test6myLineSiycfm | Def | rel: 0 |
17 |
| -// CHECK: 6:45 | struct/Swift | Int | s:Si | Ref | rel: 0 |
18 |
| -// CHECK: 7:33 | macro/Swift | myFilename() | s:14swift_ide_test10myFilenamexycs26ExpressibleByStringLiteralRzlufm | Def | rel: 0 |
19 |
| -// CHECK: 7:47 | protocol/Swift | ExpressibleByStringLiteral | s:s26ExpressibleByStringLiteralP | Ref | rel: 0 |
20 |
| -// CHECK: 8:33 | macro/Swift | myStringify(_:) | s:14swift_ide_test11myStringifyyx_SStxclufm | Def | rel: 0 |
| 151 | +//--- IndexMacros.swift |
| 152 | +import SwiftSyntax |
| 153 | +import SwiftSyntaxBuilder |
| 154 | +import SwiftSyntaxMacros |
| 155 | + |
| 156 | +public struct FreestandingExprMacro: ExpressionMacro { |
| 157 | + public static func expansion( |
| 158 | + of node: some FreestandingMacroExpansionSyntax, |
| 159 | + in context: some MacroExpansionContext |
| 160 | + ) -> ExprSyntax { |
| 161 | + return "exprLog()" |
| 162 | + } |
| 163 | +} |
| 164 | + |
| 165 | +public struct FreestandingDeclMacro: DeclarationMacro { |
| 166 | + public static func expansion( |
| 167 | + of node: some FreestandingMacroExpansionSyntax, |
| 168 | + in context: some MacroExpansionContext |
| 169 | + ) throws -> [DeclSyntax] { |
| 170 | + return [""" |
| 171 | + struct TestFree { |
| 172 | + func freeFunc() { |
| 173 | + freeLog() |
| 174 | + } |
| 175 | + } |
| 176 | + """] |
| 177 | + } |
| 178 | +} |
| 179 | + |
| 180 | +public struct SomeAccessorMacro: AccessorMacro { |
| 181 | + public static func expansion( |
| 182 | + of node: AttributeSyntax, |
| 183 | + providingAccessorsOf declaration: some DeclSyntaxProtocol, |
| 184 | + in context: some MacroExpansionContext |
| 185 | + ) throws -> [AccessorDeclSyntax] { |
| 186 | + return [ |
| 187 | + """ |
| 188 | + get { |
| 189 | + accessorLog() |
| 190 | + return 1 |
| 191 | + } |
| 192 | + """, |
| 193 | + """ |
| 194 | + set { |
| 195 | + accessorLog() |
| 196 | + } |
| 197 | + """, |
| 198 | + ] |
| 199 | + } |
| 200 | +} |
21 | 201 |
|
22 |
| -// CHECK: 11:8 | macro/Swift | myLine() | s:14swift_ide_test6myLineSiycfm | Ref,RelCont | rel: 1 |
23 |
| -// CHECK: 12:20 | macro/Swift | myFilename() | s:14swift_ide_test10myFilenamexycs26ExpressibleByStringLiteralRzlufm | Ref,RelCont | rel: 1 |
24 |
| -// CHECK: 13:8 | macro/Swift | myStringify(_:) | s:14swift_ide_test11myStringifyyx_SStxclufm | Ref,RelCont | rel: 1 |
25 |
| -// CHECK: 13:20 | param/Swift | x | s:14swift_ide_test0C01xySi_tFACL_Sivp | Ref,Read,RelCont | rel: 1 |
26 |
| -// CHECK: 13:22 | static-method/infix-operator/Swift | +(_:_:) | s:Si1poiyS2i_SitFZ | Ref,Call,RelCall,RelCont | rel: 1 |
27 |
| -// CHECK: 13:24 | param/Swift | x | s:14swift_ide_test0C01xySi_tFACL_Sivp | Ref,Read,RelCont | rel: 1 |
| 202 | +public struct SomeConformanceMacro: ConformanceMacro { |
| 203 | + public static func expansion( |
| 204 | + of node: AttributeSyntax, |
| 205 | + providingConformancesOf decl: some DeclGroupSyntax, |
| 206 | + in context: some MacroExpansionContext |
| 207 | + ) throws -> [(TypeSyntax, GenericWhereClauseSyntax?)] { |
| 208 | + let protocolName: TypeSyntax = "TestProto" |
| 209 | + return [(protocolName, nil)] |
| 210 | + } |
| 211 | +} |
| 212 | + |
| 213 | +public struct SomeMemberMacro: MemberMacro { |
| 214 | + public static func expansion( |
| 215 | + of node: AttributeSyntax, |
| 216 | + providingMembersOf declaration: some DeclGroupSyntax, |
| 217 | + in context: some MacroExpansionContext |
| 218 | + ) throws -> [DeclSyntax] { |
| 219 | + let newFunc: DeclSyntax = |
| 220 | + """ |
| 221 | + func memberFunc() { |
| 222 | + memberLog() |
| 223 | + } |
| 224 | + """ |
| 225 | + return [ |
| 226 | + newFunc, |
| 227 | + ] |
| 228 | + } |
| 229 | +} |
| 230 | + |
| 231 | +public struct SomeMemberAttributeMacro: MemberAttributeMacro { |
| 232 | + public static func expansion( |
| 233 | + of node: AttributeSyntax, |
| 234 | + attachedTo parent: some DeclGroupSyntax, |
| 235 | + providingAttributesFor member: some DeclSyntaxProtocol, |
| 236 | + in context: some MacroExpansionContext |
| 237 | + ) throws -> [AttributeSyntax] { |
| 238 | + guard let varDecl = member.as(VariableDeclSyntax.self), |
| 239 | + let binding = varDecl.bindings.first, |
| 240 | + let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.text, |
| 241 | + identifier == "attachedMember" |
| 242 | + else { |
| 243 | + return [] |
| 244 | + } |
| 245 | + |
| 246 | + return [AttributeSyntax( |
| 247 | + attributeName: SimpleTypeIdentifierSyntax( |
| 248 | + name: .identifier("AddOne") |
| 249 | + ) |
| 250 | + )] |
| 251 | + } |
| 252 | +} |
| 253 | + |
| 254 | +public struct SomePeerMacro: PeerMacro { |
| 255 | + public static func expansion( |
| 256 | + of node: AttributeSyntax, |
| 257 | + providingPeersOf declaration: some DeclSyntaxProtocol, |
| 258 | + in context: some MacroExpansionContext |
| 259 | + ) throws -> [DeclSyntax] { |
| 260 | + return [ |
| 261 | + """ |
| 262 | + struct TestPeer { |
| 263 | + func peerFunc() { |
| 264 | + peerLog() |
| 265 | + } |
| 266 | + } |
| 267 | + """ |
| 268 | + ] |
| 269 | + } |
| 270 | +} |
| 271 | + |
| 272 | +public struct SomePeerMemberMacro: PeerMacro { |
| 273 | + public static func expansion( |
| 274 | + of node: AttributeSyntax, |
| 275 | + providingPeersOf declaration: some DeclSyntaxProtocol, |
| 276 | + in context: some MacroExpansionContext |
| 277 | + ) throws -> [DeclSyntax] { |
| 278 | + return [ |
| 279 | + """ |
| 280 | + var peerMember: Int |
| 281 | + """ |
| 282 | + ] |
| 283 | + } |
| 284 | +} |
0 commit comments