mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Frontend] Opt-in missing file recovery
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user