mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[SourceKit/Refactoring] Macro expansion
Add refactoring "Expand Macro" that expands macro expressions. rdar://102739026
This commit is contained in:
@@ -64,6 +64,8 @@ CURSOR_REFACTORING(AddAsyncAlternative, "Add Async Alternative", add.async-alter
|
||||
|
||||
CURSOR_REFACTORING(AddAsyncWrapper, "Add Async Wrapper", add.async-wrapper)
|
||||
|
||||
CURSOR_REFACTORING(ExpandMacro, "Expand Macro", expand.macro)
|
||||
|
||||
RANGE_REFACTORING(ExtractExpr, "Extract Expression", extract.expr)
|
||||
|
||||
RANGE_REFACTORING(ExtractFunction, "Extract Method", extract.function)
|
||||
|
||||
@@ -607,10 +607,7 @@ ASTWalker::PreWalkResult<Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
|
||||
return Action::Stop();
|
||||
}
|
||||
|
||||
if (auto rewritten = ME->getRewritten()) {
|
||||
if (!rewritten->walk(*this))
|
||||
return Action::Stop();
|
||||
}
|
||||
// Do not walk into ME->getRewritten() because it's not what the user wrote.
|
||||
|
||||
// Already walked the children.
|
||||
return doSkipChildren();
|
||||
|
||||
@@ -8421,6 +8421,62 @@ bool RefactoringActionAddAsyncWrapper::performChange() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static MacroExpansionExpr *
|
||||
findMacroExpansionTargetExpr(const ResolvedCursorInfo &Info) {
|
||||
|
||||
// Handle '#' position in '#macroName(...)'.
|
||||
if (auto exprInfo = dyn_cast<ResolvedExprStartCursorInfo>(&Info)) {
|
||||
if (auto target =
|
||||
dyn_cast_or_null<MacroExpansionExpr>(exprInfo->getTrailingExpr()))
|
||||
if (target->getRewritten())
|
||||
return target;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Handle 'macroName' position in '#macroName(...)'.
|
||||
if (auto refInfo = dyn_cast<ResolvedValueRefCursorInfo>(&Info)) {
|
||||
if (refInfo->isRef() && isa_and_nonnull<MacroDecl>(refInfo->getValueD())) {
|
||||
ContextFinder Finder(
|
||||
*Info.getSourceFile(), Info.getLoc(), [&](ASTNode N) {
|
||||
auto *expr =
|
||||
dyn_cast_or_null<MacroExpansionExpr>(N.dyn_cast<Expr *>());
|
||||
return expr &&
|
||||
(expr->getMacroNameLoc().getBaseNameLoc() == Info.getLoc());
|
||||
});
|
||||
Finder.resolve();
|
||||
if (!Finder.getContexts().empty()) {
|
||||
auto *target =
|
||||
dyn_cast<MacroExpansionExpr>(Finder.getContexts()[0].get<Expr *>());
|
||||
if (target->getRewritten())
|
||||
return target;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: handle MacroExpansionDecl.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool RefactoringActionExpandMacro::isApplicable(const ResolvedCursorInfo &Info,
|
||||
DiagnosticEngine &Diag) {
|
||||
return findMacroExpansionTargetExpr(Info) != nullptr;
|
||||
}
|
||||
|
||||
bool RefactoringActionExpandMacro::performChange() {
|
||||
auto target = findMacroExpansionTargetExpr(CursorInfo);
|
||||
if (!target)
|
||||
return true;
|
||||
|
||||
auto exprRange =
|
||||
Lexer::getCharSourceRangeFromSourceRange(SM, target->getSourceRange());
|
||||
auto rewrittenRange = Lexer::getCharSourceRangeFromSourceRange(
|
||||
SM, target->getRewritten()->getSourceRange());
|
||||
auto rewrittenBuffer = SM.extractText(rewrittenRange);
|
||||
EditConsumer.accept(SM, exprRange, rewrittenBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
StringRef swift::ide::
|
||||
|
||||
@@ -22,3 +22,6 @@ func test(x: Int) {
|
||||
// CHECK: 11:8 | macro/Swift | myLine | s:14swift_ide_test6myLineSifm | Ref,RelCont | rel: 1
|
||||
// CHECK: 12:20 | macro/Swift | myFilename | s:14swift_ide_test10myFilenamexfm | Ref,RelCont | rel: 1
|
||||
// CHECK: 13:8 | macro/Swift | myStringify(_:) | s:14swift_ide_test11myStringifyyx_SStxcfm | Ref,RelCont | rel: 1
|
||||
// CHECK: 13:20 | param/Swift | x | s:14swift_ide_test0C01xySi_tFACL_Sivp | Ref,Read,RelCont | rel: 1
|
||||
// CHECK: 13:22 | static-method/infix-operator/Swift | +(_:_:) | s:Si1poiyS2i_SitFZ | Ref,Call,RelCall,RelCont | rel: 1
|
||||
// CHECK: 13:24 | param/Swift | x | s:14swift_ide_test0C01xySi_tFACL_Sivp | Ref,Read,RelCont | rel: 1
|
||||
|
||||
53
test/SourceKit/Macros/macro_basic.swift
Normal file
53
test/SourceKit/Macros/macro_basic.swift
Normal file
@@ -0,0 +1,53 @@
|
||||
macro stringify<T>(_ value: T) -> (T, String) = MacroDefinition.StringifyMacro
|
||||
|
||||
func testStringify(a: Int, b: Int) {
|
||||
_ = #stringify(a + b)
|
||||
}
|
||||
|
||||
// FIXME: Swift parser is not enabled on Linux CI yet.
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
// REQUIRES=shell
|
||||
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
//##-- Prepare the macro plugin.
|
||||
// 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
|
||||
|
||||
// RUN: COMPILER_ARGS=( \
|
||||
// RUN: -enable-experimental-feature Macros \
|
||||
// RUN: -load-plugin-library %t/%target-library-name(MacroDefinition) \
|
||||
// RUN: -I %swift-host-lib-dir \
|
||||
// RUN: -module-name MacroUser \
|
||||
// RUN: %s \
|
||||
// RUN: )
|
||||
|
||||
//##-- cursor-info at '#' position.
|
||||
// RUN: %sourcekitd-test -req=cursor -pos=4:7 -cursor-action %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=CURSOR_POUND %s
|
||||
|
||||
// CURSOR_POUND-LABEL: ACTIONS BEGIN
|
||||
// CURSOR_POUND: source.refactoring.kind.expand.macro
|
||||
// CURSOR_POUND-NEXT: Expand Macro
|
||||
// CURSOR_POUND: ACTIONS END
|
||||
|
||||
//##-- cursor-info at 'stringify' position.
|
||||
// RUN: %sourcekitd-test -req=cursor -pos=4:8 -cursor-action %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=CURSOR_MACRONAME %s
|
||||
|
||||
// CURSOR_MACRONAME: source.lang.swift.ref.macro (1:7-1:16)
|
||||
// CURSOR_MACRONAME: (T) -> (T, String)
|
||||
// CURSOR_MACRONAME: <Declaration>macro stringify<T>(_ value: <Type usr="s:9MacroUser1TL_xmfp">T</Type>) -> (<Type usr="s:9MacroUser1TL_xmfp">T</Type>, <Type usr="s:SS">String</Type>) = MacroDefinition.StringifyMacro</Declaration>
|
||||
// CURSOR_MACRONAME: <decl.macro><syntaxtype.keyword>macro</syntaxtype.keyword> <decl.name>stringify</decl.name><<decl.generic_type_param usr="s:9MacroUser1TL_xmfp"><decl.generic_type_param.name>T</decl.generic_type_param.name></decl.generic_type_param>>(<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>) -> <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>
|
||||
// CURSOR_MACRONAME-LABEL: ACTIONS BEGIN
|
||||
// CURSOR_MACRONAME: source.refactoring.kind.rename.global
|
||||
// CURSOR_MACRONAME-NEXT: Global Rename
|
||||
// CURSOR_MACRONAME: source.refactoring.kind.expand.macro
|
||||
// CURSOR_MACRONAME-NEXT: Expand Macro
|
||||
// CURSOR_MACRONAME: ACTIONS END
|
||||
|
||||
//##-- Refactoring at both position.
|
||||
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=4:7 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=EXPAND %s
|
||||
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=4:8 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=EXPAND %s
|
||||
|
||||
// EXPAND: source.edit.kind.active:
|
||||
// EXPAND-NEXT: 4:7-4:24 "(a + b, "a + b")"
|
||||
|
||||
@@ -126,6 +126,7 @@ public:
|
||||
UID_FOR(Destructor)
|
||||
UID_FOR(Subscript)
|
||||
UID_FOR(OpaqueType)
|
||||
UID_FOR(Macro)
|
||||
#undef UID_FOR
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user