tint/resolver: Warn for unknown diagnostic rules

Suggest alternatives in the warning.

Bug: tint:1809
Change-Id: If55f162fbd44a1987b573888ca7cc02490f8b05e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/117800
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/resolver/diagnostic_control_test.cc b/src/tint/resolver/diagnostic_control_test.cc
index 6c217e6..77ae663 100644
--- a/src/tint/resolver/diagnostic_control_test.cc
+++ b/src/tint/resolver/diagnostic_control_test.cc
@@ -181,5 +181,26 @@
 89:10 note: code is unreachable)");
 }
 
+TEST_F(ResolverDiagnosticControlTest, UnrecognizedRuleName_Directive) {
+    DiagnosticDirective(ast::DiagnosticSeverity::kError,
+                        Expr(Source{{12, 34}}, "chromium_unreachable_cod"));
+    EXPECT_TRUE(r()->Resolve()) << r()->error();
+    EXPECT_EQ(r()->error(),
+              R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_cod'
+Did you mean 'chromium_unreachable_code'?
+Possible values: 'chromium_unreachable_code', 'derivative_uniformity')");
+}
+
+TEST_F(ResolverDiagnosticControlTest, UnrecognizedRuleName_Attribute) {
+    auto* attr = DiagnosticAttribute(ast::DiagnosticSeverity::kError,
+                                     Expr(Source{{12, 34}}, "chromium_unreachable_cod"));
+    Func("foo", {}, ty.void_(), {}, utils::Vector{attr});
+    EXPECT_TRUE(r()->Resolve()) << r()->error();
+    EXPECT_EQ(r()->error(),
+              R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_cod'
+Did you mean 'chromium_unreachable_code'?
+Possible values: 'chromium_unreachable_code', 'derivative_uniformity')");
+}
+
 }  // namespace
 }  // namespace tint::resolver
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 7db9a2f..b67ce61 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -3069,6 +3069,11 @@
     auto rule = ast::ParseDiagnosticRule(rule_name);
     if (rule != ast::DiagnosticRule::kUndefined) {
         validator_.DiagnosticFilters().Set(rule, control->severity);
+    } else {
+        std::ostringstream ss;
+        ss << "unrecognized diagnostic rule '" << rule_name << "'\n";
+        utils::SuggestAlternatives(rule_name, ast::kDiagnosticRuleStrings, ss);
+        AddWarning(ss.str(), control->rule_name->source);
     }
     return true;
 }