diff --git a/lib/ConstExtract/ConstExtract.cpp b/lib/ConstExtract/ConstExtract.cpp index 2367475755289..632f7059fce6f 100644 --- a/lib/ConstExtract/ConstExtract.cpp +++ b/lib/ConstExtract/ConstExtract.cpp @@ -58,6 +58,9 @@ class NominalTypeConformanceCollector : public ASTWalker { for (auto &Protocol : NTD->getAllProtocols()) if (Protocols.count(Protocol->getName().str().str()) != 0) ConformanceTypeDecls.push_back(NTD); + // Visit peers expanded from macros + D->visitAuxiliaryDecls([&](Decl *decl) { decl->walk(*this); }, + /*visitFreestandingExpanded=*/false); return Action::Continue(); } }; @@ -473,7 +476,7 @@ ConstantValueInfoRequest::evaluate(Evaluator &Evaluator, Properties.push_back(extractTypePropertyInfo(Property)); } - for (auto Member : Decl->getMembers()) { + for (auto Member : Decl->getAllMembers()) { auto *VD = dyn_cast(Member); // Ignore plain stored properties collected above, // instead gather up remaining static and computed properties. @@ -483,7 +486,7 @@ ConstantValueInfoRequest::evaluate(Evaluator &Evaluator, } for (auto Extension: Decl->getExtensions()) { - for (auto Member : Extension->getMembers()) { + for (auto Member : Extension->getAllMembers()) { if (auto *VD = dyn_cast(Member)) { Properties.push_back(extractTypePropertyInfo(VD)); } diff --git a/test/ConstExtraction/ExtractFromMacroExpansion.swift b/test/ConstExtraction/ExtractFromMacroExpansion.swift new file mode 100644 index 0000000000000..709b6dd18e64f --- /dev/null +++ b/test/ConstExtraction/ExtractFromMacroExpansion.swift @@ -0,0 +1,133 @@ +// REQUIRES: swift_swift_parser +// RUN: %empty-directory(%t) +// RUN: echo "[MyProto]" > %t/protocols.json + +// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/Macros.swift -g -no-toolchain-stdlib-rpath + +// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/ExtractFromMacroExpansion.swiftconstvalues -const-gather-protocols-file %t/protocols.json -primary-file %s -load-plugin-library %t/%target-library-name(MacroDefinition) +// RUN: cat %t/ExtractFromMacroExpansion.swiftconstvalues 2>&1 | %FileCheck %s + +protocol MyProto { } + +@freestanding(declaration, names: named(MacroAddedStruct)) +macro AddMacroAddedStruct() = #externalMacro(module: "MacroDefinition", type: "AddStructDeclMacro") + +@freestanding(declaration, names: named(macroAddedVar)) +macro AddMacroAddedVar() = #externalMacro(module: "MacroDefinition", type: "AddVarDeclMacro") + +@attached(extension, conformances: MyProto, names: prefixed(_extension_)) +macro AddExtension() = #externalMacro(module: "MacroDefinition", type: "AddExtensionMacro") + +@attached(peer, names: prefixed(_peer_)) +macro AddPeerVar() = #externalMacro(module: "MacroDefinition", type: "AddPeerVarMacro") + +@attached(member, names: prefixed(_member_)) +macro AddMemberVar() = #externalMacro(module: "MacroDefinition", type: "AddMemberMacro") + +@attached(memberAttribute) +macro AddMacro() = #externalMacro(module: "MacroDefinition", type: "AddMemberAttributeMacro") + +@attached(accessor) +macro AddGetter() = #externalMacro(module: "MacroDefinition", type: "GetterMacro") + +@attached(peer, names: prefixed(_Peer_)) +macro AddPeerStruct() = #externalMacro(module: "MacroDefinition", type: "AddPeerStructMacro") + + +#AddMacroAddedStruct + +@AddExtension +@AddMemberVar +@AddPeerStruct +struct MyStruct { + #AddMacroAddedVar + + @AddPeerVar + struct Inner { } +} + +@AddMacro +extension MyStruct { + func fromFunc() { } + + @AddGetter + var fromVar = 123 +} + +// CHECK: "typeName": "ExtractFromMacroExpansion.MacroAddedStruct", +// CHECK: "properties": [ +// CHECK: "label": "macroAddedStructMember", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "1" + +// CHECK: "label": "_extension_MacroAddedStruct", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "3" + + +// CHECK: "typeName": "ExtractFromMacroExpansion.MyStruct", +// CHECK: "properties": [ +// CHECK: "label": "macroAddedVar", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "2" + +// CHECK: "label": "_peer_Inner", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "4" + +// CHECK: "label": "_member_MyStruct", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "5" + +// CHECK: "label": "_peer_fromFunc", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "4" + +// CHECK: "label": "_peer_fromVar", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "4" + +// CHECK: "label": "fromVar", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "123" + +// CHECK: "label": "_extension_MyStruct", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "3" + + +// CHECK: "typeName": "ExtractFromMacroExpansion._Peer_MyStruct", +// CHECK: "properties": [ +// CHECK: "label": "peerMacroVar", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "7" + +// CHECK: "label": "macroAddedVar", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "2" + +// CHECK: "label": "_peer_peerMacroVar", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "4" + +// CHECK: "label": "_member__Peer_MyStruct", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "5" + +// CHECK: "label": "_extension__Peer_MyStruct", +// CHECK: "type": "Swift.Int", +// CHECK: "valueKind": "RawLiteral", +// CHECK: "value": "3" diff --git a/test/ConstExtraction/Inputs/Macros.swift b/test/ConstExtraction/Inputs/Macros.swift new file mode 100644 index 0000000000000..3dfad8b221ab5 --- /dev/null +++ b/test/ConstExtraction/Inputs/Macros.swift @@ -0,0 +1,156 @@ +import SwiftDiagnostics +import SwiftOperators +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros + +public struct AddStructDeclMacro: DeclarationMacro { + public static func expansion( + of node: some FreestandingMacroExpansionSyntax, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + return [ + """ + @AddExtension + struct MacroAddedStruct { + var macroAddedStructMember = 1 + } + """ + ] + } +} + +public struct AddVarDeclMacro: DeclarationMacro { + public static func expansion( + of node: some FreestandingMacroExpansionSyntax, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + return [ + """ + static let macroAddedVar = 2 + """ + ] + } +} + +public struct AddExtensionMacro: ExtensionMacro { + public static func expansion( + of node: AttributeSyntax, + attachedTo declaration: some DeclGroupSyntax, + providingExtensionsOf type: some TypeSyntaxProtocol, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [ExtensionDeclSyntax] { + let typeName = declaration.declGroupName + return protocols.map { + ("extension \(typeName): \($0) { }" as DeclSyntax) + .cast(ExtensionDeclSyntax.self) + } + [ + (""" + extension \(typeName) { + static let _extension_\(typeName) = 3 + } + """ as DeclSyntax).cast(ExtensionDeclSyntax.self) + ] + } +} + +public struct AddPeerVarMacro: PeerMacro { + public static func expansion( + of node: AttributeSyntax, + providingPeersOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + let name = declaration.declName + return [ + """ + static var _peer_\(name) = 4 + """ + ] + } +} + +public struct AddMemberMacro: MemberMacro { + public static func expansion( + of node: AttributeSyntax, + providingMembersOf declaration: some DeclGroupSyntax, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + let typeName = declaration.declGroupName + return [ + """ + static let _member_\(typeName) = 5 + """ + ] + } +} + +public struct AddMemberAttributeMacro: MemberAttributeMacro { + public static func expansion( + of node: AttributeSyntax, + attachedTo declaration: some DeclGroupSyntax, + providingAttributesFor member: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [AttributeSyntax] { + if member.isProtocol(DeclGroupSyntax.self) { + return ["@AddExtension"] + } + return ["@AddPeerVar"] + } +} + +public struct GetterMacro: AccessorMacro { + public static func expansion( + of node: AttributeSyntax, + providingAccessorsOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [AccessorDeclSyntax] { + return ["get { 6 }"] + } +} + +public struct AddPeerStructMacro: PeerMacro { + public static func expansion( + of node: AttributeSyntax, + providingPeersOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + let name = declaration.declName + return [ + """ + @AddExtension + @AddMemberVar + struct _Peer_\(name) { + #AddMacroAddedVar + + @AddPeerVar + var peerMacroVar = 7 + } + """ + ] + } +} + +extension DeclGroupSyntax { + var declGroupName: TokenSyntax { + if let structDecl = self.as(StructDeclSyntax.self) { + return structDecl.name.trimmed + } + fatalError("Not implemented") + } +} + +extension DeclSyntaxProtocol { + var declName: TokenSyntax { + if let varDecl = self.as(VariableDeclSyntax.self), + let first = varDecl.bindings.first, + let pattern = first.pattern.as(IdentifierPatternSyntax.self) { + return pattern.identifier.trimmed + } else if let funcDecl = self.as(FunctionDeclSyntax.self) { + return funcDecl.name.trimmed + } else if let structDecl = self.as(StructDeclSyntax.self) { + return structDecl.name.trimmed + } + fatalError("Not implemented") + } +}