[sourcekit] Use the driver to parse command line arguments

Stop parsing frontend arguments directly and use the driver instead. The
most intersting part of this change is that it forces us to consider
whether our compiler invocation will have inputs or not.  We have
several kinds of requests that need to create a compiler instance, but
not parse any inputs (interface-generation, doc-info, and indexing when
operating on a module instead of source files).

Incidentally, add an error when trying to do doc-info on multiple source
files. This was already very broken (assertion failures and bogus source
locations), so add an error for it.

rdar://problem/17897287
This commit is contained in:
Ben Langmuir
2018-01-31 15:26:12 -08:00
parent 368e25ec05
commit 72bde687e4
10 changed files with 98 additions and 72 deletions

View File

@@ -21,6 +21,7 @@
#include "SourceKit/Support/Tracing.h"
#include "swift/Basic/Cache.h"
#include "swift/Driver/FrontendUtil.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/Strings.h"
@@ -370,49 +371,6 @@ SwiftASTManager::getMemoryBuffer(StringRef Filename, std::string &Error) {
return Impl.getMemoryBuffer(Filename, Error);
}
static void setModuleName(CompilerInvocation &Invocation) {
if (!Invocation.getModuleName().empty())
return;
StringRef Filename = Invocation.getOutputFilename();
if (Filename.empty()) {
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
Invocation.setModuleName("main");
return;
}
Filename = Invocation.getFrontendOptions()
.InputsAndOutputs.getFilenameOfFirstInput();
}
Filename = llvm::sys::path::filename(Filename);
StringRef ModuleName = llvm::sys::path::stem(Filename);
if (ModuleName.empty() || !Lexer::isIdentifier(ModuleName)) {
Invocation.setModuleName("main");
return;
}
Invocation.setModuleName(ModuleName);
}
static void sanitizeCompilerArgs(ArrayRef<const char *> Args,
SmallVectorImpl<const char *> &NewArgs) {
for (const char *CArg : Args) {
StringRef Arg = CArg;
if (Arg.startswith("-j"))
continue;
if (Arg == "-c")
continue;
if (Arg == "-v")
continue;
if (Arg == "-Xfrontend")
continue;
if (Arg == "-embed-bitcode")
continue;
if (Arg == "-enable-bridging-pch" ||
Arg == "-disable-bridging-pch")
continue;
NewArgs.push_back(CArg);
}
}
static FrontendInputsAndOutputs
convertFileContentsToInputs(const SmallVectorImpl<FileContent> &contents) {
FrontendInputsAndOutputs inputsAndOutputs;
@@ -456,19 +414,20 @@ resolveSymbolicLinksInInputs(FrontendInputsAndOutputs &inputsAndOutputs,
}
bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
ArrayRef<const char *> OrigArgs,
ArrayRef<const char *> Args,
DiagnosticEngine &Diags,
StringRef UnresolvedPrimaryFile,
std::string &Error) {
SmallVector<const char *, 16> Args;
sanitizeCompilerArgs(OrigArgs, Args);
Invocation.setRuntimeResourcePath(Impl.RuntimeResourcePath);
if (Invocation.parseArgs(Args, Diags)) {
if (auto driverInvocation = driver::createCompilerInvocation(Args, Diags)) {
Invocation = *driverInvocation;
} else {
// FIXME: Get the actual diagnostic.
Error = "error when parsing the compiler arguments";
return true;
}
Invocation.setRuntimeResourcePath(Impl.RuntimeResourcePath);
Invocation.getFrontendOptions().InputsAndOutputs =
resolveSymbolicLinksInInputs(
Invocation.getFrontendOptions().InputsAndOutputs,
@@ -479,7 +438,7 @@ bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions();
ImporterOpts.DetailedPreprocessingRecord = true;
setModuleName(Invocation);
assert(!Invocation.getModuleName().empty());
Invocation.setSerializedDiagnosticsPath(StringRef());
Invocation.getLangOptions().AttachCommentsToDecls = true;
Invocation.getLangOptions().DiagnosticsEditorMode = true;
@@ -497,6 +456,10 @@ bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
FrontendOpts.IndexStorePath.clear();
ImporterOpts.IndexStorePath.clear();
// Force the action type to be -typecheck. This affects importing the
// SwiftONoneSupport module.
FrontendOpts.RequestedAction = FrontendOptions::ActionType::Typecheck;
return false;
}
@@ -520,6 +483,27 @@ bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &CompInvok,
return false;
}
bool SwiftASTManager::initCompilerInvocationNoInputs(
swift::CompilerInvocation &Invocation, ArrayRef<const char *> OrigArgs,
swift::DiagnosticEngine &Diags, std::string &Error, bool AllowInputs) {
SmallVector<const char *, 16> Args(OrigArgs.begin(), OrigArgs.end());
// Use stdin as a .swift input to satisfy the driver.
Args.push_back("-");
if (initCompilerInvocation(Invocation, Args, Diags, "", Error))
return true;
if (!AllowInputs &&
Invocation.getFrontendOptions().InputsAndOutputs.inputCount() > 1) {
Error = "unexpected input in compiler arguments";
return true;
}
// Clear the inputs.
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
return false;
}
SwiftInvocationRef
SwiftASTManager::getInvocation(ArrayRef<const char *> OrigArgs,
StringRef PrimaryFile,