Skip to content

Commit d618233

Browse files
committed
Add source.request.index_to_store to sourcekitd
This requests performs an index store index of the given file using the given index store path and index unit output path. All other options are derived from the index store related compiler flags. This will allow IDEs like Xcode to index the file directly inside of sourcekitd and potentially reuse an already built AST.
1 parent 12ebe0a commit d618233

File tree

10 files changed

+191
-0
lines changed

10 files changed

+191
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %sourcekitd-test -req=index-to-store %s -index-store-path %t/idx -index-unit-output-path %t/indexstore.o -- -c -module-name indexstoremodule -file-prefix-map %S=REMAPPED_SRC_ROOT -file-prefix-map %t=REMAPPED_OUT_DIR %s
3+
// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
4+
5+
class Foo {
6+
let member: Int
7+
init(member: Int) {
8+
self.member = member
9+
}
10+
}
11+
12+
// CHECK: indexstore.o-{{.*}}
13+
// CHECK: module-name: indexstoremodule
14+
// CHECK: main-path: REMAPPED_SRC_ROOT/indexstore.swift
15+
// CHECK: out-file: REMAPPED_OUT_DIR/indexstore.o
16+
// CHECK: is-debug: 1
17+
// CHECK: Unit | system | Swift | {{.*}}{{/|\\}}Swift.swiftmodule

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,10 +872,18 @@ struct RenameLocations {
872872
std::vector<RenameLocation> LineColumnLocs;
873873
};
874874

875+
struct IndexStoreOptions {
876+
std::string IndexStorePath;
877+
std::string IndexUnitOutputPath;
878+
};
879+
880+
struct IndexStoreInfo{};
881+
875882
typedef std::function<void(RequestResult<ArrayRef<CategorizedEdits>> Result)>
876883
CategorizedEditsReceiver;
877884
typedef std::function<void(RequestResult<ArrayRef<CategorizedRenameRanges>> Result)>
878885
CategorizedRenameRangesReceiver;
886+
typedef std::function<void(RequestResult<IndexStoreInfo> Result)> IndexToStoreReceiver;
879887

