diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp --- a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp @@ -270,6 +270,41 @@ } } + if (const auto *MD = dyn_cast(FD)) { + if (MD->isStatic()) { + SourceRange SpecRange{FD->getBeginLoc(), FD->getLocation()}; + bool FoundTok = false; + for (const auto &Tok : TokBuf.expandedTokens(SpecRange)) { + if (Tok.kind() != tok::kw_static) + continue; + FoundTok = true; + auto Spelling = TokBuf.spelledForExpanded(llvm::makeArrayRef(Tok)); + if (!Spelling) { + Errors = + llvm::joinErrors(std::move(Errors), + llvm::createStringError( + llvm::inconvertibleErrorCode(), + "define outline: Can't move out of line as " + "function has a macro `static` specifier.")); + break; + } + CharSourceRange DelRange = + syntax::Token::range(SM, Spelling->front(), Spelling->back()) + .toCharRange(SM); + if (auto Err = + DeclarationCleanups.add(tooling::Replacement(SM, DelRange, ""))) + Errors = llvm::joinErrors(std::move(Errors), std::move(Err)); + break; + } + if (!FoundTok) + Errors = llvm::joinErrors( + std::move(Errors), + llvm::createStringError( + llvm::inconvertibleErrorCode(), + "define outline: Couldn't remove methods `static` keyword")); + } + } + if (Errors) return std::move(Errors); return getFunctionSourceAfterReplacements(FD, DeclarationCleanups); diff --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp b/clang-tools-extra/clangd/unittests/TweakTests.cpp --- a/clang-tools-extra/clangd/unittests/TweakTests.cpp +++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp @@ -2142,6 +2142,17 @@ };)cpp", "void B::foo() {}\n", }, + { + R"cpp( + struct A { + static void fo^o() {} + };)cpp", + R"cpp( + struct A { + static void foo() ; + };)cpp", + " void A::foo() {}\n", + }, }; for (const auto &Case : Cases) { SCOPED_TRACE(Case.Test); @@ -2236,6 +2247,24 @@ STUPID_MACRO(sizeof sizeof int) void foo() ; };)cpp", " void A::foo() {}\n"}, + {R"cpp(#define STAT static + struct A { + STAT void f^oo() {} + };)cpp", + R"cpp(#define STAT static + struct A { + STAT void foo() ; + };)cpp", + " void A::foo() {}\n"}, + {R"cpp(#define STUPID_MACRO(X) static + struct A { + STUPID_MACRO(sizeof sizeof int) void f^oo() {} + };)cpp", + R"cpp(#define STUPID_MACRO(X) static + struct A { + STUPID_MACRO(sizeof sizeof int) void foo() ; + };)cpp", + " void A::foo() {}\n"}, }; for (const auto &Case : Cases) { SCOPED_TRACE(Case.Test);