[SourceKit] Merge RenameLoc and RenameLocation

It’s easier to understand the code if we don’t have these two nearly, but not quite, identical types.
This commit is contained in:
Alex Hoppen
2023-11-17 18:09:09 -08:00
parent d4ee4fa308
commit e538a5ed61
11 changed files with 145 additions and 153 deletions

View File

@@ -10,14 +10,15 @@
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_IDE_REFACTORING_H
#define SWIFT_IDE_REFACTORING_H
#ifndef SWIFT_REFACTORING_REFACTORING_H
#define SWIFT_REFACTORING_REFACTORING_H
#include "swift/AST/DiagnosticConsumer.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/StringExtras.h"
#include "swift/IDE/CancellableResult.h"
#include "swift/IDE/Utils.h"
#include "swift/Refactoring/RenameLoc.h"
#include "llvm/ADT/StringRef.h"
namespace swift {
@@ -61,21 +62,6 @@ struct RenameInfo {
llvm::Optional<RenameInfo> getRenameInfo(ResolvedCursorInfoPtr cursorInfo);
enum class NameUsage {
Unknown,
Reference,
Definition,
Call
};
struct RenameLoc {
unsigned Line;
unsigned Column;
NameUsage Usage;
StringRef OldName;
const bool IsFunctionLike;
};
/// An array of \c RenameLoc that also keeps the underlying string storage of
/// the \c StringRef inside the \c RenameLoc alive.
class RenameLocs {
@@ -184,4 +170,4 @@ collectRefactorings(ResolvedCursorInfoPtr CursorInfo, bool ExcludeRename);
} // namespace ide
} // namespace swift
#endif // SWIFT_IDE_REFACTORING_H
#endif // SWIFT_REFACTORING_REFACTORING_H

View File

@@ -0,0 +1,86 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_REFACTORING_RENAMELOC_H
#define SWIFT_REFACTORING_RENAMELOC_H
#include "swift/Basic/LLVM.h"
namespace swift {
namespace ide {
/// Describes how a `ResolvedLoc` is being used
enum class RenameLocUsage {
/// The definition of a function/subscript/variable/...
Definition,
/// The symbol is being referenced.
///
/// This includes
/// - References to variables
/// - Unapplied references to functions (`myStruct.memberFunc`)
/// - Calls to subscripts (`myArray[1]`, location is `[` here, length 1)
Reference,
/// A function that is being called.
Call,
/// Unknown name usage occurs if we don't have an entry in the index that
/// tells us whether the location is a call, reference or a definition. The
/// most common reasons why this happens is if the editor is adding syntactic
/// results (eg. from comments or string literals).
Unknown
};
/// The input to `findSyntacticRenameRanges`.
///
/// Specifies the location of a base name for which `findSyntacticRenameRanges`
/// should find the argument labels as well as some semantic information needed
/// to resolve the rename ranges.
struct RenameLoc {
/// The line at which the base name starts (1-based).
unsigned Line;
/// The column at which the base name (excluding trivia) starts (1-based).
unsigned Column;
/// /// The offset at which the related name starts.
unsigned Offset;
/// The length of the base name in the related identifier. For functions,
/// this does not include the parameters/arguments.
unsigned Length;
/// How the identifier is being used (call, reference, definition, unknown).
///
/// Used to decide whether a given occurance should be renamed and/or if its
/// argument labels should be renamed.
RenameLocUsage Usage;
/// The old decl name being renamed.
///
/// ### Examples
/// - `foo(a:b:)` for a function with two parameters.
/// - `foo` for a variable.
/// - `foo(_:)` for a function with a single unnamed parameter
/// - `foo()` for a function without parameters.
StringRef OldName;
RenameLoc(unsigned Line, unsigned Column, RenameLocUsage Usage,
StringRef OldName)
: Line(Line), Column(Column), Usage(Usage), OldName(OldName) {}
};
} // namespace ide
} // namespace swift
#endif // SWIFT_REFACTORING_RENAMELOC_H

View File

@@ -77,10 +77,8 @@ static SourceLoc getNewFuncInsertLoc(DeclContext *DC,
return SourceLoc();
}
static std::vector<NoteRegion> getNotableRegions(StringRef SourceText,
unsigned NameOffset,
StringRef Name,
bool IsFunctionLike = false) {
static std::vector<NoteRegion>
getNotableRegions(StringRef SourceText, unsigned NameOffset, StringRef Name) {
auto InputBuffer =
llvm::MemoryBuffer::getMemBufferCopy(SourceText, "<extract>");
@@ -106,8 +104,7 @@ static std::vector<NoteRegion> getNotableRegions(StringRef SourceText,
assert(!Resolved.empty() && "Failed to resolve generated func name loc");
RenameLoc RenameConfig = {LineAndCol.first, LineAndCol.second,
NameUsage::Definition, /*OldName=*/Name,
IsFunctionLike};
RenameLocUsage::Definition, /*OldName=*/Name};
std::vector<RenameRangeDetail> Ranges =
getSyntacticRenameRangeDetails(SM, Name, Resolved.back(), RenameConfig)
.Ranges;
@@ -290,13 +287,11 @@ bool RefactoringActionExtractFunction::performChange() {
StringRef DeclStr(Buffer.begin() + FuncBegin, FuncEnd - FuncBegin);
auto NotableFuncRegions =
getNotableRegions(DeclStr, FuncNameOffset, ExtractedFuncName,
/*IsFunctionLike=*/true);
getNotableRegions(DeclStr, FuncNameOffset, ExtractedFuncName);
StringRef CallStr(Buffer.begin() + ReplaceBegin, ReplaceEnd - ReplaceBegin);
auto NotableCallRegions =
getNotableRegions(CallStr, CallNameOffset, ExtractedFuncName,
/*IsFunctionLike=*/true);
getNotableRegions(CallStr, CallNameOffset, ExtractedFuncName);
// Insert the new function's declaration.
EditConsumer.accept(SM, InsertLoc, DeclStr, NotableFuncRegions);

View File

@@ -219,7 +219,6 @@ private:
locations.push_back(std::move(*loc));
} else {
assert(existingLoc->OldName == loc->OldName &&
existingLoc->IsFunctionLike == loc->IsFunctionLike &&
"Asked to do a different rename for the same location?");
}
}
@@ -241,37 +240,19 @@ RenameRangeCollector::indexSymbolToRenameLoc(const index::IndexSymbol &symbol) {
return llvm::None;
}
NameUsage usage = NameUsage::Unknown;
RenameLocUsage usage = RenameLocUsage::Unknown;
if (symbol.roles & (unsigned)index::SymbolRole::Call) {
usage = NameUsage::Call;
usage = RenameLocUsage::Call;
} else if (symbol.roles & (unsigned)index::SymbolRole::Definition) {
usage = NameUsage::Definition;
usage = RenameLocUsage::Definition;
} else if (symbol.roles & (unsigned)index::SymbolRole::Reference) {
usage = NameUsage::Reference;
usage = RenameLocUsage::Reference;
} else {
llvm_unreachable("unexpected role");
}
bool isFunctionLike = false;
switch (symbol.symInfo.Kind) {
case index::SymbolKind::EnumConstant:
case index::SymbolKind::Function:
case index::SymbolKind::Constructor:
case index::SymbolKind::ConversionFunction:
case index::SymbolKind::InstanceMethod:
case index::SymbolKind::ClassMethod:
case index::SymbolKind::StaticMethod:
isFunctionLike = true;
break;
case index::SymbolKind::Class:
case index::SymbolKind::Enum:
case index::SymbolKind::Struct:
default:
break;
}
StringRef oldName = stringStorage->copyString(symbol.name);
return RenameLoc{symbol.line, symbol.column, usage, oldName, isFunctionLike};
return RenameLoc{symbol.line, symbol.column, usage, oldName};
}
/// Get the decl context that we need to walk when renaming \p VD.

View File

@@ -63,7 +63,7 @@ swift::ide::resolveRenameLocations(ArrayRef<RenameLoc> RenameLocs,
return {};
}
if (RenameLoc.Usage == NameUsage::Call && !RenameLoc.IsFunctionLike) {
if (RenameLoc.Usage == RenameLocUsage::Call && !OldName.isFunction()) {
Diags.diagnose(Location, diag::name_not_functionlike, NewName);
return {};
}

View File

@@ -396,13 +396,13 @@ RegionType RenameRangeDetailCollector::addSyntacticRenameRanges(
if (!resolved.range.isValid())
return RegionType::Unmatched;
NameUsage usage = config.Usage;
RenameLocUsage usage = config.Usage;
auto regionKind = getSyntacticRenameRegionType(resolved);
SpecialBaseName specialBaseName = specialBaseNameFor(Old);
if (usage == NameUsage::Unknown) {
if (usage == RenameLocUsage::Unknown) {
// Unknown name usage occurs if we don't have an entry in the index that
// tells us whether the location is a call, reference or a definition. The
// most common reasons why this happens is if the editor is adding syntactic
@@ -440,7 +440,8 @@ RegionType RenameRangeDetailCollector::addSyntacticRenameRanges(
// be called as `myStruct()`, so even if the base fails to be renamed,
// continue.
// But the names do need to match for definitions and references.
if (usage == NameUsage::Definition || usage == NameUsage::Reference) {
if (usage == RenameLocUsage::Definition ||
usage == RenameLocUsage::Reference) {
return RegionType::Mismatch;
}
}
@@ -450,7 +451,7 @@ RegionType RenameRangeDetailCollector::addSyntacticRenameRanges(
// Accesses to the subscript are modelled as references with `[` as the
// base name, which does not match. Subscripts are never called in the
// index.
if (usage == NameUsage::Definition) {
if (usage == RenameLocUsage::Definition) {
if (renameBase(resolved.range, RefactoringRangeKind::KeywordBaseName)) {
return RegionType::Mismatch;
}
@@ -462,18 +463,18 @@ RegionType RenameRangeDetailCollector::addSyntacticRenameRanges(
bool isCallSite = false;
if (Old.isFunction()) {
switch (usage) {
case NameUsage::Call:
case RenameLocUsage::Call:
// All calls except for operators have argument labels that should be
// renamed.
handleLabels = !Lexer::isOperator(Old.base());
isCallSite = true;
break;
case NameUsage::Definition:
case RenameLocUsage::Definition:
// All function definitions have argument labels that should be renamed.
handleLabels = true;
isCallSite = false;
break;
case NameUsage::Reference:
case RenameLocUsage::Reference:
if (resolved.labelType == LabelRangeType::CompoundName) {
// If we have a compound name that specifies argument labels to
// disambiguate functions with the same base name, we always need to
@@ -491,7 +492,7 @@ RegionType RenameRangeDetailCollector::addSyntacticRenameRanges(
isCallSite = false;
}
break;
case NameUsage::Unknown:
case RenameLocUsage::Unknown:
// If we don't know where the function is used, fall back to trying to
// rename labels if there are some.
handleLabels = resolved.labelType != LabelRangeType::None;
@@ -505,8 +506,8 @@ RegionType RenameRangeDetailCollector::addSyntacticRenameRanges(
renameLabels(resolved.labelRanges, resolved.firstTrailingLabel,
resolved.labelType, isCallSite);
if (renameLabelsFailed) {
return usage == NameUsage::Unknown ? RegionType::Unmatched
: RegionType::Mismatch;
return usage == RenameLocUsage::Unknown ? RegionType::Unmatched
: RegionType::Mismatch;
}
}

View File

@@ -19,6 +19,7 @@
#include "swift/AST/Type.h"
#include "swift/IDE/CancellableResult.h"
#include "swift/IDE/CodeCompletionResult.h"
#include "swift/Refactoring/RenameLoc.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
@@ -37,6 +38,7 @@ namespace llvm {
namespace SourceKit {
class GlobalConfig;
using swift::ide::CancellableResult;
using swift::ide::RenameLoc;
struct EntityInfo {
UIdent Kind;
@@ -893,25 +895,6 @@ struct CategorizedRenameRanges {
std::vector<RenameRangeDetail> Ranges;
};
enum class RenameType {
Unknown,
Definition,
Reference,
Call
};
struct RenameLocation {
unsigned Line;
unsigned Column;
RenameType Type;
};
struct RenameLocations {
StringRef OldName;
const bool IsFunctionLike;
std::vector<RenameLocation> LineColumnLocs;
};
struct IndexStoreOptions {
std::string IndexStorePath;
std::string IndexUnitOutputPath;
@@ -1192,7 +1175,7 @@ public:
virtual CancellableResult<std::vector<CategorizedRenameRanges>>
findRenameRanges(llvm::MemoryBuffer *InputBuf,
ArrayRef<RenameLocations> RenameLocations,
ArrayRef<RenameLoc> RenameLocations,
ArrayRef<const char *> Args) = 0;
virtual void
findLocalRenameRanges(StringRef Filename, unsigned Line, unsigned Column,

View File

@@ -1344,22 +1344,6 @@ void RequestRefactoringEditConsumer::handleDiagnostic(
Impl.DiagConsumer.handleDiagnostic(SM, Info);
}
static NameUsage getNameUsage(RenameType Type) {
switch (Type) {
case RenameType::Definition:
return NameUsage::Definition;
case RenameType::Reference:
return NameUsage::Reference;
case RenameType::Call:
return NameUsage::Call;
case RenameType::Unknown:
return NameUsage::Unknown;
}
}
static std::vector<RenameLoc>
getSyntacticRenameLocs(ArrayRef<RenameLocations> RenameLocations);
/// Translates a vector of \c SyntacticRenameRangeDetails to a vector of
/// \c CategorizedRenameRanges.
static std::vector<CategorizedRenameRanges> getCategorizedRenameRanges(
@@ -1390,7 +1374,7 @@ static std::vector<CategorizedRenameRanges> getCategorizedRenameRanges(
CancellableResult<std::vector<CategorizedRenameRanges>>
SwiftLangSupport::findRenameRanges(llvm::MemoryBuffer *InputBuf,
ArrayRef<RenameLocations> RenameLocations,
ArrayRef<RenameLoc> RenameLocs,
ArrayRef<const char *> Args) {
using ResultType = CancellableResult<std::vector<CategorizedRenameRanges>>;
std::string Error;
@@ -1402,7 +1386,6 @@ SwiftLangSupport::findRenameRanges(llvm::MemoryBuffer *InputBuf,
return ResultType::failure(Error);
}
auto RenameLocs = getSyntacticRenameLocs(RenameLocations);
auto SyntacticRenameRanges =
swift::ide::findSyntacticRenameRanges(SF, RenameLocs,
/*NewName=*/StringRef());
@@ -1503,19 +1486,6 @@ SourceFile *SwiftLangSupport::getSyntacticSourceFile(
return SF;
}
static std::vector<RenameLoc>
getSyntacticRenameLocs(ArrayRef<RenameLocations> RenameLocations) {
std::vector<RenameLoc> RenameLocs;
for(const auto &Locations: RenameLocations) {
for(const auto &Location: Locations.LineColumnLocs) {
RenameLocs.push_back({Location.Line, Location.Column,
getNameUsage(Location.Type), Locations.OldName,
Locations.IsFunctionLike});
}
}
return RenameLocs;
}
void SwiftLangSupport::getDocInfo(llvm::MemoryBuffer *InputBuf,
StringRef ModuleName,
ArrayRef<const char *> Args,

View File

@@ -695,7 +695,7 @@ public:
CancellableResult<std::vector<CategorizedRenameRanges>>
findRenameRanges(llvm::MemoryBuffer *InputBuf,
ArrayRef<RenameLocations> RenameLocations,
ArrayRef<RenameLoc> RenameLocations,
ArrayRef<const char *> Args) override;
void findLocalRenameRanges(StringRef Filename, unsigned Line, unsigned Column,

View File

@@ -311,7 +311,7 @@ editorFindModuleGroups(StringRef ModuleName, ArrayRef<const char *> Args);
static bool
buildRenameLocationsFromDict(const RequestDict &Req,
std::vector<RenameLocations> &RenameLocations,
std::vector<RenameLoc> &RenameLocations,
llvm::SmallString<64> &Error);
static sourcekitd_response_t
@@ -323,7 +323,7 @@ static sourcekitd_response_t createCategorizedRenameRangesResponse(
static sourcekitd_response_t
findRenameRanges(llvm::MemoryBuffer *InputBuf,
ArrayRef<RenameLocations> RenameLocations,
ArrayRef<RenameLoc> RenameLocations,
ArrayRef<const char *> Args);
static bool isSemanticEditorDisabled();
@@ -1069,7 +1069,7 @@ handleRequestFindRenameRanges(const RequestDict &Req,
return;
SmallString<64> ErrBuf;
std::vector<RenameLocations> RenameLocations;
std::vector<RenameLoc> RenameLocations;
if (buildRenameLocationsFromDict(Req, RenameLocations, ErrBuf))
return Rec(createErrorRequestFailed(ErrBuf.c_str()));
return Rec(findRenameRanges(InputBuf.get(), RenameLocations, Args));
@@ -3996,25 +3996,16 @@ editorFindModuleGroups(StringRef ModuleName, ArrayRef<const char *> Args) {
static bool
buildRenameLocationsFromDict(const RequestDict &Req,
std::vector<RenameLocations> &RenameLocations,
std::vector<RenameLoc> &RenameLocations,
llvm::SmallString<64> &Error) {
bool Failed = Req.dictionaryArrayApply(KeyRenameLocations,
[&](RequestDict RenameLocation) {
int64_t IsFunctionLike = false;
if (RenameLocation.getInt64(KeyIsFunctionLike, IsFunctionLike, false)) {
Error = "missing key.is_function_like";
return true;
}
Optional<StringRef> OldName = RenameLocation.getString(KeyName);
if (!OldName.has_value()) {
Error = "missing key.name";
return true;
}
RenameLocations.push_back(
{*OldName, static_cast<bool>(IsFunctionLike), {}});
auto &LineCols = RenameLocations.back().LineColumnLocs;
bool Failed = RenameLocation.dictionaryArrayApply(KeyLocations,
[&](RequestDict LineAndCol) {
int64_t Line = 0;
@@ -4034,19 +4025,21 @@ buildRenameLocationsFromDict(const RequestDict &Req,
Error = "missing key.nametype";
return true;
}
RenameType RenameType = RenameType::Unknown;
using swift::ide::RenameLocUsage;
RenameLocUsage RenameType = RenameLocUsage::Unknown;
if (NameType == KindDefinition) {
RenameType = RenameType::Definition;
RenameType = RenameLocUsage::Definition;
} else if (NameType == KindReference) {
RenameType = RenameType::Reference;
RenameType = RenameLocUsage::Reference;
} else if (NameType == KindCall) {
RenameType = RenameType::Call;
RenameType = RenameLocUsage::Call;
} else if (NameType != KindUnknown) {
Error = "invalid value for 'key.nametype'";
return true;
}
LineCols.push_back({static_cast<unsigned>(Line),
static_cast<unsigned>(Column), RenameType});
RenameLocations.emplace_back(
static_cast<unsigned>(Line), static_cast<unsigned>(Column),
RenameType, *OldName);
return false;
});
if (Failed && Error.empty()) {
@@ -4145,7 +4138,7 @@ static sourcekitd_response_t createCategorizedRenameRangesResponse(
static sourcekitd_response_t
findRenameRanges(llvm::MemoryBuffer *InputBuf,
ArrayRef<RenameLocations> RenameLocations,
ArrayRef<RenameLoc> RenameLocations,
ArrayRef<const char *> Args) {
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
CancellableResult<std::vector<CategorizedRenameRanges>> ReqResult =

View File

@@ -176,18 +176,18 @@ bool doesFileExist(StringRef Path) {
struct RefactorLoc {
unsigned Line;
unsigned Column;
NameUsage Usage;
RenameLocUsage Usage;
};
NameUsage convertToNameUsage(StringRef RoleString) {
RenameLocUsage convertToNameUsage(StringRef RoleString) {
if (RoleString == "unknown")
return NameUsage::Unknown;
return RenameLocUsage::Unknown;
if (RoleString == "def")
return NameUsage::Definition;
return RenameLocUsage::Definition;
if (RoleString == "ref")
return NameUsage::Reference;
return RenameLocUsage::Reference;
if (RoleString == "call")
return NameUsage::Call;
return RenameLocUsage::Call;
llvm_unreachable("unhandled role string");
}
@@ -201,8 +201,8 @@ std::vector<RefactorLoc> getLocsByLabelOrPosition(StringRef LabelOrLineCol,
if (LabelOrLineCol.contains(':')) {
auto LineCol = parseLineCol(LabelOrLineCol);
if (LineCol.has_value()) {
LocResults.push_back({LineCol.value().first,LineCol.value().second,
NameUsage::Unknown});
LocResults.push_back({LineCol.value().first, LineCol.value().second,
RenameLocUsage::Unknown});
} else {
llvm::errs() << "cannot parse position pair.";
}
@@ -231,7 +231,7 @@ std::vector<RefactorLoc> getLocsByLabelOrPosition(StringRef LabelOrLineCol,
unsigned ColumnOffset = 0;
if (Matches[2].length() > 0 && !llvm::to_integer(Matches[2].str(), ColumnOffset))
continue; // bad column offset
auto Usage = NameUsage::Reference;
auto Usage = RenameLocUsage::Reference;
if (Matches[3].length() > 0)
Usage = convertToNameUsage(Matches[3].str());
LocResults.push_back({Line, Column + ColumnOffset, Usage});
@@ -242,14 +242,12 @@ std::vector<RefactorLoc> getLocsByLabelOrPosition(StringRef LabelOrLineCol,
std::vector<RenameLoc> getRenameLocs(unsigned BufferID, SourceManager &SM,
ArrayRef<RefactorLoc> Locs,
StringRef OldName, StringRef NewName,
bool IsFunctionLike) {
StringRef OldName, StringRef NewName) {
std::vector<RenameLoc> Renames;
llvm::transform(
Locs, std::back_inserter(Renames),
[&](const RefactorLoc &Loc) -> RenameLoc {
return {Loc.Line, Loc.Column, Loc.Usage, OldName, IsFunctionLike};
});
llvm::transform(Locs, std::back_inserter(Renames),
[&](const RefactorLoc &Loc) -> RenameLoc {
return {Loc.Line, Loc.Column, Loc.Usage, OldName};
});
return Renames;
}
@@ -451,8 +449,7 @@ int main(int argc, char *argv[]) {
}
std::vector<RenameLoc> RenameLocs =
getRenameLocs(BufferID, SM, Start, options::OldName, NewName,
options::IsFunctionLike.getNumOccurrences());
getRenameLocs(BufferID, SM, Start, options::OldName, NewName);
if (options::Action != RefactoringKind::FindGlobalRenameRanges) {
llvm_unreachable("unexpected refactoring kind");