[Frontend] Opt-in missing file recovery

This commit is contained in:
Rintaro Ishizaki
2020-12-04 15:23:43 -08:00
parent 055dc66d3b
commit bf5d22257a
6 changed files with 31 additions and 13 deletions

View File

@@ -572,7 +572,9 @@ private:
/// Return the buffer ID if it is not already compiled, or None if so.
/// Set failed on failure.
Optional<unsigned> getRecordedBufferID(const InputFile &input, bool &failed);
Optional<unsigned> getRecordedBufferID(const InputFile &input,
const bool shouldRecover,
bool &failed);
/// Given an input file, return a buffer to use for its contents,
/// and a buffer for the corresponding module doc file if one exists.

View File

@@ -46,6 +46,9 @@ class FrontendInputsAndOutputs {
/// Punt where needed to enable batch mode experiments.
bool AreBatchModeChecksBypassed = false;
/// Recover missing inputs. Note that recovery itself is users responsibility.
bool ShouldRecoverMissingInputs = false;
public:
bool areBatchModeChecksBypassed() const { return AreBatchModeChecksBypassed; }
void setBypassBatchModeChecks(bool bbc) { AreBatchModeChecksBypassed = bbc; }
@@ -66,6 +69,9 @@ public:
bool isWholeModule() const { return !hasPrimaryInputs(); }
bool shouldRecoverMissingInputs() { return ShouldRecoverMissingInputs; }
void setShouldRecoverMissingInputs() { ShouldRecoverMissingInputs = true; }
// Readers:
// All inputs:

View File

@@ -599,10 +599,14 @@ bool CompilerInstance::setUpInputs() {
const auto &Inputs =
Invocation.getFrontendOptions().InputsAndOutputs.getAllInputs();
const bool shouldRecover = Invocation.getFrontendOptions()
.InputsAndOutputs.shouldRecoverMissingInputs();
bool hasFailed = false;
for (const InputFile &input : Inputs) {
bool failed = false;
Optional<unsigned> bufferID = getRecordedBufferID(input, failed);
Optional<unsigned> bufferID =
getRecordedBufferID(input, shouldRecover, failed);
hasFailed |= failed;
if (!bufferID.hasValue() || !input.isPrimary())
@@ -623,8 +627,9 @@ bool CompilerInstance::setUpInputs() {
return false;
}
Optional<unsigned> CompilerInstance::getRecordedBufferID(const InputFile &input,
bool &failed) {
Optional<unsigned>
CompilerInstance::getRecordedBufferID(const InputFile &input,
const bool shouldRecover, bool &failed) {
if (!input.getBuffer()) {
if (Optional<unsigned> existingBufferID =
SourceMgr.getIDForBufferIdentifier(input.getFileName())) {
@@ -633,11 +638,9 @@ Optional<unsigned> CompilerInstance::getRecordedBufferID(const InputFile &input,
}
auto buffers = getInputBuffersIfPresent(input);
// For non-primary '.swift' files, recover by dummy buffer so that the primary
// files are diagnosed. Also, IDE functionalities want to proceed even with
// missing files.
if (!buffers.hasValue() && input.getType() == file_types::TY_Swift &&
!input.isPrimary()) {
// Recover by dummy buffer if requested.
if (!buffers.hasValue() && shouldRecover &&
input.getType() == file_types::TY_Swift && !input.isPrimary()) {
buffers = ModuleBuffers(llvm::MemoryBuffer::getMemBuffer(
"// missing file\n", input.getFileName()));
}

View File

@@ -38,6 +38,7 @@ FrontendInputsAndOutputs::FrontendInputsAndOutputs(
for (InputFile input : other.AllInputs)
addInput(input);
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
ShouldRecoverMissingInputs = other.ShouldRecoverMissingInputs;
}
FrontendInputsAndOutputs &FrontendInputsAndOutputs::
@@ -46,6 +47,7 @@ operator=(const FrontendInputsAndOutputs &other) {
for (InputFile input : other.AllInputs)
addInput(input);
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
ShouldRecoverMissingInputs = other.ShouldRecoverMissingInputs;
return *this;
}

View File

@@ -215,6 +215,7 @@ static FrontendInputsAndOutputs resolveSymbolicLinksInInputs(
++primaryCount;
}
assert(primaryCount < 2 && "cannot handle multiple primaries");
replacementInputsAndOutputs.addInput(
InputFile(newFilename.str(), newIsPrimary, input.getBuffer()));
}
@@ -310,6 +311,11 @@ bool ide::initCompilerInvocation(
resolveSymbolicLinksInInputs(
Invocation.getFrontendOptions().InputsAndOutputs,
UnresolvedPrimaryFile, FileSystem, Error);
// SourceKit functionalities want to proceed even if there are missing inputs.
Invocation.getFrontendOptions().InputsAndOutputs
.setShouldRecoverMissingInputs();
if (!Error.empty())
return true;

View File

@@ -2,17 +2,16 @@
// RUN: not %target-swift-frontend -c -parse-as-library /tmp/SOMETHING_DOES_NOT_EXIST_1.swift -primary-file %s /tmp/SOMETHING_DOES_NOT_EXIST_2.swift -o %t/out.o 2> %t/error1.output
// RUN: not test -f %t/out.o
// RUN: %FileCheck %s -input-file %t/error1.output --check-prefixes=CHECK,CHECK_RECOVER
// RUN: %FileCheck %s -input-file %t/error1.output --check-prefixes=CHECK
// RUN: not %target-swift-frontend -c -parse-as-library -primary-file /tmp/SOMETHING_DOES_NOT_EXIST_1.swift -primary-file %s /tmp/SOMETHING_DOES_NOT_EXIST_2.swift -o %t/out1.o -o %t/out2.o 2> %t/error2.output
// RUN: not test -f %t/out1.o
// RUN: not test -f %t/out2.o
// RUN: %FileCheck %s -input-file %t/error2.output --check-prefixes=CHECK,CHECK_FAIL
// RUN: %FileCheck %s -input-file %t/error2.output --check-prefixes=CHECK
// CHECK-DAG: <unknown>:0: error: error opening input file '{{[/\\]}}tmp{{[/\\]}}SOMETHING_DOES_NOT_EXIST_1.swift' ({{.*}})
// CHECK-DAG: <unknown>:0: error: error opening input file '{{[/\\]}}tmp{{[/\\]}}SOMETHING_DOES_NOT_EXIST_2.swift' ({{.*}})
public var x = INVALID_DECL
// CHECK_RECOVER-DAG: test{{[/\\]}}Frontend{{[/\\]}}missing_files.swift:[[@LINE-1]]:16: error: cannot find 'INVALID_DECL' in scope
// CHECK_FAIL-NOT: INVALID_DECL
// CHECK-NOT: INVALID_DECL