23
23
#include " swift/AST/ASTWalker.h"
24
24
#include " swift/AST/AvailabilitySpec.h"
25
25
#include " swift/AST/ConformanceLookup.h"
26
+ #include " swift/AST/DiagnosticsParse.h"
26
27
#include " swift/AST/DiagnosticsSema.h"
27
28
#include " swift/AST/ExistentialLayout.h"
28
29
#include " swift/AST/Expr.h"
@@ -5130,6 +5131,8 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info,
5130
5131
StringRef queryName =
5131
5132
info->isUnavailability () ? " #unavailable" : " #available" ;
5132
5133
5134
+ bool hasValidSpecs = false ;
5135
+ bool allValidSpecsArePlatform = true ;
5133
5136
std::optional<SourceLoc> wildcardLoc;
5134
5137
llvm::SmallSet<AvailabilityDomain, 8 > seenDomains;
5135
5138
for (auto spec : info->getSemanticAvailabilitySpecs (DC)) {
@@ -5140,24 +5143,44 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info,
5140
5143
}
5141
5144
5142
5145
auto domain = spec.getDomain ();
5146
+ auto loc = parsedSpec->getStartLoc ();
5147
+ bool hasVersion = !spec.getVersion ().empty ();
5143
5148
5144
- if (!domain.isPlatform ()) {
5145
- diags.diagnose (
5146
- parsedSpec->getStartLoc (),
5147
- domain.isSwiftLanguage ()
5148
- ? diag::availability_query_swift_not_allowed
5149
- : diag::availability_query_package_description_not_allowed,
5150
- queryName);
5149
+ if (!domain.supportsQueries ()) {
5150
+ diags.diagnose (loc, diag::availability_query_not_allowed,
5151
+ domain.getNameForDiagnostics (), hasVersion, queryName);
5151
5152
return true ;
5152
5153
}
5153
5154
5154
- // Diagnose duplicate platforms.
5155
+ if (!domain.isPlatform () && info->getQueries ().size () > 1 ) {
5156
+ diags.diagnose (loc, diag::availability_must_occur_alone,
5157
+ domain.getNameForDiagnostics (), hasVersion);
5158
+ return true ;
5159
+ }
5160
+
5161
+ if (domain.isVersioned ()) {
5162
+ if (!hasVersion) {
5163
+ diags.diagnose (loc, diag::avail_query_expected_version_number);
5164
+ return true ;
5165
+ }
5166
+ } else if (hasVersion) {
5167
+ diags
5168
+ .diagnose (loc, diag::availability_unexpected_version,
5169
+ domain.getNameForDiagnostics ())
5170
+ .highlight (parsedSpec->getVersionSrcRange ());
5171
+ return true ;
5172
+ }
5173
+
5174
+ // Diagnose duplicate domains.
5155
5175
if (!seenDomains.insert (domain).second ) {
5156
- diags.diagnose (parsedSpec->getStartLoc (),
5157
- diag::availability_query_repeated_platform,
5158
- domain.getNameForAttributePrinting ());
5176
+ diags.diagnose (loc, diag::availability_query_already_specified,
5177
+ domain.isVersioned (), domain.getNameForDiagnostics ());
5159
5178
return true ;
5160
5179
}
5180
+
5181
+ hasValidSpecs = true ;
5182
+ if (!domain.isPlatform ())
5183
+ allValidSpecsArePlatform = false ;
5161
5184
}
5162
5185
5163
5186
if (info->isUnavailability ()) {
@@ -5167,7 +5190,7 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info,
5167
5190
diag::unavailability_query_wildcard_not_required)
5168
5191
.fixItRemove (*wildcardLoc);
5169
5192
}
5170
- } else if (!wildcardLoc) {
5193
+ } else if (!wildcardLoc && hasValidSpecs && allValidSpecsArePlatform ) {
5171
5194
if (info->getQueries ().size () > 0 ) {
5172
5195
auto insertLoc = info->getQueries ().back ()->getSourceRange ().End ;
5173
5196
diags.diagnose (insertLoc, diag::availability_query_wildcard_required)
0 commit comments