Skip to content

Commit 9f13707

Browse files
committed
[SourceKit/Refactoring] Macro expansion
Add refactoring "Expand Macro" that expands macro expressions. rdar://102739026
1 parent 0b29450 commit 9f13707

File tree

6 files changed

+116
-4
lines changed

6 files changed

+116
-4
lines changed

include/swift/Refactoring/RefactoringKinds.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ CURSOR_REFACTORING(AddAsyncAlternative, "Add Async Alternative", add.async-alter
6464

6565
CURSOR_REFACTORING(AddAsyncWrapper, "Add Async Wrapper", add.async-wrapper)
6666

67+
CURSOR_REFACTORING(ExpandMacro, "Expand Macro", expand.macro)
68+
6769
RANGE_REFACTORING(ExtractExpr, "Extract Expression", extract.expr)
6870

6971
RANGE_REFACTORING(ExtractFunction, "Extract Method", extract.function)

lib/IDE/SourceEntityWalker.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -607,10 +607,7 @@ ASTWalker::PreWalkResult<Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
607607
return Action::Stop();
608608
}
609609

610-
if (auto rewritten = ME->getRewritten()) {
611-
if (!rewritten->walk(*this))
612-
return Action::Stop();
613-
}
610+
// Do not walk into ME->getRewritten() because it's not what the user wrote.
614611

615612
// Already walked the children.
616613
return doSkipChildren();

lib/Refactoring/Refactoring.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8421,6 +8421,62 @@ bool RefactoringActionAddAsyncWrapper::performChange() {
84218421
return false;
84228422
}
84238423

8424+
static MacroExpansionExpr *
8425+
findMacroExpansionTargetExpr(const ResolvedCursorInfo &Info) {
8426+
8427+
// Handle '#' position in '#macroName(...)'.
8428+
if (auto exprInfo = dyn_cast<ResolvedExprStartCursorInfo>(&Info)) {
8429+
if (auto target =
8430+
dyn_cast_or_null<MacroExpansionExpr>(exprInfo->getTrailingExpr()))
8431+
if (target->getRewritten())
8432+
return target;
8433+
return nullptr;
8434+
}
8435+
8436+
// Handle 'macroName' position in '#macroName(...)'.
8437+
if (auto refInfo = dyn_cast<ResolvedValueRefCursorInfo>(&Info)) {
8438+
if (refInfo->isRef() && isa_and_nonnull<MacroDecl>(refInfo->getValueD())) {
8439+
ContextFinder Finder(
8440+
*Info.getSourceFile(), Info.getLoc(), [&](ASTNode N) {
8441+
auto *expr =
8442+
dyn_cast_or_null<MacroExpansionExpr>(N.dyn_cast<Expr *>());
8443+
return expr &&
8444+
(expr->getMacroNameLoc().getBaseNameLoc() == Info.getLoc());
8445+
});
8446+
Finder.resolve();
8447+
if (!Finder.getContexts().empty()) {
8448+
auto *target =
8449+
dyn_cast<MacroExpansionExpr>(Finder.getContexts()[0].get<Expr *>());
8450+
if (target->getRewritten())
8451+
return target;
8452+
}
8453+
}
8454+
return nullptr;
8455+
}
8456+
8457+
// TODO: handle MacroExpansionDecl.
8458+
return nullptr;
8459+
}
8460+
8461+
bool RefactoringActionExpandMacro::isApplicable(const ResolvedCursorInfo &Info,
8462+
DiagnosticEngine &Diag) {
8463+
return findMacroExpansionTargetExpr(Info) != nullptr;
8464+
}
8465+
8466+
bool RefactoringActionExpandMacro::performChange() {
8467+
auto target = findMacroExpansionTargetExpr(CursorInfo);
8468+
if (!target)
8469+
return true;
8470+
8471+
auto exprRange =
8472+
Lexer::getCharSourceRangeFromSourceRange(SM, target->getSourceRange());
8473+
auto rewrittenRange = Lexer::getCharSourceRangeFromSourceRange(
8474+
SM, target->getRewritten()->getSourceRange());
8475+
auto rewrittenBuffer = SM.extractText(rewrittenRange);
8476+
EditConsumer.accept(SM, exprRange, rewrittenBuffer);
8477+
return false;
8478+
}
8479+
84248480
} // end of anonymous namespace
84258481

84268482
StringRef swift::ide::

