[clangd] Reduce superfluous rename conflicts (#121515)
This commit adds a namespace check to the code for detecting name
collisions, allowing `bar` to be renamed to `foo` in the following
snippet:
```c
typedef struct foo {} Foo;
Foo bar;
```
Previously, such a rename would fail because a declaration for `foo`
already exists in the same scope.
This commit is contained in:
parent
4fd762caa6
commit
440ea3ecdc
@ -338,7 +338,8 @@ const NamedDecl *lookupSiblingWithinEnclosingScope(ASTContext &Ctx,
|
||||
for (const auto &Child : DS->getDeclGroup())
|
||||
if (const auto *ND = dyn_cast<NamedDecl>(Child))
|
||||
if (ND != &RenamedDecl && ND->getDeclName().isIdentifier() &&
|
||||
ND->getName() == Name)
|
||||
ND->getName() == Name &&
|
||||
ND->getIdentifierNamespace() & RenamedDecl.getIdentifierNamespace())
|
||||
return ND;
|
||||
return nullptr;
|
||||
};
|
||||
@ -380,7 +381,9 @@ const NamedDecl *lookupSiblingWithinEnclosingScope(ASTContext &Ctx,
|
||||
// Also check if there is a name collision with function arguments.
|
||||
if (const auto *Function = ScopeParent->get<FunctionDecl>())
|
||||
for (const auto *Parameter : Function->parameters())
|
||||
if (Parameter->getName() == NewName)
|
||||
if (Parameter->getName() == NewName &&
|
||||
Parameter->getIdentifierNamespace() &
|
||||
RenamedDecl.getIdentifierNamespace())
|
||||
return Parameter;
|
||||
return nullptr;
|
||||
}
|
||||
@ -405,7 +408,9 @@ const NamedDecl *lookupSiblingWithinEnclosingScope(ASTContext &Ctx,
|
||||
if (const auto *EnclosingFunction = Parent->get<FunctionDecl>()) {
|
||||
// Check for conflicts with other arguments.
|
||||
for (const auto *Parameter : EnclosingFunction->parameters())
|
||||
if (Parameter != &RenamedDecl && Parameter->getName() == NewName)
|
||||
if (Parameter != &RenamedDecl && Parameter->getName() == NewName &&
|
||||
Parameter->getIdentifierNamespace() &
|
||||
RenamedDecl.getIdentifierNamespace())
|
||||
return Parameter;
|
||||
// FIXME: We don't modify all references to function parameters when
|
||||
// renaming from forward declaration now, so using a name colliding with
|
||||
@ -450,7 +455,8 @@ const NamedDecl *lookupSiblingsWithinContext(ASTContext &Ctx,
|
||||
}
|
||||
// Lookup may contain the RenameDecl itself, exclude it.
|
||||
for (const auto *D : LookupResult)
|
||||
if (D->getCanonicalDecl() != RenamedDecl.getCanonicalDecl())
|
||||
if (D->getCanonicalDecl() != RenamedDecl.getCanonicalDecl() &&
|
||||
D->getIdentifierNamespace() & RenamedDecl.getIdentifierNamespace())
|
||||
return D;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1269,6 +1269,39 @@ TEST(RenameTest, Renameable) {
|
||||
)cpp",
|
||||
"conflict", !HeaderFile, "Conflict"},
|
||||
|
||||
{R"cpp(
|
||||
struct conflict {};
|
||||
enum v^ar {};
|
||||
)cpp",
|
||||
"conflict", !HeaderFile, "conflict"},
|
||||
|
||||
{R"cpp(
|
||||
struct conflict {};
|
||||
int [[v^ar]];
|
||||
)cpp",
|
||||
nullptr, !HeaderFile, "conflict"},
|
||||
|
||||
{R"cpp(
|
||||
enum conflict {};
|
||||
int [[v^ar]];
|
||||
)cpp",
|
||||
nullptr, !HeaderFile, "conflict"},
|
||||
|
||||
{R"cpp(
|
||||
void func(int conflict) {
|
||||
struct [[t^ag]] {};
|
||||
}
|
||||
)cpp",
|
||||
nullptr, !HeaderFile, "conflict"},
|
||||
|
||||
{R"cpp(
|
||||
void func(void) {
|
||||
struct conflict {};
|
||||
int [[v^ar]];
|
||||
}
|
||||
)cpp",
|
||||
nullptr, !HeaderFile, "conflict"},
|
||||
|
||||
{R"cpp(
|
||||
void func(int);
|
||||
void [[o^therFunc]](double);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user