Skip to content

Commit c7f32a3

Browse files
authored
Merge pull request #70287 from ahoppen/ahoppen/related-identifiers-for-rename
[SourceKit] Update related identifiers request to serve local rename
2 parents 60b3a4c + 516836c commit c7f32a3

File tree

12 files changed

+206
-105
lines changed

12 files changed

+206
-105
lines changed

lib/Refactoring/SyntacticRenameRangeDetails.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,13 @@ RegionType RenameRangeDetailCollector::addSyntacticRenameRanges(
470470
isCallSite = true;
471471
break;
472472
case RenameLocUsage::Definition:
473-
// All function definitions have argument labels that should be renamed.
474-
handleLabels = true;
473+
// Don't rename labels of operators. There is a mismatch between the
474+
// indexer reporting all labels as `_` even if they are spelled as e.g.
475+
// `x: Int` in the function declaration. Since the labels only appear
476+
// on the operator declaration and in no calls, just don't rename them for
477+
// now.
478+
// For all other (normal) function declarations, always rename the labels.
479+
handleLabels = !Lexer::isOperator(Old.base());
475480
isCallSite = false;
476481
break;
477482
case RenameLocUsage::Reference:
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file --leading-lines %s %t
3+
4+
//--- a.swift
5+
6+
struct Foo {}
7+
// RUN: %sourcekitd-test -req=related-idents -pos=%(line + 1):6 %t/a.swift -- %t/a.swift | %FileCheck %s
8+
func +(x: Foo, y: Foo) {}
9+
Foo() + Foo()
10+
11+
//--- dummy.swift
12+
13+
// CHECK: START RANGES
14+
// CHECK: 8:6 - 1 - source.syntacticrename.definition
15+
// CHECK: 9:7 - 1 - source.syntacticrename.call
16+
// CHECK: END RANGES
17+
// CHECK: NAME: +(_:_:)

test/SourceKit/RelatedIdents/related_idents.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,12 @@ func ifLet(test: Int?) {
109109

110110
// RUN: %sourcekitd-test -req=related-idents -pos=6:17 %s -- -module-name related_idents %s | %FileCheck -check-prefix=CHECK1 %s
111111
// CHECK1: START RANGES
112-
// CHECK1-NEXT: 1:7 - 2
113-
// CHECK1-NEXT: 6:11 - 2
114-
// CHECK1-NEXT: 6:16 - 2
115-
// CHECK1-NEXT: 9:11 - 2
112+
// CHECK1-NEXT: 1:7 - 2 - source.syntacticrename.definition
113+
// CHECK1-NEXT: 6:11 - 2 - source.syntacticrename.reference
114+
// CHECK1-NEXT: 6:16 - 2 - source.syntacticrename.reference
115+
// CHECK1-NEXT: 9:11 - 2 - source.syntacticrename.reference
116116
// CHECK1-NEXT: END RANGES
117+
// CHECK1: NAME: C1
117118

118119
// RUN: %sourcekitd-test -req=related-idents -pos=5:9 %s -- -module-name related_idents %s | %FileCheck -check-prefix=CHECK2 %s
119120
// CHECK2: START RANGES
@@ -196,6 +197,7 @@ func ifLet(test: Int?) {
196197
// CHECK11-NEXT: 74:1 - 13
197198
// CHECK11-NEXT: 75:1 - 11
198199
// CHECK11-NEXT: 76:1 - 11
200+
// CHECK11: NAME: escapedName(x:)
199201

200202

201203
// RUN: %sourcekitd-test -req=related-idents -pos=79:7 %s -- -module-name related_idents %s | %FileCheck -check-prefix=CHECK12 %s

test/refactoring/SyntacticRename/Outputs/functions/infix-operator.swift.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class AStruct {
2828
return {a in a};
2929
}
3030

31-
static func /*infix-operator:def*/<base>+</base> (<arglabel index=0>left</arglabel><param index=0></param>: AStruct, <arglabel index=1>right</arglabel><param index=1></param>: AStruct) -> AStruct {
31+
static func /*infix-operator:def*/<base>+</base> (left: AStruct, right: AStruct) -> AStruct {
3232
return AStruct()
3333
}
3434

test/refactoring/SyntacticRename/Outputs/functions/prefix-operator.swift.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class AStruct {
3232
return AStruct()
3333
}
3434

35-
static prefix func /*prefix-operator:def*/<base>-</base> (<arglabel index=0>struct</arglabel><param index=0></param>: AStruct) -> AStruct {
35+
static prefix func /*prefix-operator:def*/<base>-</base> (struct: AStruct) -> AStruct {
3636
return AStruct()
3737
}
3838
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
// RUN: %refactor -find-rename-ranges -source-filename %t/input.swift -pos="test" -old-name "+(x:y:)" -new-name "-(x:y:)" > %t/output.txt
4+
// RUN: diff -u %t/expected.swift %t/output.txt
5+
6+
//--- input.swift
7+
8+
struct Foo {}
9+
func /*test:def*/+(x: Foo, y: Foo) {}
10+
Foo() /*test:ref*/+ Foo()
11+
12+
//--- expected.swift
13+
14+
struct Foo {}
15+
func /*test:def*/<base>+</base>(x: Foo, y: Foo) {}
16+
Foo() /*test:ref*/<base>+</base> Foo()
17+

tools/SourceKit/include/SourceKit/Core/LangSupport.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,19 @@ struct SemanticRefactoringInfo {
786786
struct RelatedIdentInfo {
787787
unsigned Offset;
788788
unsigned Length;
789+
swift::ide::RenameLocUsage Usage;
790+
};
791+
792+
/// Result of `findRelatedIdentifiersInFile`.
793+
struct RelatedIdentsResult {
794+
SmallVector<RelatedIdentInfo, 8> RelatedIdents;
795+
std::string OldName;
796+
797+
RelatedIdentsResult(SmallVector<RelatedIdentInfo, 8> RelatedIdents,
798+
std::string OldName)
799+
: RelatedIdents(RelatedIdents), OldName(OldName) {}
800+
801+
static RelatedIdentsResult empty() { return RelatedIdentsResult({}, ""); }
789802
};
790803

791804
/// Represent one branch of an if config.
@@ -1149,11 +1162,20 @@ class LangSupport {
11491162
SourceKitCancellationToken CancellationToken,
11501163
std::function<void(const RequestResult<CursorInfoData> &)> Receiver) = 0;
11511164

1165+
/// - Parameters:
1166+
/// - IncludeNonEditableBaseNames: If `true` also return results if the
1167+
/// referenced declaration is an initializer or subscript. This is
1168+
/// intended if the related identifiers response is used for rename, which
1169+
/// allows renaming parameter labels of these declaration.
1170+
/// If the function's base name should be highlighted, this should be
1171+
/// `false` because e.g. highlighting a subscript with
1172+
/// `IncludeNonEditableBaseNames = true` would return the locations of all
1173+
/// `[` that call that subscript.
11521174
virtual void findRelatedIdentifiersInFile(
11531175
StringRef PrimaryFilePath, StringRef InputBufferName, unsigned Offset,
1154-
bool CancelOnSubsequentRequest, ArrayRef<const char *> Args,
1155-
SourceKitCancellationToken CancellationToken,
1156-
std::function<void(const RequestResult<ArrayRef<RelatedIdentInfo>> &)>
1176+
bool IncludeNonEditableBaseNames, bool CancelOnSubsequentRequest,
1177+
ArrayRef<const char *> Args, SourceKitCancellationToken CancellationToken,
1178+
std::function<void(const RequestResult<RelatedIdentsResult> &)>
11571179
Receiver) = 0;
11581180

11591181
virtual void findActiveRegionsInFile(

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -682,10 +682,10 @@ class SwiftLangSupport : public LangSupport {
682682

683683
void findRelatedIdentifiersInFile(
684684
StringRef PrimaryFilePath, StringRef InputBufferName, unsigned Offset,
685-
bool CancelOnSubsequentRequest, ArrayRef<const char *> Args,
686-
SourceKitCancellationToken CancellationToken,
687-
std::function<void(const RequestResult<ArrayRef<RelatedIdentInfo>> &)>
688-
Receiver) override;
685+
bool IncludeNonEditableBaseNames, bool CancelOnSubsequentRequest,
686+
ArrayRef<const char *> Args, SourceKitCancellationToken CancellationToken,
687+
std::function<void(const RequestResult<RelatedIdentsResult> &)> Receiver)
688+
override;
689689

690690
void findActiveRegionsInFile(
691691
StringRef PrimaryFilePath, StringRef InputBufferName,

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 94 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -2491,126 +2491,139 @@ SwiftLangSupport::findUSRRange(StringRef DocumentName, StringRef USR) {
24912491

24922492
void SwiftLangSupport::findRelatedIdentifiersInFile(
24932493
StringRef PrimaryFilePath, StringRef InputBufferName, unsigned Offset,
2494-
bool CancelOnSubsequentRequest, ArrayRef<const char *> Args,
2495-
SourceKitCancellationToken CancellationToken,
2496-
std::function<void(const RequestResult<ArrayRef<RelatedIdentInfo>> &)>
2497-
Receiver) {
2494+
bool IncludeNonEditableBaseNames, bool CancelOnSubsequentRequest,
2495+
ArrayRef<const char *> Args, SourceKitCancellationToken CancellationToken,
2496+
std::function<void(const RequestResult<RelatedIdentsResult> &)> Receiver) {
24982497

24992498
std::string Error;
25002499
SwiftInvocationRef Invok =
25012500
ASTMgr->getTypecheckInvocation(Args, PrimaryFilePath, Error);
25022501
if (!Invok) {
25032502
LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
2504-
Receiver(RequestResult<ArrayRef<RelatedIdentInfo>>::fromError(Error));
2503+
Receiver(RequestResult<RelatedIdentsResult>::fromError(Error));
25052504
return;
25062505
}
25072506

25082507
class RelatedIdConsumer : public SwiftASTConsumer {
25092508
std::string InputFile;
25102509
unsigned Offset;
2511-
std::function<void(const RequestResult<ArrayRef<RelatedIdentInfo>> &)>
2512-
Receiver;
2510+
bool IncludeNonEditableBaseNames;
2511+
std::function<void(const RequestResult<RelatedIdentsResult> &)> Receiver;
25132512
SwiftInvocationRef Invok;
25142513

2514+
#if SWIFT_BUILD_SWIFT_SYNTAX
2515+
// FIXME: Don't silently eat errors here.
2516+
RelatedIdentsResult getRelatedIdents(SourceFile *SrcFile,
2517+
CompilerInstance &CompInst) {
2518+
unsigned BufferID = SrcFile->getBufferID().value();
2519+
SourceLoc Loc = Lexer::getLocForStartOfToken(CompInst.getSourceMgr(),
2520+
BufferID, Offset);
2521+
if (Loc.isInvalid())
2522+
return RelatedIdentsResult::empty();
2523+
2524+
SourceManager &SrcMgr = CompInst.getASTContext().SourceMgr;
2525+
2526+
ResolvedCursorInfoPtr CursorInfo =
2527+
evaluateOrDefault(CompInst.getASTContext().evaluator,
2528+
CursorInfoRequest{CursorInfoOwner(SrcFile, Loc)},
2529+
new ResolvedCursorInfo());
2530+
auto ValueRefCursorInfo =
2531+
dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
2532+
if (!ValueRefCursorInfo)
2533+
return RelatedIdentsResult::empty();
2534+
if (ValueRefCursorInfo->isKeywordArgument())
2535+
return RelatedIdentsResult::empty();
2536+
2537+
ValueDecl *VD = ValueRefCursorInfo->typeOrValue();
2538+
if (!VD)
2539+
return RelatedIdentsResult::empty(); // This was a module reference.
2540+
2541+
// Only accept pointing to an identifier.
2542+
if (!IncludeNonEditableBaseNames && !ValueRefCursorInfo->isRef() &&
2543+
(isa<ConstructorDecl>(VD) || isa<DestructorDecl>(VD) ||
2544+
isa<SubscriptDecl>(VD)))
2545+
return RelatedIdentsResult::empty();
2546+
2547+
llvm::Optional<RenameInfo> Info = getRenameInfo(CursorInfo);
2548+
2549+
if (!Info) {
2550+
return RelatedIdentsResult::empty();
2551+
}
2552+
2553+
RenameLocs Locs = localRenameLocs(SrcFile, Info->VD);
2554+
2555+
std::string OldName = Locs.getLocations().front().OldName.str();
2556+
#ifndef NDEBUG
2557+
for (auto loc : Locs.getLocations()) {
2558+
assert(loc.OldName == OldName &&
2559+
"Found related identfiers with different names?");
2560+
}
2561+
#endif
2562+
2563+
// Ignore any errors produced by `resolveRenameLocations` since, if some
2564+
// symbol failed to resolve, we still want to return all the other
2565+
// symbols. This makes related idents more fault-tolerant.
2566+
DiagnosticEngine Diags(SrcMgr);
2567+
2568+
std::vector<ResolvedLoc> ResolvedLocs = resolveRenameLocations(
2569+
Locs.getLocations(), /*NewName=*/StringRef(), *SrcFile, Diags);
2570+
2571+
SmallVector<RelatedIdentInfo, 8> Ranges;
2572+
assert(ResolvedLocs.size() == Locs.getLocations().size());
2573+
for (auto [RenameLoc, ResolvedLoc] :
2574+
llvm::zip_equal(Locs.getLocations(), ResolvedLocs)) {
2575+
if (ResolvedLoc.range.isInvalid()) {
2576+
continue;
2577+
}
2578+
unsigned Offset =
2579+
SrcMgr.getLocOffsetInBuffer(ResolvedLoc.range.getStart(), BufferID);
2580+
Ranges.push_back(
2581+
{Offset, ResolvedLoc.range.getByteLength(), RenameLoc.Usage});
2582+
}
2583+
2584+
return RelatedIdentsResult(Ranges, OldName);
2585+
}
2586+
#endif
2587+
25152588
public:
25162589
RelatedIdConsumer(
2517-
StringRef InputFile, unsigned Offset,
2518-
std::function<void(const RequestResult<ArrayRef<RelatedIdentInfo>> &)>
2590+
StringRef InputFile, unsigned Offset, bool IncludeNonEditableBaseNames,
2591+
std::function<void(const RequestResult<RelatedIdentsResult> &)>
25192592
Receiver,
25202593
SwiftInvocationRef Invok)
25212594
: InputFile(InputFile.str()), Offset(Offset),
2595+
IncludeNonEditableBaseNames(IncludeNonEditableBaseNames),
25222596
Receiver(std::move(Receiver)), Invok(Invok) {}
25232597

2524-
// FIXME: Don't silently eat errors here.
25252598
void handlePrimaryAST(ASTUnitRef AstUnit) override {
2526-
using ResultType = RequestResult<ArrayRef<RelatedIdentInfo>>;
2599+
using ResultType = RequestResult<RelatedIdentsResult>;
25272600
#if !SWIFT_BUILD_SWIFT_SYNTAX
2528-
Receiver(
2529-
ResultType::fromError("relatedidents is not supported because "
2530-
"sourcekitd was built without swift-syntax"));
2601+
ResultType::fromError(
2602+
"relatedidents is not supported because sourcekitd was built without "
2603+
"swift-syntax");
25312604
return;
25322605
#else
25332606
auto &CompInst = AstUnit->getCompilerInstance();
25342607

25352608
auto *SrcFile = retrieveInputFile(InputFile, CompInst);
25362609
if (!SrcFile) {
2537-
Receiver(RequestResult<ArrayRef<RelatedIdentInfo>>::fromError(
2610+
Receiver(RequestResult<RelatedIdentsResult>::fromError(
25382611
"Unable to find input file"));
25392612
return;
25402613
}
25412614

2542-
SmallVector<RelatedIdentInfo, 8> Ranges;
2543-
2544-
auto Action = [&]() {
2545-
unsigned BufferID = SrcFile->getBufferID().value();
2546-
SourceLoc Loc =
2547-
Lexer::getLocForStartOfToken(CompInst.getSourceMgr(), BufferID, Offset);
2548-
if (Loc.isInvalid())
2549-
return;
2550-
2551-
SourceManager &SrcMgr = CompInst.getASTContext().SourceMgr;
2552-
2553-
ResolvedCursorInfoPtr CursorInfo =
2554-
evaluateOrDefault(CompInst.getASTContext().evaluator,
2555-
CursorInfoRequest{CursorInfoOwner(SrcFile, Loc)},
2556-
new ResolvedCursorInfo());
2557-
auto ValueRefCursorInfo =
2558-
dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
2559-
if (!ValueRefCursorInfo)
2560-
return;
2561-
if (ValueRefCursorInfo->isKeywordArgument())
2562-
return;
2563-
2564-
ValueDecl *VD = ValueRefCursorInfo->typeOrValue();
2565-
if (!VD)
2566-
return; // This was a module reference.
2567-
2568-
// Only accept pointing to an identifier.
2569-
if (!ValueRefCursorInfo->isRef() &&
2570-
(isa<ConstructorDecl>(VD) || isa<DestructorDecl>(VD) ||
2571-
isa<SubscriptDecl>(VD)))
2572-
return;
2573-
if (VD->isOperator())
2574-
return;
2575-
2576-
llvm::Optional<RenameInfo> Info = getRenameInfo(CursorInfo);
2577-
2578-
if (!Info) {
2579-
return;
2580-
}
2581-
2582-
RenameLocs Locs = localRenameLocs(SrcFile, Info->VD);
2583-
2584-
// Ignore any errors produced by `resolveRenameLocations` since, if some
2585-
// symbol failed to resolve, we still want to return all the other
2586-
// symbols. This makes related idents more fault-tolerant.
2587-
DiagnosticEngine Diags(SrcMgr);
2588-
2589-
std::vector<ResolvedLoc> ResolvedLocs = resolveRenameLocations(
2590-
Locs.getLocations(), /*NewName=*/StringRef(), *SrcFile, Diags);
2591-
2592-
assert(ResolvedLocs.size() == Locs.getLocations().size());
2593-
for (auto ResolvedLoc : ResolvedLocs) {
2594-
if (ResolvedLoc.range.isInvalid()) {
2595-
continue;
2596-
}
2597-
unsigned Offset = SrcMgr.getLocOffsetInBuffer(
2598-
ResolvedLoc.range.getStart(), BufferID);
2599-
Ranges.push_back({Offset, ResolvedLoc.range.getByteLength()});
2600-
}
2601-
};
2602-
Action();
2603-
Receiver(ResultType::fromResult(Ranges));
2615+
RelatedIdentsResult Result = getRelatedIdents(SrcFile, CompInst);
2616+
Receiver(ResultType::fromResult(Result));
26042617
#endif
26052618
}
26062619

26072620
void cancelled() override {
2608-
Receiver(RequestResult<ArrayRef<RelatedIdentInfo>>::cancelled());
2621+
Receiver(RequestResult<RelatedIdentsResult>::cancelled());
26092622
}
26102623

26112624
void failed(StringRef Error) override {
26122625
LOG_WARN_FUNC("related idents failed: " << Error);
2613-
Receiver(RequestResult<ArrayRef<RelatedIdentInfo>>::fromError(Error));
2626+
Receiver(RequestResult<RelatedIdentsResult>::fromError(Error));
26142627
}
26152628

26162629
static CaseStmt *getCaseStmtOfCanonicalVar(Decl *D) {
@@ -2624,8 +2637,8 @@ void SwiftLangSupport::findRelatedIdentifiersInFile(
26242637
}
26252638
};
26262639

2627-
auto Consumer = std::make_shared<RelatedIdConsumer>(InputBufferName, Offset,
2628-
Receiver, Invok);
2640+
auto Consumer = std::make_shared<RelatedIdConsumer>(
2641+
InputBufferName, Offset, IncludeNonEditableBaseNames, Receiver, Invok);
26292642
/// FIXME: When request cancellation is implemented and Xcode adopts it,
26302643
/// don't use 'OncePerASTToken'.
26312644
static const char OncePerASTToken = 0;

tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2456,10 +2456,13 @@ static void printRelatedIdents(sourcekitd_variant_t Info, StringRef Filename,
24562456
sourcekitd_variant_t Range = sourcekitd_variant_array_get_value(Res, i);
24572457
int64_t Offset = sourcekitd_variant_dictionary_get_int64(Range, KeyOffset);
24582458
int64_t Length = sourcekitd_variant_dictionary_get_int64(Range, KeyLength);
2459+
auto Usage = sourcekitd_variant_dictionary_get_uid(Range, KeyNameType);
24592460
auto LineCol = resolveToLineCol(Offset, Filename, VFSFiles);
2460-
OS << LineCol.first << ':' << LineCol.second << " - " << Length << '\n';
2461+
OS << LineCol.first << ':' << LineCol.second << " - " << Length << " - "
2462+
<< sourcekitd_uid_get_string_ptr(Usage) << '\n';
24612463
}
24622464
OS << "END RANGES\n";
2465+
OS << "NAME: " << sourcekitd_variant_dictionary_get_string(Info, KeyName);
24632466
}
24642467

24652468
static void printActiveRegions(sourcekitd_variant_t Info, StringRef Filename,

0 commit comments

Comments
 (0)