Skip to content

Commit f773e98

Browse files
committed
[SourceKit/CursorInfo] Include line and column in result
Add line/column in addition to offset so clients need not map it themselves.
1 parent 828d127 commit f773e98

File tree

7 files changed

+119
-94
lines changed

7 files changed

+119
-94
lines changed

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,14 @@ struct ReferencedDeclInfo {
405405
IsSPI(SPI), ParentContexts(Parents) {}
406406
};
407407

408+
struct LocationInfo {
409+
StringRef Filename;
410+
unsigned Offset = 0;
411+
unsigned Length = 0;
412+
unsigned Line = 0;
413+
unsigned Column = 0;
414+
};
415+
408416
struct CursorSymbolInfo {
409417
UIdent Kind;
410418
UIdent DeclarationLang;
@@ -430,11 +438,8 @@ struct CursorSymbolInfo {
430438
/// Non-empty if a generated interface editor document has previously been
431439
/// opened for the module the symbol came from.
432440
StringRef ModuleInterfaceName;
433-
/// This is an (offset,length) pair. It is set only if the declaration has a
434-
/// source location.
435-
llvm::Optional<std::pair<unsigned, unsigned>> DeclarationLoc = None;
436-
/// Set only if the declaration has a source location.
437-
StringRef Filename;
441+
/// Filename is non-empty if there's a source location.
442+
LocationInfo Location;
438443
/// For methods this lists the USRs of the overrides in the class hierarchy.
439444
ArrayRef<StringRef> OverrideUSRs;
440445
/// Related declarations, overloaded functions etc., in annotated XML form.

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,6 +2295,17 @@ ImmutableTextSnapshotRef SwiftEditorDocument::getLatestSnapshot() const {
22952295
return Impl.EditableBuffer->getSnapshot();
22962296
}
22972297

2298+
std::pair<unsigned, unsigned>
2299+
SwiftEditorDocument::getLineAndColumnInBuffer(unsigned Offset) {
2300+
llvm::sys::ScopedLock L(Impl.AccessMtx);
2301+
2302+
auto SyntaxInfo = Impl.getSyntaxInfo();
2303+
auto &SM = SyntaxInfo->getSourceManager();
2304+
2305+
auto Loc = SM.getLocForOffset(SyntaxInfo->getBufferID(), Offset);
2306+
return SM.getLineAndColumnInBuffer(Loc);
2307+
}
2308+
22982309
void SwiftEditorDocument::reportDocumentStructure(SourceFile &SrcFile,
22992310
EditorConsumer &Consumer) {
23002311
ide::SyntaxModelContext ModelContext(SrcFile);

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class SwiftEditorDocument :
105105
void removeCachedAST();
106106

107107
ImmutableTextSnapshotRef getLatestSnapshot() const;
108+
std::pair<unsigned, unsigned> getLineAndColumnInBuffer(unsigned Offset);
108109

109110
void parse(ImmutableTextSnapshotRef Snapshot, SwiftLangSupport &Lang,
110111
bool BuildSyntaxTree,

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -600,38 +600,46 @@ mapOffsetToNewerSnapshot(unsigned Offset,
600600
return None;
601601
}
602602

603-
/// Tries to remap the location from a previous snapshot to the latest one.
604-
static llvm::Optional<std::pair<unsigned, unsigned>>
605-
tryRemappingLocToLatestSnapshot(SwiftLangSupport &Lang,
606-
std::pair<unsigned, unsigned> Range,
607-
StringRef Filename,
608-
ArrayRef<ImmutableTextSnapshotRef> PreviousASTSnaps) {
609-
ImmutableTextSnapshotRef LatestSnap;
610-
if (auto EditorDoc = Lang.getEditorDocuments()->findByPath(Filename))
611-
LatestSnap = EditorDoc->getLatestSnapshot();
603+
/// Tries to remap the location from a previous snapshot to the latest one and
604+
/// then sets the location's line and column.
605+
static void mapLocToLatestSnapshot(
606+
SwiftLangSupport &Lang, LocationInfo &Location,
607+
ArrayRef<ImmutableTextSnapshotRef> PreviousASTSnaps) {
608+
auto EditorDoc = Lang.getEditorDocuments()->findByPath(Location.Filename);
609+
if (!EditorDoc)
610+
return;
611+
612+
ImmutableTextSnapshotRef LatestSnap = EditorDoc->getLatestSnapshot();
612613
if (!LatestSnap)
613-
return Range;
614+
return;
614615

615616
for (auto &PrevSnap : PreviousASTSnaps) {
616617
if (PrevSnap->isFromSameBuffer(LatestSnap)) {
617618
if (PrevSnap->getStamp() == LatestSnap->getStamp())
618-
return Range;
619+
break;
619620

620-
auto OptBegin = mapOffsetToNewerSnapshot(Range.first,
621+
auto OptBegin = mapOffsetToNewerSnapshot(Location.Offset,
621622
PrevSnap, LatestSnap);
622-
if (!OptBegin.hasValue())
623-
return None;
623+
if (!OptBegin.hasValue()) {
624+
Location.Filename = StringRef();
625+
return;
626+
}
624627

625-
auto OptEnd = mapOffsetToNewerSnapshot(Range.first+Range.second,
628+
auto OptEnd = mapOffsetToNewerSnapshot(Location.Offset +
629+
Location.Length,
626630
PrevSnap, LatestSnap);
627-
if (!OptEnd.hasValue())
628-
return None;
631+
if (!OptEnd.hasValue()) {
632+
Location.Filename = StringRef();
633+
return;
634+
}
629635

630-
return std::make_pair(*OptBegin, *OptEnd-*OptBegin);
636+
Location.Offset = *OptBegin;
637+
Location.Length = *OptEnd - *OptBegin;
631638
}
632639
}
633640

634-
return Range;
641+
std::tie(Location.Line, Location.Column) =
642+
EditorDoc->getLineAndColumnInBuffer(Location.Offset);
635643
}
636644

637645

@@ -802,10 +810,9 @@ static ArrayRef<T> copyAndClearArray(llvm::BumpPtrAllocator &Allocator,
802810
return Ref;
803811
}
804812

805-
static void getLocationInfoForClangNode(
806-
ClangNode ClangNode, ClangImporter *Importer,
807-
llvm::Optional<std::pair<unsigned, unsigned>> &DeclarationLoc,
808-
StringRef &Filename) {
813+
static void setLocationInfoForClangNode(ClangNode ClangNode,
814+
ClangImporter *Importer,
815+
LocationInfo &Location) {
809816
clang::ASTContext &ClangCtx = Importer->getClangASTContext();
810817
clang::SourceManager &ClangSM = ClangCtx.getSourceManager();
811818

@@ -826,12 +833,15 @@ static void getLocationInfoForClangNode(
826833
ClangSM.getDecomposedLoc(CharRange.getBegin());
827834
if (!Decomp.first.isInvalid()) {
828835
if (auto FE = ClangSM.getFileEntryForID(Decomp.first)) {
829-
Filename = FE->getName();
836+
Location.Filename = FE->getName();
830837

831838
std::pair<clang::FileID, unsigned> EndDecomp =
832839
ClangSM.getDecomposedLoc(CharRange.getEnd());
833840

834-
DeclarationLoc = {Decomp.second, EndDecomp.second - Decomp.second};
841+
Location.Offset = Decomp.second;
842+
Location.Length = EndDecomp.second-Decomp.second;
843+
Location.Line = ClangSM.getLineNumber(Decomp.first, Decomp.second);
844+
Location.Column = ClangSM.getColumnNumber(Decomp.first, Decomp.second);
835845
}
836846
}
837847
}
@@ -841,10 +851,8 @@ static unsigned getCharLength(SourceManager &SM, SourceRange TokenRange) {
841851
return SM.getByteDistance(TokenRange.Start, CharEndLoc);
842852
}
843853

844-
static void
845-
getLocationInfo(const ValueDecl *VD,
846-
llvm::Optional<std::pair<unsigned, unsigned>> &DeclarationLoc,
847-
StringRef &Filename) {
854+
static void setLocationInfo(const ValueDecl *VD,
855+
LocationInfo &Location) {
848856
ASTContext &Ctx = VD->getASTContext();
849857
SourceManager &SM = Ctx.SourceMgr;
850858

@@ -870,14 +878,15 @@ getLocationInfo(const ValueDecl *VD,
870878
}
871879

872880
unsigned DeclBufID = SM.findBufferContainingLoc(Loc);
873-
DeclarationLoc = {SM.getLocOffsetInBuffer(Loc, DeclBufID),
874-
NameLen};
875-
Filename = SM.getIdentifierForBuffer(DeclBufID);
881+
Location.Filename = SM.getIdentifierForBuffer(DeclBufID);
882+
Location.Offset = SM.getLocOffsetInBuffer(Loc, DeclBufID);
883+
Location.Length = NameLen;
884+
std::tie(Location.Line, Location.Column) = SM.getLineAndColumnInBuffer(
885+
Loc, DeclBufID);
876886
} else if (ClangNode) {
877887
ClangImporter *Importer =
878-
static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
879-
return getLocationInfoForClangNode(ClangNode, Importer, DeclarationLoc,
880-
Filename);
888+
static_cast<ClangImporter*>(Ctx.getClangModuleLoader());
889+
setLocationInfoForClangNode(ClangNode, Importer, Location);
881890
}
882891
}
883892

@@ -1011,12 +1020,10 @@ fillSymbolInfo(CursorSymbolInfo &Symbol, const DeclInfo &DInfo,
10111020
Lang.getIFaceGenContexts().find(Symbol.ModuleName, Invoc))
10121021
Symbol.ModuleInterfaceName = IFaceGenRef->getDocumentName();
10131022

1014-
getLocationInfo(DInfo.OriginalProperty, Symbol.DeclarationLoc,
1015-
Symbol.Filename);
1016-
if (Symbol.DeclarationLoc.hasValue()) {
1017-
Symbol.DeclarationLoc = tryRemappingLocToLatestSnapshot(
1018-
Lang, *Symbol.DeclarationLoc, Symbol.Filename, PreviousSnaps);
1019-
if (!Symbol.DeclarationLoc.hasValue()) {
1023+
setLocationInfo(DInfo.OriginalProperty, Symbol.Location);
1024+
if (!Symbol.Location.Filename.empty()) {
1025+
mapLocToLatestSnapshot(Lang, Symbol.Location, PreviousSnaps);
1026+
if (Symbol.Location.Filename.empty()) {
10201027
return llvm::createStringError(
10211028
llvm::inconvertibleErrorCode(),
10221029
"Failed to remap declaration to latest snapshot.");

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

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,9 +1609,11 @@ struct ResponseSymbolInfo {
16091609
const char *SymbolGraph = nullptr;
16101610
const char *ModuleName = nullptr;
16111611
const char *ModuleInterfaceName = nullptr;
1612-
llvm::Optional<int64_t> Offset;
1613-
unsigned Length = 0;
16141612
const char *FilePath = nullptr;
1613+
unsigned Offset = 0;
1614+
unsigned Length = 0;
1615+
unsigned Line = 0;
1616+
unsigned Column = 0;
16151617
std::vector<const char *> OverrideUSRs;
16161618
std::vector<const char *> AnnotatedRelatedDeclarations;
16171619
std::vector<const char *> ModuleGroups;
@@ -1665,15 +1667,14 @@ struct ResponseSymbolInfo {
16651667
Symbol.ModuleInterfaceName =
16661668
sourcekitd_variant_dictionary_get_string(Info, KeyModuleInterfaceName);
16671669

1668-
sourcekitd_variant_t OffsetObj =
1669-
sourcekitd_variant_dictionary_get_value(Info, KeyOffset);
1670-
if (sourcekitd_variant_get_type(OffsetObj) !=
1671-
SOURCEKITD_VARIANT_TYPE_NULL) {
1672-
Symbol.Offset = sourcekitd_variant_int64_get_value(OffsetObj);
1673-
Symbol.Length = sourcekitd_variant_dictionary_get_int64(Info, KeyLength);
1674-
}
16751670
Symbol.FilePath =
16761671
sourcekitd_variant_dictionary_get_string(Info, KeyFilePath);
1672+
if (Symbol.FilePath) {
1673+
Symbol.Offset = sourcekitd_variant_dictionary_get_int64(Info, KeyOffset);
1674+
Symbol.Length = sourcekitd_variant_dictionary_get_int64(Info, KeyLength);
1675+
Symbol.Line = sourcekitd_variant_dictionary_get_int64(Info, KeyLine);
1676+
Symbol.Column = sourcekitd_variant_dictionary_get_int64(Info, KeyColumn);
1677+
}
16771678

16781679
Symbol.OverrideUSRs = readStringArray(Info, KeyOverrides, KeyUSR);
16791680
Symbol.AnnotatedRelatedDeclarations =
@@ -1728,14 +1729,19 @@ struct ResponseSymbolInfo {
17281729
}
17291730

17301731
OS << Kind << " (";
1731-
if (Offset.hasValue()) {
1732+
if (FilePath) {
17321733
if (CurrentFilename != StringRef(FilePath))
1733-
OS << FilePath << ":";
1734-
auto LineCol = resolveToLineCol(Offset.getValue(), FilePath, VFSFiles);
1735-
OS << LineCol.first << ':' << LineCol.second;
1736-
auto EndLineCol =
1737-
resolveToLineCol(Offset.getValue() + Length, FilePath, VFSFiles);
1738-
OS << '-' << EndLineCol.first << ':' << EndLineCol.second;
1734+
OS << FilePath << ':';
1735+
1736+
auto LineCol = resolveToLineCol(Offset, FilePath, VFSFiles);
1737+
if (LineCol.first != Line || LineCol.second != Column) {
1738+
OS << "*offset does not match line/column in response*";
1739+
} else {
1740+
OS << LineCol.first << ':' << LineCol.second;
1741+
auto EndLineCol = resolveToLineCol(Offset + Length, FilePath,
1742+
VFSFiles);
1743+
OS << '-' << EndLineCol.first << ':' << EndLineCol.second;
1744+
}
17391745
}
17401746
OS << ")" << '\n';
17411747

tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,11 +1764,12 @@ static void addCursorSymbolInfo(const CursorSymbolInfo &Symbol,
17641764
Elem.set(KeyModuleName, Symbol.ModuleName);
17651765
if (!Symbol.ModuleInterfaceName.empty())
17661766
Elem.set(KeyModuleInterfaceName, Symbol.ModuleInterfaceName);
1767-
if (Symbol.DeclarationLoc.hasValue()) {
1768-
Elem.set(KeyOffset, Symbol.DeclarationLoc.getValue().first);
1769-
Elem.set(KeyLength, Symbol.DeclarationLoc.getValue().second);
1770-
if (!Symbol.Filename.empty())
1771-
Elem.set(KeyFilePath, Symbol.Filename);
1767+
if (!Symbol.Location.Filename.empty()) {
1768+
Elem.set(KeyFilePath, Symbol.Location.Filename);
1769+
Elem.set(KeyOffset, Symbol.Location.Offset);
1770+
Elem.set(KeyLength, Symbol.Location.Length);
1771+
Elem.set(KeyLine, Symbol.Location.Line);
1772+
Elem.set(KeyColumn, Symbol.Location.Column);
17721773
}
17731774

17741775
if (!Symbol.OverrideUSRs.empty()) {

0 commit comments

Comments
 (0)