Skip to content

Commit fbd5cb4

Browse files
authored
Merge pull request #70247 from DougGregor/body-macro-as-brace-stmt
Macro expansion refactoring for preamble and body macros
2 parents dffffcd + dd80cf7 commit fbd5cb4

File tree

4 files changed

+117
-27
lines changed

4 files changed

+117
-27
lines changed

lib/AST/Decl.cpp

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9155,52 +9155,47 @@ static std::vector<ASTNode> expandPreamble(AbstractFunctionDecl *func) {
91559155
static BraceStmt *expandBodyMacro(AbstractFunctionDecl *fn) {
91569156
ASTContext &ctx = fn->getASTContext();
91579157

9158-
// Expand the preamble.
9159-
auto preamble = expandPreamble(fn);
9160-
91619158
// Expand a body macro, if there is one.
9159+
BraceStmt *macroExpandedBody = nullptr;
91629160
if (auto bufferID = evaluateOrDefault(
91639161
ctx.evaluator, ExpandBodyMacroRequest{fn}, llvm::None)) {
91649162
CharSourceRange bufferRange = ctx.SourceMgr.getRangeForBuffer(*bufferID);
91659163
auto bufferStart = bufferRange.getStart();
91669164
auto module = fn->getParentModule();
91679165
auto macroSourceFile = module->getSourceFileContainingLocation(bufferStart);
91689166

9169-
// When there is no preamble, adopt the body itself.
9170-
if (preamble.empty()) {
9171-
return BraceStmt::create(
9172-
ctx, bufferRange.getStart(), macroSourceFile->getTopLevelItems(),
9173-
bufferRange.getEnd());
9167+
if (macroSourceFile->getTopLevelItems().size() == 1) {
9168+
auto stmt = macroSourceFile->getTopLevelItems()[0].dyn_cast<Stmt *>();
9169+
macroExpandedBody = dyn_cast<BraceStmt>(stmt);
91749170
}
9175-
9176-
// Merge the preamble into the macro-produced body.
9177-
auto contents = std::move(preamble);
9178-
contents.insert(
9179-
contents.end(),
9180-
macroSourceFile->getTopLevelItems().begin(),
9181-
macroSourceFile->getTopLevelItems().end());
9182-
return BraceStmt::create(
9183-
ctx, bufferRange.getStart(), contents, bufferRange.getEnd());
91849171
}
91859172

9186-
// There is no body macro. If there's no preamble, either, then there is
9187-
// nothing to do.
9173+
// Expand the preamble.
9174+
auto preamble = expandPreamble(fn);
9175+
9176+
// If there is no preamble, we're done one way or the other: return the
9177+
// macro-expanded body.
91889178
if (preamble.empty())
9189-
return nullptr;
9179+
return macroExpandedBody;
9180+
9181+
// We have a preamble. The body is either the one produced by macro expansion,
9182+
// or if not that, the one that was written.
9183+
auto body = macroExpandedBody ? macroExpandedBody : fn->getBody();
91909184

9191-
// If there is no body, the preamble has nowhere to go.
9192-
auto body = fn->getBody(/*canSynthesize=*/true);
9185+
// If there is no body at this point, the preamble has nowhere to go.
91939186
if (!body) {
91949187
// FIXME: diagnose this
91959188
return nullptr;
91969189
}
91979190

9198-
// Merge the preamble into the existing body.
9191+
// Merge the preamble into the body.
91999192
auto contents = std::move(preamble);
92009193
contents.insert(
9201-
contents.end(), body->getElements().begin(), body->getElements().end());
9194+
contents.end(),
9195+
body->getElements().begin(),
9196+
body->getElements().end());
92029197
return BraceStmt::create(
9203-
ctx, body->getLBraceLoc(), contents, body->getRBraceLoc());
9198+
ctx, body->getStartLoc(), contents, body->getEndLoc());
92049199
}
92059200

