[SourceKit] Return the old name from the related identifiers response

This commit is contained in:
Alex Hoppen
2023-12-06 14:46:48 -08:00
parent 143dccbdf5
commit ddf4a2e3fb
6 changed files with 111 additions and 83 deletions

View File

@@ -2493,125 +2493,137 @@ void SwiftLangSupport::findRelatedIdentifiersInFile(
StringRef PrimaryFilePath, StringRef InputBufferName, unsigned Offset,
bool CancelOnSubsequentRequest, ArrayRef<const char *> Args,
SourceKitCancellationToken CancellationToken,
std::function<void(const RequestResult<ArrayRef<RelatedIdentInfo>> &)>
Receiver) {
std::function<void(const RequestResult<RelatedIdentsResult> &)> Receiver) {
std::string Error;
SwiftInvocationRef Invok =
ASTMgr->getTypecheckInvocation(Args, PrimaryFilePath, Error);
if (!Invok) {
LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
Receiver(RequestResult<ArrayRef<RelatedIdentInfo>>::fromError(Error));
Receiver(RequestResult<RelatedIdentsResult>::fromError(Error));
return;
}
class RelatedIdConsumer : public SwiftASTConsumer {
std::string InputFile;
unsigned Offset;
std::function<void(const RequestResult<ArrayRef<RelatedIdentInfo>> &)>
Receiver;
std::function<void(const RequestResult<RelatedIdentsResult> &)> Receiver;
SwiftInvocationRef Invok;
#if SWIFT_BUILD_SWIFT_SYNTAX
// FIXME: Don't silently eat errors here.
RelatedIdentsResult getRelatedIdents(SourceFile *SrcFile,
CompilerInstance &CompInst) {
unsigned BufferID = SrcFile->getBufferID().value();
SourceLoc Loc = Lexer::getLocForStartOfToken(CompInst.getSourceMgr(),
BufferID, Offset);
if (Loc.isInvalid())
return RelatedIdentsResult::empty();
SourceManager &SrcMgr = CompInst.getASTContext().SourceMgr;
ResolvedCursorInfoPtr CursorInfo =
evaluateOrDefault(CompInst.getASTContext().evaluator,
CursorInfoRequest{CursorInfoOwner(SrcFile, Loc)},
new ResolvedCursorInfo());
auto ValueRefCursorInfo =
dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
if (!ValueRefCursorInfo)
return RelatedIdentsResult::empty();
if (ValueRefCursorInfo->isKeywordArgument())
return RelatedIdentsResult::empty();
ValueDecl *VD = ValueRefCursorInfo->typeOrValue();
if (!VD)
return RelatedIdentsResult::empty(); // This was a module reference.
// Only accept pointing to an identifier.
if (!ValueRefCursorInfo->isRef() &&
(isa<ConstructorDecl>(VD) || isa<DestructorDecl>(VD) ||
isa<SubscriptDecl>(VD)))
return RelatedIdentsResult::empty();
if (VD->isOperator())
return RelatedIdentsResult::empty();
llvm::Optional<RenameInfo> Info = getRenameInfo(CursorInfo);
if (!Info) {
return RelatedIdentsResult::empty();
}
RenameLocs Locs = localRenameLocs(SrcFile, Info->VD);
std::string OldName = Locs.getLocations().front().OldName.str();
#ifndef NDEBUG
for (auto loc : Locs.getLocations()) {
assert(loc.OldName == OldName &&
"Found related identfiers with different names?");
}
#endif
// Ignore any errors produced by `resolveRenameLocations` since, if some
// symbol failed to resolve, we still want to return all the other
// symbols. This makes related idents more fault-tolerant.
DiagnosticEngine Diags(SrcMgr);
std::vector<ResolvedLoc> ResolvedLocs = resolveRenameLocations(
Locs.getLocations(), /*NewName=*/StringRef(), *SrcFile, Diags);
SmallVector<RelatedIdentInfo, 8> Ranges;
assert(ResolvedLocs.size() == Locs.getLocations().size());
for (auto [RenameLoc, ResolvedLoc] :
llvm::zip_equal(Locs.getLocations(), ResolvedLocs)) {
if (ResolvedLoc.range.isInvalid()) {
continue;
}
unsigned Offset =
SrcMgr.getLocOffsetInBuffer(ResolvedLoc.range.getStart(), BufferID);
Ranges.push_back(
{Offset, ResolvedLoc.range.getByteLength(), RenameLoc.Usage});
}
return RelatedIdentsResult(Ranges, OldName);
}
#endif
public:
RelatedIdConsumer(
StringRef InputFile, unsigned Offset,
std::function<void(const RequestResult<ArrayRef<RelatedIdentInfo>> &)>
std::function<void(const RequestResult<RelatedIdentsResult> &)>
Receiver,
SwiftInvocationRef Invok)
: InputFile(InputFile.str()), Offset(Offset),
Receiver(std::move(Receiver)), Invok(Invok) {}
// FIXME: Don't silently eat errors here.
void handlePrimaryAST(ASTUnitRef AstUnit) override {
using ResultType = RequestResult<ArrayRef<RelatedIdentInfo>>;
using ResultType = RequestResult<RelatedIdentsResult>;
#if !SWIFT_BUILD_SWIFT_SYNTAX
Receiver(
ResultType::fromError("relatedidents is not supported because "
"sourcekitd was built without swift-syntax"));
ResultType::fromError(
"relatedidents is not supported because sourcekitd was built without "
"swift-syntax");
return;
#else
auto &CompInst = AstUnit->getCompilerInstance();
auto *SrcFile = retrieveInputFile(InputFile, CompInst);
if (!SrcFile) {
Receiver(RequestResult<ArrayRef<RelatedIdentInfo>>::fromError(
Receiver(RequestResult<RelatedIdentsResult>::fromError(
"Unable to find input file"));
return;
}
SmallVector<RelatedIdentInfo, 8> Ranges;
auto Action = [&]() {
unsigned BufferID = SrcFile->getBufferID().value();
SourceLoc Loc =
Lexer::getLocForStartOfToken(CompInst.getSourceMgr(), BufferID, Offset);
if (Loc.isInvalid())
return;
SourceManager &SrcMgr = CompInst.getASTContext().SourceMgr;
ResolvedCursorInfoPtr CursorInfo =
evaluateOrDefault(CompInst.getASTContext().evaluator,
CursorInfoRequest{CursorInfoOwner(SrcFile, Loc)},
new ResolvedCursorInfo());
auto ValueRefCursorInfo =
dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
if (!ValueRefCursorInfo)
return;
if (ValueRefCursorInfo->isKeywordArgument())
return;
ValueDecl *VD = ValueRefCursorInfo->typeOrValue();
if (!VD)
return; // This was a module reference.
// Only accept pointing to an identifier.
if (!ValueRefCursorInfo->isRef() &&
(isa<ConstructorDecl>(VD) || isa<DestructorDecl>(VD) ||
isa<SubscriptDecl>(VD)))
return;
if (VD->isOperator())
return;
llvm::Optional<RenameInfo> Info = getRenameInfo(CursorInfo);
if (!Info) {
return;
}
RenameLocs Locs = localRenameLocs(SrcFile, Info->VD);
// Ignore any errors produced by `resolveRenameLocations` since, if some
// symbol failed to resolve, we still want to return all the other
// symbols. This makes related idents more fault-tolerant.
DiagnosticEngine Diags(SrcMgr);
std::vector<ResolvedLoc> ResolvedLocs = resolveRenameLocations(
Locs.getLocations(), /*NewName=*/StringRef(), *SrcFile, Diags);
assert(ResolvedLocs.size() == Locs.getLocations().size());
for (auto ResolvedLoc : ResolvedLocs) {
if (ResolvedLoc.range.isInvalid()) {
continue;
}
unsigned Offset = SrcMgr.getLocOffsetInBuffer(
ResolvedLoc.range.getStart(), BufferID);
Ranges.push_back(
{Offset, ResolvedLoc.range.getByteLength(), RenameLoc.Usage});
}
};
Action();
Receiver(ResultType::fromResult(Ranges));
RelatedIdentsResult Result = getRelatedIdents(SrcFile, CompInst);
Receiver(ResultType::fromResult(Result));
#endif
}
void cancelled() override {
Receiver(RequestResult<ArrayRef<RelatedIdentInfo>>::cancelled());
Receiver(RequestResult<RelatedIdentsResult>::cancelled());
}
void failed(StringRef Error) override {
LOG_WARN_FUNC("related idents failed: " << Error);
Receiver(RequestResult<ArrayRef<RelatedIdentInfo>>::fromError(Error));
Receiver(RequestResult<RelatedIdentsResult>::fromError(Error));
}
static CaseStmt *getCaseStmtOfCanonicalVar(Decl *D) {