Skip to content

Commit f47c2b3

Browse files
committed
[ASTGen] Generate CustomAttr
Update macro tests
1 parent 0f1b650 commit f47c2b3

File tree

7 files changed

+117
-21
lines changed

7 files changed

+117
-21
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,13 @@ BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
605605
BridgedSourceRange cRange,
606606
BridgedStringRef cName);
607607

608+
SWIFT_NAME(
609+
"BridgedCustomAttr.createParsed(_:atLoc:type:initContext:argumentList:)")
610+
BridgedCustomAttr BridgedCustomAttr_createParsed(
611+
BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedTypeRepr cType,
612+
BridgedNullablePatternBindingInitializer cInitContext,
613+
BridgedNullableArgumentList cArgumentList);
614+
608615
SWIFT_NAME(
609616
"BridgedDynamicReplacementAttr.createParsed(_:atLoc:attrNameLoc:lParenLoc:"
610617
"replacedFunction:rParenLoc:)")

lib/AST/Bridging/DeclAttributeBridging.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "swift/AST/ASTContext.h"
1616
#include "swift/AST/Attr.h"
17+
#include "swift/AST/Expr.h"
1718
#include "swift/AST/Identifier.h"
1819
#include "swift/Basic/Assertions.h"
1920

@@ -129,6 +130,16 @@ BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
129130
/*Implicit=*/false);
130131
}
131132

133+
BridgedCustomAttr BridgedCustomAttr_createParsed(
134+
BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedTypeRepr cType,
135+
BridgedNullablePatternBindingInitializer cInitContext,
136+
BridgedNullableArgumentList cArgumentList) {
137+
ASTContext &context = cContext.unbridged();
138+
return CustomAttr::create(
139+
context, cAtLoc.unbridged(), new (context) TypeExpr(cType.unbridged()),
140+
cInitContext.unbridged(), cArgumentList.unbridged());
141+
}
142+
132143
BridgedDynamicReplacementAttr BridgedDynamicReplacementAttr_createParsed(
133144
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
134145
BridgedSourceLoc cAttrNameLoc, BridgedSourceLoc cLParenLoc,

lib/ASTGen/Sources/ASTGen/ASTGen.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class Boxed<Value> {
6868
}
6969
}
7070

