forked from OSchip/llvm-project
[clangd] Add basic keyword-name-validation in rename.
Differential Revision: https://reviews.llvm.org/D88875
This commit is contained in:
parent
68e002e181
commit
8a3cbb1535
|
@ -412,9 +412,9 @@ void ClangdServer::prepareRename(PathRef File, Position Pos,
|
||||||
// - for cross-file rename, we deliberately pass a nullptr index to save
|
// - for cross-file rename, we deliberately pass a nullptr index to save
|
||||||
// the cost, thus the result may be incomplete as it only contains
|
// the cost, thus the result may be incomplete as it only contains
|
||||||
// main-file occurrences;
|
// main-file occurrences;
|
||||||
auto Results = clangd::rename({Pos, /*NewName*/ "", InpAST->AST, File,
|
auto Results = clangd::rename(
|
||||||
RenameOpts.AllowCrossFile ? nullptr : Index,
|
{Pos, /*NewName=*/"__clangd_rename_dummy", InpAST->AST, File,
|
||||||
RenameOpts});
|
RenameOpts.AllowCrossFile ? nullptr : Index, RenameOpts});
|
||||||
if (!Results) {
|
if (!Results) {
|
||||||
// LSP says to return null on failure, but that will result in a generic
|
// LSP says to return null on failure, but that will result in a generic
|
||||||
// failure message. If we send an LSP error response, clients can surface
|
// failure message. If we send an LSP error response, clients can surface
|
||||||
|
|
|
@ -273,9 +273,6 @@ public:
|
||||||
StringRef TriggerText, Callback<std::vector<TextEdit>> CB);
|
StringRef TriggerText, Callback<std::vector<TextEdit>> CB);
|
||||||
|
|
||||||
/// Test the validity of a rename operation.
|
/// Test the validity of a rename operation.
|
||||||
///
|
|
||||||
/// The returned result describes edits in the main-file only (all
|
|
||||||
/// occurrences of the renamed symbol are simply deleted.
|
|
||||||
void prepareRename(PathRef File, Position Pos,
|
void prepareRename(PathRef File, Position Pos,
|
||||||
const RenameOptions &RenameOpts,
|
const RenameOptions &RenameOpts,
|
||||||
Callback<RenameResult> CB);
|
Callback<RenameResult> CB);
|
||||||
|
|
|
@ -120,6 +120,9 @@ enum class ReasonToReject {
|
||||||
UsedOutsideFile, // for within-file rename only.
|
UsedOutsideFile, // for within-file rename only.
|
||||||
UnsupportedSymbol,
|
UnsupportedSymbol,
|
||||||
AmbiguousSymbol,
|
AmbiguousSymbol,
|
||||||
|
|
||||||
|
// name validation.
|
||||||
|
RenameToKeywords,
|
||||||
};
|
};
|
||||||
|
|
||||||
llvm::Optional<ReasonToReject> renameable(const NamedDecl &RenameDecl,
|
llvm::Optional<ReasonToReject> renameable(const NamedDecl &RenameDecl,
|
||||||
|
@ -208,6 +211,8 @@ llvm::Error makeError(ReasonToReject Reason) {
|
||||||
return "symbol is not a supported kind (e.g. namespace, macro)";
|
return "symbol is not a supported kind (e.g. namespace, macro)";
|
||||||
case ReasonToReject::AmbiguousSymbol:
|
case ReasonToReject::AmbiguousSymbol:
|
||||||
return "there are multiple symbols at the given location";
|
return "there are multiple symbols at the given location";
|
||||||
|
case ReasonToReject::RenameToKeywords:
|
||||||
|
return "the chosen name is a keyword";
|
||||||
}
|
}
|
||||||
llvm_unreachable("unhandled reason kind");
|
llvm_unreachable("unhandled reason kind");
|
||||||
};
|
};
|
||||||
|
@ -471,6 +476,8 @@ llvm::Expected<RenameResult> rename(const RenameInputs &RInputs) {
|
||||||
return makeError(ReasonToReject::NoSymbolFound);
|
return makeError(ReasonToReject::NoSymbolFound);
|
||||||
if (DeclsUnderCursor.size() > 1)
|
if (DeclsUnderCursor.size() > 1)
|
||||||
return makeError(ReasonToReject::AmbiguousSymbol);
|
return makeError(ReasonToReject::AmbiguousSymbol);
|
||||||
|
if (isKeyword(RInputs.NewName, AST.getLangOpts()))
|
||||||
|
return makeError(ReasonToReject::RenameToKeywords);
|
||||||
|
|
||||||
const auto &RenameDecl =
|
const auto &RenameDecl =
|
||||||
llvm::cast<NamedDecl>(*(*DeclsUnderCursor.begin())->getCanonicalDecl());
|
llvm::cast<NamedDecl>(*(*DeclsUnderCursor.begin())->getCanonicalDecl());
|
||||||
|
|
|
@ -516,6 +516,7 @@ TEST(RenameTest, Renameable) {
|
||||||
const char* ErrorMessage; // null if no error
|
const char* ErrorMessage; // null if no error
|
||||||
bool IsHeaderFile;
|
bool IsHeaderFile;
|
||||||
const SymbolIndex *Index;
|
const SymbolIndex *Index;
|
||||||
|
llvm::StringRef NewName = "DummyName";
|
||||||
};
|
};
|
||||||
TestTU OtherFile = TestTU::withCode("Outside s; auto ss = &foo;");
|
TestTU OtherFile = TestTU::withCode("Outside s; auto ss = &foo;");
|
||||||
const char *CommonHeader = R"cpp(
|
const char *CommonHeader = R"cpp(
|
||||||
|
@ -542,6 +543,11 @@ TEST(RenameTest, Renameable) {
|
||||||
)cpp",
|
)cpp",
|
||||||
nullptr, HeaderFile, Index},
|
nullptr, HeaderFile, Index},
|
||||||
|
|
||||||
|
{R"cpp(
|
||||||
|
void ^f();
|
||||||
|
)cpp",
|
||||||
|
"keyword", HeaderFile, Index, "return"},
|
||||||
|
|
||||||
{R"cpp(// disallow -- symbol is indexable and has other refs in index.
|
{R"cpp(// disallow -- symbol is indexable and has other refs in index.
|
||||||
void f() {
|
void f() {
|
||||||
Out^side s;
|
Out^side s;
|
||||||
|
@ -639,7 +645,7 @@ TEST(RenameTest, Renameable) {
|
||||||
TU.ExtraArgs.push_back("-xobjective-c++-header");
|
TU.ExtraArgs.push_back("-xobjective-c++-header");
|
||||||
}
|
}
|
||||||
auto AST = TU.build();
|
auto AST = TU.build();
|
||||||
llvm::StringRef NewName = "dummyNewName";
|
llvm::StringRef NewName = Case.NewName;
|
||||||
auto Results =
|
auto Results =
|
||||||
rename({T.point(), NewName, AST, testPath(TU.Filename), Case.Index});
|
rename({T.point(), NewName, AST, testPath(TU.Filename), Case.Index});
|
||||||
bool WantRename = true;
|
bool WantRename = true;
|
||||||
|
|
Loading…
Reference in New Issue