Skip to content

Commit f952d2e

Browse files
committed
Provide fix-its when overriding something that's been renamed.
This is the second half of the previous commit. The most common case of this will be due to the new rules for imported Objective-C API, but it will also catch things like "I forgot to make the first parameter not have an argument label".
1 parent e67fe08 commit f952d2e

File tree

3 files changed

+130
-13
lines changed

3 files changed

+130
-13
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,7 +1234,7 @@ namespace {
12341234
}
12351235

12361236
static Optional<ReplacementDeclKind>
1237-
describeRename(ASTContext &ctx, const AvailableAttr *attr,
1237+
describeRename(ASTContext &ctx, const AvailableAttr *attr, const ValueDecl *D,
12381238
SmallVectorImpl<char> &nameBuf) {
12391239
ParsedDeclName parsed = swift::parseDeclName(attr->Rename);
12401240
if (!parsed)
@@ -1244,12 +1244,13 @@ describeRename(ASTContext &ctx, const AvailableAttr *attr,
12441244
// - instance members
12451245
// - properties (or global bindings)
12461246
// - class/static methods
1247-
// - initializers, even if unqualified
1247+
// - initializers, unless the original was known to be an initializer
12481248
// Leave non-member renames alone, as well as renames from top-level types
12491249
// and bindings to member types and class/static properties.
12501250
if (!(parsed.isInstanceMember() || parsed.isPropertyAccessor() ||
12511251
(parsed.isMember() && parsed.IsFunctionName) ||
1252-
(parsed.BaseName == ctx.Id_init.str()))) {
1252+
(parsed.BaseName == ctx.Id_init.str() &&
1253+
!dyn_cast_or_null<ConstructorDecl>(D)))) {
12531254
return None;
12541255
}
12551256

@@ -1318,7 +1319,7 @@ void TypeChecker::diagnoseDeprecated(SourceRange ReferenceRange,
13181319

13191320
SmallString<32> newNameBuf;
13201321
Optional<ReplacementDeclKind> replacementDeclKind =
1321-
describeRename(Context, Attr, newNameBuf);
1322+
describeRename(Context, Attr, /*decl*/nullptr, newNameBuf);
13221323
StringRef newName = replacementDeclKind ? newNameBuf.str() : Attr->Rename;
13231324

13241325
if (!Attr->Message.empty()) {
@@ -1391,7 +1392,7 @@ bool TypeChecker::diagnoseExplicitUnavailability(
13911392
if (!Attr->Rename.empty()) {
13921393
SmallString<32> newNameBuf;
13931394
Optional<ReplacementDeclKind> replaceKind =
1394-
describeRename(Context, Attr, newNameBuf);
1395+
describeRename(Context, Attr, D, newNameBuf);
13951396
unsigned rawReplaceKind = static_cast<unsigned>(
13961397
replaceKind.getValueOr(ReplacementDeclKind::None));
13971398
StringRef newName = replaceKind ? newNameBuf.str() : Attr->Rename;

lib/Sema/TypeCheckDecl.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "swift/AST/ReferencedNameTracker.h"
3232
#include "swift/AST/TypeWalker.h"
3333
#include "swift/Parse/Lexer.h"
34+
#include "swift/Parse/Parser.h"
3435
#include "swift/Sema/IterativeTypeChecker.h"
3536
#include "swift/Serialization/SerializedModuleLoader.h"
3637
#include "swift/Strings.h"
@@ -5479,7 +5480,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
54795480
}
54805481

54815482
static void diagnoseUnavailableOverride(TypeChecker &TC,
5482-
const ValueDecl *override,
5483+
ValueDecl *override,
54835484
const ValueDecl *base,
54845485
const AvailableAttr *attr) {
54855486
if (attr->Rename.empty()) {
@@ -5495,8 +5496,30 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
54955496

54965497
TC.diagnoseExplicitUnavailability(base, override->getLoc(),
54975498
override->getDeclContext(),
5498-
[](InFlightDiagnostic &diag) {
5499-
// FIXME: Apply fix-its here.
5499+
[&](InFlightDiagnostic &diag) {
5500+
ParsedDeclName parsedName = parseDeclName(attr->Rename);
5501+
if (!parsedName || parsedName.isPropertyAccessor() ||
5502+
parsedName.isMember() || parsedName.isOperator()) {
5503+
return;
5504+
}
5505+
5506+
// Only initializers should be named 'init'.
5507+
if (isa<ConstructorDecl>(override) ^
5508+
(parsedName.BaseName == TC.Context.Id_init.str())) {
5509+
return;
5510+
}
5511+
5512+
if (!parsedName.IsFunctionName) {
5513+
diag.fixItReplace(override->getNameLoc(), parsedName.BaseName);
5514+
return;
5515+
}
5516+
5517+
DeclName newName = parsedName.formDeclName(TC.Context);
5518+
size_t numArgs = override->getFullName().getArgumentNames().size();
5519+
if (!newName || newName.getArgumentNames().size() != numArgs)
5520+
return;
5521+
5522+
fixDeclarationName(diag, override, newName);
55005523
});
55015524
}
55025525

test/attr/attr_availability.swift

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -500,20 +500,113 @@ func testFactoryMethods() {
500500
class Base {
501501
@available(*, unavailable)
502502
func bad() {} // expected-note {{here}}
503-
504503
@available(*, unavailable, message: "it was smelly")
505504
func smelly() {} // expected-note {{here}}
506-
507505
@available(*, unavailable, renamed: "new")
508506
func old() {} // expected-note {{here}}
509-
510507
@available(*, unavailable, renamed: "new", message: "it was smelly")
511508
func oldAndSmelly() {} // expected-note {{here}}
509+
510+
@available(*, unavailable)
511+
var badProp: Int { return 0 } // expected-note {{here}}
512+
@available(*, unavailable, message: "it was smelly")
513+
var smellyProp: Int { return 0 } // expected-note {{here}}
514+
@available(*, unavailable, renamed: "new")
515+
var oldProp: Int { return 0 } // expected-note {{here}}
516+
@available(*, unavailable, renamed: "new", message: "it was smelly")
517+
var oldAndSmellyProp: Int { return 0 } // expected-note {{here}}
518+
519+
@available(*, unavailable, renamed: "init")
520+
func nowAnInitializer() {} // expected-note {{here}}
521+
@available(*, unavailable, renamed: "init()")
522+
func nowAnInitializer2() {} // expected-note {{here}}
523+
524+
@available(*, unavailable, renamed: "foo")
525+
init(nowAFunction: Int) {} // expected-note {{here}}
526+
@available(*, unavailable, renamed: "foo(_:)")
527+
init(nowAFunction2: Int) {} // expected-note {{here}}
528+
529+
@available(*, unavailable, renamed: "shinyLabeledArguments(example:)")
530+
func unavailableArgNames(a: Int) {} // expected-note {{here}}
531+
@available(*, unavailable, renamed: "shinyLabeledArguments(example:)")
532+
func unavailableArgRenamed(a: Int) {} // expected-note {{here}}
533+
@available(*, unavailable, renamed: "shinyLabeledArguments()")
534+
func unavailableNoArgs() {} // expected-note {{here}}
535+
@available(*, unavailable, renamed: "shinyLabeledArguments(a:)")
536+
func unavailableSame(a: Int) {} // expected-note {{here}}
537+
@available(*, unavailable, renamed: "shinyLabeledArguments(example:)")
538+
func unavailableUnnamed(_ a: Int) {} // expected-note {{here}}
539+
@available(*, unavailable, renamed: "shinyLabeledArguments(_:)")
540+
func unavailableUnnamedSame(_ a: Int) {} // expected-note {{here}}
541+
@available(*, unavailable, renamed: "shinyLabeledArguments(_:)")
542+
func unavailableNewlyUnnamed(a: Int) {} // expected-note {{here}}
543+
@available(*, unavailable, renamed: "shinyLabeledArguments(a:b:)")
544+
func unavailableMultiSame(a: Int, b: Int) {} // expected-note {{here}}
545+
@available(*, unavailable, renamed: "shinyLabeledArguments(example:another:)")
546+
func unavailableMultiUnnamed(_ a: Int, _ b: Int) {} // expected-note {{here}}
547+
@available(*, unavailable, renamed: "shinyLabeledArguments(_:_:)")
548+
func unavailableMultiUnnamedSame(_ a: Int, _ b: Int) {} // expected-note {{here}}
549+
@available(*, unavailable, renamed: "shinyLabeledArguments(_:_:)")
550+
func unavailableMultiNewlyUnnamed(a: Int, b: Int) {} // expected-note {{here}}
551+
552+
@available(*, unavailable, renamed: "init(shinyNewName:)")
553+
init(unavailableArgNames: Int) {} // expected-note{{here}}
554+
@available(*, unavailable, renamed: "init(a:)")
555+
init(_ unavailableUnnamed: Int) {} // expected-note{{here}}
556+
@available(*, unavailable, renamed: "init(_:)")
557+
init(unavailableNewlyUnnamed: Int) {} // expected-note{{here}}
558+
@available(*, unavailable, renamed: "init(a:b:)")
559+
init(_ unavailableMultiUnnamed: Int, _ b: Int) {} // expected-note{{here}}
560+
@available(*, unavailable, renamed: "init(_:_:)")
561+
init(unavailableMultiNewlyUnnamed a: Int, b: Int) {} // expected-note{{here}}
562+
563+
@available(*, unavailable, renamed: "shinyLabeledArguments(x:)")
564+
func unavailableTooFew(a: Int, b: Int) {} // expected-note {{here}}
565+
@available(*, unavailable, renamed: "shinyLabeledArguments(x:b:)")
566+
func unavailableTooMany(a: Int) {} // expected-note {{here}}
567+
@available(*, unavailable, renamed: "shinyLabeledArguments(x:)")
568+
func unavailableNoArgsTooMany() {} // expected-note {{here}}
569+
570+
@available(*, unavailable, renamed: "Base.shinyLabeledArguments()")
571+
func unavailableHasType() {} // expected-note {{here}}
512572
}
513573

514574
class Sub : Base {
515575
override func bad() {} // expected-error {{cannot override 'bad' which has been marked unavailable}} {{none}}
516576
override func smelly() {} // expected-error {{cannot override 'smelly' which has been marked unavailable: it was smelly}} {{none}}
517-
override func old() {} // expected-error {{'old()' has been renamed to 'new'}} {{none}}
518-
override func oldAndSmelly() {} // expected-error {{'oldAndSmelly()' has been renamed to 'new': it was smelly}} {{none}}
577+
override func old() {} // expected-error {{'old()' has been renamed to 'new'}} {{17-20=new}}
578+
override func oldAndSmelly() {} // expected-error {{'oldAndSmelly()' has been renamed to 'new': it was smelly}} {{17-29=new}}
579+
580+
override var badProp: Int { return 0 } // expected-error {{cannot override 'badProp' which has been marked unavailable}} {{none}}
581+
override var smellyProp: Int { return 0 } // expected-error {{cannot override 'smellyProp' which has been marked unavailable: it was smelly}} {{none}}
582+
override var oldProp: Int { return 0 } // expected-error {{'oldProp' has been renamed to 'new'}} {{16-23=new}}
583+
override var oldAndSmellyProp: Int { return 0 } // expected-error {{'oldAndSmellyProp' has been renamed to 'new': it was smelly}} {{16-32=new}}
584+
585+
override func nowAnInitializer() {} // expected-error {{'nowAnInitializer()' has been replaced by 'init'}} {{none}}
586+
override func nowAnInitializer2() {} // expected-error {{'nowAnInitializer2()' has been replaced by 'init()'}} {{none}}
587+
override init(nowAFunction: Int) {} // expected-error {{'init(nowAFunction:)' has been renamed to 'foo'}} {{none}}
588+
override init(nowAFunction2: Int) {} // expected-error {{'init(nowAFunction2:)' has been renamed to 'foo(_:)'}} {{none}}
589+
590+
override func unavailableArgNames(a: Int) {} // expected-error {{'unavailableArgNames(a:)' has been renamed to 'shinyLabeledArguments(example:)'}} {{17-36=shinyLabeledArguments}} {{37-37=example }}
591+
override func unavailableArgRenamed(a param: Int) {} // expected-error {{'unavailableArgRenamed(a:)' has been renamed to 'shinyLabeledArguments(example:)'}} {{17-38=shinyLabeledArguments}} {{39-40=example}}
592+
override func unavailableNoArgs() {} // expected-error {{'unavailableNoArgs()' has been renamed to 'shinyLabeledArguments()'}} {{17-34=shinyLabeledArguments}}
593+
override func unavailableSame(a: Int) {} // expected-error {{'unavailableSame(a:)' has been renamed to 'shinyLabeledArguments(a:)'}} {{17-32=shinyLabeledArguments}}
594+
override func unavailableUnnamed(_ a: Int) {} // expected-error {{'unavailableUnnamed' has been renamed to 'shinyLabeledArguments(example:)'}} {{17-35=shinyLabeledArguments}} {{36-37=example}}
595+
override func unavailableUnnamedSame(_ a: Int) {} // expected-error {{'unavailableUnnamedSame' has been renamed to 'shinyLabeledArguments(_:)'}} {{17-39=shinyLabeledArguments}}
596+
override func unavailableNewlyUnnamed(a: Int) {} // expected-error {{'unavailableNewlyUnnamed(a:)' has been renamed to 'shinyLabeledArguments(_:)'}} {{17-40=shinyLabeledArguments}} {{41-41=_ }}
597+
override func unavailableMultiSame(a: Int, b: Int) {} // expected-error {{'unavailableMultiSame(a:b:)' has been renamed to 'shinyLabeledArguments(a:b:)'}} {{17-37=shinyLabeledArguments}}
598+
override func unavailableMultiUnnamed(_ a: Int, _ b: Int) {} // expected-error {{'unavailableMultiUnnamed' has been renamed to 'shinyLabeledArguments(example:another:)'}} {{17-40=shinyLabeledArguments}} {{41-42=example}} {{51-52=another}}
599+
override func unavailableMultiUnnamedSame(_ a: Int, _ b: Int) {} // expected-error {{'unavailableMultiUnnamedSame' has been renamed to 'shinyLabeledArguments(_:_:)'}} {{17-44=shinyLabeledArguments}}
600+
override func unavailableMultiNewlyUnnamed(a: Int, b: Int) {} // expected-error {{'unavailableMultiNewlyUnnamed(a:b:)' has been renamed to 'shinyLabeledArguments(_:_:)'}} {{17-45=shinyLabeledArguments}} {{46-46=_ }} {{54-54=_ }}
601+
602+
override init(unavailableArgNames: Int) {} // expected-error {{'init(unavailableArgNames:)' has been renamed to 'init(shinyNewName:)'}} {{17-17=shinyNewName }}
603+
override init(_ unavailableUnnamed: Int) {} // expected-error {{'init' has been renamed to 'init(a:)'}} {{17-18=a}}
604+
override init(unavailableNewlyUnnamed: Int) {} // expected-error {{'init(unavailableNewlyUnnamed:)' has been renamed to 'init(_:)'}} {{17-17=_ }}
605+
override init(_ unavailableMultiUnnamed: Int, _ b: Int) {} // expected-error {{'init' has been renamed to 'init(a:b:)'}} {{17-18=a}} {{49-51=}}
606+
override init(unavailableMultiNewlyUnnamed a: Int, b: Int) {} // expected-error {{'init(unavailableMultiNewlyUnnamed:b:)' has been renamed to 'init(_:_:)'}} {{17-45=_}} {{54-54=_ }}
607+
608+
override func unavailableTooFew(a: Int, b: Int) {} // expected-error {{'unavailableTooFew(a:b:)' has been renamed to 'shinyLabeledArguments(x:)'}} {{none}}
609+
override func unavailableTooMany(a: Int) {} // expected-error {{'unavailableTooMany(a:)' has been renamed to 'shinyLabeledArguments(x:b:)'}} {{none}}
610+
override func unavailableNoArgsTooMany() {} // expected-error {{'unavailableNoArgsTooMany()' has been renamed to 'shinyLabeledArguments(x:)'}} {{none}}
611+
override func unavailableHasType() {} // expected-error {{'unavailableHasType()' has been replaced by 'Base.shinyLabeledArguments()'}} {{none}}
519612
}

0 commit comments

Comments
 (0)