kbobyrev updated this revision to Diff 321055. kbobyrev added a comment. Revert last change: leads to incomplete types.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D95925/new/ https://reviews.llvm.org/D95925 Files: clang-tools-extra/clangd/refactor/Rename.cpp clang-tools-extra/clangd/unittests/RenameTests.cpp
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/RenameTests.cpp +++ clang-tools-extra/clangd/unittests/RenameTests.cpp @@ -1010,13 +1010,68 @@ )cpp", "conflict", !HeaderFile, nullptr, "Conflict"}, - {R"cpp(// FIXME: detecting local variables is not supported yet. + {R"cpp( void func() { int Conflict; - int [[V^ar]]; + int V^ar; + } + )cpp", + "conflict", !HeaderFile, nullptr, "Conflict"}, + + {R"cpp( + void func() { + if (int Conflict = 42) { + int V^ar; + } + } + )cpp", + "conflict", !HeaderFile, nullptr, "Conflict"}, + + {R"cpp( + void func() { + if (int Conflict = 42) { + } else { + bool V^ar; + } + } + )cpp", + "conflict", !HeaderFile, nullptr, "Conflict"}, + + {R"cpp( + void func() { + if (int V^ar = 42) { + } else { + bool Conflict; + } } )cpp", - nullptr, !HeaderFile, nullptr, "Conflict"}, + "conflict", !HeaderFile, nullptr, "Conflict"}, + + {R"cpp( + void func() { + while (int V^ar = 10) { + bool Conflict = true; + } + } + )cpp", + "conflict", !HeaderFile, nullptr, "Conflict"}, + + {R"cpp( + void func() { + for (int Something = 9000, Anything = 14, Conflict = 42; Anything > 9; + ++Something) { + int V^ar; + } + } + )cpp", + "conflict", !HeaderFile, nullptr, "Conflict"}, + + {R"cpp( + void func(int Conflict) { + bool V^ar; + } + )cpp", + "conflict", !HeaderFile, nullptr, "Conflict"}, {R"cpp(// Trying to rename into the same name, SameName == SameName. void func() { Index: clang-tools-extra/clangd/refactor/Rename.cpp =================================================================== --- clang-tools-extra/clangd/refactor/Rename.cpp +++ clang-tools-extra/clangd/refactor/Rename.cpp @@ -15,8 +15,14 @@ #include "index/SymbolCollector.h" #include "support/Logger.h" #include "support/Trace.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ParentMapContext.h" +#include "clang/AST/Stmt.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Tooling/Syntax/Tokens.h" #include "llvm/ADT/None.h" @@ -318,13 +324,83 @@ return Results; } +// Detect name conflict with othter DeclStmts in the same enclosing scope. +const NamedDecl *lookupSiblingWithinEnclosingScope(ASTContext &Ctx, + const NamedDecl &RenamedDecl, + StringRef NewName) { + DynTypedNodeList Parents = Ctx.getParents(RenamedDecl); + if (Parents.size() != 1 || !Parents.begin()->get<DeclStmt>()) + return nullptr; + Parents = Ctx.getParents(*Parents.begin()->get<DeclStmt>()); + if (Parents.size() != 1) + return nullptr; + // This helper checks if any statement within DeclStmt has NewName. + auto CheckDeclStmt = [&](const DeclStmt *DS) -> const NamedDecl * { + if (!DS) + return nullptr; + for (const auto &Child : DS->getDeclGroup()) + if (const auto *ND = dyn_cast<NamedDecl>(Child)) + if (ND != &RenamedDecl && ND->getName() == NewName) + return ND; + return nullptr; + }; + auto CheckCompoundStmt = [&](const CompoundStmt *CS) -> const NamedDecl * { + if (!CS) + return nullptr; + for (const auto *Node : CS->children()) + if (const auto *Result = CheckDeclStmt(dyn_cast<DeclStmt>(Node))) + return Result; + return nullptr; + }; + // This helper checks if there is a condition variable has NewName. + auto CheckConditionVariable = [&](const auto *Scope) -> const NamedDecl * { + if (!Scope) + return nullptr; + if (const auto *Result = + CheckDeclStmt(Scope->getConditionVariableDeclStmt())) + return Result; + return nullptr; + }; + const auto *ParentNode = Parents.begin(); + if (const auto *EnclosingCS = ParentNode->get<CompoundStmt>()) { + if (const auto *Result = CheckCompoundStmt(EnclosingCS)) + return Result; + Parents = Ctx.getParents(*EnclosingCS); + if (Parents.size() != 1) + return nullptr; + const auto *Parent = Parents.begin(); + if (const auto *Result = CheckConditionVariable(Parent->get<IfStmt>())) + return Result; + if (const auto *Result = CheckConditionVariable(Parent->get<WhileStmt>())) + return Result; + if (const auto *For = Parent->get<ForStmt>()) + if (const auto *Result = + CheckDeclStmt(dyn_cast<DeclStmt>(For->getInit()))) + return Result; + if (const auto *Function = Parent->get<FunctionDecl>()) + for (const auto *Parameter : Function->parameters()) + if (Parameter->getName() == NewName) + return Parameter; + } + if (const auto *EnclosingIf = ParentNode->get<IfStmt>()) { + if (const auto *Result = CheckCompoundStmt( + dyn_cast_or_null<CompoundStmt>(EnclosingIf->getElse()))) + return Result; + return CheckCompoundStmt(dyn_cast<CompoundStmt>(EnclosingIf->getThen())); + } + if (const auto *EnclosingWhile = ParentNode->get<WhileStmt>()) + return CheckCompoundStmt(dyn_cast<CompoundStmt>(EnclosingWhile->getBody())); + if (const auto *EnclosingFor = ParentNode->get<ForStmt>()) + return CheckCompoundStmt(dyn_cast<CompoundStmt>(EnclosingFor->getBody())); + return nullptr; +} + // Lookup the declarations (if any) with the given Name in the context of // RenameDecl. -const NamedDecl *lookupSiblingWithName(const ASTContext &Ctx, - const NamedDecl &RenamedDecl, - llvm::StringRef Name) { - trace::Span Tracer("LookupSiblingWithName"); - const auto &II = Ctx.Idents.get(Name); +const NamedDecl *lookupSiblingsWithinContext(ASTContext &Ctx, + const NamedDecl &RenamedDecl, + llvm::StringRef NewName) { + const auto &II = Ctx.Idents.get(NewName); DeclarationName LookupName(&II); DeclContextLookupResult LookupResult; const auto *DC = RenamedDecl.getDeclContext(); @@ -356,6 +432,16 @@ return nullptr; } +const NamedDecl *lookupSiblingWithName(ASTContext &Ctx, + const NamedDecl &RenamedDecl, + llvm::StringRef NewName) { + trace::Span Tracer("LookupSiblingWithName"); + if (const auto *Result = + lookupSiblingsWithinContext(Ctx, RenamedDecl, NewName)) + return Result; + return lookupSiblingWithinEnclosingScope(Ctx, RenamedDecl, NewName); +} + struct InvalidName { enum Kind { Keywords,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits