Add a test for hasPublishedDocs

This causes the code that parses the `messages.yaml` files in either
the analyzer or linter packages so that it throw an exception if any
code fails to have an explicit `hasPublishedDocs` key.

We decided to require the field because it makes it easier to identify
codes for which documentation has not yet been published. Prior to this
the search looked for codes missing this key _or_ codes where this key
had a value of `false`, but now only the last needs to be searched for
which can be done using a simple textual search.

Change-Id: I1aa59eb02a628fae8cb79c5390b59c787218fe15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/431761
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/tool/messages/error_code_info.dart b/pkg/analyzer/tool/messages/error_code_info.dart
index ed93bbe..1940a12 100644
--- a/pkg/analyzer/tool/messages/error_code_info.dart
+++ b/pkg/analyzer/tool/messages/error_code_info.dart
@@ -172,6 +172,9 @@
           st,
         );
       }
+      if (errorCodeInfo.hasPublishedDocs == null) {
+        problem('Missing hasPublishedDocs for $className.$errorName');
+      }
 
       if (errorCodeInfo case AliasErrorCodeInfo(:var aliasFor)) {
         var aliasForPath = aliasFor.split('.');
@@ -215,7 +218,11 @@
     if (errorValue is! Map<Object?, Object?>) {
       problem('value associated with error $errorName is not a map');
     }
-    result[errorName] = FrontEndErrorCodeInfo.fromYaml(errorValue);
+    try {
+      result[errorName] = FrontEndErrorCodeInfo.fromYaml(errorValue);
+    } catch (e, st) {
+      Error.throwWithStackTrace('while processing $errorName, $e', st);
+    }
   }
   return result;
 }
@@ -468,9 +475,11 @@
   /// If present, user-facing documentation for the error.
   final String? documentation;
 
-  /// `true` if diagnostics with this code have documentation for them that has
+  /// Whether diagnostics with this code have documentation for them that has
   /// been published.
-  final bool hasPublishedDocs;
+  ///
+  /// `null` if the YAML doesn't contain this information.
+  final bool? hasPublishedDocs;
 
   /// Indicates whether this error is caused by an unresolved identifier.
   final bool isUnresolvedIdentifier;
@@ -494,7 +503,7 @@
   ErrorCodeInfo({
     this.comment,
     this.documentation,
-    this.hasPublishedDocs = false,
+    this.hasPublishedDocs,
     this.isUnresolvedIdentifier = false,
     this.sharedName,
     required this.problemMessage,
@@ -511,7 +520,7 @@
         correctionMessage: yaml['correctionMessage'] as String?,
         deprecatedMessage: yaml['deprecatedMessage'] as String?,
         documentation: yaml['documentation'] as String?,
-        hasPublishedDocs: yaml['hasPublishedDocs'] as bool? ?? false,
+        hasPublishedDocs: yaml['hasPublishedDocs'] as bool?,
         isUnresolvedIdentifier:
             yaml['isUnresolvedIdentifier'] as bool? ?? false,
         problemMessage: yaml['problemMessage'] as String? ?? '',
@@ -574,7 +583,7 @@
       var codeLines = _splitText(code, maxWidth: maxWidth);
       out.writeln('${codeLines.map(json.encode).join('\n')},');
     }
-    if (hasPublishedDocs) {
+    if (hasPublishedDocs ?? false) {
       out.writeln('hasPublishedDocs:true,');
     }
     if (isUnresolvedIdentifier) {
@@ -606,7 +615,7 @@
     'problemMessage': problemMessage,
     if (correctionMessage != null) 'correctionMessage': correctionMessage,
     if (isUnresolvedIdentifier) 'isUnresolvedIdentifier': true,
-    if (hasPublishedDocs) 'hasPublishedDocs': true,
+    if (hasPublishedDocs ?? false) 'hasPublishedDocs': true,
     if (comment != null) 'comment': comment,
     if (documentation != null) 'documentation': documentation,
   };
diff --git a/pkg/linter/messages.yaml b/pkg/linter/messages.yaml
index 45d4176..a90a5c9 100644
--- a/pkg/linter/messages.yaml
+++ b/pkg/linter/messages.yaml
@@ -223,6 +223,7 @@
     state:
       stable: "2.0"
       removed: "3.3"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
 
@@ -542,6 +543,7 @@
     state:
       stable: "2.0"
       removed: "3.0"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule was removed from the SDK in Dart 3; it is no longer functional.
       Its advice is compiler-specific and mostly obsolete with null safety.
@@ -1909,6 +1911,7 @@
     state:
       stable: "2.0"
       removed: "3.3"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
 
@@ -1938,6 +1941,7 @@
     state:
       stable: "2.1"
       removed: "3.3"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
 
@@ -2545,6 +2549,7 @@
     state:
       experimental: "3.3"
       removed: "3.3"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       This rule has been removed.
   avoid_unused_constructor_parameters:
@@ -4438,6 +4443,7 @@
     state:
       stable: "2.19"
       removed: "3.0"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.0.0; it is no longer functional.
 
@@ -5343,6 +5349,7 @@
     state:
       stable: "2.0"
       removed: "3.0"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.0.0; it is no longer functional.
 
@@ -5428,6 +5435,7 @@
     state:
       stable: "2.0"
       removed: "3.3"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
 
@@ -5868,6 +5876,7 @@
     state:
       stable: "2.0"
       removed: "3.3"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
 
@@ -7951,6 +7960,7 @@
     state:
       stable: "2.0"
       removed: "3.0"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.0.0; it is no longer functional.
 
@@ -8652,6 +8662,7 @@
     state:
       stable: "2.0"
       removed: "3.0"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.0; it is no longer functional.
 
@@ -11312,6 +11323,7 @@
     state:
       stable: "2.0"
       removed: "3.0"
+    hasPublishedDocs: false
     deprecatedDetails: |-
       NOTE: This rule is removed in Dart 3.0.0; it is no longer functional.