Skip to content

Commit ea3ef98

Browse files
authored
Merge pull request swiftlang#30302 from CodaFi/all-the-fixins
Teach the Dependency Verifier to Emit Fixits
2 parents 3325cd3 + 6abf057 commit ea3ef98

File tree

5 files changed

+48
-12
lines changed

5 files changed

+48
-12
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ ERROR(missing_member_dependency,none,
396396
"dependency does not exist: %1",
397397
(/*Expectation::Kind*/uint8_t, StringRef))
398398
ERROR(unexpected_dependency,none,
399-
"unexpected %0 %select{%error|%error||potential member|dynamic member}1 "
399+
"unexpected %0 %select{%error|%error|member|potential member|dynamic member}1 "
400400
"dependency: %2", (StringRef, /*Expectation::Kind*/uint8_t, StringRef))
401401
ERROR(unexpected_provided_entity,none,
402402
"unexpected provided entity: %0", (StringRef))

lib/Frontend/DependencyVerifier.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ struct Obligation {
224224
"Cannot form negative obligation!");
225225
}
226226

227+
Expectation::Scope getScope() const { return info.second; }
227228
Expectation::Kind getKind() const { return info.first; }
228229
StringRef getName() const { return name; }
229230
bool getCascades() const {
@@ -240,6 +241,22 @@ struct Obligation {
240241
}
241242
}
242243

244+
StringRef renderAsFixit(ASTContext &Ctx) const {
245+
llvm::StringRef selector =
246+
#define MATRIX_ENTRY(SELECTOR, SCOPE, KIND) \
247+
if (getKind() == Expectation::Kind::KIND && \
248+
getScope() == Expectation::Scope::SCOPE) { \
249+
return SELECTOR; \
250+
}
251+
252+
[this]() -> StringRef {
253+
EXPECTATION_MATRIX
254+
return "";
255+
}();
256+
#undef MATRIX_ENTRY
257+
return Ctx.AllocateCopy(("// " + selector + "{{" + getName() + "}}").str());
258+
}
259+
243260
public:
244261
bool isOwed() const { return state == State::Owed; }
245262
FullfillmentToken fullfill() {
@@ -439,17 +456,19 @@ bool DependencyVerifier::constructObligations(const SourceFile *SF,
439456
auto demContext = copyDemangledTypeName(Ctx, context);
440457
auto key = Ctx.AllocateCopy((demContext + "." + name).str());
441458
Obligations.insert({Obligation::Key::forMember(key),
442-
{context, Expectation::Kind::Member,
459+
{key, Expectation::Kind::Member,
443460
isCascadingUse ? Expectation::Scope::Cascading
444461
: Expectation::Scope::Private}});
445462
}
446463
break;
447-
case NodeKind::dynamicLookup:
464+
case NodeKind::dynamicLookup: {
465+
auto contextCpy = Ctx.AllocateCopy(context);
448466
Obligations.insert({Obligation::Key::forDynamicMember(name),
449-
{context, Expectation::Kind::DynamicMember,
467+
{contextCpy, Expectation::Kind::DynamicMember,
450468
isCascadingUse ? Expectation::Scope::Cascading
451469
: Expectation::Scope::Private}});
452470
break;
471+
}
453472
case NodeKind::topLevel:
454473
case NodeKind::sourceFileProvide:
455474
Obligations.insert({Obligation::Key::forProvides(name),
@@ -564,6 +583,7 @@ bool DependencyVerifier::diagnoseUnfulfilledObligations(
564583
CharSourceRange EntireRange = SM.getRangeForBuffer(*SF->getBufferID());
565584
StringRef InputFile = SM.extractText(EntireRange);
566585
auto &diags = SF->getASTContext().Diags;
586+
auto &Ctx = SF->getASTContext();
567587
forEachOwedObligation(Obligations, [&](StringRef key, Obligation &p) {
568588
// HACK: Diagnosing the end of the buffer will print a carat pointing
569589
// at the file path, but not print any of the buffer's contents, which
@@ -576,10 +596,12 @@ bool DependencyVerifier::diagnoseUnfulfilledObligations(
576596
case Expectation::Kind::DynamicMember:
577597
case Expectation::Kind::PotentialMember:
578598
diags.diagnose(Loc, diag::unexpected_dependency, p.describeCascade(),
579-
static_cast<uint8_t>(p.getKind()), key);
599+
static_cast<uint8_t>(p.getKind()), key)
600+
.fixItInsert(Loc, p.renderAsFixit(Ctx));
580601
break;
581602
case Expectation::Kind::Provides:
582-
diags.diagnose(Loc, diag::unexpected_provided_entity, p.getName());
603+
diags.diagnose(Loc, diag::unexpected_provided_entity, p.getName())
604+
.fixItInsert(Loc, p.renderAsFixit(Ctx));
583605
break;
584606
}
585607
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// REQUIRES: OS=windows-msvc
2+
// This test is special-cased on Windows because dependencies in Two.swift don't
3+
// appear to be registered against the tracker. rdar://60030114
4+
5+
// RUN: %empty-directory(%t)
6+
// RUN: %{python} %S/../gen-output-file-map.py -o %t %S/Inputs -r %t.resp
7+
// RUN: cd %t
8+
// RUN: not %target-swiftc_driver -no-color-diagnostics -typecheck -output-file-map %t/output.json -incremental -module-name main -verify-incremental-dependencies @%t.resp 2>&1 | sort | %FileCheck %s
9+
10+
// CHECK: unexpected cascading member dependency: main.Base.init
11+
// CHECK: unexpected cascading potential member dependency: main.Base
12+
// CHECK: unexpected provided entity: Base
13+
// CHECK: unexpected provided entity: BaseProtocol

test/Incremental/fail/main.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
// REQUIRES: rdar60030114
1+
// UNSUPPORTED: OS=windows-msvc
2+
// See its counterpart main-windows.swift
23

34
// RUN: %empty-directory(%t)
45
// RUN: %{python} %S/../gen-output-file-map.py -o %t %S/Inputs -r %t.resp
56
// RUN: cd %t
67
// RUN: not %target-swiftc_driver -no-color-diagnostics -typecheck -output-file-map %t/output.json -incremental -module-name main -verify-incremental-dependencies @%t.resp 2>&1 | sort | %FileCheck %s
78

89
// CHECK: unexpected dependency exists: main.BaseProtocol
9-
// CHECK: unexpected cascading dependency: main.Base.init
10-
// CHECK: unexpected cascading dependency: main.Subclass.deinit
11-
// CHECK: unexpected cascading dependency: main.Subclass.init
10+
// CHECK: unexpected cascading member dependency: main.Base.init
11+
// CHECK: unexpected cascading member dependency: main.Subclass.deinit
12+
// CHECK: unexpected cascading member dependency: main.Subclass.init
1213
// CHECK: unexpected cascading potential member dependency: main.Base
1314
// CHECK: unexpected provided entity: Base
1415
// CHECK: unexpected provided entity: BaseProtocol

test/Incremental/gen-output-file-map.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ def main(arguments):
6161
'swift-dependencies': './main-buildrecord.swiftdeps'
6262
}
6363

64-
with open(output_path, 'w') as f:
64+
with open(output_path, 'wb') as f:
6565
json.dump(all_records, f)
6666

6767
if args.response_output_file is not None:
68-
with open(args.response_output_file, 'w') as f:
68+
with open(args.response_output_file, 'wb') as f:
6969
for line in response_file_contents:
7070
f.write(line + " ")
7171

0 commit comments

Comments
 (0)