92069201
BraceStmt *AbstractFunctionDecl::getMacroExpandedBody() const {

lib/Parse/ParseRequests.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,27 @@ SourceFileParsingResult ParseSourceFileRequest::evaluate(Evaluator &evaluator,
182182

183183
case GeneratedSourceInfo::ExpressionMacroExpansion:
184184
case GeneratedSourceInfo::PreambleMacroExpansion:
185-
case GeneratedSourceInfo::BodyMacroExpansion:
186185
case GeneratedSourceInfo::ReplacedFunctionBody:
187186
case GeneratedSourceInfo::PrettyPrinted: {
188187
parser.parseTopLevelItems(items);
189188
break;
190189
}
191190

191+
case GeneratedSourceInfo::BodyMacroExpansion: {
192+
// Prime the lexer.
193+
if (parser.Tok.is(tok::NUM_TOKENS))
194+
parser.consumeTokenWithoutFeedingReceiver();
195+
196+
if (parser.Tok.is(tok::l_brace)) {
197+
if (auto body =
198+
parser.parseBraceItemList(diag::invalid_diagnostic)
199+
.getPtrOrNull())
200+
items.push_back(body);
201+
}
202+
203+
break;
204+
}
205+
192206
case GeneratedSourceInfo::MemberMacroExpansion: {
193207
parser.parseExpandedMemberList(items);
194208
break;

test/SourceKit/Macros/macro_basic.swift

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,60 @@ struct S5 {
6767
var test: Int = 10
6868
}
6969

70+
@attached(preamble)
71+
macro Traced() = #externalMacro(module: "MacroDefinition", type: "TracedPreambleMacro")
72+
73+
@attached(preamble, names: named(logger))
74+
macro Logged() = #externalMacro(module: "MacroDefinition", type: "LoggerMacro")
75+
76+
@Traced
77+
@Logged
78+
func doubleTheValue(value: Int) -> Int {
79+
return value * 2
80+
}
81+
82+
@attached(body)
83+
macro Remote() = #externalMacro(module: "MacroDefinition", type: "RemoteBodyMacro")
84+
85+
@available(SwiftStdlib 5.1, *)
86+
@Remote
87+
func f(a: Int, b: String) async throws -> String
88+
89+
protocol ConjureRemoteValue {
90+
static func conjureValue() -> Self
91+
}
92+
93+
extension String: ConjureRemoteValue {
94+
static func conjureValue() -> String { "" }
95+
}
96+
97+
struct Logger {
98+
func log(entering function: String) {
99+
print("Logger entering \(function)")
100+
}
101+
102+
func log(_ message: String) {
103+
print("--- \(message)")
104+
}
105+
106+
func log(exiting function: String) {
107+
print("Logger exiting \(function)")
108+
}
109+
}
110+
111+
func log(_ message: String) {
112+
print(message)
113+
}
114+
115+
@available(SwiftStdlib 5.1, *)
116+
func remoteCall<Result: ConjureRemoteValue>(function: String, arguments: [String: Any]) async throws -> Result {
117+
let printedArgs = arguments.keys.sorted().map { key in
118+
"\(key): \(arguments[key]!)"
119+
}.joined(separator: ", ")
120+
print("Remote call \(function)(\(printedArgs))")
121+
return Result.conjureValue()
122+
}
123+
70124
// REQUIRES: swift_swift_parser, executable_test, shell
71125

72126
// RUN: %empty-directory(%t)
@@ -78,6 +132,7 @@ struct S5 {
78132
// RUN: -swift-version 5 \
79133
// RUN: -load-plugin-library %t/%target-library-name(MacroDefinition) \
80134
// RUN: -module-name MacroUser \
135+
// RUN: -enable-experimental-feature BodyMacros \
81136
// RUN: )
82137

83138
// RUN: COMPILER_ARGS=( \
@@ -297,3 +352,29 @@ struct S5 {
297352
//##-- Expansion on the peer macro attached to pattern binding decl
298353
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=66:4 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=EXPAND_PEER_ON_VAR %s
299354
// EXPAND_PEER_ON_VAR: 67:21-67:21 (@__swiftmacro_9MacroUser2S5V4test21AddPeerStoredPropertyfMp_.swift) "public var _foo: Int = 100"
355+
356+
//##-- Expansion on a preamble macro.
357+
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=76:5 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=PREAMBLE_EXPAND %s
358+
// PREAMBLE_EXPAND: source.edit.kind.active:
359+
// PREAMBLE_EXPAND-NEXT: 78:40-78:40 (@__swiftmacro_9MacroUser14doubleTheValue6TracedfMq_.swift) "log("Entering doubleTheValue(value: \(value))")
360+
// PREAMBLE_EXPAND: defer {
361+
// PREAMBLE_EXPAND-NEXT: log("Exiting doubleTheValue(value:)")
362+
// PREAMBLE_EXPAND-NEXT: }"
363+
// PREAMBLE_EXPAND-NEXT: source.edit.kind.active
364+
365+
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=77:5 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=PREAMBLE2_EXPAND %s
366+
// PREAMBLE2_EXPAND: source.edit.kind.active:
367+
// PREAMBLE2_EXPAND-NEXT: 78:40-78:40 (@__swiftmacro_9MacroUser14doubleTheValue6LoggedfMq_.swift) "let logger = Logger()
368+
// PREAMBLE2_EXPAND-NEXT:logger.log(entering: "doubleTheValue(value: \(value))")
369+
// PREAMBLE2_EXPAND-NEXT:defer {
370+
// PREAMBLE2_EXPAND-NEXT: logger.log(exiting: "doubleTheValue(value:)")
371+
// PREAMBLE2_EXPAND-NEXT:}"
372+
// PREAMBLE2_EXPAND-NEXT:source.edit.kind.active:
373+
374+
//##-- Expansion on a body macro
375+
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=86:5 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=BODY_EXPAND %s
376+
// BODY_EXPAND: source.edit.kind.active:
377+
// BODY_EXPAND-NEXT: 87:49-87:49 (@__swiftmacro_9MacroUser1f6RemotefMb_.swift) "{
378+
// BODY_EXPAND-NEXT: return try await remoteCall(function: "f", arguments: ["a": a, "b": b])
379+
// BODY_EXPAND-NEXT: }"
380+
// BODY_EXPAND-NEXT: source.edit.kind.active:

tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,7 @@ class SourceDocASTWalker : public SourceEntityWalker {
11901190
return true;
11911191
// Ignore things that don't come from this buffer.
11921192
if (!SM.getRangeForBuffer(BufferID).contains(Range.getStart()))
1193-
return false;
1193+
return true;
11941194

11951195
unsigned StartOffset = getOffset(Range.getStart());
11961196
References.emplace_back(D, StartOffset, Range.getByteLength(), Ty);

0 commit comments

Comments
 (0)