71+
/// Generate AST from ``SwiftSyntax/Syntax``.
7172
struct ASTGenVisitor {
7273
let diagnosticEngine: BridgedDiagnosticEngine
7374

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ extension ASTGenVisitor {
2222
var attributes: BridgedDeclAttributes
2323
var staticSpelling: BridgedStaticSpelling
2424
var staticLoc: BridgedSourceLoc
25+
var initContext: BridgedPatternBindingInitializer?
2526
}
2627

2728
func generateDeclAttributes(_ node: some WithAttributesSyntax & WithModifiersSyntax, allowStatic: Bool) -> DeclAttributesResult {
@@ -54,6 +55,7 @@ extension ASTGenVisitor {
5455
}
5556

5657
// '@' attributes.
58+
var initContext: BridgedPatternBindingInitializer? = nil
5759
visitIfConfigElements(node.attributes, of: AttributeSyntax.self) { element in
5860
switch element {
5961
case .ifConfigDecl(let ifConfigDecl):
@@ -62,7 +64,7 @@ extension ASTGenVisitor {
6264
return .underlying(attribute)
6365
}
6466
} body: { attribute in
65-
addAttribute(self.generateDeclAttribute(attribute: attribute))
67+
addAttribute(self.generateDeclAttribute(attribute: attribute, initContext: &initContext))
6668
}
6769

6870
func genStatic(node: DeclModifierSyntax, spelling: BridgedStaticSpelling) {
@@ -89,14 +91,15 @@ extension ASTGenVisitor {
8991
return DeclAttributesResult(
9092
attributes: attrs,
9193
staticSpelling: staticSpelling,
92-
staticLoc: staticLoc
94+
staticLoc: staticLoc,
95+
initContext: initContext
9396
)
9497
}
9598
}
9699

97100
// MARK: - Decl attributes
98101
extension ASTGenVisitor {
99-
func generateDeclAttribute(attribute node: AttributeSyntax) -> BridgedDeclAttribute? {
102+
func generateDeclAttribute(attribute node: AttributeSyntax, initContext: inout BridgedPatternBindingInitializer?) -> BridgedDeclAttribute? {
100103
if let identTy = node.attributeName.as(IdentifierTypeSyntax.self) {
101104
let attrName = identTy.name.rawText
102105
let attrKind = BridgedDeclAttrKind(from: attrName.bridged)
@@ -319,7 +322,7 @@ extension ASTGenVisitor {
319322
}
320323
}
321324

322-
return self.generateCustomAttr(attribute: node)?.asDeclAttribute
325+
return self.generateCustomAttr(attribute: node, initContext: &initContext)?.asDeclAttribute
323326
}
324327

325328
func generateAlignmentAttr(attribute node: AttributeSyntax) -> BridgedAlignmentAttr? {
@@ -1163,16 +1166,39 @@ extension ASTGenVisitor {
11631166
)
11641167
}
11651168

1166-
func generateCustomAttr(attribute node: AttributeSyntax) -> BridgedCustomAttr? {
1167-
guard
1168-
let args = node.arguments?.as(LabeledExprListSyntax.self)?[...]
1169-
else {
1170-
// TODO: Diagnose.
1171-
return nil
1169+
func generateCustomAttr(attribute node: AttributeSyntax, initContext: inout BridgedPatternBindingInitializer?) -> BridgedCustomAttr? {
1170+
let type = self.generate(type: node.attributeName)
1171+
1172+
let argList: BridgedArgumentList?
1173+
if let args = node.arguments {
1174+
guard let args = args.as(LabeledExprListSyntax.self) else {
1175+
// TODO: Diagnose?
1176+
return nil
1177+
}
1178+
1179+
if !self.declContext.isLocalContext && initContext == nil {
1180+
initContext = BridgedPatternBindingInitializer.create(declContext: self.declContext)
1181+
}
1182+
argList = withDeclContext(initContext?.asDeclContext ?? self.declContext) {
1183+
self.generateArgumentList(
1184+
leftParen: node.leftParen,
1185+
labeledExprList: args,
1186+
rightParen: node.rightParen,
1187+
trailingClosure: nil,
1188+
additionalTrailingClosures: nil
1189+
)
1190+
}
1191+
} else {
1192+
argList = nil
11721193
}
11731194

1174-
_ = args
1175-
fatalError("unimplemented")
1195+
return .createParsed(
1196+
self.ctx,
1197+
atLoc: self.generateSourceLoc(node.atSign),
1198+
type: type,
1199+
initContext: initContext.asNullable,
1200+
argumentList: argList.asNullable
1201+
)
11761202
}
11771203

11781204
func generateStringLiteralTextIfNotInterpolated(expr node: some ExprSyntaxProtocol) -> BridgedStringRef? {

lib/ASTGen/Sources/ASTGen/Decls.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,8 @@ extension ASTGenVisitor {
460460
}
461461
}
462462

463-
func generate(patternBinding binding: PatternBindingSyntax) -> BridgedPatternBindingEntry {
463+
func generate(patternBinding binding: PatternBindingSyntax, attrs: DeclAttributesResult) -> BridgedPatternBindingEntry {
464+
// FIXME: Apply attributes.
464465
let pattern = generate(pattern: binding.pattern)
465466
let equalLoc = generateSourceLoc(binding.initializer?.equal)
466467

@@ -471,7 +472,7 @@ extension ASTGenVisitor {
471472
// ensures that property initializers are correctly treated as being in a
472473
// local context).
473474
if !self.declContext.isLocalContext {
474-
initContext = .create(declContext: self.declContext)
475+
initContext = attrs.initContext ?? .create(declContext: self.declContext)
475476
}
476477
initExpr = withDeclContext(initContext?.asDeclContext ?? self.declContext) {
477478
generate(expr: initializer.value)
@@ -495,14 +496,14 @@ extension ASTGenVisitor {
495496
)
496497
}
497498

498-
private func generateBindingEntries(for node: VariableDeclSyntax) -> BridgedArrayRef {
499+
private func generateBindingEntries(for node: VariableDeclSyntax, attrs: DeclAttributesResult) -> BridgedArrayRef {
499500
var propagatedType: BridgedTypeRepr?
500501
var entries: [BridgedPatternBindingEntry] = []
501502

502503
// Generate the bindings in reverse, keeping track of the TypeRepr to
503504
// propagate to earlier patterns if needed.
504505
for binding in node.bindings.reversed() {
505-
var entry = self.generate(patternBinding: binding)
506+
var entry = self.generate(patternBinding: binding, attrs: attrs)
506507

507508
// We can potentially propagate a type annotation back if we don't have an initializer, and are a bare NamedPattern.
508509
let canPropagateType = binding.initializer == nil && binding.pattern.is(IdentifierPatternSyntax.self)
@@ -536,16 +537,15 @@ extension ASTGenVisitor {
536537
}
537538

538539
func generate(variableDecl node: VariableDeclSyntax) -> BridgedPatternBindingDecl {
539-
// TODO: Attributes and modifiers
540-
let isStatic = false // TODO: compute this
540+
let attrs = self.generateDeclAttributes(node, allowStatic: true)
541541
let isLet = node.bindingSpecifier.keywordKind == .let
542542

543543
return .createParsed(
544544
self.ctx,
545545
declContext: self.declContext,
546546
bindingKeywordLoc: self.generateSourceLoc(node.bindingSpecifier),
547-
entries: self.generateBindingEntries(for: node),
548-
isStatic: isStatic,
547+
entries: self.generateBindingEntries(for: node, attrs: attrs),
548+
isStatic: attrs.staticLoc.isValid,
549549
isLet: isLet
550550
)
551551
}

lib/ASTGen/Sources/ASTGen/Exprs.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ extension ASTGenVisitor {
290290
return .underlying(attribute)
291291
}
292292
} body: { node in
293-
if let attr = self.generateDeclAttribute(attribute: node) {
293+
var initCtx: BridgedPatternBindingInitializer?
294+
if let attr = self.generateDeclAttribute(attribute: node, initContext: &initCtx) {
294295
result.attributes.add(attr)
295296
}
296297
}

test/ASTGen/macros.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,53 @@ func foo(a: Int) {
1717
struct Outer {
1818
#anonymousTypes { "test" }
1919
}
20+
21+
@attached(extension, conformances: P1, P2)
22+
macro AddAllConformances() = #externalMacro(module: "MacroDefinition", type: "AddAllConformancesMacro")
23+
24+
protocol P1 {}
25+
protocol P2 {}
26+
27+
@AddAllConformances
28+
struct MultipleConformances {}
29+
30+
func testConformances() {
31+
func eat(arg: some P1) {}
32+
eat(arg: MultipleConformances())
33+
}
34+
35+
protocol DefaultInit {
36+
init()
37+
}
38+
39+
@attached(extension, conformances: Equatable, names: named(==))
40+
macro Equatable() = #externalMacro(module: "MacroDefinition", type: "EquatableViaMembersMacro")
41+
42+
@propertyWrapper
43+
struct NotEquatable<T> {
44+
var wrappedValue: T
45+
}
46+
47+
@Equatable
48+
struct HasPropertyWrappers {
49+
@NotEquatable
50+
var value: Int = 0
51+
}
52+
53+
func requiresEquatable<T: Equatable>(_: T) { }
54+
func testHasPropertyWrappers(hpw: HasPropertyWrappers) {
55+
requiresEquatable(hpw)
56+
}
57+
58+
@attached(extension, conformances: DefaultInit)
59+
@attached(member, conformances: DefaultInit, names: named(init()), named(f()))
60+
macro DefaultInit() = #externalMacro(module: "MacroDefinition", type: "RequiredDefaultInitMacro")
61+
62+
@DefaultInit
63+
class C { }
64+
65+
@DefaultInit
66+
class D: C { }
67+
68+
@DefaultInit
69+
struct E { }

0 commit comments

Comments
 (0)