Skip to content

Commit 12de7fd

Browse files
committed
[CursorInfo] Pass primary path to allow comparing previous ASTs
Update the cursor requests to also pass in their primary file. Snapshots should be compared using this file, not the input buffer name. This fixes AST re-use when the AST is usable with snapshots. Resolves rdar://110344363.
1 parent 3ddab3e commit 12de7fd

File tree

6 files changed

+91
-60
lines changed

6 files changed

+91
-60
lines changed

test/SourceKit/CursorInfo/cursor_after_edit.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,17 @@
66
// Edit previously did not update the syntax info. Cursor info was using its
77
// buffer to calculate line and column (before rdar://78161348).
88
// RUN: %sourcekitd-test \
9+
// RUN: -shell -- echo '## State 1' == \
910
// RUN: -req=open -text-input %t/empty.swift %t/func.swift -- %t/func.swift == \
1011
// RUN: -req=edit -offset=0 -length=0 -replace="func foo() {}" -req-opts=enablesyntaxmap=0,enablesubstructure=0,enablediagnostics=0 %t/func.swift -- %t/func.swift == \
1112
// RUN: -req=cursor -offset=5 %t/func.swift -- %t/func.swift == \
12-
// RUN: -req=edit -offset=0 -length=0 -replace="// some comment\n" -req-opts=enablesyntaxmap=0,enablesubstructure=0,enablediagnostics=0 %t/func.swift -- %t/func.swift == \
13-
// RUN: -req=cursor -offset=21 %t/func.swift -- %t/func.swift
13+
// RUN: -shell -- echo '## State 2' == \
14+
// RUN: -req=edit -offset=0 -length=0 -replace="/* some comment */ " -req-opts=enablesyntaxmap=0,enablesubstructure=0,enablediagnostics=0,syntactic_only=1 %t/func.swift -- %t/func.swift == \
15+
// RUN: -req=cursor -offset=24 %t/func.swift -- %t/func.swift | %FileCheck %s
16+
17+
// CHECK: ## State 1
18+
// CHECK: source.lang.swift.decl.function.free
19+
// CHECK: foo()
20+
// CHECK: ## State 2
21+
// CHECK: source.lang.swift.decl.function.free
22+
// CHECK: foo()

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,8 @@ class LangSupport {
10861086
Receiver) = 0;
10871087

