Skip to content

Commit 1828bc2

Browse files
authored
Merge pull request swiftlang#37229 from bnbarham/cherry-rdar75582627
[5.5] Include locations for external files in cursor info results
2 parents 6ebf143 + d215cd3 commit 1828bc2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+742
-509
lines changed

include/swift/AST/ASTContext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ namespace swift {
7373
class DerivativeAttr;
7474
class DifferentiableAttr;
7575
class ExtensionDecl;
76+
struct ExternalSourceLocs;
7677
class ForeignRepresentationInfo;
7778
class FuncDecl;
7879
class GenericContext;
@@ -1170,6 +1171,10 @@ class ASTContext final {
11701171

11711172
private:
11721173
friend Decl;
1174+
1175+
Optional<ExternalSourceLocs *> getExternalSourceLocs(const Decl *D);
1176+
void setExternalSourceLocs(const Decl *D, ExternalSourceLocs *Locs);
1177+
11731178
Optional<std::pair<RawComment, bool>> getRawComment(const Decl *D);
11741179
void setRawComment(const Decl *D, RawComment RC, bool FromSerialized);
11751180

include/swift/AST/Decl.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ namespace swift {
6262
class DynamicSelfType;
6363
class Type;
6464
class Expr;
65+
struct ExternalSourceLocs;
6566
class CaptureListExpr;
6667
class DeclRefExpr;
6768
class ForeignAsyncConvention;
@@ -688,14 +689,12 @@ class alignas(1 << DeclAlignInBits) Decl {
688689
void operator=(const Decl&) = delete;
689690
SourceLoc getLocFromSource() const;
690691

691-
struct CachedExternalSourceLocs {
692-
SourceLoc Loc;
693-
SourceLoc StartLoc;
694-
SourceLoc EndLoc;
695-
SmallVector<CharSourceRange, 4> DocRanges;
696-
};
697-
mutable CachedExternalSourceLocs const *CachedSerializedLocs = nullptr;
698-
const CachedExternalSourceLocs *getSerializedLocs() const;
692+
/// Returns the serialized locations of this declaration from the
693+
/// corresponding .swiftsourceinfo file. "Empty" (ie. \c BufferID of 0, an
694+
/// invalid \c Loc, and empty \c DocRanges) if either there is no
695+
/// .swiftsourceinfo or the buffer could not be created, eg. if the file
696+
/// no longer exists.
697+
const ExternalSourceLocs *getSerializedLocs() const;
699698

700699
/// Directly set the invalid bit
701700
void setInvalidBit();

include/swift/AST/FileUnit.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ class FileUnit : public DeclContext {
164164
return None;
165165
}
166166

167-
virtual Optional<BasicDeclLocs> getBasicLocsForDecl(const Decl *D) const {
167+
virtual Optional<ExternalSourceLocs::RawLocs>
168+
getExternalRawLocsForDecl(const Decl *D) const {
168169
return None;
169170
}
170171

include/swift/AST/SourceFile.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,8 @@ class SourceFile final : public FileUnit {
407407

408408
Identifier getDiscriminatorForPrivateValue(const ValueDecl *D) const override;
409409
Identifier getPrivateDiscriminator() const { return PrivateDiscriminator; }
410-
Optional<BasicDeclLocs> getBasicLocsForDecl(const Decl *D) const override;
410+
Optional<ExternalSourceLocs::RawLocs>
411+
getExternalRawLocsForDecl(const Decl *D) const override;
411412

412413
/// Returns the synthesized file for this source file, if it exists.
413414
SynthesizedFileUnit *getSynthesizedFile() const { return SynthesizedFile; };

include/swift/Basic/BasicSourceInfo.h

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,42 @@
1515

1616
#include "swift/Basic/Fingerprint.h"
1717
#include "swift/Basic/LLVM.h"
18+
#include "swift/Basic/SourceLoc.h"
1819
#include "llvm/ADT/PointerIntPair.h"
1920
#include "llvm/Support/Chrono.h"
2021

2122
namespace swift {
2223

2324
class SourceFile;
2425

25-
struct SourcePosition {
26-
uint32_t Line = 0;
27-
uint32_t Column = 0;
28-
bool isValid() const { return Line && Column; }
29-
};
30-
31-
struct BasicDeclLocs {
32-
StringRef SourceFilePath;
33-
SmallVector<std::pair<SourcePosition, uint32_t>, 4> DocRanges;
34-
SourcePosition Loc;
35-
SourcePosition StartLoc;
36-
SourcePosition EndLoc;
26+
struct ExternalSourceLocs {
27+
struct LocationDirective {
28+
uint32_t Offset = 0;
29+
int32_t LineOffset = 0;
30+
uint32_t Length = 0;
31+
StringRef Name;
32+
33+
bool isValid() const { return Length > 0; }
34+
};
35+
36+
struct RawLoc {
37+
uint32_t Offset = 0;
38+
uint32_t Line = 0;
39+
uint32_t Column = 0;
40+
LocationDirective Directive;
41+
};
42+
43+
struct RawLocs {
44+
StringRef SourceFilePath;
45+
SmallVector<std::pair<RawLoc, uint32_t>, 4> DocRanges;
46+
RawLoc Loc;
47+
RawLoc StartLoc;
48+
RawLoc EndLoc;
49+
};
50+
51+
unsigned BufferID = 0;
52+
SourceLoc Loc;
53+
SmallVector<CharSourceRange, 4> DocRanges;
3754
};
3855

3956
class BasicSourceFileInfo {

include/swift/Basic/SourceManager.h

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ namespace swift {
2424

2525
/// This class manages and owns source buffers.
2626
class SourceManager {
27+
public:
28+
/// A \c #sourceLocation-defined virtual file region, representing the source
29+
/// source after a \c #sourceLocation (or between two). It provides a
30+
/// filename and line offset to be applied to \c SourceLoc's within its
31+
/// \c Range.
32+
struct VirtualFile {
33+
CharSourceRange Range;
34+
std::string Name;
35+
int LineOffset;
36+
};
37+
38+
private:
2739
llvm::SourceMgr LLVMSourceMgr;
2840
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem;
2941
unsigned CodeCompletionBufferID = 0U;
@@ -52,12 +64,6 @@ class SourceManager {
5264
};
5365
ReplacedRangeType ReplacedRange;
5466

55-
// \c #sourceLocation directive handling.
56-
struct VirtualFile {
57-
CharSourceRange Range;
58-
std::string Name;
59-
int LineOffset;
60-
};
6167
std::map<const char *, VirtualFile> VirtualFiles;
6268
mutable std::pair<const char *, const VirtualFile*> CachedVFile = {nullptr, nullptr};
6369

@@ -143,6 +149,10 @@ class SourceManager {
143149
/// Adds a memory buffer to the SourceManager, taking ownership of it.
144150
unsigned addNewSourceBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer);
145151

152+
/// Add a \c #sourceLocation-defined virtual file region of \p Length.
153+
void createVirtualFile(SourceLoc Loc, StringRef Name, int LineOffset,
154+
unsigned Length);
155+
146156
/// Add a \c #sourceLocation-defined virtual file region.
147157
///
148158
/// By default, this region continues to the end of the buffer.
@@ -275,18 +285,17 @@ class SourceManager {
275285

276286
std::string getLineString(unsigned BufferID, unsigned LineNumber);
277287

288+
/// Retrieve the buffer ID for \p Path, loading if necessary.
289+
unsigned getExternalSourceBufferID(StringRef Path);
290+
278291
SourceLoc getLocFromExternalSource(StringRef Path, unsigned Line, unsigned Col);
279-
private:
292+
293+
/// Retrieve the virtual file for the given \p Loc, or nullptr if none exists.
280294
const VirtualFile *getVirtualFile(SourceLoc Loc) const;
281-
unsigned getExternalSourceBufferId(StringRef Path);
282-
int getLineOffset(SourceLoc Loc) const {
283-
if (auto VFile = getVirtualFile(Loc))
284-
return VFile->LineOffset;
285-
else
286-
return 0;
287-
}
288295

289-
public:
296+
/// Whether or not \p Loc is after a \c #sourceLocation directive, ie. its
297+
/// file, line, and column should be reported using the information in the
298+
/// directive.
290299
bool isLocInVirtualFile(SourceLoc Loc) const {
291300
return getVirtualFile(Loc) != nullptr;
292301
}
@@ -295,6 +304,14 @@ class SourceManager {
295304
/// owned by \p otherManager. Returns an invalid SourceLoc if it cannot be
296305
/// translated.
297306
SourceLoc getLocForForeignLoc(SourceLoc otherLoc, SourceManager &otherMgr);
307+
308+
private:
309+
int getLineOffset(SourceLoc Loc) const {
310+
if (auto VFile = getVirtualFile(Loc))
311+
return VFile->LineOffset;
312+
else
313+
return 0;
314+
}
298315
};
299316

300317
} // end namespace swift

include/swift/IDE/Utils.h

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ bool initCompilerInvocation(
8787
DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile,
8888
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
8989
const std::string &runtimeResourcePath,
90-
const std::string &diagnosticDocumentationPath,
91-
bool shouldOptimizeForIDE, time_t sessionTimestamp, std::string &Error);
90+
const std::string &diagnosticDocumentationPath, time_t sessionTimestamp,
91+
std::string &Error);
9292

9393
bool initInvocationByClangArguments(ArrayRef<const char *> ArgList,
9494
CompilerInvocation &Invok,
@@ -124,16 +124,6 @@ std::unique_ptr<llvm::MemoryBuffer>
124124
replacePlaceholders(std::unique_ptr<llvm::MemoryBuffer> InputBuf,
125125
bool *HadPlaceholder = nullptr);
126126

127-
void getLocationInfo(
128-
const ValueDecl *VD,
129-
llvm::Optional<std::pair<unsigned, unsigned>> &DeclarationLoc,
130-
StringRef &Filename);
131-
132-
void getLocationInfoForClangNode(ClangNode ClangNode,
133-
ClangImporter *Importer,
134-
llvm::Optional<std::pair<unsigned, unsigned>> &DeclarationLoc,
135-
StringRef &Filename);
136-
137127
Optional<std::pair<unsigned, unsigned>> parseLineCol(StringRef LineCol);
138128

139129
class XMLEscapingPrinter : public StreamPrinter {

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,8 @@ class SerializedASTFile final : public LoadedFile {
392392

393393
Optional<StringRef> getGroupNameByUSR(StringRef USR) const override;
394394

395-
Optional<BasicDeclLocs> getBasicLocsForDecl(const Decl *D) const override;
395+
Optional<ExternalSourceLocs::RawLocs>
396+
getExternalRawLocsForDecl(const Decl *D) const override;
396397

397398
void collectAllGroups(SmallVectorImpl<StringRef> &Names) const override;
398399

lib/AST/ASTContext.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ struct ASTContext::Implementation {
284284
/// The module loader used to load Clang modules from DWARF.
285285
ClangModuleLoader *TheDWARFModuleLoader = nullptr;
286286

287+
/// Map from Swift declarations to deserialized resolved locations, ie.
288+
/// actual \c SourceLocs that require opening their external buffer.
289+
llvm::DenseMap<const Decl *, ExternalSourceLocs *> ExternalSourceLocs;
290+
287291
/// Map from Swift declarations to raw comments.
288292
llvm::DenseMap<const Decl *, std::pair<RawComment, bool>> RawComments;
289293

@@ -2020,6 +2024,20 @@ ModuleDecl *ASTContext::getStdlibModule(bool loadIfAbsent) {
20202024
return TheStdlibModule;
20212025
}
20222026

2027+
Optional<ExternalSourceLocs *>
2028+
ASTContext::getExternalSourceLocs(const Decl *D) {
2029+
auto Known = getImpl().ExternalSourceLocs.find(D);
2030+
if (Known == getImpl().ExternalSourceLocs.end())
2031+
return None;
2032+
2033+
return Known->second;
2034+
}
2035+
2036+
void ASTContext::setExternalSourceLocs(const Decl *D,
2037+
ExternalSourceLocs *Locs) {
2038+
getImpl().ExternalSourceLocs[D] = Locs;
2039+
}
2040+
20232041
Optional<std::pair<RawComment, bool>> ASTContext::getRawComment(const Decl *D) {
20242042
auto Known = getImpl().RawComments.find(D);
20252043
if (Known == getImpl().RawComments.end())

lib/AST/Decl.cpp

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -610,36 +610,50 @@ case DeclKind::ID: return cast<ID##Decl>(this)->getLocFromSource();
610610
llvm_unreachable("Unknown decl kind");
611611
}
612612

613-
const Decl::CachedExternalSourceLocs *Decl::getSerializedLocs() const {
614-
if (CachedSerializedLocs) {
615-
return CachedSerializedLocs;
616-
}
613+
const ExternalSourceLocs *Decl::getSerializedLocs() const {
614+
auto &Context = getASTContext();
615+
if (auto EL = Context.getExternalSourceLocs(this).getValueOr(nullptr))
616+
return EL;
617+
618+
static ExternalSourceLocs NullLocs{};
619+
617620
auto *File = cast<FileUnit>(getDeclContext()->getModuleScopeContext());
618-
assert(File->getKind() == FileUnitKind::SerializedAST &&
619-
"getSerializedLocs() should only be called on decls in "
620-
"a 'SerializedASTFile'");
621-
auto Locs = File->getBasicLocsForDecl(this);
622-
if (!Locs.hasValue()) {
623-
static const Decl::CachedExternalSourceLocs NullLocs{};
621+
if (File->getKind() != FileUnitKind::SerializedAST)
622+
return &NullLocs;
623+
624+
auto RawLocs = File->getExternalRawLocsForDecl(this);
625+
if (!RawLocs.hasValue()) {
626+
// Don't read .swiftsourceinfo again on failure
627+
Context.setExternalSourceLocs(this, &NullLocs);
624628
return &NullLocs;
625629
}
626-
auto *Result = getASTContext().Allocate<Decl::CachedExternalSourceLocs>();
627-
auto &SM = getASTContext().SourceMgr;
628-
#define CASE(X) \
629-
Result->X = SM.getLocFromExternalSource(Locs->SourceFilePath, Locs->X.Line, \
630-
Locs->X.Column);
631-
CASE(Loc)
632-
CASE(StartLoc)
633-
CASE(EndLoc)
634-
#undef CASE
635630

636-
for (const auto &LineColumnAndLength : Locs->DocRanges) {
637-
auto Start = SM.getLocFromExternalSource(Locs->SourceFilePath,
638-
LineColumnAndLength.first.Line,
639-
LineColumnAndLength.first.Column);
640-
Result->DocRanges.push_back({ Start, LineColumnAndLength.second });
631+
auto &SM = getASTContext().SourceMgr;
632+
unsigned BufferID = SM.getExternalSourceBufferID(RawLocs->SourceFilePath);
633+
if (!BufferID) {
634+
// Don't try open the file again on failure
635+
Context.setExternalSourceLocs(this, &NullLocs);
636+
return &NullLocs;
641637
}
642638

639+
auto ResolveLoc = [&](const ExternalSourceLocs::RawLoc &Raw) -> SourceLoc {
640+
// If the decl had a presumed loc, create its virtual file so that
641+
// getPresumedLineAndColForLoc works from serialized locations as well.
642+
if (Raw.Directive.isValid()) {
643+
auto &LD = Raw.Directive;
644+
SourceLoc Loc = SM.getLocForOffset(BufferID, LD.Offset);
645+
SM.createVirtualFile(Loc, LD.Name, LD.LineOffset, LD.Length);
646+
}
647+
return SM.getLocForOffset(BufferID, Raw.Offset);
648+
};
649+
650+
auto *Result = getASTContext().Allocate<ExternalSourceLocs>();
651+
Result->BufferID = BufferID;
652+
Result->Loc = ResolveLoc(RawLocs->Loc);
653+
for (auto &Range : RawLocs->DocRanges) {
654+
Result->DocRanges.emplace_back(ResolveLoc(Range.first), Range.second);
655+
}
656+
Context.setExternalSourceLocs(this, Result);
643657
return Result;
644658
}
645659

0 commit comments

Comments
 (0)