in tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp [559:1260]
static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
if (!Opts.JsonRequestPath.empty())
return handleJsonRequestPath(Opts.JsonRequestPath, Opts);
if (Opts.Request == SourceKitRequest::DemangleNames ||
Opts.Request == SourceKitRequest::MangleSimpleClasses)
Opts.SourceFile.clear();
std::string SourceFile = Opts.SourceFile;
if (!SourceFile.empty()) {
llvm::SmallString<64> AbsSourceFile;
AbsSourceFile += SourceFile;
llvm::sys::fs::make_absolute(AbsSourceFile);
llvm::sys::path::native(AbsSourceFile);
SourceFile = std::string(AbsSourceFile.str());
}
std::string SemaName = !Opts.Name.empty() ? Opts.Name : SourceFile;
if (!Opts.TextInputFile.empty()) {
auto Buf = getBufferForFilename(Opts.TextInputFile, Opts.VFSFiles);
Opts.SourceText = Buf->getBuffer().str();
}
std::unique_ptr<llvm::MemoryBuffer> SourceBuf;
if (Opts.SourceText.hasValue()) {
SourceBuf = llvm::MemoryBuffer::getMemBuffer(*Opts.SourceText, Opts.SourceFile);
} else if (!SourceFile.empty()) {
SourceBuf = llvm::MemoryBuffer::getMemBuffer(
getBufferForFilename(SourceFile, Opts.VFSFiles)->getBuffer(),
SourceFile);
}
// FIXME: we should detect if offset is required but not set.
unsigned ByteOffset = Opts.Offset;
if (Opts.Line != 0) {
ByteOffset = resolveFromLineCol(Opts.Line, Opts.Col, SourceBuf.get());
}
if (Opts.EndLine != 0) {
Opts.Length = resolveFromLineCol(Opts.EndLine, Opts.EndCol, SourceBuf.get()) -
ByteOffset;
}
bool compilerArgsAreClang = false;
sourcekitd_object_t Req = sourcekitd_request_dictionary_create(nullptr,
nullptr, 0);
ActiveRequest = Opts.Request;
switch (Opts.Request) {
case SourceKitRequest::None:
llvm::errs() << "request is not set\n";
// FIXME: This non-zero return value is not propagated as an exit code.
// In other words, despite returning 1 here, the program still exits
// with a zero (successful) exit code.
return 1;
case SourceKitRequest::GlobalConfiguration:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestGlobalConfiguration);
for (auto &Opt : Opts.RequestOptions) {
auto KeyValue = StringRef(Opt).split('=');
std::string KeyStr("key.");
KeyStr.append(KeyValue.first.str());
sourcekitd_uid_t Key = sourcekitd_uid_get_from_cstr(KeyStr.c_str());
int64_t Value = 0;
KeyValue.second.getAsInteger(0, Value);
sourcekitd_request_dictionary_set_int64(Req, Key, Value);
}
break;
case SourceKitRequest::ProtocolVersion:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestProtocolVersion);
break;
case SourceKitRequest::CompilerVersion:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCompilerVersion);
break;
case SourceKitRequest::DemangleNames:
prepareDemangleRequest(Req, Opts);
break;
case SourceKitRequest::MangleSimpleClasses:
prepareMangleRequest(Req, Opts);
break;
case SourceKitRequest::EnableCompileNotifications: {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestEnableCompileNotifications);
int64_t value = 1;
for (auto &Opt : Opts.RequestOptions) {
auto KeyValue = StringRef(Opt).split('=');
if (KeyValue.first == "value") {
KeyValue.second.getAsInteger(0, value);
} else {
llvm::errs() << "unknown parameter '" << KeyValue.first
<< "' in -req-opts";
return 1;
}
}
sourcekitd_request_dictionary_set_int64(Req, KeyValue, value);
break;
}
case SourceKitRequest::Index:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestIndex);
break;
case SourceKitRequest::CodeComplete:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCodeComplete);
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
// Default to sort by name.
Opts.RequestOptions.insert(Opts.RequestOptions.begin(), "sort.byname=1");
addRequestOptions(Req, Opts, KeyCodeCompleteOptions, "key.codecomplete.");
break;
case SourceKitRequest::CodeCompleteOpen:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestCodeCompleteOpen);
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
addRequestOptions(Req, Opts, KeyCodeCompleteOptions, "key.codecomplete.");
break;
case SourceKitRequest::CodeCompleteClose:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestCodeCompleteClose);
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
break;
case SourceKitRequest::CodeCompleteUpdate:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestCodeCompleteUpdate);
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
addRequestOptions(Req, Opts, KeyCodeCompleteOptions, "key.codecomplete.");
break;
case SourceKitRequest::CodeCompleteCacheOnDisk:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestCodeCompleteCacheOnDisk);
sourcekitd_request_dictionary_set_string(Req, KeyName,
Opts.CachePath.c_str());
break;
case SourceKitRequest::CodeCompleteSetPopularAPI: {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestCodeCompleteSetPopularAPI);
auto addPopularList = [&Req](StringRef filename, sourcekitd_uid_t key) {
std::vector<std::string> names;
if (readPopularAPIList(filename, names))
return true;
sourcekitd_object_t popular = sourcekitd_request_array_create(nullptr, 0);
for (auto name : names)
sourcekitd_request_array_set_string(popular, SOURCEKITD_ARRAY_APPEND,
name.c_str());
sourcekitd_request_dictionary_set_value(Req, key, popular);
return false;
};
for (auto &Opt : Opts.RequestOptions) {
auto KeyValue = StringRef(Opt).split('=');
auto key = llvm::StringSwitch<sourcekitd_uid_t>(KeyValue.first)
.Case("popular", KeyPopular)
.Case("unpopular", KeyUnpopular)
.Default(nullptr);
if (!key) {
llvm::errs() << "invalid key '" << KeyValue.first << "' in -req-opts\n";
return 1;
}
if (addPopularList(KeyValue.second, key))
return 1;
}
break;
}
case SourceKitRequest::TypeContextInfo:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestTypeContextInfo);
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
addRequestOptions(Req, Opts, KeyTypeContextInfoOptions,
"key.typecontextinfo.");
break;
case SourceKitRequest::ConformingMethodList:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestConformingMethodList);
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
addRequestOptionsDirect(Req, Opts);
break;
case SourceKitRequest::CursorInfo:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCursorInfo);
if (Opts.CollectActionables) {
sourcekitd_request_dictionary_set_int64(Req, KeyRetrieveRefactorActions, 1);
}
if (Opts.Length) {
sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);
}
if (!Opts.USR.empty()) {
sourcekitd_request_dictionary_set_string(Req, KeyUSR, Opts.USR.c_str());
} else {
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
}
addRequestOptionsDirect(Req, Opts);
break;
case SourceKitRequest::RangeInfo: {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestRangeInfo);
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
auto Length = Opts.Length;
if (Opts.Length == 0 && Opts.EndLine > 0) {
auto EndOff = resolveFromLineCol(Opts.EndLine, Opts.EndCol, SourceFile,
Opts.VFSFiles);
Length = EndOff - ByteOffset;
}
sourcekitd_request_dictionary_set_int64(Req, KeyLength, Length);
break;
}
case SourceKitRequest::CollectExpresstionType: {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCollectExpressionType);
addRequestOptionsDirect(Req, Opts);
break;
}
case SourceKitRequest::CollectVariableType: {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestCollectVariableType);
if (Opts.Length) {
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);
}
addRequestOptionsDirect(Req, Opts);
break;
}
#define SEMANTIC_REFACTORING(KIND, NAME, ID) \
case SourceKitRequest::KIND: \
setRefactoringFields(Req, Opts, KindRefactoring##KIND, SourceBuf.get()); \
break;
#include "swift/IDE/RefactoringKinds.def"
case SourceKitRequest::MarkupToXML: {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestMarkupToXML);
break;
}
case SourceKitRequest::NameTranslation: {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestNameTranslation);
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
StringRef BaseName;
llvm::SmallVector<StringRef, 4> ArgPieces;
sourcekitd_uid_t ArgName;
if (!Opts.SwiftName.empty()) {
sourcekitd_request_dictionary_set_uid(Req, KeyNameKind, KindNameSwift);
ArgName = KeyArgNames;
StringRef Text(Opts.SwiftName);
auto ArgStart = Text.find_first_of('(');
if (ArgStart == StringRef::npos) {
BaseName = Text;
} else {
BaseName = Text.substr(0, ArgStart);
auto ArgEnd = Text.find_last_of(')');
if (ArgEnd == StringRef::npos) {
llvm::errs() << "Swift name is malformed.\n";
return 1;
}
StringRef AllArgs = Text.substr(ArgStart + 1, ArgEnd - ArgStart - 1);
AllArgs.split(ArgPieces, ':');
if (!ArgPieces.empty()) {
if (!ArgPieces.back().empty()) {
llvm::errs() << "Swift name is malformed.\n";
return 1;
}
ArgPieces.pop_back();
}
}
} else if (!Opts.ObjCName.empty()) {
sourcekitd_request_dictionary_set_uid(Req, KeyNameKind, KindNameObjc);
BaseName = Opts.ObjCName;
ArgName = KeySelectorPieces;
} else if (!Opts.ObjCSelector.empty()) {
sourcekitd_request_dictionary_set_uid(Req, KeyNameKind, KindNameObjc);
StringRef Name(Opts.ObjCSelector);
Name.split(ArgPieces, ':');
if (ArgPieces.back().empty())
ArgPieces.pop_back();
ArgName = KeySelectorPieces;
} else {
llvm::errs() << "must specify either -swift-name or -objc-name or -objc-selector\n";
return 1;
}
if (!BaseName.empty()) {
std::string S = BaseName.str();
sourcekitd_request_dictionary_set_string(Req, KeyBaseName, S.c_str());
}
if (!ArgPieces.empty()) {
sourcekitd_object_t Arr = sourcekitd_request_array_create(nullptr, 0);
for (StringRef A : ArgPieces) {
std::string S = A.str();
sourcekitd_request_array_set_string(Arr, SOURCEKITD_ARRAY_APPEND,
S.c_str());
}
sourcekitd_request_dictionary_set_value(Req, ArgName, Arr);
}
break;
}
case SourceKitRequest::RelatedIdents:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestRelatedIdents);
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
break;
case SourceKitRequest::SyntaxMap:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, true);
sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
sourcekitd_request_dictionary_set_uid(Req, KeySyntaxTreeTransferMode,
KindSyntaxTreeOff);
sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
break;
case SourceKitRequest::Structure:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, true);
sourcekitd_request_dictionary_set_uid(Req, KeySyntaxTreeTransferMode,
KindSyntaxTreeOff);
sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
break;
case SourceKitRequest::Format:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
sourcekitd_request_dictionary_set_uid(Req, KeySyntaxTreeTransferMode,
KindSyntaxTreeOff);
sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
break;
case SourceKitRequest::ExpandPlaceholder:
if (Opts.Length) {
// Single placeholder by location.
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorExpandPlaceholder);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);
} else {
if (ByteOffset) {
llvm::errs() << "Missing '-length <number>'\n";
return 1;
}
// Expand all placeholders.
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
}
break;
case SourceKitRequest::SyntaxTree:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
sourcekitd_request_dictionary_set_uid(Req, KeySyntaxTreeTransferMode,
KindSyntaxTreeFull);
sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, true);
break;
case SourceKitRequest::DocInfo:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestDocInfo);
break;
case SourceKitRequest::SemanticInfo:
InitOpts.UsedSema = true;
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
break;
case SourceKitRequest::Open:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
addRequestOptionsDirect(Req, Opts);
break;
case SourceKitRequest::Close:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorClose);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
break;
case SourceKitRequest::Edit:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestEditorReplaceText);
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);
sourcekitd_request_dictionary_set_string(Req, KeySourceText,
Opts.ReplaceText.getValue().c_str());
addRequestOptionsDirect(Req, Opts);
break;
case SourceKitRequest::PrintAnnotations:
return printAnnotations();
case SourceKitRequest::PrintDiags:
return printDiags();
case SourceKitRequest::ExtractComment:
if (Opts.SourceFile.empty()) {
llvm::errs() << "Missing '<source-file>' \n";
return 1;
}
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestEditorExtractTextFromComment);
break;
case SourceKitRequest::InterfaceGen:
case SourceKitRequest::InterfaceGenOpen:
sourcekitd_request_dictionary_set_int64(Req, KeySynthesizedExtension,
Opts.SynthesizedExtensions);
if (Opts.ModuleName.empty() && Opts.HeaderPath.empty() &&
Opts.SourceFile.empty() && Opts.USR.empty()) {
llvm::errs() << "Missing '-module <module name>' or '-header <path>'" <<
"or '<source-file>' or '-usr <USR>' \n";
return 1;
}
if (!Opts.ModuleName.empty()) {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestEditorOpenInterface);
} else if (!Opts.USR.empty()) {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestEditorOpenSwiftTypeInterface);
} else if (!Opts.SourceFile.empty()) {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestEditorOpenSwiftSourceInterface);
} else {
if (Opts.UsingSwiftArgs)
sourcekitd_request_dictionary_set_int64(Req, KeyUsingSwiftArgs, true);
else
compilerArgsAreClang = true;
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestEditorOpenHeaderInterface);
}
sourcekitd_request_dictionary_set_string(Req, KeyName, getInterfaceGenDocumentName().c_str());
if (!Opts.ModuleGroupName.empty())
sourcekitd_request_dictionary_set_string(Req, KeyGroupName,
Opts.ModuleGroupName.c_str());
if (!Opts.InterestedUSR.empty())
sourcekitd_request_dictionary_set_string(Req, KeyInterestedUSR,
Opts.InterestedUSR.c_str());
if (!Opts.USR.empty())
sourcekitd_request_dictionary_set_string(Req, KeyUSR, Opts.USR.c_str());
break;
case SourceKitRequest::FindInterfaceDoc:
if (Opts.ModuleName.empty()) {
llvm::errs() << "Missing '-module <module name>'\n";
return 1;
}
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorFindInterfaceDoc);
break;
case SourceKitRequest::FindUSR:
if (Opts.USR.empty()) {
llvm::errs() << "Missing '-usr <USR string>'\n";
return 1;
}
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorFindUSR);
sourcekitd_request_dictionary_set_string(Req, KeyUSR, Opts.USR.c_str());
break;
case SourceKitRequest::ModuleGroups:
if (Opts.ModuleName.empty()) {
llvm::errs() << "Missing '-module <module name>'\n";
return 1;
}
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestModuleGroups);
break;
case SourceKitRequest::FindLocalRenameRanges:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestFindLocalRenameRanges);
sourcekitd_request_dictionary_set_int64(Req, KeyLine, Opts.Line);
sourcekitd_request_dictionary_set_int64(Req, KeyColumn, Opts.Col);
sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);
break;
case SourceKitRequest::SyntacticRename:
case SourceKitRequest::FindRenameRanges: {
if (Opts.Request == SourceKitRequest::SyntacticRename) {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestSyntacticRename);
} else {
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestFindRenameRanges);
}
if (Opts.RenameSpecPath.empty()) {
llvm::errs() << "Missing '-rename-spec <file path>'\n";
return 1;
}
auto Buffer =
getBufferForFilename(Opts.RenameSpecPath, Opts.VFSFiles)->getBuffer();
char *Err = nullptr;
auto RenameSpec = sourcekitd_request_create_from_yaml(Buffer.data(), &Err);
if (!RenameSpec) {
assert(Err);
llvm::errs() << Err;
free(Err);
return 1;
}
sourcekitd_request_dictionary_set_value(Req, KeyRenameLocations, RenameSpec);
break;
}
case SourceKitRequest::Statistics:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestStatistics);
break;
case SourceKitRequest::DependencyUpdated:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
RequestDependencyUpdated);
break;
case SourceKitRequest::Diagnostics:
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestDiagnostics);
break;
case SourceKitRequest::Compile:
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCompile);
break;
case SourceKitRequest::CompileClose:
sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCompileClose);
break;
}
if (!SourceFile.empty()) {
if (Opts.PassAsSourceText) {
auto Buf = getBufferForFilename(SourceFile, Opts.VFSFiles);
sourcekitd_request_dictionary_set_string(Req, KeySourceText,
Buf->getBufferStart());
}
sourcekitd_request_dictionary_set_string(Req, KeySourceFile,
SourceFile.c_str());
}
if (Opts.SourceText) {
sourcekitd_request_dictionary_set_string(Req, KeySourceText,
Opts.SourceText->c_str());
sourcekitd_request_dictionary_set_string(Req, KeySourceFile,
SemaName.c_str());
}
if (!Opts.CompilerArgs.empty() ||
!Opts.ModuleCachePath.empty() ||
Opts.DisableImplicitConcurrencyModuleImport) {
sourcekitd_object_t Args = sourcekitd_request_array_create(nullptr, 0);
if (!Opts.ModuleCachePath.empty()) {
if (compilerArgsAreClang) {
// We need -fmodules or else the clang argument parsing does not honour
// -fmodules-cache-path. In reality, the swift ClangImporter will always
// enable modules when importing, so this should only impact the
// clang argument parsing. This is needed even if the header doesn't
// use modules, since Swift itself will import its shims module, and
// that needs to honour the -module-cache-path option when testing.
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, "-fmodules");
std::string opt = "-fmodules-cache-path=" + Opts.ModuleCachePath;
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, opt.c_str());
} else {
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, "-module-cache-path");
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, Opts.ModuleCachePath.c_str());
}
}
if (Opts.DisableImplicitConcurrencyModuleImport && !compilerArgsAreClang) {
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND,
"-Xfrontend");
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND,
"-disable-implicit-concurrency-module-import");
}
for (auto Arg : Opts.CompilerArgs)
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, Arg);
sourcekitd_request_dictionary_set_value(Req, KeyCompilerArgs, Args);
sourcekitd_request_release(Args);
}
if (!Opts.ModuleName.empty()) {
sourcekitd_request_dictionary_set_string(Req, KeyModuleName,
Opts.ModuleName.c_str());
}
if (!Opts.HeaderPath.empty()) {
sourcekitd_request_dictionary_set_string(Req, KeyFilePath,
Opts.HeaderPath.c_str());
}
if (Opts.CancelOnSubsequentRequest.hasValue()) {
sourcekitd_request_dictionary_set_int64(Req, KeyCancelOnSubsequentRequest,
*Opts.CancelOnSubsequentRequest);
}
if (Opts.SimulateLongRequest.hasValue()) {
sourcekitd_request_dictionary_set_int64(Req, KeySimulateLongRequest,
*Opts.SimulateLongRequest);
}
if (!Opts.SwiftVersion.empty()) {
if (Opts.PassVersionAsString) {
sourcekitd_request_dictionary_set_string(Req, KeySwiftVersion,
Opts.SwiftVersion.c_str());
} else {
unsigned ver;
if (StringRef(Opts.SwiftVersion).getAsInteger(10, ver)) {
llvm::errs() << "error: expected integer for 'swift-version'\n";
return true;
}
sourcekitd_request_dictionary_set_int64(Req, KeySwiftVersion, ver);
}
}
if (Opts.VFSName) {
sourcekitd_request_dictionary_set_string(Req, KeyVFSName, Opts.VFSName->c_str());
}
if (!Opts.VFSFiles.empty()) {
sourcekitd_object_t files = sourcekitd_request_array_create(nullptr, 0);
for (auto &NameAndTarget : Opts.VFSFiles) {
sourcekitd_object_t file = sourcekitd_request_dictionary_create(nullptr, nullptr, 0);
sourcekitd_request_dictionary_set_string(file, KeyName, NameAndTarget.first().data());
if (NameAndTarget.second.passAsSourceText) {
auto content = getBufferForFilename(NameAndTarget.first(), Opts.VFSFiles);
sourcekitd_request_dictionary_set_string(file, KeySourceText, content->getBufferStart());
} else {
sourcekitd_request_dictionary_set_string(file, KeySourceFile, NameAndTarget.second.path.c_str());
}
sourcekitd_request_array_set_value(files, SOURCEKITD_ARRAY_APPEND, file);
}
sourcekitd_object_t vfsOpts = sourcekitd_request_dictionary_create(nullptr, nullptr, 0);
sourcekitd_request_dictionary_set_value(vfsOpts, KeyFiles, files);
sourcekitd_request_dictionary_set_value(Req, KeyVFSOptions, vfsOpts);
sourcekitd_request_release(vfsOpts);
sourcekitd_request_release(files);
}
int64_t BeforeInstructions;
if (Opts.measureInstructions)
BeforeInstructions = getSourceKitInstructionCount();
if (!Opts.isAsyncRequest) {
sourcekitd_response_t Resp = sendRequestSync(Req, Opts);
if (Opts.measureInstructions) {
int64_t AfterInstructions = getSourceKitInstructionCount();
llvm::errs() << "request instructions: "
<< (AfterInstructions - BeforeInstructions);
}
sourcekitd_request_release(Req);
return handleResponse(Resp, Opts, SemaName, std::move(SourceBuf),
&InitOpts)
? 1
: 0;
} else {
#if SOURCEKITD_HAS_BLOCKS
AsyncResponseInfo info;
info.options = Opts;
info.sourceFilename = std::move(SemaName);
info.sourceBuffer = std::move(SourceBuf);
unsigned respIndex = asyncResponses.size();
asyncResponses.push_back(std::move(info));
if (Opts.PrintRequest)
sourcekitd_request_description_dump(Req);
sourcekitd_send_request(Req, &asyncResponses[respIndex].requestHandle,
^(sourcekitd_response_t resp) {
auto &info = asyncResponses[respIndex];
info.response = resp;
sourcekitd_request_handle_dispose(
info.requestHandle);
info.semaphore.signal(); // Ready to be handled!
});
#else
llvm::report_fatal_error(
"-async not supported when sourcekitd is built without blocks support");
#endif
if (Opts.measureInstructions) {
int64_t AfterInstructions = getSourceKitInstructionCount();
llvm::errs() << "request instructions: "
<< (AfterInstructions - BeforeInstructions);
}
sourcekitd_request_release(Req);
return 0;
}
}