Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8065,6 +8065,11 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
/// type-checked.
BraceStmt *getMacroExpandedBody() const;

/// Whether the body of the function has been expanded from a body macro.
bool isBodyMacroExpanded() const {
return getBodyExpandedStatus() == BodyExpandedStatus::Expanded;
}

/// Retrieve the type-checked body of the given function, or \c nullptr if
/// there's no body available.
BraceStmt *getTypecheckedBody() const;
Expand Down
7 changes: 6 additions & 1 deletion lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,12 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
if (WalkGenerics && visitTrailingRequirements(AFD))
return true;

if (AFD->getBody(/*canSynthesize=*/false)) {
// If we're not walking macro expansions, avoid walking into a body if it
// was expanded from a macro.
auto SkipBody = !Walker.shouldWalkMacroArgumentsAndExpansion().second &&
AFD->isBodyMacroExpanded();

if (!SkipBody && AFD->getBody(/*canSynthesize=*/false)) {
AbstractFunctionDecl::BodyKind PreservedKind = AFD->getBodyKind();
if (BraceStmt *S = cast_or_null<BraceStmt>(doIt(AFD->getBody())))
AFD->setBody(S, PreservedKind);
Expand Down
40 changes: 40 additions & 0 deletions test/SourceKit/SemanticTokens/issue-85705.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t

// RUN: %host-build-swift -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %t/macro.swift -g -no-toolchain-stdlib-rpath

// RUN: %sourcekitd-test -req=semantic-tokens %t/main.swift -- %t/main.swift -load-plugin-library %t/%target-library-name(MacroDefinition) > %t/result.response
// RUN: diff -u %t/expected.response %t/result.response

// REQUIRES: swift_swift_parser

//--- macro.swift
import SwiftSyntax
import SwiftSyntaxMacros

public struct LogMacro: BodyMacro {
public static func expansion(
of node: AttributeSyntax,
providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax,
in context: some MacroExpansionContext,
) throws -> [CodeBlockItemSyntax] {
return ["print()"]
}
}
//--- main.swift
@attached(body)
public macro log() = #externalMacro(module: "MacroDefinition", type: "LogMacro")

// Make sure we don't walk into the macro expanded body here.
@log func foo() {}

//--- expected.response
{
key.semantic_tokens: [
{
key.kind: source.lang.swift.ref.macro,
key.offset: 161,
key.length: 3
}
]
}
9 changes: 4 additions & 5 deletions tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1027,12 +1027,11 @@ class SemanticAnnotator : public SourceEntityWalker {
if (!Range.isValid())
return;

// If we are walking into macro expansions, make sure we only report ranges
// from the requested buffer, not any buffers of child macro expansions.
if (IsWalkingMacroExpansionBuffer &&
SM.findBufferContainingLoc(Range.getStart()) != BufferID) {
// Make sure we only report from the requested buffer, not any buffers of
// child macro expansions.
if (SM.findBufferContainingLoc(Range.getStart()) != BufferID)
return;
}

unsigned ByteOffset = SM.getLocOffsetInBuffer(Range.getStart(), BufferID);
unsigned Length = Range.getByteLength();
auto Kind = ContextFreeCodeCompletionResult::getCodeCompletionDeclKind(D);
Expand Down