Skip to content

Commit 4f70a76

Browse files
authored
Merge pull request #63167 from bnbarham/fix-shadowed-rename
[Index] Handle shorthand if let/closure captures in local rename
2 parents c707643 + 4cc7167 commit 4f70a76

File tree

7 files changed

+60
-36
lines changed

7 files changed

+60
-36
lines changed

include/swift/IDE/Utils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ struct ResolvedCursorInfo {
161161
/// that names both the newly declared variable and the referenced variable
162162
/// by the same identifier in the source text. This includes shorthand
163163
/// closure captures (`[foo]`) and shorthand if captures
164-
/// (`if let foo {`).
164+
/// (`if let foo {`). Ordered from innermost to outermost shadows.
165+
///
165166
/// Decls that are shadowed using shorthand syntax should be reported as
166167
/// additional cursor info results.
167168
SmallVector<ValueDecl *> ShorthandShadowedDecls;

lib/IDE/CursorInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class NodeFinder : ASTWalker {
112112
std::unique_ptr<NodeFinderResult> takeResult() { return std::move(Result); }
113113

114114
/// Get the declarations that \p ShadowingDecl shadows using shorthand shadow
115-
/// syntax.
115+
/// syntax. Ordered from innermost to outermost shadows.
116116
SmallVector<ValueDecl *, 2>
117117
getShorthandShadowedDecls(ValueDecl *ShadowingDecl) {
118118
SmallVector<ValueDecl *, 2> Result;

lib/IDE/IDERequests.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ class CursorInfoResolver : public SourceEntityWalker {
6464
llvm::SmallVector<Expr*, 8> ExprStack;
6565
/// If a decl shadows another decl using shorthand syntax (`[foo]` or
6666
/// `if let foo {`), this maps the re-declared variable to the one that is
67-
/// being shadowed.
67+
/// being shadowed. Ordered from innermost to outermost shadows.
68+
///
6869
/// The transitive closure of shorthand shadowed decls should be reported as
6970
/// additional results in cursor info.
7071
llvm::DenseMap<ValueDecl *, ValueDecl *> ShorthandShadowedDecls;
@@ -180,17 +181,14 @@ ResolvedCursorInfo CursorInfoResolver::resolve(SourceLoc Loc) {
180181
walk(SrcFile);
181182

182183
if (auto ValueRefInfo = dyn_cast<ResolvedValueRefCursorInfo>(&CursorInfo)) {
183-
if (!ValueRefInfo->isRef()) {
184-
SmallVector<ValueDecl *> ShadowedDecls;
185-
// If we have a definition, add any decls that it potentially shadows
186-
auto ShorthandShadowedDecl =
187-
ShorthandShadowedDecls[ValueRefInfo->getValueD()];
188-
while (ShorthandShadowedDecl) {
189-
ShadowedDecls.push_back(ShorthandShadowedDecl);
190-
ShorthandShadowedDecl = ShorthandShadowedDecls[ShorthandShadowedDecl];
191-
}
192-
ValueRefInfo->setShorthandShadowedDecls(ShadowedDecls);
184+
SmallVector<ValueDecl *> ShadowedDecls;
185+
auto ShorthandShadowedDecl =
186+
ShorthandShadowedDecls[ValueRefInfo->getValueD()];
187+
while (ShorthandShadowedDecl) {
188+
ShadowedDecls.push_back(ShorthandShadowedDecl);
189+
ShorthandShadowedDecl = ShorthandShadowedDecls[ShorthandShadowedDecl];
193190
}
191+
ValueRefInfo->setShorthandShadowedDecls(ShadowedDecls);
194192
}
195193

196194
return CursorInfo;

lib/Index/Index.cpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,6 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
432432
SymbolInfo SymInfo;
433433
SymbolRoleSet Roles;
434434
SmallVector<IndexedWitness, 6> ExplicitWitnesses;
435-
SmallVector<SourceLoc, 6> RefsToSuppress;
436435
};
437436
SmallVector<Entity, 6> EntitiesStack;
438437
SmallVector<Expr *, 8> ExprStack;
@@ -449,6 +448,9 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
449448
StringScratchSpace stringStorage;
450449
ContainerTracker Containers;
451450

451+
// Already handled references that should be suppressed if found later.
452+
llvm::DenseSet<SourceLoc> RefsToSuppress;
453+
452454
// Contains a mapping for captures of the form [x], from the declared "x"
453455
// to the captured "x" in the enclosing scope. Also includes shorthand if
454456
// let bindings.
@@ -832,7 +834,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
832834
ReferenceMetaData Data) override {
833835
SourceLoc Loc = Range.getStart();
834836

835-
if (isRepressed(Loc) || Loc.isInvalid())
837+
if (Loc.isInvalid() || isSuppressed(Loc))
836838
return true;
837839

838840
// Dig back to the original captured variable
@@ -912,17 +914,13 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
912914
});
913915
}
914916

915-
void repressRefAtLoc(SourceLoc Loc) {
917+
void suppressRefAtLoc(SourceLoc Loc) {
916918
if (Loc.isInvalid()) return;
917-
assert(!EntitiesStack.empty());
918-
EntitiesStack.back().RefsToSuppress.push_back(Loc);
919+
RefsToSuppress.insert(Loc);
919920
}
920921

921-
bool isRepressed(SourceLoc Loc) const {
922-
if (EntitiesStack.empty() || Loc.isInvalid())
923-
return false;
924-
auto &Suppressed = EntitiesStack.back().RefsToSuppress;
925-
return std::find(Suppressed.begin(), Suppressed.end(), Loc) != Suppressed.end();
922+
bool isSuppressed(SourceLoc Loc) const {
923+
return Loc.isValid() && RefsToSuppress.contains(Loc);
926924
}
927925

928926
Expr *getContainingExpr(size_t index) const {
@@ -1253,7 +1251,7 @@ bool IndexSwiftASTWalker::startEntity(Decl *D, IndexSymbol &Info, bool IsRef) {
12531251
if (!handleWitnesses(D, explicitWitnesses))
12541252
return false;
12551253
}
1256-
EntitiesStack.push_back({D, Info.symInfo, Info.roles, std::move(explicitWitnesses), {}});
1254+
EntitiesStack.push_back({D, Info.symInfo, Info.roles, std::move(explicitWitnesses)});
12571255
return true;
12581256
}
12591257
}
@@ -1325,7 +1323,7 @@ bool IndexSwiftASTWalker::reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isI
13251323
Info.roles |= (unsigned)SymbolRole::Implicit;
13261324

13271325
// don't report this ref again when visitDeclReference reports it
1328-
repressRefAtLoc(Loc);
1326+
suppressRefAtLoc(Loc);
13291327

13301328
if (!reportRef(D, Loc, Info, None)) {
13311329
Cancelled = true;
@@ -1491,7 +1489,7 @@ bool IndexSwiftASTWalker::report(ValueDecl *D) {
14911489
// Suppress the reference if there is any (it is implicit and hence
14921490
// already skipped in the shorthand if let case, but explicit in the
14931491
// captured case).
1494-
repressRefAtLoc(loc);
1492+
suppressRefAtLoc(loc);
14951493

14961494
// Skip the definition of a shadowed decl
14971495
return true;

lib/Refactoring/Refactoring.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,11 @@ bool RefactoringActionLocalRename::performChange() {
912912
auto ValueRefCursorInfo = dyn_cast<ResolvedValueRefCursorInfo>(&CursorInfo);
913913
if (ValueRefCursorInfo && ValueRefCursorInfo->getValueD()) {
914914
ValueDecl *VD = ValueRefCursorInfo->typeOrValue();
915+
// The index always uses the outermost shadow for references
916+
if (!ValueRefCursorInfo->getShorthandShadowedDecls().empty()) {
917+
VD = ValueRefCursorInfo->getShorthandShadowedDecls().back();
918+
}
919+
915920
SmallVector<DeclContext *, 8> Scopes;
916921

917922
Optional<RenameRefInfo> RefInfo;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Local rename starts from the `DeclContext` of the renamed `Decl`. For
2+
// closures that means we have no parents, so check that case specifically.
3+
4+
func renameInClosure() {
5+
// RUN: %refactor -rename -dump-text -source-filename %s -pos=%(line+2):10 -new-name=renamed | %FileCheck %s
6+
// CHECK: shorthand_shadow.swift [[# @LINE+1]]:10 -> [[# @LINE+1]]:18
7+
_ = { (toRename: Int?) in
8+
// RUN: %refactor -rename -dump-text -source-filename %s -pos=%(line+2):12 -new-name=renamed | %FileCheck %s
9+
// CHECK: shorthand_shadow.swift [[# @LINE+1]]:12 -> [[# @LINE+1]]:20
10+
if let toRename {
11+
// RUN: %refactor -rename -dump-text -source-filename %s -pos=%(line+2):11 -new-name=renamed | %FileCheck %s
12+
// CHECK: shorthand_shadow.swift [[# @LINE+1]]:11 -> [[# @LINE+1]]:19
13+
_ = toRename
14+
}
15+
}
16+
}

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,6 +1172,7 @@ static bool passCursorInfoForDecl(
11721172
});
11731173
return false;
11741174
}
1175+
11751176
if (MainInfo.VD != OrigInfo.VD && !OrigInfo.Unavailable) {
11761177
CursorSymbolInfo &CtorSymbol = Symbols.emplace_back();
11771178
if (auto Err =
@@ -1182,16 +1183,21 @@ static bool passCursorInfoForDecl(
11821183
Symbols.pop_back();
11831184
}
11841185
}
1185-
for (auto D : Info.getShorthandShadowedDecls()) {
1186-
CursorSymbolInfo &SymbolInfo = Symbols.emplace_back();
1187-
DeclInfo DInfo(D, Type(), /*IsRef=*/true, /*IsDynamic=*/false,
1188-
ArrayRef<NominalTypeDecl *>(), Invoc);
1189-
if (auto Err =
1190-
fillSymbolInfo(SymbolInfo, DInfo, Info.getLoc(), AddSymbolGraph,
1191-
Lang, Invoc, PreviousSnaps, Allocator)) {
1192-
// Ignore but make sure to remove the partially-filled symbol
1193-
llvm::handleAllErrors(std::move(Err), [](const llvm::StringError &E) {});
1194-
Symbols.pop_back();
1186+
1187+
// Add in shadowed declarations if on a decl. For references just go to the
1188+
// actual declaration.
1189+
if (!Info.isRef()) {
1190+
for (auto D : Info.getShorthandShadowedDecls()) {
1191+
CursorSymbolInfo &SymbolInfo = Symbols.emplace_back();
1192+
DeclInfo DInfo(D, Type(), /*IsRef=*/true, /*IsDynamic=*/false,
1193+
ArrayRef<NominalTypeDecl *>(), Invoc);
1194+
if (auto Err =
1195+
fillSymbolInfo(SymbolInfo, DInfo, Info.getLoc(), AddSymbolGraph,
1196+
Lang, Invoc, PreviousSnaps, Allocator)) {
1197+
// Ignore but make sure to remove the partially-filled symbol
1198+
llvm::handleAllErrors(std::move(Err), [](const llvm::StringError &E) {});
1199+
Symbols.pop_back();
1200+
}
11951201
}
11961202
}
11971203

0 commit comments

Comments
 (0)