1313#include < array>
1414#include < vector>
1515
16+ #include " swift/AST/DiagnosticGroups.h"
1617#include " swift/Basic/Feature.h"
1718#include " swift/Frontend/Frontend.h"
1819
@@ -22,11 +23,58 @@ using namespace swift;
2223
2324namespace swift {
2425namespace features {
26+
27+ // / The subset of diagnostic groups (called categories by the diagnostic machinery) whose diagnostics should be
28+ // / considered to be part of the migration for this feature.
29+ // /
30+ // / When making a feature migratable, ensure that all of the warnings that are used to drive the migration are
31+ // / part of a diagnostic group, and put that diagnostic group into the list for that feature here.
32+ static std::vector<DiagGroupID> migratableCategories (Feature feature) {
33+ switch (feature) {
34+ case Feature::InnerKind::ExistentialAny:
35+ return { DiagGroupID::ExistentialAny };
36+ case Feature::InnerKind::InferIsolatedConformances:
37+ return { DiagGroupID::IsolatedConformances };
38+ case Feature::InnerKind::NonisolatedNonsendingByDefault:
39+ return { DiagGroupID::NonisolatedNonsendingByDefault };
40+ case Feature::InnerKind::StrictMemorySafety:
41+ return { DiagGroupID::StrictMemorySafety };
42+
43+ // Provide unreachable cases for all of the non-migratable features.
44+ #define LANGUAGE_FEATURE (FeatureName, SENumber, Description ) case Feature::FeatureName:
45+ #define MIGRATABLE_UPCOMING_FEATURE (FeatureName, SENumber, Version )
46+ #define MIGRATABLE_EXPERIMENTAL_FEATURE (FeatureName, AvailableInProd )
47+ #define MIGRATABLE_OPTIONAL_LANGUAGE_FEATURE (FeatureName, SENumber, Name )
48+ #include " swift/Basic/Features.def"
49+ llvm_unreachable (" Not a migratable feature" );
50+ }
51+ }
52+
53+ // / For optional language features, return the flag name used by the compiler to enable the feature. For all others,
54+ // / returns an empty optional.
55+ static std::optional<std::string_view> optionalFlagName (Feature feature) {
56+ switch (feature) {
57+ case Feature::StrictMemorySafety:
58+ return " -strict-memory-safety" ;
59+
60+ #define LANGUAGE_FEATURE (FeatureName, SENumber, Description ) case Feature::FeatureName:
61+ #define OPTIONAL_LANGUAGE_FEATURE (FeatureName, SENumber, Description )
62+ #include " swift/Basic/Features.def"
63+ return std::nullopt ;
64+ }
65+ }
66+
2567// / Print information about what features upcoming/experimental are
2668// / supported by the compiler.
2769// / The information includes whether a feature is adoptable and for
2870// / upcoming features - what is the first mode it's introduced.
2971void printSupportedFeatures (llvm::raw_ostream &out) {
72+ std::array optional{
73+ #define LANGUAGE_FEATURE (FeatureName, SENumber, Description )
74+ #define OPTIONAL_LANGUAGE_FEATURE (FeatureName, SENumber, Description ) Feature::FeatureName,
75+ #include " swift/Basic/Features.def"
76+ };
77+
3078 std::array upcoming{
3179#define LANGUAGE_FEATURE (FeatureName, SENumber, Description )
3280#define UPCOMING_FEATURE (FeatureName, SENumber, Version ) Feature::FeatureName,
@@ -50,14 +98,32 @@ void printSupportedFeatures(llvm::raw_ostream &out) {
5098 out << " { \" name\" : \" " << feature.getName () << " \" " ;
5199 if (feature.isMigratable ()) {
52100 out << " , \" migratable\" : true" ;
101+
102+ auto categories = migratableCategories (feature);
103+ out << " , \" categories\" : [" ;
104+ llvm::interleave (categories, [&out](DiagGroupID diagGroupID) {
105+ out << " \" " << getDiagGroupInfoByID (diagGroupID).name << " \" " ;
106+ }, [&out] {
107+ out << " , " ;
108+ });
109+ out << " ]" ;
53110 }
54111 if (auto version = feature.getLanguageVersion ()) {
55112 out << " , \" enabled_in\" : \" " << *version << " \" " ;
56113 }
114+
115+ if (auto flagName = optionalFlagName (feature)) {
116+ out << " , \" flag_name\" : \" " << *flagName << " \" " ;
117+ }
118+
57119 out << " }" ;
58120 };
59121
60122 out << " \" features\" : {\n " ;
123+ out << " \" optional\" : [\n " ;
124+ llvm::interleave (optional, printFeature, [&out] { out << " ,\n " ; });
125+ out << " \n ],\n " ;
126+
61127 out << " \" upcoming\" : [\n " ;
62128 llvm::interleave (upcoming, printFeature, [&out] { out << " ,\n " ; });
63129 out << " \n ],\n " ;
0 commit comments