10881088
virtual void
1089-
getNameInfo(StringRef Filename, unsigned Offset, NameTranslatingInfo &Input,
1089+
getNameInfo(StringRef PrimaryFilePath, StringRef InputBufferName,
1090+
unsigned Offset, NameTranslatingInfo &Input,
10901091
ArrayRef<const char *> Args,
10911092
SourceKitCancellationToken CancellationToken,
10921093
std::function<void(const RequestResult<NameTranslatingInfo> &)>

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,8 +660,9 @@ class SwiftLangSupport : public LangSupport {
660660
Receiver) override;
661661

662662
void getNameInfo(
663-
StringRef Filename, unsigned Offset, NameTranslatingInfo &Input,
664-
ArrayRef<const char *> Args, SourceKitCancellationToken CancellationToken,
663+
StringRef PrimaryFilePath, StringRef InputBufferName, unsigned Offset,
664+
NameTranslatingInfo &Input, ArrayRef<const char *> Args,
665+
SourceKitCancellationToken CancellationToken,
665666
std::function<void(const RequestResult<NameTranslatingInfo> &)> Receiver)
666667
override;
667668

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 62 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,8 @@ class CursorRangeInfoConsumer : public SwiftASTConsumer {
13921392
protected:
13931393
SwiftLangSupport &Lang;
13941394
SwiftInvocationRef ASTInvok;
1395-
std::string InputFile;
1395+
std::string PrimaryFilePath;
1396+
std::string InputBufferName;
13961397
unsigned Offset;
13971398
unsigned Length;
13981399

@@ -1408,11 +1409,13 @@ class CursorRangeInfoConsumer : public SwiftASTConsumer {
14081409
}
14091410

14101411
public:
1411-
CursorRangeInfoConsumer(StringRef InputFile, unsigned Offset, unsigned Length,
1412+
CursorRangeInfoConsumer(StringRef PrimaryFilePath, StringRef InputBufferName,
1413+
unsigned Offset, unsigned Length,
14121414
SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
14131415
bool TryExistingAST, bool CancelOnSubsequentRequest)
1414-
: Lang(Lang), ASTInvok(ASTInvok), InputFile(InputFile.str()),
1415-
Offset(Offset), Length(Length), TryExistingAST(TryExistingAST),
1416+
: Lang(Lang), ASTInvok(ASTInvok), PrimaryFilePath(PrimaryFilePath.str()),
1417+
InputBufferName(InputBufferName.str()), Offset(Offset), Length(Length),
1418+
TryExistingAST(TryExistingAST),
14161419
CancelOnSubsequentRequest(CancelOnSubsequentRequest) {}
14171420

14181421
bool canUseASTWithSnapshots(ArrayRef<ImmutableTextSnapshotRef> Snapshots) override {
@@ -1429,7 +1432,7 @@ class CursorRangeInfoConsumer : public SwiftASTConsumer {
14291432

14301433
ImmutableTextSnapshotRef InputSnap;
14311434
if (auto EditorDoc = Lang.getEditorDocuments()->findByPath(
1432-
InputFile, /*IsRealpath=*/true))
1435+
PrimaryFilePath, /*IsRealpath=*/true))
14331436
InputSnap = EditorDoc->getLatestSnapshot();
14341437
if (!InputSnap)
14351438
return false;
@@ -1498,8 +1501,8 @@ static SourceFile *retrieveInputFile(StringRef inputBufferName,
14981501
}
14991502

15001503
static void resolveCursor(
1501-
SwiftLangSupport &Lang, StringRef InputFile, unsigned Offset,
1502-
unsigned Length, bool Actionables, bool SymbolGraph,
1504+
SwiftLangSupport &Lang, StringRef PrimaryFile, StringRef InputBufferName,
1505+
unsigned Offset, unsigned Length, bool Actionables, bool SymbolGraph,
15031506
SwiftInvocationRef Invok, bool TryExistingAST,
15041507
bool CancelOnSubsequentRequest,
15051508
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fileSystem,
@@ -1516,20 +1519,22 @@ static void resolveCursor(
15161519

15171520
public:
15181521
CursorInfoConsumer(
1519-
StringRef InputFile, unsigned Offset, unsigned Length, bool Actionables,
1520-
bool SymbolGraph, SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
1522+
StringRef PrimaryFile, StringRef InputBufferName, unsigned Offset,
1523+
unsigned Length, bool Actionables, bool SymbolGraph,
1524+
SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
15211525
bool TryExistingAST, bool CancelOnSubsequentRequest,
15221526
SourceKitCancellationToken CancellationToken,
15231527
std::function<void(const RequestResult<CursorInfoData> &)> Receiver)
1524-
: CursorRangeInfoConsumer(InputFile, Offset, Length, Lang, ASTInvok,
1525-
TryExistingAST, CancelOnSubsequentRequest),
1528+
: CursorRangeInfoConsumer(PrimaryFile, InputBufferName, Offset, Length,
1529+
Lang, ASTInvok, TryExistingAST,
1530+
CancelOnSubsequentRequest),
15261531
Actionables(Actionables), SymbolGraph(SymbolGraph),
15271532
CancellationToken(CancellationToken), Receiver(std::move(Receiver)) {}
15281533

15291534
void handlePrimaryAST(ASTUnitRef AstUnit) override {
15301535
auto &CompIns = AstUnit->getCompilerInstance();
15311536

1532-
SourceFile *SF = retrieveInputFile(InputFile, CompIns);
1537+
SourceFile *SF = retrieveInputFile(InputBufferName, CompIns);
15331538
if (!SF) {
15341539
Receiver(RequestResult<CursorInfoData>::fromError(
15351540
"Unable to find input file"));
@@ -1608,10 +1613,10 @@ static void resolveCursor(
16081613
if (!Success) {
16091614
if (!getPreviousASTSnaps().empty()) {
16101615
// Attempt again using the up-to-date AST.
1611-
resolveCursor(Lang, InputFile, Offset, Length, Actionables,
1612-
SymbolGraph, ASTInvok, /*TryExistingAST=*/false,
1613-
CancelOnSubsequentRequest, SM.getFileSystem(),
1614-
CancellationToken, Receiver);
1616+
resolveCursor(Lang, PrimaryFilePath, InputBufferName, Offset,
1617+
Length, Actionables, SymbolGraph, ASTInvok,
1618+
/*TryExistingAST=*/false, CancelOnSubsequentRequest,
1619+
SM.getFileSystem(), CancellationToken, Receiver);
16151620
} else {
16161621
CursorInfoData Info;
16171622
Info.InternalDiagnostic = Diagnostic;
@@ -1662,8 +1667,9 @@ static void resolveCursor(
16621667
};
16631668

16641669
auto Consumer = std::make_shared<CursorInfoConsumer>(
1665-
InputFile, Offset, Length, Actionables, SymbolGraph, Lang, Invok,
1666-
TryExistingAST, CancelOnSubsequentRequest, CancellationToken, Receiver);
1670+
PrimaryFile, InputBufferName, Offset, Length, Actionables, SymbolGraph,
1671+
Lang, Invok, TryExistingAST, CancelOnSubsequentRequest, CancellationToken,
1672+
Receiver);
16671673

16681674
/// FIXME: When request cancellation is implemented and Xcode adopts it,
16691675
/// don't use 'OncePerASTToken'.
@@ -1710,8 +1716,9 @@ static void computeDiagnostics(
17101716
}
17111717

17121718
static void resolveName(
1713-
SwiftLangSupport &Lang, StringRef InputFile, unsigned Offset,
1714-
SwiftInvocationRef Invok, bool TryExistingAST, NameTranslatingInfo &Input,
1719+
SwiftLangSupport &Lang, StringRef PrimaryFilePath,
1720+
StringRef InputBufferName, unsigned Offset, SwiftInvocationRef Invok,
1721+
bool TryExistingAST, NameTranslatingInfo &Input,
17151722
SourceKitCancellationToken CancellationToken,
17161723
std::function<void(const RequestResult<NameTranslatingInfo> &)> Receiver) {
17171724
assert(Invok);
@@ -1723,21 +1730,22 @@ static void resolveName(
17231730

17241731
public:
17251732
NameInfoConsumer(
1726-
StringRef InputFile, unsigned Offset, SwiftLangSupport &Lang,
1727-
SwiftInvocationRef ASTInvok, bool TryExistingAST,
1728-
NameTranslatingInfo Input, SourceKitCancellationToken CancellationToken,
1733+
StringRef PrimaryFilePath, StringRef InputBufferName, unsigned Offset,
1734+
SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
1735+
bool TryExistingAST, NameTranslatingInfo Input,
1736+
SourceKitCancellationToken CancellationToken,
17291737
std::function<void(const RequestResult<NameTranslatingInfo> &)>
17301738
Receiver)
1731-
: CursorRangeInfoConsumer(InputFile, Offset, 0, Lang, ASTInvok,
1732-
TryExistingAST,
1739+
: CursorRangeInfoConsumer(PrimaryFilePath, InputBufferName, Offset, 0,
1740+
Lang, ASTInvok, TryExistingAST,
17331741
/*CancelOnSubsequentRequest=*/false),
17341742
Input(std::move(Input)), CancellationToken(CancellationToken),
17351743
Receiver(std::move(Receiver)) {}
17361744

17371745
void handlePrimaryAST(ASTUnitRef AstUnit) override {
17381746
auto &CompIns = AstUnit->getCompilerInstance();
17391747

1740-
SourceFile *SF = retrieveInputFile(InputFile, CompIns);
1748+
SourceFile *SF = retrieveInputFile(InputBufferName, CompIns);
17411749
if (!SF) {
17421750
Receiver(RequestResult<NameTranslatingInfo>::fromError(
17431751
"Unable to find input file"));
@@ -1778,9 +1786,9 @@ static void resolveName(
17781786
if (!Success) {
17791787
if (!getPreviousASTSnaps().empty()) {
17801788
// Attempt again using the up-to-date AST.
1781-
resolveName(Lang, InputFile, Offset, ASTInvok,
1782-
/*TryExistingAST=*/false, Input, CancellationToken,
1783-
Receiver);
1789+
resolveName(
1790+
Lang, PrimaryFilePath, InputBufferName, Offset, ASTInvok,
1791+
/*TryExistingAST=*/false, Input, CancellationToken, Receiver);
17841792
} else {
17851793
NameTranslatingInfo Info;
17861794
Info.InternalDiagnostic = Diagnostic;
@@ -1813,17 +1821,18 @@ static void resolveName(
18131821
};
18141822

18151823
auto Consumer = std::make_shared<NameInfoConsumer>(
1816-
InputFile, Offset, Lang, Invok, TryExistingAST, Input, CancellationToken,
1817-
Receiver);
1824+
PrimaryFilePath, InputBufferName, Offset, Lang, Invok, TryExistingAST,
1825+
Input, CancellationToken, Receiver);
18181826

18191827
Lang.getASTManager()->processASTAsync(
18201828
Invok, std::move(Consumer), /*OncePerASTToken=*/nullptr,
18211829
CancellationToken, llvm::vfs::getRealFileSystem());
18221830
}
18231831

18241832
static void
1825-
resolveRange(SwiftLangSupport &Lang, StringRef InputFile, unsigned Offset,
1826-
unsigned Length, SwiftInvocationRef Invok, bool TryExistingAST,
1833+
resolveRange(SwiftLangSupport &Lang, StringRef PrimaryFilePath,
1834+
StringRef InputBufferName, unsigned Offset, unsigned Length,
1835+
SwiftInvocationRef Invok, bool TryExistingAST,
18271836
bool CancelOnSubsequentRequest,
18281837
SourceKitCancellationToken CancellationToken,
18291838
std::function<void(const RequestResult<RangeInfo> &)> Receiver) {
@@ -1835,20 +1844,21 @@ resolveRange(SwiftLangSupport &Lang, StringRef InputFile, unsigned Offset,
18351844

18361845
public:
18371846
RangeInfoConsumer(
1838-
StringRef InputFile, unsigned Offset, unsigned Length,
1839-
SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
1847+
StringRef PrimaryFilePath, StringRef InputBufferName, unsigned Offset,
1848+
unsigned Length, SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
18401849
bool TryExistingAST, bool CancelOnSubsequentRequest,
18411850
SourceKitCancellationToken CancellationToken,
18421851
std::function<void(const RequestResult<RangeInfo> &)> Receiver)
1843-
: CursorRangeInfoConsumer(InputFile, Offset, Length, Lang, ASTInvok,
1844-
TryExistingAST, CancelOnSubsequentRequest),
1852+
: CursorRangeInfoConsumer(PrimaryFilePath, InputBufferName, Offset,
1853+
Length, Lang, ASTInvok, TryExistingAST,
1854+
CancelOnSubsequentRequest),
18451855
CancellationToken(CancellationToken), Receiver(std::move(Receiver)) {}
18461856

18471857
void handlePrimaryAST(ASTUnitRef AstUnit) override {
18481858
// FIXME: Implement tracing
18491859
auto &CompIns = AstUnit->getCompilerInstance();
18501860

1851-
SourceFile *SF = retrieveInputFile(InputFile, CompIns);
1861+
SourceFile *SF = retrieveInputFile(InputBufferName, CompIns);
18521862
if (!SF) {
18531863
Receiver(
18541864
RequestResult<RangeInfo>::fromError("Unable to find input file"));
@@ -1892,7 +1902,8 @@ resolveRange(SwiftLangSupport &Lang, StringRef InputFile, unsigned Offset,
18921902
case RangeKind::Invalid:
18931903
if (!getPreviousASTSnaps().empty()) {
18941904
// Attempt again using the up-to-date AST.
1895-
resolveRange(Lang, InputFile, Offset, Length, ASTInvok,
1905+
resolveRange(Lang, PrimaryFilePath, InputBufferName, Offset, Length,
1906+
ASTInvok,
18961907
/*TryExistingAST=*/false, CancelOnSubsequentRequest,
18971908
CancellationToken, Receiver);
18981909
} else {
@@ -1913,8 +1924,8 @@ resolveRange(SwiftLangSupport &Lang, StringRef InputFile, unsigned Offset,
19131924
};
19141925

19151926
auto Consumer = std::make_shared<RangeInfoConsumer>(
1916-
InputFile, Offset, Length, Lang, Invok, TryExistingAST,
1917-
CancelOnSubsequentRequest, CancellationToken, Receiver);
1927+
PrimaryFilePath, InputBufferName, Offset, Length, Lang, Invok,
1928+
TryExistingAST, CancelOnSubsequentRequest, CancellationToken, Receiver);
19181929
/// FIXME: When request cancellation is implemented and Xcode adopts it,
19191930
/// don't use 'OncePerASTToken'.
19201931
static const char OncePerASTToken = 0;
@@ -2097,8 +2108,8 @@ void SwiftLangSupport::getCursorInfo(
20972108
}
20982109
};
20992110

2100-
resolveCursor(*this, InputBufferName, Offset, Length, Actionables,
2101-
SymbolGraph, Invok, /*TryExistingAST=*/true,
2111+
resolveCursor(*this, PrimaryFilePath, InputBufferName, Offset, Length,
2112+
Actionables, SymbolGraph, Invok, /*TryExistingAST=*/true,
21022113
CancelOnSubsequentRequest, fileSystem, CancellationToken,
21032114
ASTBasedReceiver);
21042115
}
@@ -2152,17 +2163,18 @@ void SwiftLangSupport::getRangeInfo(
21522163
Receiver(RequestResult<RangeInfo>::fromError("Invalid range length."));
21532164
return;
21542165
}
2155-
resolveRange(*this, InputBufferName, Offset, Length, Invok,
2166+
resolveRange(*this, PrimaryFilePath, InputBufferName, Offset, Length, Invok,
21562167
/*TryExistingAST=*/true, CancelOnSubsequentRequest,
21572168
CancellationToken, Receiver);
21582169
}
21592170

21602171
void SwiftLangSupport::getNameInfo(
2161-
StringRef InputFile, unsigned Offset, NameTranslatingInfo &Input,
2162-
ArrayRef<const char *> Args, SourceKitCancellationToken CancellationToken,
2172+
StringRef PrimaryFilePath, StringRef InputBufferName, unsigned Offset,
2173+
NameTranslatingInfo &Input, ArrayRef<const char *> Args,
2174+
SourceKitCancellationToken CancellationToken,
21632175
std::function<void(const RequestResult<NameTranslatingInfo> &)> Receiver) {
21642176

2165-
if (auto IFaceGenRef = IFaceGenContexts.get(InputFile)) {
2177+
if (auto IFaceGenRef = IFaceGenContexts.get(PrimaryFilePath)) {
21662178
IFaceGenRef->accessASTAsync([IFaceGenRef, Offset, Input, Receiver] {
21672179
SwiftInterfaceGenContext::ResolvedEntity Entity;
21682180
Entity = IFaceGenRef->resolveEntityForOffset(Offset);
@@ -2187,15 +2199,15 @@ void SwiftLangSupport::getNameInfo(
21872199

21882200
std::string Error;
21892201
SwiftInvocationRef Invok =
2190-
ASTMgr->getTypecheckInvocation(Args, InputFile, Error);
2202+
ASTMgr->getTypecheckInvocation(Args, PrimaryFilePath, Error);
21912203
if (!Invok) {
21922204
LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
21932205
Receiver(RequestResult<NameTranslatingInfo>::fromError(Error));
21942206
return;
21952207
}
21962208

2197-
resolveName(*this, InputFile, Offset, Invok, /*TryExistingAST=*/true, Input,
2198-
CancellationToken, Receiver);
2209+
resolveName(*this, PrimaryFilePath, InputBufferName, Offset, Invok,
2210+
/*TryExistingAST=*/true, Input, CancellationToken, Receiver);
21992211
}
22002212

22012213
static void resolveCursorFromUSR(

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,16 +1379,24 @@ static bool handleResponse(sourcekitd_response_t Resp, const TestOptions &Opts,
13791379
KeepResponseAlive = true;
13801380
break;
13811381

1382-
case SourceKitRequest::Edit:
1383-
if (Opts.Length == 0 && Opts.ReplaceText->empty()) {
1384-
// Length=0, replace="" is a nop and will not trigger sema.
1382+
case SourceKitRequest::Edit: {
1383+
// Length=0, replace="" is a nop and will not trigger sema.
1384+
bool SyntacticOnly = Opts.Length == 0 && Opts.ReplaceText->empty();
1385+
for (const std::string &ReqOpt : Opts.RequestOptions) {
1386+
if (SyntacticOnly)
1387+
break;
1388+
if (ReqOpt.find("syntactic_only=1") != std::string::npos) {
1389+
SyntacticOnly = true;
1390+
}
1391+
}
1392+
if (SyntacticOnly) {
13851393
printRawResponse(Resp);
13861394
} else {
13871395
getSemanticInfo(Info, SourceFile);
13881396
KeepResponseAlive = true;
13891397
}
13901398
break;
1391-
1399+
}
13921400
case SourceKitRequest::DemangleNames:
13931401
printDemangleResults(sourcekitd_response_get_value(Resp), outs());
13941402
break;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1735,7 +1735,7 @@ handleRequestNameTranslation(const RequestDict &Req,
17351735
llvm::transform(Selectors, std::back_inserter(Input.ArgNames),
17361736
[](const char *C) { return StringRef(C); });
17371737
return Lang.getNameInfo(
1738-
*PrimaryFilePath, Offset, Input, Args, CancellationToken,
1738+
*PrimaryFilePath, "", Offset, Input, Args, CancellationToken,
17391739
[Rec](const RequestResult<NameTranslatingInfo> &Result) {
17401740
reportNameInfo(Result, Rec);
17411741
});

0 commit comments

Comments
 (0)