Extract non-error-code-related members from TodoCode.

This paves the way for code generation of the `TodoCode` class.

Change-Id: I25e113f90194f3f7ac5ab0ae2a17b9836e56b835
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/214302
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/lib/src/dart/error/todo_codes.dart b/pkg/analyzer/lib/src/dart/error/todo_codes.dart
index 6b3d5c9..e1f955a 100644
--- a/pkg/analyzer/lib/src/dart/error/todo_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/todo_codes.dart
@@ -8,6 +8,51 @@
 // _documentation comment_ when each is written as an end-of-line comment.
 // ignore_for_file: slash_for_doc_comments
 
+/// Static helper methods and properties for working with [TodoCode]s.
+class Todo {
+  static const _codes = {
+    'TODO': TodoCode.TODO,
+    'FIXME': TodoCode.FIXME,
+    'HACK': TodoCode.HACK,
+    'UNDONE': TodoCode.UNDONE,
+  };
+
+  /// This matches the two common Dart task styles
+  ///
+  /// * TODO:
+  /// * TODO(username):
+  ///
+  /// As well as
+  /// * TODO
+  ///
+  /// But not
+  /// * todo
+  /// * TODOS
+  ///
+  /// It also supports wrapped TODOs where the next line is indented by a space:
+  ///
+  ///   /**
+  ///    * TODO(username): This line is
+  ///    *  wrapped onto the next line
+  ///    */
+  ///
+  /// The matched kind of the TODO (TODO, FIXME, etc.) is returned in named
+  /// captures of "kind1", "kind2" (since it is not possible to reuse a name
+  /// across different parts of the regex).
+  static RegExp TODO_REGEX = RegExp(
+      '([\\s/\\*])(((?<kind1>$_TODO_KIND_PATTERN)[^\\w\\d][^\\r\\n]*(?:\\n\\s*\\*  [^\\r\\n]*)*)'
+      '|((?<kind2>$_TODO_KIND_PATTERN):?\$))');
+
+  static final _TODO_KIND_PATTERN = _codes.keys.join('|');
+
+  Todo._() {
+    throw UnimplementedError('Do not construct');
+  }
+
+  /// Returns the TodoCode for [kind], falling back to [TodoCode.TODO].
+  static TodoCode forKind(String kind) => _codes[kind] ?? TodoCode.TODO;
+}
+
 /**
  * The error code indicating a marker in code for work that needs to be finished
  * or revisited.
@@ -33,43 +78,6 @@
    */
   static const TodoCode UNDONE = TodoCode('UNDONE');
 
-  static const _codes = {
-    'TODO': TODO,
-    'FIXME': FIXME,
-    'HACK': HACK,
-    'UNDONE': UNDONE,
-  };
-
-  /**
-   * This matches the two common Dart task styles
-   *
-   * * TODO:
-   * * TODO(username):
-   *
-   * As well as
-   * * TODO
-   *
-   * But not
-   * * todo
-   * * TODOS
-   *
-   * It also supports wrapped TODOs where the next line is indented by a space:
-   *
-   *   /**
-   *    * TODO(username): This line is
-   *    *  wrapped onto the next line
-   *    */
-   *
-   * The matched kind of the TODO (TODO, FIXME, etc.) is returned in named
-   * captures of "kind1", "kind2" (since it is not possible to reuse a name
-   * across different parts of the regex).
-   */
-  static RegExp TODO_REGEX = RegExp(
-      '([\\s/\\*])(((?<kind1>$_TODO_KIND_PATTERN)[^\\w\\d][^\\r\\n]*(?:\\n\\s*\\*  [^\\r\\n]*)*)'
-      '|((?<kind2>$_TODO_KIND_PATTERN):?\$))');
-
-  static final _TODO_KIND_PATTERN = _codes.keys.join('|');
-
   /**
    * Initialize a newly created error code to have the given [name].
    */
@@ -85,7 +93,4 @@
 
   @override
   ErrorType get type => ErrorType.TODO;
-
-  /// Returns the TodoCode for [kind], falling back to [TODO].
-  static TodoCode forKind(String kind) => _codes[kind] ?? TODO;
 }
diff --git a/pkg/analyzer/lib/src/error/todo_finder.dart b/pkg/analyzer/lib/src/error/todo_finder.dart
index cbb1d38..e6a4df3 100644
--- a/pkg/analyzer/lib/src/error/todo_finder.dart
+++ b/pkg/analyzer/lib/src/error/todo_finder.dart
@@ -66,7 +66,7 @@
   /// any continuations).
   Token? _scrapeTodoComment(Token commentToken, LineInfo lineInfo) {
     Iterable<RegExpMatch> matches =
-        TodoCode.TODO_REGEX.allMatches(commentToken.lexeme);
+        Todo.TODO_REGEX.allMatches(commentToken.lexeme);
     // Track the comment that will be returned for looking for the next todo.
     // This will be moved along if additional comments are consumed by multiline
     // TODOs.
@@ -110,7 +110,7 @@
                   // And indented more than the original 'todo' text.
                   columnOfFirstNoneMarkerOrWhitespace == column + 1 &&
                   // And not their own todos.
-                  !TodoCode.TODO_REGEX.hasMatch(nextComment.lexeme);
+                  !Todo.TODO_REGEX.hasMatch(nextComment.lexeme);
           if (!isContinuation) {
             break;
           }
@@ -127,7 +127,7 @@
       }
 
       _errorReporter.reportErrorForOffset(
-          TodoCode.forKind(todoKind), offset, end - offset, [todoText]);
+          Todo.forKind(todoKind), offset, end - offset, [todoText]);
     }
 
     return nextComment;