Skip to content

Commit 147f81c

Browse files
authored
Merge pull request swiftlang#37364 from rintaro/sourcekit-syntaxinfo-rdar77665805
[SourceKit] Update SyntaxInfo but with lazy parsing in "edit" request
2 parents 4d7a489 + 4c213c4 commit 147f81c

File tree

4 files changed

+92
-38
lines changed

4 files changed

+92
-38
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
enum E { case foo, bar }
2+
func foo(x: (E) -> Void) {}
3+
func test() {
4+
foo(x: <#T##(E) -> Void#>)
5+
}
6+
7+
// RUN: %sourcekitd-test \
8+
// RUN: -req=open %s -- %s == \
9+
// RUN: -req=edit -offset=0 -length=53 -replace="" -req-opts=enablesyntaxmap=0,enablesubstructure=0,enablediagnostics=0 %s -- %s == \
10+
// RUN: -req=expand-placeholder -offset=23 -length=18 %s \
11+
// RUN: | %FileCheck %s
12+
13+
// CHECK: {
14+
// CHECK: key.offset: 19,
15+
// CHECK: key.length: 23,
16+
// CHECK: key.sourcetext: " { <#E#> in\n<#code#>\n}"
17+
// CHECK: }
18+

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,8 @@ class SwiftDocumentSyntaxInfo {
677677
std::string PrimaryFile;
678678
/// Whether or not the AST stored in the source file is up-to-date or just an
679679
/// artifact of incremental syntax parsing
680-
bool HasUpToDateAST;
680+
bool IncrementalParsingEnabled;
681+
bool IsParsed;
681682

682683
public:
683684
SwiftDocumentSyntaxInfo(const CompilerInvocation &CompInv,
@@ -713,13 +714,16 @@ class SwiftDocumentSyntaxInfo {
713714
Parser->getParser().Context.evaluator);
714715
Parser->getDiagnosticEngine().addConsumer(DiagConsumer);
715716

716-
// If there is a syntax parsing cache, incremental syntax parsing is
717-
// performed and thus the generated AST may not be up-to-date.
718-
HasUpToDateAST = CompInv.getMainFileSyntaxParsingCache() == nullptr;
717+
IncrementalParsingEnabled =
718+
CompInv.getMainFileSyntaxParsingCache() != nullptr;
719+
IsParsed = false;
719720
}
720721

721-
void parse() {
722-
Parser->parse();
722+
void parseIfNeeded() {
723+
if (!IsParsed) {
724+
Parser->parse();
725+
IsParsed = true;
726+
}
723727
}
724728

725729
SourceFile &getSourceFile() {
@@ -738,7 +742,7 @@ class SwiftDocumentSyntaxInfo {
738742
return SM;
739743
}
740744

741-
bool hasUpToDateAST() { return HasUpToDateAST; }
745+
bool isIncrementalParsingEnabled() { return IncrementalParsingEnabled; }
742746

743747
ArrayRef<DiagnosticEntryInfo> getDiagnostics() {
744748
return DiagConsumer.getDiagnosticsForBuffer(BufferID);
@@ -1074,6 +1078,7 @@ struct SwiftEditorDocument::Implementation {
10741078

10751079
std::shared_ptr<SwiftDocumentSyntaxInfo> getSyntaxInfo() {
10761080
llvm::sys::ScopedLock L(AccessMtx);
1081+
SyntaxInfo->parseIfNeeded();
10771082
return SyntaxInfo;
10781083
}
10791084

@@ -1949,9 +1954,10 @@ void SwiftEditorDocument::updateSemaInfo() {
19491954
::updateSemaInfo(SemanticInfo, EditableBuffer);
19501955
}
19511956

1952-
void SwiftEditorDocument::parse(ImmutableTextSnapshotRef Snapshot,
1953-
SwiftLangSupport &Lang, bool BuildSyntaxTree,
1954-
SyntaxParsingCache *SyntaxCache) {
1957+
void SwiftEditorDocument::resetSyntaxInfo(ImmutableTextSnapshotRef Snapshot,
1958+
SwiftLangSupport &Lang,
1959+
bool BuildSyntaxTree,
1960+
SyntaxParsingCache *SyntaxCache) {
19551961
llvm::sys::ScopedLock L(Impl.AccessMtx);
19561962

19571963
assert(Impl.SemanticInfo && "Impl.SemanticInfo must be set");
@@ -1982,15 +1988,14 @@ void SwiftEditorDocument::parse(ImmutableTextSnapshotRef Snapshot,
19821988
// Access to Impl.SyntaxInfo is guarded by Impl.AccessMtx
19831989
Impl.SyntaxInfo.reset(
19841990
new SwiftDocumentSyntaxInfo(CompInv, Snapshot, Args, Impl.FilePath));
1985-
1986-
Impl.SyntaxInfo->parse();
19871991
}
19881992

19891993
static UIdent SemaDiagStage("source.diagnostic.stage.swift.sema");
19901994
static UIdent ParseDiagStage("source.diagnostic.stage.swift.parse");
19911995

19921996
void SwiftEditorDocument::readSyntaxInfo(EditorConsumer &Consumer, bool ReportDiags) {
19931997
llvm::sys::ScopedLock L(Impl.AccessMtx);
1998+
Impl.SyntaxInfo->parseIfNeeded();
19941999

19952000
Impl.ParserDiagnostics = Impl.SyntaxInfo->getDiagnostics();
19962001
if (ReportDiags) {
@@ -2105,8 +2110,8 @@ SwiftEditorDocument::getSyntaxTree() const {
21052110

21062111
std::string SwiftEditorDocument::getFilePath() const { return Impl.FilePath; }
21072112

2108-
bool SwiftEditorDocument::hasUpToDateAST() const {
2109-
return Impl.SyntaxInfo->hasUpToDateAST();
2113+
bool SwiftEditorDocument::isIncrementalParsingEnabled() const {
2114+
return Impl.SyntaxInfo->isIncrementalParsingEnabled();
21102115
}
21112116

21122117
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
@@ -2335,7 +2340,7 @@ void SwiftLangSupport::editorOpen(
23352340
EditorDoc = new SwiftEditorDocument(Name, *this, fileSystem);
23362341
Snapshot = EditorDoc->initializeText(
23372342
Buf, Args, Consumer.needsSemanticInfo(), fileSystem);
2338-
EditorDoc->parse(Snapshot, *this, Consumer.syntaxTreeEnabled());
2343+
EditorDoc->resetSyntaxInfo(Snapshot, *this, Consumer.syntaxTreeEnabled());
23392344
if (EditorDocuments->getOrUpdate(Name, *this, EditorDoc)) {
23402345
// Document already exists, re-initialize it. This should only happen
23412346
// if we get OPEN request while the previous document is not closed.
@@ -2349,7 +2354,7 @@ void SwiftLangSupport::editorOpen(
23492354
if (!Snapshot) {
23502355
Snapshot = EditorDoc->initializeText(
23512356
Buf, Args, Consumer.needsSemanticInfo(), fileSystem);
2352-
EditorDoc->parse(Snapshot, *this, Consumer.syntaxTreeEnabled());
2357+
EditorDoc->resetSyntaxInfo(Snapshot, *this, Consumer.syntaxTreeEnabled());
23532358
}
23542359

23552360
if (Consumer.needsSemanticInfo()) {
@@ -2402,7 +2407,7 @@ void verifyIncrementalParse(SwiftEditorDocumentRef EditorDoc,
24022407
SwiftDocumentSyntaxInfo ScratchSyntaxInfo(Invocation,
24032408
EditorDoc->getLatestSnapshot(),
24042409
Args, EditorDoc->getFilePath());
2405-
ScratchSyntaxInfo.parse();
2410+
ScratchSyntaxInfo.parseIfNeeded();
24062411

24072412
// Dump the from-scratch syntax tree
24082413
std::string FromScratchTreeString;
@@ -2507,19 +2512,22 @@ void SwiftLangSupport::editorReplaceText(StringRef Name,
25072512
}
25082513

25092514
// If client doesn't need any information, we doen't need to parse it.
2515+
2516+
2517+
SyntaxParsingCache *SyntaxCachePtr = nullptr;
2518+
if (SyntaxCache.hasValue()) {
2519+
SyntaxCachePtr = SyntaxCache.getPointer();
2520+
}
2521+
EditorDoc->resetSyntaxInfo(Snapshot, *this, Consumer.syntaxTreeEnabled(),
2522+
SyntaxCachePtr);
2523+
25102524
if (!Consumer.documentStructureEnabled() &&
25112525
!Consumer.syntaxMapEnabled() &&
25122526
!Consumer.diagnosticsEnabled() &&
25132527
!Consumer.syntaxTreeEnabled()) {
25142528
return;
25152529
}
25162530

2517-
SyntaxParsingCache *SyntaxCachePtr = nullptr;
2518-
if (SyntaxCache.hasValue()) {
2519-
SyntaxCachePtr = SyntaxCache.getPointer();
2520-
}
2521-
EditorDoc->parse(Snapshot, *this, Consumer.syntaxTreeEnabled(),
2522-
SyntaxCachePtr);
25232531
// Do not report syntactic diagnostics; will be handled in readSemanticInfo.
25242532
EditorDoc->readSyntaxInfo(Consumer, /*ReportDiags=*/false);
25252533

@@ -2578,11 +2586,12 @@ void SwiftLangSupport::editorFormatText(StringRef Name, unsigned Line,
25782586
return;
25792587
}
25802588

2581-
if (!EditorDoc->hasUpToDateAST()) {
2582-
// An up-to-date AST is needed for formatting. If it does not exist, fall
2583-
// back to a full reparse of the file
2584-
EditorDoc->parse(EditorDoc->getLatestSnapshot(), *this,
2585-
/*BuildSyntaxTree=*/true);
2589+
if (EditorDoc->isIncrementalParsingEnabled()) {
2590+
// If incremental parsing is enabled, AST is not updated properly. Fall
2591+
// back to a full reparse of the file.
2592+
EditorDoc->resetSyntaxInfo(EditorDoc->getLatestSnapshot(), *this,
2593+
/*BuildSyntaxTree=*/true,
2594+
/*SyntaxCache=*/nullptr);
25862595
}
25872596

25882597
EditorDoc->formatText(Line, Length, Consumer);
@@ -2616,5 +2625,13 @@ void SwiftLangSupport::editorExpandPlaceholder(StringRef Name, unsigned Offset,
26162625
return;
26172626
}
26182627

2628+
if (EditorDoc->isIncrementalParsingEnabled()) {
2629+
// If incremental parsing is enabled, AST is not updated properly. Fall
2630+
// back to a full reparse of the file.
2631+
EditorDoc->resetSyntaxInfo(EditorDoc->getLatestSnapshot(), *this,
2632+
/*BuildSyntaxTree=*/true,
2633+
/*SyntaxCache=*/nullptr);
2634+
}
2635+
26192636
EditorDoc->expandPlaceholder(Offset, Length, Consumer);
26202637
}

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ class SwiftEditorDocument :
107107
ImmutableTextSnapshotRef getLatestSnapshot() const;
108108
std::pair<unsigned, unsigned> getLineAndColumnInBuffer(unsigned Offset);
109109

110-
void parse(ImmutableTextSnapshotRef Snapshot, SwiftLangSupport &Lang,
111-
bool BuildSyntaxTree,
112-
swift::SyntaxParsingCache *SyntaxCache = nullptr);
110+
void resetSyntaxInfo(ImmutableTextSnapshotRef Snapshot,
111+
SwiftLangSupport &Lang, bool BuildSyntaxTree,
112+
swift::SyntaxParsingCache *SyntaxCache = nullptr);
113113
void readSyntaxInfo(EditorConsumer &consumer, bool ReportDiags);
114114
void readSemanticInfo(ImmutableTextSnapshotRef Snapshot,
115115
EditorConsumer& Consumer);
@@ -129,7 +129,7 @@ class SwiftEditorDocument :
129129

130130
/// Whether or not the AST stored for this document is up-to-date or just an
131131
/// artifact of incremental syntax parsing
132-
bool hasUpToDateAST() const;
132+
bool isIncrementalParsingEnabled() const;
133133

134134
/// Returns the virtual filesystem associated with this document.
135135
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() const;

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

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -834,11 +834,24 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
834834
break;
835835

836836
case SourceKitRequest::ExpandPlaceholder:
837-
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
838-
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
839-
sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
840-
sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
841-
sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
837+
if (Opts.Length) {
838+
// Single placeholder by location.
839+
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorExpandPlaceholder);
840+
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
841+
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
842+
sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);
843+
} else {
844+
if (ByteOffset) {
845+
llvm::errs() << "Missing '-length <number>'\n";
846+
return 1;
847+
}
848+
// Expand all placeholders.
849+
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
850+
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
851+
sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
852+
sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
853+
sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
854+
}
842855
break;
843856

844857
case SourceKitRequest::SyntaxTree:
@@ -1341,7 +1354,13 @@ static bool handleResponse(sourcekitd_response_t Resp, const TestOptions &Opts,
13411354
break;
13421355

13431356
case SourceKitRequest::ExpandPlaceholder:
1344-
expandPlaceholders(SourceBuf.get(), llvm::outs());
1357+
if (Opts.Length) {
1358+
// Single placeholder by location.
1359+
sourcekitd_response_description_dump_filedesc(Resp, STDOUT_FILENO);
1360+
} else {
1361+
// Expand all placeholders.
1362+
expandPlaceholders(SourceBuf.get(), llvm::outs());
1363+
}
13451364
break;
13461365
case SourceKitRequest::ModuleGroups:
13471366
printModuleGroupNames(Info, llvm::outs());

0 commit comments

Comments
 (0)