880888
class DocInfoConsumer {
881889
virtual void anchor();
@@ -986,6 +994,12 @@ class LangSupport {
986994
IndexingConsumer &Consumer,
987995
ArrayRef<const char *> Args) = 0;
988996

997+
virtual void indexToStore(StringRef InputFile,
998+
ArrayRef<const char *> Args,
999+
IndexStoreOptions Opts,
1000+
SourceKitCancellationToken CancellationToken,
1001+
IndexToStoreReceiver Receiver) = 0;
1002+
9891003
virtual void codeComplete(llvm::MemoryBuffer *InputBuf, unsigned Offset,
9901004
OptionsDictionary *options,
9911005
CodeCompletionConsumer &Consumer,

tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/Frontend/Frontend.h"
2020
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
2121
#include "swift/Index/Index.h"
22+
#include "swift/Index/IndexRecord.h"
2223
#include "swift/Serialization/SerializedModuleLoader.h"
2324
// This is included only for createLazyResolver(). Move to different header ?
2425
#include "swift/Sema/IDETypeChecking.h"
@@ -367,3 +368,81 @@ void SwiftLangSupport::indexSource(StringRef InputFile,
367368
SKIndexDataConsumer IdxDataConsumer(IdxConsumer);
368369
index::indexSourceFile(CI.getPrimarySourceFile(), IdxDataConsumer);
369370
}
371+
372+
static void emitIndexDataForSourceFile(SourceFile &PrimarySourceFile,
373+
StringRef IndexStorePath,
374+
StringRef IndexUnitOutputPath,
375+
const CompilerInstance &Instance) {
376+
const auto &Invocation = Instance.getInvocation();
377+
const auto &Opts = Invocation.getFrontendOptions();
378+
379+
bool isDebugCompilation;
380+
switch (Invocation.getSILOptions().OptMode) {
381+
case OptimizationMode::NotSet:
382+
case OptimizationMode::NoOptimization:
383+
isDebugCompilation = true;
384+
break;
385+
case OptimizationMode::ForSpeed:
386+
case OptimizationMode::ForSize:
387+
isDebugCompilation = false;
388+
break;
389+
}
390+
391+
(void) index::indexAndRecord(&PrimarySourceFile, IndexUnitOutputPath,
392+
IndexStorePath,
393+
!Opts.IndexIgnoreClangModules,
394+
Opts.IndexSystemModules,
395+
Opts.IndexIgnoreStdlib,
396+
Opts.IndexIncludeLocals,
397+
isDebugCompilation,
398+
Invocation.getTargetTriple(),
399+
*Instance.getDependencyTracker(),
400+
Invocation.getIRGenOptions().FilePrefixMap);
401+
}
402+
403+
void SwiftLangSupport::indexToStore(
404+
StringRef InputFile, ArrayRef<const char *> Args,
405+
IndexStoreOptions Opts,
406+
SourceKitCancellationToken CancellationToken,
407+
IndexToStoreReceiver Receiver) {
408+
std::string Error;
409+
SwiftInvocationRef Invok =
410+
ASTMgr->getTypecheckInvocation(Args, InputFile, Error);
411+
if (!Invok) {
412+
LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
413+
Receiver(RequestResult<IndexStoreInfo>::fromError(Error));
414+
return;
415+
}
416+
417+
struct IndexStoreASTConsumer : public SwiftASTConsumer {
418+
IndexToStoreReceiver Receiver;
419+
IndexStoreOptions Opts;
420+
421+
IndexStoreASTConsumer(IndexToStoreReceiver Receiver, IndexStoreOptions Opts)
422+
: Receiver(std::move(Receiver)), Opts(std::move(Opts)) {}
423+
424+
void handlePrimaryAST(ASTUnitRef AstUnit) override {
425+
auto &SF = AstUnit->getPrimarySourceFile();
426+
auto &CI = AstUnit->getCompilerInstance();
427+
emitIndexDataForSourceFile(
428+
SF, Opts.IndexStorePath, Opts.IndexUnitOutputPath, CI);
429+
Receiver(RequestResult<IndexStoreInfo>::fromResult(IndexStoreInfo{}));
430+
}
431+
432+
void cancelled() override {
433+
Receiver(RequestResult<IndexStoreInfo>::cancelled());
434+
}
435+
436+
void failed(StringRef Error) override {
437+
Receiver(RequestResult<IndexStoreInfo>::fromError(Error));
438+
}
439+
};
440+
441+
auto ASTConsumer = std::make_shared<IndexStoreASTConsumer>(std::move(Receiver), std::move(Opts));
442+
/// FIXME: When request cancellation is implemented and Xcode adopts it,
443+
/// don't use 'OncePerASTToken'.
444+
static const char OncePerASTToken = 0;
445+
getASTManager()->processASTAsync(Invok, ASTConsumer, &OncePerASTToken,
446+
CancellationToken,
447+
llvm::vfs::getRealFileSystem());
448+
}

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,12 @@ class SwiftLangSupport : public LangSupport {
563563
void indexSource(StringRef Filename, IndexingConsumer &Consumer,
564564
ArrayRef<const char *> Args) override;
565565

566+
void indexToStore(StringRef InputFile,
567+
ArrayRef<const char *> Args,
568+
IndexStoreOptions Opts,
569+
SourceKitCancellationToken CancellationToken,
570+
IndexToStoreReceiver Receiver) override;
571+
566572
void codeComplete(llvm::MemoryBuffer *InputBuf, unsigned Offset,
567573
OptionsDictionary *options,
568574
SourceKit::CodeCompletionConsumer &Consumer,

tools/SourceKit/tools/sourcekitd-test/Options.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ def vfs_files : CommaJoined<["-"], "vfs-files=">,
166166
def vfs_name : Separate<["-"], "vfs-name">,
167167
HelpText<"Specify a virtual filesystem name">;
168168

169+
def index_store_path : Separate<["-"], "index-store-path">,
170+
HelpText<"Index Store path to use for indexing">;
171+
172+
def index_unit_output_path : Separate<["-"], "index-unit-output-path">,
173+
HelpText<"Index Store unit output path to use for indexing">;
174+
169175
def suppress_config_request : Flag<["-"], "suppress-config-request">,
170176
HelpText<"Suppress the default global configuration request, that is otherwise sent before any other request (except for the global-config request itself)">;
171177

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
154154
.Case("compile", SourceKitRequest::Compile)
155155
.Case("compile.close", SourceKitRequest::CompileClose)
156156
.Case("syntactic-expandmacro", SourceKitRequest::SyntacticMacroExpansion)
157+
.Case("index-to-store", SourceKitRequest::IndexToStore)
157158
#define SEMANTIC_REFACTORING(KIND, NAME, ID) .Case("refactoring." #ID, SourceKitRequest::KIND)
158159
#include "swift/Refactoring/RefactoringKinds.def"
159160
.Default(SourceKitRequest::None);
@@ -205,6 +206,7 @@ bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
205206
<< "- global-config\n"
206207
<< "- dependency-updated\n"
207208
<< "- syntactic-expandmacro\n"
209+
<< "- index-to-store\n"
208210
#define SEMANTIC_REFACTORING(KIND, NAME, ID) << "- refactoring." #ID "\n"
209211
#include "swift/Refactoring/RefactoringKinds.def"
210212
"\n";
@@ -428,6 +430,14 @@ bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
428430
VFSName = InputArg->getValue();
429431
break;
430432

433+
case OPT_index_store_path:
434+
IndexStorePath = InputArg->getValue();
435+
break;
436+
437+
case OPT_index_unit_output_path:
438+
IndexUnitOutputPath = InputArg->getValue();
439+
break;
440+
431441
case OPT_module_cache_path:
432442
ModuleCachePath = InputArg->getValue();
433443
break;

tools/SourceKit/tools/sourcekitd-test/TestOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ enum class SourceKitRequest {
7171
Compile,
7272
CompileClose,
7373
SyntacticMacroExpansion,
74+
IndexToStore,
7475
#define SEMANTIC_REFACTORING(KIND, NAME, ID) KIND,
7576
#include "swift/Refactoring/RefactoringKinds.def"
7677
};
@@ -148,6 +149,8 @@ struct TestOptions {
148149
llvm::Optional<std::string> VFSName;
149150
llvm::Optional<bool> CancelOnSubsequentRequest;
150151
bool ShellExecution = false;
152+
std::string IndexStorePath;
153+
std::string IndexUnitOutputPath;
151154
bool parseArgs(llvm::ArrayRef<const char *> Args);
152155
void printHelp(bool ShowHidden) const;
153156
};

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,13 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
11531153
RequestSyntacticMacroExpansion);
11541154
setSyntacticMacroExpansions(Req, Opts, SourceBuf.get());
11551155
break;
1156+
1157+
case SourceKitRequest::IndexToStore:
1158+
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
1159+
sourcekitd_request_dictionary_set_string(Req, KeyIndexStorePath, Opts.IndexStorePath.c_str());
1160+
sourcekitd_request_dictionary_set_string(Req, KeyIndexUnitOutputPath, Opts.IndexUnitOutputPath.c_str());
1161+
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestIndexToStore);
1162+
break;
11561163
}
11571164

11581165
if (!Opts.SourceFile.empty()) {
@@ -1585,6 +1592,9 @@ static bool handleResponse(sourcekitd_response_t Resp, const TestOptions &Opts,
15851592
case SourceKitRequest::Statistics:
15861593
printStatistics(Info, llvm::outs());
15871594
break;
1595+
case SourceKitRequest::IndexToStore:
1596+
printRawResponse(Resp);
1597+
break;
15881598
}
15891599
}
15901600

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,48 @@ static void handleRequestIndex(const RequestDict &Req,
14211421
});
14221422
}
14231423
1424+
static void handleRequestIndexToStore(
1425+
const RequestDict &Req, SourceKitCancellationToken CancellationToken,
1426+
ResponseReceiver Rec) {
1427+
if (checkVFSNotSupported(Req, Rec))
1428+
return;
1429+
1430+
handleSemanticRequest(Req, Rec, [Req, Rec, CancellationToken]() {
1431+
Optional<StringRef> PrimaryFilePath =
1432+
getPrimaryFilePathForRequestOrEmitError(Req, Rec);
1433+
if (!PrimaryFilePath)
1434+
return;
1435+
1436+
IndexStoreOptions Opts;
1437+
if (auto IndexStorePath = Req.getString(KeyIndexStorePath))
1438+
Opts.IndexStorePath = IndexStorePath->str();
1439+
else
1440+
return Rec(createErrorRequestInvalid("'key.index_store_path' is required"));
1441+
1442+
if (auto IndexUnitOutputPath = Req.getString(KeyIndexUnitOutputPath))
1443+
Opts.IndexUnitOutputPath = IndexUnitOutputPath->str();
1444+
else
1445+
return Rec(createErrorRequestInvalid("'key.index_unit_output_path' is required"));
1446+
1447+
SmallVector<const char *, 8> Args;
1448+
if (getCompilerArgumentsForRequestOrEmitError(Req, Args, Rec))
1449+
return;
1450+
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
1451+
Lang.indexToStore(*PrimaryFilePath, Args, std::move(Opts),
1452+
CancellationToken,
1453+
[Rec](const RequestResult<IndexStoreInfo> &Result) {
1454+
if (Result.isCancelled())
1455+
return Rec(createErrorRequestCancelled());
1456+
if (Result.isError())
1457+
return Rec(createErrorRequestFailed(Result.getError()));
1458+
1459+
ResponseBuilder RespBuilder;
1460+
return Rec(RespBuilder.createResponse());
1461+
});
1462+
});
1463+
}
1464+
1465+
14241466
static void
14251467
handleRequestCursorInfo(const RequestDict &Req,
14261468
SourceKitCancellationToken CancellationToken,
@@ -2042,6 +2084,7 @@ void handleRequestImpl(sourcekitd_object_t ReqObj,
20422084
HANDLE_REQUEST(RequestConformingMethodList, handleRequestConformingMethodList)
20432085

20442086
HANDLE_REQUEST(RequestIndex, handleRequestIndex)
2087+
HANDLE_REQUEST(RequestIndexToStore, handleRequestIndexToStore)
20452088
HANDLE_REQUEST(RequestCursorInfo, handleRequestCursorInfo)
20462089
HANDLE_REQUEST(RequestRangeInfo, handleRequestRangeInfo)
20472090
HANDLE_REQUEST(RequestSemanticRefactoring, handleRequestSemanticRefactoring)

utils/gyb_sourcekit_support/UIDs.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ def __init__(self, internal_name, external_name):
212212
KEY('Expansions', 'key.expansions'),
213213
KEY('MacroRoles', 'key.macro_roles'),
214214
KEY('ExpandedMacroReplacements', 'key.expanded_macro_replacements'),
215+
KEY('IndexStorePath', 'key.index_store_path'),
216+
KEY('IndexUnitOutputPath', 'key.index_unit_output_path'),
215217
]
216218

217219

@@ -279,6 +281,7 @@ def __init__(self, internal_name, external_name):
279281
REQUEST('EnableRequestBarriers', 'source.request.enable_request_barriers'),
280282
REQUEST('SyntacticMacroExpansion',
281283
'source.request.syntactic_macro_expansion'),
284+
REQUEST('IndexToStore', 'source.request.index_to_store'),
282285
]
283286

284287

0 commit comments

Comments
 (0)