From 1a224c925c1a1630b51711b13c6b2825381cb4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crazy=E5=87=A1?= Date: Sat, 23 Mar 2024 04:27:47 +0800 Subject: [PATCH] Modify diagnostics to suggest updating existing available attribute --- include/swift/AST/DiagnosticsSema.def | 3 +++ lib/Sema/TypeCheckAvailability.cpp | 22 ++++++++++++---- test/Sema/api-availability-only.swift | 1 + test/Sema/availability_define.swift | 2 ++ test/Sema/availability_swiftui.swift | 1 + test/Sema/availability_versions.swift | 28 ++++++++++++++++----- test/Sema/availability_versions_multi.swift | 6 ++++- 7 files changed, 51 insertions(+), 12 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 3b94f33ba8039..ca2fc199012cc 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -6649,6 +6649,9 @@ ERROR(availability_variadic_type_only_version_newer, none, NOTE(availability_guard_with_version_check, none, "add 'if #available' version check", ()) +NOTE(update_availability_attribute, none, + "change the @available attribute of the %0 on %1 from %2 to %3", (DescriptiveDeclKind, StringRef, StringRef, StringRef)) + NOTE(availability_add_attribute, none, "add @available attribute to enclosing %0", (DescriptiveDeclKind)) FIXIT(insert_available_attr, diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 836f655a0ca07..a1ed7f2f41ee5 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -1821,11 +1821,6 @@ static void fixAvailabilityForDecl(SourceRange ReferenceRange, const Decl *D, if (TypeChecker::diagnosticIfDeclCannotBePotentiallyUnavailable(D).has_value()) return; - if (getActiveAvailableAttribute(D, Context)) { - // For QoI, in future should emit a fixit to update the existing attribute. - return; - } - // For some declarations (variables, enum elements), the location in concrete // syntax to suggest the Fix-It may differ from the declaration to which // we attach availability attributes in the abstract syntax tree during @@ -1833,6 +1828,23 @@ static void fixAvailabilityForDecl(SourceRange ReferenceRange, const Decl *D, const Decl *ConcDecl = concreteSyntaxDeclForAvailableAttribute(D); DescriptiveDeclKind KindForDiagnostic = ConcDecl->getDescriptiveKind(); + + if (auto Attr = getActiveAvailableAttribute(D, Context)) { + if (Attr->isUnconditionallyUnavailable()) { + return; + } + SourceManager &SM = Context.SourceMgr; + auto Version = SM.extractText(Lexer::getCharSourceRangeFromSourceRange( + SM, Attr->IntroducedRange)) + .str(); + auto Required = RequiredRange.getLowerEndpoint().getAsString(); + Context.Diags + .diagnose(ReferenceRange.Start, diag::update_availability_attribute, + KindForDiagnostic, Attr->platformString(), Version, Required) + .fixItReplace(Attr->IntroducedRange, Required); + return; + } + SourceLoc InsertLoc; // To avoid exposing the pattern binding declaration to the user, get the diff --git a/test/Sema/api-availability-only.swift b/test/Sema/api-availability-only.swift index 0f1a087a4a2fe..89396d1642e9c 100644 --- a/test/Sema/api-availability-only.swift +++ b/test/Sema/api-availability-only.swift @@ -10,4 +10,5 @@ public struct S {} public func newFunc() { _ = S() // expected-error {{'S' is only available in}} // expected-note @-1 {{add 'if #available' version check}} + // expected-note @-2 {{change the @available attribute of the global function on macOS from 10.51 to 10.52}} {{9:18-23=10.52}} } diff --git a/test/Sema/availability_define.swift b/test/Sema/availability_define.swift index cdb3f9f26a740..aed4498698943 100644 --- a/test/Sema/availability_define.swift +++ b/test/Sema/availability_define.swift @@ -59,6 +59,7 @@ func client() { onMacOS10_15() onMacOS11_0() // expected-error {{is only available in macOS 11.0 or newer}} // expected-note @-1 {{add 'if #available' version check}} + // expected-note @-2 {{change the @available attribute of the global function on macOS from 10.15 to 11.0}} onMacOSDeprecated() if #available(_iOS14Aligned, *) { @@ -68,6 +69,7 @@ func client() { if #unavailable(_iOS14Aligned) { onMacOS11_0() // expected-error {{is only available in macOS 11.0 or newer}} // expected-note @-1 {{add 'if #available' version check}} + // expected-note @-2 {{change the @available attribute of the global function on macOS from 10.15 to 11.0}} } else { onMacOS11_0() } diff --git a/test/Sema/availability_swiftui.swift b/test/Sema/availability_swiftui.swift index 752ec87cf2fe0..bbe180f2f786e 100644 --- a/test/Sema/availability_swiftui.swift +++ b/test/Sema/availability_swiftui.swift @@ -13,3 +13,4 @@ class AnyColorBox: LessAvailable {} // Ok, exception specifically for AnyColorBo @available(macOS 10.15, *) @usableFromInline class OtherClass: LessAvailable {} // expected-error {{'LessAvailable' is only available in macOS 11 or newer; clients of 'SwiftUI' may have a lower deployment target}} +// expected-note @-1 {{change the @available attribute of the class on macOS from 10.15 to 11}} {{13:18-23=11}} diff --git a/test/Sema/availability_versions.swift b/test/Sema/availability_versions.swift index 79cbbad4a4cf4..b8b62e368103c 100644 --- a/test/Sema/availability_versions.swift +++ b/test/Sema/availability_versions.swift @@ -55,6 +55,7 @@ func functionAvailableOn10_51() { let _: Int = globalFuncAvailableOn10_52() // expected-error {{'globalFuncAvailableOn10_52()' is only available in macOS 10.52 or newer}} // expected-note@-1 {{add 'if #available' version check}} + // expected-note@-2 {{change the @available attribute of the global function on macOS from 10.51 to 10.52}} {{43:29-34=10.52}} } // Still allow other availability annotations on script-mode globals @@ -327,7 +328,8 @@ class ClassWithPotentiallyUnavailableProperties { get { let _: Int = availableOn10_51Stored // expected-error {{'availableOn10_51Stored' is only available in macOS 10.51 or newer}} // expected-note@-1 {{add 'if #available' version check}} - + // expected-note@-2 {{change the @available attribute of the pattern binding on macOS from 10.9 to 10.51}} {{326:31-35=10.51}} + if #available(OSX 10.51, *) { let _: Int = availableOn10_51Stored } @@ -409,10 +411,12 @@ class ClassWithReferencesInInitializers { var propWithInitializer10_51: Int = globalFuncAvailableOn10_51() var propWithInitializer10_52: Int = globalFuncAvailableOn10_52() // expected-error {{'globalFuncAvailableOn10_52()' is only available in macOS 10.52 or newer}} + // expected-note@-1 {{change the @available attribute of the class on macOS from 10.51 to 10.52}} {{409:29-34=10.52}} lazy var lazyPropWithInitializer10_51: Int = globalFuncAvailableOn10_51() lazy var lazyPropWithInitializer10_52: Int = globalFuncAvailableOn10_52() // expected-error {{'globalFuncAvailableOn10_52()' is only available in macOS 10.52 or newer}} + // expected-note@-1 {{change the @available attribute of the class on macOS from 10.51 to 10.52}} {{409:29-34=10.52}} } func accessPotentiallyUnavailableProperties(_ o: ClassWithPotentiallyUnavailableProperties) { @@ -522,6 +526,7 @@ enum EnumIntroducedOn10_52 { @available(OSX, introduced: 10.51) enum CompassPoint { + case North case South case East @@ -540,9 +545,11 @@ enum CompassPoint { case WithAvailableByEnumElementPayload1(p : EnumIntroducedOn10_52), WithAvailableByEnumElementPayload2(p : EnumIntroducedOn10_52) case WithPotentiallyUnavailablePayload(p : EnumIntroducedOn10_52) // expected-error {{'EnumIntroducedOn10_52' is only available in macOS 10.52 or newer}} + // expected-note@-1 {{change the @available attribute of the enum on macOS from 10.51 to 10.52}} {{527:29-34=10.52}} case WithPotentiallyUnavailablePayload1(p : EnumIntroducedOn10_52), WithPotentiallyUnavailablePayload2(p : EnumIntroducedOn10_52) // expected-error 2{{'EnumIntroducedOn10_52' is only available in macOS 10.52 or newer}} - + // expected-note@-1 2{{change the @available attribute of the enum on macOS from 10.51 to 10.52}} {{527:29-34=10.52}} + @available(OSX, unavailable) case WithPotentiallyUnavailablePayload3(p : EnumIntroducedOn10_52) } @@ -878,7 +885,8 @@ class SubWithLargerMemberAvailability : SuperWithLimitedMemberAvailability { override func someMethod() { super.someMethod() // expected-error {{'someMethod()' is only available in macOS 10.51 or newer}} // expected-note@-1 {{add 'if #available' version check}} - + // expected-note@-2 {{change the @available attribute of the instance method on macOS from 10.9 to 10.51}} {{884:31-35=10.51}} + if #available(OSX 10.51, *) { super.someMethod() } @@ -886,10 +894,11 @@ class SubWithLargerMemberAvailability : SuperWithLimitedMemberAvailability { @available(OSX, introduced: 10.9) override var someProperty: Int { - get { + get { let _ = super.someProperty // expected-error {{'someProperty' is only available in macOS 10.51 or newer}} - // expected-note@-1 {{add 'if #available' version check}} - + // expected-note@-1 {{add 'if #available' version check}} + // expected-note@-2 {{change the @available attribute of the pattern binding on macOS from 10.9 to 10.51}} {{895:31-35=10.51}} + if #available(OSX 10.51, *) { let _ = super.someProperty } @@ -961,6 +970,7 @@ protocol ProtocolAvailableOn10_51 { @available(OSX, introduced: 10.9) protocol ProtocolAvailableOn10_9InheritingFromProtocolAvailableOn10_51 : ProtocolAvailableOn10_51 { // expected-error {{'ProtocolAvailableOn10_51' is only available in macOS 10.51 or newer}} + // expected-note@-1 {{change the @available attribute of the protocol on macOS from 10.9 to 10.51}} {{971:29-33=10.51}} } @available(OSX, introduced: 10.51) @@ -973,6 +983,7 @@ protocol UnavailableProtocolInheritingFromProtocolAvailableOn10_51 : ProtocolAva @available(OSX, introduced: 10.9) class SubclassAvailableOn10_9OfClassAvailableOn10_51 : ClassAvailableOn10_51 { // expected-error {{'ClassAvailableOn10_51' is only available in macOS 10.51 or newer}} + // expected-note@-1 {{change the @available attribute of the class on macOS from 10.9 to 10.51}} {{984:29-33=10.51}} } @available(OSX, unavailable) @@ -997,12 +1008,14 @@ func castToPotentiallyUnavailableProtocol() { @available(OSX, introduced: 10.9) class SubclassAvailableOn10_9OfClassAvailableOn10_51AlsoAdoptingProtocolAvailableOn10_51 : ClassAvailableOn10_51, ProtocolAvailableOn10_51 { // expected-error {{'ClassAvailableOn10_51' is only available in macOS 10.51 or newer}} + // expected-note@-1 {{change the @available attribute of the class on macOS from 10.9 to 10.51}} {{1009:29-33=10.51}} } class SomeGenericClass { } @available(OSX, introduced: 10.9) class SubclassAvailableOn10_9OfSomeGenericClassOfProtocolAvailableOn10_51 : SomeGenericClass { // expected-error {{'ProtocolAvailableOn10_51' is only available in macOS 10.51 or newer}} + // expected-note@-1 {{change the @available attribute of the class on macOS from 10.9 to 10.51}} {{1016:29-33=10.51}} } @available(OSX, unavailable) @@ -1054,6 +1067,7 @@ extension ClassAvailableOn10_51 { let _ = globalFuncAvailableOn10_51() let _ = globalFuncAvailableOn10_52() // expected-error {{'globalFuncAvailableOn10_52()' is only available in macOS 10.52 or newer}} // expected-note@-1 {{add 'if #available' version check}} + // expected-note@-2 {{change the @available attribute of the extension on macOS from 10.51 to 10.52}} {{1063:29-34=10.52}} } } @@ -1655,6 +1669,7 @@ class ClassWithShortFormAvailableOn10_54 { func funcWithShortFormAvailableOn10_9() { let _ = ClassWithShortFormAvailableOn10_51() // expected-error {{'ClassWithShortFormAvailableOn10_51' is only available in macOS 10.51 or newer}} // expected-note@-1 {{add 'if #available' version check}} + // expected-note@-2 {{change the @available attribute of the global function on macOS from 10.9 to 10.51}} {{1668:16-20=10.51}} } @available(OSX 10.51, *) @@ -1689,6 +1704,7 @@ func funcWithMultipleShortFormAnnotationsForTheSamePlatform() { let _ = ClassWithShortFormAvailableOn10_54() // expected-error {{'ClassWithShortFormAvailableOn10_54' is only available in macOS 10.54 or newer}} // expected-note@-1 {{add 'if #available' version check}} + // expected-note@-2 {{change the @available attribute of the global function on macOS from 10.52 to 10.54}} {{1701:16-21=10.54}} } func useShortFormAvailable() { diff --git a/test/Sema/availability_versions_multi.swift b/test/Sema/availability_versions_multi.swift index 89e61cbb7528b..f30172d263483 100644 --- a/test/Sema/availability_versions_multi.swift +++ b/test/Sema/availability_versions_multi.swift @@ -34,17 +34,21 @@ func useFromOtherOn99_51() { o10_9.extensionMethodOnOtherIntroduced10_9AvailableOn99_51(o99_51) _ = o99_51.returns99_52Introduced99_52() // expected-error {{'returns99_52Introduced99_52()' is only available in macOS 99.52 or newer}} // expected-note@-1 {{add 'if #available' version check}} + // expected-note@-2 {{change the @available attribute of the global function on macOS from 99.51 to 99.52}} {{26:29-34=99.52}} _ = OtherIntroduced99_52() // expected-error@-1 {{'OtherIntroduced99_52' is only available in macOS 99.52 or newer}} // expected-note@-2 {{add 'if #available' version check}} + // expected-note@-3 {{change the @available attribute of the global function on macOS from 99.51 to 99.52}} {{26:29-34=99.52}} o99_51.extensionMethodOnOtherIntroduced99_51AvailableOn99_52() // expected-error {{'extensionMethodOnOtherIntroduced99_51AvailableOn99_52()' is only available in macOS 99.52 or newer}} // expected-note@-1 {{add 'if #available' version check}} + // expected-note@-2 {{change the @available attribute of the global function on macOS from 99.51 to 99.52}} {{26:29-34=99.52}} _ = OtherIntroduced99_51.NestedIntroduced99_52() // expected-error@-1 {{'NestedIntroduced99_52' is only available in macOS 99.52 or newer}} // expected-note@-2 {{add 'if #available' version check}} + // expected-note@-3 {{change the @available attribute of the global function on macOS from 99.51 to 99.52}} {{26:29-34=99.52}} } @available(OSX, introduced: 99.52) @@ -55,7 +59,7 @@ func useFromOtherOn99_52() { _ = n99_52.returns99_52() _ = n99_52.returns99_53() // expected-error {{'returns99_53()' is only available in macOS 99.53 or newer}} // expected-note@-1 {{add 'if #available' version check}} - + // expected-note@-2 {{change the @available attribute of the global function on macOS from 99.52 to 99.53}} {{54:29-34=99.53}} // This will trigger validation of the global in availability_in_multi_other.swift _ = globalFromOtherOn99_52 }