Skip to content

Commit 2792c31

Browse files
committed
[Sema] FixIt for override func that should be override var and vice-versa
Resolves swiftlang#57499 This adds `override_property_not_method` and `override_method_not_property` notes by performing a member lookup for the respective diagnostics.
1 parent a92f379 commit 2792c31

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3458,8 +3458,12 @@ ERROR(override_of_non_open,none,
34583458

34593459
ERROR(method_does_not_override,none,
34603460
"method does not override any method from its %select{parent protocol|superclass}0", (bool))
3461+
NOTE(override_property_not_method,none,
3462+
"did you mean to override the property %0", (Identifier))
34613463
ERROR(property_does_not_override,none,
34623464
"property does not override any property from its %select{parent protocol|superclass}0", (bool))
3465+
NOTE(override_method_not_property,none,
3466+
"did you mean to override the method %0", (Identifier))
34633467
ERROR(subscript_does_not_override,none,
34643468
"subscript does not override any subscript from its %select{parent protocol|superclass}0", (bool))
34653469
ERROR(initializer_does_not_override,none,

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2671,6 +2671,30 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
26712671
} else {
26722672
VD->diagnose(diag::property_does_not_override, isClassContext)
26732673
.highlight(OA->getLocation());
2674+
2675+
auto declName = VD->getBaseName();
2676+
auto declType = VD->getInterfaceType()->getRValueType();
2677+
2678+
auto inherited = DC->getSelfClassDecl()->getInherited();
2679+
if (!inherited.empty()) {
2680+
auto superClassType = inherited.getResolvedType(0);
2681+
auto lookupResult = TypeChecker::lookupMember(DC, superClassType,
2682+
DeclNameRef(declName));
2683+
for (auto &candidate : lookupResult) {
2684+
auto *valueDecl = candidate.getValueDecl();
2685+
if (auto funcDecl = dyn_cast<FuncDecl>(valueDecl)) {
2686+
if (funcDecl->getBaseName() == declName &&
2687+
funcDecl->getParameters()->size() == 0) {
2688+
std::string funcDeclTypeStr = " -> " +
2689+
declType.getString();
2690+
VD->diagnose(diag::override_method_not_property,
2691+
funcDecl->getBaseName().getIdentifier())
2692+
.highlight(OA->getLocation())
2693+
.fixItReplace(getFixItLocForVarToLet(VD), "func");
2694+
}
2695+
}
2696+
}
2697+
}
26742698
}
26752699
OA->setInvalid();
26762700
}
@@ -3717,6 +3741,34 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
37173741
} else {
37183742
FD->diagnose(diag::method_does_not_override, isClassContext)
37193743
.highlight(OA->getLocation());
3744+
3745+
if (FD->getParameters()->size() == 0) {
3746+
auto declName = FD->getBaseName();
3747+
auto declRetType = FD->getResultInterfaceType()->getRValueType();
3748+
3749+
auto inherited = DC->getSelfClassDecl()->getInherited();
3750+
if (!inherited.empty()) {
3751+
auto superClassType = inherited.getResolvedType(0);
3752+
auto lookupResult = TypeChecker::lookupMember(DC,
3753+
superClassType,
3754+
DeclNameRef(declName));
3755+
for (auto &candidate : lookupResult) {
3756+
auto *valueDecl = candidate.getValueDecl();
3757+
if (auto vardecl = dyn_cast<VarDecl>(valueDecl)) {
3758+
if (vardecl->getBaseName() == declName) {
3759+
std::string varDeclTypeStr = ": " + declRetType.getString();
3760+
FD->diagnose(diag::override_property_not_method,
3761+
vardecl->getBaseName().getIdentifier())
3762+
.highlight(OA->getLocation())
3763+
.fixItReplace(FD->getFuncLoc(), "var")
3764+
.fixItReplaceChars(FD->getParameters()->getLParenLoc(),
3765+
FD->getBody()->getLBraceLoc().getAdvancedLoc(-1),
3766+
varDeclTypeStr);
3767+
}
3768+
}
3769+
}
3770+
}
3771+
}
37203772
}
37213773
OA->setInvalid();
37223774
}

test/decl/inherit/override.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,20 @@ class ObjCSub : ObjCSuper {
8686

8787
@objc(method3:withInt:) func method3(_ x: Sub, with y: Int) { } // expected-error{{method3(_:with:)' with Objective-C selector 'method3:withInt:' conflicts with method 'method3(_:withInt:)' from superclass 'ObjCSuper' with the same Objective-C selector}}
8888
}
89+
90+
class C {
91+
var v1: Bool {
92+
return false
93+
}
94+
95+
func f1() -> Int { }
96+
}
97+
98+
class D: C {
99+
override func v1() -> Bool { } // expected-error{{method does not override any method from its superclass}}
100+
// expected-note@-1{{did you mean to override the property 'v1'}} {{12-16=var}} {{19-29=: Bool}}
101+
102+
override var f1: Int { // expected-error{{property does not override any property from its superclass}}
103+
return 0 // expected-note@-1{{did you mean to override the method 'f1'}} {{12-15=func}}
104+
}
105+
}

0 commit comments

Comments
 (0)