test/Index/index_macros.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@ func test(x: Int) {
2222
// CHECK: 11:8 | macro/Swift | myLine | s:14swift_ide_test6myLineSifm | Ref,RelCont | rel: 1
2323
// CHECK: 12:20 | macro/Swift | myFilename | s:14swift_ide_test10myFilenamexfm | Ref,RelCont | rel: 1
2424
// CHECK: 13:8 | macro/Swift | myStringify(_:) | s:14swift_ide_test11myStringifyyx_SStxcfm | 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
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
macro stringify<T>(_ value: T) -> (T, String) = MacroDefinition.StringifyMacro
2+
3+
func testStringify(a: Int, b: Int) {
4+
_ = #stringify(a + b)
5+
}
6+
7+
// FIXME: Swift parser is not enabled on Linux CI yet.
8+
// REQUIRES: OS=macosx
9+
10+
// REQUIRES=shell
11+
12+
// RUN: %empty-directory(%t)
13+
14+
//##-- Prepare the macro plugin.
15+
// RUN: %target-build-swift -I %swift-host-lib-dir -L %swift-host-lib-dir -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/../../Macros/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
16+
17+
// RUN: COMPILER_ARGS=( \
18+
// RUN: -enable-experimental-feature Macros \
19+
// RUN: -load-plugin-library %t/%target-library-name(MacroDefinition) \
20+
// RUN: -I %swift-host-lib-dir \
21+
// RUN: -module-name MacroUser \
22+
// RUN: %s \
23+
// RUN: )
24+
25+
//##-- cursor-info at '#' position.
26+
// RUN: %sourcekitd-test -req=cursor -pos=4:7 -cursor-action %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=CURSOR_POUND %s
27+
28+
// CURSOR_POUND-LABEL: ACTIONS BEGIN
29+
// CURSOR_POUND: source.refactoring.kind.expand.macro
30+
// CURSOR_POUND-NEXT: Expand Macro
31+
// CURSOR_POUND: ACTIONS END
32+
33+
//##-- cursor-info at 'stringify' position.
34+
// RUN: %sourcekitd-test -req=cursor -pos=4:8 -cursor-action %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=CURSOR_MACRONAME %s
35+
36+
// CURSOR_MACRONAME: source.lang.swift.ref.macro (1:7-1:16)
37+
// CURSOR_MACRONAME: (T) -> (T, String)
38+
// CURSOR_MACRONAME: <Declaration>macro stringify&lt;T&gt;(_ value: <Type usr="s:9MacroUser1TL_xmfp">T</Type>) -&gt; (<Type usr="s:9MacroUser1TL_xmfp">T</Type>, <Type usr="s:SS">String</Type>) = MacroDefinition.StringifyMacro</Declaration>
39+
// CURSOR_MACRONAME: <decl.macro><syntaxtype.keyword>macro</syntaxtype.keyword> <decl.name>stringify</decl.name>&lt;<decl.generic_type_param usr="s:9MacroUser1TL_xmfp"><decl.generic_type_param.name>T</decl.generic_type_param.name></decl.generic_type_param>&gt;(<decl.var.parameter><decl.var.parameter.argument_label>_</decl.var.parameter.argument_label> <decl.var.parameter.name>value</decl.var.parameter.name>: <decl.var.parameter.type><ref.generic_type_param usr="s:9MacroUser1TL_xmfp">T</ref.generic_type_param></decl.var.parameter.type></decl.var.parameter>) -&gt; <decl.function.returntype><tuple>(<tuple.element><tuple.element.type><ref.generic_type_param usr="s:9MacroUser1TL_xmfp">T</ref.generic_type_param></tuple.element.type></tuple.element>, <tuple.element><tuple.element.type><ref.struct usr="s:SS">String</ref.struct></tuple.element.type></tuple.element>)</tuple></decl.function.returntype> = MacroDefinition.StringifyMacro</decl.macro>
40+
// CURSOR_MACRONAME-LABEL: ACTIONS BEGIN
41+
// CURSOR_MACRONAME: source.refactoring.kind.rename.global
42+
// CURSOR_MACRONAME-NEXT: Global Rename
43+
// CURSOR_MACRONAME: source.refactoring.kind.expand.macro
44+
// CURSOR_MACRONAME-NEXT: Expand Macro
45+
// CURSOR_MACRONAME: ACTIONS END
46+
47+
//##-- Refactoring at both position.
48+
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=4:7 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=EXPAND %s
49+
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=4:8 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=EXPAND %s
50+
51+
// EXPAND: source.edit.kind.active:
52+
// EXPAND-NEXT: 4:7-4:24 "(a + b, "a + b")"
53+

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class UIdentVisitor : public ASTVisitor<UIdentVisitor,
126126
UID_FOR(Destructor)
127127
UID_FOR(Subscript)
128128
UID_FOR(OpaqueType)
129+
UID_FOR(Macro)
129130
#undef UID_FOR
130131
};
131132

0 commit comments

Comments
 (0)