From 4a3fbb01850d0140e8406e7adc8675d18608df12 Mon Sep 17 00:00:00 2001 From: Minhyuk Kim Date: Mon, 16 Aug 2021 15:58:31 +0900 Subject: [PATCH] Modify diagnostics to suggest updating existing available attribute --- include/swift/AST/DiagnosticsSema.def | 2 ++ lib/Sema/TypeCheckAvailability.cpp | 6 ++++-- .../attr_main_struct_available_future.swift | 3 +-- test/attr/attr_availability_osx.swift | 16 +++++++++++++--- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 4af092ddb775b..17d0ff704cb18 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5327,6 +5327,8 @@ NOTE(availability_guard_with_version_check, none, NOTE(availability_add_attribute, none, "add @available attribute to enclosing %0", (DescriptiveDeclKind)) +NOTE(availability_update_attribute, none, + "update existing @available attribute", ()) FIXIT(insert_available_attr, "@available(%0 %1, *)\n%2", (StringRef, StringRef, StringRef)) diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index aa6262c0f8dd4..5789197ab0fa8 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -1453,8 +1453,10 @@ static void fixAvailabilityForDecl(SourceRange ReferenceRange, const Decl *D, if (TypeChecker::diagnosticIfDeclCannotBePotentiallyUnavailable(D).hasValue()) return; - if (getActiveAvailableAttribute(D, Context)) { - // For QoI, in future should emit a fixit to update the existing attribute. + if (auto *attr = getActiveAvailableAttribute(D, Context)) { + D->diagnose(diag::availability_update_attribute) + .fixItReplace(attr->IntroducedRange, + RequiredRange.getLowerEndpoint().getAsString()); return; } diff --git a/test/attr/ApplicationMain/attr_main_struct_available_future.swift b/test/attr/ApplicationMain/attr_main_struct_available_future.swift index 5d36cda72d3c9..9c20d6ebbdef7 100644 --- a/test/attr/ApplicationMain/attr_main_struct_available_future.swift +++ b/test/attr/ApplicationMain/attr_main_struct_available_future.swift @@ -3,8 +3,7 @@ // REQUIRES: OS=macosx @main // expected-error {{'main()' is only available in macOS 10.99 or newer}} -@available(OSX 10.0, *) -struct EntryPoint { +@available(OSX 10.0, *) struct EntryPoint { // expected-note {{update existing @available attribute}} {{16-20=10.99}} @available(OSX 10.99, *) static func main() { } diff --git a/test/attr/attr_availability_osx.swift b/test/attr/attr_availability_osx.swift index 4b44cf87981c4..ecaee9dbf902f 100644 --- a/test/attr/attr_availability_osx.swift +++ b/test/attr/attr_availability_osx.swift @@ -100,12 +100,14 @@ extension TestStruct { // expected-note {{enclosing scope here}} @available(swift 1) func doFourthThing() {} + @available(macOS 10.12, iOS 13, tvOS 13, *) + func doFifthThing() {} + @available(*, deprecated) func doDeprecatedThing() {} } -@available(macOS 10.11, *) -func testMemberAvailability() { +@available(macOS 10.11, *) func testMemberAvailability() { // expected-note {{update existing @available attribute}} {{18-23=10.12}} TestStruct().doTheThing() // expected-error {{'doTheThing()' is unavailable}} TestStruct().doAnotherThing() // expected-error {{'doAnotherThing()' is unavailable}} TestStruct().doThirdThing() // expected-error {{'doThirdThing()' is unavailable}} @@ -113,6 +115,14 @@ func testMemberAvailability() { TestStruct().doDeprecatedThing() // expected-warning {{'doDeprecatedThing()' is deprecated}} } +@available(iOS 11, macOS 10.11, *) func testUpdateAvailabilityAttribute() { // expected-note {{update existing @available attribute}} {{26-31=10.12}} + TestStruct().doFifthThing() // expected-error {{'doFifthThing()' is only available in macOS 10.12 or newer}} expected-note {{'if #available'}} +} + +@available(macOS, introduced: 10.11) func testUpdateAvailabilityAttribute2() { // expected-note {{update existing @available attribute}} {{31-36=10.12}} + TestStruct().doFifthThing() // expected-error {{'doFifthThing()' is only available in macOS 10.12 or newer}} expected-note {{'if #available'}} +} + extension TestStruct { struct Data { mutating func mutate() {} @@ -208,4 +218,4 @@ extension UnavailableStruct { } // no-error #if os(macOS) @available(macOS, unavailable) extension UnavailableStruct { } // no-error -#endif +#endif \ No newline at end of file