Skip to content

Commit 363d536

Browse files
authored
Merge pull request #34955 from rintaro/frontend-missing-input-rdar33757793
[Frontend] Recover missing input file by dummy input buffer.
2 parents 0b0025d + bf5d222 commit 363d536

File tree

7 files changed

+56
-6
lines changed

7 files changed

+56
-6
lines changed

include/swift/Frontend/Frontend.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,9 @@ class CompilerInstance {
572572
/// Return the buffer ID if it is not already compiled, or None if so.
573573
/// Set failed on failure.
574574

575-
Optional<unsigned> getRecordedBufferID(const InputFile &input, bool &failed);
575+
Optional<unsigned> getRecordedBufferID(const InputFile &input,
576+
const bool shouldRecover,
577+
bool &failed);
576578

577579
/// Given an input file, return a buffer to use for its contents,
578580
/// and a buffer for the corresponding module doc file if one exists.

include/swift/Frontend/FrontendInputsAndOutputs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class FrontendInputsAndOutputs {
4646
/// Punt where needed to enable batch mode experiments.
4747
bool AreBatchModeChecksBypassed = false;
4848

49+
/// Recover missing inputs. Note that recovery itself is users responsibility.
50+
bool ShouldRecoverMissingInputs = false;
51+
4952
public:
5053
bool areBatchModeChecksBypassed() const { return AreBatchModeChecksBypassed; }
5154
void setBypassBatchModeChecks(bool bbc) { AreBatchModeChecksBypassed = bbc; }
@@ -66,6 +69,9 @@ class FrontendInputsAndOutputs {
6669

6770
bool isWholeModule() const { return !hasPrimaryInputs(); }
6871

72+
bool shouldRecoverMissingInputs() { return ShouldRecoverMissingInputs; }
73+
void setShouldRecoverMissingInputs() { ShouldRecoverMissingInputs = true; }
74+
6975
// Readers:
7076

7177
// All inputs:

lib/Frontend/Frontend.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -599,17 +599,23 @@ bool CompilerInstance::setUpInputs() {
599599

600600
const auto &Inputs =
601601
Invocation.getFrontendOptions().InputsAndOutputs.getAllInputs();
602+
const bool shouldRecover = Invocation.getFrontendOptions()
603+
.InputsAndOutputs.shouldRecoverMissingInputs();
604+
605+
bool hasFailed = false;
602606
for (const InputFile &input : Inputs) {
603607
bool failed = false;
604-
Optional<unsigned> bufferID = getRecordedBufferID(input, failed);
605-
if (failed)
606-
return true;
608+
Optional<unsigned> bufferID =
609+
getRecordedBufferID(input, shouldRecover, failed);
610+
hasFailed |= failed;
607611

608612
if (!bufferID.hasValue() || !input.isPrimary())
609613
continue;
610614

611615
recordPrimaryInputBuffer(*bufferID);
612616
}
617+
if (hasFailed)
618+
return true;
613619

614620
// Set the primary file to the code-completion point if one exists.
615621
if (codeCompletionBufferID.hasValue() &&
@@ -621,8 +627,9 @@ bool CompilerInstance::setUpInputs() {
621627
return false;
622628
}
623629

624-
Optional<unsigned> CompilerInstance::getRecordedBufferID(const InputFile &input,
625-
bool &failed) {
630+
Optional<unsigned>
631+
CompilerInstance::getRecordedBufferID(const InputFile &input,
632+
const bool shouldRecover, bool &failed) {
626633
if (!input.getBuffer()) {
627634
if (Optional<unsigned> existingBufferID =
628635
SourceMgr.getIDForBufferIdentifier(input.getFileName())) {
@@ -631,6 +638,13 @@ Optional<unsigned> CompilerInstance::getRecordedBufferID(const InputFile &input,
631638
}
632639
auto buffers = getInputBuffersIfPresent(input);
633640

641+
// Recover by dummy buffer if requested.
642+
if (!buffers.hasValue() && shouldRecover &&
643+
input.getType() == file_types::TY_Swift && !input.isPrimary()) {
644+
buffers = ModuleBuffers(llvm::MemoryBuffer::getMemBuffer(
645+
"// missing file\n", input.getFileName()));
646+
}
647+
634648
if (!buffers.hasValue()) {
635649
failed = true;
636650
return None;

lib/Frontend/FrontendInputsAndOutputs.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ FrontendInputsAndOutputs::FrontendInputsAndOutputs(
3838
for (InputFile input : other.AllInputs)
3939
addInput(input);
4040
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
41+
ShouldRecoverMissingInputs = other.ShouldRecoverMissingInputs;
4142
}
4243

4344
FrontendInputsAndOutputs &FrontendInputsAndOutputs::
@@ -46,6 +47,7 @@ operator=(const FrontendInputsAndOutputs &other) {
4647
for (InputFile input : other.AllInputs)
4748
addInput(input);
4849
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
50+
ShouldRecoverMissingInputs = other.ShouldRecoverMissingInputs;
4951
return *this;
5052
}
5153

lib/IDE/Utils.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ static FrontendInputsAndOutputs resolveSymbolicLinksInInputs(
215215
++primaryCount;
216216
}
217217
assert(primaryCount < 2 && "cannot handle multiple primaries");
218+
218219
replacementInputsAndOutputs.addInput(
219220
InputFile(newFilename.str(), newIsPrimary, input.getBuffer()));
220221
}
@@ -310,6 +311,11 @@ bool ide::initCompilerInvocation(
310311
resolveSymbolicLinksInInputs(
311312
Invocation.getFrontendOptions().InputsAndOutputs,
312313
UnresolvedPrimaryFile, FileSystem, Error);
314+
315+
// SourceKit functionalities want to proceed even if there are missing inputs.
316+
Invocation.getFrontendOptions().InputsAndOutputs
317+
.setShouldRecoverMissingInputs();
318+
313319
if (!Error.empty())
314320
return true;
315321

test/Frontend/missing_files.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// 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
4+
// RUN: not test -f %t/out.o
5+
// RUN: %FileCheck %s -input-file %t/error1.output --check-prefixes=CHECK
6+
7+
// 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
8+
// RUN: not test -f %t/out1.o
9+
// RUN: not test -f %t/out2.o
10+
// RUN: %FileCheck %s -input-file %t/error2.output --check-prefixes=CHECK
11+
12+
// CHECK-DAG: <unknown>:0: error: error opening input file '{{[/\\]}}tmp{{[/\\]}}SOMETHING_DOES_NOT_EXIST_1.swift' ({{.*}})
13+
// CHECK-DAG: <unknown>:0: error: error opening input file '{{[/\\]}}tmp{{[/\\]}}SOMETHING_DOES_NOT_EXIST_2.swift' ({{.*}})
14+
15+
public var x = INVALID_DECL
16+
// CHECK-NOT: INVALID_DECL
17+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// RUN: %sourcekitd-test -req=complete -pos=1:1 %s -- /tmp/SOMETHING_DOES_NOT_EXIST_1.swift %s /tmp/SOMETHING_DOES_NOT_EXIST_2.swift | %FileCheck %s
2+
3+
// CHECK: results: [

0 commit comments

Comments
 (0)